diff --git a/README.md b/README.md index 275bfba4eb..4d58f0e082 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,11 @@ ps:核心功能已经实现,正在对接微信小程序中... * 2022 Q2 => 完成对 的迁移,作为 onemall 的 Spring Boot 单体版本。 * 2022 Q4 => 完成对 > 的重构,作为 onemall 的 Spring Cloud 微服务版本。 +### 会员中心 + +正在开发中,大体计划如下: +* 2021 Q1 =》完成对 的迁移 + ### 基础设施 | | 功能 | 描述 | @@ -118,43 +123,45 @@ ps:核心功能已经实现,正在对接微信小程序中... ## 技术栈 -| 项目 | 说明 | -| --- | --- | -| `yudao-dependencies` | Maven 依赖版本管理 | -| `yudao-framework` | Java 框架拓展 | -| `yudao-admin-server` | 管理后台的服务端 | -| `yudao-admin-ui` | 管理后台的 UI 界面 | -| `yudao-user-server` | 用户前台的服务端 | -| `yudao-user-ui` | 用户前台的 UI 界面 | -| `yudao-core-service` | 公共服务,提供共享逻辑 | - -> 友情提示:`yudao-admin-server` 和 `yudao-user-server` 会存在需要复用的逻辑,通过 `yudao-core-service` 实现。 +| 项目 | 说明 | +|-----------------------|--------------------| +| `yudao-dependencies` | Maven 依赖版本管理 | +| `yudao-framework` | Java 框架拓展 | +| `yudao-server` | 管理后台 + 用户 APP 的服务端 | +| `yudao-admin-ui` | 管理后台的 UI 界面 | +| `yudao-user-ui` | 用户 APP 的 UI 界面 | +| `yudao-module-system` | 系统功能的 Module 模块 | +| `yudao-module-member` | 会员中心的 Module 模块 | +| `yudao-module-infra` | 基础设施的 Module 模块 | +| `yudao-module-tool` | 研发工具的 Module 模块 | +| `yudao-module-bpm` | 工作流程的 Module 模块 | +| `yudao-module-pay` | 支付系统的 Module 模块 | ### 后端 -| 框架 | 说明 | 版本 | 学习指南 | -| --- | --- | --- | --- | -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.12 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | -| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | | -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.8 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.3.4 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [Redis](https://redis.io/) | key-value 数据库 | 5.0 | | -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.16.6 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.13 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.4.9 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | +| 框架 | 说明 | 版本 | 学习指南 | +| --- | --- |----------| --- | +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.5.9 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | +| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | | +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.8 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.3.4 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [Redis](https://redis.io/) | key-value 数据库 | 5.0 | | +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.16.8 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.15 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.5.4 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.0 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | | [Activiti](https://github.com/Activiti/Activiti) | 工作流引擎 | 7.1.0.M6 | [文档](TODO) | -| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | -| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | -| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.4.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 | | -| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.7.1 | - | -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 3.6.28 | - | +| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | +| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | +| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | +| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.4.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | +| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.12.6 | | +| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.7.2 | - | +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 3.9.0 | - | ### 前端 diff --git a/http-client.env.json b/http-client.env.json index c4686b274f..2f18d251c2 100644 --- a/http-client.env.json +++ b/http-client.env.json @@ -1,7 +1,11 @@ { "local": { - "baseUrl": "http://127.0.0.1:48080/api", - "userServerUrl": "http://127.0.0.1:28080/api", - "token": "test1" + "baseUrl": "http://127.0.0.1:48080/admin-api", + "token": "test1", + "adminTenentId": "1", + + "appApi": "http://127.0.0.1:48080/app-api", + "appToken": "test1", + "appTenentId": "1" } } diff --git a/img.png b/img.png deleted file mode 100644 index 0e0c73ca1f..0000000000 Binary files a/img.png and /dev/null differ diff --git a/pom.xml b/pom.xml index 0f791a822f..2acee53168 100644 --- a/pom.xml +++ b/pom.xml @@ -10,9 +10,15 @@ yudao-dependencies yudao-framework - yudao-admin-server - yudao-user-server - yudao-core-service + + yudao-server + + yudao-module-member + yudao-module-bpm + yudao-module-system + yudao-module-infra + yudao-module-tool + yudao-module-pay ${artifactId} @@ -20,12 +26,16 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.3.0-snapshot + 1.4.0-snapshot 1.8 ${java.version} ${java.version} 3.0.0-M5 + 3.8.0 + + 1.18.20 + 1.4.1.Final UTF-8 @@ -51,6 +61,26 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index c74a93c009..d3d5d2a078 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/sql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80026 File Encoding : 65001 - Date: 23/01/2022 01:39:15 + Date: 02/02/2022 01:23:59 */ SET NAMES utf8mb4; @@ -61,9 +61,9 @@ CREATE TABLE `bpm_oa_leave` ( `day` tinyint NOT NULL COMMENT '请假天数', `result` tinyint NOT NULL COMMENT '请假结果', `process_instance_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '流程实例的编号', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) @@ -222,14 +222,14 @@ CREATE TABLE `bpm_process_instance_ext` ( `status` tinyint NOT NULL COMMENT '流程实例的状态', `result` tinyint NOT NULL COMMENT '流程实例的结果', `end_time` datetime DEFAULT NULL COMMENT '结束时间', - `form_variables` varchar(5000) DEFAULT NULL COMMENT '表单值', + `form_variables` varchar(5000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '表单值', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=194 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流的流程实例的拓展'; +) ENGINE=InnoDB AUTO_INCREMENT=198 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流的流程实例的拓展'; -- ---------------------------- -- Records of bpm_process_instance_ext @@ -348,6 +348,9 @@ INSERT INTO `bpm_process_instance_ext` VALUES (190, 1, 'OA 请假', '2152467e-7b INSERT INTO `bpm_process_instance_ext` VALUES (191, 1, 'OA 请假', '7317cec6-7b9b-11ec-b5b7-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '2', 1, 1, NULL, '{\"day\":23}', '1', '2022-01-22 23:53:32', '1', '2022-01-22 23:53:33', b'0'); INSERT INTO `bpm_process_instance_ext` VALUES (192, 1, 'OA 请假', '7470a810-7b9b-11ec-b5b7-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '2', 2, 4, '2022-01-23 00:08:41', '{\"day\":23}', '1', '2022-01-22 23:53:35', '1', '2022-01-23 00:08:41', b'0'); INSERT INTO `bpm_process_instance_ext` VALUES (193, 1, 'OA 请假', '3ad174fb-7b9d-11ec-8404-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '2', 2, 4, '2022-01-23 00:07:03', '{\"day\":23}', '1', '2022-01-23 00:06:17', '1', '2022-01-23 00:07:03', b'0'); +INSERT INTO `bpm_process_instance_ext` VALUES (194, 1, 'eeee', 'b243fa82-7c06-11ec-9110-acde48001122', 'eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a', '1', 1, 1, NULL, '{\"field121\":\"AAA\",\"field122\":[1]}', '1', '2022-01-23 12:41:14', '1', '2022-01-23 12:41:19', b'0'); +INSERT INTO `bpm_process_instance_ext` VALUES (195, 1, '测试多审批人', 'ecddb286-7c07-11ec-a41d-acde48001122', 'test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a', '1', 2, 4, '2022-01-23 12:59:40', '{\"field121\":\"AAA\",\"field122\":[1]}', '1', '2022-01-23 12:50:02', '1', '2022-01-23 12:59:40', b'0'); +INSERT INTO `bpm_process_instance_ext` VALUES (197, 1, '滔博', '4f676a08-7c09-11ec-b8a1-acde48001122', 'test:21:c2cd44b0-79b0-11ec-b2b8-a2380e71991a', '1', 1, 1, NULL, '{\"field121\":\"aaa\",\"field122\":[1]}', '1', '2022-01-23 12:59:57', '1', '2022-01-23 12:59:57', b'0'); COMMIT; -- ---------------------------- @@ -526,9 +529,9 @@ CREATE TABLE `bpm_task_ext` ( `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '任务的名字', `task_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务的编号', `result` tinyint NOT NULL COMMENT '任务的结果', - `comment` varchar(255) DEFAULT NULL COMMENT '审批建议', + `comment` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '审批建议', `end_time` datetime DEFAULT NULL COMMENT '任务的结束时间', - `process_instance_id` varchar(64) NOT NULL COMMENT '流程实例的编号', + `process_instance_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程实例的编号', `process_definition_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '流程定义的编号', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', @@ -536,7 +539,7 @@ CREATE TABLE `bpm_task_ext` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流的流程任务的拓展表'; +) ENGINE=InnoDB AUTO_INCREMENT=210 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流的流程任务的拓展表'; -- ---------------------------- -- Records of bpm_task_ext @@ -667,6 +670,10 @@ INSERT INTO `bpm_task_ext` VALUES (201, 1, '一级审批', '215cf4e5-7b9b-11ec-9 INSERT INTO `bpm_task_ext` VALUES (202, 1, '一级审批', '73211d9d-7b9b-11ec-b5b7-acde48001122', 1, NULL, NULL, '7317cec6-7b9b-11ec-b5b7-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '1', '2022-01-22 23:53:32', '1', '2022-01-22 23:53:32', b'0'); INSERT INTO `bpm_task_ext` VALUES (203, 1, '一级审批', '74736737-7b9b-11ec-b5b7-acde48001122', 4, NULL, '2022-01-23 00:08:41', '7470a810-7b9b-11ec-b5b7-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '1', '2022-01-22 23:53:35', '1', '2022-01-23 00:08:41', b'0'); INSERT INTO `bpm_task_ext` VALUES (204, 1, '一级审批', '3adac3d2-7b9d-11ec-8404-acde48001122', 4, NULL, '2022-01-23 00:07:03', '3ad174fb-7b9d-11ec-8404-acde48001122', 'oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122', '1', '2022-01-23 00:06:17', '1', '2022-01-23 00:07:03', b'0'); +INSERT INTO `bpm_task_ext` VALUES (205, 1, '申请', 'b25363db-7c06-11ec-9110-acde48001122', 1, NULL, NULL, 'b243fa82-7c06-11ec-9110-acde48001122', 'eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a', '1', '2022-01-23 12:41:14', '1', '2022-01-23 12:41:19', b'0'); +INSERT INTO `bpm_task_ext` VALUES (206, 1, '1.2', 'ee7cbc97-7c07-11ec-a41d-acde48001122', 4, NULL, '2022-01-23 12:59:40', 'ecddb286-7c07-11ec-a41d-acde48001122', 'test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a', '1', '2022-01-23 12:50:05', '1', '2022-01-23 12:59:40', b'0'); +INSERT INTO `bpm_task_ext` VALUES (207, 1, '1.1', 'ee67adf1-7c07-11ec-a41d-acde48001122', 4, NULL, '2022-01-23 12:59:40', 'ecddb286-7c07-11ec-a41d-acde48001122', 'test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a', '1', '2022-01-23 12:50:05', '1', '2022-01-23 12:59:40', b'0'); +INSERT INTO `bpm_task_ext` VALUES (209, 1, '任务一', '4f6fce81-7c09-11ec-b8a1-acde48001122', 1, NULL, NULL, '4f676a08-7c09-11ec-b8a1-acde48001122', 'test:21:c2cd44b0-79b0-11ec-b2b8-a2380e71991a', '1', '2022-01-23 12:59:57', '1', '2022-01-23 12:59:57', b'0'); COMMIT; -- ---------------------------- @@ -696,125 +703,541 @@ INSERT INTO `bpm_user_group` VALUES (110, '测试组', '哈哈哈哈', '[1]', 0, COMMIT; -- ---------------------------- --- Table structure for inf_api_access_log +-- Table structure for infra_api_access_log -- ---------------------------- -DROP TABLE IF EXISTS `inf_api_access_log`; -CREATE TABLE `inf_api_access_log` ( +DROP TABLE IF EXISTS `infra_api_access_log`; +CREATE TABLE `infra_api_access_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键', - `trace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '链路追踪编号', + `trace_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '链路追踪编号', `user_id` bigint NOT NULL DEFAULT '0' COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型', - `application_name` varchar(50) NOT NULL COMMENT '应用名', - `request_method` varchar(16) NOT NULL DEFAULT '' COMMENT '请求方法名', - `request_url` varchar(255) NOT NULL DEFAULT '' COMMENT '请求地址', - `request_params` varchar(8000) NOT NULL DEFAULT '' COMMENT '请求参数', - `user_ip` varchar(50) NOT NULL COMMENT '用户 IP', - `user_agent` varchar(512) NOT NULL COMMENT '浏览器 UA', + `application_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', + `request_method` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法名', + `request_url` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求地址', + `request_params` varchar(8000) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求参数', + `user_ip` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', + `user_agent` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', `begin_time` datetime NOT NULL COMMENT '开始请求时间', `end_time` datetime NOT NULL COMMENT '结束请求时间', `duration` int NOT NULL COMMENT '执行时长', `result_code` int NOT NULL DEFAULT '0' COMMENT '结果码', - `result_msg` varchar(512) DEFAULT '' COMMENT '结果提示', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `result_msg` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '结果提示', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=22788 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='API 访问日志表'; +) ENGINE=InnoDB AUTO_INCREMENT=23199 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='API 访问日志表'; -- ---------------------------- --- Records of inf_api_access_log +-- Records of infra_api_access_log -- ---------------------------- BEGIN; +INSERT INTO `infra_api_access_log` VALUES (22788, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:34', '2022-01-23 01:42:35', 47, 0, '', NULL, '2022-01-23 01:42:35', NULL, '2022-01-23 01:42:35', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22789, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:34', '2022-01-23 01:42:35', 47, 0, '', NULL, '2022-01-23 01:42:35', NULL, '2022-01-23 01:42:35', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22790, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:35', '2022-01-23 01:42:35', 9, 0, '', NULL, '2022-01-23 01:42:35', NULL, '2022-01-23 01:42:35', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22791, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:36', '2022-01-23 01:42:36', 2, 0, '', NULL, '2022-01-23 01:42:36', NULL, '2022-01-23 01:42:36', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22792, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:35', '2022-01-23 01:42:37', 2051, 0, '', NULL, '2022-01-23 01:42:37', NULL, '2022-01-23 01:42:37', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22793, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:36', '2022-01-23 01:42:37', 718, 0, '', NULL, '2022-01-23 01:42:37', NULL, '2022-01-23 01:42:37', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22794, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:39', '2022-01-23 01:42:39', 45, 0, '', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22795, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"dc6xv\\\",\\\"uuid\\\":\\\"4078d0241f0343faaea0d8393dbe639d\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:39', '2022-01-23 01:42:39', 399, 0, '', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22796, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:39', '2022-01-23 01:42:39', 47, 0, '', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22797, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:39', '2022-01-23 01:42:39', 50, 0, '', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22798, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:39', '2022-01-23 01:42:39', 12, 0, '', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22799, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:40', '2022-01-23 01:42:40', 28, 0, '', NULL, '2022-01-23 01:42:40', NULL, '2022-01-23 01:42:40', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22800, '', 1, 2, 'yudao-admin-server', 'GET', '/api/tool/codegen/table/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:42', '2022-01-23 01:42:42', 89, 0, '', NULL, '2022-01-23 01:42:42', NULL, '2022-01-23 01:42:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22801, '', 1, 2, 'yudao-admin-server', 'GET', '/api/tool/test-demo/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:43', '2022-01-23 01:42:43', 59, 0, '', NULL, '2022-01-23 01:42:43', NULL, '2022-01-23 01:42:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22802, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:46', '2022-01-23 01:42:46', 49, 0, '', NULL, '2022-01-23 01:42:46', NULL, '2022-01-23 01:42:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22803, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/oa/leave/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:47', '2022-01-23 01:42:47', 54, 0, '', NULL, '2022-01-23 01:42:47', NULL, '2022-01-23 01:42:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22804, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:48', '2022-01-23 01:42:48', 50, 0, '', NULL, '2022-01-23 01:42:48', NULL, '2022-01-23 01:42:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22805, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:48', '2022-01-23 01:42:48', 59, 0, '', NULL, '2022-01-23 01:42:48', NULL, '2022-01-23 01:42:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22806, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:48', '2022-01-23 01:42:48', 23, 0, '', NULL, '2022-01-23 01:42:48', NULL, '2022-01-23 01:42:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22807, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/oa/leave/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:49', '2022-01-23 01:42:49', 31, 0, '', NULL, '2022-01-23 01:42:49', NULL, '2022-01-23 01:42:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22808, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:51', '2022-01-23 01:42:51', 57, 0, '', NULL, '2022-01-23 01:42:51', NULL, '2022-01-23 01:42:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22809, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/list-by-process-instance-id', '{\"query\":{\"processInstanceId\":\"3ad174fb-7b9d-11ec-8404-acde48001122\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:51', '2022-01-23 01:42:51', 188, 0, '', NULL, '2022-01-23 01:42:51', NULL, '2022-01-23 01:42:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22810, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/get', '{\"query\":{\"id\":\"3ad174fb-7b9d-11ec-8404-acde48001122\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:51', '2022-01-23 01:42:51', 215, 0, '', NULL, '2022-01-23 01:42:51', NULL, '2022-01-23 01:42:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22811, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/get-bpmn-xml', '{\"query\":{\"id\":\"oa_leave:5:004b710b-7b8a-11ec-8ef0-acde48001122\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:51', '2022-01-23 01:42:51', 20, 0, '', NULL, '2022-01-23 01:42:51', NULL, '2022-01-23 01:42:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22812, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/activity/list', '{\"query\":{\"processInstanceId\":\"3ad174fb-7b9d-11ec-8404-acde48001122\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:51', '2022-01-23 01:42:51', 40, 0, '', NULL, '2022-01-23 01:42:51', NULL, '2022-01-23 01:42:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22813, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:57', '2022-01-23 01:42:57', 26, 0, '', NULL, '2022-01-23 01:42:57', NULL, '2022-01-23 01:42:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22814, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 01:42:57', '2022-01-23 01:42:57', 32, 0, '', NULL, '2022-01-23 01:42:57', NULL, '2022-01-23 01:42:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22815, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:27', '2022-01-23 03:21:27', 135, 0, '', NULL, '2022-01-23 03:21:27', NULL, '2022-01-23 03:21:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22816, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:27', '2022-01-23 03:21:27', 12, 0, '', NULL, '2022-01-23 03:21:27', NULL, '2022-01-23 03:21:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22817, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:27', '2022-01-23 03:21:27', 135, 0, '', NULL, '2022-01-23 03:21:27', NULL, '2022-01-23 03:21:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22818, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:28', '2022-01-23 03:21:28', 3, 0, '', NULL, '2022-01-23 03:21:28', NULL, '2022-01-23 03:21:28', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22819, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:30', '2022-01-23 03:21:30', 177, 0, '', NULL, '2022-01-23 03:21:30', NULL, '2022-01-23 03:21:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22820, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:28', '2022-01-23 03:21:30', 1565, 0, '', NULL, '2022-01-23 03:21:30', NULL, '2022-01-23 03:21:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22821, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:27', '2022-01-23 03:21:30', 2946, 0, '', NULL, '2022-01-23 03:21:30', NULL, '2022-01-23 03:21:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22822, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:32', '2022-01-23 03:21:32', 24, 0, '', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22823, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"1\\\",\\\"uuid\\\":\\\"29afe343dd6e4c45bad958997ccb8027\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:32', '2022-01-23 03:21:32', 412, 0, '', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22824, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:32', '2022-01-23 03:21:32', 52, 0, '', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22825, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:32', '2022-01-23 03:21:32', 60, 0, '', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22826, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:32', '2022-01-23 03:21:32', 12, 0, '', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22827, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:33', '2022-01-23 03:21:33', 30, 0, '', NULL, '2022-01-23 03:21:33', NULL, '2022-01-23 03:21:33', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22828, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:43', '2022-01-23 03:21:43', 89, 0, '', NULL, '2022-01-23 03:21:43', NULL, '2022-01-23 03:21:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22829, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:44', '2022-01-23 03:21:44', 27, 0, '', NULL, '2022-01-23 03:21:44', NULL, '2022-01-23 03:21:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22830, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:44', '2022-01-23 03:21:44', 148, 0, '', NULL, '2022-01-23 03:21:44', NULL, '2022-01-23 03:21:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22831, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:21:46', '2022-01-23 03:21:46', 45, 0, '', NULL, '2022-01-23 03:21:46', NULL, '2022-01-23 03:21:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22832, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:23:49', '2022-01-23 03:23:49', 30, 0, '', NULL, '2022-01-23 03:23:49', NULL, '2022-01-23 03:23:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22833, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:23:49', '2022-01-23 03:23:49', 55, 0, '', NULL, '2022-01-23 03:23:49', NULL, '2022-01-23 03:23:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22834, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:23:49', '2022-01-23 03:23:49', 9, 0, '', NULL, '2022-01-23 03:23:49', NULL, '2022-01-23 03:23:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22835, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:23:49', '2022-01-23 03:23:49', 19, 0, '', NULL, '2022-01-23 03:23:49', NULL, '2022-01-23 03:23:49', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22836, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:23:49', '2022-01-23 03:23:49', 61, 0, '', NULL, '2022-01-23 03:23:49', NULL, '2022-01-23 03:23:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22837, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:24:07', '2022-01-23 03:24:07', 44, 0, '', NULL, '2022-01-23 03:24:07', NULL, '2022-01-23 03:24:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22838, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:24:07', '2022-01-23 03:24:07', 59, 0, '', NULL, '2022-01-23 03:24:07', NULL, '2022-01-23 03:24:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22839, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:24:07', '2022-01-23 03:24:07', 9, 0, '', NULL, '2022-01-23 03:24:07', NULL, '2022-01-23 03:24:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22840, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:24:07', '2022-01-23 03:24:07', 16, 0, '', NULL, '2022-01-23 03:24:07', NULL, '2022-01-23 03:24:07', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22841, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:24:07', '2022-01-23 03:24:07', 88, 0, '', NULL, '2022-01-23 03:24:07', NULL, '2022-01-23 03:24:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22842, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:24', '2022-01-23 03:26:24', 38, 0, '', NULL, '2022-01-23 03:26:24', NULL, '2022-01-23 03:26:24', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22843, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:24', '2022-01-23 03:26:24', 65, 0, '', NULL, '2022-01-23 03:26:24', NULL, '2022-01-23 03:26:24', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22844, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:24', '2022-01-23 03:26:24', 11, 0, '', NULL, '2022-01-23 03:26:24', NULL, '2022-01-23 03:26:24', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22845, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:26', '2022-01-23 03:26:26', 18, 0, '', NULL, '2022-01-23 03:26:26', NULL, '2022-01-23 03:26:26', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22846, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:26', '2022-01-23 03:26:26', 43, 0, '', NULL, '2022-01-23 03:26:26', NULL, '2022-01-23 03:26:26', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22847, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:53', '2022-01-23 03:26:53', 27, 0, '', NULL, '2022-01-23 03:26:53', NULL, '2022-01-23 03:26:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22848, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:53', '2022-01-23 03:26:53', 44, 0, '', NULL, '2022-01-23 03:26:53', NULL, '2022-01-23 03:26:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22849, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:53', '2022-01-23 03:26:53', 8, 0, '', NULL, '2022-01-23 03:26:53', NULL, '2022-01-23 03:26:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22850, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:53', '2022-01-23 03:26:53', 15, 0, '', NULL, '2022-01-23 03:26:53', NULL, '2022-01-23 03:26:53', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22851, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:53', '2022-01-23 03:26:53', 62, 0, '', NULL, '2022-01-23 03:26:53', NULL, '2022-01-23 03:26:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22852, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:59', '2022-01-23 03:26:59', 18, 0, '', NULL, '2022-01-23 03:26:59', NULL, '2022-01-23 03:26:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22853, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:59', '2022-01-23 03:26:59', 28, 0, '', NULL, '2022-01-23 03:26:59', NULL, '2022-01-23 03:26:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22854, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:26:59', '2022-01-23 03:26:59', 5, 0, '', NULL, '2022-01-23 03:26:59', NULL, '2022-01-23 03:26:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22855, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:00', '2022-01-23 03:27:00', 17, 0, '', NULL, '2022-01-23 03:27:00', NULL, '2022-01-23 03:27:00', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22856, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:00', '2022-01-23 03:27:00', 27, 0, '', NULL, '2022-01-23 03:27:00', NULL, '2022-01-23 03:27:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22857, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:03', '2022-01-23 03:27:03', 30, 0, '', NULL, '2022-01-23 03:27:03', NULL, '2022-01-23 03:27:03', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22858, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:03', '2022-01-23 03:27:03', 44, 0, '', NULL, '2022-01-23 03:27:03', NULL, '2022-01-23 03:27:03', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22859, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:03', '2022-01-23 03:27:03', 8, 0, '', NULL, '2022-01-23 03:27:03', NULL, '2022-01-23 03:27:03', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22860, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:03', '2022-01-23 03:27:03', 16, 0, '', NULL, '2022-01-23 03:27:03', NULL, '2022-01-23 03:27:03', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22861, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:03', '2022-01-23 03:27:04', 58, 0, '', NULL, '2022-01-23 03:27:04', NULL, '2022-01-23 03:27:04', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22862, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:42', '2022-01-23 03:27:42', 28, 0, '', NULL, '2022-01-23 03:27:42', NULL, '2022-01-23 03:27:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22863, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:42', '2022-01-23 03:27:42', 44, 0, '', NULL, '2022-01-23 03:27:42', NULL, '2022-01-23 03:27:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22864, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:42', '2022-01-23 03:27:42', 6, 0, '', NULL, '2022-01-23 03:27:42', NULL, '2022-01-23 03:27:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22865, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:43', '2022-01-23 03:27:43', 12, 0, '', NULL, '2022-01-23 03:27:43', NULL, '2022-01-23 03:27:43', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22866, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:43', '2022-01-23 03:27:43', 30, 0, '', NULL, '2022-01-23 03:27:43', NULL, '2022-01-23 03:27:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22867, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:49', '2022-01-23 03:27:49', 16, 0, '', NULL, '2022-01-23 03:27:49', NULL, '2022-01-23 03:27:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22868, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:49', '2022-01-23 03:27:49', 25, 0, '', NULL, '2022-01-23 03:27:49', NULL, '2022-01-23 03:27:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22869, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:49', '2022-01-23 03:27:49', 5, 0, '', NULL, '2022-01-23 03:27:49', NULL, '2022-01-23 03:27:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22870, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:50', '2022-01-23 03:27:50', 15, 0, '', NULL, '2022-01-23 03:27:50', NULL, '2022-01-23 03:27:50', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22871, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:27:50', '2022-01-23 03:27:50', 29, 0, '', NULL, '2022-01-23 03:27:50', NULL, '2022-01-23 03:27:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22872, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:29:58', '2022-01-23 03:29:58', 28, 0, '', NULL, '2022-01-23 03:29:58', NULL, '2022-01-23 03:29:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22873, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:29:58', '2022-01-23 03:29:58', 43, 0, '', NULL, '2022-01-23 03:29:58', NULL, '2022-01-23 03:29:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22874, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:29:58', '2022-01-23 03:29:58', 6, 0, '', NULL, '2022-01-23 03:29:58', NULL, '2022-01-23 03:29:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22875, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:29:58', '2022-01-23 03:29:58', 15, 0, '', NULL, '2022-01-23 03:29:58', NULL, '2022-01-23 03:29:58', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22876, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:29:58', '2022-01-23 03:29:58', 45, 0, '', NULL, '2022-01-23 03:29:58', NULL, '2022-01-23 03:29:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22877, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:02', '2022-01-23 03:30:02', 21, 0, '', NULL, '2022-01-23 03:30:02', NULL, '2022-01-23 03:30:02', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22878, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:02', '2022-01-23 03:30:02', 32, 0, '', NULL, '2022-01-23 03:30:02', NULL, '2022-01-23 03:30:02', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22879, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:02', '2022-01-23 03:30:02', 5, 0, '', NULL, '2022-01-23 03:30:02', NULL, '2022-01-23 03:30:02', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22880, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:02', '2022-01-23 03:30:02', 14, 0, '', NULL, '2022-01-23 03:30:02', NULL, '2022-01-23 03:30:02', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22881, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:02', '2022-01-23 03:30:03', 31, 0, '', NULL, '2022-01-23 03:30:03', NULL, '2022-01-23 03:30:03', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22882, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:25', '2022-01-23 03:30:25', 32, 0, '', NULL, '2022-01-23 03:30:25', NULL, '2022-01-23 03:30:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22883, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:25', '2022-01-23 03:30:25', 46, 0, '', NULL, '2022-01-23 03:30:25', NULL, '2022-01-23 03:30:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22884, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:25', '2022-01-23 03:30:25', 10, 0, '', NULL, '2022-01-23 03:30:25', NULL, '2022-01-23 03:30:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22885, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:25', '2022-01-23 03:30:25', 19, 0, '', NULL, '2022-01-23 03:30:25', NULL, '2022-01-23 03:30:25', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22886, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:30:25', '2022-01-23 03:30:25', 62, 0, '', NULL, '2022-01-23 03:30:25', NULL, '2022-01-23 03:30:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22887, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:18', '2022-01-23 03:32:18', 64, 0, '', NULL, '2022-01-23 03:32:18', NULL, '2022-01-23 03:32:18', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22888, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:18', '2022-01-23 03:32:19', 155, 0, '', NULL, '2022-01-23 03:32:19', NULL, '2022-01-23 03:32:19', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22889, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\",\"key\":\"eee\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:49', '2022-01-23 03:32:49', 148, 0, '', NULL, '2022-01-23 03:32:49', NULL, '2022-01-23 03:32:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22890, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/role/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:50', '2022-01-23 03:32:51', 36, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22891, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task-assign-rule/list', '{\"query\":{\"processDefinitionId\":\"eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:50', '2022-01-23 03:32:51', 63, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22892, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dept/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:50', '2022-01-23 03:32:51', 58, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22893, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/post/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:50', '2022-01-23 03:32:51', 60, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22894, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:51', '2022-01-23 03:32:51', 65, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22895, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:50', '2022-01-23 03:32:51', 82, 0, '', NULL, '2022-01-23 03:32:51', NULL, '2022-01-23 03:32:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22896, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:54', '2022-01-23 03:32:54', 13, 0, '', NULL, '2022-01-23 03:32:54', NULL, '2022-01-23 03:32:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22897, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:54', '2022-01-23 03:32:54', 98, 0, '', NULL, '2022-01-23 03:32:54', NULL, '2022-01-23 03:32:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22898, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/role/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 27, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22899, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/post/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 28, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22900, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dept/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 47, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22901, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 23, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22902, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 48, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22903, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task-assign-rule/list', '{\"query\":{\"modelId\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:32:56', '2022-01-23 03:32:56', 217, 0, '', NULL, '2022-01-23 03:32:56', NULL, '2022-01-23 03:32:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22904, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:33:55', '2022-01-23 03:33:55', 21, 0, '', NULL, '2022-01-23 03:33:55', NULL, '2022-01-23 03:33:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22905, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:33:55', '2022-01-23 03:33:55', 40, 0, '', NULL, '2022-01-23 03:33:55', NULL, '2022-01-23 03:33:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22906, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:33:55', '2022-01-23 03:33:55', 5, 0, '', NULL, '2022-01-23 03:33:55', NULL, '2022-01-23 03:33:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22907, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:33:55', '2022-01-23 03:33:55', 14, 0, '', NULL, '2022-01-23 03:33:55', NULL, '2022-01-23 03:33:55', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22908, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:33:56', '2022-01-23 03:33:56', 43, 0, '', NULL, '2022-01-23 03:33:56', NULL, '2022-01-23 03:33:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22909, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 19, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22910, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 30, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22911, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 7, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22912, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 18, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22913, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 18, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22914, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:23', '2022-01-23 03:34:23', 101, 0, '', NULL, '2022-01-23 03:34:23', NULL, '2022-01-23 03:34:23', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22915, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:38', '2022-01-23 03:34:38', 24, 0, '', NULL, '2022-01-23 03:34:38', NULL, '2022-01-23 03:34:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22916, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:38', '2022-01-23 03:34:38', 39, 0, '', NULL, '2022-01-23 03:34:38', NULL, '2022-01-23 03:34:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22917, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:38', '2022-01-23 03:34:38', 6, 0, '', NULL, '2022-01-23 03:34:38', NULL, '2022-01-23 03:34:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22918, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:39', '2022-01-23 03:34:39', 19, 0, '', NULL, '2022-01-23 03:34:39', NULL, '2022-01-23 03:34:39', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22919, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/get', '{\"query\":{\"id\":\"02b756a8-79af-11ec-abb0-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:34:39', '2022-01-23 03:34:39', 48, 0, '', NULL, '2022-01-23 03:34:39', NULL, '2022-01-23 03:34:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22920, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 28, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22921, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 46, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22922, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 22, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22923, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 5, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22924, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 31, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22925, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 6, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22926, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 26, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22927, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:44', '2022-01-23 03:37:44', 36, 0, '', NULL, '2022-01-23 03:37:44', NULL, '2022-01-23 03:37:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22928, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 17, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22929, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 16, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22930, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 14, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22931, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 125, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22932, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 20, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22933, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:45', '2022-01-23 03:37:45', 141, 0, '', NULL, '2022-01-23 03:37:45', NULL, '2022-01-23 03:37:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22934, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:46', '2022-01-23 03:37:46', 18, 0, '', NULL, '2022-01-23 03:37:46', NULL, '2022-01-23 03:37:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22935, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:46', '2022-01-23 03:37:46', 35, 0, '', NULL, '2022-01-23 03:37:46', NULL, '2022-01-23 03:37:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22936, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:46', '2022-01-23 03:37:46', 5, 0, '', NULL, '2022-01-23 03:37:46', NULL, '2022-01-23 03:37:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22937, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:46', '2022-01-23 03:37:46', 4, 0, '', NULL, '2022-01-23 03:37:46', NULL, '2022-01-23 03:37:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22938, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:47', '2022-01-23 03:37:47', 11, 0, '', NULL, '2022-01-23 03:37:47', NULL, '2022-01-23 03:37:47', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22939, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/todo-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:47', '2022-01-23 03:37:47', 121, 0, '', NULL, '2022-01-23 03:37:47', NULL, '2022-01-23 03:37:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22940, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:47', '2022-01-23 03:37:47', 19, 0, '', NULL, '2022-01-23 03:37:47', NULL, '2022-01-23 03:37:47', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22941, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/todo-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:47', '2022-01-23 03:37:47', 64, 0, '', NULL, '2022-01-23 03:37:47', NULL, '2022-01-23 03:37:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22942, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 23, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22943, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 34, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22944, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 5, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22945, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 26, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22946, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 39, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22947, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 30, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22948, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:52', '2022-01-23 03:37:52', 74, 0, '', NULL, '2022-01-23 03:37:52', NULL, '2022-01-23 03:37:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22949, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:53', '2022-01-23 03:37:53', 5, 0, '', NULL, '2022-01-23 03:37:53', NULL, '2022-01-23 03:37:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22950, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 25, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22951, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 41, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22952, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 6, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22953, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 5, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22954, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 22, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22955, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:54', 19, 0, '', NULL, '2022-01-23 03:37:54', NULL, '2022-01-23 03:37:54', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22956, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:54', '2022-01-23 03:37:55', 120, 0, '', NULL, '2022-01-23 03:37:55', NULL, '2022-01-23 03:37:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22957, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:55', '2022-01-23 03:37:55', 16, 0, '', NULL, '2022-01-23 03:37:55', NULL, '2022-01-23 03:37:55', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22958, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:55', '2022-01-23 03:37:55', 17, 0, '', NULL, '2022-01-23 03:37:55', NULL, '2022-01-23 03:37:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22959, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:55', '2022-01-23 03:37:55', 144, 0, '', NULL, '2022-01-23 03:37:55', NULL, '2022-01-23 03:37:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22960, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:56', '2022-01-23 03:37:56', 17, 0, '', NULL, '2022-01-23 03:37:56', NULL, '2022-01-23 03:37:56', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22961, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/todo-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:56', '2022-01-23 03:37:56', 68, 0, '', NULL, '2022-01-23 03:37:56', NULL, '2022-01-23 03:37:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22962, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:56', '2022-01-23 03:37:56', 18, 0, '', NULL, '2022-01-23 03:37:56', NULL, '2022-01-23 03:37:56', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22963, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/todo-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:37:56', '2022-01-23 03:37:56', 61, 0, '', NULL, '2022-01-23 03:37:56', NULL, '2022-01-23 03:37:56', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22964, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:45', 146, 0, '', NULL, '2022-01-23 03:44:45', NULL, '2022-01-23 03:44:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22965, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:45', 156, 0, '', NULL, '2022-01-23 03:44:45', NULL, '2022-01-23 03:44:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22966, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:45', 4, 0, '', NULL, '2022-01-23 03:44:45', NULL, '2022-01-23 03:44:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22967, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:45', 12, 0, '', NULL, '2022-01-23 03:44:45', NULL, '2022-01-23 03:44:45', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22968, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:46', 16, 0, '', NULL, '2022-01-23 03:44:46', NULL, '2022-01-23 03:44:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22969, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/model/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 03:44:45', '2022-01-23 03:44:46', 120, 0, '', NULL, '2022-01-23 03:44:46', NULL, '2022-01-23 03:44:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22970, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:38', '2022-01-23 04:10:38', 47, 0, '', NULL, '2022-01-23 04:10:38', NULL, '2022-01-23 04:10:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22971, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:38', '2022-01-23 04:10:38', 50, 0, '', NULL, '2022-01-23 04:10:38', NULL, '2022-01-23 04:10:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22972, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 1, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22973, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 10, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22974, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 11, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22975, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 10, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22976, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 10, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22977, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 10, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22978, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', 'undefined', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:10:39', '2022-01-23 04:10:39', 9, 0, '', NULL, '2022-01-23 04:10:39', NULL, '2022-01-23 04:10:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22979, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:46', '2022-01-23 04:19:46', 51, 0, '', NULL, '2022-01-23 04:19:47', NULL, '2022-01-23 04:19:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22980, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:46', '2022-01-23 04:19:46', 51, 0, '', NULL, '2022-01-23 04:19:47', NULL, '2022-01-23 04:19:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22981, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:47', '2022-01-23 04:19:47', 12, 0, '', NULL, '2022-01-23 04:19:47', NULL, '2022-01-23 04:19:47', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22982, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:48', '2022-01-23 04:19:48', 2, 0, '', NULL, '2022-01-23 04:19:48', NULL, '2022-01-23 04:19:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22983, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:48', '2022-01-23 04:19:49', 1172, 0, '', NULL, '2022-01-23 04:19:49', NULL, '2022-01-23 04:19:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22984, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:47', '2022-01-23 04:19:49', 2370, 0, '', NULL, '2022-01-23 04:19:49', NULL, '2022-01-23 04:19:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22985, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:52', '2022-01-23 04:19:52', 45, 0, '', NULL, '2022-01-23 04:19:52', NULL, '2022-01-23 04:19:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22986, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"nzgnu\\\",\\\"uuid\\\":\\\"256030e97aa64c5a84e0614f5b065a66\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:52', '2022-01-23 04:19:53', 366, 0, '', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22987, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:53', '2022-01-23 04:19:53', 54, 0, '', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22988, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:53', '2022-01-23 04:19:53', 60, 0, '', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22989, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:53', '2022-01-23 04:19:53', 12, 0, '', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22990, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:53', '2022-01-23 04:19:53', 40, 0, '', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (22991, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:58', '2022-01-23 04:19:58', 106, 0, '', NULL, '2022-01-23 04:19:58', NULL, '2022-01-23 04:19:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22992, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:59', '2022-01-23 04:19:59', 29, 0, '', NULL, '2022-01-23 04:19:59', NULL, '2022-01-23 04:19:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22993, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:19:59', '2022-01-23 04:19:59', 117, 0, '', NULL, '2022-01-23 04:19:59', NULL, '2022-01-23 04:19:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22994, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:00', '2022-01-23 04:20:00', 19, 0, '', NULL, '2022-01-23 04:20:00', NULL, '2022-01-23 04:20:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22995, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:00', '2022-01-23 04:20:00', 138, 0, '', NULL, '2022-01-23 04:20:00', NULL, '2022-01-23 04:20:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22996, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:00', '2022-01-23 04:20:00', 16, 0, '', NULL, '2022-01-23 04:20:00', NULL, '2022-01-23 04:20:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22997, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:00', '2022-01-23 04:20:00', 87, 0, '', NULL, '2022-01-23 04:20:00', NULL, '2022-01-23 04:20:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22998, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:01', '2022-01-23 04:20:01', 26, 0, '', NULL, '2022-01-23 04:20:01', NULL, '2022-01-23 04:20:01', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (22999, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:07', '2022-01-23 04:20:07', 17, 0, '', NULL, '2022-01-23 04:20:07', NULL, '2022-01-23 04:20:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23000, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:07', '2022-01-23 04:20:07', 67, 0, '', NULL, '2022-01-23 04:20:07', NULL, '2022-01-23 04:20:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23001, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:10', '2022-01-23 04:20:10', 20, 0, '', NULL, '2022-01-23 04:20:10', NULL, '2022-01-23 04:20:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23002, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:10', '2022-01-23 04:20:10', 53, 0, '', NULL, '2022-01-23 04:20:10', NULL, '2022-01-23 04:20:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23003, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:11', '2022-01-23 04:20:11', 22, 0, '', NULL, '2022-01-23 04:20:11', NULL, '2022-01-23 04:20:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23004, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:11', '2022-01-23 04:20:11', 54, 0, '', NULL, '2022-01-23 04:20:11', NULL, '2022-01-23 04:20:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23005, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:13', '2022-01-23 04:20:13', 27, 0, '', NULL, '2022-01-23 04:20:13', NULL, '2022-01-23 04:20:13', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23006, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:14', '2022-01-23 04:20:15', 15, 0, '', NULL, '2022-01-23 04:20:15', NULL, '2022-01-23 04:20:15', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23007, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:14', '2022-01-23 04:20:15', 41, 0, '', NULL, '2022-01-23 04:20:15', NULL, '2022-01-23 04:20:15', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23008, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:25', '2022-01-23 04:20:25', 24, 0, '', NULL, '2022-01-23 04:20:25', NULL, '2022-01-23 04:20:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23009, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/get', '{\"query\":{\"id\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:27', '2022-01-23 04:20:27', 17, 0, '', NULL, '2022-01-23 04:20:27', NULL, '2022-01-23 04:20:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23010, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:30', '2022-01-23 04:20:30', 22, 0, '', NULL, '2022-01-23 04:20:30', NULL, '2022-01-23 04:20:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23011, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 04:20:30', '2022-01-23 04:20:30', 68, 0, '', NULL, '2022-01-23 04:20:30', NULL, '2022-01-23 04:20:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23012, '', 0, 0, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:11', '2022-01-23 12:40:11', 46, 0, '', NULL, '2022-01-23 12:40:12', NULL, '2022-01-23 12:40:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23013, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:11', '2022-01-23 12:40:11', 46, 0, '', NULL, '2022-01-23 12:40:12', NULL, '2022-01-23 12:40:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23014, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:12', '2022-01-23 12:40:12', 22, 0, '', NULL, '2022-01-23 12:40:12', NULL, '2022-01-23 12:40:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23015, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:12', '2022-01-23 12:40:17', 4835, 0, '', NULL, '2022-01-23 12:40:17', NULL, '2022-01-23 12:40:17', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23016, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:12', '2022-01-23 12:40:17', 4887, 0, '', NULL, '2022-01-23 12:40:17', NULL, '2022-01-23 12:40:17', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23017, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:58', '2022-01-23 12:40:58', 164, 0, '', NULL, '2022-01-23 12:40:58', NULL, '2022-01-23 12:40:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23018, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"493kz\\\",\\\"uuid\\\":\\\"7e3a66a57c4d491cba7ca3425029d780\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:58', '2022-01-23 12:40:59', 359, 0, '', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 12:40:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23019, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:59', '2022-01-23 12:40:59', 67, 0, '', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 12:40:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23020, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:59', '2022-01-23 12:40:59', 62, 0, '', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 12:40:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23021, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:40:59', '2022-01-23 12:40:59', 17, 0, '', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 12:40:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23022, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:00', '2022-01-23 12:41:00', 53, 0, '', NULL, '2022-01-23 12:41:00', NULL, '2022-01-23 12:41:00', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23023, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/oa/leave/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:07', '2022-01-23 12:41:07', 119, 0, '', NULL, '2022-01-23 12:41:07', NULL, '2022-01-23 12:41:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23024, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:07', '2022-01-23 12:41:08', 104, 0, '', NULL, '2022-01-23 12:41:08', NULL, '2022-01-23 12:41:08', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23025, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:10', '2022-01-23 12:41:10', 71, 0, '', NULL, '2022-01-23 12:41:10', NULL, '2022-01-23 12:41:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23026, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/get-bpmn-xml', '{\"query\":{\"id\":\"eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:12', '2022-01-23 12:41:12', 33, 0, '', NULL, '2022-01-23 12:41:12', NULL, '2022-01-23 12:41:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23027, '', 1, 2, 'yudao-admin-server', 'POST', '/api/bpm/process-instance/create', '{\"query\":{},\"body\":\"{\\\"processDefinitionId\\\":\\\"eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a\\\",\\\"variables\\\":{\\\"field121\\\":\\\"AAA\\\",\\\"field122\\\":[1]}}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:14', '2022-01-23 12:41:19', 4971, 0, '', NULL, '2022-01-23 12:41:19', NULL, '2022-01-23 12:41:19', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23028, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:41:21', '2022-01-23 12:41:21', 71, 0, '', NULL, '2022-01-23 12:41:21', NULL, '2022-01-23 12:41:21', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23029, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:49', '2022-01-23 12:49:49', 251, 0, '', NULL, '2022-01-23 12:49:49', NULL, '2022-01-23 12:49:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23030, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:49', '2022-01-23 12:49:49', 251, 0, '', NULL, '2022-01-23 12:49:49', NULL, '2022-01-23 12:49:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23031, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:49', '2022-01-23 12:49:49', 24, 0, '', NULL, '2022-01-23 12:49:49', NULL, '2022-01-23 12:49:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23032, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:49', '2022-01-23 12:49:50', 70, 0, '', NULL, '2022-01-23 12:49:50', NULL, '2022-01-23 12:49:50', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23033, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:49', '2022-01-23 12:49:50', 158, 0, '', NULL, '2022-01-23 12:49:50', NULL, '2022-01-23 12:49:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23034, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/oa/leave/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:53', '2022-01-23 12:49:53', 153, 0, '', NULL, '2022-01-23 12:49:53', NULL, '2022-01-23 12:49:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23035, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:55', '2022-01-23 12:49:55', 140, 0, '', NULL, '2022-01-23 12:49:55', NULL, '2022-01-23 12:49:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23036, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:57', '2022-01-23 12:49:57', 42, 0, '', NULL, '2022-01-23 12:49:57', NULL, '2022-01-23 12:49:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23037, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/get-bpmn-xml', '{\"query\":{\"id\":\"test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:49:59', '2022-01-23 12:49:59', 34, 0, '', NULL, '2022-01-23 12:49:59', NULL, '2022-01-23 12:49:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23038, '', 1, 2, 'yudao-admin-server', 'POST', '/api/bpm/process-instance/create', '{\"query\":{},\"body\":\"{\\\"processDefinitionId\\\":\\\"test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a\\\",\\\"variables\\\":{\\\"field121\\\":\\\"AAA\\\",\\\"field122\\\":[1]}}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:02', '2022-01-23 12:50:06', 4140, 0, '', NULL, '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:06', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23039, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:07', '2022-01-23 12:50:07', 162, 0, '', NULL, '2022-01-23 12:50:07', NULL, '2022-01-23 12:50:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23040, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:38', '2022-01-23 12:50:38', 41, 0, '', NULL, '2022-01-23 12:50:38', NULL, '2022-01-23 12:50:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23041, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:42', '2022-01-23 12:50:42', 28, 0, '', NULL, '2022-01-23 12:50:42', NULL, '2022-01-23 12:50:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23042, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/get-bpmn-xml', '{\"query\":{\"id\":\"self:2:3a5a065e-76b1-11ec-9c66-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:44', '2022-01-23 12:50:44', 16, 0, '', NULL, '2022-01-23 12:50:44', NULL, '2022-01-23 12:50:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23043, '', 1, 2, 'yudao-admin-server', 'POST', '/api/bpm/process-instance/create', '{\"query\":{},\"body\":\"{\\\"processDefinitionId\\\":\\\"self:2:3a5a065e-76b1-11ec-9c66-a2380e71991a\\\",\\\"variables\\\":{\\\"field121\\\":\\\"aaa\\\",\\\"field122\\\":[1]}}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:46', '2022-01-23 12:50:46', 217, 500, '系统异常', NULL, '2022-01-23 12:50:46', NULL, '2022-01-23 12:50:46', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23044, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:51', '2022-01-23 12:50:51', 53, 0, '', NULL, '2022-01-23 12:50:51', NULL, '2022-01-23 12:50:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23045, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:55', '2022-01-23 12:50:55', 29, 0, '', NULL, '2022-01-23 12:50:55', NULL, '2022-01-23 12:50:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23046, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:51', '2022-01-23 12:58:52', 585, 0, '', NULL, '2022-01-23 12:58:52', NULL, '2022-01-23 12:58:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23047, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:53', '2022-01-23 12:58:53', 48, 0, '', NULL, '2022-01-23 12:58:53', NULL, '2022-01-23 12:58:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23048, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:53', '2022-01-23 12:58:53', 57, 0, '', NULL, '2022-01-23 12:58:53', NULL, '2022-01-23 12:58:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23049, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:53', '2022-01-23 12:58:53', 16, 0, '', NULL, '2022-01-23 12:58:53', NULL, '2022-01-23 12:58:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23050, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:53', '2022-01-23 12:58:53', 41, 0, '', NULL, '2022-01-23 12:58:53', NULL, '2022-01-23 12:58:53', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23051, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:58:53', '2022-01-23 12:58:53', 57, 0, '', NULL, '2022-01-23 12:58:53', NULL, '2022-01-23 12:58:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23052, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:07', '2022-01-23 12:59:07', 23, 0, '', NULL, '2022-01-23 12:59:07', NULL, '2022-01-23 12:59:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23053, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:07', '2022-01-23 12:59:07', 32, 0, '', NULL, '2022-01-23 12:59:07', NULL, '2022-01-23 12:59:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23054, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:07', '2022-01-23 12:59:07', 8, 0, '', NULL, '2022-01-23 12:59:07', NULL, '2022-01-23 12:59:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23055, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:07', '2022-01-23 12:59:07', 18, 0, '', NULL, '2022-01-23 12:59:07', NULL, '2022-01-23 12:59:07', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23056, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:07', '2022-01-23 12:59:07', 46, 0, '', NULL, '2022-01-23 12:59:07', NULL, '2022-01-23 12:59:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23057, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:10', '2022-01-23 12:59:10', 40, 0, '', NULL, '2022-01-23 12:59:10', NULL, '2022-01-23 12:59:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23058, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:36', '2022-01-23 12:59:36', 25, 0, '', NULL, '2022-01-23 12:59:36', NULL, '2022-01-23 12:59:36', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23059, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:36', '2022-01-23 12:59:36', 40, 0, '', NULL, '2022-01-23 12:59:36', NULL, '2022-01-23 12:59:36', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23060, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:36', '2022-01-23 12:59:36', 6, 0, '', NULL, '2022-01-23 12:59:36', NULL, '2022-01-23 12:59:36', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23061, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:37', '2022-01-23 12:59:37', 15, 0, '', NULL, '2022-01-23 12:59:37', NULL, '2022-01-23 12:59:37', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23062, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:37', '2022-01-23 12:59:37', 50, 0, '', NULL, '2022-01-23 12:59:37', NULL, '2022-01-23 12:59:37', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23063, '', 1, 2, 'yudao-admin-server', 'DELETE', '/api/bpm/process-instance/cancel', '{\"query\":{},\"body\":\"{\\\"id\\\":\\\"ecddb286-7c07-11ec-a41d-acde48001122\\\",\\\"reason\\\":\\\"aaa\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:40', '2022-01-23 12:59:41', 403, 0, '', NULL, '2022-01-23 12:59:41', NULL, '2022-01-23 12:59:41', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23064, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:41', '2022-01-23 12:59:41', 41, 0, '', NULL, '2022-01-23 12:59:41', NULL, '2022-01-23 12:59:41', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23065, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/task/todo-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:43', '2022-01-23 12:59:43', 92, 0, '', NULL, '2022-01-23 12:59:43', NULL, '2022-01-23 12:59:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23066, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:44', '2022-01-23 12:59:44', 49, 0, '', NULL, '2022-01-23 12:59:44', NULL, '2022-01-23 12:59:44', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23067, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:48', '2022-01-23 12:59:48', 40, 0, '', NULL, '2022-01-23 12:59:48', NULL, '2022-01-23 12:59:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23068, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:48', '2022-01-23 12:59:48', 58, 0, '', NULL, '2022-01-23 12:59:48', NULL, '2022-01-23 12:59:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23069, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:51', '2022-01-23 12:59:51', 44, 0, '', NULL, '2022-01-23 12:59:51', NULL, '2022-01-23 12:59:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23070, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/list', '{\"query\":{\"suspensionState\":\"1\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:52', '2022-01-23 12:59:53', 49, 0, '', NULL, '2022-01-23 12:59:53', NULL, '2022-01-23 12:59:53', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23071, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-definition/get-bpmn-xml', '{\"query\":{\"id\":\"test:21:c2cd44b0-79b0-11ec-b2b8-a2380e71991a\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:55', '2022-01-23 12:59:55', 25, 0, '', NULL, '2022-01-23 12:59:55', NULL, '2022-01-23 12:59:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23072, '', 1, 2, 'yudao-admin-server', 'POST', '/api/bpm/process-instance/create', '{\"query\":{},\"body\":\"{\\\"processDefinitionId\\\":\\\"test:21:c2cd44b0-79b0-11ec-b2b8-a2380e71991a\\\",\\\"variables\\\":{\\\"field121\\\":\\\"aaa\\\",\\\"field122\\\":[1]}}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:57', '2022-01-23 12:59:57', 392, 0, '', NULL, '2022-01-23 12:59:57', NULL, '2022-01-23 12:59:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23073, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/process-instance/my-page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:59:58', '2022-01-23 12:59:58', 35, 0, '', NULL, '2022-01-23 12:59:58', NULL, '2022-01-23 12:59:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23074, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:12:55', '2022-01-23 13:12:55', 182, 0, '', NULL, '2022-01-23 13:12:55', NULL, '2022-01-23 13:12:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23075, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:12:55', '2022-01-23 13:12:55', 171, 0, '', NULL, '2022-01-23 13:12:55', NULL, '2022-01-23 13:12:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23076, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:12:55', '2022-01-23 13:12:55', 15, 0, '', NULL, '2022-01-23 13:12:55', NULL, '2022-01-23 13:12:55', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23077, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:12:55', '2022-01-23 13:12:55', 34, 0, '', NULL, '2022-01-23 13:12:55', NULL, '2022-01-23 13:12:55', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23078, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:13:00', '2022-01-23 13:13:00', 121, 0, '', NULL, '2022-01-23 13:13:00', NULL, '2022-01-23 13:13:00', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23079, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:18:59', '2022-01-23 13:18:59', 29, 0, '', NULL, '2022-01-23 13:18:59', NULL, '2022-01-23 13:18:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23080, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:18:59', '2022-01-23 13:18:59', 57, 0, '', NULL, '2022-01-23 13:18:59', NULL, '2022-01-23 13:18:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23081, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:18:59', '2022-01-23 13:18:59', 5, 0, '', NULL, '2022-01-23 13:18:59', NULL, '2022-01-23 13:18:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23082, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:18:59', '2022-01-23 13:18:59', 12, 0, '', NULL, '2022-01-23 13:18:59', NULL, '2022-01-23 13:18:59', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23083, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:18:59', '2022-01-23 13:18:59', 25, 0, '', NULL, '2022-01-23 13:18:59', NULL, '2022-01-23 13:18:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23084, '', 0, 0, 'yudao-admin-server', 'POST', '/api/logout', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:39', '2022-01-23 13:24:39', 6, 0, '', NULL, '2022-01-23 13:24:39', NULL, '2022-01-23 13:24:39', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23085, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/captcha/get-image', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:40', '2022-01-23 13:24:42', 1905, 0, '', NULL, '2022-01-23 13:24:42', NULL, '2022-01-23 13:24:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23086, '', 0, 0, 'yudao-admin-server', 'GET', '/api/system/tenant/get-id-by-name', '{\"query\":{\"name\":\"芋道源码\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:43', '2022-01-23 13:24:43', 25, 0, '', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23087, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"111\\\",\\\"uuid\\\":\\\"7f690d86eaac44f18c0aeabfa8c4e365\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:43', '2022-01-23 13:24:43', 307, 0, '', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23088, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:43', '2022-01-23 13:24:43', 18, 0, '', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23089, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:43', '2022-01-23 13:24:43', 29, 0, '', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23090, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:43', '2022-01-23 13:24:43', 5, 0, '', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23091, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:44', '2022-01-23 13:24:44', 13, 0, '', NULL, '2022-01-23 13:24:44', NULL, '2022-01-23 13:24:44', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23092, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:48', '2022-01-23 13:24:48', 47, 0, '', NULL, '2022-01-23 13:24:48', NULL, '2022-01-23 13:24:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23093, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/user/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:49', '2022-01-23 13:24:49', 38, 0, '', NULL, '2022-01-23 13:24:49', NULL, '2022-01-23 13:24:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23094, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/user-group/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:49', '2022-01-23 13:24:49', 50, 0, '', NULL, '2022-01-23 13:24:49', NULL, '2022-01-23 13:24:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23095, '', 1, 2, 'yudao-admin-server', 'GET', '/api/bpm/form/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:50', '2022-01-23 13:24:50', 24, 0, '', NULL, '2022-01-23 13:24:50', NULL, '2022-01-23 13:24:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23096, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:52', '2022-01-23 13:24:52', 24, 0, '', NULL, '2022-01-23 13:24:52', NULL, '2022-01-23 13:24:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23097, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:24:52', '2022-01-23 13:24:52', 134, 0, '', NULL, '2022-01-23 13:24:52', NULL, '2022-01-23 13:24:52', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23098, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:05', '2022-01-23 13:25:05', 31, 0, '', NULL, '2022-01-23 13:25:05', NULL, '2022-01-23 13:25:05', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23099, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:06', '2022-01-23 13:25:06', 30, 0, '', NULL, '2022-01-23 13:25:06', NULL, '2022-01-23 13:25:06', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23100, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:12', '2022-01-23 13:25:12', 29, 0, '', NULL, '2022-01-23 13:25:12', NULL, '2022-01-23 13:25:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23101, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:12', '2022-01-23 13:25:12', 31, 0, '', NULL, '2022-01-23 13:25:12', NULL, '2022-01-23 13:25:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23102, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:12', '2022-01-23 13:25:12', 29, 0, '', NULL, '2022-01-23 13:25:12', NULL, '2022-01-23 13:25:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23103, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:12', '2022-01-23 13:25:13', 30, 0, '', NULL, '2022-01-23 13:25:13', NULL, '2022-01-23 13:25:13', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23104, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:32', '2022-01-23 13:25:32', 33, 0, '', NULL, '2022-01-23 13:25:32', NULL, '2022-01-23 13:25:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23105, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:42', '2022-01-23 13:25:42', 30, 0, '', NULL, '2022-01-23 13:25:42', NULL, '2022-01-23 13:25:42', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23106, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-12-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-12-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:48', '2022-01-23 13:25:48', 31, 0, '', NULL, '2022-01-23 13:25:48', NULL, '2022-01-23 13:25:48', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23107, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-12-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-12-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:49', '2022-01-23 13:25:49', 32, 0, '', NULL, '2022-01-23 13:25:49', NULL, '2022-01-23 13:25:49', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23108, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-12-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-12-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:50', '2022-01-23 13:25:50', 31, 0, '', NULL, '2022-01-23 13:25:50', NULL, '2022-01-23 13:25:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23109, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-11-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-11-30 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:25:58', '2022-01-23 13:25:58', 31, 0, '', NULL, '2022-01-23 13:25:58', NULL, '2022-01-23 13:25:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23110, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-10-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-10-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:26:19', '2022-01-23 13:26:19', 83, 0, '', NULL, '2022-01-23 13:26:19', NULL, '2022-01-23 13:26:19', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23111, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/get', '{\"query\":{\"id\":\"121\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:26:57', '2022-01-23 13:26:58', 77, 0, '', NULL, '2022-01-23 13:26:58', NULL, '2022-01-23 13:26:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23112, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/get', '{\"query\":{\"id\":\"120\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:27:06', '2022-01-23 13:27:06', 41, 0, '', NULL, '2022-01-23 13:27:06', NULL, '2022-01-23 13:27:06', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23113, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/get', '{\"query\":{\"id\":\"119\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:27:13', '2022-01-23 13:27:14', 40, 0, '', NULL, '2022-01-23 13:27:14', NULL, '2022-01-23 13:27:14', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23114, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:28:09', '2022-01-23 13:28:09', 13, 0, '', NULL, '2022-01-23 13:28:09', NULL, '2022-01-23 13:28:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23115, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:28:09', '2022-01-23 13:28:09', 63, 0, '', NULL, '2022-01-23 13:28:09', NULL, '2022-01-23 13:28:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23116, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2021-11-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-11-30 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:28:15', '2022-01-23 13:28:15', 31, 0, '', NULL, '2022-01-23 13:28:15', NULL, '2022-01-23 13:28:15', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23117, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:30:06', '2022-01-23 13:30:06', 27, 0, '', NULL, '2022-01-23 13:30:06', NULL, '2022-01-23 13:30:06', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23118, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:30:40', '2022-01-23 13:30:40', 12, 0, '', NULL, '2022-01-23 13:30:40', NULL, '2022-01-23 13:30:40', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23119, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:30:40', '2022-01-23 13:30:40', 79, 0, '', NULL, '2022-01-23 13:30:40', NULL, '2022-01-23 13:30:40', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23120, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/channel/get-channel', '{\"query\":{\"code\":\"alipay_app\",\"merchantId\":\"1\",\"appId\":\"6\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:30:57', '2022-01-23 13:30:57', 25, 0, '', NULL, '2022-01-23 13:30:57', NULL, '2022-01-23 13:30:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23121, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/channel/get-channel', '{\"query\":{\"code\":\"alipay_app\",\"merchantId\":\"1\",\"appId\":\"6\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:30:59', '2022-01-23 13:30:59', 19, 0, '', NULL, '2022-01-23 13:30:59', NULL, '2022-01-23 13:30:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23122, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/channel/get-channel', '{\"query\":{\"code\":\"alipay_app\",\"merchantId\":\"1\",\"appId\":\"6\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:02', '2022-01-23 13:31:02', 14, 0, '', NULL, '2022-01-23 13:31:02', NULL, '2022-01-23 13:31:02', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23123, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:09', '2022-01-23 13:31:09', 32, 0, '', NULL, '2022-01-23 13:31:09', NULL, '2022-01-23 13:31:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23124, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:09', '2022-01-23 13:31:09', 45, 0, '', NULL, '2022-01-23 13:31:09', NULL, '2022-01-23 13:31:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23125, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:10', '2022-01-23 13:31:10', 7, 0, '', NULL, '2022-01-23 13:31:10', NULL, '2022-01-23 13:31:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23126, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:10', '2022-01-23 13:31:10', 13, 0, '', NULL, '2022-01-23 13:31:10', NULL, '2022-01-23 13:31:10', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23127, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:11', '2022-01-23 13:31:11', 16, 0, '', NULL, '2022-01-23 13:31:11', NULL, '2022-01-23 13:31:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23128, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:11', '2022-01-23 13:31:11', 57, 0, '', NULL, '2022-01-23 13:31:11', NULL, '2022-01-23 13:31:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23129, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/channel/get-channel', '{\"query\":{\"code\":\"alipay_app\",\"merchantId\":\"1\",\"appId\":\"6\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:16', '2022-01-23 13:31:16', 16, 0, '', NULL, '2022-01-23 13:31:16', NULL, '2022-01-23 13:31:16', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23130, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:50', '2022-01-23 13:31:50', 14, 0, '', NULL, '2022-01-23 13:31:50', NULL, '2022-01-23 13:31:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23131, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:50', '2022-01-23 13:31:50', 39, 0, '', NULL, '2022-01-23 13:31:50', NULL, '2022-01-23 13:31:50', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23132, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:58', '2022-01-23 13:31:58', 32, 0, '', NULL, '2022-01-23 13:31:58', NULL, '2022-01-23 13:31:58', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23133, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:31:59', '2022-01-23 13:31:59', 31, 0, '', NULL, '2022-01-23 13:31:59', NULL, '2022-01-23 13:31:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23134, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-09-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-09-30 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:32:07', '2022-01-23 13:32:07', 30, 0, '', NULL, '2022-01-23 13:32:07', NULL, '2022-01-23 13:32:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23135, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-10-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-10-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:32:15', '2022-01-23 13:32:15', 60, 0, '', NULL, '2022-01-23 13:32:15', NULL, '2022-01-23 13:32:15', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23136, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:10', 24, 0, '', NULL, '2022-01-23 13:33:10', NULL, '2022-01-23 13:33:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23137, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:10', 42, 0, '', NULL, '2022-01-23 13:33:10', NULL, '2022-01-23 13:33:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23138, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:10', 5, 0, '', NULL, '2022-01-23 13:33:10', NULL, '2022-01-23 13:33:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23139, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:10', 15, 0, '', NULL, '2022-01-23 13:33:10', NULL, '2022-01-23 13:33:10', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23140, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:10', 20, 0, '', NULL, '2022-01-23 13:33:10', NULL, '2022-01-23 13:33:10', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23141, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:10', '2022-01-23 13:33:11', 46, 0, '', NULL, '2022-01-23 13:33:11', NULL, '2022-01-23 13:33:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23142, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-11-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-11-30 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:18', '2022-01-23 13:33:18', 29, 0, '', NULL, '2022-01-23 13:33:18', NULL, '2022-01-23 13:33:18', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23143, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/order/page', '{\"query\":{\"beginCreateTime\":\"2021-10-01 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2021-10-31 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:33:26', '2022-01-23 13:33:26', 54, 0, '', NULL, '2022-01-23 13:33:26', NULL, '2022-01-23 13:33:26', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23144, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:08', '2022-01-23 13:34:08', 14, 0, '', NULL, '2022-01-23 13:34:08', NULL, '2022-01-23 13:34:08', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23145, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:08', '2022-01-23 13:34:08', 38, 0, '', NULL, '2022-01-23 13:34:08', NULL, '2022-01-23 13:34:08', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23146, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:18', '2022-01-23 13:34:18', 33, 0, '', NULL, '2022-01-23 13:34:18', NULL, '2022-01-23 13:34:18', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23147, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:18', '2022-01-23 13:34:18', 35, 0, '', NULL, '2022-01-23 13:34:18', NULL, '2022-01-23 13:34:18', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23148, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:18', '2022-01-23 13:34:18', 32, 0, '', NULL, '2022-01-23 13:34:18', NULL, '2022-01-23 13:34:18', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23149, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:19', '2022-01-23 13:34:19', 33, 0, '', NULL, '2022-01-23 13:34:19', NULL, '2022-01-23 13:34:19', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23150, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:19', '2022-01-23 13:34:19', 24, 0, '', NULL, '2022-01-23 13:34:19', NULL, '2022-01-23 13:34:19', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23151, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:19', '2022-01-23 13:34:20', 47, 0, '', NULL, '2022-01-23 13:34:20', NULL, '2022-01-23 13:34:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23152, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:20', '2022-01-23 13:34:20', 6, 0, '', NULL, '2022-01-23 13:34:20', NULL, '2022-01-23 13:34:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23153, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:20', '2022-01-23 13:34:20', 14, 0, '', NULL, '2022-01-23 13:34:20', NULL, '2022-01-23 13:34:20', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23154, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:20', '2022-01-23 13:34:20', 15, 0, '', NULL, '2022-01-23 13:34:20', NULL, '2022-01-23 13:34:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23155, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-23 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-23 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 13:34:20', '2022-01-23 13:34:20', 42, 0, '', NULL, '2022-01-23 13:34:20', NULL, '2022-01-23 13:34:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23156, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"admin123\\\",\\\"code\\\":\\\"1\\\",\\\"uuid\\\":\\\"44f9703e0c7049fbbc1cab18a32ea742\\\"}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:08', '2022-01-24 07:50:09', 359, 0, '', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23157, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:09', '2022-01-24 07:50:09', 41, 0, '', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23158, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:09', '2022-01-24 07:50:09', 50, 0, '', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23159, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:09', '2022-01-24 07:50:09', 11, 0, '', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23160, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:09', '2022-01-24 07:50:10', 39, 0, '', NULL, '2022-01-24 07:50:10', NULL, '2022-01-24 07:50:10', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23161, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-key-list', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:13', '2022-01-24 07:50:13', 16, 0, '', NULL, '2022-01-24 07:50:13', NULL, '2022-01-24 07:50:13', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23162, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-monitor-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:50:13', '2022-01-24 07:50:13', 79, 0, '', NULL, '2022-01-24 07:50:13', NULL, '2022-01-24 07:50:13', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23163, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/job/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:51:09', '2022-01-24 07:51:09', 139, 0, '', NULL, '2022-01-24 07:51:09', NULL, '2022-01-24 07:51:09', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23164, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-key-list', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:51:12', '2022-01-24 07:51:12', 9, 0, '', NULL, '2022-01-24 07:51:12', NULL, '2022-01-24 07:51:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23165, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-monitor-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:51:12', '2022-01-24 07:51:12', 39, 0, '', NULL, '2022-01-24 07:51:12', NULL, '2022-01-24 07:51:12', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23166, '', 1, 2, 'yudao-admin-server', 'GET', '/api/system/dict-data/list-all-simple', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:20', '2022-01-24 07:52:20', 127, 0, '', NULL, '2022-01-24 07:52:20', NULL, '2022-01-24 07:52:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23167, '', 1, 2, 'yudao-admin-server', 'GET', '/api/get-permission-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:20', '2022-01-24 07:52:20', 161, 0, '', NULL, '2022-01-24 07:52:20', NULL, '2022-01-24 07:52:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23168, '', 1, 2, 'yudao-admin-server', 'GET', '/api/list-menus', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:20', '2022-01-24 07:52:20', 11, 0, '', NULL, '2022-01-24 07:52:20', NULL, '2022-01-24 07:52:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23169, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-key-list', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:21', '2022-01-24 07:52:21', 23, 0, '', NULL, '2022-01-24 07:52:21', NULL, '2022-01-24 07:52:21', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23170, '', 0, 0, 'yudao-admin-server', 'GET', '/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:21', '2022-01-24 07:52:21', 51, 0, '', NULL, '2022-01-24 07:52:21', NULL, '2022-01-24 07:52:21', b'0', 0); +INSERT INTO `infra_api_access_log` VALUES (23171, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-monitor-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:21', '2022-01-24 07:52:21', 73, 0, '', NULL, '2022-01-24 07:52:21', NULL, '2022-01-24 07:52:21', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23172, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/api-access-log/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:25', '2022-01-24 07:52:25', 145, 0, '', NULL, '2022-01-24 07:52:25', NULL, '2022-01-24 07:52:25', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23173, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/api-error-log/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:26', '2022-01-24 07:52:26', 71, 0, '', NULL, '2022-01-24 07:52:26', NULL, '2022-01-24 07:52:26', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23174, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/config/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:27', '2022-01-24 07:52:27', 49, 0, '', NULL, '2022-01-24 07:52:27', NULL, '2022-01-24 07:52:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23175, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/file/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:28', '2022-01-24 07:52:28', 29, 0, '', NULL, '2022-01-24 07:52:28', NULL, '2022-01-24 07:52:28', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23176, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-key-list', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:30', '2022-01-24 07:52:30', 14, 0, '', NULL, '2022-01-24 07:52:30', NULL, '2022-01-24 07:52:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23177, '', 1, 2, 'yudao-admin-server', 'GET', '/api/infra/redis/get-monitor-info', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:30', '2022-01-24 07:52:30', 31, 0, '', NULL, '2022-01-24 07:52:30', NULL, '2022-01-24 07:52:30', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23178, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:31', '2022-01-24 07:52:32', 73, 0, '', NULL, '2022-01-24 07:52:32', NULL, '2022-01-24 07:52:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23179, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:32', '2022-01-24 07:52:32', 29, 0, '', NULL, '2022-01-24 07:52:32', NULL, '2022-01-24 07:52:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23180, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/app/page', '{\"query\":{\"pageNo\":\"1\",\"pageSize\":\"10\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:32', '2022-01-24 07:52:32', 138, 0, '', NULL, '2022-01-24 07:52:32', NULL, '2022-01-24 07:52:32', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23181, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/merchant/list-by-name', '{\"query\":{}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:33', '2022-01-24 07:52:33', 20, 0, '', NULL, '2022-01-24 07:52:33', NULL, '2022-01-24 07:52:33', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23182, '', 1, 2, 'yudao-admin-server', 'GET', '/api/pay/refund/page', '{\"query\":{\"beginCreateTime\":\"2022-01-24 00:00:00\",\"pageNo\":\"1\",\"pageSize\":\"10\",\"endCreateTime\":\"2022-01-24 23:59:59\"}}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-24 07:52:33', '2022-01-24 07:52:33', 181, 0, '', NULL, '2022-01-24 07:52:33', NULL, '2022-01-24 07:52:33', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23183, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-28 23:40:57', '2022-01-28 23:40:57', 20, 0, '', NULL, '2022-01-28 23:40:57', NULL, '2022-01-28 23:40:57', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23184, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-28 23:46:37', '2022-01-28 23:46:38', 236, 500, '系统异常', NULL, '2022-01-28 23:46:38', NULL, '2022-01-28 23:46:38', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23185, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 00:35:08', '2022-01-29 00:35:08', 241, 500, '系统异常', NULL, '2022-01-29 00:35:08', NULL, '2022-01-29 00:35:08', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23186, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 00:37:24', '2022-01-29 00:37:24', 153, 1005000000, '登录失败,账号密码不正确', NULL, '2022-01-29 00:37:24', NULL, '2022-01-29 00:37:24', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23187, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 00:37:51', '2022-01-29 00:37:51', 171, 0, '', NULL, '2022-01-29 00:37:51', NULL, '2022-01-29 00:37:51', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23188, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin1234\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 00:37:59', '2022-01-29 00:37:59', 177, 1005000000, '登录失败,账号密码不正确', NULL, '2022-01-29 00:37:59', NULL, '2022-01-29 00:37:59', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23189, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 11:50:08', '2022-01-29 11:50:08', 297, 0, '', NULL, '2022-01-29 11:50:08', NULL, '2022-01-29 11:50:08', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23190, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/send-sms-code', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691399\\\",\\n \\\"scene\\\": 1\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 11:50:26', '2022-01-29 11:50:26', 131, 0, '', NULL, '2022-01-29 11:50:26', NULL, '2022-01-29 11:50:26', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23191, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/logout', '{\"query\":{},\"body\":\"\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 11:50:45', '2022-01-29 11:50:45', 14, 0, '', NULL, '2022-01-29 11:50:45', NULL, '2022-01-29 11:50:45', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23192, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/logout', '{\"query\":{},\"body\":\"\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 11:53:20', '2022-01-29 11:53:20', 9, 0, '', NULL, '2022-01-29 11:53:20', NULL, '2022-01-29 11:53:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23193, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/logout', '{\"query\":{},\"body\":\"\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:06:11', '2022-01-29 13:06:11', 30, 0, '', NULL, '2022-01-29 13:06:11', NULL, '2022-01-29 13:06:11', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23194, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/logout', '{\"query\":{},\"body\":\"\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:06:19', '2022-01-29 13:06:20', 13, 0, '', NULL, '2022-01-29 13:06:20', NULL, '2022-01-29 13:06:20', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23195, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/mbr/logout', '{\"query\":{},\"body\":\"\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:10:27', '2022-01-29 13:10:27', 21, 0, '', NULL, '2022-01-29 13:10:27', NULL, '2022-01-29 13:10:27', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23196, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/member/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:58:03', '2022-01-29 13:58:04', 443, 0, '', NULL, '2022-01-29 13:58:04', NULL, '2022-01-29 13:58:04', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23197, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/member/send-sms-code', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691399\\\",\\n \\\"scene\\\": 1\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:58:06', '2022-01-29 13:58:07', 105, 0, '', NULL, '2022-01-29 13:58:07', NULL, '2022-01-29 13:58:07', b'0', 1); +INSERT INTO `infra_api_access_log` VALUES (23198, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/member/sms-login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691301\\\",\\n \\\"code\\\": 9999\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 13:58:09', '2022-01-29 13:58:09', 38, 1005001001, '验证码已过期', NULL, '2022-01-29 13:58:09', NULL, '2022-01-29 13:58:09', b'0', 1); COMMIT; -- ---------------------------- --- Table structure for inf_api_error_log +-- Table structure for infra_api_error_log -- ---------------------------- -DROP TABLE IF EXISTS `inf_api_error_log`; -CREATE TABLE `inf_api_error_log` ( +DROP TABLE IF EXISTS `infra_api_error_log`; +CREATE TABLE `infra_api_error_log` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '编号', - `trace_id` varchar(64) NOT NULL COMMENT '链路追踪编号\n *\n * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。', + `trace_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '链路追踪编号\n *\n * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。', `user_id` int NOT NULL DEFAULT '0' COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型', - `application_name` varchar(50) NOT NULL COMMENT '应用名\n *\n * 目前读取 spring.application.name', - `request_method` varchar(16) NOT NULL COMMENT '请求方法名', - `request_url` varchar(255) NOT NULL COMMENT '请求地址', - `request_params` varchar(8000) NOT NULL COMMENT '请求参数', - `user_ip` varchar(50) NOT NULL COMMENT '用户 IP', - `user_agent` varchar(512) NOT NULL COMMENT '浏览器 UA', + `application_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名\n *\n * 目前读取 spring.application.name', + `request_method` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求方法名', + `request_url` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求地址', + `request_params` varchar(8000) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求参数', + `user_ip` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', + `user_agent` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', `exception_time` datetime NOT NULL COMMENT '异常发生时间', - `exception_name` varchar(128) NOT NULL DEFAULT '' COMMENT '异常名\n *\n * {@link Throwable#getClass()} 的类全名', - `exception_message` text NOT NULL COMMENT '异常导致的消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getMessage(Throwable)}', - `exception_root_cause_message` text NOT NULL COMMENT '异常导致的根消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getRootCauseMessage(Throwable)}', - `exception_stack_trace` text NOT NULL COMMENT '异常的栈轨迹\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getServiceException(Exception)}', - `exception_class_name` varchar(512) NOT NULL COMMENT '异常发生的类全名\n *\n * {@link StackTraceElement#getClassName()}', - `exception_file_name` varchar(512) NOT NULL COMMENT '异常发生的类文件\n *\n * {@link StackTraceElement#getFileName()}', - `exception_method_name` varchar(512) NOT NULL COMMENT '异常发生的方法名\n *\n * {@link StackTraceElement#getMethodName()}', + `exception_name` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '异常名\n *\n * {@link Throwable#getClass()} 的类全名', + `exception_message` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getMessage(Throwable)}', + `exception_root_cause_message` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常导致的根消息\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getRootCauseMessage(Throwable)}', + `exception_stack_trace` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常的栈轨迹\n *\n * {@link cn.iocoder.common.framework.util.ExceptionUtil#getServiceException(Exception)}', + `exception_class_name` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类全名\n *\n * {@link StackTraceElement#getClassName()}', + `exception_file_name` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的类文件\n *\n * {@link StackTraceElement#getFileName()}', + `exception_method_name` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异常发生的方法名\n *\n * {@link StackTraceElement#getMethodName()}', `exception_line_number` int NOT NULL COMMENT '异常发生的方法所在行\n *\n * {@link StackTraceElement#getLineNumber()}', `process_status` tinyint NOT NULL COMMENT '处理状态', `process_time` datetime DEFAULT NULL COMMENT '处理时间', `process_user_id` int DEFAULT '0' COMMENT '处理用户编号', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=230 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统异常日志'; +) ENGINE=InnoDB AUTO_INCREMENT=235 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统异常日志'; -- ---------------------------- --- Records of inf_api_error_log +-- Records of infra_api_error_log -- ---------------------------- BEGIN; +INSERT INTO `infra_api_error_log` VALUES (230, '', 1, 2, 'yudao-admin-server', 'POST', '/api/bpm/process-instance/create', '{\"query\":{},\"body\":\"{\\\"processDefinitionId\\\":\\\"self:2:3a5a065e-76b1-11ec-9c66-a2380e71991a\\\",\\\"variables\\\":{\\\"field121\\\":\\\"aaa\\\",\\\"field122\\\":[1]}}\"}', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', '2022-01-23 12:50:46', 'java.lang.RuntimeException', 'RuntimeException: 123', 'RuntimeException: 123', 'java.lang.RuntimeException: 123\n at cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl.BpmProcessInstanceServiceImpl.createProcessInstance0(BpmProcessInstanceServiceImpl.java:134)\n at cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl.BpmProcessInstanceServiceImpl.createProcessInstance(BpmProcessInstanceServiceImpl.java:94)\n at cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl.BpmProcessInstanceServiceImpl$$FastClassBySpringCGLIB$$1ea09b96.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)\n at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)\n at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl.BpmProcessInstanceServiceImpl$$EnhancerBySpringCGLIB$$f97788b6.createProcessInstance()\n at cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.createProcessInstance(BpmProcessInstanceController.java:33)\n at cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController$$FastClassBySpringCGLIB$$ad8c2f14.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:88)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:75)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController$$EnhancerBySpringCGLIB$$7a6fceef.createProcessInstance()\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:73)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter.doFilterInternal(TenantSecurityWebFilter.java:43)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:62)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter.doFilterInternal(ApiAccessLogFilter.java:59)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n at java.lang.Thread.run(Thread.java:748)\n', 'cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl.BpmProcessInstanceServiceImpl', 'BpmProcessInstanceServiceImpl.java', 'createProcessInstance0', 134, 0, NULL, 0, NULL, '2022-01-23 12:50:46', NULL, '2022-01-23 12:50:46', b'0', 1); +INSERT INTO `infra_api_error_log` VALUES (231, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\n \\\"username\\\": \\\"admin\\\",\\n \\\"password\\\": \\\"admin123\\\",\\n \\\"uuid\\\": \\\"3acd87a09a4f48fb9118333780e94883\\\",\\n \\\"code\\\": \\\"1024\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-28 21:03:26', 'java.lang.IllegalArgumentException', 'IllegalArgumentException: retrieveUser returned null - a violation of the interface contract', 'IllegalArgumentException: retrieveUser returned null - a violation of the interface contract', 'java.lang.IllegalArgumentException: retrieveUser returned null - a violation of the interface contract\n at org.springframework.util.Assert.notNull(Assert.java:201)\n at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:143)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)\n at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:518)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl.login0(SysAuthServiceImpl.java:157)\n at cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl.login(SysAuthServiceImpl.java:114)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController.login(SysAuthController.java:59)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController$$FastClassBySpringCGLIB$$9b8cbcb.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:88)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:75)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController$$EnhancerBySpringCGLIB$$ed8ab69e.login()\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:73)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:60)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n at java.lang.Thread.run(Thread.java:748)\n', 'org.springframework.util.Assert', 'Assert.java', 'notNull', 201, 0, NULL, 0, NULL, '2022-01-28 21:03:26', NULL, '2022-01-28 21:03:26', b'0', 1); +INSERT INTO `infra_api_error_log` VALUES (232, '', 0, 0, 'yudao-admin-server', 'POST', '/api/login', '{\"query\":{},\"body\":\"{\\n \\\"username\\\": \\\"admin\\\",\\n \\\"password\\\": \\\"admin123\\\",\\n \\\"uuid\\\": \\\"3acd87a09a4f48fb9118333780e94883\\\",\\n \\\"code\\\": \\\"1024\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-28 21:11:21', 'java.lang.IllegalArgumentException', 'IllegalArgumentException: retrieveUser returned null - a violation of the interface contract', 'IllegalArgumentException: retrieveUser returned null - a violation of the interface contract', 'java.lang.IllegalArgumentException: retrieveUser returned null - a violation of the interface contract\n at org.springframework.util.Assert.notNull(Assert.java:201)\n at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:143)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)\n at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:518)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl.login0(SysAuthServiceImpl.java:158)\n at cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl.login(SysAuthServiceImpl.java:115)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController.login(SysAuthController.java:59)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController$$FastClassBySpringCGLIB$$9b8cbcb.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:88)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:75)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.adminserver.modules.system.controller.auth.SysAuthController$$EnhancerBySpringCGLIB$$11506edf.login()\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:73)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:60)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n at java.lang.Thread.run(Thread.java:748)\n', 'org.springframework.util.Assert', 'Assert.java', 'notNull', 201, 0, NULL, 0, NULL, '2022-01-28 21:11:21', NULL, '2022-01-28 21:11:21', b'0', 1); +INSERT INTO `infra_api_error_log` VALUES (233, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-28 23:46:38', 'java.lang.IllegalArgumentException', 'IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]', 'IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]', 'java.lang.IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]\n at cn.hutool.core.lang.Assert.isInstanceOf(Assert.java:704)\n at cn.hutool.core.lang.Assert.isInstanceOf(Assert.java:682)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.getUserType(MultiUserDetailsAuthenticationProvider.java:69)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.selectService(MultiUserDetailsAuthenticationProvider.java:61)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.retrieveUser(MultiUserDetailsAuthenticationProvider.java:56)\n at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:133)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)\n at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:518)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl.login0(AuthServiceImpl.java:179)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl.login(AuthServiceImpl.java:91)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl$$FastClassBySpringCGLIB$$eedc869c.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl$$EnhancerBySpringCGLIB$$c685808a.login()\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController.login(AppAuthController.java:44)\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController$$FastClassBySpringCGLIB$$107086c2.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:88)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:75)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController$$EnhancerBySpringCGLIB$$485c7e33.login()\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:73)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:60)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter.doFilterInternal(ApiAccessLogFilter.java:63)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n at java.lang.Thread.run(Thread.java:748)\n', 'cn.hutool.core.lang.Assert', 'Assert.java', 'isInstanceOf', 704, 0, NULL, 0, NULL, '2022-01-28 23:46:38', NULL, '2022-01-28 23:46:38', b'0', 1); +INSERT INTO `infra_api_error_log` VALUES (234, '', 0, 0, 'yudao-admin-server', 'POST', '/app-api/login', '{\"query\":{},\"body\":\"{\\n \\\"mobile\\\": \\\"15601691300\\\",\\n \\\"password\\\": \\\"admin123\\\"\\n}\"}', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', '2022-01-29 00:35:08', 'java.lang.IllegalArgumentException', 'IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]', 'IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]', 'java.lang.IllegalArgumentException: Object [UsernamePasswordAuthenticationToken [Principal=15601691300, Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]] is not instanceof [class cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken]\n at cn.hutool.core.lang.Assert.isInstanceOf(Assert.java:704)\n at cn.hutool.core.lang.Assert.isInstanceOf(Assert.java:682)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.getUserType(MultiUserDetailsAuthenticationProvider.java:69)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.selectService(MultiUserDetailsAuthenticationProvider.java:61)\n at cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider.retrieveUser(MultiUserDetailsAuthenticationProvider.java:56)\n at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:133)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)\n at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)\n at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:518)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)\n at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)\n at com.sun.proxy.$Proxy156.authenticate(Unknown Source)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl.login0(AuthServiceImpl.java:179)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl.login(AuthServiceImpl.java:91)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl$$FastClassBySpringCGLIB$$eedc869c.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)\n at cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl$$EnhancerBySpringCGLIB$$6ee399ec.login()\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController.login(AppAuthController.java:46)\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController$$FastClassBySpringCGLIB$$107086c2.invoke()\n at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around0(OperateLogAspect.java:88)\n at cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect.around(OperateLogAspect.java:75)\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)\n at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)\n at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)\n at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)\n at cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController$$EnhancerBySpringCGLIB$$bd77834f.login()\n at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n at java.lang.reflect.Method.invoke(Method.java:498)\n at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)\n at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)\n at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)\n at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)\n at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)\n at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at de.codecentric.boot.admin.server.ui.web.servlet.HomepageForwardingFilter.doFilter(HomepageForwardingFilter.java:73)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:113)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter.doFilterInternal(ActivitiWebFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)\n at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)\n at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)\n at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter.doFilterInternal(JWTAuthenticationTokenFilter.java:60)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)\n at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)\n at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)\n at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)\n at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)\n at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter.doFilterInternal(ApiAccessLogFilter.java:63)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter.doFilterInternal(TenantContextWebFilter.java:32)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter.doFilterInternal(CacheRequestBodyFilter.java:22)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:97)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter.doFilterInternal(TraceFilter.java:30)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)\n at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)\n at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)\n at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)\n at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n at java.lang.Thread.run(Thread.java:748)\n', 'cn.hutool.core.lang.Assert', 'Assert.java', 'isInstanceOf', 704, 0, NULL, 0, NULL, '2022-01-29 00:35:08', NULL, '2022-01-29 00:35:08', b'0', 1); COMMIT; -- ---------------------------- --- Table structure for inf_config +-- Table structure for infra_config -- ---------------------------- -DROP TABLE IF EXISTS `inf_config`; -CREATE TABLE `inf_config` ( +DROP TABLE IF EXISTS `infra_config`; +CREATE TABLE `infra_config` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '参数主键', - `group` varchar(50) NOT NULL COMMENT '参数分组', + `group` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '参数分组', `type` tinyint NOT NULL COMMENT '参数类型', - `name` varchar(100) NOT NULL DEFAULT '' COMMENT '参数名称', - `key` varchar(100) NOT NULL DEFAULT '' COMMENT '参数键名', - `value` varchar(500) NOT NULL DEFAULT '' COMMENT '参数键值', + `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数名称', + `key` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数键名', + `value` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数键值', `sensitive` bit(1) NOT NULL COMMENT '是否敏感', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='参数配置表'; -- ---------------------------- --- Records of inf_config +-- Records of infra_config -- ---------------------------- BEGIN; -INSERT INTO `inf_config` VALUES (1, 'ui', 1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', b'0', '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 'admin', '2021-01-05 17:03:48', '1', '2021-12-16 07:42:36', b'0'); -INSERT INTO `inf_config` VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '', '2021-04-13 03:48:02', b'0'); -INSERT INTO `inf_config` VALUES (3, 'ui', 1, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', b'0', '深色主题theme-dark,浅色主题theme-light', 'admin', '2021-01-05 17:03:48', '', '2021-01-19 03:05:21', b'0'); -INSERT INTO `inf_config` VALUES (4, '1', 2, 'xxx', 'demo.test', '10', b'0', '5', '', '2021-01-19 03:10:26', '', '2021-01-20 09:25:55', b'0'); -INSERT INTO `inf_config` VALUES (5, 'xxx', 2, 'xxx', 'xxx', 'xxx', b'1', 'xxx', '', '2021-02-09 20:06:47', '', '2021-02-09 20:06:47', b'0'); +INSERT INTO `infra_config` VALUES (1, 'ui', 1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', b'0', '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow', 'admin', '2021-01-05 17:03:48', '1', '2021-12-16 07:42:36', b'0'); +INSERT INTO `infra_config` VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '', '2021-04-13 03:48:02', b'0'); +INSERT INTO `infra_config` VALUES (3, 'ui', 1, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', b'0', '深色主题theme-dark,浅色主题theme-light', 'admin', '2021-01-05 17:03:48', '', '2021-01-19 03:05:21', b'0'); +INSERT INTO `infra_config` VALUES (4, '1', 2, 'xxx', 'demo.test', '10', b'0', '5', '', '2021-01-19 03:10:26', '', '2021-01-20 09:25:55', b'0'); +INSERT INTO `infra_config` VALUES (5, 'xxx', 2, 'xxx', 'xxx', 'xxx', b'1', 'xxx', '', '2021-02-09 20:06:47', '', '2021-02-09 20:06:47', b'0'); COMMIT; -- ---------------------------- --- Table structure for inf_file +-- Table structure for infra_file -- ---------------------------- -DROP TABLE IF EXISTS `inf_file`; -CREATE TABLE `inf_file` ( - `id` varchar(188) NOT NULL COMMENT '文件路径', - `type` varchar(63) DEFAULT NULL COMMENT '文件类型', +DROP TABLE IF EXISTS `infra_file`; +CREATE TABLE `infra_file` ( + `id` varchar(188) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件路径', + `type` varchar(63) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '文件类型', `content` mediumblob NOT NULL COMMENT '文件内容', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', @@ -822,57 +1245,57 @@ CREATE TABLE `inf_file` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文件表'; -- ---------------------------- --- Records of inf_file +-- Records of infra_file -- ---------------------------- BEGIN; -INSERT INTO `inf_file` VALUES ('1c164a1d-5f2d-460b-a0bf-dfc33deeaab1', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010402030101000000000000000000000405060702030108090A0BFFC400511000010302040305040804040404040309010203110421000506311241510713226171088191A1091432B1C1D1E1F015234252162462F1335392D20A4372A2253482E218356317192655648393A3B2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004A1100010204040306050303030302030607010211000321310405415112617106138191A1F00722B1C1D11432E10842F115235233629272A20924E21617344382C2D225354463B2F2FFDA000C03010002110311003F00FCFF00F041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C10418208FD87B813D3E67F3C7788F3FC6E69363C22D6FDDF0411BB815D3E63F3C104286410153D460823760820C10418208E4027618208E7815D3E63F3C1041C0AE9F31F9E0820E0574F98FCF04119A10A936E5D479608525EBE1F78DBC0AE9F31F9E08520E0574F98FCF0410702BA7CC7E78208DADA0999B6DE7F8E08236F77E7F2FD70410777E7F2FD70410777E7F2FD704118A93C317999C10CF13AFBFF008C638219C72013B608232E03D47CFF002C1046694F0CCF38FDFCF094D4158006875877214CC4D4FD59E32C6132985EBAD1DBC7E9189A1DBE576B559DD9FA7DE0C2D0D1724AAA4545ABF8AC18553348A7AD1FC695F7ADF44E1946C9F53F76F5BC6C473F76174E33BB4F03024EB57AF9368DA3830E51803308511C2536ABBB6EC6FE9D1A366135E0FBF1DE92CDF335347DDEE075873FAB3873DD005AC29CB7F4D6B780E5F4D5A851A8FB2D5C6FCFDE363F973C309B988C092848E23661A353F0E1FEF1B1CBBF5AEA52806AD7954F9B1B391E70DFF567A9D7C397282190654A510010227ED1F523D3E3A0CBA7F68FE44CB50E2F95D8D8BEBB6EFE908AB3AC2766471AE623E4A8721E9CB4B73D7AC467586B5D2BA4A851555F54D2B3108594242AE1691B7849036DA2498EB6BC763FE0E62FBF335285B02145D07567AB3373E839C707F8B3F13F099FCB1290B41E0052E143F8D47E2EF1E7E769BDBC67DABAADECBA8415508529008E12384980678418B58EC46F7DFD51D8BEC1E2B2C54A331040053420A6D4D5DB4616EB78F1AF6AB1E8C5266709A17DA8E49ADFDF98A15D4F1A96E288FAC39726D6264FDE7974E5B63D138341C3C89686F942403B1259FA01BF3146BF11C561D4AC41535D46ACE2E3416D980B78C33F7B56CB87BCF13677208B0B58013EFE77E5BE1D4FC4E164A0103E602A5EA0F46E9EB5B45932826536F4DD9C352D4F3D2FB3D52AD755FC9CB69D6AA85405AE080831637111067A72BE2B38BCC82D570DD5DBF34FB545E26B329A26A101DC0DBCB6D7DF296D2692FAB2135D9FD5200FB41B252088822E08322C6FCFA5F112BC5898E259248B9B01B6DC8F3B5AF09DD10CA04B0BDBDDFCB5768E2B75F6579237F56CBC0EEC82952B8ACBE1B022790F58E57DB0B48C089EB97C60A9BF6D051CF2BDFD0738CF0B7ED2DBEBF58A8B526BFF00AE05C41924CCDE6E6F620C5C7A82011CBA064F952259494A49B3DC57AFD1875DE32C5EF4D9B4FE7E914E669A892E9971405D51B73DE4FF00B8169E78BD48CAC2C070C031353E0C4FBBD214960D6BEFA7D2AFD5CC57B9BE76C282A48264F31F388F2C5830A8561C0094150029CEB5B3D2FEE90B02458C5659CE748414107884AB8960CF0743CC103623167CBE79596EE94016DFA3DBC474D602A56FABFBB539443ABB50B652A4B55A16A0090D94F09932624F43E9E98B127284E3903893DDCB7625C9A1A3B5F7FB466F57751D1B9EF688457E7D9A212B536D0A74916295A5C2F728099244741BF4387185ECAE5929655FAC4F10A974B355CDDB63E2E7687F845F7038881A74156ADBD80C46AD1966479EEB3AE4D1D165F58FBCEAB852A34AFA112AB495A91C113E7F3C67138DCAB26429B1929D22A0A92096E4FAB69CD8690FD58B29038998F420ED607C5F4D23B15A53D8935667C935FA8EB5191D227816D347B97D758857DB061C0A68A45A08BCD8CC6397E79F18303226AB0982FF00E6785D2B354849D2A4172F5A13B46E9C6CB482490966E120BB1B9B1EB77F28EC2699F669EC9F45774E57D00ACCC1AB9A90F3A8950DD5C21445FEE0440C72CCEFE2063F16B2A9092949774049513D0B75BF4143185E669593C441239EA1F73A0A103520EF16DB35D9169D60B392A825A5A424B72A3C2102D75493EF323D310723033BB529EF714852384BB11551275D400DA3B93D22B79BC93982870034D75F00FD4921BF2C198EB9692092B4DE67C43A5C6D6B5B162C2F651583471CA4958005003E16BD3F310F2B2598925C103426F5F2B5B5BED15FE6DDA286F83B92823C5C478922236DCFC45EF893C360F1085702B09316C59FE617A060C77E40F51599C365533880AB01424569E5D6C4E8763F43BDDF9FCBF5C7C6A8FB131B1B6F7BF4E5EBE78208D9DD93B19F77EB8208CC20A6666FD44608239C1041820830410A1948215239E082377027A7CCFE782083813D3E67F3C1041C00EC27E38208D884004CA62DE7E5CFF0C10A4BD7C3EF1B3813D3E67F3C10A41C09E9F33F9E0820E04F4F99FCF0411B5B481303A608236E0820C10418208D0FEC98DA4CFEFD7E6704369C2A7937D0084D82108DEC6EAF4C10429C1046B7397BFF007FBEB85E454A81B375D768D54A2080CEFEDBE91AF1B2C0248D296E821DCA415F086277E956F0E9061B2BE57D5B6F7E71209C10500785CF3A0F37F1A6FAC7307A1F81C3757CA1EE7503D2B6E7CA36FD3357840DEBA79FE233458906C4EC0D89DF61CF1B494158E32A219CF0B78EFF0096D371A99A9927846B43A93CB95EBEAD1B0DAE6C3CEDF7E135E3E725624CB4A94FF28A3EDCB9F3DA31330B24CA33662920B7155B7D4927E9CB584B599BD1E4CC2EAAB9C42184A655C6A090A001DA489F389DBD316AC87B198ACF6721465AFE6503504B545C0B373357E4D1CCFB55DBEC2767E4CD4A26A78D20FF00700C40237D3EA6E0D23AA9DA97B41D332DBD41A6DC42570A471A162EA883736EBCFDF8F507633E14272F952E66270E1870A99419EAFAD5DC0D2F78F2376E3E2FCCCC8CD932672812541252A3F2935B0BEFA0E978E906A3D759BE6D50BFE3B50F2FBF512C00A5917BAAE9240B0E6664917DF1E89C8F23C248C3818591292500098FC2CA61435D983B0A9BED1E7CC7F6971666A973E72D426124024D35B39BBBD3C621A3307585FF002524A567ED106D3E666F7B01F118B1AE461928799C0929B0000E7561E7A97DAB0C5199FEACB1750258B9F017E6684EBCA14AA96B1F5B45995B951FDBE2E020C0E289E1BF5237EA31058BCD254B79682DC2E2EEEDD2B5D4EFE0DAAF0495BA8861A335EA46F41A915AE8226D94E87AE6529ABCCD680C7DA2952900F08BFD9E2927CCFEB8AD4FC7AB1130CBF9893D75ADFDB1A690DB80E1EA0B373BD036B4035BD3C21C333D4F91E46D0672361B554905350E18F09488175023D23F2930B96E2312B515F114D38433B5DDB5E437F28CCBC419CE92F6605DDC543DAFEDDA29BD41AE1350B50CCAA949249E16D1C5C23A094102DCF7F28C5830B904E5280E025C8AB352FCDFC7CEA215E015F6C3DEBE91546799EADC2D990191C45B5055C8E7304116DAF8BBE53D9A595259160E5C10CFEBE9E2D521962CF5DC5BDFD3C04573996A24B4140AED3D63EF31D07E62D8E9596E401013F2ECC1897A56BE356BFA1D420EA5BDF5F7F4AEF3AD4C1DE0E05C70F14DEDBF95BE1E78B561B23E2203300D417AB7974ABD342F0A2106AD5F2F7B8BC5719A67CE9E2217293B4131CF97E38B0E1F26C34A40330A53C357207DCEDE20C6C4117D62249CE6BAAD6696929AA2B5D7D5C284B2D2DD0924C429494A8226D1C513CAD384B1D8DCAB2F149D2828034701D86B5F76BC64214A4A940512CE5F7B7BE9168692F674ED1B5938DD5D4E5AACBB2E708597D6EB654942B9941215B6FCE76C737CE7E25CBCB5E5E194E5CB70D8B01A5B52CDE71AB6BB74BF4BEFEDE3B33A5FD98B4069B525ED515BFC7AB7C0A61A525D61348A4C158F0A8A1C0B3D640E9D39DE3FE2666999CD2995355864A5DC825D6F4AD886FB36D19FF74A552D2EA0BB8D49EB4AEBA336BADF946F643A6A8D34993D150D22109E14A8D3B0A58E1020F196F8A6013BDF7E78A86638BC7E6734CD54E9F3261FEE0A98906C2C0B1D80A51AE6012E7B01F3569BB72BD76AF4110FCDF581A4595F12AA03F370EF7496639A532019E805ADD4E12C0E439962A60E34288243B80E4022E59EC7DDA35EE26B5016AB0DF7E5EEB158675AE6951C6B7B312DEE4B6A4A9503A711BDFF00327963A7E4DD90594A0CCC389967240A1D74AD58C024CCAB8507D2B5E75F75EA22A8CF3B4FA36520533E85405719EF00EBB898103974B7AF47CAFB21C20BCB4CB048E1000DE9B5D80B1F4895C0C86204CBBD5F9BB0A8A50783F952FA8BB5C5242F81EE217809503693D2763EF1B5B95D309D9BC0E1C0FD44C9680003F3149D8D8989944992194DC99AF5D79BDF9161B0A9332ED3B38CC1C4B7468AC599321961D7449DB88A52A03CA6FE7189299FFD9DCBC12B992262AFFDA1DBA56A75F5893952E4FEEE14B269A0BF2A75D8C7D9F702BA7CC7E78FCE947D488CD00899E7820856D7F4FBFF001C1046C7397BFF000C1046BC10472013B0C10473C0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208CD00899C1042D47DA1EFF00B8E082327397BFF0C10A4BD7C3EF1AF04291B1BE7EEFC70411B304118A93C51788C10463DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1046C4366F0472DEDD7D7046AA4F13559A33E03D47CFF2C11AF77CFD3F98E0A4A6262F820EEF9FA7F318E083BBE7E9FCC6494F14DE2309AE7095AD4DC0F4D21ACC404AB702C767F7AFD9E32EEFCFE5F1E78C27121542AB50F46E9E17AD59E25B0880407143F624F87500F231AD41485A63633263D63979F581BDF0A0636ABFE7F36F48972BEED2598003A7ADE9785E97611E000AA2C009933E847E5EA6CA0C3950709AF536F63DB457B1D980960B1B3EBBF386F5A1F2E7795280D2904965C2425206EB27607C89983B637460B12B9A897250541440A026B4B5FCCE962D103333EC1C94AE64F9A947007F995AEFE837E758ACFB40ED7B49691A171BCCEA9BA8AF4A141A085414AD22D3DD9BEC3A73DAF8ECBD90F86188CD97266AE5514439526D57B37516FE787F6DFE2F4ACB53364C99C0B710042BCA8EFE1D0DA3A0BAE3B6DD45ABAB3EACEBAE3792A4B818E05F0C2153CD30A3CAEA9F863D51D9AEC160B2097C62524CC64F1929D980615D49D2BE71E43ED576FB17DA099302672D94A2ECA25DDF9DEF67D0E800A32B5C72AAB0A299C5960A8A9C5A964913E2B9513CE79F2F71E852E6CA54B1282412DC219852C2D7A6F60E3568E61370B880B3396A528383577AF89E7C8E9631ADEAC697C34AC8EF9C62CB4F0F1294544110482607979F3C44E331ABCA5887F9AE1D83D7F353E71159809B882020171471F6E648FE1A90F794E98CD7365871491474A2EB2E04DD063FBA08B4D801E5D442CFCF7138C3F2950068384925CEED785B01297214935040AB8B9D6F5D2BCF689839FC0F48B45197AD0F5554A4FD6D44F180A6C0E1E10A2A09BCDD3E569384F0F87C4E26612B4A88A312E5FD0BF8FF009B14BC406093C9CB83D2BD7A00FE759EA5D6AEB895A50E2D2992084A8C46DB0F4E9EEE58B9E5D9271315203D2AD5FE437D5C447E2809BC4003A7B715A5EBE42F151D76A72E71F78A22E4824C13D46F3E71B62FF95648944B0A080E68430E6DCCFADDB946B8190CA20861A1AD7C3EFD4968AF739D40D10A2B50B4F43BDA79F5F527618B8607260E9FF6C1377200BF20DB7F889054A0EA6340CDEF5D76F48ACB3ACF95C214D3A4F0C9E0130A9DAFB88FBF6C5AF078144A07BC481D40A6CDE9FCD635EEF9F5F7D22AFCC750D45495A16CFD58DE17DE7113CAC89E76DA7D4C624E4E270F852429495736614E47CF7D768C940A72F50F5AF9FF0010DF94E5B9FEA5A85D0657435598D4A9494B290D3ADA254620BBC3C2396E4623F31EDC65D93389810A55C7CC01A07D3ABB3788A4615F29A51DDC69E1E71D89D1BEC9FA82B8B199EBDCF13A5E8950BFA806915E5D418F09534AE24CED3CA76C732CF7E2B4EC68523289267AD2E95242FBB67E65810078F2302502BC5F28350757A93E7B1FB476974DF673A0BB3EA7713A6B25A6E3AA091579A3C43EAAE5343C2A4B2F051A7E13C93C24C99C73AC463738CD27CC9B889D312EDC3872A5349767F9C11C4F7A337AC60D0326BC5767AB1D9E9515A316F25D5DA83EAC9296F81A481012D8091FF4881B4DA3D061C48C9674FF009A6ACAAF42E6B5D5C9B5691A457D9CEADA068076B1CE052788A1C924A6638A403723A6E3EE7533B2B389419128A8387603FCF9D0E97896CB90851F98F2B0D3EB5DAA75BC5459FF0069542942D34E7EBCB4880B528D3F099B58C4FCE0FCAF5D9EEC84C982599C8E12083548275F3A00C452912E2549092431B0E74DDDEC35B750D14966FDA5D6BAB5F7CA53886C92D36DAA4B53361C175CEC378F22631D7705D95C24940527BB42884F12C81F330E76620B9153EB194CA9003900DEBBD1CD6ED53B3B18AF2A738D47AB5E34795B55656E12800D33C94C9B7FC45242779B93077E589350CAB2F9759D282807532D0F4D83DED6DF9C60C99360D7200602E4120BD9A950D123C9FD9B35B66E876AF50E6E720A65F0AD912DD49A94AAEA94A17C4D948EA39FC6859BF6DE5CB5AA5E58B338CB2CBE1052CF600B17F0AE81AD08CFE0C30534BE252838214CDD40FC01436689851760DD9DE429073DCCD39B3C800AC28AD90A2093221640B08F39BDB1589B9B67999A80968C4278AAE0A983F26B7DBC223CE2A7AA8A24241B52A0D59FEBE1A38896D1661A0345B6B190645423BD003CE3AE36F13C164901E4A888E7004DE7961493D96CEF1E52A9B889E90AB92165B4AFF86E4E408C9C54D724120D2C6FE1FCEF4DFEA0B813D3E67F3C7C448FAE1182C01103AFE18208DAD7F4FBFF001C1046C7397BFF000C1046BC10428640215239E082377027A7CCFE782083813D3E67F3C1041C09E9F33F9E082315262201E73B9E98208DC8FB43DFF71C10464E72F7FE1821497AF87DE35E08523637CFDDF8E08236608236B6099813B7E38208DBC0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208D8DA0C99B5BC8FE3851129730128492DB03F88D4A929604B3C6EEEFCFE5FAE345A552DF8C14B5DC41C69DFC9CC25A84414C49B1E584BBD976E34BECF1B42683D0FC0E144FCEDC3F33D9A08554E82AE29062D68F774F31EBB74223333973D2C532D5CA86EDEBC879C68B0E40F60381E3F6850503991EFF00F7BF2E9D79623E4CD5A3F7862DF6D6EFAFD62530A81F2922ADA1DDCE87DDB48E52D852D28304AE403C86D79B6D7FCB161C02D33F85D8BB3695ABEBE239F284F30C64B9328954C4861A9D9E8CFA74DF94346A0AFA5D334CBADA8A86509402AE15BCDA4D8490125533F38B5B173C164F8AC424193214BD5922AE76A55EC06DE11C833FED56030CA5F162D0821E8A50B8EA59AECE63A7DDAA7B49A94CA32BCA4A53671B79D6D4991FDA640133E47CFCB1DFFE1A7C3A39924E231D87E0EED890A4DDFA8ADBC9AFA793FE2AFC5299972C4ACBA7F7DC45415DDAF98A509A57968DCBA35A8B3BABCEEB5CACABAB72A8B8A2AE052D5099E504991E57E533338EFF0085CBE4F673865CA94084B00C1B7B9FCB6E1A91C067E718CED0054CC44C5A42854124924EDB30ADC784343D5A5B6437629779003C3C3BDC093BFEF9CBC9C7FEB4F0A93C06C4BF938A0B50EA79561A0C18C19EF0AF8F5F5DB7F0B7431BB2E4399B1197E5ADBA9754614E702F8403170A2909023CFD30E4C993844F7EB9A193F31147DC51DCD7D0E85842C31699E44BE10D40FE62A49A0DEDE57B0E934E64BA5984D4E62B43998B838D282AE2248BC5A529B5A481327AE2BF982E6672BE1C3C95144B35531170C0B1E96D7A42F2B2EC3A4778B5A49502458B36F5EB7FA9AC3B52768350EB6AA44C5234994A3BB29320587D88378EBE7732712195F67A6383310470B1729DCFD69F5EB0C7152E4CBE208502DA8F1D411BFDC08A6B36D4F5544438FB8A750F71142F8A763264090396F13B73C745CB324C31212402B4B3B80F514A11B8DF588552D6E785CBEDD357BF4D6A6915F663AC12EF1092679C9F988B753691E918B2272A5CB712A5B8A51987D4FAC48E152B985969246BD01A7566AF9440338D4895C70AC08E2913173F03CCED2475C59F27C2290969D2CA53A72BBF27F06A5A251587080080D6E54B5BA69BB12358AD735CFD6A514A572A13B193F0DC9BEE2E4CF2C584CE918541AA52DA9A9D3D2FD5BC635280D40C7993E30DF9465DAC351542A9F22CA6A2A9C5A9295BEA429286428D882B4049045EC63E2315ECC33F91282809E974BEA97D4DABA680758D084E8AB339DC9D3A5347BF28ECD683F65862AFBACEFB42CDC30530E0A20DF15EC4A4A9A544C45C8B1BF2C72CCEFB6B880A29C0A3F505D414CAE1E1AD0824D79B7F319FF6FF00B884DD892F6D4B6FE3CA3B2D97A748E8DA6396699CA695A0A486DCAA5212A5BBC0212415A0A916BDBE3CB154387C7E7E1588C56257420A52C7E4D48A5FD9B184D402E882585E80BEDD05B6E7AC36D7E7294A56BA806F24153A4848BFF4931EE03D7AE24F07947E9871A0998A0C48E121D9AA6E796E1ACE29A2A5AD3423F1AD36DCD7EF15E57EA96E902FFCC15A144C24130D81E7263E3CB98179895350A5241C39045096626C0559A8DF4D69191C61C90EF67A5BD9D2FE71516A3ED0D0C970072499E704C728EBCADBC8907170CB24C89A9038784B8D59AAD5F3EA06D4318214A366F114F7E315557EA3CE73E525ACB32FAAADAA04F70C06DC4B6E1302EE9414245C1249B832671699589C065724F7A25ACAAA1D497A6C2F60458D61591395248649A967AEFB1A59FEF1BF2FEC875667EE7D735BAD3A532F242843ADD515A39C869414391B89BDFCD15F6F24C99331380C195CC450000A5EAD761CDFCE1CCCC54C0A294925243B87E47E94E74BC4E99D15D94E97434B08467EF23ED54ADD718EED49DFF96A242A6368F80C404EED57687325A532C4DC1A4B8E04A78DC1D8B53AD2E23518D50354F15033ED7F1DEB47109732ED674CE4CC9A4CADBA3A100708E1A7694A03942CA267DF208DE775A56498FCCD5DE4D9D384C2039254012756240E54E8F185636610DC2A67E9A860ECFEF9C53D9FF6C152D9E2A3CD9FFE7717136D32B7A609800241088BDA00DAD8B764DD98C065EF33319885BD7E7604355DC972FF0047E6CFB0AB188A4C3C2D4F9B5AF33EC88AFDACDF5CEB3ABFABE51936659938B5405A9A7E992A2A3FDCB404C5F798138B0CCCFF00B3D948225A641290593C4870DD1CE9A3DC0D61E1C3C915E201BC6E2EFA0E55040701E27B45ECDDDB3E7C84395D90AB2AA65805152ACCD9594A5512A2D1701300EC47E00D6F17F19329C29549C3E152560904014D6AECCDE7472212386921CF186D6D576BD5CEE2DA120C7D69E3E0F47D6C80807700FAE0820C10460B49511161CCFE9EE8C1046D423E1F7FEFF41E4410A020FF00E91E9F8608232EEFCFE5FAE08237349E124CCED8D16680737F2FF3030370F1BB0946186C3C840403B807D719722C488180B0020C62061B0F28C929E29BC4608CC65DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1042AA64F09573C1042AC104182304034306081850B5ADEFDB4189CCAB32C3E102C4E0090000E1FC8B7D9B9C6ABC14CC5074288E1B73D3EC7C6FCCC218F9F2F18E25D097B36B61B59F5E95B335C89987352FC2EE0DDAA0F27B6F4F28E201DC03EEC5715964FE22A0A535C162037E0FD358C271A38B8483521EAEFE0C2DF6D9A081D07C06257053460C8EF403C2A04BD2BA8AFDEFEB137879667B0142C2C3A8B5396DADB44EFBD50C42984CA3FF32C3DDC89B1BDBD0DB12788CD70F8C09969949530201A6F714F0BEBB46D8CC30C2A4AD6A6D6BAF83F3AFB7E02D971B554D43818424712CA884EDB8F1116B1BFAF2C2723B353735534A96A1C4400C1E87A0ABEBB522A599F6B30B964A513312E906EA03C6FE26FA333C541DA0F6D7A674BD306289E6DECC21C4852553C2A168316E9626FD48231D2FB31F09B3099325CD54B99C2483549EA2FE3F5611C1FB61F14E4290B44A9E051428B048F5F31E0F531E78F68FDAB679ACEB5E1555CEA69829412843A4002F000491E86DF3C7A7FB21D809597A658C4C80B147E2480777A820E94FE44791FB63DA2CCB369B37F4F8B98905DB8546E6A2C5BFC6E0353ED39F5BEF50E71252DC0EF56A51E2264CDC99F75F1D824A30B95202644B4CB7150960ED7B0D3CF9C735C160B1656A56653173C9248E304D39151D5C3728D0D507D62A52CD3B6BA92A500549E2013B740A1B99E7CFAE23F1D8F95381709D6A6A75A134AD1AF577D8C4BA42650F91013C3FDB667D1FF001A88B432BD0D49414EACC3397D219090B0C2889E662C67CCD8F96F8AE9C61133BB9293C4AA822C9BD7C5DE9D21B6214A52439A0D1C543F3F4FE6AC79CEB3628D2BA4D28869829052A584A7888F252D3C5C8DEF688C4AE1302AC510AC5A9534E8092914E42F4A795223A62969712FE471A6A75D68DECC55199EA1A9796A5D538B150A278C95920ABFD227840B1FB3BF9E2F794E12522584942526C01001A35CEB4A353684D336711C2165B9DA8F4A07D5EF468AFB36CE5B85294E78AFCCC73EA6D6DCF962DD84C12569E14A472200A5431D3CFC7946122613572FA93720DEFA3914E422B1CEF3F70777DDD484B7E20E34471F780EC02BFA63A889D8733896C3E4F3259E304EE4B353C1CEBCE8FA448C8420BF100C3EC06FF715D62B1CD756B6959629E9781D5482B0E05993009E1F9E2C3231185C394F7E525290DC2435854BDB6F06A8B44B495CB9690C90EEEFA6BC8F2F58D794E88D73AE1E0C64740FBA0901EA93FCB45325C363E20028104CC6F1104E18675DB3C0602504E1D32C5083F30736F122D63CB91DE74F49D406B6B4F2DFD3A34766344FB30E4FA74379BEBFCED35B54385C145DD9042B7E096D445AD7237B75C726CDFB7B89C428A70B2C94A9C779C4C13CC03CFA7943454C4B925437602FE1717BEADCC98BF69DEA1A1A3728B4BE594F454CD25282F169A2B7922C93C4B4858889306E0ED338A82B133F19342E74F54C5BBA6A5210ECEE01634D08A784325CC592529A03D2B7F2D7EDCD9BF88D6D1F7AE57B854923ECF140883CA63FF6FC394E60F2B13C0E22492000C08776D75A7F8864B953947F716B9DDD8B337ABC40F35D4F4AA538A6DA085A64874AF842226E12A0019F5F518B5E132B97804242A604A1603A08A9AD43E9734F2890CBD1C0FC4E4D402742F5DF76F74A8339D7CC07974AE55BB5EE9202596DB5C09361C4806D31CEF1BE2CB839397280485A11C41CBA85FA13E5B3BECF28426EA0EDCDBD61137936AFD4AA6DBCBDB5E5197BD77EADCE17613C8842E15617107CB6C2B8B19561105969993B4484D49D03D58D817D34A46532788B80C3572C3D6BEBA7521DA97B3AD1F912BBED539BA351D427C61B334812B17E1250A20DEC6D163EB8ADCEC563D5296AC3619724A8FF00B6A0EA7008AF0B6BEBBC6552D095014551EFF7F5D59E8766FCE3B60A3D2FFE4720A0A4CB29D00A1A6B818A85D504F475482B411D4193898ECEF67CE7EBEF33698A42E5D415CC32C3171FB78922C36D9EA63454C42414801376D58F53CCF872678A633BED3B51EAAA834D4B479834F38A29406987DD696546DE24365B4836332201F762D98BCAF26C9C30C44998A483AA43EE1DEBB35FA930DCCC4A9D400246BB8B73B7873BC3B651D8F76C1A8D21CA8C8D54744F416EB975CD71F02B752A9F8829300FD95004F316B56E776E72FC14E54A46150B5208621373D598BB7A8DA324CB090428125C10D6F4B45A593FB2665A809ACD59AB0D42800A732F148B49EA51DF2147E37E4646D86B33E2662F8BBBC2E583855699C403529429B83A75148C254805D469A5363416B1D06FE962651D96F64BA5160D268D6EB2AA53354ED738A0B52765774E7104ED31104F2DB15BCCB36ED0668A4CC9B982D085391282384240AB3A59F6DEDE08E2B1219A586291A7D37A6F5F48B21AD48E65F4FF0057CBF2ACBF2BA303847053D22D684C58F106F8C9F7C8F9E20D7964CC44DEF67CD9AB59673C6A00B07FDBC5F4E9710C3F578866EF0B1DEBF588F3B9BAEBD6E29AAF5BCB0417525469D289D8004A527A1816F7E2464E5F2C30984166009009EA4FE5F78D3F513BFE6AF323E847E23DECC7C878FB35060820C104668483337DA3DF82085A845801CB73CBF7C86082378481B608239C104184E669E3F6820C27041820830410A69D20F1126361820855C23FBC7CBF3C10473C00ECA9F77EB82083BBF3F97EB8208C8009993BFBBAF9E0823991D47C46082091D47C46082091D47C46082091D47C4621F3113411DD922EED57D4F93B1D59E257018A972814AD9C8A39A16E5E2FB738CA0F43F0C38CBB106510269AD1C973776A73FC6B1A62A4271615DD01E06FE3CBDE91C7BBDFD316B463642D2CC38D8598EDA7DBFCC404DCA57294555046B5372FBF5B0E8638E24FF70F88C4762B013B141465A4925D9ABE81B4E9CA91B0CE64659F2CC58043072469BDDEDF7860CF3525269EA735D52F30186D2A53895BADA490279150240E606DCE3161EC8762B1D986251C52E61054E070A886B9FED6E9BD6AF143EDAFC44C24890C99C80A092C428072CE351D2BA79C7457B62F68A73375BF95E9474B4471216A6CDBA13361E97F4C7ABFB11F0F4618CA3889628C4BA7EFE75B08F2176EBE22CD9C26093394CCA145EEED626FBEBAD1E3A69996779ED6BEAFAC3EED43EF9256788A8B7B9BDCC4836F98C7A432BCAB2EC248484CB40EEC072120396AE9A757D3568F32667DA6C762B107FDC591C45AA58392E0BEACDD3D21BDA7F2FA154E64EA9550B8E1404A892A2622124F5DA06E3918C298DC44B961E5A512D20162C34B52F5229C9DF789EC8B13DF9499EA249209E2BF874ADABA6C048B2DD2F9FEA073EB4D27EAB9332429D5B812DF78DAAE3842A167C3BC4C03E726978FCC53326A65713A96EC12EAAA7FE4D673BB06B4587384C94CB49941367A36DECF5058D584E4E69A774A52F7394B68AAAD4A48754A9B2E3C5754F3FED36E62C30D6565F89C428F1A1610A6F95DDC3BBD2941E9D62AEB584D8F12AA09EBE60536FBC5699F6B673325254E3CA6FBAE2E2A70484906C048201B7FB5F169C0F67E61E17430A3121CDDB930AEA5C4205D4E4D46BC87BFCC54B9BE785D5A8B07EAEA932A9DFCC93113D245A7173C0F67C84A68C056C1D8F205B91F1A3C375CB7341A50FD8F5FBF5884E699FD5AD0DA1C8847142D2A04AA44CF86E23CF9F5C4A4DCA972787802985E9D35FF00378564C906F53A8A55AA3969BEFAD4D659C678E1529216A2ABF824924DF95C99F4F332379DCBA6A70AC66D367274B97366AF9738597213AB31140DB7F25FF10D195E9FD4BABDF5D365740FBAB94A0BAA4A9086B8F9A4A841041E46DE5CA4719DA5C1E1E51056805B7AF956A29467A79EAC6C68123414E5B54DBC394762344FB346459625BCDF5D66A0D4D9C6E93BA2AF172492DA88DE05E773D231CA33DED5E23133169C04854E9609E29817C3C2E59D8D09D4FD890C999852FC4A22EC2A6DF96FA0D62F7A3CCDBD2ED2F2DC9B2F62832F74043354036B5D4A50224829E3470EC66F27E15F91819B9B28CEC4297C52AA904A83137700D40E6E28C1A1133D75483C40B798DBCFEAD0C55F56D289A9A86D554E93214A754900998F0CC45EDC8C46155640FF003214E454802C006BD3ED194951503A9B87DBA52C1E83A8311C5EA4038C38FF007684CF7680809088E448DFCC9E7F0C208CB664999549D1F7A727F7D21E4A4BA8248626C5BCDBD9FCD51A8F54E7755589A5CB10E3E952A09424A80E57201DBA74F2C59F018D561E850CCC03FAD4DDFAB3D2241186E3B5199EFF009630A5DD179B6694F49519C560A1A532A711092A701024182088DB6C6732C562B31E197870A2514570DAAC45474EB5368274AEE1228C2C74D9B5356731B54AECFF0046B25CA6A0A7CCAB523894F2AA01525606E1B5151372791B817DC8C60B2AC62B87BD9CB96C352479D5F416DF9C240BFA1FC7F9EB102CFBB58CD7345A32AD314350F553C4A1BA56A95C4366E213DFF77C207424C74C58F0F829186509B3B16898A4B9659156DAA4D033DFC2360A2011E5CAAFEB1865BD8BF6A5AD9095EA0617A5D959E21506A5BA92A49933C09585260728BF2DCE1EA7B6B96E01250252710B45199813B71330E77E718D9CD0D5EFE3EEBCA27D967601D9E64C108D639B1D4158C90695052ED3C2EC5CBA150676932003D23142ED776CF34CD8A1394E19783624284924B8A307481CCD183F388FC6CC52280EC47E3C770FE348B8B2BA8D3DA5E9114BA7A86872EA74240495D3B358E2D226DC6E214B13EB23AD862B3864E6D8F081994C9F420875AC1AB12E1D8EF0C0629490C1C13D48600D395EFE50D953AA1AA8716AA665D65D905D79BE3E07093E129680E04C5AC1201993CA2E385461658509D350B0C004A800400198A8B957992D7D635FD612096AEAE5FD1B5ADBC5F44C9ACCEF30584B4A79D4AA3C3DCA933B40E22981EFDFE58D978FCB70C4944B4A9B6200240F07AF2FA467F52B7DFADB56E5D474D6B0A7FC2B9FD514ACE524857DA75750968A3A10851133CEDEFDCE23E767F2E6B2508091A1150DE1D18EEDABC67BC330D284D087BDBD34BF2EAE6D7672E389E3ACCDD3978DD48E10F01CB70A8F94EF86ABCDE6A52552D0A98480750F566D9C0DBC63520BDED42297F7EF7D4F68BD23430735CF3F882893DDA50CAE9F808FB576D438F8AD726D1206114E79892549549286622AFE83C7762488D8D855C540B0FBBFE0347B95C0AE9F31F9E3E55C7D9E8DADA0999B7CFF007FA608236F77E7F2FD70411B5A401337DB718208DF8208304106082324A78A6F1184E669E3F68232EEFCFE5FAE138236B68179BFCBF7FBE98208DBC09E9F33F9E0820E04F4F99FCF04107027A7CCFE78208514E002A8168C1042AC10425A80094C8B4608213F027A7CCFE782083813D3E67F3C1041C09E9F33F9E082324D10A93C72AFE544004DE76B741F8E1DC8C3A2783C407537A3B01BF37F37B44E3953D2B4997C4CE6D6DF4FA6BAEF0E0DB8FA07748488800C807CBA44F337DCF28388DC6E0D6853490E09A84835666A8EB7F1312F97E3C480F38B505C80E3CED4FBED1A5F7174692BA9521B61CE2EF14A2910123DDB091B73C3DCA329C5E226A3E4590486A12CE45A9CC72DF410CB3EED66070D87983BC9614124FEE48D0D3AF2AEB1D79ED47B63D37A5E9DE672DA943B570A078566CAE7CC8933CB6F863D15D8EEC1CCC70477D289A24D52FB568C18EBE2D5AC794BB6FF00113B954D32A707054C12A1CE9473F8B3D5CF40F5FF006A59CEAD71A43952F21849761A4BAA48712ADA4248DB9C83E5CC63D43D90EC4607289056A909E32126A914A54543F3B9A3758F2DF6A3B7D8CC7CD5253354415100859347B383E914C54BB534C4AD973BA0ABAB888515493375C1BDFCFDF8B96225C8C24AE3949482DA5096D8E8CDF6778A32F173F1A499855F31AB9A52BEFABD617646D56E64EB8D6574CB0FACA454542C1291FDAA01620082660F493D2A58CCFE6A55C090404D1C3D2E6A35FCDE3072897FBEE4B3E9FE2BD356DA2C8634C69DC890330D50E22A6B40E36C724AA398448F2BF2DCE231798633174758E226B52C05F4DB4FA464BE098A0971564914277F53E8F0C59FEB9398A1BA7A750632FA4E24D321B86CA81B10AE182AE51C409BF217C5A3B3B94A5466CF5CA2A9931B88A9D56B33D07A56F183984DC480164B25E8F67ABEF563D68DB1AA735CE91255C769EBF39264FDE791B63A160F2C007EC0E7968CE0FD3A728DD0AA9737667F7FE62BACE738010568584AC025299BABCA79C5FF002B62D183C081F2292C926AA6019B5E74F585C70A5882F77BD7F0DCEF155E67AA9F5AD6DBAB0CA45B912AE5B8BCDF95F9C6D13D25183C3B1510784B5D859DDBFC7842C9009259C8BDDCD051FCA18E91CD439E3E32FC832EA875D78F0AEA8A565082A220C389200BC83378DF0962F1F824216A98B425206A5209A56848B51D88D2F028F7601259DC74D7D6DEDE2FCD11ECFAE53A919CEBCA80F03C2EA59B022D37EECFA4D8F4C730CDFB49266AD72F2F52A628062405009BDBADBD7A616B143B8717AFA534A55BCE2FC6ABB4F644C228B4FD3329425212B525B485022C2545215E867EEC50B158DC5CF980ACA96A7F94D58576B12DCAF7686EFCEFE2FEF7861CCF3543AA2E3CBB7424C08E8240B7E96B9C4E65B2573B87BC04715E8C0ED41BF87E74324AEA5C9DDAF6D010F119AACEA9DE6D4A4284B1C50A5287849E8933EB6D8E2C404BC0002628049BA451C6CF7FE29BC09C3D406A93434661CF42DE3D4DE0EFE7199660FA9965E5D409212DA5B2916FF58106C2E6479CD8617958EC19708940391FDCEFCFD61C264A87EEAFDEFAE9E75BF5C93A7731AE5A6A334CC5BCAE8A98F12E957C0A35C954784AF88291C3039DE71B4E5CB5292997244C2B70482DC1B1E6CEFCEE6B0FA4C804B936A8D3952BEE94DDBF34ED0720D3ABFE17A572952F3357F2CBCDA1CAB0B7088064B6B489DCF8A3AC61EE1BB3FDE052F198A4774AAA65964B001C7CC0825835361489044C9690C181F37E5B5ED6DEC68DAAD2DDB06B30CD4552065F973D252FA9DA76E1B277EE8A924100DEC3D37C6ABCE72AC8A62E4E19231539D94C951029AA8022AFCAC39435C62CA920B7D093BFA379D21FF2DEC4BB3EC9168ADD539DBD9A6683C4AA64A2A0202FA12DA94D913D3CC6D1883C7F693178D98512B07DCA1569BC605D8FED6069615F2AC4705A48E251A8FEDF6DBBFA74B0A92BF2CC98219C972E672E60C065D1469AB71F8B4951694B6A37B91336E711189C0AE7A92A56348A12471D89157655486FBF4D04D2096B1B0A7E35F4E70F02B7516663FCBA1755C768314DE83C5C200E5B5B0D8C99787078E626601A8AD87224B7BE507784D002454F3DFF003BF28C17A1AB73458733C6DBCAD283FC950A843EA7A7ED4F0A8F0F0C73DEFE987D82ED0C8C220A25484CD5D944A4023A15276FA0A6B0CB1838882B0C3A8377D06FEE90E4D68BD2796A439559877CA489293C66E04DA146DE5E76F2D3119C62B1CAE14E15287A382353CBEBA4302DA17FF34F4BC64ACCB4750A0F754A97DC16061420898DD379E968DEDB61AFFA4637145C2D487B3F3BD29D5C884F84EA3886E28DB0D2FA0B08677B5CE60CA94DE5342DA132027F968317371C49E912461D48ECC82927118863A82E3D5F71EED19083606BA52D4EA012DBFDE1BEB351EA0CC0215983A5A0890D25B084833733C040F59F779CBE0F24C14A1FEDAC4C7A17D1BA9B97BBC38972D44BD9B9FE3DB8863A8CCEBCC8352E0106D0AE9E768BCFBFCB121FE8D216DF28045ED47FF1FC428401AB9E43DFB6D21ADD715557AA754BE01E13711CCEC47C67AE355E4320B1041BD185BEF6B51E8CD180CC5CF41CE3E827813D3E67F3C7C7F8FB3F1B5B481303A608236E0820C104182083041060821553278B88CC6C36C27334F18215777E7F2FD709C119A1004CA80F5FF7FDDB0411B3847F78F97E782083847F78F97E782083847F78F97E78208CD20098333FBEBE78208CB04118A93C51788C64249720381730463DDF9FCBF5C6AE096D76F7D63608529983BDBFC5E0EEFCFE5FAE1512A61B24F913F40605A4CBAAC30DFF003B41DDF9FCBF5C2334F73599F28DCD3C77AFE37AA299A859E14972341527C89B7B78534C9525445E1504988100733FBB4DF082317316B12F0A0CD0A2C420D9DB40E75AE96A562630F2F2E97256BC7CF97228E9EF080E79390FE1C9B788CEB0D5F41A5A8DCA875E6429092A20BA806403C8999DB91E5B418E89D9DECF63332988E3C32CB91562589E4CD476BB53998E3BDB7ED465D97226FE93192D7C214DC2A1663B135DEC6F56AC744BB53F698A9CC94D65794ACA427BE6DD5A0C8BC817FBAF8F48F64FE1AF109532661D8FCAAA81D59CED4D0D5F58F1AF6D3E27634CD992E54E5A9CA83824867A7D7C868D1D42CEF3E5D73CED4D7D4ADE75C5710495120711FF00EA039FE938F42E47D9A9397CB4012C7CA120BA59B9D458372B470CCC3B498DCCE61E352C827576AEEEDEDF788655B952E3EC968294F2CFF9742415711D8F144C0DBED45FE387B9D66E9CA6584259D42A686DE9BDB9C37C265E9C5152E62C39AD7C4EA77BE8D13BC974066F99A5198EA17052D23403810A521329F301493CB68B4CC75AB4CCE958B484A428A967E54D58BDDEE282F5E5D1E9C2A247ED62CDE8DCFF0005DF61128CC7566579553232BD38C349718053595090388923C264893CEE955BEF7182C82762662A6E25C216C509290C96B8A0A9DDC437562D95C201A5E8E7E87E8DA3EF54671A8D0B5A8D73E5F52893E2511C27DE6F1D7A7CEE380ECC4B29042028581671CF47D0F23D2009FD439340AB3F8374A6BB5B940B31CD5A4C2997070AE7C01511E9E5EE1B7A62DB97E59FA67404301C3A0F32E1FC7A50886B3F08B92C5150A3A07F56B6CCFAC40335CD9C4F100BF326401E46F1E9EA316294844A0EA4B3022A2D6FB7D6D1ACB1301AA4802D47AEBA6AE7ECD15DE69995556D4D35252A1E7AB5F2A4B01A6DC713C52012B294A929DC594403060E1862F389387491DE253BD406141B8A8D39DA1E4B06A542B4BFE2C0DADE9170E89EC0F36CD4359BEB157D5E96CE21B252494EF10D906E2D713F7628D8EED580B992A44C2B58B241372E3F75A8EFE778792F800F98F08AB9D69EFDBC76068FF80E9160506459730E180976A6101482810140AD24C9BCC751B462A1986698EC54D96662662D21D9292A003E8598173BDBCE23F30C414B7764177AD2FBD34FAC26A9CF5B7C2D352F29D4A859B014902DD45AC23F1B4E2532F94BC40654AEEF89AF5D28E5A97FB8BBC45A264D591C454403CF9EFCFEED588CB953474A8A87DA4C950920927840BFA83B7BB6DE313B23279666A42D21DEAED762E5C359ADF4899C3A09038B6A6FB721AEDE01A206E664FE6D59F56678F854A8309200927E7D24DBC8624274AC3E15C24A681C00DD69B695F21BCACA93C4C4DB6D9BA69FE3687E7B45505232D57E6F9A8A765292B5309256B77994F0A145423CC7A6F3881C662138C981082FC27E773C2C0D475B579B43A4E1A5862A2036FA9F37A368DBEF0C6BCCF35AD7865BD9FE9E5BC80425CAF765B027FAC77E913CF63CBD063051230C92A54E48091F33548A5A85FF008B18D4A253965060ECCE4539BFD4D1D8C3E9ECB9FAE432FEB5D48595BD25596328E22B3B9471D3AFC3130277D84E1A2FB45DD14FE9C7788018AE8967A588721F97F0D2694A49F99B60E45AF725DABB7D227FA6B4BE41A711DCE95C9425FB7F99A86CD471AAFE206A10AE199EB691888C6F69A64D2518A52E6CA49F965A54A9652F70E92FCC68F4869FA9E0A8FDC054DC17BDDFD37D61FABB4AE7B5EB69DCFB8282957C45A79B7D0070FF0051EE5A5262DFD247BA766927B6B2706152E4600AC1038B89D45BFF005281347F5EB0DE6624CD62A2F7602D7E839B7918E5BCB343E46DC9CE0668F0FB4C2E9D6140F3016AE2927A8E7EB25A623B513F18B213853281B10FAEE3847913A7584DD2F715E7AD21BC6ADC9E914E0C972B69852A05429C21D0E47D8E10EA484D85F86DBF4C2F84918AC6AC199314800B8BD1FA5E9BB585E91B8243B6B786AACD4EF541934AA120CF7083EEFF00869171CE2F8BA60B2247085CC9E8593A294000D615569FE37813C27FBB6D3DF99D8B88630F66398929A3A6AC2763C61F0049B01C6047BA67D7066392E1528044D948D7852A492B6E8AD07F26129F2EC01E2B3062C0BDEC3C284F58DECE8AD61527BD6E914B46F0E3C94C4DAFC4479741F2C44CACC70B97100AB8DA8C0120FE29CC4371289B1DBDFE37E50E88ECD757558E34D332D773757154D39E29E775CD874E91B61E1ED8E1A538EE540A87CB425F42580A78D77D633DD172C41B569FC736BD4B73854741EA36C774A0CB6A00ECE30AEBD0C0F7DFDE30D2767A8C602CA992C1D4254E1EAD40F5DFA467B956FE405FCFDEF18D3F673AA9EE33C54EFF0040AA8A747044EC14ABCF2E9F2C311DA03972BE554C98146DC0A16EA0EA5DDAD6DE3432D40396E61C13CADE31ADEECC756C1229E98EE20D5D34DBCB8E3A6DD646D7792FB6CE2A8586A97496AEE18743E71A80F6FA81F5863ACECF33DA28557B494850F0065C43C6DBCF764C6DCC5F962630DDB01378B8525811C44B8EB7B5EDE87508502035DF51A728F7531F24E3ECFC6C6F9FBBF1C1046CC1046494F14DE2304119777E7F2FD70411B5B40BCDFE5FBFDF4C1046DE04F4F99FCF0410A69C01C51E5F39FCB04288D7C214E085235B9CBDFF008608C100DC03D635E08186C3C8472013B0C1030D87908E7815D3E63F3C1030D87908D8DA157B74E63CF040C058011B3815D3E63F3C10307076B78C668044C8FDFEFF0076C6C2614B2407E2A01D2BEEDB3C359FC5C40006A6F4D05DBC2F5BB346785D385A778A21EF7E9A13A7D99A24E44B44897DE2CF152C6F4366A90DE16AC1C2AE12A4C42374F320D847A794EC6D8D6667327040A182D5616D5DC59CE9EA219CD98BC61328A4A454055A9AF8FA3D1AE212BAB65B6D550B712D21B054A2B206DBEF122DB7218CA32FC57699918696A495020F00DDDADF8262B79AAF0DD9D44CC5CDC5051038F8491FDB56A9B5361E4E2284ED37B7CCA34C5322872F79B72B569752A29503E24881C88E7D7A5F1DAFE1A7C1CC561CF7F8C42A677842871A0B5CEF414F3178F297C56F8BB88CD8FE972F9C70DDC128265AC8E236FED22ED53D4F21E74EBFED6732D575AEA33079F4B4E2D413C2EAC24024C084900F291BEF8F567677B1785C0703E193403FB6D4D4355F937DE3CEF8CED26678B2A13B17326715C9528D198EBEF6D62A879229525C2BE2454DD3C4789422E7724CDFD79C6F8EA38746130E84A1084CB54B152183BDBEBAF9B522BB89526629D63BC7724AAAE75F07EB42F7B99664398E67529552214585195A9426C62FE2DA2F61CBCED8431D9BA2524A1243B338D7C00BD9CD8BF488C561D0E78500381E0C5E963EA4DA2DCA4CA74F69BA32FD429B5E6CE241610BBF8C0B813206FEE33EFE7B99CCC466B8860925292DC4347EBD3F11A80A940949290A34BD750EEDE8FB8AB18AFF0039D4F9AD71719CD5459A3121AE05048206D6410761F9626F26CB1485238D1C5C2DA37D07DD8B6D7D54B529DCBBFF0098AD6A3306D0A78D2BDC2DA2EA59333EB26E3DF7E5E7D37098796108050EEC0066AF27B0FBEF184A52028ECCE2BE15F637DC57F9967F975538B69F05D7A4C2C15244DEE427A799F5107162C2C9320278260969B94B03CDF88DB9D7F11BF100CC1D85DDBAE95DE20D9AE6C9A3E04345556F5448A6691C454D907621326E0F38F888C482F1B85920AA64C4A5491F35871B3B16D0D05BEF0EA414AA93038A54BB0A6C74F3076898689EC7F5BEB379198662E9CBF29242D69742012DF41C5C2A88E979337E543CEBB628904C994388A9C24A6AFB59FD5857A8859425004200E26673D76FA3116F18EC9E53A6744E8869C672A6587B30E148AE79C4F7AA2B47D828EF02B809BC94113EB8A5946619C4C98B98552D0B6E1AD3CC1F4FE59152411F2B12474AECE35E7EC21CCB54B8E9534D921A1221321201E8040F2DAFD2F187527B30A92F38CD2B53394B17D2BBBC47AA5CD24A9C9074B54F4A5BA6E6230E6614892A52DE879C32DB241FE6904C82B261113CFCF98C4B610253FECAA504B515314038E6C4574FE630241511C639EF7DEBE875E5766AACD2ABBC08711F524A8C02DA7EB5C5B6E5B0787DE47BB94903849201252B53514070D7C286B6E8FCCA889291FDAC5C31A13AF5F752F1B5BA3754D97EADF729694C71250C29F5D6CEC0A100AD920F2816E5D62F1799F00A2824070EFE55EB4AD4F8C3A4100304D5B7BFB7261D6974C67999B61DC932D4E9BCBC5D79DAD48A979C4F350A273F9A9BC8E1099FC2B589CD0AE67019C78D40F0B3905AB734AB0D6B7D62465CE64BB0005FC6CFA9DE9D00892E4FA1320749152E556A7CDC91DD553A8A8A1692B06F2D2C06A395C006E7D21A662679F9C4C082788F0F10268FA82F56AB55F90A35C5CD247CA4B52A2D714B7B689F2321ACC9A9C9CE730A6CA68801C148C32C3EE2D16F0778C8E3498804933798C3246266E20A97294B98A059414E90347A96363E50C8CC58001554BF51E2E6EDD3C6191FCC743658A2FAF2071E7D5766B5558F2FBE527ED1EE1455C107900266061412316B981427F0CBB997C03415F17A6BE75867366926A493B1A37D6BE5D06ADAE76859DD52CD2E474EE32C1F0A51F538001DA5C53408B79F9CE1C7E8A42D7C5318AE80FCC2E07FC41EB7DED0D56B58D68795AD478C469BD61A865EA97954284DCB86A12B94A8CCF76560A607288EBC861F4A380C229A64A0A245B878812D6259BEFB5A149014A075B6B56D287EBF57785AD681A3A24F7B996A843AB172C7D5D33E63882C9E5D27A635FD58529A5E5E9087A2DC55F56E17047DC690B306BD7663F58D4F37A3E9212FE567315A6036EA5F71A8237242779E876BF5BE674DC4BBC8986504B12909041A6ED46B0F3E990A2976D7F98DADEA6CA6800FE1F9421881E12A577845EFF6C198C20BC562D48E05AE62C30B122BEAD56661F88C0252EC5ADB69E11B5DED033152404229DB4806006184904ED278413EFDADCF19C26055885BB4D26E5E62C8A6C0F8EF734A46C662CB39B72F7688C663ABF50D5CF7550100FF006F0276EB045C0E87160C3652400E8A0DEA7CEFCADAD76844A1C92F53CBD2F11A39FE76C294AABA97561CFB1C2E28011B93C26FE73EEC4B48CA9142A969F14026FD2C7E96178C701B7153DB307AC267351D6F279E33BAB8D667DE5437F8FBB133232E9691492936B20680727209F08CF07FDC7FC5B5EBE7E6DD51A96BC1003EFA45FECBAE0DEF78541D8753E98CE232993359E4A054D4A053500B03BD396D0DE70502DC47A837B6A0BFAEDA426FF1357EDF58A983FF00EB391FFF00DE18AB2295A4A4D1EC903EC5E1100837BB6F7D353E821C6875A673421C55357A9A0A8E34BC03DC7D000E93C31B1E1DFDD76537B3C95824CBE1356091C3BECC096F5F187D2DC3B726A3FBFAD63DF2C7C938FB371B1B04CC09DBF1C1046D83D0FC0E08214D3A24AA645872C1042AEEFCFE5FAE08233420099501EBFEFF00BB608236708FEF1F2FCF04119A4013041DBF1F3C10A4BD7C3EF19608523058262013BFE18208D707A1F81C1046E6904CCDB6DC608236F77E7F2FD70411B9A6F7B13B6C0FE1FBBE0823670A7A7CCFE782063B462B4C0040317F4E5CF12783C3226254A590E03B1D99CF4FBEF1B15A1287203D6A5B7E77E5E20F2D720EC715ACD7309D2667732C1370C1EA3766353CADBECC82D7C454B244B7724D9AE69AB72F1A3430E7B9CB792532B3075F69BA7610A53C95BA8471003601441277DA7A461FF66BB298EED06253C4898CA5025D24DC87D85B67B58C577B53DB7CAB20C24C509F2FBCE134E201884F22EDCEEDE31D13ED87DA357982DFCA74D3DC05054DAD4DAE4133133B6F3CCF3DB6C7B47E1C7C2C465E9933A7CB0AA24974D281ECDD5B6F28F10F6FBE2F62F37C54CC34998A12F8949052A2C41A587837956E7A559EEA3ACAF792F56BCE3B56A52D49F1120124F99178DBEF818F5065B94C8C3CB0992896942000484A68E3C398AFD8C70DCD312A528CF99338D4BA91B390F7353CB7F186A6AAA9EA15C35C897366C4493681B0FD70AE33BBC2A7E42900BD38478DF9FBDA253882A62E41A3EADCDC8736DFF1129C934557672B5D5BEB0CE5F49C2A6C3D08E34AA09E1E382A8E71276C52F1D9BA04D1292BF9A61200487A8A55AC5FA5BA43D94492EC40D79FDA9A743D224798EA7CB74ED31A1CB5082F2014A9420C9D89BFCAF78E57C272F018AC5BAC9514962915A0EAEEC40D7587899695330E44F9F9D5F97845319CEA4556540AA75D5F7CC9596D209892798109DA3E4479DBF22ECED38E6A6FA9FE7CBAF9C32C64A0804B8A55F7045075DFAF3222199A6A4AECCC776FA825B48804285E0C72BFEFAE2DB2B289723F6A40DEC29EC57C623A2135D9A06F853DF453890F80A92676100C9B9E585D4A124306A74FBF88A6D56104194E99CE75555213A6A996BA752A1E75C050009BDD71B78B9D8FA623F179BCBC3A0AA6CC609D4338D2C1DFEF4BC0C5DB972F4F0EAFA6AFD83D3DD96699D28DA731CE386B33480B534A0A506D62E76E24804FEED8E6FDA1CEF1989983F4A261924B05071C41C034D81E84D2052CCAB1A9049E5F987FCE353D45731F51CBD69CBD840E1086C253316004705F6DFAF5DE4B26C14B992C623128E298402AE22FA9D0F3E8EC291A4B9CB5900A80E47ADDEFABBF5D6B1057DAAD4142DD54C932E158973E26F1D3D39E2E127F4E10AEE40240B04D88FCF94498410905B47B83F48E5450F2785082A7369402A9923A0373F0BFBF090C5094B69DF225E8E740357341BDBA438952C077B6A3917B03F7685997E83CCB3B2B742D6865882E305B23BD0AD8070C14111CB103DA1CDB0D2912CC85A4294E15C2DE16D0DFA878526619203A6E0BD7C373FCDA2C3C9B485365E90DA1B144BB0571A7EB7C645CDD5C404F381CF7B038A87FACAA624852DC0DEFE8DCF4A8686531205856E096F13A0B023A72894B191A288AAA29D4CE5F605ECC9D4B6E848022452AFC37E612075386989C699E82953AC2AC904A49634750723EF6A3420B5F097E26167BB72A36BB7ABBC20ADCF322A074394F5DFC57334EF56DB2A65A4A87FF00D327F967680784C917C212D6A5A12E8EED350A415711FF00C9891E6618AF1252A3F3120D8F3E81F5BBD8D7AB4BFA8B5B67A453E4C94D2251E1A851A569B35A954F004A948496F807349133279E159587C3021641F92A3E6248772410E7D6DE91B4AC42E6FCA4BBD09B7986B071E7CE1C29346D406CD5EA6CC4E5CB2389414B35416664C2428813BC45B688C2E7109207E8E477CB7A86EED88717342D537F285CA080E4814EACE396AE6A368E10CE8FA55ADC34E3367198EEEA0A96D06CC5CF74652A98DA396FB61E0C3E2A709678BF4C43F12182C2B6E41BD2EE690CA6AAB51C6FB16B015BFBD21054F6888649A4A26996DAFB01B14CDF108E5DE16C1B0E7EFC38465120A84C582B9A2A5414A0FCDB88016FCDC43798B2C00A0AD3F9F1FBDDC98FD7E7AEB890B4B8AA253A09E14ACB9F58E920186E04F4EBCED33232E4CCE10A008A5581296A8EA793F28CC87AB12051F9EE39535F2D621B54F55AD7DE2E8DC75333DF7D6942DC8844CFBA3711CF1228CAF0FC410141E8FF002B5090FE7CE1CC694661510A4D354164A7EDA548E38E6002ADBA6F187A32492082A4A549558BD4EFF7ABDC068C804D8437D4E635C8E22B7839E7C294CFC36FDF538712F21C22D8AC01BFCA0D43B506DEAD625A33C2ADBD47E79C34AEB1FA8214E2CB6048179E299F75FA1F5DF1212B27C361FF00E90E27B800A6A7ADEA6FE42321075207AC6835A968FF00F33B5A26D7F203F7BE1F232F4B8694F4FE6FAE8EF4D2F19EEF9FA7F31A9CCE5B48852FBCE9CF879EF73FB89C3B46014689484B3D680927AB7BDF4C141D0BF266FBC373B9E20589BF9188F4117F3C3A4E015A3807C7E8FF00568D82030715D6BF83086A73C64F0F2DF73F98E71F2F3C64E14CA7E21C43A1F03A73F386F3D0281BA1FA7DE879C26FE36D7EFF00DB1B230E85D801BD0D3D457942299628D53F4E7B7D7CE1155E6297D4DAC37C696E4ABC653131161138728C14BAA480E450B061A6E77DF485D2909622E35FE0BED1F4AFDDF9FCBF5C7C3D8FB350A69D20154C1B6E47CB0410AA0741F018208E426761EB10304119702BA7CC7E78208D2EA488991EFF00C8FAE0823540F3F89FCF0411B5A493C51276DCFAF53821497AF87DE37702BA7CC7E78214850C8202A45E7F7F760823760823058262394E08230E0574F98FCF0410AE99E2C25C4981C7B6C76F7E08238642DC778B913E7F18FDDB98112100D0C10E75CE328A64B40A42DC163D001279FE9F3185A54C9C169972D2A5719E12DA3F423476F6D198E988920CE5CC094A0124380030D5EFB6B5DAD14F6ADED0324D134350BCC6A9B2FF000ACA47109E20091201F302637F763A9F657E1A4ECFE6CB9864F105104BA4D053537AF90DA388F6EFE2F60F29C34DC348988E209525D2AA82DF5372C36778F37FB52EDA730D5D990CBDB7DD4654A5BA16A43CA40E124DCF0907D24DBEFF0052765BE1AE1F2244B5AA4A1C00E38439FABD5BF378F11F69FB779B67D8A9AD3A6196A52BFB8904134A3B3331D5ECEF1D73AD71BA7AC2CD02D4B43A654A528A8C912492A9BDF69F21D71D6B0988952909932E58433024306601BAD3EFB456D05253C53140CCE65C83A53EF5EAD182692AEA1F6E9D8A75ADF74F85E825283CC9E569E640B61DE2330FD22490BBD4D852BA02C75F7687C526629557297B6EE6FF005DE2CBC9B4AE5F92B69AFD46B4BEEA405A1361C24DC02127D224408E4315AC5E613F1A0A6529552012D41E7B8EBADE13485020B11EF5DBDEB0DFAC7560AF6A8E9A99D0D52520743286886C90409E32D9055B082A07CBCF6CB3294AA719AA492B9853DE12E6DCAAD7D186FBC3C97354E012C2BA7E3715F6D14B66B9A13C5078B7B9373E649FDF3C752CB72D421090120160E48B5B97D34D9A1F4BC400003403526AF567FB115F5881E659C2DB5A5B0986AA09E35822101331F7CF9F438B1A244A928E3550A050333E9CBDF3108E366A6600010790343671A9FB38A188DF05754D4A58CB1876B3BD304A38A1324749EBD45BCEF88FC663A5A41248480EE5DBF0FF009ABBD21845CBA5BB17A6AA6C66BA81EE1202568A55133782A100824F3BA76F953331CE809C9952419855C4E412C9E6EF5EAFF48D92970E4B6DEF6FE768B6E9DDA5C9694D164686E97812132128055C22665404FC639ED0045AF0E714A0BC4BAB54A41347E94DB9BC0542A1346A3EBA1FC73F1778A5566B98A56EA89E22A27BC2A215DE003FA649023CA36DCE25F0D82C2A929EF509734402053E971CC5793426651984FAF878F2FCC46DF759AA5296E2BB87A6787C44ABDC0817BC5AE2679E159981E075CA514A459AA29BD75236D2309C32829CDC10C351E2FCF67B33C6DCBB21D4BA96A053E5D42EAE92988151532521295DD2785513D6C77107081CEF0D97527A93C6A1F28A39005B97E4F9484B2A0068C0737A1B036BEDD18068BDF4FF0066F4D94B287AB2A43EF708516D4DFD9205E4FBBE1EFC513B41DAC18A131121010CE1252A724D6CD6D2947E7787489812CF524073B7DBF1CA251515D4B9636942DF699660CD3252826A026D0A5A6EDC4089B99E56C51309371B8A5CC54D52C8D0173AD3F716F768C4EC40018AC33073E0EEC1EA3F976888661ACBBC7052E4B953944FA8F087D3C5549715D7EC94A77F75F78C49CB90B47EF5D4E85874B9F2A93EB0C66E252A040A91A35B7FA56BE4EF0997A775167686DDCFF34148C0054C84F04BC93B8521B50298062E01331C8E1DC941E258BA92DC418B07B56C4977FE61929455521817A7B25D8C6E4651A5F20477C809ABAB45C28A8F89436B1240F4B6DEEC3B4380AE24B59CDC1F2BEAEFB97B3C335CB2493663CCDECCFB7DEB0CB5FDA03ABE063BB4502192A0D77684A8B808DC94266D1B9263961C61A5212A2AE1AAD892A2FC4CE6C6829D1FC61690952487B569E0FF007F3A4476AB3CCC3300422A1E7A6E3C0A2083E57B795A399E92885A1218048E6004BFA0F6E6B0E88704421629B397B8BB969E215B80D2A075984FC663A6D8593894A58A949049A02A0391D9EF5DA1A2C5880799F76A7BD96A348EA7ADF137401C0AFEF521A37BFF005011F1E9B6379998C8921D4B0280923E61E2078D89F48414973415EB7E5D7C9F4736507B35D66E82AFA8B4C81713594EAE29F22AF0FA19F99C309BDA495288EE54B26AEE950D6A2A069EE90ACA414F13EE05F6FC74DE13AFB32D6A1265A6B9C4D5306DCFFACFC3D631B48ED6A9FE67045CF09FB06DFF008061686DA9ECCB5E0134CC30491E33F58A69B6DBA89E5BCF5E789893DB293F2F7814787604B1A5E9F53CDE320136D39C42B37D05DA432543F8621F1D5350C73DAC93CFD7A62730BDADC3AFF6A08D6C4539B80EFAF93504655C563FE6F5880E69956B1C9C4E71953F4C854F741A9A82E017325A49E083D627979CF60FB4322791C4532CBDCA833317E47CB58524A544579B167EBB72FAF38ADB33D5154DB8A61541534E663BD5B6EA408E67893005A7A40C4F49CC654C03854950701C11A16D0DE90B777CFD3DFDE3450EA4ABA54BCAE36EB52EC120B886D54D133209255363FBB4ACA5A2714926DA3DFAF21A8F1A46021E8EC45FECDD6BE4CD0DF53AA5A2E052B304A164925908E28B1B4881899932524710A00185CBEFFCEAF19EEF9FA7BF6758E06A34BD1C46020595F678A7CA6DF87C2313F00A981D20A8867715F0D3A8FC468A92E0907E63EFDB8F0DF7379EB53056224733CEDCE2DB73C248CB6705070BA5C70B7DEDD5B4F04BBB0356D5ED5DFF00970DCE36399D34AE14858F71BF5BDFA75DFD2D87C9C14C4B7C849E63D2DFC7D6125A824B5CF2000F478FAA9EEFCFE5FAE3E0C89885332856DA7D63ECDF02B6F51F98C80099922FD6DB7BFCF1BC60822E232C6C124D40F51188DCD0078A481B6FBF3C1C0A360FE519009B08DBC03FB87EFDF80A14039040E719E056DEA3F3182DB248893EEFD7CB1AC60822E230EE8F9FFD27F3C1188CD08899313D446DEA7CF046E8203BEB1B3801D953EEFD704280836AC66941131267CB1A95A45D43CE36E151D0FD3EB19411B823DD8C7788FF00908D84B59B249E958CDB4154F84988D813F763066CB01CAC010195305D0A1D4465C09E9F7FE784FF005521DBBC0EEDEF9467B998CFC26CF63F86F568DCCD1FD60D85926E7D6379F38C2C852564041E27DBDFBB5DA135BA012A0C05CB8A7BA7B11CD77065ECA96A504800995111600EE4C7EA4FBE42565B8C9DFF004E4A95AD219AF1F8496FC7392967B91A7F98EB476B7DB153E92A0094D436AAA7D2E86381D4A8A0A78B7292637B131F9F67F873F0FE766EAEF71521480820FCC9A1AF303AEBBD75F377C6BF8943B392D387C24CE3EFB8904A14CD60F404DD8F851A3CD6D53DA1675ADEBEA55985538A602D5C03BCB419E40C72B4F9EF79F54F66F274E46512D12010800060D6D682BEF48F1AE6ABC4F6856AC54CC4948592B292490C4BB5FD05EF15AF7DC4AA8654B01282384A884CC9E52798F2F8F3EA32387152871A780B3049D5FE9A73BC56A64D97820650471173F37A3D8D76D1C561E726D3AFE78529A00A2A4AA54E14F840DCF88C8137BCED26D338AF669265E05E677A01A9617BD07F97F1686D2A5CC9F30289294B82CFA03BD2EFA8AD4B88B5159964FA6281140F34DBB5E5252B7400A2D91CC403FBB7962030866E6B88A4D644BB23877B5F7D5BCE2566995C094801C0152CFF004D856DB6F150EA1CF2BDE5AD4DBCA758519093E1E117D81DBE5CEC062E383C9815255C3517A7959BF3EB0C968490F46FAECDFC6915D3F52B6CAD6A7788AFFA788908F7DFCFA4F4C5AF0F9726500B4A78599C357D456BD4D4EB0C660208AD9EBE5B7BBC44731AE5A8A9216093602428C911D66E64587CF12273097857723E5624BB6B66D7EFD61A4C9F32A00B8A372BD6FE2F4872D2DA2B36D60BA8525B5B34148506A9C790503856411C05613C5707EC123699C43E65DA790E995DE00A502129152E342D41E3D442B875A9555BB356BEDF4E757768BD727674AE85A72CE5F4E8AEADE185A8A54A8541132A0A1FBE5B629F9862B158E70A52A54B770805F883BBD08EAD57B43C0A480183B863EEB42FEDA1AAB353FD72A3BFEF14C3927829E0A5279401013B6E7CF09CA4CC4942425C02439AFAD75FC35DF5AA8EE4FAFE3DF266CADAC76B104BCA2CA87D9E19326D13C302F6F8F4BE2C384402DC4013D767DE9716AF8B46C25AD4EC934FE3F30C14ECE735CFA29DB438E2CAA28CB692BE393E2E220787CB8FA88E785F1624A071F7C9414876240A6947AB723E0454BCC2CB493FEE029E166D8F503F3CF78BD7487640F5425ACCF57114ED8E15A10A2078409B8491D472F238A4E69DB43210BC3E0BFDD98974958B0D19CB8F5B3F8AF31284915001A33EBB7E75AD79DB5519CE41A529914997A986587070385084AD4F706D300A9245BF7BF3DC5CFC4E6B34CD993162612E0D404BF205B5FA88426AD09E24A0B00C431BB53C3A52FD1ABCAECF755672EA98D33951553384872AD4EA510956EA09700279EC76E6409C187CA4E1D499D3E695A49FDBD2DA9F01CAA223D731492CEFCA94FA78B8077D192A34C657918359AA33A554D4D6F89597776B2029024A038824279C9116E9B62C38752E6BCB918701219A7050A3EA451F66B5219E226A8872A2FF00F115FCEFF4D2353DABFEA08EE34BE5CD503401497DC08A852845C80EA54A13C883387C32844DFF00F1534CF208524A7E4E12EE47CACFB3F2A43718850601241D5C3BF990D406B4B7288EAEBAB6B5C52FBAA87AB1E3FCC7077894715F8785221099F281D79E1DAA4CA4242414A5800EE1CB6875A59FAD21DCB3C572DD747DFC79D39011CB1A3B51D72C3B54E7D5E9946656E249E1DF6E20498FF6DF0D57325214521D6694009F221F7143B3C394CA04124D34A375D625D43A6345E5A92739A94D7D42C0E0400A4F7253F6AE92649FF6C349C9C62D40CB965080CCA05DC11701891EEF48DD4254A624B93BFDAB6DDC79C66EE6DA53290A19765887B876F11B40B5940FC79EC71B0958C23F7AAB764F9DBEDAD79424A992C9141C989FC81A359B4DA1B9CED26B18F065CC3396255FF10961A7FBE036FB48053C3E5136C61596F7E52A9C998BE1FDACA2867DD8B79DA1B4C9C12A74A80045880D66D8F95A962D467A9D6F9B56821CAA0B077E06D2D5FA0E100EFD0751B0C4861F06245449240B12EAA6E5DDFC4FAD61B4C9BC4CE5B71CB414AB36F0C1539C562883F597999076716BE23D202A047291D6713123264E3D24AD212CDFD8C6B6FF0088F7717856428105B96B777A8F7F58685E6F5C3C23317C0BF35106E660150F2DBCB0F13D96929D52C030A0D7D9EB587108DDCE733490A4662FA60D812BF17FEE3F327F2772BB3126951FF88DA87E95A1DE08554FAB7356665E5BC446E77BDE64FEBBF2C3E4767F0C3FB80074E11E9E3AD057782143BDA066EC94F030CF0ABFE221D69977BC03A7789570C738009E588DCCB23932F80A10B9A03F094A9496A87B1A8F7BC3DC37100588ADC10EC2A3DB11AF8A0ABD47A5F3F6CB1A934D53BC14005B88525926F04CB4DC8F71F7E12C261B31944A70F3978643060A495DABA97676FA43A4A52E4A92EE46BC87DC37214A88AC353F62DD9DEAC4A5CD1B50AD3158D859AA696E3D509AD5ACF8002E2C25AE0DA475BF95832FCCF35CB26138E7C64B531130327BA019CF0A7F7120BB35348DF825ABFED3B56BF41AF5D39C75EB56F60BDA26960E5751D02B35A16E562A1A79B512912A2AE04952AE22DBFDE7A0655DA9CAB14B4484E27866D1D2B4292DCB89403973F50EC29A2A42C00A6A6A5C1E761AB5F4B5A28B7F5156B6EB94954C3F49514AAE1710F36B6C12491652C242A083B480778C752C85781C4820CE96554003A6A497FC579EB68C77547D2BA8F02D7B5E95B8B18D88D44A3E12E0E5042C48DAD63F95F9C62D072C94A0E809376602BE156EA2908AE592E521DAE68F6F03B721E50E14F9EB8BE2FE6131037FBE26E6F724EDE78417964A480C815059CBB74DFF00311D365AAEC4B3BEF5ADAA63EC831F9C095839AE5C94B333823C0398FB38AC4CB510CCF5F1F21D6343DBA6F11CEFCE7CFCBD7CF1212A470DDCEC1F53D2E3EFA4604CE21FB5C0BBF875DE3142547727DE6607E7FBEB87F2C0003D8D4B6DA0FE3AB460254A2A60FC8066E9F9FBDD634024102794F9FEFA7973BE10C4E255254E84710E9CABE95D3988DD0A4CB07BC152D5351E819AF5F02446DC3318C5AE851D5F6D49A563071491F2A405528C697DDCB78C641D71BFB09E2264F5836827FD8FA1C2A898482E1F4D00FA7A69082E7CCAB21C1079D79DB71B5F48DC871F7265C089882426D7F4F891F3C2A99214FC47A06D2EE7DFDA1A2B158B144C9596772029F968C0F58CDC436803EB2A352493C3C1E1088899E106645EE46C71198FC4CDC2377492B7BB75E9CFA74710BE19626907123B903FE619EFAD350DE3AC6D645393C2867879F89447DF1B7C4619CA9D8CC45449587E4EF7BBB7430F26627052407C42001B2853F9FCC294B9C0084A1A8E654E206DCE144193CEE3E7897C2E498FC5B34B5D6C58B87FAB577E750D0CE676932CC3FEEC44B2D562A039EFECD0D210D566F9753A66AEA2999817979B047FEEE53EEF38C5870DD89C74D01C2C9BBF09200AF27B74F5864AEDE64F2B8BFF009892C3750BD3737F43B558B4AB5C69ACB829F39E5236C27FE38E26D731F641F11208EA089838964FC32CC316C89689C566C02155BBD746DABAF48AF66BF15F2BC17FD39929628E42D34F00F7E5CB9C305476AFD9F38E2AA17A96910DA264909827CC71016B8B7E786B3FE10E6F2CA4AA5CE06A482953EFD6A3C7AC42FF00F7D39714F0F1A050D5C1D1FD3760ED788F7FF882D0D48E3C8A0AD6F306CD9C711C490D948812448215D2D389AC97E1C63A4CD48992D65881F32496B55989EBBF368AA673F19B0BC0AE05205C82140BE87974AF2DA3ADFDB07B4AB6F52BD4990BA12A712A49295410152362266F8F41F63FE1FC996B44CC4CAEF08E160A4B01CACCC3C79C70BED1FC68524CC12A6F0B3D44C2D63A3F414DABCBCFFCEF3FCD7397AA2B739AE71D6DC512DB4A595589364C28913E5BF28BE3D1990F67F098342448C3A50081600585EC037D9F78E19DA2ED8AFB5530AA6CCEF382D5048E757A121FA446DB63EAE3EB617DCB0B3E14195151260EE64413CA712F88561B08E1494B8B9A0B7E39379C57933A620325440E4FF9891E53A1EB33CA962B2B12B6B2C2AE25386521494FFD244907E26F8879D9F4A48299412E91400F09D79FF24E8F08A997FBAAFAFBF38B0F31CF69B49D28CB321E05B65252E2C70C8B4925464CFBE397AC28C2E23362672F8B8DFE506A05480D56B35852F405A3604A1D293F2D35F3A0714B6A08D6292CD754B85F7B825750EAAE5478BAF5902DD395C8E96DECEF6695862A993430353A3E9FE29C8B184A612E9726A4DC935BF9DEB110ADCEDD434B35EB0804184FAFA5CFBEDE5B1C5C026560EB4E11577DBEDE0D5D85352A2431F7AFB6886D353E77A82BBEAFA769DDA94A963BF6FC412B04D8F78A10809DCF5DB0D713DA0C3006A904023D8170DAE8046840343EFF00117C699ECC74FE4C84669AC1D0FD7405A3282A50E1501201750608363703F3A263B158BCCE7AA5E1507BA3FF00F7014CDD13AB9A5EAE0BDE0EE65A43962A06DBBEAED421B6D5EF589466BAAA99A63EA8CA114F428494D3D13294A14DA62FC4EA1216E4DC8E2923118325C661A72A6F0AE6AA690EAA96B58924797D291A9412C123A803D77373BF9C578BCD09A82AA263BB0A2495384A84F33E3F3F772EA7167CBF07C491DFB020390696DF61B579428896430218DCBFA0FE34FAF0FB88AE537F5B6D55552927B84B28E1851201E22D0215CB7B731E52AB460E4310B42529152549714AD1DEEE000C6E3943A97C23E635E16A351F4DFC9A2CCD23D946A4D45C35956A19665A98510E841251B11E320FC2F7C52B38ED4E1702BEEE5AF8D6E78528048A740CFCDC561F4B5A58D0067AD3DD7DEA62D166AB44F674DBC8A453559982C27EB0BE12EA82D03C3C09855CFF00A76E722D8A74FCD7139CCD69AB5CA969B24122EEE0B16AEBE70D3173C24012C877AB6E0D3968FCFE91F7B38ED0FB415919165AA4652930BA871C45284B60DC8438104C01CBE7CD354CCBB0491DE7F796763314EF42400E2FAEDD623BBC98B3FBAB7BB7ADF7B56B4B8829F24C8F272EA733AE39AE6C882BA5571A514CB1BA439250B0A33245875BC61696EB5132E5F04A1C244CA7CCFCB46D7534B426EE4B9BD4B9277AB79C32661AD2B985FD4A887F0A4A894A03480F95721240913205E636C3E3292A6E3F99BCBA37DC3460DCEBCF78D74BA7758E7A7BF790A7583E245538529E049BCF02BE7F773C615899520F095849D921CF90B426B524508735A5A9AD6D1236B22D3F91242F3CCCD1595200229D0D91067ECCB648DCC5F975C2B2E6E266B8949212A3498E4335D81A9A381BDE13EF24A48AFCF5F958DC73B56953C9A0A8D5F4F449EEF2ECB9B6985C84AC84ACAC0D89E24120C7291CF0F519799BF3622615ABFB5BE5D2AE030F5AE86D185620243A52CF76D2AE3D75E8394305767B51988216A5B73C924A449F48E47A5CFC04DE1B052E526890ECD50EFE27C06BE702B16433DCF36BFBEA74148634D3A5B2A529C528B907C4A2A889E64902797AF4BE1EA6420B02905BC00F0B7A13F66988C4296C1D9AD57EB7D3ABFD63538844C48EB78FD9F761512258B2436C403FE39D3486DDEAFF00E47D863E7FE1A113E1B000253CE0C739F3FF006E5CB0E65C941A8961B9900D76A59C6BD631DE2DCB93B54BBEFD3FC6D0DEB2DC1F10E8449FDFAE1C8C3A4DE5B1AE83F0DA535AB41C6ADFD0437D43EDB407881E2917E51B6FC8003CFD30F644874B24330D8B1A9D87D07D1A1F609D8EDA7ADF43BEF414840AAE6047119236836FC7CA77FC30E53875357C6A47A53D6EC224211BD5CD9E102204FEC4CFCFCF0B4B9452E2DB6BEF5D6086F5D6A0837F75BF7E779F4C29C0DFDCD6B0FE75B4109975295F0C19DC99B812622DD630EA54A4A920A98DC5439F571D4DE1594A29762D6FBC2571D4926C24F97972E60FAC5F0B1932DAA81AD424026BEA7CCC2BC6ADFD07E211FF0011629DE6E9DC42BFCC980B42949E0E1BC9281CC91F9E18CC934B50BB16707CE81AB4EA233C6AA9E2AF415F187D4EAED47A78368CBD62AB2E77FE221D0878047310EF11DA7CFF00185C56592F10A4AA623E641252504A087D8A4A49F41F58D84D98971C47C61AB54E97ECC7B4EA7A56338A5628338752E019836853629DD588054868210BE251FEA369EB87582999D65E5588C32A64D91218A6471F0950D7E62788F09FC757D84026FEE5313AFAB01D7F160F1D27ED53D9D759766CF2F36A243B9CE975A8B89CD18BF76DEE3F92D95AAD2522676338EB1D8EF8872B19325E127AB827A084AE52D4C52FCD4CEE7F1AC3A9984E1142E0DB571A9FB5E28C7739532D06E83892572971C7014294A4DA0A1705252AF8F3E98EF3844E17152FF51316821829297147B9A1ABF36AF230DD58628F95497357D497059BD2AC07578FB7CC7E6CC4E4005806DE9E2D43E61ED1F5CE5E196E2E583391BB3D89F01EB189415DC49E1DE01547AC6D84578800B685FC391A3FA6FA343D44934228055B7F13B356362131629B799223F3FC30DCE2175E10E2A3416F0AF41E70F654B48AA9403914E7A3FADF468DE4445EE7974FDDFE18DE562012CB6E840F1041FAFF00889191946171B59D8844A61476AED7352DE4238F3E5D712386C32710C10872A346035F27EBEA4D21A63301966041271B2CF0D7F7245B9397B338D8E91C8AC66990B5B8F32DA40995B8DA66378E2509F77CF6C58A47661738A7E457CC47ED4151F161E1E02D57A8637B5B93E59C5C58892AE1B82A4876D9EDE1BE9101CFFB54D1790717F13AFA747083C5C2F24ED7BF02AF37FC2716AC17C33C7E2D295CB9334BEBC2A1434F6C7CB4A9E33E3664181E249321D3AF120BB5F715B6AF14EE7FED67A03254A5392BADD638B2A0F82B578236FB522FD131B62F9D9DF8178CCC4A8E264A900311C697E2D2C5A9CEE5EBA472FED77C6FC1E62C9CB9694B38265A83DF97DFD228FD4FED9B50AE2FE18C84CCC70A84011623C3CB6BF3E78E9584FE9F644A62A4A69FF60150068FCBED531C8B31F8AF8E524A53316EA06CA3A740E39741B98A473AF6B2D7B9BAD28A2A97691B4157111C278E6C394DADB7588316B4E0BE0C61B0801EED0786E784333BB1D0F98BF8473ACD7E25E6CBE2E19B32AECCA50B31F37AEE29D22BECD3B5DD679E89ABD4552C71CCF0855A6DFD2A1E405B6F3C4E23E1FE1B0A18C943501748E5C9E8056FF68E73987C45CFB895C3327D4B8F995D75A0FA72885D6EA6D4C1B729D8CFAA6BDBACBBFC4B71B0D04191BAAFC57DA448B8C5D7B3BD9BCAF0C952E7C89448A25D209D41D1DBD3D1F4CABB519CE68A3DFCD9A18B3A8ABA01567FAB6950CD543459FEA47539551D6562005CBAE77CEF0113C46545511CB78E90621E67392647264AA74C44A4B876E104D4D0301ABD9BF02D12F178E58613D6FBB9A9A69E7ADFC1EE845651E87C9D1943657519854208AA70BAA708524784924A80927918B6E314BC176770D8C9CB9F2E4A65C804143A402A72C6E90430A9603D6AD71A718A4979AA73D69ADDD9BADBA45479857ADFAA5AEA1D212B55815710B93CE6DBFB8822778B8E03249320829480C050003425A8C683D691CFF34CB71B3CA8A96A2E6A2A5A9422F46DC68613AB2B26A29AAD4FA9E4492DB224F1156D10542248E5CB61CE4A7636560E5AA5B04101B4D68EE7F36342C28865597CEC1A9466125CB80797234F5BF568B0B29D2CAA85B59AEA43F56CA5B1C4DB3CCC0B4A130BFB4049239913BCD1F34C67EA94A9723894B07F68762F5FDD7B7E0C5859EB615E6DEC96F3DA156A2D76A4538C9F2C4258CB784A68DD109242478CDC0572DC993CAF7C43E1B27C54D9FC650A01452E6AC7566B060F517D235AB004BB453798E7EF309729D0B53AF2EE5464D899373236B833E57DF1D4320CB5324244C484877A803C6BEDBC6088356E6FFCD652DB6B5D4051EF42413727C26D3F7C7AED8B6AE7C8C2A56164310024380CC2BE06CF616A54C68BE11C240735706DEF5D45625394F66D9D6B071AAFA9596689052B50721129064C85149881EFF7E2979E66B2427BB0B20A8909094953D6CE079D830D2130926C29BFDA2EAA2CC720D194472AC9E95B4D6B8808ADCC4242CD3140012784A55C7C664784CFBC629333078A9F3828A95C176F9AA0D6F46D3D01B4093C229E66FAD7AD621398E64E54BAA71D756F8513FF00C4AF6E63F9009B0FB3616126D8B5E592C4800ADA8C48A0714F76829B7F17E7F7D21A1B0D3ABEF944BE1933DE10525EE2D806CC404999B79DF13B331B879728A54B44B49FECA2B81BAD5CD2DD3ABFC3A41A90E5C317E97A9BFE0BDA24F9668DD41ABDF6D748C8A4A0491DEAD4128F04DFED7018201BEE663151CE339C2489265CB98CA51674B9E2B5481CC55FAC6F31254556029B507A036BF48B9F2F6BB3AD0AC34CB884E639FAC40470B8B097936B1852609B4EC27CCC731C6CFCC674C5913D6845D2789F8C747A30E571E30CE62F841653BDE8CDE1EDF9B346BAEA9D79AB941B654727C98447086D00B676B0E056D1D7CC1DB0D30B2972D45531E6951ABFCD5D4B976B9A5295864BC5292E09DD80F0B73AFDE358C8B4D643DC3950D7F15CD5525352B795C34EB024A968E25257C53B1B401D7124A0B2B4909EE9201E2481FBDEDA79F2686C310A5062E0AAF514AFD4F23A8F04399EB6CF549FE1EAAB0BA758E0698A669B67844C0054CA4131379DE2F33824616521456996EA56AA3C43C8B815D79C1C44EA7E9F48479668CCFF0032EF6ADE7BEAB42F14A9DA975490A693CC84AD416E7A2648F961E2E722594CBBAD60F0A52924121CB5289A8D5AFD6000973E25CFE624ADD1E90D38D9552AD3A9F3148BA57C54FDDAC5F759E130768B58FBB32A5E618A0AE296707C27E5B2FBC1F6A3539E91BFCA9B1E23E829A6FB7DE19EBF5A675512CB6AFE174A652AA642438427902B48936E7CF7BC62530F952070CC5278A6007E725C3B5684B0D98FA5223F15356976376DBEC75D2911879D0BE2719A4358F2AEA79C78A003BF17028FA98FD99697842861C2C1EA001F8B1F1B56EF0C7BE531AD740DEFEDE3686D7F316E80CD5BA1D53A3C2CC4060A6C405010AF5F899DA4A4E116A50253A9AEFB528370D077C40A54EC5BEBAEDE7686D7B3C61CE20D909E704C586C2E39FC4FBB12F270A6CC6D5A1EBF5DB954C6BDF2D550695029D43F5E74FB43554E7BDDF04B89E1331E20408FDC733EB787F2B02A2E58B8B8009A7D453E958511C531C9E55347F01FE3A4352F5118BAC4F5E2E43CFE64488C394E5EA70E9BDEC006F1A783F9D6151289B1F4FE61B2B752287042C73BF103F8E1DCBC0106897A75DB73F43E1780CA22E6F6B7E7F10D4BD48A9238C473F1263F48C38460554F9091B55ABD1FEFBF28C777CFD3F9844E678AA823F98070CFF5723D0DBA4F2B03D061E49C1949FDA45C9A337AEEDF6A54BEC2A7868EEF5DB7FC5FC2C61BDCCD557858B03FD42DBDB7F4BFCF0E061AA686843DD9BC7DF287D1C3599A94092B163FDC3F138C9C2BD8795BA51ABEDE08D6BCC094AAE08DB7079DBF0E5F0C63F4AE1A85C8D09E7BF9B7DA08C98AC0BE2E2500444091B5FF00630A264A903840A5F60078D61497AF87DE335D40EA09E5E216C1DC294A26E1FA7ABF41F4DE148D6DD5B6D05171016372AB029DE62449DBF59C0708667CACCFA5EA2D572DEF9C118A3306AA41432E48120A4836B9B5E0FBC6D37B63656042032920061517661CE96621B4EB1935EA6FEFDECC183E28140AE345424C120F024A9256A1B10A0653C27CF63B6C70C3172A648E032C128550B6828366D75894C0021DC6FD36B8E7F5893E59ACEBF2D6159457329CE74FBE3BB5E5AF849EED06D679C0A54DF885E6D88DC6E5183987F592268C2E392CA44F413FB83DD23E52F6A8DDE25E5CC09F9549E24D68CD53CFFCC513DAFF00B39E47AAE81CD53D9D14525536DBAFE679536254CA9409406F8882E711927BB4AA22F02D8B0F67FB7799E0F112B2ECC662D9C264E28D133C0607880608614009ADEB1B89095974D7705CB0A6FF006E76158FAAB14EF3A0A90E82D93F6004F101D36FC7CEDBE3E20C8913A610385441A00EC29F4E56ADDE91F59F118E9125DD490DAE86FF006B73715684CA72BE9969450321B4B9FF00CC2D7C30A236238C5A04ED3B1C4F617259D3880124BB12361D5B5F3615E55BC6769B0F21C7789003B90459BF3D5A346659A64F9630AAACD6B594388054A05C48D874040B11FBDCD8B0FD92C4CF1F24B596607E53AD99C0A3B781F2AC623E206130E5415350E9E62AECDA86BEC6295D51ED01A1F23B1A969E750141084AD5E28DC120981B419117DEF8B7E49F08F1B9C1E24CB5A58D5924BBDB9BD29CDFC389FC45F8DF8BC9001815A960BBF02C96B33B37AD772CC23AC3ACFDB12B96B769321A314A83294540712E0F230527D63CCDB6C746CAFE0AE2706B42D6851622852696E83DF28E1F8CF8F19E63C1733920B82CB51E5EFF002F1D76D4BDB8EBCCE8A5751A89F7D2A2BE065A6FBBEE42B70A53647174BDF9F3BF55C93B11272F20CD9292433F12013460E1EDE94D22A38FEDD6719985033E7278BFEE56BF9E81CD2B68A8EB739CEF3A714AAE456D5F19932F3C99044EC09DE76F49BE3AA65D272EC2CB4A3B99492033F08A11C9BDD6F150C4A332C7289563660E225DD458EDFDD61D7C43426469E72A882C650FB6AFFCC52AA1C571CF4E2F2E60F98F27389ED0C8CB292C2268D025012C756615E60B786ADA42E764C5466CF334A8BBA95FC91AB6AD48548D25999108A4EEFF00F538099F45183CE07C0DF0F307DAB4628006530AD1CFE3ADC3BD0087E8CFE5CD0C58BD49241F520B06FAF36852D692CC385C76A0329EEF8424171A4C9263FB8191F1BFAE24BFD6F0CA21012A49554B851E66C3D39439978BC34EFDC94101E85BA7D768CB30D179DB9429AAA32CC0FB49EFD904806F04A81EB6DF7EB8653F38C1AD6649242CEA50A6259EE4352D4859385C0CD1C4532EA4172C585AAFADEBE2690F5A734057E64D30AA94A5AA51C4730702D2AB054A6E93E1E60F0D8F989C406639D7E854132144A9764F86DAD6CF5D21B626661301592122CECD4622F46AD6BF7A43FE7799651A5DB396641C2B70A7856EA0788280BF8A09DC9D8EF6B622E463E76366056252A59249E024B002C0D9CF514AF323546768482134E747A57933D7C1DB56A8EAF37CC8D438AA90A71970F8D2A32A50E5C24CA844990244018B1C89F44B27800601A8D6F036D6B67DE1519DCB200501E2CC5EB6228CDEE91B586691C5216F952D959114E38B8812481712AFB5F95B7C490CC0CB04710068C68767D41B6946B0BB46A71F254A07840511BBD2F5F0D398B345A5A7B4E52E5684E6D99AE19580ACB185927BB800B9379B9FEEDE3D6299DA2CC2662E60952145453FBF841ABDABAFF815863889A998414A425EB4F1DB9FDD9A10E7DA95556FA90B3FC9448480610001174A77B81FB3891C872F993129529152410E2A3CC5295637F366CE6A37BF845339AD7F7F52F9AE7434DB5FFCA5E37FB51C246F6FC76C74C9197C844B96A44B4A94C4AC1A11B5E97F2DDED9E1E1153C3B58BEA7F930C748F56E6358DD1D1503952952827BF01400E222E4C5F97CFD31179A6351824B23852402D50FF8B35AD188BCF23D03956414DFC5B3BA865C7DF095B2C2928968A4788113CED756C67C8E2818BCE711899BC082A213422B6D6D4A0D7784E669E3F68E730D45F5D49A4CB406DA48290A6BC00804DE131BC7E00E25F299299A7BC9E1C83FDD5D3636E7AF22E634249A3D36FA7979727AC4442D4C970BAE2540901C4900A957EBBF53FB8C59952E4147CA8482D7A5B96963B0D2EF1903E663CDFC9E1C28281FCCD696F2CA25F093E271415C3732480A1C36DFA1E98A8E6D8C1872A12D40B39A1ADB6A9A07BFE4C6B164657A4725CA50BCC73A790EBE8095374A91F6940494F0A099320EE3CB738A54DCD264D532D642483F315370D767AD74ADDC42D2A6A50E09620382F5A93E57EA2F0B135FAA3533E9A1D3944ACAF2E42B816F1010148062656944D81BCF48C5731B8E9C14AE07984E9FBADEFD758DD7890A003EE6ECFB83A6AD489454645A5F4C334F5598BC8CC739502A5124ABBA7073201503276DAF7C34C3E231B3A6F0AA42F84D2C751CC396D6CD7B4305A8A892FD36F2F65A19731D675B99B2BA64B6453A13C2DA5A1C32361050013E7E7D77C742C9F2CC3293C4B484294CE144DAE4B28D2BA72B690D264B54C2017A390296E6435BC341B430E41936699EBF56A710ED253D2A9257DE9528B895CDD25571B5E397BB0E33DC26070E990254D4AA64C7F9501C820589492CD5A529CC424652921418B26E5C83E1FC52FE32DFABE9BC97C41BEF2BC5C2D456A057B4C1246F7F5F8E2224E0A628B5810E4004D08A3D6E45BD2350417176BD4B8E5B7A1F4864CDF3FCCF38EE997DC2CD352F10A7436AEEC10AB10AEEF878B6047145E4811898C26532A592B4CBAADB894AF9AD66E276F2B3D636330292E406D0DB7D2E756F015A4459C71B6892577EA5444D8F9DF6E7D7DC276560410DC3660EDBB696D81D4D810635AEA7AFBAC37B99BB4CFDA583C5CCF4079DEFEEB6E67A49C9CB8948012FB966D0335FD6F0DE7A0A8063E1D2D5FB75AC30D6EA1607142C2605A1511F0FF7B79E2464654A2DC487AB501A574BB8EB4AC35EE14C75B785DEC69A5493C8443731D44D150E250E70499F7DB90F3307CB13527292C192D4AD3EA7C3F98C890A1FB8172FEC445EAF50B4A9870081D773BF336D8DFAFA5E425654A7608A167A6C18354BEE3703CF412964870D5DF476D1FDBE95860A8D42D7FCDD89FEAFBA76E7B6C6D896C3E50A2E782BD356E5CB95BA3079213C3C4E18500ABEEF4AFBEB0D2FEA36D323BDEB7E2549BED161D7E76B6245193F100F2F95A8FADC1FCF5870DCBDFB3EB0D2EEA141301C9FFEA3637E5C5F2E5EFC381939000EEC9ADDB4DED7FC6B04225E7EDC1FE61F39511CFC893F324F3C3A464FC207FB6FE14B73A7BA410DEFE7CD9E11DE1E67ED91F71FDF9F25464C546881E1414B682B530E246B4A7E34F7E9AA6FE3ADFF00CC57FF00E457E78DBFD157FF001FFDC7F30E23919E36777543FF00EE1FFB8631FE8CA76E1ADEE6DD5E08528CF51B1709B5A547EEE21F2F7E30AC98D886B356C2D4A182370CE9300A5C2379851EB6B138426654514E177F06F16F75F1511AF87BF585EC6728FF009849E9C5D49F3B587BAF384C601418701A9156B3D39EEEC7561A39521C539B2146EAB73BF96DBFDF8D7F46520B259AD6F6FC818215B15EDF1020A44F21CED3D7F51842661D4456D63F6D7D5F94652A29FBC2DFADA5704116BC0249F4F2B0E76F761BAF0E0A5495241705BAB52A5F958DDFC5E49C404A48258BD0687C7F8FABC6F6EA87507FBAF7B100585EC3CBDC714BC664D8CEFB8DD5DD951219E82FE03DD2A21F4BC4A0D8B6FB1B31AF8D8DADAC3FE539A54D02955B40E115D4E4162482D142A03A1683FCB5CA0C0E206390E78595270F3A48C34F40285065814571519943E60C58B067E7123271001704380C09E6075AFF0036BC7BF3AC7B66D1FA494E135ACADD6F8BF969741937E84CF29B1906048C7CAECA7B258D5A920E196F7FDAA0FE83C4F531EF1CEBB7580085706312431FEE1F9DABB1B4757B5DFB5DBF5C86A9F4FA02035DE25C5226564D9264A790E9D37B63B1767BB0AEA4AE7492C4070DFB480696FB0D2C63887693B7EC17DDCF0407019635E43AEC7C2D1D5FD45DAAEBDD64FA9A554D4B2D3AA2375253076E968F3DC6E37C763CA3B1D9722524CC4A12C3E674876E76B695BB33C70ACF3E206378C844D5A81268146A1C9F7F48853F9054370F6719829D2FC90AEFB8CB7175484ACDC83CC7E38B7E06760B23491839299A411C4C86236D3D436BCA2A0BED5CCC7A9B1897FF00885973A58973F52E29C92BB4FA36851C7519B87D699259EE9627AA78879DA6D6E9CA6E5E6F89C6D25E0B80287EF6700F88DCDFC2AF1B8CCF0F313F2E1D24E8CC2B6D35B68D76D21A1CD6BA4E81696D8CAD2667C6A755FCC0911212A16117813F09C292F2CC66255FEECDE02BA049400D5A07363E760FCD2999868892C75BEDD2BBBB6F4168459876AF96D1B455474CC36A1BC14AF6B8DC6F613313E71189C93D869F8801E729955A24B7938ABE9ECB338CC52D8CB4A9AE4077DB4AFB1CE2BDAEEDFABDB52D287596D2926490D2605A2640F88EA22F3890C37C2C389502A9856D5FDA4B750E6BE7D1E1D61B28C5672E161496620170FCEF5B6ADAF843731F685A900977326DA039A4208DB62523CBDDD799B5603E142920140528D4905045056CDE3604D77874AEC74E92FF00EE1009A51886EB42E7AB8A369100CDBB7EFACB8C0FAFAAA5B1C657C2E16529B5AE08076DC0B0F22709E61D959395A4A66A9285D8829009E8EF4E5CEF1A8ECE62921452A5280AB0734EBCFEE41BC4F3B2DD59A9FB4BCE11419526A0E56D2D3DE3A9714A6B845CCAC9E1DC1FEADE6D7C736CF0230A0A829013BB25CB1664B3B9B7DC434998799875042A694AB4049A1A316704EDFC476FABB3CFF0F50AB4FE584A2A8B694D7B9DE71C92014F0A892266C4249DEF7DAB581C1CBCCF10578850013FF4C287EDA005EEEE2DA588A40AC14C989056A25DEF527CF5A1ABECD1515467148DBCAA62A2ED72D478944AB72646E623DF318B6C8C830F2C02569E1BBF981AFD2DD2B0DCE5938170694AB1A8D2A2DA3741D23706DCAF7A8A9A991DED792AEEDB4DC2A6E66011617B8D88F3C63112F05212409C800025DC1B03ABBE9AD74E9AFE82671001449E8C697D7AD0B7A87B7F28D3993E4544732CDD4DAF36E12A452954C2AF7B4A4181B102F8A5E3F138898B230C82A92927E70E3A535EAFD378789C1AD20294B246DA8A01A5EEDE0CE22BACEB573CF1ACFADA9490084D1308F106D3B1FB13B8BDF7F8C4CF65F2D56625467A3F6915533EBA9BB336EDAB340A32A4D0CC0496A3B9BF3AFA1881566A25B74A43A92A75C308812A99816BFAC799C5C96309971212B438FED76F20CF72DCBC28A04952428541D7E9E75FADAB0F9A7BB38ADD4494E699C2D4CE5E921684AFC1C693720494A8F2E477F3931B89ED194132A5B296A042529A8B6A459F991EA2123365A4B15007626F7FC74E7168A6A72ED374668F4CD232FBA94F0B8EA8A0293D482EDCDE763E5CE0577103118F5257892A72E529721AA2EC454EA2BF58732D132601DD825F502876D0B5EFAF237AD734A8ADABA89A9AA5ADC7092E3409086AE6C9E1F09B1B91E5BE25B2AC9A432A6CD02805E8ECEE0EE079BC253A52D052160A5ECE3F9DC74BD617656DA8A85252216A71C84850429504DA660F53CFE42C9E2F1185C1F1095312549B80A17D0BBD6D6D3EA8CC065D5747ABEF6E9E9F58B032DECDFEA4A39AEA1A8029DD85B2D12018173C412411331045E0E2A38BED5AA52952788D1C392D7722E2A0FE63596D33F655B6D3C36D983562734F9837DC8A1D3F40142380BE940213CA78949BEFD794623518A4E378A6AE6710350E77E4E6DB39A6B1998B4A4F091C2545AAD5A3B6C2A3434A3DE36D1E9AA3CBCBB9B67B541E7D10B6698A8DCF310959102C208BFC31178BCB06371084E1A61E00FC6A14096A8D6AF57A7833B33C515A0029716A8D7E9F5B0A8611AEBB58E6D9B32AA1CAE91BCB291A051DF24B60A9239FD94933C3313BEF899C064986C214CC9FFEE2B73AEF434AFDED0D133575150CCE29E429D2B70FE706A4C9B32CD2B1D6689D5D63C149FAD2DC909493241415CA4DB7E13EB737B14CC56598792FDC21C0D05475000724599FD21CA160B82A1BDFEA7CAFD22CBA0A1A0D254E1DCE50876A0890810BBDCC4A245AC36E700E2AD9863664E495E102920B874B87D03A41715FC720E5065A4FCC43806C41D8F4D79BD9CDA23F9CEB87AA5484D2D3A68E9FC4105011FCD02D0A80088E5C5EE1318C64985C5E2262953C2D4090DC4E48E94A5F47F178618C9B2C2992B751A000B123A7B6F07887D5E7A5C3C6F360CDCA94B13BEF1CF6E5F8DAE585C192689D589FA0B1BD6B5F0061B9933420AB84807521FF0087F17FA447EB73E652905A792557949504F0CF2127C899B49C5870997AD4C384814D2A4935FE6EEFA330D5089C43B384D8B1A3BBD1ABA9B52B101CDF5496F8A1C0627FA80B6FC8FA6E7EEB58246553385F80B51BE5D29E36BD34A42467252A62B0145831F16E5BFB3104A9D56A755FF140E136F10BEF1B917E53EEDEC6C183CB0949796F673F6A73D1FCAF0F25CB2B62490E1DD9DC54F833D2CEFB445EBB51B92A3DF0B72E31CFD081F9E2625654A2CD2AA6D4361BBDACCCEDCAD0B19029F35AEFA74888665A91C2A402EDAE6CB11F7824F3E7EFC4BE1F2B98C0196CC2B4D99F7F4F38D44820B3B0F7CDC9F088BD5EA35AB77A081FDE09336D81FDF5BDA465656A0C44B735D1A966B72F7AE5586AF102CF62DC98DCB69AE85E23D53A85DE4E026E7ED475E84CFEEF7C4DE172DBBCAA1D83FF00FB7F9AEB511B09640147275D76D74A35294B986A7F50BC2DDE4DCCF8891CED73E6791E5D70FD3966BC1E9BEEC0F3E7B178CF028E9EC7A7B1B874275039C4AF1CEDCC7CEFCF0E519726A0A1DB71F753728381434FA7E634AF3E7099EF08DCEF73E5BF2DB0E13972187C9C8D016F27F483815B7A884AACF56A375931CC2B693CFDFD3DF8C2F02948FDBC2D761A0A0A836F621442141C949D3EF1C7F1B56DC67AEF68EB311843F4D2FF00E5EBFCC1C497670FB4033C5F270DED3C604FE3F2F96373824B71105AF51F9A42810A21C0710A919DAEC7BC2473F10178E7CB9FE58D5385973094A594D46BB574D746A0FAC618BB6BE10A5ACED6A27F983FEA120499BCFEE309CECBF87E6200480C5C33BEEE2CEFB3C6E3E43F3538980F53EFAC3AB19D2A44B824EDE2DFE7E7F7CC6E19AF06548744BE2A35001EEE1F91703585C4B5A83A524F4F7EDE1F28F3852F8897072E7F2DCCDFDDF2C436324F700712784A8D396F435F2DEB1AA814FEE0DD61F98CCD500F18F5E21E5E639EC797CB117FA79AB2549415234228FD2952F52CF0977892581726C07376D46DBC3E51E653214A06C902E0FDA1E5BC193C845BD1A9C2198A0B52486771B1D76F7CE349A569524B108A574E7EC08764D428414AC137240222E041B7974EB718D664A49490A48200356B68FBBFF9E70B49C428D2DA6EED52DFCF833B43AD354ADCE249516E9AC5F7044A4FF48091E2326D6DB9CEE2B98ACA2522677A164A892A096D056F6A1E8FD686564CC55DE8343B86B54FB6DEBDD07F2A7EB966BB51E68B78995AD25D5113B9B0599BCEDB472E7E6F464597E1788CAC3A54117FF6DADD534E7FC3C6ABCDF3458FF7315354FA712ABB0725F4EB5DA1A2B750E92CA94D37474C2B1E1C414AE35A4A08D8DECA2623A8B47338778693C7300972C4B492001C352D46259EFB986ABC5E22692264C511FF00A8D5C5E95A7AC46F39ED12A92C292D25AA66384880947104C750028DFCFD2716FC176566E2D940A9054DA16ADF61B16FBC32323BD72A0E75700FD4D77B52298CD7B44A36D6A51CE9548A24F1A1495381DF20552940126E3FDAC69EC4E270252BEED5890B63FB2CC694A8FCF3786D332B54F520CB1C201B8DBA1E6CD5D62AFD41DAD65B468529354DBAB0492B2E804F9F093607CF963A3767BB2A7112D972532980705007D40AD35A08B5E579384201980A8D3A790D9DFC2B14E673DB930E3ECADB5B95350CA5D4B0594AD5DD29C0526528078A7948E56C48E65D93C1226C84F7D2E59E2A80D70A17636A72AEE6A5DE27052D2582343A01663EB5ABFDA2AD7BB48D5CB52BEAABAEA976A164A58348F2001C5207196E0083126398E78E9995765B2E19795AA6C952932C70A8CC4248201AF0F103FE1ECD19C1CB44B5FCD2D240342C0F3367B3E9D4421AB63B57CF9756E8C8D4D53381B97175CCB5208B1E12A4949EA2079F5C46644BC164B8D9DFAB216852FE43C25693C2589F95D88BF9178BB607F4C8427BB090A57EE0CCDA8AB7956ECEFAB4BBA27B48AAA734EE5336D33B92ACC1827726092E037B8DFD31D025768FB349E29AA2A134821291216C4B14D592C295F3F04F345A5212124352CA0DB55893ED891689B766DECFDDA4F6919DD26554CD2A8A868D73985621E6DF4069638941442884CA0280BE3CC1F17338929C4F7B257C1296A2C0382A721B84382CFB0B448E5C70EAC24E2A092A09BD284397D6C6F67A8AC7A7DA732DC97B11D3597E8CD2450BA9792539954777C4E3AA0429D8717C4A4DCB9B28C0F28C732C0652ACDD2AC5E632CF73874954849510FC42A48043EF5D758E17DA5CC38735484CD1598CA00528A037E571EAD0B17574798B952FF7AA6DA2106882B88A90E11FE638D47C4A0573F6CDA60784E18E132F3FA99812582154140E03D035D9BC46A6F12D9866024E1B0E65A5C902DD2A7AF3A6A6F11F6B2319957A5145C55554A5C2D494A884A64026448FB26E7CB7C587198708C1A953A67720268A26F7602BBE839C62566A66CB09EE6AD550D49AEDEB6D748BBE82874FE81A46B32013559F54B6A4788A8FD50A93DDDC2894F882B9C4103D31CA55226E231AB95326A9520AC10AE2FDCC5EC0D3437ADAD48C2E7CDE207BB2923400D1FC3A78F898ACB39CD5D6C56875E50AE9E342F8E5203B2B03864A620C6DD77C752C065B2A64AC3B04AA5AD2C4F0B31096AEB53F4BEE86231844B50E0341CEFB6D5FAC4332646679EACD1D0D2386A9A59FACD4AC12921C24A080B1C161CD24FADF1B2BB9CA933921494853948000239DDC97F6CD151527158AC424A4AC242EBE63A73FC345B796690D3D90B09AFD50A45555C05B68BC0526F109907E1D3DFCFB1737118BC4998952D48E3372AA5580772FBBBF95A2F5875265E184B27E7296A80F47D34EA35F44B9F6B2A8AE0C50D2B41BA06F8D14CB6CF006D077E2E10999B7DAB75DB13D95CBC261B8A7CC03BC980099C5524A4101817029A8BE9568AD4FC1E2A6CFE21C5C014E1BC4D34F77A9784B8E3C1F0DB6B72A9D70C70B7C52924F3299D846F3D622E5FCEC5485281484B519A81AD7F3A5045EB275CAC34B4A2704B902EC7424FE3E9BC58F90E81AF75BFE259BBA9A3CB602DE715C2A7109DE128FF88B9D8C030664E21339ED0A30F2D586904F785268976700EA0303AFF22233B438B44C9F27B9E1090A62D5A53C6F5DAEF6898399DE9FCA194D1E94A0EFDE309566DC2A52F8A409FABAD2A32488B72BE39F65AB9B8C9F34CE9C4A492482AB55C7CC4D3D3C19A1C66186C24EC24A2A9C996AE0A92D570FBD74AB0E5A339655A673BCD07D6F52D7C65EF0E26B8949417920DC774950537C361B49911B1C37CEF0CBC54F1230C851EEC8E352412002037CC28AB5DCF50042DD9CCAB2CE19AB9B8D965C5124A5F5A371120F2EA7585359A8E9B4F28E55903086A980E15D42871957532E5F73C8EDE78B4E51D9996AC27793D4AE34A5D280EEE41D9B9162348AF768A4C9938B47E9A7A540289201150FB8366A5F95223158F1CD1C52A9C3B53528238D0952F856A5ED00022D3CB7F29C3695227E0674C13414A41F9490051B525B98D2369C50B912C149058B3D74E61AA36B73A3C8B25D159916C667AA6A92C65691C69A2942145226CA285070C98DC6C79E1BCFCC4AE67712945531F404A438FF0090A1A6C74DE23BBA0012452C2F5AB3D6DEED78DF5FA8F26A40963226C36CB414145208593112A52BC44C89B9C38C3C99EB09131454A2CEE1C1F3F00F71F56137E42A2091B1777636F7D6D4101CDF55B8B90B5156FF0068CFDFB79EC36C5AF2FCB52B002E502555228CE395BF35B4305AA6EB3157BF9B0BD2FE3E1100AED4C9511C64240E28D87C36F9F4E98B7E0F2B4253C294840236AE8C6C37D0FDA23D52B1137198758528252A0540BB2AA3C3ABC42B35D4CD99977C239050006FB41FC39EE312B96646A52D4E93C2F4241E7607E9B3523A6E3F1386958194C8485F08726EEC1EFA9F0E9726BACD751B6784A5D2278A7C647A7300EC63D2D7C5CB099294948E0F9410E0A76B7BDCEF11996CF958B97380482A4A5836E41F33D0D6E62BECC73D016497491267C66E26799803A7511EFB449C0012EA803421BD34BEAF6715B452733C24E46352A4F184859A6843F56DDFAD2B10CAFCFD2A20A5E3CC471458ED3CCEF6368E932313380CB93F334B00534A8F4B8BEB16F12C0C34B2470AB87CFF00C9D1FCCB3C72AB3C041FE7122F038CFE727F1BD8DCE2764E5E0542075007833D3A8D28CD68D00510351B5BDBE86AD11DADCE92A2901C2626E556B8DB97DF389291800E494826971D3D4E9A52D0B212096D05C75B577E4F0C2FE6E9B8EF0C8907C47EFB8BD80FC30F9182096F901A12C45697723A3FD68C21CA659507B253B877360DD3D986E566817B393BF3B01BDED249F2E7F3752F08003F280C6D46E9BD3FCEA61544B4921C13BDF6E51A1CCC904005C1CC8827F318553866D007E87DFA9BC2DDD207F68FC7B6D6B081DCC900CF1C5C8E511F1BFEFDCB0C3A3500F4FF00023532050D4036603DFD3531ABF89A3FE67DDFF763612258B068D7B81FF23E5182F366D304AF6E7E667CE22206FBE37FD089E93F2920820330E7B6FAFDC08732D80EEF878B8A8E0506CFB0D2E3D04708CDDB5184ACDFA9B0F53F95C93388F3D9E0999DEA945DDD9B47D6A7C2EECD08E2BB3C427BF132AAF9C241AB01D76E6232733147085779F3B9F77CA6FCB71872BCB4CE0100708662406BD09D0FD39B5619E1A64C4FFB2A964B1E106951636DC55F42F66781ACDD04C0548039288BC5BF1EB6EB8424640308B334AD4A51735A00FA5F6B7D7589BFF4542657EA0CC0EDC412CE6AE483D3F9856C57000A8BA46DB133D7D48F5B8C6715844E29065A2E2F4B3353404BFAEB48ABE3A64D9B31294A58254D66074D28FE62B5B557B79924812B320F3511F1826E2C6E6FEF386D86C0F7482820716A2AE0396D2A3F1168C9CA12825601F946BAEE5FED7E6D0F9439A24260ACC7FEA3D6D6F758CDFD6062A1DADC02D430E65820F128A881CF561D7EAC62333A50AF754D4B56AD43F4F6D0FECE6D0532E1B40B289036FC87CC72C39C0604A7088F943B397DF4B83E15D75884CB92A5CC2555622E79EA2E7F160CCD25A4CD53F694E9D8589DBCEC418DE399EBBE19CDC2B4D989090D4F3AFABF96D58B062A48084828D9F57736FA1A75DE25F9766A92412EC8B58C1F84FE5F9E22F158321D9246DE7BEFEC0AB06A895F351343CF93EEFEEA369652D7B6A0003CC4DF7B8F744131BC7CB1018AC3109502284353DD8EC2BA8A43F961980B0B8B6EDCBA6DEA7B219EEAB6E95A5FD62B0F0806C571EBCEDF87AC1C72BC364431A383B8097A12C1ABB9603936E213329C38A0BFF817E7B34509AABB4FC8B2921C6EB5282AE3E200970A88D801E254CF48FBB13384EC54B94A0B52425AA03020D5CFA7D1ED1852284804DADA55AAFBFBD5A98CCBB5ACFF00523A6834D52D5D53CB3C083DCBA841262095291C31026E408DF7BDA70E8C0E5AC26A524A06AC2DB780E605232A94A007C8DC562EED67A7F35D233A0EC93B5CD48976AF515635A7A8442D9529DA6796F21775F842C2D25201DFDD87A3B7B9660D6654AC08C42D343721F467497A11AD76891C3144A523BC20F17200FA8FB574A3337E61D99766590A8AF54EAA566D5693E3A5E07D94A9437485A16537DA45B99B4E2532FED1E6F9DA972B2FCACC94AE9DEA48F945DD8A6BB7D22E9829B2152E8D50DC3EEE3E9F46AFF13F649A51B7579369168D414CA2A9CAE5BC5C52365869DE28F3040BE37C4762F3DC462A54EC4E2662F88BB04B04837143CEEE6C4C31CC70A99C7FDB04390CCF770EE6FD0559F68ADB3CF683CC909AC5E5E28E99B69486E998FA95328A78CF008516E7722E76BF58C5F51D91CB30180188C7198E99654B3DFCC40E24A5C538DAFCBAB5838CAB26C4CF530043B3029A9028EF5EB6FE7BE5D867B04FB587B54F665936BFD1144AABCBF35EFD65D69DA461BE14BA529E1515A4288023C33067AC63C6FF0012FF00A98EC8FC38CDE7652BC5A0622528A4CB215319AB555454784770EC87C1FCC7B4B2FBC9485814F980671E8D51FC459751F429FB6CD45452B4F65D54D31DEA4BE456529051C60AB67B98B48EBEFC5070BFD73F64BB95A573D05C3026517773AF07BA458B35FE9CF374AD053C6F6142D701D9F5ABFADE3D1DECBFE8BAEDDBB30D1D4995E4795AC6639B3406A2AB5BCC2DC694CDDA8EF16A32A25425044F4338E2BDB5FEAC7B399EE6527101626092B265B9525290A6770C0286DB1DAD133967F4E59AA3018842B8D948621AA684DDDE8F60F6D68F49EBBF649ED5F48769DA6742E7D95139CEB535634C294E324BAAA26B8EAE405148DEDC660D809938B8647FD47E418ACB674EE20512509EF439B90426C059BABBC79E7B4FFD3AE689CE25A5D65E691FB08FEE6707E9A3D445AB4BF46CFB42D49425ECA96D0A920BA0394E4348DD3052ABCA6F6F43B628B3BFA9BC9938B5CC1352895C44035B24B7ED6E46F78E8723FA6ACCD78592172D7314100D53472295FA9BB7888B7B25FA3E7B5BD1D4119564FF005DCD5D480B2B5B03855104F8C916079100C5F0AE69FD4A767333C2A513310489696484F125C9A87600383BD2D4D636C2FF004F58FC3CE32D724872CDC20B8D03D7DF9C573AB7E8FAF68259733472856DD3298A9AACDA5C615DCA699B53AD0482A9B84C7839D8CF3A8E5DF1E32C9D984A0AC50095CC4A5142CE4802CF476BB5EBAB4BE3BE044FC2E11734C83F2A492E8B53EBAF2B39B4744F2EECD7501A8CCAAB523BDDD0D3551A7714A292AFF2EF29920A428AF7411CFD71EBBECEF6E138BC04AE01C4B9B2819600DD2FC4ED4F2D3908F3F768BB1C8C04F54B5B009514970D50762E7CC7D627398E63419027EA790D334964A10972A470852884813E283636DF9623B1B8FC5E2672153D478CACFCA280026D60F436BE94D6B53728918596B52784FCAEEC36BBDCEFE1B56203579AA5F59FAD2D55255B24491799802474D8751B5B173C065F2D7850B253C5C37200D9CBF56DCEFAC51B138952311C01C241621C806A1ABF7AB6BBC2FC9B4A6739FA9C396B4A6B2F4149AD5BA9EEC2127EC96FBD00AC58CF0131BF4C54B37C48C24E1282C3AC901296502C6AE4394D09201009D00B45C30064AE4B9090403767B0E5F48B532B4767BA3592D102BB3822E9521D514B906627893BF4076F53886188C66266097DEF75243712A84A86A286E6A09B51E915DCE731FD33940248240009607951BA73E6D1853516A1D615AA7D2E2B2FCBA9552DAD5C21086D7BFF002CF0F78142C2C626D18639B63158541938792672A6063303922E2AC091D7AEF15CC3663331934959258B81A07D68D600D0FA3B89AF0698D2D4E56C5334FE6FC278F3499471C183F5720A01E5B743BC1C4365D819C95F7D3B8932D45D726A14AD5B881A35ED53A6CEF33C262B3195DDE1E72D2A01833967ADC569ADEFB88ACF33CE2B3317D6E5456283DC47EA8A49E04BE09F100DA4A528E110088E5318B4CACFE46101C3CACBC84964925D4A0DAB94B91AD7C394060FB2F9CC8529671B3B84D59D41C07A5FC8D3D5A0A5C83526A501971AEE196E097C70994820CC88B408DE60C1F39FC267B83C220CE501C4A0590FA9B86D0BEE2FA343B3956324CD42E6CE5AD94092A2FAD6E59B975E5135A77B2BD254EDB3488455E6CD24F79C5B2957224AA5361F740E78AFE27319B9CCE99C492251344F0B1AE8EDCAE0DFAD2CE71495C9972825949001377207F1B7E62079FEADACCD5E2ED5552997D3B5189088B08E2042222E3A89C39C1654785294228F43725DCDEEE1FEB5308124B925CF3E7B69CE20799EA4A5612820043EA90FA7886FC8CDC13CB9F9EF8B7E03252A524A935A55BC0D5C3FF30D4827881AD68F773FCF8DEF15FE6DAB1A1C44293BC0F101B9F2B8FC63D062F797E48470B259AF4FAD74F65A1232DC07152FD1BAB50DFCAF48AD33DD521CEEC36EA418513E21279D8137B6F63E6631273302A9588C3A384B2D55A74BB35C1D3A8112D9765C898854D203A6ACDB68F6F0B6A62B2CD753B8B2A0974285C1215BC7483CBE5E7B63A461B2F9186972D53120384DC35C36ACF43CBAD0C46666B9B3C2D087570529CAD61BF3FBC40EB351BA54415CC722BDA3AF3FDFA9167C365F2972C2D0010402384392FD1F573F8A46BD9533533D52D692C540317B3DAB7BB50DF42C222798EA074951EF02A761C516DF91DF636E9B6109582519CB41140450587B6FF348B567995210A93338402AAD03EDA003DDD8C44DFCF5D244AF7079DA7EE9371FB8C5AB0780EE9344B95004783BBD0BEF7109AE4714B4252C03063C837D3D5A186B33C74AACA2520112153EE1D27D2F7E5B4ACBC1AADC229C8F4D05858EF51D124E1406E2A91AF95181E5E3CA19979BB8A90A5445C5FC8F9C74E62DD36C3C460CA4B101EF4FAB51A95DFAD4C3A97877341437A7F3EB0DF519BAA6CB85007FAB7B7AC7422FD075C3B4614901869F96D7DEFAC3A12000346BDF573BF88AFD2A959CD5C5154ACC0E40FE33E44EE4018752F0459CD01F60D6BE1D616461F4097D6B46E752F4FBD0462E664AFEE5DA62F1F8DFDDBE161826B26D46625C697FA53D046E70E59CA03757F1BD3C5A123B9829444A95F133CF19FD116A20F93FD49BFA368F5C770FFD8EDE2DEB1A85728FF52EDB9981F3FCF18FD1285D247FFA47DC08C19005E581D7FCC62AAA539CC9888337F7F23B7C2FCE709CCC44BC1944A586E270E457F1AB75A68D0BCB4265A492900914047A83A50EE2F7BC02ACA08014491B9076E77106F1D63EFC48A1099C90A0C41A8E6799A6E2FAE9681299D354000A52491462CDD756F61E35BB982D447888BC448BF49DB9F90DF0D1139026141961206B7048FA0D776F387F3B2E912A57794E221D98120F9BD6DB73856C3EA4A544ABC46F79F8F9EF617116E9853152D465ABBB62520B10D40472F7AC442FBC532524948705B67EB407939FB70ACD5482471F0DC820AA0D89E46E3DFF007401179361A64C9738CD4170A277B13E54FCB40BCB810998104F139701F913B52CE2D0EACE66B21104C9DA3981B91E97F3B79E1A6608561710084FEE34DCB03777D3C29A3C3544B5E1C28005B7D00DBC2961E20830EAD666E20825563E640B4F537F873BCE1BE232F4E3D09F95DAACCF5FAE9CFD68C710833ECE6C4DCBF81A79EDD19EA97355909E254CF98DE663CFD26DF18D3F41DC4B292914140DBD35D687CFC94C1604A5567259CF2AB1A8B575A8DDA2434D9A2B652FED6C26F6EB11163B5BE2710EBC110B52B86A76A86B0B1B736DC6B594C4C970070B90CD5FBB816160695A0897E599A2E5202FA589DFE307F1C4662B04A20921CB5473D77E85F9814868249492FF002BB102FEB6F7B3458393E64A58582AB2787FAC1FBFDF7E5CE3158C661BFEC2F5F99ADE15D7A575AC2A896439BD9852AC4BEB1AA95BED3BB4FABEEA8D87E8E8DC5417950070C6F0A026C3CEF3BE2898C9F86CAD049280946819C54B52EFF61E6A892AA0B3EDA791A7E62C7A0EC034D64094661DA0E6C9AD7C80E53305C20A08BAC10DAC83E844748B6206676B26E2499584415D6ABAA7836A1BBDAFD79EE24F0A5492C4534AD399AD1ADFE21C337D75A5B4C512E8B48B5474CA690529714CB6A5981B853A8E29F7CDC1C3CC364F8DCDC714E0B592494B3A58DAC3E9D7A46BC0EE52E0747B5ABA30D472B475AF51F6C59AA96F2330A9714B54FD58A1E5251CC2A1283C207AF96F8BFE43D84537793A4F11A28F121CD37D69D4EDD59CFC3CF5AD250E438AFA5B93781A36FD6DD55AFABAB5E73EB4D2DF4A8F857DE1B0246F17239C4F43EBDA7B23904AC2A4A512932CBFEE2069C8B52F5163CAD6DCA708B0904A8956A2BA695A3F5A54ED15C6639A3CD394D58BCD3B84A43850C4779F68006402608F39BF96D7D3819331425094028302A34E27346068D7A5A2DB86C38580172DC9E16511FB18EC68417F30D488857EA6CB154F507EB1F58AC514F842549248513204401CE7D7A62A7DBDECC77F92E289C40C30EE54CAE2BFCA6A5886F16F48EB9D92C9F0D3D72C280D2AC391A5F60DA72B47E80DF413E62DE61F47FF0064E92D04BED8CEBBD709971415992C2428993610624F4B5B1F9B9FEA872F9B967C4CCF659C519E81353C0B27E5A26C1C90EFE7A47B93E15E5F87C160125084A8D2C91CF46DB773473B47B3A0212121490BDE2C3CBCA4F203D27738F33489C661583352E08A3B372BFB6DE3A6E63DD95A099009E497722CF46DADBEF53AEB94534C5688111E1005EF1BF972B73C45E284C9988969188FEE70CDB8D8DFCAB611218432C4951320370A87084835E122AC3CDED48F25BDAB2B6BBFFC5E7B3204B24203FA9803C3B4D322796F020FC71DE3B31842BC927A913C02657CC2F50926B6E82D51CABC1FB50A9433843E0C319AE0B3595436D77FABC7AB54E7868284A129054C3455E1927C099E53F198F2DF1C2F379B8C958F98254C51489847083407888D7DDC476BC8F0D859D97CA54C9284932D2C0A43DB524736AEBBC2E14EC8325092B804D85CC5BC85B903EE8C4A499D3D5201571061B9A96F0D796BA188E9D81C01C67089681534606CE76DCFE221FAF1B791A6B3BA86929E16B26CD14E3600F19144F70DE0C41BC5C6263229AF8AC3A66A8F12B1128A0D411FEE0241B1F173F730DDB6C1E1B0F934F9D2A5241125668904512696DDFC0C7C74EAAD78F54E7BA8E85D2AA7E0CE730484892920573C36063D3A5B9463EB17C2DC189F9560F8940FFB32D9D8FF006063BFDC9A88F8FF00F15FB55FA4CE3112C0349CB000A37CDEEDE1486BA4CA737D595F4F4F44DB8780F0F72A96D3565C8BF784009E1113E2C745CE30586C1CA56257313FED8E23C243F9024B1D5A9CC473BC1E74BCD148929155B301FF00736BF6E717552765234BD3B75F9DE4B505D653C6DB050EAD92A5899FAD2525B3C8DCF5F7F3F5FC43C221472F958D4495717013C40A85588E17DAACC0EB68B3CFEC362E64838B3216470F1F10496B3D4FD47942456619FE7B52D653434DF51A7A7E24B25A42528602A64ADC484A5E9E8A51E1B6D189B09C0FE8E6637BD0B9B39214B593C5C647ED29492787C39C73A9D8D9F84C5FE94B8659480EC4176F176B7D3495E4DA0E93295A733CE72F7350D7892EA69D2E28B4A3211C4194AC1DC6F698B6397E6FDAC95809CA9499E996A0AB93A38DF96B70E6F17DC0F62B159EE1FBD44952F892FF00B5EFD0381C9FC18D63BAA6BB33A52F36285DCB929FF84C10A6D6DA0C9F1029413E188E2FBB1D0BB199A65F9C4BE35AE59596FDC52A0A7A30AD35A6B15ECCFB233F20528CF94521C9A829147D2FF626FAC41D9CE93528465C285FCC2BEB894B496CB8A51524F2080A1CC4DFE76C5833C9596E5E8562A6E224C99680E949524F16BFF2046F60748D3229189C4CDE091215398B3004DF981A0EB4A0DA27F94F6579952B4C669AB296A68D2EA92ACA2816CB8555414A1DE0052906DE1DC1EBB639D27B7B93E2272F092FB92CE933810784876241BBB72D758B566395E6D864248CBA77090C7E45077F0BD28D485FAF2B339D26C50D3D2D3D569CA5AA491DFB94AE3A1C4881214E204483D441331CF1BE1E6E0313350B463E54CE253F0256950AE84051DDAA2DA4404ECBB16A92B33B08B96C29C40D05DEA01B7F9ABC52BA87508CB5483F5AFAD3AF24A9CA82384AD452083C3B02276E73B6D8EB192659271B2E5F772D20331501C54F01CBDD445352489D312F54A99A8FE1AF3F08A773CD646566403C8CF999D8833CAFE7B62F597F66CF106451C3A9835F636DD85DE1624E9E5BFBF22D5D08ABB36D53F598E2708E19BF15CF3BDC7588C5F703D9E4CB0974D5AA1AB50CFD4302F4D61CA5254453AB69D3D748AF735D4083C52E1EB1C4479723BDBA7E0459F0B94A5000096AD9AAF46A9F51E5A0859325C907A3EAFC86BA7BBC12B73F68B88594778A01690F178A031C40832926153CB7239DB1B4CCA0CCC5E1D610084A9DAE28DB126BF8D5A27F0004AC1CF0402AE1B9069422C76A5BC225DD957613DAE76E4C6A66BB23D3CEEA9AFD32AA75D586AA50CF748AC2A578B8C904700306F611BE28DF1A7E20657D8691949C7CF460A6630284A429871776520B10D5F017D5A935F0FF00B213BB4D371E65CA54D12880CC4E86DE5A7A5E2A0ED234A6A9ECCF5256E92D6B96AB28D4D96142731A353E1D5214E242D01412400384F2DCC1BC63A07C21ED3E1BB5F942F15879A99C829470A8317770C0FA59C6ADAE734ECA2F20CC528992CCB06654314D9B5F3E5A456157992493E2DC5AFF0018F5F2F3DA71D6F0D94A44D9930A5C1219EB6B7AD6A5B5BBC63B440A9186421AC28FC853DD7EEC6EE6095ECA262473B4F5E5D45883C84626E5609291448716E54DDFCBFC4472243CA4921E8ED5E5D1DF52417D4B59ADEAC02615D64933F21F77A83E4E9184A82534B966FB9AF56E70A230E285827A56DBD6FB3F5867A8AB4920F175D89B8163791E9704FB8CE1E4BC182430706E763CAE6E21D4BC33800077D68D47AB1B7BAC372EAC6FC4608224EDD391803D7E18708C154B80E19DCFF3434E7A43A1863F2B33694F47AB1A7836CD1ADBAC4A64F11B98DF90F79E7875FA5E160DE94A575377D7F98728C2392784BB6DCEBAD2BA6958E175A08038E7717206FBC926FEE8C6C9C3D4FCBEFC2BF6854E149B20BEAFB741BB743091CCC1488EEC933B9E5E5CCFE07CB0A8C3B8A8D742DF5F41A78C6461535E2A7D69E3CCEB78D5FC51FEB1EE18CFE993AA5FA91F983F4A8AB971D2B4B5493E8D0E1495DC6CBAF39501A5330024A67BC0B3004F2F5F7629FDA0C1A5536532C4B636B95390481A3F87DA18E230C7BD972D128CC4CC77502C11C350E357BB3E94A9A6972ADB5FD692D3A9A3701680A92A0E719598F0B64C6C48D8F2E58C62E72725C21C4E226F04A4A38895960400F724742DB30D00E83D9CC8862F0DC265712D88059F90637B30229BEC0595A6FB32D55A9F2ECCAB729CAB32ACA3C99943D5D99268AA4310E24AD04ABBBE048B45947DF0239D4AF8A7D9AC6E3D3814E3F0DDFA97C28477A80B2A70FC20A9CB78DCC2799F6233390B33132D66597247012002F5D74E86915A8CD2B5C72A51564D1AE956A69B70A78CACA1452A1C02F3298163E831D6A41972B069C54C295485238CA8AC335DC9A7F2D6D4B5C1F644CCF9420AD6A241604104E9677E4DB44F74B767FA9F57E5B579B655A7B33CD90C20BB595C9A5AA699A64B61452A24B45A5029178200FBB94E7BF18BB39946612B2EC2E370C674D982594098877E262C389DDDFC9EC4C4F0EC2E324CA066CB522500AE005069A9A8A914D6D5862A2AA4512E9DDA9571B8D2AA1B5B1B290A6CA9041024CA488BEF1E78E8786E1CEF069C62450A02D2A1FB4821CB69C874A450F39C957852A48B28906837FE6A07D840D6726ACAE4F025B24A5237B93631723DD699DF1A6580778B92AFDC0B01D1DE86956BB5DCDA2BE32C095213FB9CEDB11D79B72F0872A7AE91E9E67EEDF6B74E73D5FE2B0CE8259F930EB4F643E90F4E0061C0570D5AA6E3C5EC6E7D22434398250492A2640B93B46FBDF975FC0E20CE1DC9252C4934059BDFE68290C8A4CC253A0D2953B8AFDF9F496D06669041E2BDA21476F8EDF7EFE586389C30AD03D6AD4BFB6A168D152002771A558F377FBFDDA6995E6A94A95E3224833C47CB6BFE43CF6C55F1984624A8380E053EB4D39E90D94185410A0F4AD7A731EEB48EEFEA4D77479252AF2ED2EC314A96D250A791DD83000BF88024983B6C7CED8F2FE5F2B159ACEE2C5256A5ACFF00738034B160586A767021D9E15324103503DF58EAE6AED6A97D6971FCC5EACAD1C64B3C4B09428EF1E2298B721237E738EBBD9EEC22310D366A42258296200A825BC5A8C45EB58D84924EB7DABEFEBA0A18EBB6A8D522BD4B4BEE2E98A49809528CF99E1D86D73C84D8C476BC9BB2F84C0CB4A932D130001D4A6480DB0259DF97A429FA550A31074E7BF4D5B72F78A8736CCEB9D5B4C37DE55074A934EB6817140CC1909E2373D7CF718B94B5E53859478E74894784BA0A904D05831D0D1EBCDA2CF91E5986C413FA852659A37151DF968F4D236E4FD96F6B9A9DE42729A15AA85D23C6F06D9E14AA2E7BE00C409EA7A6D8A3665DB8C264EB599684CE0825B816C684B38483ADA8CD56117C9794E0A4CB79650A0055A8F461F5A569D69169D1FB2556B259CC3576AA6B2A091C4E5325B6EABBC9890436E1E189FEDBC8E98A663FE3263D73E5093819894F1101B88155280FCB6E76035BC45CCC74B9426489412A3C4385419C005C80CE4BFAD75A0794763DD87E9FCC5A7334A819C901417097D89213127849893B1DAE7A5A37B5BDB0CEB3DC8B1457266E18092A62144B82935A00CCCED4E82B16DECE674AC22E58528A7898026868DFC0A53CA3EE03E86DA1D2543EC5FA019D1F972B2EA39CD4477AE3A14057AE08EF0DAFD2C2DCB1F017FA8F38D9FDB8CD25E2F11DE244CFF6A802925892E412A3CB88B801C56B1EF1F837987EA700389355004A8B905C13FE45FABC7ACA84A9284C99266474B8EB279CC4FCF1E5D9397CF13261134A413B9AED7FAF5A476AC5CF4861C1C4776B0E8DAB7DEF0933104A50A0762094A60D8103AFDC0F4E738DA4E0569C54B0B98684B924D6ECD5DF61A7587B839D2CA1654001C35A5A87F9DDAEF48F33BDA9ABF2F4FB577B32B6E368EFBBDD4BC20800ABFCB372424DCC0E9CB7E98EF9D90C2CC392E604ACB2658E100D4D0DAAE7ADE388F6AB17874E71292A97FF00E630346FDC2A36F623D30A31C6CD3AA3C219660721FCA4C5B9CDBF1C7259B2509C6E256A524A8CC3C2EDFF00222DBFDFC23AEE5B342F2D9440E11DDF9B871F9F17E71B908714F49802E77E97F81DFE6061CAD52C4A60CE41A02CE1BFC7973AD6E5C9C4AB1C5452A090B2C482C2A77FF3D4888E6B2E3774AEA26511DF2F26CD12D091E22285F88E5BFC46F8DF2B9DC18FC299859A721A97216920817F5AD3AC3FED6611589C871A07EF4E1D756FFB0E9E6E7E8098F90FA6ECDA9EA7516A6CD357A90C3633BCC56D78924280AEA8200283D2279DCF4C7D2EF869DA6C5CACB30DC1296DDD203D69F2800DAAC757BC7C4BF8C792255DA1C50E2048C42C5F751D743F4D9EB0E8EE76D51D7B74FA66943CCE5EE35C4C349F155265370E04F123840B998DE77C755FF534E272EC7E2312A2B9E994BEEF8C90124A486E13436614A748AD64395230D9865E388042A6238CDC5D37D1A95D478D7DD6EC934769FED6FD96E82B337C929575AEE5B5AB7A987766A5B5529594F13E91DE8928B49079729C7CDDED676B731CABB6D394A339027E300487504B05B0205850B9661E71F47724EC46599C762A64DC22A5CF9C8C239084A5441E07A90E0171CCF311E2EEA7CFC653599E69EC969052A72EAAA969D4148EF29D21D73861C52429C2A026C48000EB18F76763710ACC7B392B309DC6168C2F15492144CB35634A31E6795447CD3EDD65389CB7B5E70AA92A42558C290188FF00F319B9F869ADE3D58FA3C3B28CA33AECE6BF5BEA2A76733467A406175C84A52834CF2DA50497A5224DADCE37B63C55F157B6389C3E73324E1714501135695B176F9A9A1F1711F48FE057C3CC366191CAC462B0E95F14A41495258074814D76AFD691D5CFA403B28CDF24ED3720A9D3540D51E4DA8BEB7F5B094B6DB4D2699A4849E22129209322201F3C760F81F9FCFCC30AA973318A54C40485A8124BA8D280DC78D7CA391FF531D8D9191F02F0B2C251F31570A40A029ABF4AD746B8887FB20F66D91D476B9A4F2FCC6859CD65756AA84A825C4A0A5A2B4F1C71A45C5A472816C4EFC699F9865D951C4A7319A014FCA975077206A473A8D2F1CD3E036024E6B9870CBC1A715C0B4F79404258D5FE53A0AD7AB5045D1EDE1DA9E96ECEBB5CEC972CA3A0A5A5CA74EBB5EAD48865B42B81B710D2E9F8D9420A956981C2666D8E19D83C266F9B23133CE266290B4A9D64A884B850DCDDDEF4A9348F58F6C256478491264FFA6C94AD80092948515001EE01BFE2D48EB97B607B5EF62DDA7685CBB28D06C37519BD2D3210E3832E76894D38037C652A718471EC762769E77EF3F073E1B6759A6638B9AAC74C9B2913905BBC2B48471925FE62D4E8ED68F3F7C431809981693804619625AC06481C6480DFDA34634DDAB68F22739D68BAB6D0E0A97EADC1DE175A4D33884B026C0391C2B1020F0CC45F79C7BFFB3D84C9F2597FA5C462E4255292848599882A5961C4384AFE562750E4C78F8767F375E3311311859AB965648012A00004EA017E474F28AAF35D4B59561468E96AAA409934EC3AF8B1DBF94857A72DA0F41D07099B767247089B99E1D0542814A46875756FD7CE26B0FD94CFA785775974F98CD6428EF7F969E3E1159E61A8AA0294D3A87699E132DBE95B2B3E5C0E2524C499F4BD862F395E2328C6B1C262E4CE701B8549376D028DDA8FE71BCFC8733C00FF00E6F0B370E752A490EDC940575D85DACF09CDF3DA8209E3299B03313E9B4CF31E91899C5FE932F94666216994801F894C186A5DC7D5B5D042984CBF1189253265296AA330249F2D0D869E31147EB2B5E6BBC3956695C82470FD5A96ADC41837975A6CA52204DD5D205A04049ED7764D13C22666D8497312AE101531018920070577EB4899576673DEED43F433D12D49AABBA5916A5386DCFF0088FA24FF00C3F34FFC4F38F69DEF288501A4A6D32426A521C5A78A9DE3F65E128248E8279EC4E3E6C7F5FBDA5C0E3335EC649C163538D4C95E278D522604865AA5900842AADB97F3B7AD7FA5DECB9948CD5799A4A030215365F0E8AA7CC0077F2EAE23C90FA4F9F799F6D1ED756B1C2555196A65238504229624204045A2605EE4E3D39FD1162A7627213278569C3A254A290B51506A93F329F9EAD63AC56BE39E5584959AA7F4265CC5198A7086705E96BD741EA1A3CFB62A6AAA96B14ECBF544D9229D972A15249E4D25667CA3F1C7BB3199FE43810462730C348EEDF8B8E621268F4AA9361E6F1C1734C9F3198A93C7849C525B80842D4EE06C08D75DA123D499CD2F78E55E5799D2B523C5534354C220EC789D6D222F3BFBCCDE1307F11BB1588C51C3CBCF708B9A5410940992C9772187CFE6DE10F53D97CDD3290AFD0CF08E176521428C1B4766360073B4332EA9D75410D256B52E7850D852D4A22660264FC26224C62ED3331CBF0D253899B88968C3A805A6628865248705C9666E7E17847FD1F1B2D410AC3AD2A51FDBC25DDF52DE97F186EAA5D43062A1B758528F843C85B73D63BC026046D244EF8532ACF327CD57DDE5F8C953D4925C2169241ABBB13F4B36D0FD792E370C90A9D8698806A92524537A86DAAFBD748481C71E3C0CA5C79667C2DA14B51F720127A9306D7EB896C663307974B13719391211565AC8F17A8F74D61F61320CCF1C954CC361664D4A3F7292951677BB258D053ED78D2E9A964F0B8CBAD2B925D6D4857C160131CEC7E186D97E7D93666B28C163E4CF502C52852491D589FA427FE9D8996A32D72D499828A0526EE69B0F7CE13A5558F71772D3EEF0DD61A69C584FFEAE049299E40C4F2C3AC666795E585031B8A9520ACB242D690F6B3900D4EC5EB5348772F25C74D415A30D316848752824F08BD7F6BB53F98D68A9712EF74A4385E5FD96D2DAD4E123786E0A8FB87CB0D319DA3C87052933B139848932D41C294B400433EFEDE12939662F1333BA91216A5A4F094A52A517766A5AADD7CA1CCD2E6E96FBE5E519AA59DFBD396D586E3AF7859E1F3DF11586EDD76471733BAC3E75849B3096094CD412EEDA178959FD8FCFF0D2FBD9D97CF972D9F8952D6CCCEF61A08D2DD653394D52D5532424800B8A25B2D284C4A6CAB9226622DB8B61CE6B81C3E3A4A71D22705F7693351C350A08054E5A961476DB788FC160CAB12996B4578825448B0763D3A781E7ED87D1C5F46D7651ED01A2D1DAD76D5AE32BCAF4AD3B89A84D1D656314EA7514EF10524FD65A7374581078B90BC1F9A5FD527F5419DE4017D9AC9B289F8A9C53364A972F8C04708677082F67BBD3C63D37F0FBB2194A9289D331929165709625CB96297D6DD23E8A352763BECDDA0BD8D7B435762D94652FE4C9C86A1A7B3A453B6F2AA1746D3EDA16DBCF214A212E20DDB70C8E626FF363B07DBCED3E63F12726CC733C5E310538A9B351853366A59D5C452A4F1071703886CC184764CCBB37835E5AB972F08853240337841715AD459B5F5BC7CE37D1D3EC0BD9C7B4E506AAED5FB5CED2B2BC9F4A6439EE60E1A2AE14F4A5D6D19A54A3BB014FB4E2802D40213B444E3E907C52FEABFB4DD9AECAE5D91E4DD9EC4E3F159AE0E64B13E5A9694CBEE258E251504101C56A43E95B50324EC4E469C619B89C6C99650B1FEDAB841249B00F4AF237D9E3E9B321F67CF66FD2BEC9FAAEAFB23C9F24CE3237B4D66ED8CE986987455B941495282B4B8A42D40A5D41921773D6063E6164DF157B5DDA0F899819B9862317215FEA282252D7308495CE4F121A80B3B07A8F37E87DA3ECCE00E4CB99859289A132DF8D207CAD7AB5776DF5A47E7EB99553CAD5DA81FA670AD946A3CF5A4B53E14A5BCCAA5B09126200004011D06C31FA51F85AB389EC06553B17F2CC9D8294A73534969F534A3B11D23C5FDB3C261E54F9C94949505101340CC5BCB4D3ADDD61A9E179C360A20152428409120743783F3DF0D64CE50CDA62250E24998C4836A9B36F5F50D578E6D2240E30E011FDA4EB537A68DF4BC2EA5AD22C5422473E91B19FDF3DF17B9D870653B7F66CE6CFCABE5BBDE15CC30EA4C8701C0069D28F4FCDAD687715CA44428136BCC6DB72B72B73B46D18ABC896A993660092C341AFDC59ACC1BC62B3224BAD4EF7DBDFB2D787EA0CC9700C9E5CF6E5204D8F4F913CCC46195574B06EB7AB81AF8E9CC18DD72D9C1A8FA3F5BDEE225B419A2E6EBFEDD95B79DBDE3DFD6715AC7619469C06AE280F4FF01C5BAB329A9B38FF00D5CEB4B794762B54E6C071A83A41333E237F58DBA5EF7DE71C7A565D225E253C12921883448152281C6D51B4339649559857C6F7DAAD7D6281CFF365B6EB4FB0A9711DE44999E4678A6C7AF58C769ECFE110BC1842C3215C2EC360E2CDE21CED13786AF8375E9EBD1B5178A7EBB33ABCC332397B6477F5B534F4EA240801D712824721014762248DF125DA5E2C2E54461D4A4044B515106AC2B73CAA7D889895278A6254A4FC86C79B0E5A901AC3AD63BE792F641A23B2BCAB2CA9CD69855E76ED326AB89D4AD694ADD6D2E8B282907EDCF3DA48031E5F38ECCB35C73E1B1737F4FDEA90085AABF310AA39208E7F888CCD676264CE0B0B29516A804381414040EA79B934AC573AED1B387EA1C6A90B34797A014A034869A21116FB294AB94FAEF8EB196F667032A44B99350A9B3D41255C4B591C4C0BB17162697DAD161C063316BC1CC2A9A543828EEE457C6CEFCBA5285CF359E62BAEA86E81D76A5E724A94BA8500929499E14AD445FC85E3DD8B22B29CBD6A92956165A96183809716636ADA9EDA23275CD5E3546628A92A5901DCB876677E74F3A98AD6B350D7BB46E2EAEA453BEEBED0727857094BC018BF4990236DB1359E76764CCECFE365230E90A561A6540AA7E451156AD3DE9178C405CBC5E0FBB0CEA4B80F40E9A96F36F311F6FF00F44CFB487627A07D8CBB31C8339D5749499930D6646A43A8292A5AEB0AC0054A093626627CF1F9D6FEA4BB1B9D49F8859DCF5C92705371044859500ECE08FF0095F4E4C358F7CFC27CD64E5B92E1C14FFB9DD8E335776A58789FE5A3D3C67DAE7B07A893FE35A0513B789223FF00783D368C79E667657311C24E1C8059994039DE86DC8C75D91DAA91312B2A092C39967F06F7CDA305FB55F624AA86186B5AD125D7C90DA000E070CC09F19E1DC7BB6DB0CF19D97C6257294B42A5A9C355DF97F9BBDAB0CD1DAE90913425600D6F5607D456DBBBB831D07F690ED5FB27CD3DA6FB08D495F9AB0EFF0085179EAFBE43842426B29D00294942B8556BDC1B74138EDDD8FECCE3E6F67B1C6493DFF749E04B0D01E2BB5EB7B4705ED876C24FFAEE140AA0CE72412EFC405B9791FAF7968BDAE3B1147749FF001C51381D6DB4A29F8384B2A420050278A4C9EB1B5A0638D637B25982F1B3D2B796B4CC5380417254FEA5FA73AC77197DBBC2E0B2FC12952C282E527889A30090C0536D47DA256DFB4AF63B52D17D3AB290242642B626D22DC40CEFBFA7A88ECCE612CA122515B9B920077D9CF21B35ED12D84EDCE027CA331284B84972D504F36372E5C0A39BC42754FB4E7636E64F9B32CEADA572BD596662C52B009056E3D4AEA001E21CD437F8EC70FD190E2B0D9860538895DDF14D965831765A6ED43B78D4456B3BEDA8C46539A32C1692B09029FDAA05CD3DDA823E726BB4D6A1D439C662AAA74D2E46E667983E97C29278D976A9E701001076563E90760D587C2E43841DC85CC3212C1AAAF94063E8FE11F1E3E27E67FA8ED1E2C951FF00F10B377BA8F3DEE1F76D1D5A15A4F42B81592559CCF34752A43E56C2D2195A92522EE05257C526FC8EFE53B2E4E2B3454D95DCAA44A7AA41278C39B6C035999AB668AC23303225CA5057FB80122B66622BE9EAD1EA67D1C3DA356E6B4DAD74267D5014D965A4E5ECACA600A843AB73BB40B0B284C0DA77E5E47FEA07B392F2DCC32FC7C99211DDCCE359081F310A4DC9036AB9FCC7D02FE947B5666659986131F33BE4CD95C284CC53B5160F08579EBA691E6DFB57D02F43FB446ADD2F48CA826B336CAD9A6436D1850AE711DE59293301D2609B795E3D03F0CBB5D82C6F60569529089D2706B4A8135044B291B3500F0E748E49F1ABB1E319DB5C26270F2190BC5B92948ABAC56800F46D9DDE3D63D679EB5ECDDECA7A4B4FD3D70A0AFA85E55514DC09EE9C70565753543E0410612975415CA3717B785F3FC9A7769F3FCCE76154A9A11885BB025BE657E29A1AF87B5BB159B49EC8F6772F913C0940E1D00020020F025DF7B86F1140219FDB652DEBAF673CB7B42A1A84D65465397D0AA9DF6520281A92C21F3C683E466F3F3C74CF833982BB31DA219762014AA7CC9685A9668CED650DCEDA5ACFC77E3BC8576AB239936534E2A9534A384026B4D37B80C28D778A1FE8BBD38ACC751F6A7AE3362A552E434B4151953EE712D3E0A675555C04CC41410A8FBA23A6FF005398DF9BB3D83C3AF8D3981095049A2788CB0280B7F73D5E28DFD1B7674E447B478BCCE571197F34B334587FB960A0478383D2F1D00EDF3B4DCB3B5FF6D6CC1CAD6C57698AECE692810DF787BAFF002FC34CE0481B12B490A81EA2F8BA7647E1F4EECC760A7E2952D4A5E2704660590470BCB2A0C5BFEEA6BE04449FC40ED2C8CE7B5D2F0B8629E04E2420A50A0430500D4F3A6D631D85FA4C7B09ECFBB23ECBF446A9D0990B397BF5B42DBB59DDA882F71A29E49E202D0B5796E76C3CFE9073EC42737ED665B8C9866210660725C83FEF70B29CF0B10051ACC6AC218FC68C99183C26453652693929E2012CF496EECE68EEFD6DADC5EC3BEC93D82F6D9ECCF95EAED55A69877387A87303535EA75C49A782E214E10980B800AAE6D1CB1CA7E2E7C43ED4766FB6F3F0F85C6CF121589504A12B57FB80AE8007A338D2FB88E87D81EC064D9BE469C5CDC1CA0A449054B29490E52EE695766F13E1D77CB7B55FA307D95F5337D966A5ADA5CE7575066CE50E74A5D0E6150D2DDCCAACA695B0EF03AD00D77A124A55102F187F2FFF00BD4ED5E0F119A617178CC26151251370C4052C21900AEC6BC446BBC5C3B2C9EC56598D56031587C199A66776C5281A90033737E8417878FA4D3D843B14CDBB0EA1F692EC3F29672E6F2DA36F31AB5D138E38DE60D661DDF7278388251DCA16491C2798306062D1F007E3B76A724ED88ECFF6AB319B3947132E5494CD74F02428853D4D081AB0B1B8880F8E1F0DB28CC72F46332AC24A948EECA94A9612D514B0B3EDCE3C95FA3EFD8CAB7DAFFB5072873D529AD09A51F4AB3B7B825B525C0A52525692950F1B651E156F36C7B53FAA0F8D583ECA76572F5659344DC6E61872112E5CDF996B2945B87626B7B4713F853F0CF0F88C7CC33D2172E52D24852416626EEE28CCD7F331ED076B5DA3FD17FEC44ED37657AB32FCAEA3324B69A5D4714B53982DA70B63B9529C6DB78B654553E150BEE4C63E7164B86F8B7DBDC662B32C1CFCCF0F216A13249489AA4A03BB3BB105FF00168F54CEC1F63B2E912F0B3F0B8452929E151504024D8D1BF8AEF1DBDF602D2BECA39865BDA876B9ECBD5AC3B9676954F42FE7397B02A1B5529CB5A712C0522A085A78C95010948E5046DC7FE30663DAFCB73DC932DED38C44D9A89FDD89B394A257F3201531729091A3F3ABD1DE5792E513F038E393AA5C80B40F96530268A37074F1A7311F2D9EDD9A0F5876C5F48CEABECE34B65EED466DAC334A1A4A4A169216B534C53A1352E955FBBEEDA25C85471011D4E3EBE7F4EFDAEC8FE1E7C239B9DE3B1B2A4ABFD3CCCEF145293C5C059342093C54E57358F3EE33E1D4DCC3B4015899AA9A9EF8B25609A055C13AB55A3DB2D21EC57EC31F474F627956BBF6A534555A86AA958AB7EB6A8543AF5454B8A42C34DD134A70ABBA5B81B3C283B49006DE1EED3FC50F89FF001AFB4999E1BB0F331872FC36226A672F0F314A010A52C24802B5636F08EDEBEC6F65F26C1E1978F93875AD284901410E4802E48247E5CD843AE8CED37E8AFF006F2AD1D8C694A4CA58D699834E31434BF52AACB54C843656DAD0FA9A612F153402880A244C1BEFCFE7E59F15FE1E6608CFF1F3F349F2B053113664B519C12A2140A81724338E90DE68ECAE3C8C2E1B0987750605212785A9B397B5DED68F1D7DACBD88321F60BF6BAEC9B33D4CDFF17EC2359674ED3525229B506128796C539429E1DE3A65EA800159F43C3B7B8BB2DFD48E3BE26FC3CC660A5625597E719560D689A9E22B521610A0826DC5C5C1D45758A2E73F0FF0D2F32C34D4E113DCAE62492122A388122DABBB73AB3476CBE995F611EC7B40F609A23B68EC4B4CA74F30DE5B435D9C2A9DC79F4D50CC51485A512BB2203AA22DD7D71CE3FA55FEA0FB519476C336C176971F331C9FD6777253314DC23BC58701C9A863A8F38DBE28F65B2EC365584560F06842D329D44243BB26EC0BEB61F58EB77D0CBEC69A0BDA2B5EEAECF3B48C9115DA5F4A379686DFA9714DD3B8BAE6149578EC9052E8B4F31B49C7A03FAD0FEA531B90766B2CC264188386C66310A226CB554B942943875A1ABD5E25BFA7ECBB2BC6E0B35958DC14B9CAEEF853C4134A2C3D41AFD77148CFE9C5F64DD15ECCDAABB21CCFB27D389CB322D4633E5E7556C294EB01146DA0B01448291C4498BFCB101FD0C7C4BCC3B6D8BCE26E7799ACAB02252D6664C241E30A51A1506B6C45F68E55F113B372324CE3113A5C905136728CA4705140ACD1EA035F9DDACFD87FA2DFD917D9F35B7B1EEBFF00682ED6B49359BFD7B23CC6A324CC2A5E7996D353963756DA8A00849979B48E524629DFD62FF501DA7C27C41C9F24EC7E70B9185C04E50C6CB90D30CC1F229292C5C380776D8BD7A9FC3CC8F2AC66478B18FC1CB13264A696A5330252AAFEDAFBA433FD16FF0047C7633ED01946B2F6A3ED7329198689CB736CF1CD319170BC80D51E519856D354789985B83829D2BF1209E84E3867C56FEA47B5D9965594653879D88C2E2B13284A5CFEF540A0808054524A5F8AA7C1F9C2BD81F875976133AC563674B973A4A269584148660A510CEE282EECE03C76133EF6D8FA209F5EAEEC8F37CAB2FC8AA72466B32CA247F07CC5C73EBADB6FB2905F14C140FD612920A951B99E78A9F6313F19666639763324CDF31C62A6E2242A68016A4AE5AA624CCA9240F95EDCAACC23B1F6C71BD9E9992CCC20CAA42572E4A92662529BF0900B04D5A80D5CF947CB7F6DD98682A9ED2754D0690A448D286B5E772AAC69C7385FA7756E38D1088E26F852A40009E77BC63EF5FC2D19AE27B2182979895FEAE6609099895D4998A9490B725EA0B9602C0DE3E7D66984C361F1F8E992F86B3144240FD9F329AD43EEA5DA204E7699DA05168C4E8ACBB50E6F43A64D7D10EE28B31A9A50106B10B221879060991D0DE6C4638DF6FBE086071B85CDB35C76024CF294CC9A17325A4AAA16A35209A0E679984BB3798E2E5E6F874CBC64CE033405490EC9AB0ABB1E63611F719ECCB4196577D12940C55079D6DCD299BA9CAA7DC75C71C5F0BCA256E2CF1AFC7B1528C998C7C5CCCB0B87C17C7E46130C844AC2231E89699290004D92599AE6E1BD23E876569953FB10B98B960CE18572BA12FC14D3CBEF1F1263B45D6195D26A5D1596EA0CCB2FD38ACFB37416286B9FA34A93FC52A5442FEAEF2146E49BDCDED8FB5123E10651987C3D938FC560244E9BFE9C572CAA524A83C804949524A83BD5887E758F9EFDA2C6E6327B52A12F1B350062FF00E902B0923BC6625C69C888FB62FA37436DFD10F45C0FD454A91A67582955352FBD50EB8A5AEB4925D794B70DC9FEA81E58F87FDB0C1E1B24F8E786C34A9489586959AA1299694A5213FEEA1DE81DCEEE7C9A3DDDD9793FAAEC4A97894F78B5610152C977F91C13B6E1B6E71F0D41E4FF0019D517B1D4F9FDE7AE6F567CB97A48DB6C7E8E7B00A188F879911C3B07CBA58615A8949B3035F060DAD63E7B76F113067F8C96147804E5F0DD802A3FC39F106F07D6386A5E954FD98127A6D791711D3117D9EC22E566589993417E371C557D4DFD3FCC56E4E19425CB2454025F5AF2BEBBF4D442B65F4A549F1117D8133B9DBF111118E9C7826CA5310DC2CD7D0FBB51F70D0EE6CB070EB0A0F42DCEF4F5ADDEA21DCD581C104806C04932237EA6F6F33E51882C348EEE6CCF9581347D1AE08A8FA3F28AAA241EF4B503D5875A537EBE46EED495890078A368BED3D3E23F29BE179A8490C589624F869F6DFCDA313648276D542BF9E477DED125A1AE4C99267C30677DAFB99FC09DE4E21B13265F1D520835622C4EC74F388C9F29945C5363CF5A1AFA9F38BB35566EB3C70BEBFD43CE36900188FC0922390232E2A9C9530A9AB077DFEC7D98889490A55ACD5AD7EBAEDA738A4F33AB7EA52E21A5C3A2E825406D1363E5CB68BCE3AAE4321387929EF43A05F50E5DB4B124B7B1161C248B52A0723BB1DBE9BC55D5D555F97D6B398A163BFA5ACA575C3292785A7D0B31FF00D2920C5AF8CF69B0C313835CB961C290B4816A28105EDBB1B78C5A70187965491387FB6012F5A16A73D06DA7231EC2D0E6343DB5F64794EA9C890DD4667945070670DA16953A8521096592A6EEA121063C33F7E3C9887ECA769A7E0318A29C3626705604A87CAE3E69B7A0209D6F0CB37C009C25CC4A6A824289A382ED4DF7DDF58F3FF55D53A8A8ACA6756ED33ACB8A429B295A4D94531C8F974DCDB1DD70D99499F230FC052470804820B8206BEBAC38C2614A306BA31092CFBB6C3D19BEC6A1CE2A1B6E94D552D6298A961412A012A529C0E2A0DA64409E7127A0C5AF0384EFE64A524D8855BF8A03AF2E710793A267EB485A010A98782AC181A8A16F0FA51E155F574F58EBB978796F3ED86D6E28A54890A0144126DB74F77417FCC241959262E7CC4A512BF4B31C382C532C87BEB52CEFD63A16225A9388C0CD029C69AB87A902B7D3AFD63ED77E88CF630EC27B6BF627ECBB55EB6D3F559D57BA33712D66B5F441A28AF536ABB0E212E714011702DEA7F365FD5776CF189F8939D6065CC12F0786C47FB44049E2E2249AD598BFD2CE23DE1F0CB234E3B22913520F11949E2150CE06A59F5FA3B523D456BE8DBF65AA623FFE03AE03911A9336303CA1FF0021D463CC333B578E584BE2980141C29D7EC2C1FA474DC3F64C244D704F10B329CDDF97AD18C3831F47AFB34D0BED3B4FA1EB42D0AE20E2B50666AEECA60A6389D26FE5CF0C31DDAB9E152C4F9C95936F9406F001E9EE86AC91D9204CE025100DEF5A3FB60199F58E8D7B457B34F63B90FB4CF611A5D9D2D50FB1AC1CCF9A52179BD60211434C9FEA53849B120472B0C769EC576BE6A3B3F8FE09E1333BA1C33784167E270DD287626D568E0BDB0EC71FF5FC277608499C1856EE1CF8F883AD8C776E9BE8F0F65F3DCD4AB485635565B6DCA8FF00E399990494050801E001E4607AE3924FED5E28E37124CD1326198A2E400D521C001B6A0B58EF1DE25FC3DFD5E5B81EF16C44A4B062744EA0E8DEBA6B2647B107B36D3B229C698AC526200FE31997DFDECDED68F3C03B439AAD49299818170191C9B41AF3A1B81489BC2FC3993230EB48554A7FEEE7CFF817D4B4373EF61DF66CCBA92B734674A568CC6932FCC2AA8E737CCD490B6695C7495254EF0C4A07DA91CE3A3E959C63B178EC1AF10B0A289F252FF2820296806D5B00ECF50FD28D9D7638E132ACD5810F26656BA254CF50FB7947831A8B5585D456D065B50728A0A5CC6BE999640FAC1E062ADC6805289E2D900DE37DE44E3EA4760F2892AC83033D127BE52F0F2CB92DC24A126D50F577AB97A5488F8E5F14303364F6931891C494A3113372FF00316D0FD39EB157E6DA919CBE1798BCDD436A5781D84A0C922E40F14926D72676BC0C746CBB234CB13172FE4580EA05360493737A1D08F431465F7E664841258D0726605EFBEAFBC7643D8BFB54CD727F689D274B96075594666E3E8AF5281699504D390D7138B0126E6DE2BEC271E5CFEA1B24978ACBA74D080A5484AD5C406C1E80835A3787311EA5F835DA09FD9DC760E54B9851FA85A1376FDC4021AAF43AD9EF1E95FB45F61995EA4F69BEC673E6F2B15CAD6AF57D4E6CA292A43472CA765CA72B51494DC8944C49B0DF1E36EC176EE6E5F2339C12A62A5CA96932C20A8BFCC169FDBC8B75BED1EEFCDBB132B3A9D94E63DD85AA6844D2784528824DBAEBD23AD7F4A7F69CC52E7FA1B413084A19D334CF273069A7C6FDC32BA7EF1B4AA525251299026245B7EFBFD3C761D3DA34E6F98CC1DE89EA2B0E976F9A61D47D7978729FEA2BB4733B289C9B0B2D7DDB0082104876E00CC36DABD358BFFD99EAA97B78F624ADC89D712FD65265798F7895381C752A654FAD80A049298E04F082013CAE71CD7E2CE0E7761BB62AC5A5E54BEF9250C0200E020166BEDA50C59BE17E151DB7C97867FF00BA7BB4B05391F303BF5AF86911CF672AC47B3A7B09EB3ED133C0296BDD6F51D1D4B8F8EE5C5835F5D474A49500612952786D7E538D519DCDF89DDADECBE0A6CC52E5CB9A8E034570F01965B672CD5B6D175C5F66657C3DECE677899284CA54C92A24A592F45D68DCD9BA574F9C3EC1F5EBDA8BB72D195B5B52A5B95FAC2BDE2932B5BA87736E26EC24C00A107EF8C7D53ED664186CA3E162B8E5A50519594824004B61C8A3B17A73158F017C3FCD67F68FE214E4AC952518FA3925819A7EC03E9A0BC7BC7F4D6D6FF09EC47B2F57D6453B4F652CA9692910A866948B58DBD31E0EFE93F15C19F76C8B904E215F35DBE79C2D7343E5E2DED0F8E39209B97767D93FB25A6800BB4B7F13AF808B4FE8FACFD549F477D567542FADA751A6B51A9350941242D2DD604A936894A8026098DE7149F8A586979A7C5BC1E1A604AE5CEC74B40492000EB4824D9A8790A1E7171EC14B184EC6631228A4E14F096B325479F3D0347C5C675A8733D4FAAB3FCF33FCC3F8B664F6AECCB82B9D400E2CB19DBC96B88993FC9094000AB940B1C7D81EC77C2AC9B29F86BDEC9912710B9D960592109F915DC71000B106A48A3171CDA3E7F67FDA7CEA4F6F92893366F7631E9494B90083380E8D5E5E31F657D9FBAF6A0FA23A8EA350D51CC1674DE661E5B80AD4E16DC70530264901AE1481702009C7C62CEB02B97F1C71B8192938799FEA00219C703289A33338A8A6FA47D19CCF2FC6633B0183C54C4A9415820B59209249402E6E472DF68A37E836D3D97D07B32F6959EB85B39ED70D46E553EDC38E452556666907123888284252902463A27F51133192734EC5E1E74D5CE9689B2C1E25BA4A4992FF00292798DA39F7C1CCB958939C1E13C487090C410471F206ED4FF11F2EFED8FA8F52EA1EDDFB4CAAAD79DA976B73A79AAA1564B8A4A296A1D431C21E24B7084A638627CC63EC27F4CF90F64717D89C395E030857FA1905733BB944BAE587513C3423E66249203D5DDF907C4D999B617365204D9B2E5F7AA0CE4502B7A7B2F4B1F7A3FF000DE663AA9DA2F69CA1CCAB9FAACA72CA6D37FC1A89C052CB21D69F35019512507888957081B7A63E5D7FF101ECDE4B9676EF245E562428CCC4CCE3EEC207012A433B683CE3ABFC229B889D8498A9B89513C0010493C4E0DDCB79D7ABD5E7B03CBF24D4DF4D0F68D575CD30CE6D9355D21CA92FF03A0177285F7E5A6DC94A89008514A4C4C9223152ED6CCC661FE0B49948C44D38695879616842D690BEF1496A820D09B30F1022F08C2E1FFD53884F471F192D4DBAEDCB77B88EB6FF00E230D59AD55DAE764D903A9A87749D28CE52CD0F7C5AA5AC52D868F1AAE107B8761694A8192200B63D3DFF00C34F22CA670ED22F30548EFE7770654C9B2D2B291F395278540BB8A170FA93148F8AF3A6C992832A72827849E04A8D580377A7361D291E2CFB2666FA9325EDFBB38CE748E72F2F57E539ED1B74CDD3346996EB15B52C35508213C29792DD3A949921462488C7B6BFA81EC7F65476273EC4FE93088C423093945932DC321452A0C9B967A5059C5E3987C369D8AC6E745D4BEE4CC40092A2A0083F31725EA6AC6D1F57DF4EE657923FEC8BD9F6ABCD99646A8D3949A7333CA1F79612F37501FCB6A6B0A4AA0C9524C83F2D87C73FE96F23C5768FB5BDACCB30EB52B0F3A7CF429491F2CB4A0CEA10ED50001401A8C418F5EF6865E0B0781C14D9851C72D095558392013737ABF56630F196E6C7DB87E89E6AB2BEA1ACCF3F3A7DBA6532036A768FF84389658909B9E2453A6091F2C42E6B879DF0CBE2F4FC3941978638827BCB267900A8D2A070977B3DCDE2A99F60F0FDA4C995DD11314896470A43905801B16D872B3563A8FD8A6643D877E8BDCF7B415D40CAF58EA9CE5867EB253DD55775976A834D716591DCC0936817B6273E21CDCC3E3576830D8096959C3E4921656A014A48EFA53A4B86A120B579D59E203E19E5E7B32719DE3A3F50B02B4601441E573BC5A9EDED95A7DAFF00E8B1D29DB250BE8CE35150399652D3543284BEF819967749435012A471281EED478C4DEF24628FF0CFB77987C09CEF3BCBD6B992A5CF284AE695143F0850173BABCA85C45C7B4FD94C1F69049528A14A7252C94921C826CC4D40BD5C3888E7B42D72BD89BE877D2FD9464B982323D579CE541540853694D43C330AE69FAC480B214B05150A077001DA76E91F09F21C57C6FF008BB8BCF66838BC1A274A33E6295DE252148F97E524EA3D0C547B5394CFEC764A9186E2E12820000B903722B6FA5447523E874FA4FBB34EC3F4D669ECE3DBA54B590E5B58B71AD3D993A953CCD5273971D7F350E36D2421BEF3EB0471BAAB4C836C76AFEA6BFA64CCCFFA6669D98C3AE64DC2A0AE6C99287131410909AA4109621D9AA4EF7A87C34EDF19B3F1387C4A08257C20A9554804824BEF5F5D6DDE1F694FA20BD9A7DA6B2BCE7B5BF657D4395E4F9BE694B559BE6147401399AB3AA82D395094ADC53AA142A2E1544849515584838E71F07BFA83CE3E0866986ECE76F7B389981731121189C4F04B32471048290A96EB0C45886AC7A0D59060BB4592E3F112260E3EE4A82407E27492D7DFDEA7E40BB5DD09AABB12ED0354766FAE3277329CFB22AE55355D33AEF7CE04F78A0C3BC424C3CD04B800FB33048DF1F6F7E1276EB2CED864F97E6D8032C61B19290B9694149487487629A50D3ECD48F9F3DA8CAB1180CE71D875850509AB090411FB496A9B50F5E948AED154DADD6D0EBB14C2AE8545266E3BF6CC72E639EC3963A6F6F932A5764B3498B4A7FF00C24EAB80DFED2EB434A79F9BC7767B0CD98E1D64007BC0E7982057DD5AD78FBEAF662AFA773E880CB14869229BFC279D8EF645E3EB039827DDBF524DB1F9A1CDF855FD47AE7713FF00FCDD2424D984D1AB81A5E84599CC7BDF23C6A7FF00B26B95C54FD310472E02E763B7324B5A3E04330A827526A39794298EA1CDC8DFFF00E6753EFF008FC36C7E8DF26C560D5F09F08BE14850CA4A4D451E4000EB73CEF7B4789FB418642FB4AA25001562814ADFFF00F23F9D3EBB53EF17E8DD7C39F43DD125091C08D2FAB036A172AF1D6CF29989FD6C4FE6E3E364B549F8F1317254ED9BCA5708714EF52687A104FA55C1F727663853D8DE07001C29DADC157B0153CB7BC7C2A3EFAD39C6A42018FF0013EA08FF005019BD64C7327AFA5F991FA25F8098838CF87D9226657830328126A6B292DEFEA2DE09EDCE042F3EC41480C672DE9CCF5DD9CFD5A3172A549A9709901411C2677B5E27E605E3974BA63F049C14C9B36581525541AD7DB6BADA22315970932A5F086A3B806D4A0A69E1A6AECA115465266E0F23C87DE7D63718322C51C52E625CB75B1AF93D01F5D221D587E397303513A1F16EAFB6FABC38AEB4422157326D73E9633F3208F291890C534951090C4D9BCEBE1B79BC41230CCA5921874DC9BB37BB42DA5AB55A5506DFD5E963EF3F872C45AE6BD5FC5ADBDEEFE95DE119B2039A3020B86DB9EDF5F52FD4D5EA491E2E917E91EF13F0DB0CE6A8AFE660143C7EA3D988D9F86AA986CFEE9EF5D22ECD40F90557B78B993D4DA3E47FDB15AC1E5E95B16A534B3B78FF00377AC5670C82E3776B3DCFE4D8DDADB54D9ABE12410A20C988B4753337E5636FBF172C149125212C006A8BF4D34B9DAF16BC149E2670E77AFA86E5E0E4BC56D9CBF2570A3799BF39B5A4733D49336318DB1B244E42924536D2C34E7BF268B6E1B0E0814D7CEB563D43D69D2B1D8BF644EDD6AFB31D768C86AEA4A74EEA7710DE69DF2B89942584F80042E42788A88F0804DB7DB1E5BF8C3932D58BC3CC972495A78CCB524170A2285FCBFC5DF62300674A2AA0E023E56078838366269B36FE3DF7EDCFB25C8F5C255AF34025A348DD38A8ABA36133F5A2A6813C3CC4104F8419918A6F65B3DC7E5C24603385A84F0A3C0A51A293C4E1C82C960C189A9E704CC20460A6AD2070941AD058359F4A9FBE91E5F6ABA775AAE7D54B4EBA179B70A1CA2752429B521453243804F111C42C37168838F4C765F3CC24F5490262492120A5DC681F57BE9A6BA8A165ABE1C4995310584C265CC7BFCC49D34B171D62B87DFAD69FAA7AB82509013E201209B47282771698B5A717AEDC62049EC8662BC3034C2CC345137428F366735DB58BCCCFF73138201F88AD0C1C9145245AD6E576ADDBF421FA081E6DFF00A3B3B225A2C952B3DF173319ABA0C1F224F5122DCB1F971FEA4D53719F10B3D52C9E3562893BD14A16D396B4AD23E8D7C2099DCE47210A179483E40793687A78FB2AA6CAA07148163F2F3B7FBDA31E7E998351E021668C08F2AB7A4760958896A0B205007A5BD3C357B469ABE15367FD31045B9ED68B7EE310F9AE5B3166594CC371AB00DC3CE96F6E211978D9604C5300100BB867B8B5796ECFE5E4C7B5B1AA57B657B27D400AEEE95FD58091B0E3A56C5CEE0F4BFBE6D8EDDD83C0CC464D8B2B55049AD2DF2A99C6FA0361D2384F6BF3195FEB7840502B3C696F9921FA5391FB7AAC8610A436F95C7794F4E08BC59A02F11EFDB718E62AC0A978EC4CC0A202A6ACB7451A75D5F6F08EED2B3A95232FC17124377496AE9C290CE7F834E8601429510B0AD89277B0F5E717B7AC61E04AA5293C35B8A9DD85A96FBC3D939E499929443304D7A0B576EAC79C326AC729DAD3B9F07109FF00F25CD477840F07F917E4F513E58525E24C8CC72F05C257390493AF0AD275A1B0677FCD373ECCE5E2729CD014848EE576BD9557DEDEB678F8E1D4F9E32D6A0D474542DAAB1F5E7799A51C00F8146BDF1B00A8B9927CADB463EAC7C2DED370E418342905411225B56CC8079DC0D46978F8CBF15A44A9DDA3C629D81C4CCADDC7191BFBF48D794F66398E69568AFD5EF16329716DB8DB6B570C2525248F0A82809EBE40E3ABC9ED34C9B87C42654BE29841E1029BD5D9A9A3ECD72639BE27092654DC312404B83D76AF93459D996B0A7D019AE42EE8D2D3797D2D7D025EAA6C252B4A45432167BC23886CA04F15C18338E4BDAEC9F17DA2C973097390553CCB99F2B3E8AE10DC9C5FCA3A764989461734CAA6CB53211325970E416282F73AD58FDEBF499A435D685D45A334A6BCCCB39CA9FAACA32353D48A5D4D377CCBA28501EE195F182A5A609B4F3136C7CE35F62736CAB3DCC72F460E7AD789C4A124A652F8529332AC5883451B6EF1F4DFB3BDB3C12F22C04E9F8894572A424104A5252C90DCDA805BED1F2C5ED9BDAD37DA37B40F69BA9D7998550D53F4AC51C39DE3605334A60F7601294C9489E10279E3EA77F4CFD805E41924E070CA2664996A09292EEA492AA915624D0DFCDFC45FD50F6A65F68733CB8489A0895318F097A0296D756D6B1DD9FA1DFB66CA5BCE3B40ECF33FCE986F2FCCBEA21A159528A7692840716E06C3CE2130A04F170EFCE71E78FEADBE1E4FC595E3E4E1967B8528F0CB4173C6A6FED0F7FA0B08ED5FD3776B70F96E1B0F879F31290B4CB492A22C000E1D85377E7179FD33BDAF694D0DECA2F765BD9F5565CFBBAC5C4AA918CBABE9C70FD533043D530197140F1852CA85A7A1338E73FD28FC32CC734ED4A71188C34E4A72A9D2D40CC94B0E165E8480D6B579DEBD7FFA81ED86053D9A9D2B0F350158890A4D140BFC9B3DCE9B79B7CD77B2766A32EEDEFB3072AE9196D0BCCDB577CED5B61A6141C68B8A5052826E649E23F9E3EA97C69CAB118EEC0CDC26124949C3E5F302B80151534922C072FE77F017C0B92995DADC4E3262811FA90B750666593ADC6ADCA8ED5F79BE9D9D6196E73D877654CE4F99E5F9A5553E5A84BAC52D7532948E24520095069D2AB0041045A27CF1F3E7FA49EC8E367E73DB554CC34E92133C8495A1697F9A6B91C4002D705ED48F717C4EED06171F82CAA585A0996800B10744DAAC35D3CAAD78FB04EB9CA32BFA322972CA8CCB2BA4CC9BD33A992ED23B5D489794A79157C03856E05137B5A6F618E61F14FB219E9F8C32E5E1A4625CE3A41429329652405209F9827845AA01ABDCE88E51DAEC265DD9DC44954C9602A5147015024B8237AD4BFB68F8D0FE20A6B3ACCF2DFE18DFD61ED599B283E2A91C1C2E674FAD2AB9E002140CCDC791C7DC6F8739663F07F0B70CAC5952972F2A53CA5A492B6C3D2A41208DACFE31E4BCC065F3FB6386C72928E0FD5A56A371598087F324EEDBC7D8F76739E65591FD132CE50EEA5CAD19A2F4F578550AABA914EA438E2C941417B8A549510044DE7A63E2DE2B2AC6F683FA929A065D364CB9F992A5999C0A0901CA1DF85855F56D3578FA378CEDA64EBF87F230B24C92B4E0D2821D2E0F00167A35EA0757631E6A7D081EDA3A43B2BCFF005CF619DA03AC65B926ABCCAB98C86B2B2B521A612BA9AC5D61256A4821D2EDB8D4041F0F2C7A13FABDFE9E33ACAB2BECD67D96CC993E64A93FA832132C924F0CB5247102598D5ABAD63897C24EDBE5B95E6799CBC419694CF9A52975003F72858B543EC2978EC3FB64FD0D190FB42769B98F69FD9176C990698D3DAA5F6EBB34A76CE5D5296DB442D6A05CAB04132A5129005E3AE285F08BFAACED47C30C966F67F1992E3D589EEBF4EE654E676294B132882E1ADA758B476F7B2B96F6BD68C5E1E74A4852B89D251576367B0B55ED6611E837D1D3D8EFB387B29E95D73D9668FED4723D49AEF2AA2A56F5F66685D3D297DF71A71745655429B5F772A4FF002C9B092463CE1F18F37EDE7C4AED2E5F9EE3F27C7A30D331266A25944D99C492B4963F238D0E8E29710E7B1FD8D9393E1712138E4105150E915093AB862ECECFB6F1F33DDB8FB4F663ECD1F4C46A1ED372CCD5BCC34FE4B9C50375B554EB40A5758CC28934CB529C6CADB5F76971517544198C7BA7B13F07715F11BE14FE8B1597CEC3A4E0E92A6216145728129FDC12A1F307F3022A824A64E76427304BA67317208AAAA2AAA96A5C37D7E813DAF7D9B3B11FA59BB1ED21AA346F68F91649AB74ED122A28EA7EB14AE3E8A8AE4B2AA805A72A5B5288525408502236F2F337617B67DBEFE98BB4B9A6066E4B8E9D2319394995365CB9BC0844A2BE1AA65905D245F7EB16DED7F6270B9D60A4CD46310A5997549E162E03D4AA800FCC7527D943E861D25ECD1DAA50F6E7DB776CD926A3CB3479555E59973AD515021A0868A544ADAAA01E3E04AA540C102379C5CBB6BFD55F6E3E20E538BECEE0F2BC623179924CA0A2998C94AA8B042900170A34E434022A1D98EC9E0BB278A13D7390A757168EE1CE84F202BCC563CF9FA747E900D37ED2FAAF48F62BD926629A8D1FD9B0ABA2D52E53387B9CFF00BE6DAFA88412477628D6D7FE52941405C441C7A5FF00A01F80398E588ED467F9E15C939A2113128992AA85A9331F849A9752812D67AEB087C4DEDA77B2F0F2F0EA2C804712554228D4D080EF7FB9EDDFFE1ECEDF34C6A4D2FDA67B3F6BAA9A5FE1540D658D51A730AF45335C351DF3CE06D0F389063651493245C1C79FBFAD5F8659CF677B468CD7012A6CD97227CD5F14B9449214A0CFC214751BB5A8224BE14F6865E2E4CE958A57CAB486E2340C0BD0DCE8FCEB5BB37D3F5DA4E8BD03A1FB2AF67DECD1CA0A9CA73A733E5E6AD50660CB8CD3943E8AB68AD2D2D6992B24A4820CDE4E247FA39EC5E6FDB0C6E7B3730C24C4CBC6A30C897DE4AF993C09525552028B9706CD6899ED6E7185CB1483865A400A51E20407ABBB3DB414B02EC0D6F2FA0EFB42D17DB1FB2AEADF66DD739965CCE55A0AA327AA0335AF6025C5D4E647304708A97533C2B6D2004930400231CD7FADBF81D8BEC8E6B968C2C99C3FD51538CC99264CC3C265F090FC009ABD1FA0687BD91ED29C74A99356B0132785454542805682DA1F0AF28E96FF00E221F684C973ED77D94762FA3FEAB5D93F67F4999B59A2B2ECC1B5538EF6959728F8D34EB2DAFC4D88DE3CAE07A6FF00F875FC20FF004DC873AED2E3662C4C9F252B9726721495BC94AD2C38AAE586973C8423DB1EDE6599C4B565AF2D7DDA4A388917218BF3A6D7E51487B197D12992FB6E7B2EE8CED8727ED3F2DD13AFB33399A33AA652E99CAB4269AB174B47C295D534B47F25008E048277B9BE257E2DFF005739D7C30ED563B23C4F646766982953C4B933940A92A4053121E52DA9CEC361150EC9F6224625189C6E16600A53A884B50FCC6CFCAAF4F08F793E8ECF653CCBE8CDD13DA8D576BFDBE516B1D33995031534197E67534ECAA8450B4FB8B6DA53D5AEB87EB0A2010902D682231E11F8FF00DA8C5FF513DA8ECE4FC83239D95AE54EFF007C4A90B481DE197FB9425201E1FF00D4760D1D0BB35DA49BD97938B918C2552D614900AAECE0D34636B5C3968F907FA447B67D33ED09ED73DADF6A7A792C3391E695F46C65686214CFFF000F42A91E712520254165B2AB822FB99BFD73FE9B324CC3B0BD8AECD649889F3711330F2815CC585024CC29531724D1DB661E5E67F89599E1F33CD66E230C94A553564A929E1726ACC40F4E82F1D247948AD71B69A3C6EBB574490B1002385F6C12784DC01733F7463DB1DB544EC6F617310924A95825B0B9FF00A65869AB59F7BB98AAE538632E7C998CCC41219C82FCF4FE35B7DDBFB336A1D3793FD1114D91661A9B2B7EAA9F4B66FC544BAEA565F42DC2F2908E00F070CAA364C9DF1F9D5C776733199FD434B9630338056684F7E25CC2857CFC553C2C963401EEF736F5164F99A11D9F989EF83995C25259C3EC77607E952F1F0AF98B15CFD56A6AFF00A9341273DCDFBA685437E20732A80DA80998363E933338FBBF869388C2FC36C361895059CBD824920FFD216075B53D77F336793258CFD2B04F0F7C4F78C4DD428C2F6F1E8F1F709F468EA4A2C9BE879C99BCD33DCB28F323A7758A2AB2A76B690D4203AED6A590A429D0E7892411E1988B63E137C46C8B198EFEA09787999662168566329489E25CD32CB14A89E2E129A1A5CB178F5A6419AA47645C4D48E1C3906A1CFCAC19CB8EA3A5EFF1079D56A9DD479CD0B47EA85AD47A8D65EB2D2B0EE6956B491C8820C8B9B75B8C7DEAF8272BFD27B2F95E166829030D253C268DFEDA685EF6B0E81AB1E46CEA60C566F3E61629338B1707FBC8AD6951E62102EA1F436DB6FD4FD6384A8254121300A8EE2D3F0F48E7D23B4B365994549775A48A6C03DDA9B787268C6712929C2A1807E116704061E2E6A3EF1922AA23C441F5F9441DA3DF883EC8A0F14F51258177DAF4B57EDB45630D85EF44C0D41A5FC5B6BF4DA17B3540F3E7613EFB1B0FD8DED1218FC4254B2904120D791D1FAFF88613F0641248D5B6BBF4D7EEDBC39B15299BDCFADE00F3BF31FBBE23FBDA0A38EB4F0F188E9987242810054736D4B915F1F5AC3E51D5004CAA768E7CEF73B794DB96136F5FF10C26E16F4E7EFCFAEE445EF9FBCA495C99916BEDE5E63E7317C37CB7BB3C3F3247450F3F06F5B450309C248A8D4B1D694F37766F4200A9B337AF24C133CF7822DCE08F95F6C5816B961988B5C355B5F0B922EFCA2E99690C12EC59AB4FE2B7A45739CBA47149067CED07A12768E7E98CA172C9F988FBEA6DCF98B45CB0286006B4B80C1AF77AFA6F102A9AAA8688729DC534B6DC43BDEA55C2B49696958008330A88B13D3683880ED276670B9ECB4A804AF8056D4B6A3A6BE4F13D265204D42D49E24B1052752A70E79EB6E5AC7B09EC69DBAD16A3C859CB7357D0E56E4ED064513AE052AA82C14990A3C809BA4FE5E61F899D9E565A0FE9A590563E65A41E24F0331A5473AD87384330C0CD93869E94A14B0524A5816AA5C5F50E0121CFAC4E3DA13D9FA83B45A1ACED1744308A4CC5092EE7B97B0907838070B0520402560711EED26F20CEC28DD8CED5E272BCC70D81C629687584CA98A27FDC018977A066662C4EED1C7B0699E8C7AC4D744B42CB248019D4E59D89FC1A691E516A5C933664E654556DADA76994A4292E24B6B3C2483E15709361331B796FECA9D9AE5F99F64B152578A97DE4CC22AEA492FC0A162AABB8FF00069D070D353331B8128F9F8549B312038BDDBEB406B1F7FF00F40754328FA39FB1E678871B6ACFC2E08327F8A3BB7C7AC74DF1F9ABFEA9B013301F14BB412E5874FEA125019A85C92799BF851C47D21F84F8633F219135350258141B74A6F6B5CD047B573C37170AEBCA3D3CCFCA31E7054C50E1FF006EA6F5B3791DFD6E0C752958644A4AD2A50254F7D3933DDEB5A53484756DFF0029464057862FB99E40C72BFB879E22F1F899A0CA4A65120104B5AF6B3C30384470CD26684EB56B56BA3DB4DB9C7997ED4C8A65FB4C7B3BBAA092ED2BD9F84A8C594B6100F39F90C769EC5E38232AC64B5A7878E5A68D664976D79B6FAD9F85F6B7088999F61BBB980844D1516FDC0E84801C7F916F48A8549FA95229C215C4C35179FF00CB06C07E679FBF9ACE5CFF00D6E238657CA16A6A8DCE9E57E7BD3B9E1729958CC0615256DC32D249A97A07EB60FD042D4BD07812D9E13304DA39449E9E71CE2708CC54D0A41E0B9AD411F57DABA9A56F0F5394C8C3C99893307EDE4052BB8FA9FBC43B5AF0AB4EE774EA8E0A8C9F354B8B240E0FF24FED7E60F97BF0E25619789CCB2DF91E5A27202C805EAB481CBAF4E91CF73DFD3C8CAB3596710973297C2E039649E7F47FB47C9CFF0087F4FE94CDB52E62C96AB6A579C664B21C50250AFAF3E47DB2779DA01FBB1F53FE18646064797CBE220CD92876154FCA08A354D5A9F48F8F1F144E2FFF00B438D54B96B52062165C02D45162FA8F1D6BBC55DAEB5E546669750ED48629297C3DD214059560070C1E42605A2F6DFB5C8ECE1C0C852E5A4A8CC0E0849B8D7CEB7F38E479AE2B1AA5E1C194B0C468695076E5E3A87B50F9EEB658CB5CCB43D14CF1E24BA560A92A6D457224CCF1446DF0DE7FB23D98563D73D18A90485FCB504382FA16AF879B45D329CC2711216A7E29401B331706FEFED1006BB78ED1F2C6574547AF330A6CA2950B67EA816EA92A4BA14DF081DE6C27A72F7E2771DF05B2D44F9589978290A54D515294654B7D2E4A5DEA48E62D48E98BF88D98E1B06A9285CD010801202D4D404559BCB4D0475D352EA97DD5BA0E60E5754BCE975E754A502B2B595192499DC9373EA39F77EC7F6364E4B82EEE5C84A4290DFB40B03A369CF5AEA1B926699EE63DA1C5099890B3C0B3C04B9D5F4B5BEC08D23B4DDA8E75A5EB5CACD3B995569FCD69D1097A95E741A80B4C2B88B6B483C0098924FA1DE9FDA8F85F27B4B8BEE276192B97316428AA58500E402E0A483726FF0066BE7663B5B98E46B9264159092976590CC41D19C035F28856A2ED63567696ED2D0EB3D4B98666CE9F53C72FFACBEFAD3FE6BC6F405B847BC9DE23A62FDD8EF82992F6170FDF60B0B25733149056A42128293A12007353AD9A8D171EDEF6EF34CEF05874954C502901438891A0E7737D2FA562BCA9D40FE459A65998E4B5AEB2F30E38B62A10E2C2DA5248B8F103722C7A581B62E0AEC761F1384C56131081313884291C2A0084F102050D3534A0D2D669D809F332E13B1330702D4CA36492589E553FCD8D1F75576A9ABBB412A6B5A6ADCC337A4A06826969EA6A1F5A112DC0094A9C2081C291EEF2C503B27F0872FEC763B19330F879481984C75704A4A48724D4015FDCF5D9F58B2E69DB1C7E2E6A10A2B28413C2EA2CD57AB9E60DB4D2B0DBA7FB70ED3322D34AD3997EB0CCA8B4E5225F65BCBDA7DD0D38D3E56140A43804428D883BE2C78DF81D90E3B33C3E3A661244DC4718985664A38A9C2AAAAA46C6B5A42A736C5E2E5A13DF2D0966238942A7714A5ED7E45E29276B87091C6E77AEBEB74D4F12B88B8E3A5C2B3B1278953EFDE71DA26E5B2B2CCA1196CA940C8549324200040053C26C0EEF42F6B34426264CD97884CD1338940951AB12407605FEEDBF3B353DAF76A54BA75CD08D6B3CD1DD38FB62687EB6F25969B47F34A0254F0042CC8B00224918F3F49FE9D322476865F69132E4CB9C7102795F7238828A8170581A1B6BA691D4FB239EE2F31C0CEC2E227AD12D29290952CB0670CEFD0FA91AC55D97E635EE553D9A503D5394D530E05A2B29EA9D69D6561478969536B428971424C2A6E649C768EDDFC3FC0F6970795E5D8C28C4A70C9084A972D2414B2284104580F3DE29598CDC564B9909D869CB525530FC892415392FF303A383E1B34596D7B5EF6FDA7285DC928BB50CF5BA1E014ED527D62A57DE34B942C77A5E253C2826FCEFEEE57DA2FE9DFB213A660572B29C112E0AD430F29C905372106B4D4E84C751C176C33395839404C5AFE573F39245050172FD473888E53DBA7695A1AAB37CD74AEBECEB2CCE75496959C569ABAAAA55616E40E24ADF3C3C016A48BCEDE98B2627E09F63F0323087FD1B09356809242A44B64D059D3BF4AF844BE13B7D987E8F1038E602A490071177A8FAE9A6A6B117D41A9EAB52D43F9CEAB7DCCFAAAAF8559966AF3CA4D4D5A80F0124953814D936214622C462E384C8F2DC9300A9383C049932B807CA89684866A8094A40028C4806BEBCCC769B34399098274D333BDE2EEBE6660A7AA8D2D5AF41A448342FB40769FD9636F27B25D5B9DE421B5346980CC6B1E69238A5CFE53CFF00040BC023CAD8A64FF86BD95ED9A7128C7E45835CC50204C99265A8B977214A43F3A9BD6BAF4CC4FC40C68C3C896B9EB432085312402C1A81C1D9EDF7996BAF6BEF6A7ED1A84651AC7B64CDEA74F3C80D869B0B614C881C485165D4B8E0717E12A3B5ED6C73EC37F4A1D99C2667FAC9383C2B77817C2244B00317350351E075BC452BB7388C4A529257C697A959215B720DA0D49A5E3AE55D4AFB4A7731ABAB71DA9E24ADBAA71D53EE38A599597256B52CAF97193C3336838F487677B3780EC9E5DFA6CBB0C894020256109E00AE1D580F17A8AD1ED10B8ACCE6664E272B881A1048B68C6A030E5666ABC4B3477693AB3B3DAF567DA1752D6696CF5F6C8AF4D1ADD6FBEE0414B454A42DB49F092773B9F29A4769BE1764BF12153139A61249AB1EF65A5770C28A05F97D350FB25CEA764AA3DCAC94A8FCA453AFD5BD2D0CFA9BB4AD6DDA356B59AF68F9F57EA4CC925EFE1AE555438A2C820A5CE02A717C05405CDA6DE470C3B29F0B724F845881FE998594B18958E2084252031352C1A8ED4E82D0BE79DA4C56629497514268B3C4494BB0B7D5BC636E94ED33B4DECE686BDBECFF0055E63A4559CB8D2B325D13EE95560A75CB417DDB8829E00624F5B7385BE27FC25CA3E24A7073F192A415243A44C968594BB1A150A3F215F5898ECFF693FD3B018A40593DE2181763622CFBF9DA36679A9F3ED6F9A576A0D5B9C556A5CD4B6C8CC6A6B2A1C2B57F2C210525C7167ECD884CF520EF8DBB15F09B03D85C3AB09829E89689C9632E5CB084B005D82193635A728A5CA5E2F1B33118C33152C05A9481C4FC45CB6B46A3D35B6D38ECDBDA27B6CEC7D8699ECA35DE67A5B2A60AD4DD0B0FBAED3A5C512AB32A7782EE19FB20199E6629DDB7F813D98ED8AD788C5E59869D393C44CC5CA4151513772924D75BD2B6ADFBB11F11B1B904D9B82C4A55312BF941366B5D8BB8A7A5ECE7AE7DACBB7CED8A94E51DADF69B9D6A1FE2922A285A7EA32E4308A732DA4AE95E42561D4813D3AC99315D88FE99FB33839A56BCB70C9EE8828224202878B39F7766893ED0F6867E67C5364932CADC800D01FF0026E47211D79A9CCF2D06BA99346E51B34FC011C6F2EA14E71FDA59714789449F11BA8DE099938F42E1BE1865F95E1E5CC91C3DDCA1F227858D00A017A352C34B4727C7E0B187172A6AA615AE693C40D804B6B6FB0D8986AA253ED24D45112A6DC50214A3050526410150A9E7D248F73AC4ABBFCBB1197CC4912D52D52FA8208B1D34F037AC4FC932A470778A4A66242788022B6D8E9D5ECC77B799EDC7B60469F6F43653AE7356B260DAD2BCA9350F374FDD9F1B8982F25B3226C419F2DB1E6FC2FC0CC8979F9CE152B0FDF77E66059948E3078B8BF71F9BE96B35AED83CEA52705350270AA18004D4D59C3DBD8058456B4E8A377EB05552B156B5713882B594A9C995AA4909F12A547D63963B2E7787949C261B2B92014A502529A80064A45052C00D3A544727CCF118B56350B12C2A49987E7A1FEED989A9B5ACFCA2DCCA3B77ED9748E937F4A69BED0732CB34CB882CA7256DC7154E50E921C484F7A1290A2A26C800CFC38FE7FF000772AFF51C366430B865CF52F8CCDEE659980B823E729E22D472F5B728EB595670A95932E5A9652F29B85C80696634F1F48A997589A4A751CCFF00CC562D4E3CB741BADC7945C52894F52B24FBCC0DF1D672D9672AC36170E80C1090030D801BEDD1E968E42A44CC4663326C90425535CA49B7CC6C4DDDA837A5A120AF55434C9EE032DA4ABBB571F115C9BCF3116B9E7BF9CB6653D73A5A454FCA34DC375F3E9511379980BC3CB48A900B80795F402D460C4794642A215008B7E5BEC3DE01EBB8C3DECDA3B9918A333E5252E09D686C2C746B5ED588CC04B4852828555AD2BCACC5B9F95995B5504CC72E5B7E1F84F9EE3103DE4C5E2A6853F0F116F07E41FECFD0C6B98E1857853C54E54F2F7CAD0EAC54A85E6E39C8B18F78F4FD92E3D6212661D4011C377E5FC74D1DC5EB0EAC55A81B2A662DCA39FA4DF7F8E1C4454D90B0E18815F467BD7CBD63B31A83FF0030F9729F3FDF5C5772ACAB109E1FF714DD5EC0023C58BB56F1C87064FCBCF5237BD9FDF8454B9AEFFF00501BFE1FBF23B62EF2329594FEF248BF27D37D7F2748BBE560F9DFC3C0D9B56AD9A2B8CE261572771BF33B7A4795B9DA30DB13964C40A2D887A8D46947F7CF5BC6096A6000B063CECDA06EB5F1115F660B2961D00F8942537BC03B73FC7737387196CA54942C2D7C65ACE76B6B4BDEE1E2D3804898A4BA4900B7A87B3378FD1C44F3B1CD74E7669AB726CED2F2D2AAEA80D5537C6A094A0A92D789174FD9513F64091B49C72EEDC61246213338A5853F1338043814A1D4B57A88BAAA4495E0D49525259140D770E5F7B8B92F5762447BBBD9F6BC0E06B32CAEB52BCA6AE9D872A11C21E6EA389A056DC2B885D4549909244CEE31E5DCEF2C4712FE4E15851E152404941770411B30B50EF78F3E76CA58C3E216A909EED890C000FC8351CFE34AC535ED49D82A35A6529ED5740E4E9A7AB6997D59BE9DA75A54A76525A0F155B7014F42516DBA623B2ACF335C3ABFD3B178F9AA2974A165D299A935E16FDA3803246F7DE1976471844EFF0076BF3A0A5CD5241AF9FDEB5871F656FA6A3B60F628EC4B24EC374A766CF6754BA42A2B02AA5CCC9144A52AB6B5750B4F74EB6543854A5241BC81320638FF006E3FA61CB3E296738DCFCCBE2C6E2780A94093FB53C3B905C72A0F38F72F60BE2CCBECC65430D310172C20339B33B3537F6E4C770B49FF00E240F69CD7DA86974E649D911454BAF52A12DA73AA5592952925C20A99E4992795AFE7C5F34FE89A46094B64148960924836A126FE941B6F0DF3FF008FABC3A138B4A949134AC896096649203902869B56A23D6CCB7E946EDBB32C8727CCF30D00AA3AB553A5754C8CCD874B8A7109264049038493CAF18E793FFA5BCBA54E992C4E49282C42914046C7463A87A5F78E6B9B7F54D8891296944A293C24385549B6DADC0E61A299ED17DB175FEB9D65A375E55E96FF0039A3D756B651F5E689FF003894A1710009001BC19E587184FE9EB0F830A40C425282188018116FF9023E9CE38ECEFEA5313331C27AE5296EB772A22C6E28CC5B4DA2E36BE93BED716BA5A2CB745B8E14252DA17F5C6E13090904CB7113CE4EFE7784CDBE03E4B800A5290272E6D4B121D89ADEB4F623B1645FD5CCC95874CB9A42025200E2581A731FE0B062D13CFF00F78C76CB45979ACCD74D251E00A4B66B2941822C2C276B0B6D1B6C6051F02B01895BE1F0EA4826CEA557A380F5F3B3E8669FD59AA705844D0285C85E8D4B6BF93BD693CFFE94CED32B5EAACB2A749A99A3A9A6ABA45BBF5D6D40F7ECB8D6E102078B91F23D7177C87FA70913264B5AE5174A90B49E134620EAEF51B8D2D58E4B9E7F5278EC6098133490A0A0C0D3E67BD18B83B1AED1E5CE7FAD2B97FC56A2B1A5533B9AD53F54A417F8E3BC79C7AD06DF6EFF00083B63DA3D83EC09CAA4C994A5525A5090E9A06006A4BF3D8EB68E099DFC44958F9CB9B3308959592492D5737A03D6DBC5199DEB069D0950A8E2E2E20B4F111B5AE49826DCF9FC477AC16449290854B414A406FDB5B3863E477BC404ACD70D9B14BE1C21ACFA7FEDD2CF435F18A7B506A469C04A5C22247085189322C41E66D63E51B62D797E4D230DF34B9684ACB5001E069B0FA18939494380848036B742FA3015D5AF58A8F33CE0155DC8E22A27C5B983B8B4FA1E67CA716C912A67CA9324CCE166A3F326C69E874261F224226065241069BD01E777B58E910BCC3356C93E3937BF15ED6E93D39CFB8E27646267A180C228B5D81B55A8DE7CE159396C90414CA1D5A8DCE84EBD1BC221B9A66685442828F8A4CC98F599300733D05AF13382C50278A7617BB240624786C0914DE9A4484AC24B42920A1D542CCDCF46A90DCF4AD6227515C8415149009DC8B4EFE9CC7BFE18B1C8C52267082C4358DACFAB8B9DBC6257825CD480B47101448B81666A7A8E9BC30D4D625704A8929B013D77E7E5D2FF002C4B4AC1A26BA811F3352D517634FAB57C21F485A657CA80C9147FDA080395EA1BC690C4FD741549227A137378DBF641F5C3A392CA9DC2ABA81B9F114F7AEF1212D32D4C4A58D093AF23F7F5D6120A90A0AB9BC5A48B74236F3103F1C18D9A8CA25A4A93C6E0806AFA3E9AE8FB43D4CA3352D2DC70D9BAD4D7670046A55401D2D7F4F5B1B8F761B4BCF70D3C1E342411404B1AD742F4EBFCC2FF00A25CCA4C25540CC0D35AF263E35D4437D655B29E1529E5A0DEE0124817E578063CB68E85EA71689A03106DC2011EF53EB6687B8595330A0894B28B384D1DFF003E957B086F73336F84B6CD42D40FF470290099EB11BF3369EBB61BCCC4E2CA9908330A59A9E9507969B0787ABC389ACA9ACB2352C589A8343420DBEE61B8D0BB592EAA95252824951793C4679804D8EFCBD712381C4255FF00F50099007ED330815DEBF9D4522470D3E5C84B2C150B003A369CBFC5C9C0AE812420D32BBC1027894B00C5E3700C748BFAE36C766794CB0D3319294002C389346E60E85BF9B4384E3E5A50A12D290821D55677AEAD7A873A36E63356599AD78032ECA6AF306D32169650F2BBBE232094212ADFCC72DF618A466BDAACAA43B4F94B4A6FF324003667D8DBEACF11E3159782B5AD6896AD0B713F27D08A0D2ADE12BD3BD9B6BDCF9E4D3657A5F365B8B20049A1A94A2FB4AD6C817E4662FBF2C52E6FC4CC9302A509788912D44D077881BFFDCF47A8A6CCF0CE766523898AF89239368F5F3B5B5EB7F647EC4FED1BA9592EE5FD9E2EB1901254A7F33A7A5EEC2EE0F0BAA4933D22C79E29B9EFF51585C866265CB2311DE71550AE266009A876D9F5BF3868ACD70284ACCCC426514D5296B96347A7D757B18B5322FA373B79CD78467196B7908541505D6D255F08F4EF8EDE5EEC5626FF0054D85980032542EE0A54DE3F2F56B5E1827B4985492EA0A4BE8A29FCB03FE22CCA6FA2AF523A38F3DD7AD50A94077484D132E1FF00571290E72F3E57E830D07F536B72AC1E14CC209E26251C3CEA9AE85EC393B05876B30E1242425059A8429DB91D5EDA58D61DE9FE8AE0820ABB4B440DBFF86A26FBC78EDB9BC09C34C57F5238FC494AA6E5A66105C1E3A83E29E42B082FB53289FDE189DFF173AB46EAAFA2DA9C371FFED6114EA13C08394A55DE1F52E7863AF5E76C43E3BFA94CD019694E0A64B4D4169855C351A70F2AF4DCD7795DA9C3A1DD6140DC7133F5B575AFA6B5FE75F45E6BC4073FC3FAADACE42BEC90D314A1C8DA429C1E42F204DB78C2F23FA93C50E156225AC002EE49F06497F4F4787D23B5387B258053BFCD4F0F3B33EDCE9ED4BF4777B43E996C2E9B224D734EF19EF1BAEA425B0904C96D2B24F15E39C99F2C5CF25FEA37018C5894A05C517C4952589E7C3A837DA8EC224A467B85042C043F25025F5737DF5703778EAA6B6EC6FB44D0150B6F55E4398875054389AA479C4A00B9FE6B2DA926D17E288E918EA7967C70CB25A4292B94870EAF9C135B386241DEB534262770DDA3953662509295710600A9AA2B525BC45FC1E2AA5BE5B5C3CDAC380C354EEB65B24C90788AC03311B89DC62DD84F8AB96E6B294A18847180591C4002FA00E2B436E578773D5331E4F0A824A59CA485B3EC5DFC34D8E9A066C95BA9A761BE3A8BCD37D8481B9872C36BC49F5C472BB55FEA738CA968E1492DC4CDADDC063BDCBFAC269C9E7A921E62B84F11EF1C93CA8FAD9CF8467515AD28B694B85156DF107D909527B90A8E1874001CE213B1F0EC45AEE8E4F3023BE91892B2594521A85BD59FCA1C232AC4489615C4BE136507636A91D2F4D6D5847DF892413277B9927CCC74EBD7094B54E0A6C42485248F995AB6CFD3CF5A5779721082954C4F1105C3D811C9A8FE7E158E7EB12209558D81262DCFF2FC3125326A26A50090B2072F201B4FAF487188C41527810A5252CCC090C3D3CBF980BE15F68957A927EF18D5D2400500B6E7F888D12824B82C6B6045FC63732F4C80600B6FB03BC08B72DB029408AA016B57FC5BDB465482AA1538B5BAE9D7DD21636F264C44DA4733F2B72F5B7963744E280C9A0B30342D4AB01E3184CAE0FDA5B5760EF1BFBF09E1BEF78FD8936EB1F2B37514051213525F66A79746D21708E200AABB121DFC1E961F6852DD4A6D06D17DE4738FBBCE7973C63BCE41C73F6D4FAC379B2900314860FB33574BEB6878CBEA412B24DAD37F75B616E971CF960331F4F5FE222E749410484802A6C36FADEAD7F08EDB6A0040701045BF3C31CB7304BA7FDB2FA579BFA3F378F3BE0813C15616661576D74F22D78A97340544F0DE27693D3A6DF2C5AA5E6A5293C2082756FF001A37BAC5E72C07C68E3A83CC7DE2B8CE5278556379E477822FEFF909279989C7672B03F6B9666DFA9D41BEDE16B9E0DE83D1EE29AE971E7B08AC734596EA29D441E0495950E5E11B73DF973F7C028E5D98AA695F10201DFC81D18EF4A79C5D3286A92C188B8DEFCADA9E95B98655D7AD550FD7107BA2A40A640994A93092A02D1E200ED1067152ED203384CB9A1E571B51E2EC84F1C9E009A81F317A105F6E434B691EA87B17F6AD539AE96AED10F362B73FA1EE0D0075F08516D6B538EAC15595DD340280327C3000918E059E610A662D4B5129413C619DCA8B245011AD0ED1C7FB6F9605A953254BFF006A603C079A5B8DC1A8A83B69B47A5DA2B519C9DD65D72BCE6B475414D66C1D6781B6A41406FB95CA48BA91294C18E2DAE68F98658713254152FBB5A6B2A60357049D1B50E4127504B472CC0A97976238D880F50E5AFE43C3C63A43EDADECD20297DAAF674B41A0AF4AAA33BC9A9A9D24502909096C95004AC3CAE25C25238660ED8E87F0A73F4489F3F29CD4044F96129C34F5B0FD55092364F7618126A6E23AEE4D9C4A9D2901DDD8104FEDDDC1F3371E05A3ABFEC4344731EDD326555708144E540A9429B0A054195252786265244D872F5C4C7C40C6CA380C47E9CA44DA061C24873A91B8A3BF8C3BED14AC3FE88CE511C2A4121D80703CEB4B5483A08FA26A3AE6695960B550AA86D68285A12DA95C240E14400098D87B8EDB63CB39B058E352A50410494A9C55EA4FD7634AEB1E54CFB339471CB94140A7BC29E170D73B694F26DC9892643A5DDAAA866BAB6A0B742B2E29E6DC470020FD910A20F316F973C73CC51C4AD6A329454F4F94BB7BAD4EDA5A3599230DFA633BE57E1A3B6DAEDD75AECF120CCF55E95D2A834B42DB4ED50078DDE107855CB84949111CC1E9230861F23CC33450E2428F0961720FF8F2D4F3A34F993B153552E44D52425458A7C7A7954DF48A0F57F6A4CD5171BA8AD524F8821B4A484EFB5845AC49881BF91E89D9FEC7CD94A4999873421DC3BDA963BF8C38919762D5533D570EE4DA806B715A39AE9143E79ACEA56C3ECAEB514A1EF152AFBB42CAF80F12BA14C6D7371EB8EC99476792908030BC4A02AC198598EFA6BD280C4FE172013402B9D5531A834AB5A87DD0C75E750EBACD16FD7BF515EAA86698B68427842678FC2600D87BA062EB23245CA4251264103CD893ADA874E4EE3533527B2D216C14B0A70EE69B1621EBE3D62AACFB53BA1C4968948209510A241E200FBB7F2F7462DD90F673118824CE2A961E9C5B6B41AD830E6FC9599934BCBD8CA214FB537A0BE962DB83CABECC351BAE182BEA6EAF5226E2C0F95E2D8BE60FB3699443CCE2F02C7C2DBFF0D573250490C1B42CE6EFD6C4D76A5E910DADCDD6E470B920C830AE978DEC7E43C862DB84CBE54A041097A0A8BDB7BFE7C62730F24380C5A95B3EE3DF5D5E2235F98BE6DC6522F2662C3CB909F3E76224E26E461E426A780780E5B0D89AFD627E4CB40482000534059DABB6E74F1DC4465DCC9C3FD44949224107E22FBCED8713B2CC3E350C3853B148A55B40D6B757EB1208C009A54501ADA6CCD5FC4335557B841324037BEDF3888E9CE7E1ACAECDA10070CD34B86ADFABF95442A32E54B7E21A8615DAB6229B5872AD5B055ADC2B009514C4917DE46F7BDCF5C494ACBE6618057116A358380CE19E8D4E96A5A164604B3F091ADAA6BB5ADE81EB085FA9B9922FBCD88E563BC8B79FBB0E06231086F914AF3A6BB73FC3DE1C0C3B1143535F0A0E7A1A68C79B205D5A927C2241BDCC7E22F63373870AC2E1B31923F56B4208144AD41243BEAA21E9A535DDE24B0613294788B6940ECDAF20CDF6D0C6C69398559029E92A1F9B70B2D38EA8F580DA56A3E71F28C44623B3F93212B51C74892054ABBE4D80D7E70283916D5E1D4CC5C8428A52A4BB56C35A5F517FB1898E9FECEF59EA4714C659A77347AA8A929612ED154B485294760B71909BDAE2C23CED48CE3B4390E43C6A939B61A7AA557804D43BEA080B27CD9EACE2194ECCA4CB524AD6025479114205081F9D83DE3B1FA33D823DA6B5829AA8A8D24DE5F93B852A354E56D105A5B55C9EED4B42E40E5636E471C7B35FEA7728C8B10A9070DFA8992CB06248537309203B1673E7584F159E6065CB4893344C24328BB70B36F42FD37D03C76AB4B7D18342E37DE6AAED03F83D43010A7E8D1446A038A31C480B69C8B796F6EA46396F6CBFA9CC776904B9595E58A9281C41644E32D9EA09701EDC9BC62B38EED62A505044C03621890297BBEBF715A76234B7B0C7B3A69A6D0D66D4BFE2CAB4402B57D6A8F8C88BD94A001E7726FF001E653FE26F697304F0A27CDC0F15E6199DE316BB13FE69688299DAB985FBC99C6F70297E8D5D5A8DCDE2F1D37D897635A24B8E696ECC6932E53DC25C79DAD35A1E0DC701087D2BE1E1E805EF388239FF006967A97FA9CF66E212A6F9423848FF00C4DCE9CB486533B461638904855C7CDE7AE8DD7D4C58ADE6EBCB1B0C65596E5542DA4404A72AA25280116E3EE38BD6FD245F1018ACAE7E366F7B3313882B26FDF4C0097B9653005C0B5F5BB207B4734D02CD5C1D7E9D46A2352B35CCEA7C4FAD3FE90C3696072990D848239C11E58565E117824A93889A663B7EF256D5A312FB8B7E62BF9AE753D750B21C9700967028F5D2A77F368D2A7EA957E37D20C41EF17CB7E7EB6EBBE1C24E1D54E140F2FC52FE3E110A3339E47EF556ACE58BFB0EF189A779D952DE748039B8B813D25437F9ED6C3D96990406425B56001E868EF7E9A5A31FEA9882ED315E2F4F33F6869A969D6C9875C302DFCC549173D7D3E7E787C89120904048D9C0DABB7BF53FD4E79A7117143534E8FC9FD3AC3154BC040A975D41FE8BAC91783B137E5EB1698385D381C2CCAA9085686836E4FBFD615959A620280E3350C2A59F5D77E5A5EB0D8E54BE3FF97CC9F644DBFE27431CFEE9C67FD270CA344A48D030B9F3FE6FC83E4669884D96A0372496BF3FF3053E619E33C6E0CE9C5017871B2B00F48595020F39C2BFE888A04A824AA80A5203D2EE08E5F6112387CE31003898ADB5BDADEBD6DAC6AADD4A9CDA9D596EA2C872ECFE81D05B794ED1D2B2BE056F0BEE4AE483BA4838513D9854A2A5C9C64C96B50A1E252803D38A97B35EB1252F3EC48293DE2C503976A35598B8F27A523AFBDA07B24FB3376A34AE53D16408D199ED5059773D6DDA9A914AEAEE1429414B6A9262DB74DB1B6165F68F245CCC4A272F1C5052A912BBCEEC283BA83BD29A11BD8C5FFB2DDAD9786501899C4059657117E837EB56D63CC6EDAFD81FB44EC9456661A5595768FA71216EA33AA608A27A9DB00A84D224A9E547D93693C338EE1D90F89E8C5A256071F2460F14964AC2D4286CE16400697A86A08EC9957697018A530527829C21C11CDDBCDBA523CF9AA7336A5AEAACBF36A3768DDA359406DE694D380DC292AE24851E1B8F10EB78C77CC9BB43230C12B13C6202C0243BD1AD42DE3E517644FC3622524A4A4F10B023A585CF854D79469EFD179880379B7A13C8FF00B6F8B81C761339960238252D983303B3E84B9EB4BC4163B0E2BC15B503F5BB36BE1A93A6C53E821245C1D8F5B5C5BA1DE074DB9C4FE8E76114F31F8093C24B904540D0B7E5F788C1294160A9F57A31A386234D1A30EF93FB9FCB193300A91EBFC42BC0373E9F88DCD3DF6B87CB9FE630779CBD7F883806E7D3F10B1B789F23B1FC2D1F3FD70779CBD7F883BB1B98C9EA854A60FC083F1B5FF1E671A2E630AD01E62BD76FE6374C9777A0D1DDFEA3DEFA728A93C8DBEEF740DFAC1BE11131C5C3D039B5EC694D07DED09CD906AC016A74DF7776E7B0877A0AA502A8369111E51BDB73BF2F2C678EA694A372DF4AC45CD90E750350C0D3EA7C34BC77CF51E5EB71C5051932AF0404F3200046F7FDED8432B12183292C19EA090F570FD3D63CC9817E2041A0D2F4B963420877F2A4545A859772E085200A5EF42A54921F2E70FA4F0C6D1F9E2DF839586C43844C042400414B33DAE35B6DE517DCB9822C1880C7AF2F2ADEF152672FD528A8877BD1CFC011689E83CB7F5DB18C5E512149078D2C7567B9DDF5736FF371C194B25CF2DC8A91F7E6CF6B456F9A07090A75239806C67AEDB7A7A4DB7849B21182A022AEC436AF7B74FA1BC5C32F21201497E4C777E57AED5884D70001B08DE3901FEF73CA715FC7244E428F0D4824017A1B791F0A6D175C11331043162C1B660FE15F758977649AF33CECFF005EE459FE56FA99629EA52DD692B012A6DF5A5BF182608095288F7F4C735CE32B528F1000A49571029D85C93B35CF8436CD728958AC0E213351C5340FF60B1F95CFCD4A03AD76018C7BED91EAAA6CDB2ECB731A65A2A29336A661C438D11C3DE25B4174786D3DE133D31CEF1D8732C2A581F32497B549B7A5ECE2F1C073FCA15855AC80C1CB162373E9CDDDB58B9F24AFA4A9A07B25CDD947F0ACE98729EA9D7877A965250A42086D5C533C53E1162271CEB3ECDC6553A44E49289D20A8A568F96F7729BBF32D70221F2699311315FEE94A4104F83DABA1D1C6D1D4EEC5FD9A33FECFBDAC296AB4A65CEE69A1F3172B2A1CAD282C329EF2956BDD60D92E2C8104440DA6D50CE7E2262716854B2E02B84125454DC2AF3AFAED61161CFB389588CB061D5891DECA4A8218D55C40BDB6A7531EBE64793653A529EA5FACAA6DDAC078D146B4825854CC49242A77988B4EDB55B179C62335526570144920052AE5541E219ABAF8011E67CCB2B2BC72A709DC40ADEAE3FB9C6AE06A01BD05E23F9F6B5ACCE10F34BE1629590784A385B1C2245B8426F6F5117D8E25328CA6520FCB24952AA5C955FF00F559DFA56D589718713B0DDCF7CC4A48DB403536DF4E44B375A7546B1656FA99A373BC5D39525DF119BED249BF2F2B7588EB1D9EC9A58964AE5A52E450A406F120120FF8E6CB2CC84C99B316495125C5BA915A7BD6F1486A0D50A056A2A04DFA488E62DE9E98E8784C0E1E4814492350D635A90187E6AFBCCAF00A4B324834AB1F2E75714BB549D6A1CEF527D65B2B5BE5A53615C12779F2E5B01F0C5A72F12D3312132854B6E5AFD0EFBF898504AC4A0060AA52943F47AD87561147E6DAA1E53EB6CFF310A2249D94394DAF07998EBD063A265987C34D4874A5058559EBB917AE95A3738591331628EA013A69FE0DB6ADDA2279C67C9643243E58EF02B89253C7C7CA24ED1C84CE2CD84CB82D4B200570B70914636D285C1D4D1D856B12983953B140F1254403525C9E6C0D9F666D5E21D579AD1B92A7495F9DD03DC200F5F85A31312F2E5AC072CC5A877E96A6B5DF78969381525884B39A505EDCB4AF97278D556654C920D22E5641E23C53C3D01067AFDD322D8772B2F41238E604116255FCB8E571B077893958650E1E305AE094B38B0667FBD9C07BB1D43F5AB9716F828BCA2104C45C5AF7F41720F39C2BFA1C3BB1C5A470FF00DC001B33A8EDA8A57568934F0A40484B1FF95459C825E95BEA46E2195758B0A8A5A4A82B9873BB65D7E49D884A52A22FD3A6DCB0B7EBF23CA10AFD66632934FEF58727C4D39FF989EC0A4A05D04914248F3A9D43FF00910FB94697D5BAA1D45365390E6B5EEB842508FE1B54CA5449B7F30B010073927E57C41E3BE21766B02852A5E658770FF2F7A8A9E4EA716F52D0EE6E265CA6134A43E80A4DBA758BAF4EFB1DFB456A250FE13A25CA3A77F83BD79EAA6124A55B1097824A60192239DF96396E7DF1FB26CB57C266226F0F170942F8830AFF00692396B7B3C68730C1A038989516622CDCAA3AFE2B1DA1D19F45CEBECD908ADD65AA5BD3E084A9D6BB962A7867ED0FE5BA0DAE3913CA39F3BC6FF565270C95FE9307FA8526C97297BD1CA5B415BDBC5BCCCD7082C108AB12EEEF6A55B7B45FDA73E8DFEC8723528EA8D53FE27523861A148FD206787EDA7890BF1F19040998F8E395F68BFA9CCF7B41C49C3E5F3B0411FB4A2612EE4D7E516E6C0F48AC66FDA456087FF293434CBD02883E20FA5FC5A3B0DA47D9DFD9F340703990E8C65EAE6C828A879C79E0549FEA28792B499B7236C73B9BF127B639B288566B899725414152FE6143A3B83EC86357A64FED1CE9B314B5A895A8D482C36D282DB8BB98B869AA58A64A5A6724CB1B61B1C34E96F2EA442909800CA92C711311751B462117271D8854C9EAC7E20AA6D55C53A6904F205675A9A798863373EC4AC01C67CDEAE343EC55E1CD2FD4D4A78471B083601B529A17E894948827947DD66B338E516989EFC821CA839FFC8824FD81D4C47AF339EA720A8F16B51BB8DB9D3F98D468452294A538A25DDF8D5C5B7BEF37DBCF1A771FADA22477406A05075A026DEED0C311899F32E49376726DABD7C347784AA4324C828F23001E5D0CEFB637FF004DC423F602A6152E453CFED5D79B41326AA951E20BF58E50A4A66556E84CFC24DBF19F2C06662B0F4EE896E4F50C7C793EBD68ACA335C072491AEE082E599BC6B4DE352D6CDE4A63F7E53BFECE105E718B92DFFCBA88AB104F3DB978C39E09859A85AAC01E5A9D2DF88C5A75A4856C7C847E53E9FB8798654ECDD1C53126504EE2EE48B167F1F08CFE9153182FE63573D6B6EBBD9F68D6AA865332073E6246FE40DBE1F761FCBCA59BE634B6E7ECC7CE3539730D0B1D6FD286A7C18BBBDA105454B728BCEFB1E7EEBFC236E987B2F2D20B124333B936AF3D34D7CA31FE9ED7040D75F1753F46F65B9CA84110543C849FDC7CF0F51810CDC64B5F95DB5AF3DF58DBFD39C58685EDE05DFEA7470CF0D954A6D7C3E14922FF003E5B9005FF0008C3D9187E1242AA92E1C6C00BDEFF00687787CB9249A07D8536D7A8F2AD21B1E423FB42444FA5FA81B7E1BE1F22525CB38E8FE546F53F7872701C24961D0D7C3A569F567742B284F100A067748833CF9C7FBFCB798274B0148048AD0D08EB736D9B5E90230C906CCDEF7E9AF386CA85260CC08312204FC23CF7EB783862BCC71F2AA994A34B3134DEC76E9CEF0A09006AFC9BEEF7DA9E570DAF02D34F5624A5229C0E2480257C5B7BF6DA4C9F84BE5988C4E34844F4AA5F17ED7AD06F4A74FA968AEE7388C4E1969FD3F130AB87172294E67EB0647A9730CB4B9581487B2F78143CC54A50F36A6D52850E07828010790B1E9C94CDF03879C8017F22E59E274ABBB248A872962588F1B8BC4F7677B4F8EC3AD1C4B50346049DABD3C5AD1D6FEDE3D913B30EDD32BCC73ED0E8A7CA35EA9A5BCA2DB6509A87402A212DABBB641E104481E7CF09E4DDBACCB24C477338CC9B2414212A249090282DC44B6B5D23BF767BB5EA9C2524ACF0967756D70CCFA53C447833DA4765FAA3B34D4359A5B55D15465CED23EB4BAFB8857054A428A9252A808BA40FB24EE3D71EA2EC56732332972F153316996DC2A282B1F33B16151D08AD6B526BD6B059849C5042E5965AA9C1722D5AB3EF70D4E8212E555138D34C50345A6980A06655C449B9955CC993B9FBB1D4F1B9EC9C721126524112D207159DF9B68D6D77A51DE230E95A8AC91C440E2200A1B587859B972D1C6AEBF21F96233BD2400D416AFF0010DFB8FF00BFFF006FFF0054668708993F2FD318EF08B06F183B8FFBFF00F6FF00319F7C46CA23DDFA6326613704F53FC41DC7FDFF00FB7FFAA39EFF00A92A1F77EFD0E1099340D58ECEED7D1BCF997D614461C382EED7D1DDFAC6F6DEDA0CFA5BCFCC79C1C23DEDFE6F4E9CBD3C79C6B3648014F534F7D7C07850876A2A88E3BEF69FD8B6F06FD6D80CEAB1557A7BB36DAF945CF94CEC1A95F4377DEF4D758F7DB59FB27D26A443B5DA635EB4942C2968CBCD121244EC8EF56B493FDBFA63CBF947C4ECDA44D48C4E1A64A941899A492E05E806EDE7E11E55C0844BE22B0F41C20D385B67BF51D6F1D57D4FEC9BDAC65EA29A3C9139937E28A94D653A83813B28202D453D62FE9B01D3F2DF8BB8698024CD5255F2820829ABEE40BD6C7E916DCB6721012153122F471A8B73DB7A6978EB4EB7EC3FB48C982FEBDA7EAD8E1E204B2D29F802D6EE90A99E9F0E98B02FE26CA29ACE43B3B1983ABDC1FF000E368B860F1B87494954C0C0D9C397AFDC98EB8E75A4751D2A887B29CD94429524E5D569098EA7BA88EB3B615C2F6EB038E5813F152D1A00482DA9B97E9A79C5B7058CC3A923BB5252DFF70735A6AFA68CF4A59EB6CD686B698AC3F4952D116875871B20DADE2408DF9F9CED8B049CE32EC427E4C44B503A710D7C7D9F38BDE498A925B8949B860E0877EBEC79986BC1D70A9A69EEE8929936B292414C90445F698E5CC5A2B369D84282D310EC5CB86E46F4FA3F9C5ED69C2AF0EEA29720FCAC0D1B4A56D7E7AD48F5BBD897B40CC75664343D9C966A2B333D36427EB010B7439F5A73BC400A09527C298FEAEB2236E319EE3F012664D267A0281759E260C1D99CB5A9A39DEB1C4BB7B83C3C997DE808952E6F1F761C1248FDCE2E2A4DC748F63B4776415EFB8C661AB9C34F42D842A9A9140053F61C40F010A4418FB42083E58E19DA8CCB09984F54BC1ABBF525C4C20370F9D08D3D46B1C1262E5CA4620A2684A8711005C8D350DD69AD758EC054578CBE9A8B23D3342C656FD1021CAE86DF754DA882485A815094822CA3BDE6F8A0A32B5A97326CC26622614F025B878384D41A56B7E948E5D98E678C998832D2B581C443B96356B68D5D76DA2B5D4B5685E66A78B8BE3504F7AE952825E21104845922FD2D04C729B4E599710B4B49766B0766E751E773D69B4DC22D720CC2A3C5C2E473DE9A170DCBC22A8D619D56B4C2DAA5580D1042B848063A7AFAF39922F8E9F926024F1A4AE50E2A3063E2EDA534B73310984462BF50996A52B84A83925B5FA1BBD0C75A33DCE99CB96A595CBAF93DECA88BA45AE491E91D6F16C5B71B2C20CA12889628080DBDF7726CFEB58BDCC989CBA52149F9CA920921EB4D48DA8D14CEA4D5C885F0EFE216923A5F96FEBBEF7C5E7B3B9461315C2676252E786854075A936E9E109CACDD2B3F3CBF4AEC28D4D2D41E315257EA1A7AB2454B6F786780212E2A49B5C207BC75F863A748C83072C20CB5C8530A9336586B6EADBD626F0B889136E024D1DDB6AB747D08E7CE34BA2CD337738327CAEBDD5AA424A28EA0DE3707BB20FCC5B91061CCF46558297C5331D2249009ACD411E6547C6C37E526818472192E1BFE3ABF87F9AC3ED0F60DDB16A984E59A6AAEA9498E02F27EABC1C7B7FC54A42E6D244C75938A7665F1532AECC71204E938E4BFF6CD4929035F94A987D5EBA44B613F472C1F9D32FC8B33D81607D88B334FFB047B43EA2527F88E548CBA8D712A35348A294D8981C4156116B138A4637FA95CAB0AB5265C932C870C3896D70F6200E861FAA7E0D80EF25922A15C4915BD9F77BEF17264FF00462E6301CCFF005CA72050E12E205222AFBFE6A00A1CF0F0DC08DF79B629999FF519889EEBC061D734172BF9CA0827F6B710F5AD199E90D66E6928278664C42B87FE991C3F2B9E4EFCBFCC5E5A4FE8FEEC5721EED5A93509D44EA2EB47D5AA69C2C8DC781440980091B75077A2661F1E7B43382C4A91370EA2E1333BE2BE1E60354F2AF5111ABCD81042A7858D8003D6AFF6DC98BFF21F673F678D2602F24ECFD8AB7EDC750ED4BAB00A2784F76EA488277023998DF146CC3B5DDACED3F12B139DCF4A0542424A59E8CE0B9D2A5C44163F3C561DBB952ABA851F1B1DCFF116AE5E9A1C95A14FA7322CA72E69B84A5272EA275691C80716CF17BE7CE462BD88CBB34C414AB119A6216D60264C079D38ABA73110ABED16281A2967672487F115E9AC6E7EBF50BDE27D6CB68FE8EE5965B007A36123A7481B63323033258527F50B98E0385F128EBAA892DAB0FA0AB39DDA0C58F99D55BDDC78339161EEAD8A756E2CF7F993A49DDB8584CF9C1F2DC6D63118789CB4104AA5850ABD03DBF9F462F4664BED062839F9C93677FF003E7FE5400C34900B21C0B175973681209124F2F5E584E6A8E0182240505120808725B5766A79EE7409CAC7CEC7179814CD406BAEE696B59ACF4846E54D2B5E215694C4FF002FBA1FF4F144F51B448E5B61CCAC589A901182295D3E600D6B701836FF00430B842D475009342C6A3504D6B7BBD9C98E59D4540D85875B48200E05752378006C236F96D892460B133EA1250EF46DC3B37BD28CEEEA561C29B8AFE94A917DB97AC3755EA8609FE49092072DB6371CF7F31E98929393A830981FA8DFE81BD29A43D978246ACC4588E953A7A0F188F556A171EE1529E8093065439F493BEC2D6EBCF0B4EC327049F96495BDD8174B741FC36B4108E2B0E89600410A05C11F4A9FCED7A437AF3C8559D4C1DA143F1EB6F31CFCF59730AC809C32EC78810AF070C1EE7EED0CD329CF090E6E77615A57E9FC423775129023BC0799F15C419117F873DAD8949382135819079BA49BBF27F5E51212F0C9201E163D4DBCD872A747844BD50A124AD244990543CB789BF3E57EB87E32394B002A5027FF00450BECCDEA21FCBC1A76FE1F4ABEA39F852139D565327BC03D543AF9903CB95FE1855191CB402112B843D404F2E87AF4F386B8C906511C20D5F9F9381F8DE342F562C890E0F14FF5A7DFBFBA3CBDD8DCE5069C29A0E458DF952BCB4F38E75A07CE3EC6BCAA7F10997AA564FF00C498B18526DCFD0EF8426E533459246C5B6F277A73BD1E3624F0B849AD8ECDCAAEFCBCE12B9A95524F1DCFFA87C7F7F3C31565D8A07F693CB86F7A0A13B59DF94612166BA6B46F3A16FE232A5D46A5F79C6A1023723DDCFDD387584CBB12A727880D4116A9D1BCBADE1D61D6438343BB86D7D3EFE718D467920CA811BC7145E27E516E9D231248C04C961CA4977DF6F06B373A73858CD27FCFE07F88C292BD355DECAD29E1893C5BF900489F5BE362860077640DAA5EDB8FAC26A9AA49AA29CCFB6A59C470FAD2A0A097048DEE0907DC64DF7B5FCF18135083594E2CC53AF3A6BE1AC6AA9E4D58FD7A685CB5FA436BCF30DB0EAAA1D2536F009F1F4FB33B72B4F2C2F2A782A4944BE0BB909F2D3CDFC01895CB72C939A85F7C4258382A67A3B8140C69A42043F963ECCADC2DA018EEC0599336F2F7EC3CF096372D9D8E6505148AF11B167D6A36DBC75847199248C32D4652D2003466A51BC5EFBF8D23625C6A9174CFD2BA685F492BA2524921E832B4A84C7900B917F8B34E130F854AE5CC94261218A88B3B8A52FCE15CB7133B07352CA20021AA6D5D3F3E24D44417B70EC334B7B50690A9A5CC2829F2ED7795D3B8BA0AA6DB4F15529292AF1A9B084494A07DB260911E2DA3E4E3B1BD9F9885C89D31380E225402947B872080C0BA828DB6B5ADDAFB359F70A90A54C09581A970C4070C4800E869B697F9D5ED2F416A2ECD35766BA475150BD4B59963EA6C294DC36EA3895DDA9B5A5210B1C204F0931378B63D07D83EDACBCDC1913480A40002890EA70EF50E3CCF2ABC75BC1E324E2A54B988980F183C4970599C56A5AA79024F9D7DC6A98813D20CFC2671D6C294A4F184929677D199F6DA1FA51C5FB520F808C16E2936B03CC117F81FDFE0D978E9083C2A5805D807D75E7E958C29007EE4B7A75B461DF2FCBE18593392B0E9623707F88C25295164873B545FAC721E5733EFB7DD184E62CAC809E8C2BB6BF56E861712BBB0EB0C0DAA6EDD6BE0F0A5B7AE20F3369DFDE479EDCEDD708A8197520872F7A93CAB0DA601707D2FCFFCE90B98A92926F04C11703CFF000E9EFC69DE23FE43667E7B7AEFE71173504A8EDCDEB4E7E14F03611EEB687EDA28B56E4B4B5F415A52AE04F1D1A5E217C560411C4166E3A7DF38E6399F626461D6102527814FC2B0078B860C29A8ADE3CD998767A74BE2480525248A0B9AEA39EB56D5EB178E49AE334453F7F4CFA815892D38BEF0A78605FBCBDFC85CEE76C51332ECD2A51504A4109B70A5B5DC5C575761B55AAD3B0B8CC3AC8429418B0BD0EB7A1058D37DE1F59ED3F380A087E9289F44C12ED2D2B93E678DB50DAFCFD0F2A8E27239D5265CE26E005AF437007260CDD6C61C49C46310A1C530BD1BFC3FDC0BD4439AF5CE555D4CBA5CD34F64F5497C4718A2A26C343FAA5419FEA9EBBD84E18AF21C793DE495CE90031502A5176EA6940FF589019B62A5283CE551810ED723622BCFCF522B5CDFB3AF67DD66EAF2FCEFB396332AFAC2502A292A1C6C256BB02453A20415036FF66188CEB38C8D4923325CB9693F32141F880E64D2F423AD6AF7CC8BB5BDC00264D2486A9558EB63B8E756E515767DF44BE94D4D5943A8B24CC93A634DBEB53D9865EB4AAA14EB44828405B8E25C4102D298266F84317F16D6B0642E712A0024FCE471102DF9DDF5BC5D95F1144891FEDCE1C481FEDA8A8324EB427E606DCAFA477C7D9F7D9C7B1BF67AA34A342D0D3D5679C094D4D6B85456E38911C443E55B5C0124016C53B1B9B6233E0A016B9724BFCC16544BF315BF372F1C73B5BDB4C4666B9AB99882B5ADC10080070B8700161A3B00FD62F7ADA8AFCDEA1E79E7128503FF00080084A06C0003853B03748F9E236528E440AE72FBD44DB155C80DA924F5276E42397CACC66CC5CCF9C92EE43DEFABFF001D2C18EA1BA868C90EAD5B7F2DB52A40B72067D66230EE5769702A2C6580FF00F73B3F40C352CC35F14CAD255C4B40E2B82456A6FAB730C2B10ECEF2DCD336EE9BA1CADFAB7D1C501495D3DD5612A5800CF9EDEEC4CE03B5584C3AD5C012C59EAF41767E5CBC21533CB049FDA6800AFD056FFCC41ABFB1BED433849527206E8A9553FCE56614EB21276250A58579C73C5830FF001272BC3AC209698080592ABEB5667DB9962F184B03C4940079102D52C34F0D1A22CE7B251CFDC0E6A4D7BFE1F553994308CB855F7FC5F693C6D984949B1379C2B9976FF173C4B396E0063925F8D426897DDD9A8C1DF6687285A6682274DE103F682C767D3F1B58564D967B21F65D4252333CE7FC431F689A77A9B8E05F63691CBFDB11E9EDC768387E4C1AF0AA028A13DF84F47FA862CCCD192890141960B37F6B7D77A0F1B356279967B3CF6099382468C4BCEA88870D53EAE229333C278A2FE93E7B618E23B5FDAF517FF599D2907FB5DEFA163A57CB7AC6FDEA01749D2EE5B67FADFADDE27796697D21A7CA7FC35A6A8A9383ECF1B0D3A44411FF0015B331FBB620330ED06758E97C189CC31334310E16B49AEC42BAD346A88DD38B9A97216435AA4937FF0015E512919B57BC022B6928D086ACC062969D98B00412D213C5B5A648F2C43E0654C26628AE74C2B238B8E6AD5FFF00B288D74617BC4763731C59002669D59A877D4F3ABF23B4267EAAA9D1C2DA96849D82145239DBC307E189232491F384B06350090FFE79C468C6E3CFFF009AB67BBBFBAFF986E4D23EEF117DC70C1044B8A264CF99318CA70A14C18005F4034B53D4185C6231441798A7A52A75D9EAFE8D7D2368A669BFB4A048DA483B6F2663F59C6DFA142A9C219EE40E8297D2947A987099939BF7AAD73CC31D7E8083AE91B05752D28225002F918E533B9EBE62E37185E4E02683FED2481AD2DA6D62C0DF43768590954C204C2549A9AD3A5074D61A6AF39A61242D23EEF94FE53CBA494BCBF1258976D86DE36A5AFE26B0A77097A02C3D3C798A5B41D6182AF5353D3000BA0C93CFA6D173E5D6D6DF129272A5A8025245AADF7EBF4D69019090C421C7476D39EAE59BC223957ABA94FF00E6206F7B731F0E5BCF3DF9E2564E50B15009A6C69E8E29F7B464E1A5A88F9051E8CFF5B7DE9ADE3D57AD92D001B766667C5C899037807DF07D7793939089A1D480A6FF00B45DEA6CFF00CF9C2B2E44A03E54B3D28E35F23E1F5AC46EAF5D1332E024F981703EF9FDDF1292BB3A84B34B48662070F2E9F4F387224814E1B5BC798F1FF26AC4FEB8248F1C8BDA76EB3064CDA67DE30FD1912524809BEC9D69F9F43194A149B06ABDC7E61ADED6E20F8EFCFC5CFDDCC7C2C230F5191BB30B96B379BD6AFE1195778BABD0FDB772D7B6BE02AC559AD9C514F0AC889FEA22F3B7EE63ADF0FE4E412CF1712126C47187FAFBA1D2329413FBEBBD6FB6F0D8E6B47044B86C6F0A3CE23F73D7D0BD4E4328544B40D43247E2AFA53F30B2252410421B9D2BB52F5D77844EEB4709003863AF11D86DB9F8F9DFD554E4B2D364D79240FB31F77D1DA2593FDB4F23EE9AC37AF59AC190B3D278A40F7491BEDBFBF7C2C32996DFB6ECE784D5B4B034A6DD2B0E901496615AD684DB66F7531A15AB7BDB29DDB621506FEA47EF95F1B272C4A5DD001E97F21E479C273A5098C0A5C8D4E9C98B7D630FF13A3FE72BFEB1F9E37FF4E47FC47FE3FC421FA51FF11E9FFF0014649D581BFB2E154EF2A063E78D55964B3FD96D923EE3DFD33FA61B0B35403B6E746A465FE3157F7FCC634FF4A957EEEBBF0A7F119FD3E8C1B664FE63735AA43C4953844742448F71F9FBB1B0CAD228897E694DB5D3A437992BBB366E8CC3DF5610B11A89B3092E18F27279CF33F0F3C68BCB4D7FDB05A96B1E8072D0C26505AD4F03E90A46A244801C2044471013D363CBC81DEFBE1BAF2A0C78A58DEC34BB346BC25DDAF7706B4FA78690BD8D428FF9A4C46EA3B73B49F2F293E986D332A4176403425B8454F887376D3EF0265077E1A1E8FCEF57A5DE168CF1A72C482636DC1F98D8FE7E8DCE5A949FD95BD874B1A7807D79C6C999364D251297BB38A3FF0027FC085CC668C9220A2368205BCF632447ECEC9AB06A0EC2FB69B3D7ED5D1A144AE6ADF896FE0F777A9A9AEF7FA2A7ABA99D085B8A03BBFB306DE2E824903AED88CC5617852410EE0D5BE85B96AF6B6B0EE5CA4B8243AA846AED434D9ECF53E149365999E694291539324A82E0385253C410601B9BC44FAF5EB4DCC6429414921D2F620B7277D798B51A25254D9929B814436D4F67AC7567DB77B00A5ED4BB305EB6D394AD3BABF4BB2E5454B4C3294BCF0755FCC2E148057C2DA55048558408B636ECD664BCB3324238FBA4A96912D4E594010E341C83FE5BAB762731981610B52969510169528B125D88B90C6B71E0F1F3DEDF7C9CD169A9416EA90E3AD34D2814F0AA9CA90F02081B7091E21D0EF8F67E419B4BC5E5492A292A54A0D624D00249A55C53CAC63BCE1132C278480A5000AAA0B712411A36BCF4A4697EA454D5BF503C285C252208129B1811D762371BEC3140CD6562958CE296A57095D6A433B5AB6B0D00E909E290002430B0FBFBF5A911C71A7AFC8E2D7830B97853C6493C22BAD479577357A437C2F0AA635C3816DCD79D6B5D7AC1C49EBFBFDFC79616CAF1697982656B47D2FEB41B810F33340084100301BF2DBAD86BAEF0718DC18F49B7FB7AFC70E715884ADF84B372BD6CF67A723CE2118867DB6BF383BCB8857A933CB6DF104A2B33388289ADF66E4F50631C2083405AE453F98BEF4CEBFCDF43E794F9965D50E9485A78A88295DDF0D81BCF01B5F613E9389CCCA4CD4A54264B2DCDE9A333756AF955AB79A64B214E90122E5D87873771AB063A47A3FD9AF6B949AC680D577E18AC69B6BEB6C71EC4A61302449317E104C11D714FC523052810B2902A5891426A5C92FAB5FA54C72ACE32B420AFE502EC58E976D2A03FF88B92975032FF000B3DF1EF098060CA89DAD33F0B9C432E6E5C16489B24DE84A74A015D7F8AD6B41C609525441205D9B715BD06DADCD9EF6EE83ECAB5B768350EB793E5B50FE54D29BFE2754B96830DAC8285202C02E710E48E5638E73DBAED8651934B95204C947133828042784BF0817297E17D373D5A2BB8D5A964996E529BDEFCB566D0135AB011DD2D15D90E98ECEDB64D251AB34CE4F0F1B6F36E0097089238DD053B93B1B45BCBCFD9BE69333C33A825243F090A492A0C492CF4E76356880C4E65370CC10B50A907ABEA4034FCEB511720D1FA973CA74BB9850A68287861084D6B6070931F612B498883613BE3974EC1E18E294938898A585314894B22EFFBAD4E6CEDE4C27768319C247129B60AA6D6F13E8C740859ECF74CE5CE17559BFD55D0656D80B724F31C5C5CAF7DB7C59F058F9F94200448336591FB94B09B5CD7DF48623113712A75AD4E6ACE6BB8B6FCEBBC3A21DD1F9780DAB2B39D2C1FF8A2A1CA5EEE01B9008E3E2F88F4C6313FABED08025E23BA425DD213C44BE875A31E5E4D0E01EE482C41362E4F56A1F62140D434ACC8CAF276E8F7E12B58A883E7C6923E0394E3597D9D9B29242E6289D4915BB3D01F7A1BC67BF528D15E0DCF701FCA13BFA8733AEF0D656B14FC00865A6E89A05C9B1054840222DB98F538DD1912A5926592CAFDC5CB6F625FC9A3638936770391FB8A35A181F4E60F2A4D33CA6C99EF9352A02277EEC1F7F4F33857FD3141642940A8EBC21D853C8F5DA35EFD4C3E7A3D8D6DD6ADA7F9AEC66899701EF2A94542E5050A3C3D07113B5AE7975C4A6193370547252451AD4B9676A1D7913A43895378C92E5F4FA1DA9A7DAA615A72DA350BBC1405B927DD333F9728C3BFD54D5DB88B9A72A59890799858924B98E54DD2D00965C4A4B932080EC91B1B931FEF8D485CF0CA4A8105810E2EDA5AB5AF2B883894050B35BDDFD61AEA734A76E4ADD4C83C92904F98E1FBA2270A0C02D5429241D473B56CFADBC633C4ADFE90CEE6754A248524C03BAA260F9FA8DEDD2C2F2585CB5612921041D0B3D4F2A57F31812C4CA6A2D6D8D1CE90CF55AB69A9F9A401207881E66768998B7A5BAE256564EB99520925BFB4DFEBCBEB1B230FC26A1F6A8007853CEBBED11BABD74DABFE1B89404CCC280BF2267EFF00C0E2464E44416E124DC534D74BF91D21D4BC3D89A1602C5C9F7B6F4D622398F682B6C2A1D49DFF00AC1BF9F8BE44FC70F9390AD80EECBF215BF4AFD0E94687430C4A696D5F9D59BEA2B10DCC3B45714524BC00122EA03F1BEDD207BF161CB7B3A560BCB714041B8D057EBF6A8877230E5AC69A569EF96BB0BC56B3B4274CFF003C1B5C718B8E5CC1D8FBF13F2FB3290C020B3EC69C85EBE7BD9A1D7E9940174D2847A3B1BDFCF61AC6730D74EBDC20BC07093B2D27AD890445C72B5AC31212BB38D5087DC375D5B5BF846BFA6511FB5B4A9B79D2CFE0F117ABD66F4121E1EE5811B473EBF2F762491D9DA0FF006DCEB415BB3D3DED5739FD312E025FA9BBB8E9D3A8A9BC323FADD4D59C701076F18E80CEFE5BF2B7962570BD9F24370330B30F64756E75610A230AA0FF00280D7D19ED5F77861ABD7727C2E5AF238A47CFA7CBA8C49272229BA7A52956AF8B74610A8C3916FB7E7F9E70D0AD7624CAEFE6A03E127FDB9E1C232276250EDA37E038AD7EF19EE0A86A474B5C6FD6F081ED729BC3969DB8A62FCEE7F2DBD70F139250108236A7F07EB1A8C31146D5EAD7D45C53EBB504379D6E924852F6E7C5E7D247C7D30EA5E48E920A59D8BB6CDEBE5AB88DFB824BB12CECCDAF8EC368D0AD689932A9F5503F8FE1F0C384E4D5B59DD9F4BE83EBE70E65618809171B31153CCF975E621139AD1004057583C561F3F7EDD05A7191947201D9C37A5479D7C61CA70E77E800000DFEDAEB7842E6B34816548DCC1FD7CB01CA3E604A75676F1760FB9A9A51E9ABC9720A52294D69E22AEFCE91A0EAB2F9F02E387FD43F3B45EF323A8C64E535A203176A7D69AB56FB18D2761EE5B85EF47D2F7F1F516783FC48EFFCCFFF00DBFF00DF8C7FA47FD89F2FE21B771FF7FF00EDFF00EA8DECEAA2D1571B9BC478F8BE65780E51FF006A4780FBA4C67F4E7424F8375DF979F9EFFF001827FE60F889F778BEF23DF8C7FA3F21FF008A7D7E5FA03E107E9D85490741BFA46D6F54A9E0781C1E189850E768B98FDEF8C8CA7874A3DC8481E845FCFEC9AB0E4E8EDCF7E9E1710B1BD46E5817418F303EE36F79DB91C6ABCB05004B3BBB5AAFBDEE1CEA4D18C2470E496143AEDE2FBC2D6B50B8AB9581111E2927E6267DDCF0D26654521F87992C3EAC2DCDEF194E18B12407D28C79BB17FAC3A53E7EB1B391CCDC193D37F38B461A9CA8104B709DCA5F9D01AB6B5D89D2038751B06F33E9EFF0FD459E2D6482E4111CC5847AF4F8729B623F17960FEDB1D5ADBF43EADB420BC3312141C9361F663AEBD4C3EB19CAC443827D45EF1BCD8DFDF798C33565E59CA496A0A5FEBB3D7D4C604B22C9DB63B0F2B44932BCC52FAF8AA163BA6E244EF3B6D24C6E0EFB79E2171D97F08F950E482CCFE24BD36D3CEF0B252DB82E1CED5E741E9BD22CFC8335A8A358718521748A0016E526124729BEE79F3988C5231F8104A93C3BDC5413A1F1FADE1CB52F6DEE7A7DE2DCD26ACB975754BCC1097B2ACD695FA6AEA75A789BFE732B65B24104594B9102058CE39BF6851330CB42652CCA58585058151C2A04B6B5142CD422F16FECC6293879C1CB391AEBD1EBCFCAF48F9CEF6DCEC453D8FF006BB9B53E5AD1672ECD2A955793A82785B525D1F58A80826CAB2C8DE4131CA31E81F87DDA6188C261E5A965CA02189B94809FA82DA72B3FA03B3D8BEF25D54486A9357A5013A0157D7C0C74D2ABBB052EB3096DCE5FEA480164CDEEA9FC31DA6465C8C4A5331828DC1AD1EBE66C7A686B162C47CE9048A1BD7A75F01F50212F193CC7CBF76C2799A46164100B508352C4D19EEF6FB5A1BE192CB1460487B59EB7B35FC290059E4418F43E938AB60712A4AD556726AFF4EBE3614A43DC6A3890973A58E9CBCFEC39C1C6AEBF218915CD2A04855DA94FC6DA188CEE81BD4E94F6F1A9D5AAC449F203FDFE7F942492AE249507BDADB7F93A36CD1B265814BFA790DDF6FCC7A3BA43D897DA2F5C86BEA1D9DBACD2B9C3158FD630D2824C1E3EEDE0950B72DEF1CF109DACF8C391484CC42E6A105415C251F3B535E10DEEBABF38C7769704B92172B12998B1747ED3714E22DAD4D6B66B4771FB2EFA323B56CA2A9399EA1D78747210A6D6AA3144CD726A4020A9254DAE121039911D31E74CF7E22FEBE6CC565B8A54C492A74F094D9C8A96176F66B4ACEBB4B97CCC32E5CDC083359A54D137F6124B9617A373DCC7A1DA23D973B3BC89348F6A0CF3FC499951F0127EAEED2071698B424C47879881C81C732C7F6AB39985412A9A82EAA85135362C08D34F0D8C714CD7321C4A505F0D4B03B6D4D816F2B477032AD5941A7B2EA6CA74F640CE554F4E8E053A82859AA000092AF00360247112761E58A2E2E566799E2A6623173A64D248E10AE2F92F6AF47635110F85C72269520AC5ADBBD1BC3D2B4763086BF546655AA2A4B08926CA0DA02B9DE4241B75B5E7CC99BCBF0F2E401DF715AAEAB378FF0098658C099AA50490E2E68C3A6CCC7576A924C372179A66055F5879E42531C0038B00850B82124585BACFBC1C4DA27E0A50FF006D12B88B392949B5AAA07DEA62115825153BBD4B1A7A6C6DA7D6323953847896A51B9924998247351FD7717C41E6D2D58B1FED6D460D76DB5D6C2BD0C4AE1308997C2A533E808E76A6AFBC6D6B23EF02C13B478BD7900227F0C23914B9B9671778E78F7D2A4B6B776F3AE85C6324215C212CEC4B0E5CFF000DF58548C992D7DA337DCCCFEE3F199C58558EE2B067E8C3ABB3F85B48622411CB7D7EA60759669C02549E7731F2263AC1D87C30267297706BCD81FB7E203294081777DBF3FC6F081DCC1A6C11C4205809B5A7CE3A5BF495912B8FFB59DF57D7AFE2F18187481F352DA93D69E7E9CD9ADFCF295B1E25A0127910368F537BF3BE1E4AC04C9A3E54BA74E4EF57E5B887985C3BD402DA1AD6FCED5FA54C45331D494C0C77C241BC28DF9DB90FDDC9DA4E464AB5172953D1836BCF7A57E9A43A1865392E4826819BEE0EBB9FB443AB75AB742210F7171CCCAC9022D6931E640E9EB89CC3F678AC0FF6D8EED7DF4B8F2DAD1B0C22B899ED5B73D75B369BF2787E65DA1A47178C738B83CBF5E7CE713B85ECD129629A1E5BB9ABF41F5AD2344E14872493A746D9CF336A6C0C40733ED0B6876082AD97122D0441E5F3E66F89AC07674A685048E8F6DC6DD2876A43BC361CB9E77A5697F434A75BC436BBB41324F79BFF00ACDCFBC4C723FB8B0E1FB3A354576E1EA3969F4EACF93874BD4D4B39AE834AF95222959AE43F056F149127ED913B8037F5BFBF13123B3547EEE81B427E809B914B386B343A4618306147AD1CD6C6BE0DE43788CD5EB068C8EF8DFAAE6DCA6F6E7BDBE589797D9B4A98F7551CBD5ACFFE7A3A4E1EB56E5B9B6B5E7AC43B3AD58DAFBBEEDF20DEE167EE9E5E66D36C4FE5DD9FEE81FF006AA2AFC3F5035AEFD61E49C307B1D19C1D2EDEF4B86788B3BA9D2265E3046DC6ABCEE7AFC671369C981AF776D4A5CFBEBD44385E19EF47D83BD3607CBF8A36BBA8D0A36748893F6D573FF508FDDBAAE8C9D229DD9ADA9FC72D6BE71A7E9056A6AEC18DC7D5B7E669B35BFA844477AA02F3E3E7E4388EE3D371CF0E1395049AA6BA387E9B37DF5A46C30E052B7A50FF001573EA219AA73D42A25D3B1DD5CA36267F73877272C4A480C0A8DC331157DDBCCB42A891566BEB5A5DF586B5E78DFF00CC83CA144DBA993CFA6DF0C3D4E5A1D9491E403EBA9D3FC6F0B7E9B97BFF00CA10D4E7483C24382F3324C7DFF8CFBA30BA32D4D999ABA13E2CF18186219EA77615EB5D36B5F786B733947F79224CF888FCE3E1BFBB0E9397A00140DB307ADDB9529BBF8C67F4C1852BC8D3EB60DB8BF846AFE309360BDA6FC479FC3E736E470A0C1A122890185C00F7E46329C355A95DDBEA490FF583F8B0BFF337FF0054C0EB73BFEE6241D7F4C904B2789DDE81EBEFA7285D3866360DE05BA0AFDFC213D466893C1FCC169B4813F33EE3B0DA231A8C3006A900B9B81AF9FBD03C3A120B8AB0D680136D39EF6E468C98E66836E3DF9123EF07F0F86F8C0C280A761D7DFE2B0E8480C38BC472D371EF5B473FC5120D9C8DB65728F51CFC87BED07E94034008E601FC74A8FA97D6761C10E030D8D7EBEDDB678E7F8B27FE67CCFF00DF83F4C3FE29FF00C53F986DFA73B0F21F98066C9FF99F3FCD6707E987FC53FF008A7F30770761E43F31BD19BA37E31E627EFF0017DD1F2C1FA61FF14FFE29FCC67B826EDE207E617339B213C5E33B8D951F8FE76B4EF8467614355218DC507466277E909F72C482068C43535B3BD5F4E421623371FF003150623C64FAF3133F39E9BB7386410FC201EB50D62E4B1EA5CFD8EE52DABEFF00C3FE617359C246EE131FEA8F4B4C7EF6EAD2661527FF004BF5BF466F00DE91A1C3A740FCEC7CADEF943A339CA0442C836985DBCB63EBCC01E47082F0A91D342C7C6FCEFEB78CA64243D1BC4926FB1FE6D7879A6CE923FF0030F23F68F4E7F9FC45CE194EC185E8F76205B9B3F98B6D0DE6C904BA412750697A59FF00C33BC49A873A4C0FE64F985493F80F39F29C355E5CC91476D19B6BEECED61630D55254E5A9B8D9AFBDF661E1131CB73D6D2140B84484DC93FB267ACF3B5B10F8BCB8A83F0D3E6E6E7714A536D61352787C7935A2C1D399FA03E805C24150B719EA3913D6D7EBCE6714BCC72E67213BF42EEDA7F986C0BBF36B16A0FB7D1B678ECEE8ECC935D4EF3282081DD13D4410641991307EF3B938E37DB1CB140899C25C3F85BCFDED0E30D8BFD3E225B1A715DCDF57DC97AB52F7B8E9CFD269D90AB53F64592F68F48D71BBA51BA82FB884CAC8A9752D278D43C4AB279F981CA63FB199D4CC2E3BB92AE14A16800380F4D282C2FCE3BE763F302B44B4B965D0DB7F16F2FA57E759550EBA029C04252A5049DBEC98363CC4796DEB8F6BF65F3046272F96A7015C1524BE9F7FBDDE3AC292424275A1EA0D7EE235973CA790BFAFCBEEC466758B4CC5292142B46BEC7714F5EB1ACAA2D3617FA1FAC6C43A6FBF2E7B7EA7D047DF5D912560B83424F838D74A335372D0EE727BD606840A86F2F7EB1B0B806E23D4E2465A295DEB7F2F2B9FA86847B8AD154E8E7EDF7FC62AAF7996D4CB090A2F885180600E932458F2BE375A8A0505073DCFA6BBBC6532120D4B87A7E49AFD0D23EE58D7D7B87F90F334A23FF2295968091784A12916E623D31F37578BC5A49054B501AACA97471FF27AFBE51F3CA5769715303AA6101EA6B5FE43ED5118703AA5A7EBD9D2CA567C08EE54A9F78988DA670B48C74C2A0F6342C03823C295B785A3188CDE74D4105448152E6ADF515F10FBC0E648A52C3D4AEF7A94C12A29E19D8EDF3369DEF89FC362659FFA92DC8D697A7DF5262A7986266CC25B88062E01D5DAA4330DAEDD21C9344BAA4210D27854CD9CB44CF4DB6F89B5BAECAC44A94B981494B2998961D0DBD2D5A44223193A4AD8053137A83D2DABDFA750BDACB5F6CDC098B4904DAF17E9B11E82F88E9DC331F8080EEE069D1F43EBCA27F098A54D62A0DB56FE9B3824C6F51553C7188045A0031B7404EC3783BF4D9A270D338832B6607D75F21CAEF1348E129D1C742EFF009FA51E95D2BAB49025503DD3D3CA3979DEC77C4B49904252407FBF99DFAF3D8319F8954BF9520921D9A8E487A300D7606D5D286123F9C374401EF078A6F206D1D7A5AE7E785958454D0C0356E2BAE9A68CDFC467033666214789241AFEE24BDC5F41D7CED114CC358776094B891C878927A81E5FBEB87587C996B3AB86A36A58F3BFA44909243D0BA7C5DDF9EDCA21B5BAD14EFF00E6A470837E310679DCEE3E78B061FB3EB2CE14E74626F66BBF9BF278DFF4E5DF57DFF9BB546819B6880E6FAD9D6F8887B69D9423AF22479FE63160C376616A1FB554D83D6DB7B1CDE35EE00AB7A1F5AFD6F15B66BDA0BE88870DE40F1F48E73CB9C1FBB16FC9FB30025416973472CEDE5A7869A562470522A6C69A0DFAD36143CEA220D98F685502DC7133FD53B6F10636F8FCB16CC3F6725A588439E9F5A55F95F6DA48E1C1B25AF63FCBFD36882669DA3383878DCDE784957BBD2D7FDC625A4644840712BA8B0D0FDF5BED77C7E98EC697DB96BB11107CCBB458E2FE77C553F79B7EE71268C9D9889543AB6DE1AF2A6F48C7E90E80B68000DF5310FA9ED0A7ED390449BAAC7A9131BF947C313383C8D731C22512433B06F56DCFD2978DD187E0366A790F7B539C45EB7B40041873CECAE77F506F61B7289C4EC9C8668209924071A52F7A57C0727DCBA9529D541C46CF6F01EFEAD11B7F5BAEA15097002264F1011D0EFF000F76DCE7B0D9404FEE4682E3A7D747EB630F112663064B02D522FABDB956CF6863ACD5CFC121D83FFAB6E53CEFCBF6226246552001C400A6DE27D9A6D7A391216CE433D4BEB40CF6036A18607F54BEB8974D898BF2EB24EDF893E78929796C9154241702A18EFA7E5FEF0F24A1449F9438B7A787AF367AC34BDA99C5132B248B595BCF94C7AEF85060D2094A6583762DFC35B975DA1C194B37413D4084ECEA0717C72E447FAC5FE26E6DF75BA6A708D6433BB8E1767DEDE756615A083BA57FC3D04277B3F59305C1CEFC5BF3F21B0EBE9B6105618B91C0430D8ED4ADFC1BD088C2A5A9AA8F4FB8722DF686D733D75572E584DA473262D3E5BFCF69DD18750154B73E61AD6E553585A5485100A505F723C47DBDD92AF3C5DBF99E9D4EDCBF630B265115B9DA94F7D75858E1A610CC5FD3F9F2109159D3A77583D25447E9E97C2F2E492C40A92761ABBFA54F846061542A5FC74E77E637E509579CB9BF797F5FD679F2FD70E44903FB69B381F7FABC6DDCA989AB3EDE9CE386B365A8A871DF7BA8FE07CF9DFF001467A120064B72B8D3D3A529CA364E1946A01AEC0F81B10357B46EFE28BFEF3EE3F9ABF0C35602C1A1C2308B001677DEFD1C68E2135466AB1C32B3B923C407A49323E1F9E08769C32C81C496E9AF3B8F6E7AA6FE2CBDF8CDBFD53F120C0BF909D873C10BCBC3B100A4DF5177F1A3539E83683F8B2CECB3F1302DCCCF3371CE647492359D86528D05A9AD3F3E3D2907F165FF0078FF00ABFF00BB0423FA49BEC472335593F6C7FD5FA9FBB0460E1660D3D3F98528CDDCFEF1E6388FC7D2FE57C118386982A416E9FCBF942E673654125520C589DB698E636DFDD717C379E3F69F0FAF2FBF5168495865F11A1AB3163CFF0093C86CF0B119B2AF0BE9FD463CB788C335817173A6FF00CFD7EBA9C24CAD1C8B50FA7F10A7F8BB96F1CF520FE67F7EFC345A5DCB3034F2B5A82BECC6BFA69C2C83E00FE217319C2C412AF7C9F4E5E5CA7A473C362826E0EFAF4B535F1F078C9C2AEFFF00ED3CBCB43E476877A7CE5C9BAAC77BDFDD049B4F2B7ADB1B499449F9833EFA5F57D79C379D87527FB5DF6A03B59FEBA59E251439D2ADE3B48983C85AF33D798FBB0E4C8960114A5AB42EDD29F73630C66495281052433871D7AD76FB44958CED61248724881F6A08F74EFD7732047945E2F0C1493C29A54E9E3CFF008D618CD9132AE9248A06FA790D6B6A9AC4D34E6A073BF44B877B99116E9CA47979EFCE9998606612AE14B8360C49D795296E8F11CA9337662FB0FF00034E76A563B63D98EAE0CD7B54CB5857D64A123C52045BC5D2C7A8EB7C735ED464EB99865CC54B628428B9005FC2AD66FA35232795C99E8F9480541B4F57D999E96E663B0DDB9E9A4EB5F67FED074C5434568FE18D5435C49903810BA8F09DFF00A44C1B9F5C79C50A548CEE4F092026629C02CEC59E9F6DF68EE7D859A4F03BDD2D6A5B7A59B63A74F8FECF1B6E92B2AB2F4A4257499857B4A064484D4B891D62C2D6BDBD4FB1BB15989465C80B53012C30259E95E6DCFC6D1DE904AC7117AA535028C05E9E3F9864539E7246DF1EB1E5CF0F67CC99889C7841238B9B33F900DB42A94D416A7E1E3969DBA813111D7F7E677E589944B972E5A12B676ABFBE6478187A9040480CFAF37FBE9D2371713BF14FC6F6F3F2C39425240E1200D83726D7A46EA42920929206BEF58C1EAB4D35338F012B4A9BE131600A84DE236EBD461963D69952D550686A1AB606F570ED6E51893C33961093BFA036F7D23EEB90C0E9E222361023FDBDD8F9E53E52438291434F478F99099412E05069ABFAD2FF00C0A4284B29FEA48F7807ADBCA30C912439A3541D3C4BDC68E7CA3612D9FE6356A36CDF8F7AB830F25BB13007B848F3BF97BEC39E25654A25258508A5DD9EBE1CFD8D0E1D157653DCB6E051A91B1598B6CA499049E9E198DAFE9D77B5FA6C704A9C40A80EEF5BD49F0D3F986D3B0729D252800005C52BE766F76863ACD46D37BAC022CABF4DAF20CF2DB79C3B93922D740E75A7A786BD7A88D512C22890C34034AE9A9E9EC45ABF59B54E2CA0419B1503100DF63F77E789AC276754BB8552CE2D466F7AC3C94859B17D19B5A52B51E9CA2039A6BE80A01404743EBB7E6019BF2C5830BD962B22A5AAC081F6D7973BC39124283901BC86EC6C3F07AC40B32D78E389480E9313693FB8F58817C4EE1BB2490589D469CC9F1A7BA0791C1E193A21B7D34715A7DD8B96315F66DAE570A3C6AFFA8DA37DE48823F41CAC983EC8CB05249AB0D00DAEF4D7979C48270E4B101B4DEFE3AF28AEF36ED01C6403C6A13360A304027A411E738B7607B2B289B03C2DA313ED8FE09683F4F5B5CD00FA50FDA95A33C57D99768CE92A951833BA89DC1DEF37F3F741C5AF0BD974060C2806839834D5ABE02D19FD393702DB0D34707C07E2209996BF7564788C09B137E80EDCAFB6E6313F87ECECB940B84D59E8DBD0DEC5ABD76687125A43850BEE1FD3CAA4FDE2215BAF1EE4AEBBA8F4F5B49DFD791C49C9C964B03AD68431246F7A07BFD21E09C820820176D486D6ACE2B7BC43F30D542BF87896416E600279FBF9F4DBA4624E564D2D92C052E4B5791F1B56C3785D130711A38A11A38A6BEFD2B17AACE512789C37064F118206DFEDC879E24E564928814018D28FA07A73D6DE10E51310481C2C7CF73B1F3FE222F9866C1C4A421C208E52473BF3DE2779F4DF161CBB05270E829094EF6150FE22C346FC6B36499EB484D00B902F50DB1BEBE2F0C2FE647FE6CEDCFDDD6D73CFEEDA5D12E4B5427A33B7B1E1607487D85C190A0E9E56BEFEEEFE24A2566409252E12044413F70EBE9CA63094D9485060863FF2A02C1DB6E94360444F49C1800028046C5A8DCDB7A8B38A184CE660019E33111F68CFDFBF958FA02488E99809ABAA490C6A03DEDB6C5F5D6BBEF3A42024FCB5FF003AF2DFC7486D7F304DA1CE479F49E9FEF6E587B80C2CC90E26329CEAFBFF0022FE15B6F8292921C867715EA77AE9BFDE1B575C913E3B936379FBFA7C312BDDCBD852FF00CC487E9D1B0F2FE634FD787FCC3F13FF007633C12CD78475FE633DC27D83F984CE55CC8EF0DA48B9BFFEE1F2B7974C704BD93B697FCC63F4E8D8797F309555A0117F9917BD8DFCB0D67A521D9205054372F1B75BEC214972057852FD037D2B1A1CAE17857A7895CFEEF4C3585FF4B47E1A1D77BDFE6EB094D7264CAEFCFC4BC107E99A8CDCBDAA38FAF23FBFFF0072F1B71AB7F41F88C1C283700F5FFF00EA37355C91C442F988B9BC0EA48B0E64CEDCF094D2FC3B87F173EF4AD6B0F30F85490C523C869E6F4DE87CE395E62019E23FF58B7BFF000184A1D7E8D3B0F249FAFF008848BAE0621479F318236FD2816007BFFD5187D70FF71FFA8608CFE9B97BFF00CA33456024CA80FF00D4411849603D2F57F48C190137D793FDCC67F5B1FF00311F2C690774397FE23F307D707FCC46083BA4F2FF00C4473F5DFF00F553F1FD7041DD0E5FF88FCC29A7AE09E225C076D898F7C1C27334F18061D2AAB024720295F0BFF887046629DF8933B1BABEE9FBF09D3DEDAC67F4C9FF0088B6C9A7F3CC79C2D6B304413C493B4C927E026E45F6F8E352949B814BFF003FCC63F4A9FF008BF4F7F585A9AF4C8F1EF72388FE7FBE538C7026FBB6BEEFFE231FA245F847D835986C75BBF285CCE60949FB569E4ABDA76B8993EB68C359E0241005DABF51B7BDDA23F17252904049200AEA6FF6F7762FD4D99A2C02F94183FAF59F7FB8E1A4462F0E922CEF534F1EA6FD6DBD5F18CD5278471C7FF5449B4F3F9DA2E3D304021BD7686D330E0B70D80A8A1DF707CB9C4CF29CD5B8038C8E5B91173E73720F5C2664CB533A438D587E3E90D558740BA4575DFDEACCF174681D52AA1CD58097152A75B54955E10A06C6E248FBF9099ACF68B29973F053D6123E596B7617749FA3B57D68D5CCD70E04D96426AEEE1A80355AA2BE7C8DE3D7BCAEBDAD5BD87E78F00852AAF24AA055024F734CE8B98F2B836BDF1E16CD248C276AE4B025299EB013A1E25746714BD599A3A576397C0123F69F958B1D3C2FBF9EB4F8CFED532F465FAEF523688FFF0036AE040B01154EF2B44DAD138F4D64B30C9C2618874F1212487E40E8D4D5CD01DC18EFD964E3330F2C7EE00539B8721F7A1D686DA45798E83964C9665924076BD34A1BD47D5A2591281E9BECD6DB4BB6AC6353AA03867CFF000BFA61863713F3B0535695E6E050F869D61DA249E20402C2EE59C737D4F946BE31FDC46FD7F77C2B2316521B89F4676E4ECE3E97F087989522649EED0C54DBD453AF4673D19A1592D5552BB4AE186D650A52F6E1E054C5C03E2888F7DE711F99E238A54C7535CB3FE4F98E9CE2264489D267A2784964F13ED5BE8D4BBB7231F79E8692483607CFA4F33D3A7E78F0CCE0A2753F8D1879FB78F9A610E03D0D5F57DB5D2372DB40493C42C0F3F96E709A10789238581D5B6B7B3F78381B9F2B79D7488ED6D4A5A053C6011100902237E63F600C4D61E4BF0B8B81A5FC2DADBAF283839BBEBB7AD5ED10FCD3352DA13C2B07ED490409BF3BC413187C65AA531425478B46D34F3F37F209AE5DABBD5AD6E715467FA8D6DF170B8044ECA1CE3A1DA62C7AF95A7300A98E01944BB35DBD0780A8F18C26497B39A69E3D4DEDE622A9CDB58AD9FB6B242A62E6DC26F6E9B7BFC8E2FD96E144DE10A9646EA20FD00A5A9FE21DCB96524937D2C7D2B5EB4E45A2BBCDB5B92170B55CC889B83D36E5E5B46DCAEF80C9E5A824DA81DC74A0F1FF0030EC218543BDCE835EB53EE910E7F5B59414B226D04EFBCFC62F137C4D0C914E381015CECCC76A3DDEF7D054449E0D245746D859B969A575F288566DAD93713E97B7BED7F48E773890C364D3D0CE87E82BA519BCC5A8D41121107ABD522AAE49841E6779DA2667CBF238B0E172F9E900041F6E3F3AFD60F7D07B6888661A8132A957B819F5E401F77E589FC3E167243841A5A8CE5E9706E7D7AD4888D4E7685127909DCFDF079FC2313586C0CC9C3E6490ED52DF4BD7931AC67F4C673102A7F8E63C3F9788B57E70832479F1413F7C4DF78F98C4ACAC9144BF16C76B3685BC7A54C2C8CB961EE096621CED56356BD6DADE22F559B990524A4C192491F1DFCF68E9E92B2325208F999E868FCADCE9CF5687A9CBE651817D6FE0DE218FD1AF1FA8CE1641959581EA2F71CBD3E3CF0FE5E4CAE22126946FAFAECDD6B48772F004DD241E86B7DFECC7AEACCEE6AB51FB479D898B5FAF9C6FD23AE1C8C9E63808AEEC6A0BEB5FE3986896C260121412450B5C1B53FCFA8BC36BF992C09E226677F48E7CBF0BCEE4AA9CA2626A2B6DCEED4A9E9FE1A7A4E050006482C5C161AE97D35AF84256B3155F8D5BCC4F9CC70F5E5B5BA61C270252C5436FF17E56BEB1209C2B248E17DC8D2874171E2E7C2BC3B5CE411260FAF59DCF2FDC61CA30E84B3801AF41CAB47DBCFCE23E7E1493661BFB1B37896A351B2A6BD5E0B9B024816B1F78F2DA2FE77C36C5A65A47CA41248DBC79DB6FB554C0E1EAA090E297E67DB9D078C36AEBCDF7F2137F84DFDF862E6EE5F778933873FF0017BD5EDEDF9F8C70D57295C526C47F70DFD27F7EB8C3EAFCDFEF07707FE3EA7EFE5BEDBC60BAD11BF3B78B7F9CFEEF8CB9DCED7F483F4EAA7CBFFBAD6BD7E9CE13AAB48820F90B8F91F3F3239EFC9A4F533EAFA93AD3EFF8E8ACAC39049663E07D5FDD7C343958B04EE6666E39FE1FB3869C67610BF72ADFE9F9F7B084A6B960917F88FDCE0E33B080C957D36DBA8F7BDE31FAFA86E63DE3F3C1C6761EBF983B857B03F31926BD5E220DCDA26479EDE42D84D6B347ADFED6F661C4A94A4D086E647531A5CAF72E01168237F9FCFA634EF03B51EB47AEADF673D690B776378D62B9CBC903A6FF00AE0EF361EBF7F380CB1A13E35FC4726B564CF11F404C7BED8CF782BF2F42F6F483BBE7E919A6B14641519F7FE53F2C36985CDB73E7FE20EEF73F6FCC67F5A3FDC7E7FF006E138CF00DCFA7E20FAD1FEE3F3FFB7041C0373E9F883EB47FB8FCFF00EDC10700DCFA7E2334D6A93B1E7CC9F2E91F3B61399A78FBF7F783806E615A2B960DD56F53F7613804B7DCF41A7BD7D216315EABF885BCFAC7EF6C101975D41E63CF6D87942E6F31541F189D8127D39F5F33D7041DDDAF6F3E6397B78503317131E3F2DF9CD8F3BEC3973B9C359C6B4B1FB010D71320936B8EBCB507D1FC21DE8F335DBC44C45CC4CFC7A7C4F5B611861330EE9735D29D46DE0F73E7477FE28B0A49E3DBFD44EF1BC47CB6E7821A2F0B47776D36F51F7EBBCB329CD96384F1DBD76F9C8FC799C10D26615DDEC76BD1B57AFAED13FC9B54FF000DAC61D51528CDB8495472BC0B5CC826DD31AE324A6665B8B2A0ED2D4C06A58BFA3442E3B08A98A49093F2B9A3F96AE6EDBB7378F6CBD997355EA5F67BCFDE52A4D3E5758949245FBD4BE9304FDADF604FC71F3FFB649123B5982401FF005712B04805CF0A9EB4A6CDAD6D13591CDFD3A892A090180A736B6ADADCD5F78F93FF00685CA9CC9BB50D594EEA5499CCEA1490A052654FB8A98224CCFA73C77EC19E0C34804D3BA43518B848A7979DE958EFBD9C9C3138292C6CE14D5B9A3EDD628C2A80241133F2FDFBBA62D597E294994B00B16D4E95F5B5766DA2EF2E41090598F5D2FAB5FA5234B8B24A523ED5EC0C9B6FE1FD397C22A7628AE6AAAF5B57EB7B33B36BD61D4A944CA98487B51EDA6FAB4042CA0AC24C0DC81205E37023E3E784BF5CA42CD4802CC5DFC896D0B188C9638B1291A150B8B870198E97F1AC29CBE9DCCC5F6B2C485F1573CD348E0495ACACAC25094A520A89248989F3BE2371D987121614A77259CDB9FB6EAD169CD25CAC165CA9C0252B12CA9E95A55C9B3E9BF847DE977E9FD93F963CA8403711F2A7BBE7E9FCC24AA7C04D8C588DFEEDAFEA396E30BC997C4A7091422A7617F0A0D2FCE0EEC6F6B53F98AE73EA829E205467909D81F7DFAC98EB8B460240212785FA8B1D797234783BBE7E9FCC55B9BE6EAA44A932541C993C46D137079FC276B0DF16DC1E5B2E7FEE48A33D2FC853CDE977730A224F103A9341A6DD5BEBD04529A9B3509529C0FA9B324D8157EC7C3DC716ECBB219331490994058D5ADBD773E3CE90A8C314967EBC9BF3C9C7845379BEA072B141B455F129B24429B080667990072DF68E5D6F381C9B0F2582C25205CB8A7875F6EF0E932428DFDE9EFD451EBECD735CE5BE25165B0D5E1C0F34605EFC324C8FBBCAD8B5E12565C3E4EF0120541A35A84BDFD97870891A31A54923DEDA163B1A4429DCF5A794B4D4D690B444212D1B13BDD3BDCDB96F7DB0F26E6395E5F45CC9638AE4A817B73F7A521C0989902CFA0B7A38F74A52196AEA9E767EAD4F5954397754B50A99E9C2855FD2DEBB9CA3B5393CB0077F2ACF5501F53CA9A5B68C7EAC3BB73AD9F62D7D6C075786FA6D3DACF3F5AD19469CCCDDEE48EF09A5A96878BECC153402BA7C49EA17476E32094DC588C397D0CD40A8AEFCFEB4615C8C524B92083E9A569E74AFD62454FD8576D19B81F52D2554B04FF5B896E3D78C00236E5D779C253FE28F66B07FF56749177E15856BA70B92E2951E942ACB9A8501C4BD580614F7BD7D2AE87D927DA2F30095536892A09992AAFA54403B1852A779E56E7883C5FC77ECA61292E78249A32555AF20D6D5F95ED37815A12ECA490C18961A787516AB52EC81FF00637F692BCE8804117FFE25487E1E212379DB9ED84E57F507D98A033A9A517BBD68DE0C74E71312D72DCFED1677228C3E9E5118CD7D8FBDA329921751A114A4C1852330A7544033210553EF1F9626709FD40F67669E193312F40428A83FFE4297F57DA1E266C9B28A5EC198B1E4DE75FCC5539FF61BDAB69C4ABF8B68FAF63BB9E20DA16FC0E63F96850BF53BFDF6397F1B72650752E53901BFDE4F8EBFE3EAAA67C80400C40BB306DADA9315366990E774CB08AECA735A22991DEAF2EACE111BCCB2058F3DAD0716FECF7C51C97342522749413A77A9513CD9F7F4BD2CF244E0A53A025401F992E900DB52DC81AB1E42B11475550CB8505A1992447DB50A45373B82954131E9BF962D67B5997B3C89F2C837F9817D857573A69E313B875C9984F11EE82438480540F881EA28FE70D9993CC3686DC7AA0B0E89EEE9D282B0DFF702B13C53E77C2A7B41859A974AD249D5EFA52A29B5EC3C64A423BD05405750FA581BED5E9CE1BE9B397140A1CA9E200785250124F2898916EBB79E3538FEF090920BB1047A519E96FF00308CEC27CC4F0B39734A1E5B8A0A5DC51AAD182AAD6A2A2A6CB69DD04DF8BA9DAD7E57B72C379B356A2789C27A9248F3E7BBBC2B86C1A407721EE386CDCEEDB75BC2672A81BF17A99FC62DFAE10E24EFF587BFA54D9CBF43F47FBFF089DA9008E131D60FCEC09F960E34EFE8631FA54B7EE3D58FE6FEDA357D689DC93FBFFD3838D3BFA1FC41FA54FF00CBD0FF00FC51A9CAAB893BF5E71EEE56E5CF7C369EA1422ADE1AFB3E3A43997870E0B3F890CDBB937F6743AFEB3E7FBFFA70DBBCE5EBFC438EE07FC07A7E639EFC281926DCA3F41EFF008E0132A1D34D6BFC41DC03640F06FE613ADE4C89F76E07EA7DDF760332EC3A560EE07FC01F2E576A7BE75E5AA8826F3B474F41B981E9EFC379AAB134049F7EF58048E7C23A3D7C08FCC6FF00AD790F9E11E34EFE8633DC7FDFFF00B7FF00AA13545403C3CBD27FDFE5EFC1C69DFD0FE20EE3FEEF4FE6137D60753F13F960E34EFE87F10771FF007FFEDFFEA8DEC5481C5700F9C9B7BFF2F7E3459059B478C89203B906DFDBD79FDFF951F5AFF5A7E18D236EE872FF00C47E60FAD7FAD3F0C10774397FE23F307D6BFD69F86083BA1CBFF11F98D6BAA16950E7E5D3C8E119AAE16A3F8FBF6F183252756E80463F5BFF005FCFF4C23DE72F5FE231DC0FF91F211B1BABB9F1FADFF7E7CBDF83BCE5EBFC463B815F98DA94D6B7E56F58588AB103C5BC45FAFBC6FEA70779CBD7F88CF703FE45BDF9FA78C2E66AC492553EF9E9222D3EE048DF1A124DC93D6119B87245F8B9B337A9A7BD6AEB4F5A9170AB7979ED79313E7BFC318866B9203862DBFE43D3F8A43B335C991E2045AC4DFF003BCF58B804D8E0840CA150534BBE9EC6DE90FB4B9824404A88E978F3B79C580BFBB04365C8493C4CFBF3D37D4ED5F1AC4BB2ACF9346164C2839C299578A0191FD524738F90D8E179CA6CAF16583896B63B0E13A589AFE758426E042E5CC5D9858815EA6E0B79F808F71FD95EBCD0FB2ED5D6344949695DDC13FCC0E54282E4CC90248BCF4137C7843B48944EED9E012520A7BF9E56C43020B8DD81E4DE8229B3E7FE96690E032806D5BDB9E54A068F05FDBDF432A935AA356D3B60379C3CF297C090005320054C08B99DF73D648C7674C9270F87521354A45BA002F4B6BD3731DABE1D6681695CA597E3E16F326C7D1AA7D63A00E38971BA5B01F6828C7398FDF9DAFB626F0292A96AD29577EBEDCF5BC777932C2A47117AD46D5B57434ABD2FA3425A86DBA37DEAB026A14128A74DC821638551B83123E1CAD88F97294664D5317AF9543B7315A9778D258E14AC3BBD816771E7FF00768DD636D3A2B1861CCB1100D47F31E5282645BBC4DD5B589DA76B622F160C849AD43D0EA1F6205A86F5AF846CC42D13BBF2966502036C58BD346B335F778EF6FB03F600AED63B51A2D479CD314E97D1AE1AACC1F7507B8716A6CB8CFDAB28871B1B489B5C462A198E35499530A13DE2E89097624AFE5706F477A7E04557B71DAD4E1300AC31980152140A5C38614F3A07B1E51F58E1D3CB88FCFF001B63877007E5B7F37F778F9F9C01DF4DBF9BC25AB74847F548D8111F8DFEFF00961E48284B0A51B56BF96BBDDB918024026DC872F1BC5719F3AA2493369DCC1E87E3F23CA3169C04C92809798916B9D35F75FAC67853B7D62A5CF90A7DB5109714B483C21B6DC5933BC84824440DF165C366F83C1DE6254ECE1C353A6BD357DA364B4B2F50D7677D47DE2A6774EEAFCEEAFEAF96E455350951294A9C4A9A499302EB40817BEC79198387A7B6F83921A528248A30587A72A0AD7F9A43849E201D56E5E76B747BD8561E97ECAFDA4EA84B0E2E81BCA1944971D152C2D442AFC45016140813637B7B8C0E2BE2B4A94B3242D7C7503E55106B4AD4791EB487680901DC30B546BAB5CF2FF1132C8BD89F2547039A9B582D6E0238E9452BAA13CD2548570F94ED88BC5FC58CC65ADB0F8733127FBBBCE137D99EA74A1B5377085201254B02C01DFDEE6A7A98B4F2FF0065CEC474EA52ACCF4FFF00885C708EE5DFAC5453776A4EE4A41F1151E4623A9338ADE69DB3CEF3CE032E7AF03DDFEE1FBCCC7A5EC1B938BEB0C71B3004FC81FA503EDD39D3517BD8F92E82ECEB4F84FF0002D0F4AC70C7097541FDAE27BE428CEC7CEF88539AE70B491373198A7B8019E8D707D6FAC46778ABF057FF005505B4D1EC6BCEB411384559612114F95E5B95A2200465F48E97472921A0470F29BE21E6CC2B5154C9D3D4A15713A6001479057E5B771194CF9B60199EE7C4E8E437D2F48C175599387F969A65CC7D8A561991063ECB698FC3EE406214876338D35993162E373B7AECC20FD44FA1A5A96BB9E6F6F510980CD883DF2C5288F070A52AE3EB3C3B797320E14E29F8A002261436F523CEFB1B6F511A2B1D8894411C4C0E85B8ADB786AD4246D081F4D692AFF3EBB5FF00E198DBDDD6DCAE07A6F2F05892586206946035BD6D4DEF7B46C337C4B8002B954FD7D98E292AAAE9839C59824154471D325CE28F250300758BF2387A301895103BF2E3FE25AECF40CFA43C4E6F8A21DD7B357EFF0088455B995528101343524FFCCCBA9940DB9F1B4A3E9B1DEDB4C94BCAE69487C4CC06C7FDC56CDFF2F4737D459CA33AC5ECAA5CEA7616D2E77A3C42739A2CAB3E6CD1EA1D2F95E6748E712168451D1D31095483E36D90AB8B4CCFE2A4BCD330ECE2BBCC06227267AAD302D6BB16259448FB75D657079BE216405F130AB59EEDA8F0E7AC755FB47F61EF67CD76CBF579436746E78F0528290AAAA94F78648F0CA5BDCCEDCC88C5D725F897DA494A40C499B8E24D57C7DD700DDAC76E9EB76CAF3C521011DE84248658500A2DC8A99A9B75D23CF8ED5BE8FAED3B47D2AF36D26FA759654C079C77BB0C5338C34992986CA94EB9C491C8488913271DD3B2FF0014F033A748C2E3712A953E610132D615C20815759F97CCD7D0DD3058CC3CC40216971552C2C3AB88B8F968CDD181F38E8266B95D4E4F5CF65D9EE4F539457D3A96829A86DD6C1520AB8A0AD0849888B4CF58C7A4322CFF002AC44B96A5E3651700BF12542A0355D9F4DF7E73F28C9989052A0A49146A934AEE450727BC449DCDDFA975CA7247774D01B200D9513717DADF28C5AE74DC2E2403849A89CC3FB0BFD09ADF50FA6912299094212B02AA7A359BDFA084AE54AC78BC50373B7DE07E186852A4D155E6CD7AFBB429DDA9BF6D3C1BA6DCE113952A26C6C6F63EEE9EBFA6D848CD40B9EBEFDDE8F1A8049600B8A5ACFCFEBEB1A8D4AC0B98F327CFE1B5B18FD44A667AEEFF0068C9045FEA2353952AB024F316BF5F2F220F48F8B798B4ACBA4BFBD6A76DBF10B4A415548A6845FC287C7D79E935046F23D47FF6E112A22E9F5FE21C77279F98852C544855FE71F801F29F3C63BCE5EBFC41DC9E6DD45FAC62B7FA104EC2E3D4DA3D718EF92ED4715BFF001E9783B93EDBCA349A829224C1BC7C0F41FBF38C27326254086AE977BF4F7E31A2E480D4726FCB6AD1F583EB47FB8FCFFEDC2109F75FF6FAFF00307D649E7F13F98C10775FF6FAFF00307D60F51F11F96083BAFF00B7D7F984EFD491C3E2DFA1E9E83CF09CCD3C7ED1BA255E8478FE49F7D213FD68FF0071F9FF00DB84E14EE4F3F3107D68FF0071F9FF00DB820EE4F3F3107D68FF0071F9FF00DB820EE4F3F311B1156AB8E23F13F97EFE184E669E3F68D552942C09F23F4F7F6D9F5A57F71F9FFDB84E35EED7FF00131B9AA95C9FB5620DE7F21F0B7E4463815B7A8FCC2D455192788C7333B7CBF3C60902E5A0E056DEA3F31B455994C2ADD419DBADC45FF6318E34EFF5D6353254AD3AEAFA6F0B98AC54C71729E53EB1791F1913D2300524D8DFAC21370C412149F16EA199FAFD61C45728100199BEF7046FB0BF2F775B8C6D0C662129714BD7EC6F4A0FB43C51D63C2150AE198920DFF2837F7C8C10D7BBE3A243D68D424DB7A373D2241475CA75496388953EF30D260C905C702009E57311CE6DD433CCF172F0D96E2FBC584032D4CFA963E3AF4874890D2660586F94B02CF6EA3C74173B8FA1BEC932E1D9FF00B2B68FA5ABF0AEB692B56FA17214A2B778DA2524711FB408B1E51D71E199934E33B638F2E5430D3D3DD96268B25EA37B9DA38EF690044F4F0D52565C8B33EDCBCB7D0C7955ED5B912354691AE79C6F8DCCA3BF5B64265403EB2AB089DAD69F3C77CC34A98AC249F94FED0496A014F07D3CE3A3FC3AC54B44D9616B01D40124B061A07F7E11E28672E2A8A502789B75C1C306603846D048B7DD79DB137815CA08582B014CC4539D6F4D6F1EB0C1CD953B088E050AA400072035D35362D76DF3154DD453A2A160ADC6C0EE85E49912600331CFE06D8D1084A4AD4A2CEECADE9A7B6BD223CC89E678E142B81EEC5BC09D0EE2D7A54C4A74DE9FCEBB44D4791696D3ECBAEE699C54B6C90D24A9494A5C6C2AC0181C04CDFACE2A39E4E9638D226A52A6E27BB302F63B0B18DF3AC5E0F2EC0CCC4CDE1265CB2E95109F988212C4EC40FBD63E95FB2CECA72EEC1FB12CAF4165E86D8D5B995353BFA8AB1290871402D152DA54B1D1B5A9278546DBE2858291331F8F5620712B0F294D862D4512196E1AAC46A3CDA3C21F113B633715984F9689A5654B502534012F40002CC07896E91EA7B1926655447D58771C5B712527DFE2B981E43A1C70B9B89080E54C0D5C124FDDBCDB511C942944D0FD21D11A1B377071E6199B6C22070028412AEA0106C3DF73CAF88F566409694A5129FDD460281B91A335E90ED091424373BDF56D3C39F8F1FE09D3E811982D35A6E1512824F9413CB78FBB1AAF31C451A628307BDBA907C74BDE1596CE695F31BFE3E9B46EA5A0D0D917789A4C992AAAA93E15282DE128F25A4A52098B1B61AAB1D8CE204E295C25F8925DF956FA5FEF189AA008A577F0FE7AE919C67750E7F96A7A5A7A256C94D353A5413CBC41015EB27D26D8D44CF9F88F1926E4AD46ADA827E83F108F78BD090341B46EA8CBA128287DC2F19EFC254A0279020103D23DFC861F2677197500E2E4A413AB69F8680AE6A59C902BA8A37BFF0031C3542120711BDF71C511D49EBE67607AE1C8095A5C067A6BF4A46C0CD21C1247D2BAF46F5F2DCE5234EA47110422E2448E879DCDF6F28C289509746A35F66DFAF4A985E5A4AFF73923AB0DCF5F2BF38D7DCD3B444AD23681C201B7BC79636078DF8535DDCF5B102E3F30B7729DFD0FE61BAB6B29982D8E2499E21C8CFBC9FDFA61497825CD04A659D0D8F4ABECFBD3D20EE0173D1FEDA8FA4361CF295A925C47C0088F779FEC6153944C51A20DAC4747D2A280F5D20EE13EC1FCC6A7354D12225D47389208816B79FCF7E787523249E6BC0455E9B1DF6BFAD2B19EE65B5520EE5839F12E69A43255EAAA3330E3441F31F76DBC91B1F75C3F464588B842A94142399FB5CD39DA329932925F801F7EBEF48627756D1200971B93E693F8FE7E98728C93141B841D34660342F63EB7687689128BBA035281BF07C36844E6B1A1360E376EA40F59BFCBE6360F5392629A81637FF3F8A561D2654AB042481AF969D7900DCDE1239AAE85F04075B91E622FCE06C07E56E78752F239A0033251535DD2F72EF5E40BB3EBA34394CA40FED62350DB03E9CE8F57D9BDCA8A3AC061D4926F2089EBB83BFE3E58D66E5E24A4B4A0826B415A78529E7F58DC4AA6CA3F228A46843D3E82EDF9A533A677F8705BCCACA9C5005BA85ABBD698FEE0A6164A17C62D04731EF64B95396381C841FDCC9295F50B4B283105D8B6E43346F81CC7132D6089AA0C402EA2CC6FC8EEFE5A452BDAEFB3B7657ED079255B59D50D2E5BAA10D2FB8D40C301905D20904B0C25B42BEC84893326712B83CEB39CA1094E13113A6E178A924CC53CAADCA892A2EE0D7A6B1D4722CE56952146610B0DF31A82FA312D6D8163E9E0676FBECDFADFB00D4028EBE8AAB34C973175FF00E139BA1A3DD38D3249517036161B02401DE284F58DFD2BF0AFB726485271B89EF0A827E55A98A696625F5367B3C757CAF128CC51C4C94A92050597CF61E7D2ACDD7B66A2AABCA9879BEE129DDE490E4C4CCA40B481CEF3E631DFF0D9D61F30ACA5A40536AE6BD0D2BA6FD626BF4D2D29725A96B5ABF7F0AC37BEF369754C21125AB17B889EF49F2330009DADCAFC9FAF2B5CE485256EE2E3CF4EBAD3D61AAC4B42411FBAAF4A80F4B0AE82BF68C50A49DC7BB9FE136C4062B053B0EA3F329B986A7893F5864A4AAE09B583EEDEEFB721995A524F4311BCC01EF3BFDDF0CE04A8F1025DEEE76B6AD0E308EE41767FB8E9BDFF00883BE4F4FBFF002C3F2A01DC57FE3EDFEB121C09DBD4FE611D53B3C3C260DF6E9EFF003C319AB1500DB5A8D6AC6CDF88D880407167ABDFF10938D7FDC711EB98A7724977D4C60002C238E359DD44FC30AC82E76D59F67FE1E02906E1DAD071ABAFC87E587718E04EDEA7F3071AC6CA23E1820E04EDEA7F31CF78BFEE381AFF009F67CA0E04EDEA7F31C15ACEEA27D630D67000800333FDA3200161071ABAFC87E5846331B5B59BCDF6F238208DBDE797CFF4C10462A722397CE7E58D9258B9DBCF940C0DC3C63DEFFABE5FA6304B926D030B353683BDFF0057CBF4C20A5BD4D00F1FB46A5293A0FA7D20EF88D9447BBF4C325CD2C43D352C0F9341C09DBD4FE63626A426788CED1D6F31F71C21316695AB12696FB69A43BC3CA4283148DF9DCEB5E5D2B0AD15224907736BF436FBCDAFEB87324D5B6A75773E1EB08E250928500966B53EADB8E5D6E61522AA1485893C324DEDE5BFEEFE7187C491C2A0683CEBE86D6D0FA56E6C924AC17F9EB41E76BF36E557893D16A3294861D4A7822012120C5B9C1F2F4893CCE365E21294BB81F73C9C535D7C637C160F816EA0E97EADB6EE5C9F08B7BB19D22EF693DA4699D1D94053EFE6D9830FB81092A296E89D4542ED36F020F911CA71C5FE26F68060E5772998C262174E261C4052C59DECDE05E1BF69669C2483325A820A12C43548550F5A1AD3D5A3E84BB5B798A3CA72ED22CAD29A7C972BA569B0D98417051B45C848313C6920C0277C710EC5E07F5B3BFD426CB3DECF984CC2760A3C26DB0D686387E6D88EF2628514C5C171527AD407D457768F33BB46AAFAF52565129292AAB45434A4AA088485A504883262FF00AEDE9AC2E0D2AC0042501FBBA0A5DB571FC987FD9CC44E953A584ACA7E6B0E55A79D3C23C43ED37275E9BD63995238DC043EB294910077C4A840023FA8444EE4E39DE33098AC2E294A05411C44EAD7AD4B69F6A8B9F5F763B18676070CA5AF89540A725CD69D1B9B03B5A21AC9719535434A98AA52BF94BE1E3E10B32B49491078C2B844891BE169F998EE38388021245C39A6ADB3C74CC666585C160D454949570FEEA51C07A6AC0D7C1E3DB0FA3E3D9D329D17962BB79D754210F6608074750D4A095B0B48553D639C047178D452B1C690003E13071CB71EBC4E331F351256B51E2F9C970250351C94E1C3E9E71E4BF8BBDAD5CEC28C0E0A6148477826CD0AFF00ADC45D3F2BD022C1AE7531DE6D53AA2A6ADCA87AB1E0A6D4496140A6C89809B2A6C205EDF0117CECDE5AA011C49A06AB0A93ADAFD1C8E4F4F21284DC46314B9CA2B254EE5CD8FF0000B374D23D7253B5B5622980667688113F033EFF004C78E0CC67A927635FA822357ABF8C6AFE159A2FC558E29E1B23C6501039EC6FB5FF0063092945449DEA6DD2A5B9FAC3D41241E5AF2FE291B0656849016B29B192495F43D49C6841208767F7F785E5EBE1F785CC51A5B0A534845544151584A7BBF4E2DE77F59F5C22A965C104BEED41A59DABE118980167D5FED1CBD5F4AC8E17561A3B140492262F71D4F4E9B5C61CCA96B5800034F0A3EF6FC7842600028290DCBCC2848269CC9FEB93F0249DF9EDE677B893938659AA83026BCFA7DCFA40C0B3D48861ADCE12D9512B4003A293CBDFFAF2F5949382510004923EBE3A8AD1BC8C6CE588DEFE1115ACD56180425693C57FB43DFB19FBFADED898C2E5466B7125C8616B1BF8B75A38EB0E30E81A1BEF7BD6BAFBB3D6119AEBD534490B1239F17EA7FDEFD266B0D919268871FF00A7DF8EE75D9DF77CFD22019A7680E3BC27BD1E12A89501327E1E9CFEEC59F05D9B26AA96C0B386FB36D5FB6B0777CFD3F9881667DA2BEDF143FC37BC2A46D6B4FE9F218B1C8ECA099FB500D350DE1F814D2918E02FF7F7E1E7AB188357F69D52D903EB0428CCF8F7DFCE0CFE42062C380EC8238085201234E1B3DF9D7C0F331A9412086E5BF37A4466A3B53A8850EFCDC9895DC472DF7E973E589A95D9094A1FF4D9887A1623621ADA9B96A6B00429ACFAE9E2FEA4F588C661DAB55254909A832267C7681B400679C7EE43F4762D0A149628CEC923D5EBC853A42F2E5A941EAE7705E9AF4AF28655F6AF58524FD60DF9779B7AC91B9FDC9C3C47629240694073236E82BE5E5587694AC0DD46F6A372B7E00E708DCED76B1929E1A851E23FDD3B795EE4ED3CBDE70DB17D8D290C9941F9279DED51A96F4891C3C92B49D4B5697F77E4C5A1DA8BB6FAA640FE793B48E21C88DE7D7A479E20315D8A98A04F766D6E1B79529ADE94AD1996330A482403CC5CBEA473A5BAF3690B1ED06E32A4D3BAAEFDA7C8E2638A3BCE1823C60786373793B75C404EEC54D49E2EE94E2D43AF8066A306671A38786EE95296183925CEC5B5E6D5B7DE2CFD3DDB9E48E1698CCC269E956414D3059924EF2EA6151241B9B6D30311388EC8E2405AA5A4A2616E13C20B35689B568FD68627B058A992AAEE28E2BA1A31A1A369FE2E8CC72DD01DB3E93CC34BE7B47415B97D753F754B5AE1696FE50A5A49E26E65E59716A04C111104918A8636466BD9EC6C9C54954C4CC493DFC90E0625BF6D6825F00BB5DA3A9F65FB408929E098A6B1049763CF42093E25F9478ABDBDFD1F3DAAF65598667A83B3EA7735468AA95B8FA9D692842D968952C2528254F2A0950B09B6DB01D3BB1DF14254B9C893899865E210405495929035B9A59CF3A8A878BE8ED1616700998A09243F7AF5E4C91D408F36F3ACAB30C9730A8A7CC69AA696A92B297296A69DD616DA84820075292A122E403D27618F4A647F127013D2841C44B51200AA83027406AE39D6AD416890C2CF4E264A149140FF00EE38255D520BA4528F7E7A321AA29540B106F0608E7F1DBDC0F3838BBA332C2E6684F76B492B0E450DE86A37A781B8A3484AC22A790D507602E06CCC3CF581152553C46E37BCC721FBEA00368C4762E58C190A019CD2ACE3F8A7A9BC3A565EB9041524A5EDB10DD5AF5F0EADB03E39284F90B88E7FBF74618FEA945E8E0EC7CEAD5F6EF0770B735D9830A7AEB1A5D72786F3BDB6FC3F5C36993BFE5A5A967B79D2DCA306490E49B72FE79C69EF3CBE7FA6102B0BB69D75F01B465324AAC7D3F983BCF2F9FE98D90B2922AC3D9FAC68B41433977F7EFA41DE797CFF004C2BDEFF00DDE9FC4690779E5F3FD3077BFF0077A7F1041DE797CFF4C1DEFF00DDFF00B7F8820EF3CBE7FA61354EDFC2BF602364A789EACD0779E5F3FD31AF7C9F6FF88DBBBE7E9FCC6C439B88F9FEFEEFD4EF93B7D7F1EFE8777CFD3F98D9DE797CFF004C1DF27DBFE20EEF9FA7F31A1E74880047BFF7F77BF1BA5616682DD75DEDE1D3946C257158DB5D23477CAFDC7E584D6B147A0D2F58C19453737E5FCC1DF2BF71F961B4D582181A8F7D6DBFF9C777CFD3F983BE57EE3F2C342B0297DF97A467BA3CFF00F1FE63053E411336BDA3DDC87BF7F9DD25AC121D85FD9F7B987B87965AFA736E5ADECFA6C291BD1526264F283FAC18BDB96DD670EE5A81D6A40F41F6DA1ACF0CA524835A00DE1D7DD0DE1E32EAB090EA9C850013E76F416DB7999185E6CE4CB492685A8747E5E8C7C7A9232E1398F01351F5E54EA75B0DCB830EB398AFB9694942B69046E4C6FB72F4B1D84E2AB9866C25950E2B3EA69F5B830BCCC28C2A4A8A5D22E35D4BD3AB51A879C7AF1F46476448CBB506AAED873A60AE9F45B0C8A05BA8FE5BEACC987183DC2D4385CE051495168AB84DCF0918F2C7C5CCF138AC6617042710A9F32810496E1525DD999F623560E6392F6F730E14A422812E082DAB114D7D1AB1DC8ED0F3DA8CC01AA5A897C3D505D24C12DADD25B1E8106398F9E3A176170A0612495A43290928A6C056803BE963778E32B9C66CCBBD89AB35C6BA077F60C74B35CB08FAE665560F829928537D09524CDCF9CDA37F3C774CA25F1CB94959AA8B35ACD46B7BE7164C94913D079BF4ADAF5B1D9ED1E52FB4464FDFE7C3374B453F5D5A8A951013DCC004AA204EC27DD7225AF6B72A97230C6680012851240D838ADAD4D3C418F4B763330E094002FC3C20279F21CA9A56269EC6DECF755DB57692DE719BD3B8D688D34EB1519F5538DA836613DE52A5B240539C4E37C2AEECAB732236F36AF1789C4632749940A8A14A4F059DC900BEE967E64342DF123B649C932D01C0C4625244B5F13997C20713A6B705803F68F6FB5867B414D449A4D30DB6C65140CB3454397A385A6D80D212C38E0042412E1471EC08E66716DC932698A4A3BF509D36A56BE009245481A03C2081AF8C790B3BCED59A2D4A2A2788927E67A9F0346B68DBB88A7EBDFA948A6A075E2E97B8D5C615207F5904824089237D85F7C749CBB048C3CB0A609006C03F2E5E772358AB8C331E337B7315BF95A8FE74FA0166912C8492424889EA46DB7BBF1EB8F9E17600F100F4666EA7C5EF5F288500A8B0ADE8D7F1B53F8BC735110DF88CDE4498DCFF00BFC6C70BA1249568295677A7BD7A6B0F91FB46DAF99F7E3CE1BDCA869BB2943CC4EC3CF95F0E048E20DC26F7624BF4635E45AF4BC2D2F5F0FBC3555674C5288E3038A440316E460413F779E1EC8CB5534FED25ABE760CFA3F37B429107CDB52D3F8BF9824837B4CFC763F9E2730D92A8B320D69635E9A75EAF04416B75630DECE01320F8A36EB16F96DB6E062C586C8944370D9AC1BD9176822B7CEF5835E387881B59663DE27E079F4838B1617B3A5407FB64EBA8FC0D18736171522A9CE75F268882878A839C5278F6B7207CE2E2201F8DA32DECD93FD8C7667B6946D3C2EE758752120EC0EFE6FE240F467115A671DA72A15E3277FEAB917E9BDE79F2EA316AC1F66C3B775E36D6BA1FF3CA1D7766EF417A796BEFC62B2CDFB4B528A4059B49B28DE3AF98B1DBAFA0B7E03B3A97004B1B540E4581F7B883BBE7E9FCC40B31ED21609FE6AA6FCF96DB93B0F889B8E58B7617B372D828A45A800B026DF6A3F283BBD5EDCB7F1880E6BDA22D6A49E3322608519F7FC7D368B62C382ECECB485120076D07261EFCA1D4990662598902DB68EFD6D5B5DF588A54F682E03016444C9E237F74DEFE9CBAE25E5E4726AE0519E801D7EBF5BC3B4607899C585E94D2BCB93B1D285E2335FAFDC25242D5378854FE16F8F94C61F4ACA248E2F901B7BFB5A9CED0E118124B3160EC451FA5DDB5F1D5CC313DDA0BB1F6951E6B2239CF3E43EEE7B3E4E572831E00FD03F88F62BE6E9182A5BA51ECDA86EB4B6DAC256FB4170714AD5D6E6639DB7EBE97E507189995C851AA1236A8F1E5B5FF00C49613046A120B16D0D3C079DEBD6315F684B93C2A23A78B7882791F593D37C6BFE8586994084316D05CBF5FA91E10B4CCAD4BA10C3A16D8B57CC5DEED0A287B45524A8A89266DC47ADA0123E406D1CE70CB13D97C3AC1696914E87C75E5ABD9A239791A89A21C7420F236D1B6D46D49053F692E0825C36123C4444C6D1D3AF2F7C62BD8AECBC9493FED8A93A0B073BEFD234FF465A2E867DF939DBDF9C58DA1FB69CFF21CE69F30A3CC5C6F2F60CD7B4A76CE050F04052A41046C07AE39B76B3B12314852E54BA804D12FE4E29F810DE7E171185FFA61418559FC3E97F5DBD79F679EDE721ED4B4E2F2B5BB4EBAFA1427FCBD4703BDEF112A52781C0526C0C883B89F2F2C76BBB3188CA718BC4A50A12D45426F0F12598302E19DC81EA4BBC664637168042CA9C7ED279173E82A5FC6C6211ED05EC5FD8EF6F34B53A86A6869B27D62FB6E062B2999534961D424A01532C8432AE30126E39CDC9C55B29ED563F2E9B2A4714D0994AF91456A20825ECEF4A569B522F3907686761DD066B22614858531B17A136F4D2D1F3FBDBE7B16F69DD8B66B5B555197D4E6FA790E38B6736A740290D4920965A0B518102FE64ED8F55FC3EEDF2E709427CF73F2D0A80A0E4588B5DAFB4769C97B41829825FEC4B0058904F3E95DCEF7D7A8A288BEB7FBB2A6CD3102A4B80B6A76491C3C0B852784C8902FF7F72C56792B1F2E5F7530120025883B0D2FE4FD0459B1F8A938896832F84D3420B16E54BDB61CA836B596BEF254BA4506823ED490663A027D4C6E27E0C462D540FF00C5B9357CB66A444A4A6BC49E2F13F57A587AC25356DB84B1C10F3261D5DC8513B1DA3972DF0A8C4059E151A8F7A795F96B0290400480CAF6C418E7892398FBFEEC3842B436D3DF38D638E34FEFF7FBF8E09EAE1A055C69A8A751CAFBC2339C800549F4B17F4838D3D7E47F2C35756E7CCC36E156C63052A6209F3DC60E23B9F38D822EEE36A8FE63193D4FC4E073B9F331B700DCFA7E23893BCDFAE14429C313516AD5AFF98510002075BF898E64F53F138DE178D88544C920F52795B9E08233E3FF0057FEEFD70411A9C50312A077DCFA6364AB85E8EF046B91D47C4632A5B8666DF58C100D0C71C69EBF238653161CF0BB9B9FB0F7D231C097FB69F9F58389279FE1F7E1BA95C2D4778DA3153894F39BFEFD7EEF3C204804026A6D12B8295C52D4793F3D5AAFB6FE5025C4AA6F11D7A47FBF21E587D2940DCD2846BE1F6E4622B152DA6B58F139A795B7F1F1854CBCA553BECB07F9CE29A09DA7838877963D1336E97E8434CD279972CB280614DDF6D77F41B44FE57212521C3961CEFE96BF90DE2CAD11D9E56EB3D6BA7B4BE9569CAB733CA965B7D2D712BB94214D97CA8DF8470951B91B475C714ED3674B9054429E8B7AD281CF8916B78C42F69B132B05879B3967FE98A21DB89C5F9333B7F88FA71D1BA1F2EEC7BB2ED2DD9BE5DDD8464D445DAA7109E15D43B5A94542D2FA8789D2DB8A504F78A5445A0638263702ACFB30398CBE2577B31248539E012D4051D99DAA68EE5DE3CB9DA7CE5599E2169E30424B30346A016D19A95B13D280ED12B920BBC3037DADFB8E5F9E3D25D8BC29461A44B218A529141B51C7A73D0EB15A929E250043F3A8FE3AF5E74E9EEB4A9A9A961686CFF97593F58322641F04F337FDEF3DA3072132C21668CC40B6C4DBD0B3F8D22C980024A9045DEDD341A1DF5ADB9F5AB3EECC737ED773ACAF43E594AA76B5DA81F5D7D081C2DB0161C27880013FCA0660824CC620BB699949565D352A58480929248A82CD6A12E6836D869D3320ED18CBA6226B717082C97672CC5DDEDEB4A47A59A6F46699EC07B39A3D21A6BB953ED530FE24EB690971C7970E14B8BBA97C2A2A0029460898031C3723CA5588C54C9BDD90952DD2752E4FA1BB18E71F13B3D9D9BCD413314A751700BA458000025B4D2BE51535766C336A779E71C2D8E2528A42A2E144C5A01B827F738EAF80CAD322585283300EE0FDF6D869AC50B01835291C641552A1BC286A5CD6ADF688B5255E699857D0E539334E543F50E16D4B00A8A1054028F1198F099EBE9BE13CC7304619052080002545C0B57EFEC98DF1BFEC8370C0B1EA79EF1F44D599B06F8A1409B990403F01CBDC7A63C0F2704EDF2D3A1A7DF5BD3CED570160964B0B33B9D6EE6F5D0D623CFEA0201957853360A173EA7A749F81C49CACBF8BFB0BAA83A52A08FB3E95AC3A9648A58A7EEFEDE2119BEAA5B6550E0000330AF97BA44ED89595969424012DC9D83F37B86FA1BEA216439249E515C66DABDE723F9974F15F8C017FC081F941C59F28CA8A93C4B450B0A8634B796AC2FAB43897AD36FF001EFF00115D66BAA9CF12BBEB9FF501E5B4CE2E584CA40E1025D68CE9D5EDE15BB7A38522B7CE756BA8E187C5C13F6803378E7B9FBA05CED68CBF264A81E2410A1A33F859AD6E45B4822ABCF357BDE287A08B9F1CEFD2FF00BBF5BDBB059225212D2DC3683AD0FB7E71B702B6FA7BD62A9CE75629453C6ECFDAE63EE9B7BF7E569C5A72FC88DC4B6DA9CEA3EA2FB50438929A07A359E807F80DE25F578ACF39D5890170B060C9F1794DA0DA3AF2B62C786C9549209960100B16AF3EBF53AD1E1D3278801CDEB4B1D5F9457F5BAA42B7546FB99F5E73E5EE3CF13D83CA8A6BC35A0B0F7616D3D236128AB88814A01CBAD7CAB110CC352A49278FDD3B41161F1B462770F8166052DCF98661AD799D6D1B270D3174483D4317EB703EBADAD0FABD42924CAC9898FC7F193D3D6EF84B12EC9B5B407C7A537E91399760560FCE926C6FD5E8DF588ED4EA049264C0E809F95EC363E5EB8CFCC5E9C3E47EDB0F11B44E8C18FF00800598354B02FBB56F6EB0C5539EB64595224DCF53B6DFB163E8BCA510DCB51CEFF78729C0A890C9A0B8E5F4F426196A33C499124474371D2F3B1BF3FC70E78D2039142D473714FBDB9D2242565E6C12E59C6A1BD2DA1DBCA10AB3D42448541E927EFE7D7E1E9889CC3126590516AFBE836A6B68792302A4129281522A40617D06E7D884ABCFD06FC5D058FADBAFFB88383098E5310A074151D37D696894465E1403A59DF4E85DAAF4BF95291827512533E2DE2F226C67A72F8EFE5896FD5CB2E4ABC1DC96DFECFF00430F539525491F2D1F6E9A31F4DFC21C58D4C9060AC587F76FF1E436F7F9E186266CB268A07AD3DD8D1A8FCA345E512D4E38452C680FA5AAC34B9B80F0A1DD48B7CB6CB5545A2E1E2212AFB7C3732418100409DF60271B60B0586C64A9826F0BB7F7355DFE82953E1568565F6764E2524109046E2F76F5DDABB3B45E1D90F6D59AF65FAE74C674CD538DE5B515496AA9A4AC94A8712199589200054771CE4440C716EDF76330D8D973BBB48527866592E4163C24B6DBFE1A2BB99F65F825CE32D20AD0C50281F7A1342351A57768FA23D3FAEE8F50E52C67678174599D1D2B9421A70143CA0CA0BA12EA0C24A566E2649B6FB78D732ECC8C1CF5492C67485AFBF510C500A89438B971CA976D4728CD26E232F5A9402801448E86B5D1B5EB09F3BA4A0D4794D56599AD15366F4952853672D7D0D4A12A0413DFB8951E7C5BDEC0488C2580993707353370AB5226CB219692A2363F2DAC7D0F8B7C376DF1386F912B5914043B352CEEDA72D6D1E457B4D7B026579A22AB56F66B1455680FBF9A652CA09EE54428B612A5101CE2B93C22D231DCBB19DB1E2C47E9B315AA48584893314494CD61F35E8963E7E11DBFE1F76B55994B28C54E60867E321C397B93F6A18F1933ED3FA9346E775392EA262A68D54EE38D82E34B4F1C122764F9441FC31D7E4665865DA7A58B310417717BB01D2ED1D725E270B8948326625445569E214DB5AF3E66CD0C2BB2D4509841D9569579C1B89F3E989595325AFE64A817A82FD5CFDABADA14490A6E1ABBF266BDF6A3F3318952809260752001F18C48A1429C25C1201FF27AFE6374A16A0FC247DA39E251124C03B18DF69823A0336C693663060A7DC6EEFD5BA78D1A1B4F42812E0823F87FA3FBA16FEF3F03F9E1AF79CBD7F886D19A386F2E7C41FC4E0EF397AFF118248B07F168CFC1FDE3E1FAE0EF397AFF00118757FC7FF708E0C5A140CCFCB0ACB983E67F96D57EBF5F778712412412185697F17B681B9BED0614EF11FF00210EA30592220F5FC3005A4D8BC11871ABAFC87E58CF1A77F43F88235B8A55AFD790FCB194CC4837EB4351FC7DE0626C1E35F1ABAFC87E58D57352A71C4035BF1BE8C5E33C2AD8C1C6AEBF21F961B19A80402475766E55FBB46785550D7BD469071ABAFC87E586E66A058BF4FF00107028D924F484EFB91C337DE4C7E42DCE7D3E1ACBF98B8AB5CF33FE6F13B9620095338F67B59B938AB8F1BF5E1A58292A83C3C88048313E5FB8C3DC3AD0A04715B516D4D9FD4DB7DE131692A9C78773EA691CD3D6770F21C68F12B8836122EA5170F0080249B9B002FEEC577B418EC361A5AC4E9E94382CE41AED7A7589AC03C994A2B7400E5CD2EFE4C1EBF48F7A3E8E6F6776345699A8EDAF545377CBCD508569C66ADAE175954A997D496DC1C6012B064A40D88240BF99FB5D9B4BC662266130AB3314E4AD601646A2B6214C4339357BC719F8979E61D1226265CE495F0AC04822E6FAD68EDBDF471DECD635D54CCBEF39C6A7F89492140C22E52090792488BFA011675D8DC377C959989F9924740E59DB9D39EBBC799F2B9B37158A9EA98E47112092599F4DF537D183523A8DDA1E624878070126E52140F3F2248DE31D8F2859C36265A00F95C7CDA50694B8DF6F4B3484CB04592CFE049A5FED58EACE66E56E6598D3E5F4E14E3550B536F250389416AF0B648124788CC8F59C75D562F0E8C119A5680A12DDC903FB7AEFE3A43C54E4A40F983FAB83B0A57AD393476BBB3FD2947D96E987B31A869B5EB7CC9B0A69E570F1B6D90AE6652921856DCE23CB1C4738C5E2339C6224CB0A5E082D42600ED34834622A38540EB51084DCC57292784B91600DA8F7E7CEB7E462ACD4DABB8D150D3CF29FA97D64BFE22A83C44F224589D85A05B962FF009065089694AD6809A07040B01D03D1EBFE0454C4AF309892B06849AFF9F16D7A308AB4E64F543AD51D38528BEE04F0A012A32A8FB224989BDA7CF699EC7AB0F8794A485A41092087A58D05583EE49E82D137879587912C82B4A484EB4F4E7AFDEE3B71A0324CA7B39C85DD4D9C3487330A9642E8D2EC071B54113C06542E41F1016EA231C4BB478B998C98B9387515842889894870E5CA471015E6DCDF58A8E72A0E4CB75036367AD2951B1F0E71EA36659C3664717226EA36B409F3B728F80C79D70B8304FED776B8DB6AB0A3176A7A4457027D9B7BE6F107CCB3B4240FE6753BC7A73E53EEC58F099792DF2D000006A907EA6F190902C22B7CE73C412A973ACCA8C7BBAD86E39FA462CB85CBC10029034FEDBBF852E06BCF9662B7CD73B6FF00E6708BDF889B6FB6E4F945FE3369CBF2F649E14072DE7B6D7E5CBA64122D1566779F24154BA45CFF005284EFE7602FCA716FC1E0520A4140AB68C4B7416FE3785E2AACE73B4A88FE612255038CDA796FEF91E96DB170C065E9FF008245051ACDFE75FB42E00141158E739B83C443A7983E237F2EA4F5E5E9B62DF82C024B3A053560341EB6A783C390C34A569FE7D8D22B8CCB34E22005A8913FD47DFD63A927DD6C5A3078364FED1A5C0AEC341B523632F8806A1DF6AF8546B6B59E21398E668F102A207A93E47FDF9CDE263139230C90015005AE1AF571A3736B885A561D45882E353A9D0F97D1A2179866215C30AB09E7FBFBA0DC937C3F972E5D59228D6E4FF4899C3616CC1DFCC56C2F7BF880F678BD556A493E283CAE679F39E63D3A838708968AFCAECD7FC79FE22730F82040743125EBC98F2634B7DA2355B5A2D04F393227ADA39F2F59F5C131080C486BD757F7FCEB12F84C210E079816F5B753E42D1CAAAD4927C4444C5FCAC664721333CF081084A41201B87B52A3EECDAE9AC4A4BC3970C97DE82BF5D343AD7AB2B95A0920A8DB7827693EF883B911E778C375000B00DAEB57DE24E4E1C16743BEC2BF47DB7E621ADFAC499B9F333063CFE07CF7B73C36529CFD044949C20D45069F9FC56D48697AB120024DEFCC47BE08F3933C8F48C359C0177AB3372B7958F9F3112D86C1214DF2D587570D4E74E8FF00442E5724EE7AECAB7C41836F8C0DF0D432052A0BB301F514F7E4F0E0827467AFED3F47D377F268D06B5226E62FFD5D3ADBEE9FC7092A72C502BC341CBED00904101E96A066F0DF95631FAFA3FBA0F3F10FFB8619AA6AC9352DF5EBEF946E306B0EC0B1F3FA1F6F7731C8CC9C410A6CA890A489E29DCC6F262660C1F29BE1D499D3112661130A69A7FF00AB4E5BB7285E4C8293B2B6D4EAD7D6C29E178795E7EF32FD352125448E2124CA4C05483CAF04411E5388BC2AC4E4E204E50997FDC1C6BBB8BEBB6B18C6E0FBC94A253522A6DB8BEBAED6D35F7B3D853B48675CF616F69872A0AEBF43A9A04AD654F2BEBF54560152CF11802D72074DA3C87F16B048CBB3999899008566055DE84BB204A0424DDAA7616F5E19DB0CB9284CC1DD8643906D777D8EB4D43DC388EE73F53DD17521C238D2D917327853248827DF706200E58E7FD9A946609CA5FCC0115218D497FBB694B6B1C52661889A43317A0F1AE8CCCF7F5668462B5AA94BE92E250EBC9E14154149004282C2BC2AB75F4B5862CAA966594841E14A4BB815A9A310C7AB1357A6D3B976327E048EE96657135412051BD5998E9568E977B41FB33E8FED432FACA9551B0CEA1085A9AAC6DAEEC2DC8241212128E82E637DE3172CAB1B3414A16B570822BC44B5294EAD6148EA9D9BCEF1699A850C42810DC4E7881D0821EA2D7E54263C32ED47B1DD57D93E78E51E7D46F399754BAE8A2A94A49404B64CCF76088129E7BD84CE3A9E513E624242A605022F4A027ABF9B78D1FBC6579948C6C994A03BB9881F3077EF1D83F2D49FADE295A97EAC3C94A877F9783B240494FAC4AAC79CFE38B74B99C49705F7B78728B8E1A6CB5212A291C400047A3697BFB10B6A54A0D30524160825A47347F749DCC99DC635984D1CD4DC56BF6D3AFD90C7250B4860C79ED616F523D211779E5F3FD309C45F723979983BCF2F9FE9820EE472F330779E5F3FD3041DC8E5E660EF0F43F1FD3015F06F5E434EBD616932921DC0F5FADF783BCF2F9FE98C77C79F9085F813B7A9FCC6D6D60CCC8F98FF007C67BDE6DE03EC0C1C09DBD4FE636F1A7AFC8FE583BDFF00BBD3F883813B7A9FCC705606D7F97E18D173096657A7F1070276F5309DC5EF3D2E768F86FF00BDF6C20B5AC10CA6E97F1FB78C1C09DBD4FE6908DC73602FD3F7CBD39DCE1098B5503B3BBB787BFA343E4A10003C21EF563EF96B1A7BCF4DFAFCBD7F71867DE2FF00E461544B4D5C3F5F18C915612B4B0A00A5E07895BF08489B1DC7388F2EA313D96AD3DC4E2B2EC9BF817EBAF421A821C7767BA584001F9B6FCE8E5BCABCD653D638D52D496480C01146540492490F44DC93CA7D4621F058D299D89055F213F292435C92D7F5D7AC43BCA973E519A38A73FF00BA384B00FF002B814A0A3B51E3B8DEC2FECA99AFB41F699475F9952BAC68FC96A13575EFB895772BEEC77E80788A64171B22C48B99118E09F16331C415BCA9EA425D99277236BF4FF10876B73C9383CB664B90532D66529D8D5DAE37F5BB347D2566ACE459464747439486D8A2D3B4EDD232C3490DB4A84A5824348E149BA249E1266E2F3344ECDCB993CB4E05666A5C2D42CC28F7771D4D58E823C2FDA2CCF158DCCA6056215313DE2800E5AA4EE49F7B33F5DF54E6EB8AC696A5292903EA4493BA812E45CEC771CA04473EABD97C0F77317F2808243B01536FAD35DE25B0525326425412028A4540BBDDD869E1CEAF1D4BD4AA79CAD577854E3AEAF8384289B1302C081CC63A2CB97C3502BEA1ECDAD7946B3A62D36253F97DF5BDAD6BC4FF0046E87C974851D46AECDD095D654252BA143838B8080428F0F885ED123716DC6196267E2B153C60A54C5140FF00ACC4D033A40635714A7A43513660209516FEDBD77E5E3466F3AFB5BEBDABAAAB5B8AAA4F0BD2869A04029481C205B6111B798E47172C97279328213DD5989E20EFABD5CDFC9CC399438CBABE635777018FF9B7E628DA8CD5FA6A9A879F052144428F8F88AB6481B9E298117BCDB9DA31F3118390C964324D2CE4793EDE35AB449A0A254B53258B3123EA29A79DB578EC5F62FA169DA655DA1EA767B9A0482ACAA89E07894E5D1C7C2405D9CE1500A4911B5B1C6B3CCD2762710BC2C89C5D4A214A497084ED7209507E8F6D62B3996216569E0511C2EE428B2AA34D18D2C1C72BA5ED4B582AB2A4B752F0352DF185F01E068B51FC901B443638500030395E0EF25906070E129946582054F11E2249A92497275678DF2C96AC4CC1DEFCCEC2D7DA9A7BAB47A7398E70F193736EBBF9C733EA71C070F80424B82E36236A353EACF488A880E6F9CB8024827C455CEC4FEB6FC37B59705824A883D2B60343D6C7AF8411586759D3A4AE144EF107D79DBAFCB16591854A00702D717DB4E9FE5E8456B9A674F447113B9224FDFF00B988E718B3E57864872A0030F1F3DF716A1DA08ABF3CCED7E205666F249BC91B7975361E87168C2E141F9A805399B8F5FC5E1C0B0D22B4AFCDDC528CA8AB7BFCBA1E7BC7C3171CBF0A1D23CDC374EA36FB5E1C457B9CE6AE78BC44133CF9413E9713B47A8BE2E183C325213C4028D6835DFC052DA6F0E694F567AF2AFD6D5B30AC0AAF3270932A3B9B5F793E5B5C6DCBAEE6691204A161A786DF6AECDCE24B0B28299D2C28EE5F99DEFF00E221D99662ABC1379FDFEF97BB0BA789C7FC6AF67D1BE8DB8D1844E61F0A82E05D2CE5ACFB575B797488ABB5CB502788DBD4F9003CAFD473F52E258357B166F5FBBFA44E61B0813C2281CD9BD7F00F8F363AAAC549B9136206DF21E7D37E4230E25EBE1F789B918349BD5FDEFCBEBBD63B5B58A004DF7D89E73F8FBAFB6E71ACE7E17D1EBE9F8898C3E112970430A5BC1B9F2209D22355758A13722D37BF5F311BDFD6D866B24853F2AEFF008689195844BBD850F9FE34DACED76572B172649E7FED37EB1CAD6EB86EB511E3AD0337F1D22570F84492C19C5E9BF93D18E8DF46B7AAD706E4F99BFEEE778DE2791C332A7B519EAFEED5F331232B09562001FDC47E2A3D37F16A76B166209833FEFEF9E7C8FA0084F3ADDE9D29E147B5BAD624B0F87482DD34D6A7ECC2D4840BAC50E7E637FBF7FDDB0CD4585013BEDFC7AFD8B93246C0F8FE77FF00309CD5B9D499EBFBBE1B295C2D4778D3B87A801B4A0E9BC71F5959DC7C0C7E1FBDEF11868A5851F95C0AEA7A7DA36EE696F17FE5A394E6A9A675A6D6990E104C9FED20F4EBEFEB6B1CA56384D6A4100877F3B4389785E22549B25B89CEE5A9E76630B9FCF1B72AEAAA026F4C1A4A4F4E301260F381F08C3196BEED6B06EA2C696B8F56FE443D9B81FF00648201E204A74A01E8F53FC523D2BFA35BB42A9A3ED79DD089528D26B3656E38893C3396D2B8F24F0DFF00A86F1EFDB1E68F8D5FED6265B31EF2CCDA33B120DF61B3B35B91F6DB2CE3C0CB9894022571F78453767A024F87D80F65AA3345BC8A9784FF0025F2D4F203BC2D816E97001F2BE39B766E58972C922843B7A9DFABBD19E9531E75C5E1409CB61AB721EC6C776A421CD1EA7A65B2CD538A692B0141692641226D11249B7A62D2A962600B48D6A0D486A539D397DE22F184482962ED6E56A6B7BD296686CCCF35A814BF5653519790422B090547CF8638F7B46D3D4E24F0321226898872B49A2743B3E9D4B1D0522C790E3A624A4034357B7997B5AA0F8C50FDA2F679A635E64EF506A0A269E67BB7050D52920AC29625644026CA20448C5D7018B9D2672552C711769D29C86164D5E828FB73D23B6F67F305B25894B70B58B9E7F4FB3B478BDDB876059AF66B9B55D6E5090F644E38B500784008DC40512AE768131E713D0B0B39D20A4B12016726BB5437D368EA981C72D68055FB8332874D68E695AFDC47565F0E25454567854480DFF6116313D4CED874B2EC742EDE7FE2260CC33D22E08A13BFAF43FCC2793D4FC4E348D7BBE7E9FCC127A9F89C10777CFD3F9824F53F13820EEF9FA7F31CF12873FC7EFC11B253C2F577F7BC1C6AEBF21F9608DA3636A55EFD3A79E0823671ABAFC87E58208E0ACC1936E76FC8608212AD66E67D07EFCBF7CB092EE3A7BF6FFC9089D5ED373CC7B87945B084CD3C7ED0F93FB4468EF0F41FA7EF9FCB0CE1697AF87DE32EF9A292D287F39653DD1BEC3EDFA0E107F330061EC99A65C998016241A72A8FE3A9E6625B0D2C2A5AA81D85478B136D5A96FB5BBD8FF65B9C76D1AFF21D01A7C91F5EAA6C344708E26D252E544F14720A1731EF99A066B982B0489F3662F825A41516E4F76E61ACCE763152CDF1A8CB7BC9C5026CD5823859B85835D8D4695B8BD23EA3BB30ECA329F679D0995E89D354CD53E6E9A563F8F54A10038A52909704AA24C82B1E156C6D36C70ECDB1CBED04F5E317F3617888C356DC2785742C4B91AF3F0F35F6DFB5335026C9E3539E20456C5DBC0023C2ECC2346AFCD29DC5B6DE5CB3F554A54AABB93C4B899337FB5C5E5E800C5A3B35844210AF943900696736AD1ABE768E13865FEB71A56AD5679EFAFAEF4B168EBBEAFCECB74E16A324F1269CED24920CEFCF99EB8EAB91E1021D40073566F3FB8BDE3A409625E1D054588143BBB303D2E5AE2C6231A474F36E29FCFB3B4F1B490A71B045844C6DE839183169C486366AD2A1270DFF0055640E96777BB8B546B1173C025459C01FB7C3466A8FB08AC35EF69CA0FD665A904D123C14C018080278AC049B89369BF3C59727CA6505214AACD5B152CBD48D2BCE97AB54E911FF0032A610372E0B7E69C9C9D7668EB56679C3150B5666FD4AF89B51286A1504A8909E703CCC6F36C741C3E01329085B86E9771B796AF1278595354A1292975173C2E03B03F40C6CE79C5F9D88F6655FAFAA9DD5FA9804E89CA54D3956490429464538213FCC82F2520900FB86397FC46CF93972A4E0A59271789E21264DB88062B3C4681857573477A95F1330A2539D010B5731403F9E51716BCD5AE53D4AE9A8DB0CE5D4AD7759751A2020B696F84ACC40160177124C9DE71CEB08927854A24CC51F994CC5CD5BC2D7D3668A8E2141732D47A5F91B73B56DE71D1BD55AADEA9CC2B180F29D430A90E99F171924A6F061311E62F18BE64E966A1040AF31E5E0E6D5A6F7EECF6010532A610FC676B358D29F4B47CB3E3F3111F6BE0C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C1041820830411FFD9, '1', '2021-10-06 01:15:26', '1', '2021-10-06 01:15:26', b'0', 0); -INSERT INTO `inf_file` VALUES ('26193c15-afd3-469d-b55d-eb1aaa2a4b63', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010305010101000000000000000000000304050206070809010A0BFFC400431000010302030603060406020104020203010203110004052131060712415161137181082291A1B1F01432C1D109152342E1F13352620A172472164325345392E2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004311000102040306040602010303010803010102110003213104415105126171819106A1B1F0071322C1D1E132F114234252081562161833437292A2B2D224258234FFDA000C03010002110311003F00FBF8A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A0AC4C7CF97DFD89ACEE920903F71909243FB3CA2953A948260E5AE5FEFEFD29962312647F261DADAB54FBB46C10A2D60FA966E70826F595BA5941E25A7FE44A4825BE9C63513CA69A276A214A097A9E03D63265A85DBDF46841EC5AD187C5BBCE0696AFCA56A0904F2039FCAA524AC4D018D5BEDC3CFD886932709658834BD0F0E56F3CA1E22E10B820183A1EBF4CB9CD6B326196A29A1B6B623B74F38525AC2D20DB510B05054C4E5D684CC2A6602BAFF71BC7B4A07CD9F841149580633FBF5ACC11E832268823DA20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20840820C73A5029934B8D789F7DA140A64711AF13F87ED142BF29F4FA8A6D88C289E0920391507D9F66D0D558B097A0245BCA9D7FA363108D34DDAE2172E38BE137E13C0A0608F084104E5F43A193CEABD8AC18C3106D7A5E95AE76A59BCA1791395398105EC3ADBD39DB268B6B10C5F0D18A0C3577187A9E42B5B958372743EEF3D2069A4803AB0FFBC8C2AF777C066624B736FEDA9A44C4BD90B9D2BE7192B552C843AB3A97D1C7F717BDB3ADBC96D6D2925053970E900465CEA6F0B8A18B97F31DC9624FBCB4F60464E90642CA14929539704311C0F9FEA1FB7CFD3F5A9295FEDEBF784614A710422BFCC7D3E828821447E51EBF53441155104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104450C4D92F5D301B70BD6DC3C400FCFC63FF00D79E70067D09F4A6EB9E106B400E7C75F6348C33B8F21786AEE2AD254C254D3E90EA5D5AD6A4C2184B492A25E3FDA08120FE99D64ED09094B93500D33A3F0B521AAB05316680B121FBD3D8EC0C72B7DBCFF894EE97D96762F197705DA5C2369F6F9E6D6CDA6016578C5E5DE18F825B3F8AB54AC38CF1485A6332248D0D5476EED793F2D5BAB4835A3874E7EFFF00F422DDB1360CE99392152D6427759C12921BCDBD75AC7CA1ED6FF11EF696DBEDE6E03B7F6FB718AE0F64E634D1B8C0ECB11BB61B72DDEBB69086C5B85907FA440209233D2B8BEDADBCBF9A425550A167CCB3B50F6341D23B76C5D8084491BF2C01B85BE90D6ABBEB6BF4AC7DC57B266DF5CEF13721B0DB518825F17B89618D2DF55C4F88A5A5B6D2A528992789526739EDCBAF783710711B2E5AD4492522A79F1F7E51C6FC6385186DAF3D2121292430019837A46CFA7DD05474807EFE357795FEDEBF78A94548585A428640F5A710426BFCC7D3E828821447E51EBF5344115510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510478639C7AD10422B70699F61F0D47D34F5A208B57157D9B3B945F38EA6D8B48756950570B2E808952AE4999091F97A647ACC06D3C4090824E8FA3D2D7E1A1830A37E72505FEA2DCE9AF5F58F9FBFE279FC5A30ADC058E31BB6DCF5FDA6D46F5F1369CB0BDB5B3713796D84A5E4F85E2145BAC3CCAC5BB8A5C990148988CEB96EDCF150C2EF8DF096041AD9BFE35B1CFBB88EBDE16F09AB1CA4FCC969992BE9282DBCAADDFAB335358F90FC671FDA5DB2DACC7769F6E318BDDA5C5F137957CEDC5F3EBBB603AF953A5A42DC3C50C9596C24C70F0C72AE57B43C6431130A44C24926E4BF06A7E7817AC76FD9FE071225A54248140C426D9E94F3E2F0CF67F1042F1861576C16BC2C4B0F36E1A4F0A045D37A13D3224E7998D6A2D13978D58512540A852F73E5435F661C6230A9C0A199B752ABB0A80457F0D7B47E871FC3C2E9CBCF65BDD95C3AA2B5AB0F70499984A9B09D73FCB15E96F044BF97B265A48AEE8A9CDC9FD7947977C6F33E6ED89AA77049E548DF55FFC47FF00A8FD2AF72BFDBD7EF14C8A58FF00893F7D29C4102FF31F4FA0A208511F947AFD4D10455441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041A510435372388A40CBA99E5AFDFCEB2C7431B896A29DE0CD5A674E9F78592E020120FA7FBADB715C3BC25315F2802ACFD9ED0C9CBC487FC208717EE9515244A13099827404C7DC56E656EA0294E1DFAF271EFAC371880A56EA475D3FA7F53A3C4BB8AB49B755CA92E04A78CF01FCEA4B73C4B039848127A0A693268403C01BE747A7EE91252A42A6B338720727B3DEF46FC47CEE7F186FE29985EE1F652F3747BA1C4DAC4B79BB4E872D1D5DB3C975FC1036471F096161EB75B8CA95196640EE6B967893C4F2113D7841FC88604B642ADF97D6863A6787BE1A6D0C74B4ED10A1F2CEEA9206F6B906D0E5FA3F1FB79B578EED16358A6D56D05DBF7FB538A381FC4F16C61C5BB8A153C494A1A7D5EFF00080A28009FC99682B89788F0D89C7854C94A2CADE2E496725D8B06D341DCC77FF0A6CC97B1CCA4CF4A545346AE547660DCB3B0E1157CEBADB8943CF5C34C13C43F0AA8599CC95F2CC991D672D6B96AF63E3913C952D4C55A9B5333F961C834761978FC0CCC37D284856E8029C297E35CF389AB3C66D117B84E1B609E2BCBABDB4E07AFA080A6EE1B27888CE55FDBD7A9AE89E1DC0ACFCB4AC97053C474ED5766CE398F8A12662672A596A1208003D3FB7AE75A47E875FC353F1AAF643DD5BD7E86D1706C6E38C36084C071213139990273AF50785E42A5E025A5A8406F795ECDC9DE3C83E2C27FEE73526E925CDEF6F4CBAB1BF41B8C2D05398311DAADB2D2433E4F5AB574EF1578ADA494A003DE96820520924E5F63CA8822B488007DEB4411ED104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104332D00B2A264F41A67FE32FB9A0162595D1F4E1EB0AA57BA8AB801DD850D4F7EBCA14CB4F80A5C6A73F21A7BE4E5A23713382CEE876163D7D3BFE60B124DC36DB82DE42AE20054E69232D46920FCE75D50C4CFDC40054ECEC1C503D7FAE1CA16C061FE6A9DA97E4C4971CEBDC0A67CC3FE259EDBFB39EC5FB88C6714BEBFB556DCE2B66FDBECAE1FE2A3F1172E3A54C5CA92D1525D596D2EA55EE194EB19556F1B8D4A50BDE57D441662E406B1A38EBE917DD8FB24E2D7266CB42BE56F0F98141C100B0619E649D4F38F811DB3DE2E2FBE2DBEC477BBB68E5F5D6D0E23777772117854E5BB69714E78296C392B03C352444E59655E7BF124D3336B29408A28B9CD9B2CA9991C4C7AA7C307FC4D8E996DBA4245281FA50E5EE8F67DC630E3D69885E5DB1174EA901808465EE2B8444E7F9634FAE74D14BDE90D9B503BB8EB763566E8F1954F06728D2F5BFE9F2F530861F8C9BC69CFC69875AE1E20AD424E49CBEF43553C6319A684107D8D732EF607AC5870B3C26592AB1029ADC55B5C9BEEF10B6F77737FB71B3563624A9C7F6870461A08CCF0BB88DAB6E4013970A8CC0F955B3C3E80A2839EF0E771DB8F7CA29FE22DA0942561CD942EFADEE1BB3F08FD407D92F6311B15B82DDC60086FC216FB3D873E5311EF5D59DBBEA310352A24F53CEBD29E1D4B602506144E5EC97F2C8671E50F13CEF9DB5710B705D43EEFC3311B3496C01CC7C8F79CBE1FA54FC57615A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821B3AB4A544150062403E5590905CD011E777E30DA62941C55893AD2A1BF5E50D9B7D2B497152809FEE5E49CF2CB49C87AD68A9852145C80900DE9C857B3422941597DDBDC900F9FEF9B461DDF76F3F04DD76C3E2FB658EE256B8761183E1F7777757172EA5A014CB2E38DA10A5909E35A90123AA8819CD56B68E37702885391966391F7CE2E7E1ED9E274EFA9255660D4AE4DD6DC5A3F385FE203EDABB55EDABED378B6338BE2574ADD8ECF623776FB0586B8EAFDF2CF131882AE995294C90B7590A64B5A82273AA06D0DACC6602B2581B9D41AD4F1AC776F0FEC69625A1210024350240BD4F0ADAD6F3D78731F17984B16E2C98B661B9485787C172424812AD358907A6715C7F6A6304DDA0B50373AB82E38687DB978E8F2D230F204A14614E1E61EE1B90E062C2C57690DBBA96D0C85DAA3881E24CAC98911CB23CE3E4269D024CABB535A6B6EB6CDEF586292A54F05A84E560F62C5BF3E916A0C4EEAED38A5DB07C312C809320E796401CBEE2273AE624154FB9626CFDEBE6F67D4889C4EF26428D430A87CEAFFDE71B1BEC8BB0979BC6F68FDD0ECC23C172E6FF001D6AE5697412829B2B862E3300124808300E522AF5E1B96EA41A0A8E6DEF8DAED1CA7C598B32BE692A20310CE6F4635E55E01F48FD46377F689C3B63F666C4A63F0B816156F0065C4CD85BB6AC8F29498AF456C30D8443061BA18767C838F7C4F9DF69ACCCC5CC59B93F97F26CFA45EE1415313975A9B88E8F68820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20886C47F0E9429D5BA50BE24C4A8246640239CD658B3B75E7EEB5F36704952C92029B32C481D7DB72A431C582DF612CDB381B6D0DA9C7DCE284A5284859248D321399023946551F8A5A82083762E03B3694CC8E76D042D2A484946F060E03666B4E6072CFA47C5B7FEA1FF00E2238D31B43B3FECA7BAAC7949FC4A710636E6F70FB950FC280843F68875C657EE789EF27FA91331D6681B6311F4AD5BEDB8F404125EED99E3766D0C749F0EE1C26624A430514F61A7A91CF4A7CB7EEEB0DBA432B6F197495DA3AA7B0DB85A8F1DCA9F70BB7478D43DFCCE64684E7CCD722DAFB40852F749CDC3DA829AE7C63D01B064A44A416B80030D296D5EC7D488C8D7D8C97EE5618052D70A5000D3DD10743A4899D0CCE46A80B9E6662F7AE5C0B335684D1BA718B1CF91BD4614A583D2A75FCF786A2D9BBA1FD4D79CFA4E7DC8D0E43B0CEAC7296AF9391A0D2BC3F6D5A7186987C2EF4C14203DEC0D4F98D3EF148B06ED78D981C374A4C003FE9F231E4395474C4EF4D14BDDB2B135AD0FEEB689B9D86DCC39A1B162C6BE753EBC6E3A93FC19B76771BC2F6F3D8252992EE1BB2CF5CB974A20A90D7E22C8A9AE230401C439F38F4E85E1B961E58FA6AC6B7E7C69F78E03E392A499C9245281AF7AF2CDCE7AC7E8C585B29B6B3B46131C2CB0DB690232086C240CBB0AEFFB1C3615219A9CB38E0B8B24CD24B3B914E0D7B5625DBE7E9FAD4BC358528820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A3C41C6524111FDC7435A15805AFAC11E2DD4A412015C65091268F98343FBF79F9410DD37D6E484A95C0B248285101498EA279F2A3E60D0C10BB8F36D23C45AA11CD59401D4924563E60D0DBCFF001C7CA08F5A79A7D01C656971B54C2D06526323047435B82E1E0852B3045256018CFEFD68823CE31D0FCBF7A208B571E6FC4F01A09754A5AB88140948E15030B1D3A538972BE64B52B78242323405C93D843DC24D4A5D0A6B356ACF50E39DB8D738E7DFF115F6C4D9AF637F67FDB4DE063772E1BBBAC1AE2DF03B2B2527F1CF5D38C396C9534DA882A0D3CB42DCE1CD284CF4AAAED9C64BC382F352E410CE32C9AEDCDB5689FD99B3558C50051541B9142E4EEB3D2DAF611F975EF2F7D5B63BEBDE46D36F3F6C7164E218DED5E3776FDD3AEBEB75C66D5178EA6C9BB752C952562DD4843892609C84015CA36EED295B8A295EF1ABB106D50E34CFBF38E95B2B644CC3142D6592902CF60CCFC18FF548CF1B05BB1DF0EDE26CC6C96C06D46D0D9A1294E197383E18FDD372EC078DC2DB0470C9CA0F2CCF4E1FB73C45829626A9588952D52DDC4C50750D031B9B679657E8381DB72B01BA161F75B7788AE763CFB0CA376B63BF8757B536D1DBDB963763B4ACADE1C454FE11789038BDE1242758C8E473CC93A57259BF123032316A48FA994438DD3D4135ABD357789C3E2BC2CD48514EEF16003B379B77D62736B7F8737B57EC6DA1BCB9DD86D2DEA1292A09B2C1EF1C591130014807FD55B303F11F67CF425090D40EE0573A375BD4BF087DB376F613133025050A0F5620B372377E753A18D3DDB3D91DABD8BC66C702DB3C0712D93C5ACD6E26F2D71CB65D93C82B82D8521C1C43887E59D4C413CED9B3F6B49DA0B4992B1BCA228E0BF519B699C5BA662A54DC2AB75988EA0B3963DEFCCDCC7D13FF00E9CDDDBDD5EEFA37D5B697765E1B7828D9DFC05FBE8E1688B861C4385A77A119647D729AEC7E1C401F2E8080CC59CF337A172D5AC79DFC7C903E6BBA9DC84A43A8B3D407AB67A0ABC7DB058A38D86D695A5423549904C09835DCF6497C3279379C701C511F394002189BD0D4E6D1209494CCC671FAD4AC368AA8820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A4AC0319FDFAD10479C63A1F97EF4410718E87E5FBD1041C63A1F97EF44115032268823DA20828820A20828820A20828820A20828820A20860F2149716EBAFF000319402A80206797CE9057F23CFDF7BC11666D2EDADBE06C1164D1BD7D2098653E249F4CF4CBEF2C41166E05BCBB7BCBA51C630B7EC9CB8570A1C71A0DA441E104151CA4C41EC2688232C5BC9654B5A85CDA3E029224AA124663A089F97C48224ECDB61A6108B7484340A884A4400493390CB5A591FC4756EF0439ADA08457F98FA7D051045344116D62CFDD61C9BABDF716D0485A52A24F021225D24682132673F4A8ADAFB59381C217207D24BE74239E55F3D61EE130FBF346B4E01F2AF0C88EA23E367F8C3EEF77F5FC42FDA8706DC2EEA2EEF2DB775B1572A6315BAB75DCA6C6E5388B4D3AE788B6789A5F84B43807101C24419AF2EF8CFE24CBC0CE9FBD3095249F96970519BEF54D9B22CF7B18E9BB025FC94277F777BFDEAFF713715CD99983F988D9AF63EFE047ECE7B90C1B0FBFDE660ADEF076990CB2F5E5A6256F6D8A61697D438C8436F36160024F1839C8AE05B57E2999C66113882778108564697269525F3F38BD7F9094C94EEAD237B2984351ACE5BB3D63B05B19ECE9B98DDC61CD33B2DBBBD93D9BB665294B16B85E176F68F909802108004981A6624F3135C43C4BE3138A54C57CC7DE2436F56A4F17A5CEBCE23B153C4C56E041537FF1121D2332C6C34F4148CB78761B6966E8559D93F6481012C7861B291119240301433F2D35AA12F18668F9EA2CF5AF0D78039641B3A4252E6808604115078F0A173C34D5A24317167736E59BE65C711C2414AC05020F9E5E5CF2E734BE0FC512B09352952EC46741AD29AF730EF67CE5CB9A3E42D285121EE120D09B7534C985E38F7FC473D89374BBF1DD4EDA6D3B3B38D61BB6384D91BB671CB7B4659B8B95B2953A0AAE024AD45296C2046931AD778F03F8BE4CF99282144311BCE456A2DABD6B9DF9741C16D4C42657C9C42E5B28109DD35B5779ED95ABF7B3FF00F4F9EEA319D90DD0EDC63D8922E16EED0DF8B5B75BE1456EA307BFB8B702559ABDC4011F488AF68782270C6C894A0E4A8249734B86BBFEBCE39478DF1BBF3378A80037C12E1C3D1F5173D6B58FA6FC25C53962CA94C9B739A7C2524A48E131307918915DFF00662372424337D3F88E233CBCD59077812483CEBC35FB448D4942505104144105104144105104144105104144105104144105104144105104144105104144105104144108AFF31F4FA0A208A68820A20828821647E51EBF53441155104144105104144105104144105104144109ADD4B7A83F7FEC51045958D5E3172EBD69E25CA1600109308CFA798FB148ABF91F77AC109605B396885975E6C5C2559C3E0288E7CF2E9DFA56B043EC6B6770BBCB77FC4B0687829E2654CB490E056B918EA069C851046161B6DB43B3B72E30AC3EE6EF0F61442129694B5F082604640E9CBFD10465CD8DDB6B2DA6C383E8B67AC9F6F272D1E4043A0CF240CF3D7BF6AD3E60058127562D5CBBEBEB045EA8B84ADA0E942900980958856B12474E7E559F9BC55EFAC11EA882B81993F2C86BD3E7419841673C6BD7FBB41082EE1A6D6B438A08298CD4400644E46B066D0D5563EEF19170FAC6B27B4DEF217BBFDDE6337B68BF1B14BE43769855B33EF3CE1BA5FE1DD52500F11084B9C448D0024E715C8FC7BB653230D3D1F308514AB76BFC6878E7DB57AC59F64618CD505252C10DF31EE4AACC1ABAD79651AAFB8ADD4586CBECB8C7EE6DED95B7D8FAD7758962A1224B6EBAA759487A3C42B6D973848568A112057CEFF89BB7277CE9FBB354594AA856A5D99F8E94B333C5FF00012CA081421830565A1F4A371E7B09636C6C4ADB45D5CBE98042DE5F12CAB55051FF00A857E5E511E47CF3376B6297356D316CFAB539D5B36F3AC4F7D6A4212B4CB3BAE086A0193529D33AC797AAC42ED4DA0A2CF810A9F1784F8E04823DECF3FBD29862264F9A1D44DEAD7BE7C6FE56B0D44909720A9943F893F4B8B3701A449B988ADBF75B425C504A4788E895929039F6323F5A55789F978420ACB806A491E76A0E19650C66CA284155537648A015CBC9F9B690DBF1A5FF0076EADD95248E4993DB5E9DC4F5E75CD7696D5988C428254582C3E6CE79B71FCC35953D52D745117A83DFEFEEF8A37C96F60FEEFB1F6EE2D9B364E5B969D4292381497429052444199C875AED1F0C36B4F9B8BC3A43B1525EFADF4EE474CAC92316A423E62D64A88A026D4AF916D3A45C3EC57B23826C66E3367ED365F09B5C3106EB1277FA4C21A5A94F5FB8E294BE0E64A8C1EE3AD7D51F84A93370787047D44249241E3566E57E4358E61E2A9E664C9CA2B5105BE924103CF37A664C6F95AF1F80DF88657C2388832248072F8D7A525A021200D07908E7A15BCFC0FBE5CA1C5291B414410510414410510414410510414410510414410510414410510414410510414410510414410510422BFCC7D3E944114FBBFF0064FCFF006A208A8249008220FDF4A208F780F51F3FDA88214488007DEB4411ED1041441051041441051041441051047848027E5D688222DF773E7EA72E5AE7F64FC48220578797AE4BFC392C8CCEA741E7AD22AFE4608B86C5AF0841CBAFC3B9ED5AC10929775F89B801014C80380998329CE3B7DE74410CADAD6C9DF1BF1366CA8CC9E3427424E79F59E9441186DD79EC1F780EB966DF87875C2D03C240842211072190939F39FAB259AB07073228FEFF0030466C2E2AE5F6024FF4D29E254130AE2483D391F856AE753DCC10A5C5C1B40FBEA9E11C013AF3CBEFEE300AB3513C6D04446216CEDFAEDDC4ACB49852DD5494C2520193D3219498AC2D442165CD12A373A18C8B86BB86E71CE5DE862973BC6DFEFF00212E7E236536023F1E12A2AB77DCBFB70A678A4F028A1D1CF307A9915E2DF8C1E334ECEDA33F0666B315021F813DC7987E71D4FC39840BC1A5652904E6CD6377A0F74BC66FB36DBB4C2587D88E06F8901034080AE14E404649033E990EDE20F16EDC4ED09B30EF05051373435B8C87DEF16642129510033588018937ADE95EDC22590A0E202D26028498D67CFF00DD51654B0BFA88CCDC31CFAD72D1ABA43C4AC001EA78DBAF0D0BFDD839289199E83D358E5D3AF5A6D8C9D2E425449A797E32CB9D32541053BB40C439D1CE5C7335147610D56E24B9075E632EFF007DF99CCD57B158EDF96B093420D34D2D5F778D9787DE946809AD49176F74E59BC535503825E2A7B004EF2AE7526A0B7E7ED158992CA66804B549616EADEF84620F68571D4EE9F1566D64DD5CDDE1AD3694FE6295DEB685E999C952794666BD1FF0AB602D38AC3929FF00720B805AE3D7EE7A494B5A84BC8848BF3D03E9D78D236AF725B3AD6CE6C060384840496ED10EA931C2429E4A5D5748F789CFE35F55BE1360BE460E43803E8431B56DC78646B58E6FE235154D9ADFC722F4F747AF2CA33D5BBA3C24F1647A65CB21CFA0AEF4A67A5987A7BE778A6243121C1E5D6FFDD216F151D7E63F7AD6378AC104023434411ED104144105104144105104144105104144105104144105104144105104505694983AFA7EF4411E78A8EBF31FBD1041E2A3AFCC7EF441078A8EBF31FBD1045054D289F7E09E522474D3CA882105DBA97F957944E4743CBEF9E74410E59429B6D295192264D1042B44105104144105104144105104144105104144109389242BDE0001CCE9FB4D1045B57B74865478B88C4CC73FF1209F5D288225B0E75B7ED1B7384E723319E47BFC7D6932824921BDFEE32013610B2D694C8022798EC7B47C72ED4990C723CA164CA0AAD85BAB642FDCF78667124A16EB5C6DFF004C0993EF264492AEDDB23DE88DFE466DD03EB9790C83968B3711DACB1C39C2D2EEED9F79F3C286587029D0498F7933AC91F5A23030E4BBB86E5EDF87E229C130379EC42EB13C490DA997FC35DA367FE46C47BC5615A7148E1035ED35ACDC12B70AF79AD406A59DDFECDC21BCC1F2D401B17E3EF236B18BEC2036DF0B412956504F200E9941D341A77E906711FEB7C904EFBB1739F063EB0A84A481561A8F67B656A44462D78D7862DDC9487149F7E3DD94107CF5C865AE50273B1E1B63CD9F2FE605BB07202AB5C855B8D78F08748C0AE60DE410DA532D6F56EFA462FDEFEF230DDDFEC5E278D5E5C22D12AB376DED7C4586C97DE41619E19227FAAA4E633CFCAA8FE2ADB523C3B266AA7AFF008CB5B82A1FF13C5A8C73CB38525ECE5CC514A6AA494BEE976E63D75EEFA05B91B0C75DD9DBCC5B1C478DB41B497770FE2D7484AD41DB745CB8BC3F816A1C4A86149078B2E432815F24FE39F8E93B43C518932261DDDF50001D2F47A5ADEC760F0F608CBC000A71F4FF00B8D0737A57FB8D87B5BFF0D3FCB1E65E408010B526100E5993CB3CE73E95E795ED799356E54482753AB96E678826260E11EA92E03B101FB51DCE629F68B92D0165A4B4B3C4A124A939A7324C4E50454B48DAA809DD20BB5E8C7F5EB09893AB5CDC90694AB7AFE21DA4CE71A9CBBE83EB95426D19D3315BC104806C051EF42C076D7ABE486247BF6D10B70EA19B8216415023DD1911F1D7FCF6A811F3503E52F7897E94AB74A7BBBF96B4AA5697BDEEF5E9D876878D02E20B8AFE93600256E7BA8CFBFA67DF49AB16C7C3854E4AA60012487F2B3D9ED71C6ED1058993BD314A4B3E82FA656E1D58C618DE4E3981DCE2182ECE5C62568E8BBBA415B61E49092CBA858E313919194E875CB4F587C3618695370E5D0900A6EC0BFDEF566A5A12FE32D60A4BEE9A0772CEC35A8B746168DD2D9CC5ACAD3F0564CBCD5D7896D6E96FF0EA0B0809653F9A208D07F800CFD0AF00ED5C14991210264BFE2960142EC2FD0DB5E158A26D2C24CC4C954E52552824A89F9819C12599E873CED1909CC52DDB70B706404E4223300F977F9D77594B913E58989C44A0E0382A0EEC38FE69DA2AD2F662948DE4A98126A74761D34E70A22FDA5E8950F3F5FDAB55AE52003F3659A904850CBDE709CCC1290F576CEDD6D6E6444A34F23813C326674923BCEB07C865A5335E325A4B0208D41E5D3386AA96A45F26E07D8CCC0AB9099046604F0C67E5AD23331E94644962C067FF00DB6F65A1B99890ADD37E7EF5B3C788BB4A92094A927A1107EFCF3ED5A2768EF16DD20D1DC0CF8D7D2174A0AC021AB50FFD7AC565FF00FA89F3CBE84D4A4A0A58DE2CC6DEC0F7D9F3F2D4ED4ADAB4E5CFFABC79E39FFA8F89A5770EA3CFF119F92BE1DE2B4BB2341E99451B8751E7F88D770F0F7D2140A07B1FBD3AD6A43163946A43163945548AD6524D0306E756E3188A0AC0EA7CBFDD227120121879FEE0838C743F2FDEB231209018579C1092AE1093041FBFF34F512D6B48506AF4848CC67666E37F231EFE21249804C7435932D42EC1F9FE23433C26EDCF2FFF002848DE278CA122549891CC489F877A426A8CB2D4347A024D9CE7FBBD28635389A80002F9BFE3D87EB09AF1065B5842D412546005644F909FD67E94C958F4255BAA0D56AD3ADF8C60E2802C401DFB33C7AE2D2525D198ED9CE5AEA7FC548C9DD9A84ADE8A7A8346F7C6F02A7ADDC27E9362DDF87115ADA1AFE2D80095389491FDA489F818A658BC6C9C3024AD34A9721DBDF0D03830E657CC9A5820BD1A9ADBFBB738B4368F78BB23B24C2EEB68F19B1C1ED500A8DCDFDC22DD8000CC95ACE83E755D9FE2BC2C956EA88E7A51DCFBCE26B0DB1717894BA10A3C0073D83FAE91A6BBD8FE257ECB5BA7656E621BC1C171E75BE20BB3C0713B3B9B90A4EA0A14AD7B76A64BF1C60104825D9EA18DBF7C62CF80F87DB631D284C4A02378D1330282868E32D7567D239FBB45FC797D98ED31FBD6AD30ADB7B9B7B72800DBB366B4AF2FED21C00F383A66075A8099F14B672715FE36ED49005BAE74EB6E313137E16ED3C3E1FE74E22953BBBCDAE9D39C7537D943DAB3653DA8F77184EF2F636C318B3C1B17F185B5BE2CDB68BB3E03A5959525B5149F7812209C88E8455EB656DC95B51095CAA6F65C3D7AE6C639FED4D953366A9495D4A0B1777ED973D637090EF124129209131D3E3156058280F43C8F2E1C620D13378B311A93D721CA2AE31D0FCBF7A13F53366FE4FF0088557F43BE515020891410D431AA54141C47B446D051041441051041441051041441142E214329313D4FEBA510441DD61FE31396B3A67F5FBE7144116EDC58E2ED38A45BBFE1B00FBA9E25089CCCC69D75FA524B51721E9EEFEF9DA1E61D28287500E4E6389F7588F5D9ED01822E675CF8D47D7335A43A094E4057AFAFB31430E5C38DDED93E034FA1290BBB57BA973881885E731FBF9D101166715CBFA3D85333990D706D8FC2BDDBEB809BABB0A2A4B8785680AE23A1226040D3A40E704614486622D576F6E7215B68F1925A49084050485240108D0002123E1197A695AE331625C929CCD88E4D41C751DA18CD413535009B8F3F261AF011497614467AFA76EBEB1FE6AA5225AE662F780533DCD337FA587BB57368AC48954CC137F74A9A30A5E18E236D6D76DF84B212E6AD9D0A888309D27400E7CE3A55F25E32660A56F95B0082F91A248CFC9F4E912180C7294A00541B8CDB3CCB665EA0718E597B6FBB8CEF0369B61B73F845CB96CFE2578B7AE54CAD4996EC1D6AEA1C89905082065067400D78CFE37F8C4A7FC994164B058A13620F117BBD0718E9BB0F65CA9F2862124013189529A841D73FBD3AE68C1997B05B7B2B266D90CDADAD95A5B97B87852A71A61B69C515692541473CABE5CF8C14ADA3B5E762007056A2146B43E77A791D22FF00224A30F2848241DD01F7454BD6A1D988E2ED17336DA5E22E3C443EB4E7C2D90A333066333D32CE67CAAB08D9EA2E40A92CCDCAD46EFC808C198949284A4A121C1DEE232F4EBAC4DDBCBCDA5650A6C1905247BC08CB31F4CCCF5A7A8C1AA8198B54E8F95B8356D0D17300A3D4E6FF007FEB38916DAFFAC18D32FD33F5FF0074E656CF35A10491522CFE8D5E5943698BDEFF00711A9B69FD311C231A6F0F0ADA2C5ECD769B397D84D95E70C071E756DDD024E454532476CF41CB28901B004C4098CE74B922D50DEEA79624CC095AC12B3BCC5CD5218656E02B7C8EB801BDC96F571869C631BDBCC5ED5974903F95624F200049309E21D08E5CA9038656115BCCDBACC2D6ADBCBED1BAD6925560750CF4008E397DE2DC77D8FF000A7AF6CEEEEF6EB789738C30B5AFC7388A576FC64CA4A5447140F9721573D81E2B56CD5A1456A1BA430701BCF26A1E1A1AC7CC595294459C5412E4B74D2FECE44C1F731BCDD97BD373856DF628B602006138B624F129012520980069198CF5EF5DCB60FC619D8308099EB1BBA28F0E34F40618CF4A672548504AD2F621C3F1D4E5700DE2FDC3B6977D9B1CD2157ED5BED132C294A5DD3097EE94F02660AC91309CBB1CB4ABCC8FFA81DA4852509C5CD01C0AACB3578E435111337092C277004A5811BA96043BD59BF558C93B37ED2EC17136DB4BB3D88583A212A58B50D3614041CD674CE672EF5D0B617C73C562952D33F124A54D5DE27CCAABA1CF38839FB28B1DC52C924B6F3B6B4D2FAE7D6335601BD0D8DC7941FB6C79AB37DC88B4B9B94204CE49080499EBD08EE4D773F0F7C42C163928F99392EA6FE4A0D5B9A97B674BE510D88C0CD4072016D3F96879F6ABF01191BC67EF5B4B8976DD76CE094BF6EA2551CD5C432939673E75D7765EDAD91884A54B992882D5DE490F9558F971A8688C560D2545D2CACF7A84B016CE8C5BD6CF5B6E069210DBA5D4670E2D4173D4714C64646556F9123093A5A66A11294156290922F46A3380CED9C2C896508B330ADC96FC5AD9C48B6E92331946503AFAC79D23895A70E92D714DD1DA83DDE82125ACB543317E3C21D0526341E801FAD468DA254A6097E3EC7BEF0D97308B5341FD7E5BEF5A4A4E994F2FF1A7C3D69F4A9E99A2B43D9E9E46F639776EA9CB0ECAAD3A67D7CEF0BA220693F3D4D616A4A5443B935157E37FECEB0A4B51525D5724FDA2BA44A4ADFF00AE83DF38DE102412634FDB2AD7FC71C3CBFF00D608F2B230E9F607EA086EE708566067CC810329FBEF4BFCEF94022CD4B1AB572311B389DF60F6C8FD87BBC15A1C600F9B5873BD1F58525CBF983EA4D746A5CEA0E82185F3B656ADA5E7DC5214A39F86614A8319CC4C1C8672396B934993D0B503BC1D4ED5CBA16032275A43D95B3D730EE84D732065760CF907A88B3B6AB6DF65765B0F5631B478BE1985E18D214A55C620FA185A40199E224267BEBEA29B4C9725492A2536A03F661EEB4687B2B62CC98BDD32D4496FA98EEE84BF06FEE3955BFDFE30BECABB8BBCC5B0D6B68713DB3C5EC12529B2D9BBAB3BF4F8A50A29496F8C2A01D408CB903542DB3E3093B2E62B0C998A0A4B8A1A6BA81AFA3DA3A36C5F00E37192913552A57C823EA0C77EA28D6F4E85A388DBECFE3CBBECDBBBEBAB7DD3ECF613B3D8195AD2D398EDB3F6D8B96E4F0AB89973878C8CE4643280245738DA9E3D54C27FD4357ABE5C6B9D2F46D6B16AC3FC3D129BFD206B761992DCACDDDDDA39D3B6FED7FED39BF5C5311B8DA3DE66276F86DD70F16096D8B5DA18680490B4B76EB51090A1DF3CA6A8B8CF15AE62C8DF24AAF527EFE4CDCDA2EDB23C1C990A4112D346B8C9EE28FE51AE78DE39676ADDDA71AFC6DFE22B0A3F88BA8778972493C4A20E67BF3CA342C7FEFAB50BDE97AD69E9E51D4B65EC544B4005291BA34A59CF6EFC811185B0E606278AF05B3AB37B8B62D85DA35689325297EF1A60C379900A57396A290C0C85E2F69267392EA15A117EFADC6B5884F154E461A42E582032482006B7E473CB468FD14FF8766E72DF72BECB3BB4C19C6CA2EEDB0D174F248851388F8770272CC8F167EF2F5578370DB9869273600EB517E793B5695BC7913C598BF9B8BC44B3FED53825994F577E047D9AE23A1A93C494ABA807E226AFF882529000A65C6CFE6DECC52B0F55BDCB9278302DE7CFD60041CC5664972068FE6F0E27D52DA8EB710B2343E7FA0AD95FC8F3F4A42328302346FBC57588560A20828820A20828820A2082882122851513208310348A208560741969DA8821A3D6C1C515152B38C81D0F68A457FC8FBFBE9CB942B2E66ED353E5EDF586CAB04ABFB9D1EA63F4CFBD6B0B7CEA30207FFEA9F6880C6F6751895A1B66DE76DD6A20975A5702D4279A867A081D46BD0119130D492492D9E598EDCF8C2D85E088C330F45936FBCE2923375C502B3273CF4D39FA5119F99CDBEF639B5BEF12008B5050AF154948F796BCC99EA7A74E7F5A467618CF0031700B3FE3DF2816A0A41248B331390B505B87DEB152805A4B8D9E21049CE4E43B4F4FBD4AB84C0224A82D4056B517A93C3AF663157C6EF952B75EFA114390A7363722ED68B7AFEE12DADBBEB8712D34C3370E34851E152FC36D456540C03F964768CC542F8A368CAC360E67D607D2A6FA99AE3CECF9D4D6253634A9C54860E094B8625DCB1CB4C9BCAFC45DB7F691D911ED23B53798B0BA7F15C11E6ADF675868A14AE37982D5C00951E3954641199244D7CE8F8C38D9D8A9F88521649758BD0D59A8C19B2B47A5BC298290AC1CB92B037581340E480F9687BE5568CBB84E39BDDDBE71972C1BB6C1B01BA585316F8925E63134B6A5492EA40291C5AA0E85275E55E47C46CE54D9A4A85779553EEAF52D121B5548978829960519D839A00D5152D4BF03C636D763765EFB02C350BC42E7F1576A4F12E1456DF144C0E283049F5035AC4BD937FA43BB00C41E449B0CBCEEF15F9B8A2A59417E2A0EDA70635ED98117AB16AFDC3697941A41512385220009240D27BCF7A7C8D904B7D15F27F2D7422838C3533C2014825441B90E7BBB43D459B89E69D3BCFDFCB4D29C276492A622DC1802296B1E6FCDE105621F3B59957E6FF88A6E703B2B8683A96909BC2656EC09510444919E42227A6B06A625E125CA921012A2B63BD620F07F7D2F088C5CC44C505281416DDB922D723956A5853587B6B87B4D33C0F296A580608323CB965AC79F28A86C5ECD4CEDE0DF5170187BFED9A8F189B899A4FD0CC4DCDDB872D3CE133873438D456E05E5C1044089D3991D79C54327C3938A8B254483F4BDABC72A5A03314A29DD2376CAD6DCB3E6C6D94242DDF7521170195849212482441EB3D80F86752786F0E63A852086B81A5FD321F78DBE9DD26CAE19F3A738F51645B5296979CE1207FF001B8A2D8408C91DF9FC69E0D97324ABFD451749FE24E79F115AB7A65A6EA492E91FFCC456B98BDBADE2DCC67671389A148FE578392ACBC47191C7E64C6BDC472EE2A57098F5E09492950013A65DAB95C1343586EAC3862417E7DA8C29EF40D8C712DCEE1D8CAD6CAEFD5835E364290E614E861614731275FDEAD381F8838BC090113961233DE37EED969DEB0CE6E0D2B2494D6AECDE85F864F9E822350FEF4F7560376589BB8FE12DCC26F9E7AE6E3806790100E444E9A4559F0DF1AF6AC8094A71539280400CB56B5CC0E43BC319BB39054E101CEA32BE84B7F6D431943607DA57673137D9C07692CAF301C552AE05DCDF368B6B0796A248F016A32ACC00ACBF3111DFD31E02FF00A81F9B80932313892576FAD7516E24F13DEAF1058BC1A82D4121806B51DF2F57A74A46D2DA6236D72C22E18790EB0B48521E4AB89B5057BC08568723967CF4CEBD0FB07C6B276F041F9A0EFB31DE70FA82E5F87488C9B2181A392E0822BCDAFCC5697687CBC4ADEDDA6D450B794A2470B602940CEA474CB289D0E95D43038144E4158DD60017C8BE64B1D73636BDE21E6A56926967C891CBD3BD9E1F255C680E04A803FDA47BC34D47DFC6955484CA528A4BB1CAC4559BBDA90C26129C8F4BBBD843A654481FF975D79C5472D6EB22AE0DC9B30CBB7087D20BCB079FDA14592001D67EFF004A7A9237732D702F5261588EB8BC0C29280CBAE951CFC34C84CF33F7D69CA64EF237F7D22B626A5DEDC9ABFAAE5AD6AF71CE2BB8B945BB5E32C1298931A8F3F2CE7A4674829494920A998B7AFE3DD1F1112DE356F72B73C169D5A1A897801C19CFF74F633D0014B8952E6A77C9497147A9A3BF2F4F386C70AA98A4B7FB89B7DF367E50C76876B304D9AC02F369318C42DAC308B0656F5D5E5C3A96D96508924ADC3EEA6025524FC63484C7997252A5EF064BB817BD1AAC28EE747B9896C1E109989941277CEB6D79E8DA18E0A7B647F1CEF672DCD59639836EF71DC376DF6B6C92F31F87B4B9B5C46D9BB8014801286DC0B052A1EF4E7293A72A26D3DBF2F0FBDBA40A666CC2E3D0E61FBDE3666C45AD43E67D24336E50915BE7406C3A068F93CF690FE27DED2DED3D8CE22FBDB71896CA6CB3AEB9E1E0985E217564A530A51848B7E2289E18303204F3CEA958CF1B1438334B00400154CF5E83BC5E70BB092129FA0BB8A33E62BC41D7D19E352F655AC731FC4978B5C620ABB2FAB897738B3CA73117540FBE5F5E739E692732233E75CAF6FED39FB4710A9A851AB9727D2B5E14A748EDFE1CC148938044B28E7415E56B1E3EB4CDE19526DA54DD895369F79C00F1E594827B0FBE74E9F2F12A7FA946A6AEFEC657CF8C4E2A4E140277464C186B5CFDD1A14C3F6999B26CA584DB32FE61C7D43856E6A004A844C4C08EDD2929180C44D58241041CDF3CE95EC38E51A7CF91203A4806BCCB52C33AE6D912F18537938DCADEC41CBCC482585202DA65CCD7C6A480509332003249D055830BB1672EAAE14A6BD73CB8D5E31FF7C932412E2C74A30CEB95697A56CD1D0DFE14FECC175ED3FBFCC3EE2DEDAE2F3677642F70FBCC5D7768E34BC55C0FB019500524A16DFBFC530418ED7CF0F6C55267CB74BD45817A5DB8654D699C722F1A6DE42BE6913004905892181A80E6CD501AEF5CA3F431D9BB0B7C1306C2B08B56C2AC6DAC2CAD136CD2415B26D5869A1EE400904A24EA20798AF49F8730624C8410186EB579598F1F5B078F2FEDCC519939656A054544BA5D98BEEB74A3BDB52232234A3E1254A82607E5F8019F3EB53D8B6000E7EA3F0623F0409054482C00A5AAEDE5F8E752223D73AD30EFBC092F42DFDFB6873882C87F7710E11A1F3FD052CAFE479FAD611945C13AB7DE2BAC42B0510414410510414410510414410510414410520A0CA3EF8FDE082B10422AFCC7EF9511973A9EF14D106F1D4F7860DF8CAB8BA4BE10AB684F8204951CA4F148826748F2E735A9C5A650751B02CEE7EF4E7A16778C09BBC580AE84063EEC6A6F9443629B4786601875DDF62453656B6E852CADD86D30013CFDDE5CCF6D74AE6D7F1548C14A51DE09DD06AFA5433177763D69430FB0FB3158B50F9680ADE672059B57CCD581E2F1CDFDE56FCB787BC1C6F12D9DDCD5ADB5CD98E3B5BDC5313438BB669B7125B51C35E6090161255C53202C0D6BCD7E36F89328A66CB137250A9B5C3DF507A3F38B860362FF008DB8A5218674B659B50DC509AE9168EEABD92F6236318BDDB2DA2B21B57B758E3CDBF7CFED0A1ABDFC1BC1D24FF2F2A4F88D8014A8933091E9E5CF106D795B5A6AD5BDBEE54595506E0E64D281B325A2ED85DA3FE1CB32FE61960060A0A62E1A879E7964CF1B9B63B1D86E1B6ACB8C3447B89290E2471A724FBA3A246881D001CEB9D62B664B52F7D018073614CAA3EEF4E108AB6B4DC54D50984153B1527302C78DB8005DC9891B64F128B440E10787CA63491A7AD272F67241FE2031B8041200E55E34EC0C6AB98A0EA2C5DCDC9E1C3BF9522585B86FDC48303CB9E7AE9F3A792F673D5A8C031D682DD1BF30C264E5283871AB0A9B0B547BEE785D95F0FF0014ED1B2C33EEB16CC1AF260DD4F7D10F9A599D479B7A8CA3D09E1CB3F5D6994EC0284C6018756BFBB423F3EBE66833D6BEF8C7B4A48D9C1C2D6064F47BD6AFAE5C7BC3844DDE00062D71E9D385E8D14139E5F993981C8CC4FCBECD4EC8D9F86491BC9191B015E7D87EACE12A041191BEB476EFCA1322091D3F6A974C9C24B05928A248A00F6CBEF0B82E1EC4E9CCC56940201CF3CBD7A695CBFC452A69C72CE1DFE5BB0DD2D95CF3F57845530A0EED2F753D7367D6A2CF9F5ABC2ECAF87F8A869783C44C0CA4AAA2D56E1771F9B88D7E6162412599EA73D397210C8E0F6C1F55F2DD5071504A240D073CA7A7E9DDEA36229406FA40725BE9E37CB3BB346BF31CB6EA8F162C6D639F56D213B976D5D4969DB64BE902389490A1D33F3D3F4CA96FFD3A08344922D720F4AD9C3F93C6C4004A98BF07E568B2368762764F69EC97677383376D7290A2DE24DB084396EB2642D0F1CD241CE6397A544213B4B66E387C952D3292A0480481A5851E95D7267845782DF3BE405050240CCE7A54B861E4D5318B707B4DE4EEAEF14EE0B8CBDB5FB3A544B96F7AFBB7CE5AB4924F0A12004208048E7A67CABD2BF0F7E224ED9864A67E216D2F75C1516AF33F8FC4362B6703FC5212EE2A08347B7EFD2367776BBE2D99DB05A70D52D16F8C3502E2D5CE04A90E1904044950CC73123E75ED1F097C58C163254A926783BC00502A1C19EAD6627D728ADE3302B1FC523743B8CEB9E56CE8391158CEC16A2DAA0057BA4A38648D32E5F0D632CABB16076A4ADA32C2A52810A17497EB47CFF262066E1EA686DA6432D0713C4F111E58ADCF0506E3DD72552279126358E47965D28988DD9B7725C9D052312D3BA902DC0C3C52D2A882329D48EDDE9FCB4921C0BFB17FB7DE3788F7D01FE34F8A5942735ADB3C2B3D33CF29D7D7AE44E9A99128953BB6593E5EEEEF187AFA9C873310B718B58D95A3A1E778AD5A0A2EDD5C94964093C456BD00027B0EF3548DA9B6C4B593BE46ED6FD43D6B5D736BB53748ABDF22E282A19B9F7BE4CDC7DF6F5FE2F5ECE3EC4D86E202E2FAEB6C36B196969B6D9ED9272D2FCA6E4A6129BEB6E30B0952C8200CE388C659D77FF5FE1E4A861953909995AA94C2E5DFCEE6D5368B56CED96AC44B44C4A014577C815625830B39B13C0B111F15FEDC3FC6A3DA8BDAF710BDC3F0AC7F1DDD06C3DE3AEB565846097379818BDB75A8A529C4184AD4DB9C42240CB356550FB43C609C4AD72E4CC1398FD664AB791517D0EA7AE6C22D5B3F634A97BBF4925FF92C7D4FABF0A7ADA395F84E078DDE622EE33893ABC531ABA597AF2EC294F5ABE552A0E070C2D4B20F12C9D5649E66A83B4F689C5297F2D4ADD36DEFE56620E82EDCFA8BF6CDD9E12120A4134AD08EA7FAD38C648C31FB5FC4A18BF47E19F1C291E100949E44C9CF21F03C8553B1180C5CF5B82ADD7767367D2FEA783C5BB0F864A775EC187D5567B90E07F4C4466CD96B816F72B6997896C04F01E29CF84731D3C8FD625709B2CA640F989753177048F57B171CF361163C2E21725210927746552D7FEE9F78C86E5F3C2D5E01D3F96667E1AC1EFA7956B330528120A6A08CA9D72E17ABD61EAB10B2C9049CCD781E6F4BDDCE6498C4B88E32BB40E3B7971E1B685136E4AA38D45449199CFDECB2F8D2B230B2CCC0C81CC0A3D05B3BD39C44E3A74C092A06CEC3837524FEA31DE39B4F717EB16CB42DFBABC7ED6CEC6D900A94FB974EA18494A355105C4E911CB4AB56170B2804B804532041AFDF2EFC22998EC64E439DE51BBD4B0FEAF957B1FBF2FE04FEC896DB81F662C136DB1FC33836D36C6D85D622A5B205D34D78CA72D64A93E20059746BC87202AFFB0B67A4AD13129B33306BD1B3399A76BC71DF166D19931464A95F4AB789075150D503DF48EEFD95BDBB3C4A67371E990A8CB52223489CF90E935D87038712B0E80C599C96BB0CDA81B839EB1C7F1B89F9B3D8549D7514AFB01CDA25D8694D3010A571112A999D4F144F3A6D8E98CB1734A0FBD876BB44A6046ECB2090E58D0713FAF6F0A224054093965EA6B6C2972391F407EF0A62BF80E7F88748D0F9FE829C29DCB97E36CA1293FC7B7A98AEB585A0A20828820A20828820A20828820A208283404E90426A58989223A18EDA73CF2D4532F9DF327096902B4734F7CCFEA36092438F7EEDFA8A38D3A052893DFA7953B54ADD04BDBDE43DE51A2F7902A070ABF93088C77114A2E0B1E138B331C604A64C6A67BC9903F5AAE62B6D4AC24C3294952C82CFCDDB3CF2BF384C6F28D378F04F36F7ECC2AE5DB698E24AF212A29CF834FCC7ECF6A98D9D306D097BE92CE1C0A7637F6F0BA70EB51DDDE21C3B17B67A03FDDE2DEC5B1FB3C3ADAE31572ED962C2C5B5B972FBEB096CA5292612AD388C10419CFA662A9DE2CC6AF65AD692ADD090A2429B9D5FCBABB185E56CC9BF3A51049269BA5DDBB5732281E39D9B7BBC0DADF687DA0B8D99D8470586C8D83AA6713C56E54B698B86C9215E0BED92DAA0A5691235307531E55F1E7C424C84CE97BE428053170C2F6FC9B9E317DD9721184402A439A1500DBC454D985B36343934664DDE6EC300D8AC0DAC330C75C200972FDA523F10F3AA3C4E9538912A4F19504C9FCA44F39F246DEF16CFDA78B5844C56E952AA0F13C69976062C93B169284FCA4A0518850147A061C5F57A5728C9E30D65B4B4D332EA1325C5BF9BB394709D067DE72CA29FEC3D978AC6292BDF25370E4BD6EFC2B50D4E358AFE2FE6CC7650E0C580CDECF7A1C83EB0ED4DDC7861A4B9C484880567DE8E84F6E5F0EF52F8AD97364CCDC25E81C1BBD6C19A86F0E30A7E5206F01BCEE5FF007EF46786ECD9B8DAB889124C920F3EBA09FF0011148A700C5C8F2ADED63966E4DEA61D2A7053B9150D70C29CF5FCF08921319EB4ED18548CB93DFD0FBE10D94B2682803DA84F33EC426A7529E44CF97EF4B09433096E03F50814A8DC8E4E5BD228E20A923E741C3CA374BF36FC424A9449AEF1E469D29482B53874D40602CD6B743E50B4A0524124B747A0A353D6E1F8414DE648985B74D9E9563A519BD5A1E226240AB5793F23584CA0924E59F9D47CEC1E35544CD2903FF2229470DC7CFAC2E89D2C2402AB727EB0BA084240CCFC2B28C3C84A00C44BDE99A90E686B535F2E1C6194F52A62DC1000E3F703EE62AE31D0FCBF7A5449C2972896906C1C0A33F0A75E9946A14A600914CC67A450596DC254B52E0C6423C8EBCFE548AB0C924EEFF10EDD790A6679E90A198A09A11BC727A0E2457850FEA02C3491FD3409FF00CB9F63CB23CFE1DD33849AFF004EF30E0587DE83EF78513369F536562D6A171DC8E6D10EFD95C5C38A0F381A6103DC4B248F132829781FCC397918D66965E0F0870FBB3100CD62E480E789CDAB6E22F487D2F1084A494BA89762AB26AC4A4D18B1B0CF85DAB9625F49B77382CAD888526C00429D11FF00ED1A2A7B81A9EB3542DA88C5E1967FC75196905C6E929B170E539DB33D2D0D66265B28A54A528D5D4D47B80EEC0BF105DAA5846BD6DF6EFF0013B1C5DCC6F76C9561F8F2B85C78DC4B56F745B0090C168712D5C20F10CFDE396822C7E11F1963F6762A4A66E21659401FA8B1008096CC9D72D6EF11388C2198414335406E3776D0D99B3E117EEE67DA770EBCC753BACDB65BB85EDCB29F089BC29658B85841582C970F88B052019E73CF9FD00F85FF001230F3244846217BCA5000B9A1714BD620315B266B19A94B807EA09FE4C7986A3871F88DCAB3BE57876C8BA520BCFF00190B41FE9848CD3AF2298CF31CE73AF4361F684ADA4533A5325243E42841E26BD74CAB159C4A55266143021E87D5DBD323A3C4938BE00550549001E2198331A7589135609612100EF2599C97146615BF6CEB1B4997F3684B1CF2D5A87F3EA230E6F3B7C5B2BBA7C32E718DA3BD69087504B5685C407AE1491010CA164712B888100EA467A550BC5BE26C26C991314B9A93BA0E632E9A8BC4A61F644D99BA405104DF235BF12CD4EACD6E6E6DB6F5F7E5ED28B7F01DDFE16BD87D81794B6EE318BF62E30EBEB8609502BB47DA25B59D609C80226BC87E34F8E7B3F674C9C962A3501B758F98EED46A71964786310A620B39760F605F95A3125A7F0C1F673C69C462FBC5C2DEDBFDA0716A7AEF10DA466D71271F7D47895C4E3A9E25210A242330427872E9C2B1DF154ED19AAC6C898B421C90016A0241602D6F4A5CC741D8FB31586C3225A92193725EBE55E74FCE16F685FE0B9ECADBE0D9C7ED304D9AB6D95C69B6949B17B0AB4B3B2610B2212A5292D9500204C09E94B6CBF8B0654C08F9AB05446F1DEB9763636A1AF4CA9328F9685329296A1147B54BD28F947C9E7B6CFF000F9DE87B186DE5CE0B7B762EF615E717FCA719B65BAE043613C4A4DD5C1425B1EF282120089D6BB3F87BC6183DA625283998AAAC16297C99ECF9F6033899C16365A5410C2AD6CA8D90FBDED1A02EB88B0B979448BC55B94153AB1C725794A5594C48E233D72E47AE6CE99849884A952D2491A034EA4F5A18B4E16626687B0CDC50F56C88CCD416ADA2ECC27690D9DDAD65695A161247826502139807491306329EB90AD316100ABE52581B5393861CE1D89E25CCE160722E2D5BD74EF172DCEF01BB7B7712B0F12A040800807389CF4FF0476859A852890189CAB53517BFBBE50E918E949014402CF7FC57BB4611DAADA6B9C6826C9A2E361A2B5B4B54849CF8B32390233D2233E54F307B3E6CC50AD1FB1F5AFDDF9C56D1DAD21285380287477ADC5AF9DA3AA7FC1DFD86B6EFDB13DA576371EC730A69EDD76C2DE1BADA2BDB961C55B5F29482E590B470A4B2E16DF6929702A20E99D5CB67F87F1535490154A67F4B1E5996A5F80731CDB6B788B0F21330A81234003F02DA0ED4BC7E93FB01B1D65B21B278760382DA37656F63676F66D5B9406DB422D9B43321090350991020FAD752D8BB25785968DE7269BD5156F2E39FDA38C6DDC71C74F5A83115DD29A5C017D403C8DE2EE4E1A5B750B4A885092449E193398112739CFD7CAEE89E94CB32C83BA02402C09D58EB9FF4E6291330330CD0B05AEF52280B0E41FCF8C4A21B73800594F144652447EFE597D2A33152CCC5BA012D6BF12D5FDB651338649948017FC99A99313CAF7AD7BC7A968A673067EFF7ACC80659FA816B5AB61A429387CC4B0A177ADBCBF10AA41020F5FDA9C13BC49D75ED09CB414062DD3A9FBC55588520A20828820A20828820A20828820A2082B06C73A1A6B04357092A910620C73F874D29B09252AF9C4589ED773A7E381261647F11D7D63DE11911023CB39FF13E5F0A5D33E5CC05233A000F31521EA74E7570F084EDEAB351AEF4B5BEF0D9684A5D04244281E3312721967F4CBD73A85C76C413D66600924D4D3215AD037BAB08DA4122C0F3AB7E351AF1CA20EEAE59B017F7D7AF34D61E96C952D6A00200499CC809198EDE672A8A3B5E46C1428CD584A520D5C0667E79BFA8689297294A28009330FF001EBAF0229F6BC6816DDE37B53BE6DA4BCD8DD8CBA5586C660EF70E23888716DA71343A78D6961D6E5B7BC35052083A695E6AF88BF12E562F1D3A5A673B3815A160455F419F48B860F0DBA8131613F31817D1A819EA1F3F3E394763B63B03D89C359C23006529B27004DF82948B953B3EF28F04020B854A93CB3CEBCAFE2BDA29DA6B9A42C2829F37B917B8E033B7030FC214CE48278753F8148C8ED5A316484DBDB28ADA4E609226559A81390C8935CC8ECCF95882A6DE0083BC03839973D79035B4094A941C8097CB870A690FDBE7E93F7F1E9F3CBA06C4C6A70410924815AD038617FB76D633B8751E7F8852A4F138BFF2166685120B541AE9C1ABEE820DC3A8F3FC414D44D39953F03FB8370EA3CFF108B8E70923E9AF2EF59F9BC55DFF0070141CABEF8C3271D83E5FE34CFE347CDFFE6E35FDF383715C3BDFDF1685DA3C4DA4F6F8E7AD1F37FF009BBFEE0DC5708528F9BC55DFF706E1D479FE20A3E6F1577FDC1B8751E7F8828F9BC55EFAC1B8751E7F88294FF10CE0666EBD9BD34A59E33F2D46CC7BFE20AD0E1021C6E8074A7DC463E5A8E9E7F88A82E0465975EF9F5A6EBFA32A644501F7CA32259259C41E2F74FC7FCD22AC484D013C2B4E8CFDED18F96751EB0D1D77357D807383DF5FA0CE9A2A7059D586AF5E27DFE5D252C18A401714D5DFA8B70866E3A0F383CE35D3CCFE9F3AACED762853598DF3A12FFA6D2B19DC4B73E6F4E74AF0885C55FB8B1B471F48438FDC148C3CAA55E004901DE23FD9C40F2CA35E754A933D3227A565552A1BB57DD635DE177E0F58D0A415802C9BB1707EE465FD574CB7FBB977B6B311B0DE56C95D2F0FDBBD970ABFBD5DAB85A4DE21094B81B940F11CFE8B452412012632D0FA3BE1EF88132848054CC520DAC14053A1F79EDBA4EF02DBA5D801A86AF2BFDF4CA7ECA3ED9580EF81DC4365B1B4230BDACC0128B4C42D710E06431F854A9B2E942945690E2195384919EBA1AF7DF8476DE1BFEC72F10A9B2C112E84A9896B76AD3D9A86D2D8E573153132D4402EC915AB87000635ADE9D1E28DF57B746CDE07B46E6ED776CEB7B59B5C54AB774618A45EB36CEA9328F13C1571A0093AE723C85517C63F1651B2513512E781BBBC1D2AF3BF00F916BDA37C16C73F4AD482294045B982F4EAD666B0C3381EEA76FB7938B33B59BE4BC7EED9B858B8B4D9F4ADD5DB59A490A48FC2BE084710E052A3533E55E57F15FC6156D33364AA7A95BCE03ADF5E3DC5338B461309B80580160010389CB8D73E31B8786E0D6186616C5934A4D859DAB6136D676E435200192DB040CE01CB339EB9D712DA32D1B794B9AB65397AD49AFF006FD2A1844DA48410000F99E7906F74D6B0AA5CF1471F006C49012040001C8C752209EB3355AC561938196A909002402E05B33E67DDE25E52B725303900C59DBF157CBA45550D253B93D243B3827A0E99FE61B2D2E4B8A5DFDE6FEDA39EFF00C4A7D97704F692F672DA8C1C5AB08DA0C3B0DB8BDB1BB0848B91F850BBA7385C82B1286B87DD1A6B3CFBD7823692652A424A9882C43B5A9A9B74C83DA16C0CB22728B9214CDA0028D90ADCF334D7F3D2DA1B16B66715BAC19E654F39657F8A58DDF12415715A3EEB08E2D39B79157975AF56F87B1699F2905C10522CF980DE6743ADDE2EB83514802AC59C727AF95A95B8D71F5962096C9466985AE12A1060A89032D321979CCD58A724A8D29C6CF4D58F935844899617F5172DDBDE66FDA14C4F1305B3067DD33DFD674CBFDCE68230CEA0A22B5BE872A0ABD33E30D27912D0541419BF8E46BA017E59579C3EC5ECD637BC4DB7C1361F044ADEC5F6A313B2B2C25A6B894A2872E1A6AE8F0A7DEF75B70A8C010019D60D8F676155BE9A549C85068F6E428FC294A36D9C7A50140920006FCBEFA77148FD383F8597B1BE13EC77ECE9B05B0C8B060ED462F8622FB687130DA7F101C7D28BC612E3BC216327783DFE4234AE95B2E514A529003D1DF2FD373BD9C57906D6DA2899355F52884BD07F153BBB9CC69CDA3AE167C66DDBF10242C0293C208100C0D7392209E5D2AE5202826B66D69937DF93C5594ADF2540B82491571D21D4099813D79D388D60A20828820A20828820A20828820A20828820A20828820263A9F2D68820A208681242C922049F9CFCFEF9D656DF254FA1EEE47DE164FF0011D7D4C567E3E550924B4D014480E737E3DDBBC22BFA9DB36F2688176E1F55EBD6ADA92D9F7787C6301C912A2D811300E7940F2CEAC7326E1E561D3316A0FB8A26A0E54DE7ECFAE90E64A52900A92E4359F8B3DE8DD41D234AFDA1B6F71CC5F6AF07DD46C4DD326E6E14E8DA4BAE35163096F843ADA6F548CD83728E24B1C63DF30398AF1E7C61F180C11C4A24CE228AA24B53BBFF0064F3B3ECBC3A66A1334A46F1D722096637D3B9CE2736476551B35875AE1F62B0CB366994BAD9097EF1E7614F9BB23FE44870A8B71A24E7CABE7EF883C6B88C4ED25FFAAA037D55735726E5FCE9468B44A9094824951DE1549341C86BC7F4D7BDBDA9171F8D7084BCAC94D23FE088E1E2819F16A74D49CA9CECFDA7FE531592A7D59BAFDC5BB88544B480C09E04D48FB7944BF0210785B2A299C8AE264EBA72074ED560DD9653BC012E1CE84578D630941DD01443825C8170F4F7E50F112013AF413D35CBE039D454FC52A52BE82522CC29AE9A91ED8C6CA4A697D037BE66292F2418827AE83FC7C2A57058B2A940A8DF2068393D89CF3F383743DBCB9D9F9E547F2F3C71FF0053F114F3FCA1A9FF00EA1F98CB0D07610D5E738946011A73CF4E51F7AD63FC9FFC8F71F9BF970818683B0868A4A892441E809F43C88158189FFCBCC77B8F7DE061A0EC21E30785B4854939CC79D60E24E4AF31FB818683B08578C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDEB2312A71F5663307C9AB06E8D076838C743F2FDEADB809C9387493BA685F9F11ECB528C6022C0123967941C63A1F97EF49E216835052189766AF36CEF7FEF0520906CC5E99F384D464935018A9EC0A4101AC469F7AFE348374053F0B69C63CA839B88DDB9AE8F977AFBA5E009038F3860FBC12E2926728CB91CBCFB7DE74CD38B4998C0DC970FC082E01F3B5DCE65D210E12EC4077198734CA9C61929C2A39653AF2F84534C7A3E64B531269C686BAE66F67E758DCCA4BBE438777A57852FE69BC8B552136F745D26F012DAD59A590DE64B44FE52ACE48D4F3E55CE31E172E7024167B8B38201E1957D18423F2C6FB8FF0069B0A9BFFB9BA37DE2DABA4E1D86B57CFADD0E61CCB4BFC5BBC414E94290A1FD654C70415083309ABEF8576A2E4197F591BAC6F6CEE39726B17221432986E9DD0A361CAA47366CC671C32DB0DD66DAEF1FDADF15B9DC762EC6CAECD38FA5ADAAC4F0E7DCB26EF90E5B1427F00F5B8E071C6E5C4BBC792579098AF42E07E2A1C0ECC18233C83BAC06F3573ADF2D39BD225A4E065AA4EF280B5185DEEE286ECC0F6CE3A59B89F642DDFEE52EF15DA0B172EB6A76BF1816EEDE62DB49E15E3EC3C904BAAB67C00E264A9404C9223A5722F1778AB13B5D530A6728EF12CCA26F77AB7A733708CCC2A0252120005DC9A10D5191CEF9F1AD36DF8906D92C3656B0911E33F9BE0F31C407E549C9234E181A571BC527186715EFAF77789724EAE6E5A909A30CA4555BAE1FE94BB372233B9191B3188F71588A53E0B2CD93CD2A789DB9054F0067349D01CE0796719558F666D91839604C249CCE766677B758D172AA9980A86E9A007E93615705EBC7F6DD09FC3FF4497164192B3EF66ACE275806009E5E54DF17B4938CC4BA4BA4F4FB56BDE967021D4B5A94002430CB53FAAF46BBC2C0CCE4479D26A414B4C71676177A9AB5A1DCB4B800B91C74C872A7E22036A70D6B1EC1311C34AD4D97309C52D9C4A8C21C17166F37A664E4A8F3D62AD1E1CDB22462A5277C065005CD4641B9F57ED0FA56F61953269495209484253553D89577E62968FCE1FDBFF76D71B9BF68BDE16CFB1641AB45627717569E2B640578CA76E1D288024CAA7202799EBEC8F877B4062E549ABB800BB31CDD9F9FE22C52567752A0E1C02791AE5A3E59BC73C6C31238978778AE161370B7810A3C21AF09453EF8D13C6734C6B945762992525767A03C2DAD4D5B83C4E4B989F92096E2EC4F1035AFDE9085E622CBEF1B62F21840506D574EAB8584B8A84B4852F40A757086C7F728800666A470780F98A480379449167A0FE9FD3855F6B6304B0ADD20000876008F4AFBD5BE9CBF8057F0C3DA1DE9EF2309F68EDE9604E5A6C86CC3EDDDECDB57D6EA43B71E282DADD425D470293C694AD2A428120826ADF80D9AC5F70D19E99D074AFE9E3906DFDA43EA4EF92B3BDBA1D817E14F76A47DEC5B60F6966194DA39C2CFE1D86322250DDAB4969A4B519084A52083CB402AE184C304904023785CD05079380DDACC1F97E371049672497A641C9AD34FC708BAAD0CDBA0CF16A27AC18CFBF5A9C9619091A08D64282A586CBEE4C39ADAAE2CD9EBC1A1682B30414410510414410510414410510414410510414410510414410D1C5F0AC891AF3EFEA3FDCD65C2D1B82E72A645EB58DB786EEEE7FB78A3C5EE9F8FF9A8AC6CAF912CCDCC027B5ECD93FB35D635DB7FFBD7C3775BB3AAC75E702B1828718C1EC10525DBD7AE3FA1C48689973C25AD2A907DD1279E7C4FC69E3D3B2B0F365998A4965004A99E95B1BD7B7689AC1E1C4C60A70090F43AFA5188AE547B6ADEE7766718B5B0C5B793B5FC573B47B6AE21EC6D2E7129766D30E2861C1A0B1C6D9532A471956B1EE98AF0CFC42F162B6D4D9E04C2A0EA04825EAEDCB2C9BBC5E70125084A120252080523DF0BD5DEACD48D85B17416112A99923FFA926075C84039FCABCCB8DC2CC38B54C20D54E1F2AE629476353689854A19003570C7D2255B74189D0F2E533944FF008CEAC3B331064EE87634B919599A9D4D78D2032D346038D05BDF778ACDC42A24F91D7E67F71156D97B437D206F0B35EB600D34D73A5E0328640371BF90872DDCEB9EB1CF3FA8D7B99CBE0DA7054E2FBD7B1CEEFA311EF211A992ED60DA7F5142DEE2513273E93E5D7B67E7CE9FE154508DD2E1ACC7524BE46BFDB9AC6532D21C100B379BF28A7C5EEAF8FF009A75F378ABBFEE37F968FF00888A819CFAD1F378ABBFEE0F968FF88828F9BC55DFF707CB47FC447857C2624FA7FBA3E6F1577FDC1F2D1FF111E78BDD5F1FF347CDE2AEFF00B83E5A3FE220F17BABE3FE68F9BC55DFF707CB47FC441E2F757C7FCD1F378ABBFEE0F968FF00888F3C5EB3DF3FB9E7525276B7C997B80B76EAF6AE59346BF283D83720FE8D1EF8BDD5F1FF0035A4DDADBC18967766F7C6B7318F95C13DBF5078BDD5F7EB51B3717F308DD51CE8E1ABA0FB40658C92FA9200E4D9FB7178F3C533CFCE73FBF5A66B24A492493C4EA7EF1B09696A80FEFA53AC47BE789C51CFD7EFD2A00E20A71052E5277B2350DEEC05B5685E52185817EA5EAF97B109559D28F9D87A312D5269AF6A690AEE876DD0FA35619E2171EEDBD838827F16974B57490786CD2D82A70B8BD1B0A00E63588D73AA76D4C12B7882D7A70E5616393F1840A1017F31949DDBB00CA761AD5B96B1A75BD1DBABCDB0BC7773BBBA7DC7B115BC96B1FC6DB59534DB2A5074A7F10D9E20435C6885039E54B6CB92B97BA0687AB545B8BFBAC6FBA972B20BE5BD91AD9ED761FB78CD3BADDCE6C6EEBF0A69BC30B5797EA6C38FDF39E1B8F3B70E8E3789740055C2E1508E5E750FB57138B958F212A59008A034ED5039106B68728C5A952C2024A124B7D4E0E840AB7BA59865AB14F0979F5C80B981CB2072CF969E8672D2A6366CC1380F9C5DEEEDC0D457EFAF11BCD595EE84814A123B822BA8B9F2314820C919093F5A90C64AC39964A521C0B518BF072EDD2372779B80CEE48BB0FEB8E4C551F68485851129C81A3FDBAB7611A2A56F26A2952458B67D73F4A9A380C345A0E1002889E84C1E672FAFED4C367A9631010B777CF2B75A8E5AF2604AA5CDDD043037CD8543F1A1FDC435DDC30C922520C99394F6FBC855D6724270BBDA26ED4B015F6EE468F13D8594A98000EC4DF4FC9E432A45818FE36AB76EE5F6B34B4A6D2A03FB83A4214394829267B738154995B53E56D0090B23EB19DC38AFEBA0D0582448489441009ABEF0700E4D42DA6BE71F187FFA81B65B08C037E5B0D8F61CC36C0DA56F1255D38848485A99B46C09226482A233F809AF777C12C48C56137DCA8A44B097399A171CB5E22968D1531686046E9259920330B061CF2CA8098F9AFC6F16C3F01B753EA32CB6A507594C12A2EA88494A4E47878B889E5F2AF50A2415CE09A0700D4DFE9E5635A67D5A155E384B90EF522C1A94CC6A3871615AF4A7F8567F0FFDA8F6FADF5607B3C6CAE99DDB60988DADEED1634A6D69B7BB4A568BBB66937052A65C0975A2D2C2B39C84E756CD95842A29DDA1166B9BD68294F6F1CFF6E6D51BB30EF1000CCD0BB017273A796B1FA6EEE1B72783EE3776F816EE764F0DB2B0C2706B0B5B44AED594B4B70B0D3695AD65109254A44CF73ACD5E7098408028038161439FE4E669D0F25DA78AF9CB2B2A721D8136F6E3F119BDBBA6D572D59356EB86C1F15D08FE9A4C1391CF5333D0CFACAFC94A4DB26A5037403D88ADA91BE52A193820F1EFEDA272C8116E906322AD34D67D35D0D6C030034871292120A4351AD9DFDD6BAC3BACC2B051041441051041441051041441051041441092DC28272C873E9973CC51190926D5EB088BA9310358E79F97F98AD54ADDC8C2BF256CFF004F272FE622B55C25313AF6CC72FDFAF23956A99814486208B8BB7BE0EF0CA7CE124805DDF2EBA8E51EF8E989391E5D23E3FA8A5189200773661EC778DE42FE6B310E6DC39E5A373D18C44BD769F1C85B6B6D103FACA10D679895729981DE7589A692A72A5E2F70B14DB4B86D4FECF3A3954B09CC96B817E94108BF74DDBDB3B74A5071A6D0A7096C923810095A87284804AB3119926293F104E4CBD9F3959EE1672327CADC6FCA1597237949033A17CB9D9A85B4B738E66EF0312B5F684DF658E1F863C87704DDABEE1714EA81B2C4977AD85280E194BAA61C411C8A142BE76FC62DB13C4FC42113084EF29802697B6597A728B66CFD9EA202897766EE351CA9AC6CB216C5B617716EA6E5B52186B86253FD101032D2047BBA488E535E503B4953274C1314E5C80F9B12736CAEF61C62F385D9AADF9403020135BB90FA66F5F2E3E32E301094B4AE28049464548E70A1CBB4F2A8FC62A52D5BE12695B720D7BB77AB878DF120C89850BAA8163BBAB73CE9D4C4BD9A177297148040409F7A73D724F726047523D22D78B4CBA80435DAFECBD7D61B7CF4DC8507B53F2DC871E8ED4871C9250E36648287010A1048981391891FAE54AE1B6AA779AC468CF7E9D69C236131EA283DBF6AB5BB42C8511014A1EF0CF3CC40CC1CFE3C888AB361B1E998016A0E1AF31F717BD046DBE38FBCA02F804C127A9075FDFEFBC2F33692504B120E675D33FBB508D21C4B96575AFEFCFCBFBF3F11D95F1AD7FEE5FF00946FF238F9FEA1637ADB2C29D5C908CCA47E6CC9D073F39AD86D548A10934B92470EF1A192BDE0901DEC6ADD69FB8A9ABF6DEB537694381BCFDD508518E83E1FAC56DFF764FF00C5376B9F7CB58D7E590B0870E7476F4849171E3B62E129712DA89038801106338319F5A708C57CC1BC081D5BEFEF58D5437494921C33F0F7EF48F5B790EAC368701513192B2FAD6FF38FFC8773F98D49090E6D0E5C696DACA0AC122261479FCEB266A8162A1DCFE6308585A428380758F034E75CBFFB4FC2B1F38FFC8773F98D89604E91E96D43FBC7C48D7CA4FCA9BAD13261041735B1F5367A7BA460170E338F3C357FDFE07F723E9594CB980015F38CC78A42BFEC08F3FD33FA52884AF371A3BD3AFE3F3047810A9C881DE48FD294620124B8639935CBCE084D6CA8AA6419EF303F7EDF6602660662B1466B9625D2EE4039BEBA52B6BC2889BB818B56CF7F56F3D2F08A93C399223D7EFB0EB564918B461A5042EAC2EC3F67D3362F0B09C86722BD1FDF0AB6710B7D6B7AF337EC34E20377CD29AF1164F8B6E1485364B247E59073EB94F3A88C66364CC0A1BA93BCC5C8167A65D385EB684D6A96A5A16EA1BAEE9C94FA8A8A1BF522AD18CB77DBA7C0F60938B5D3015718B62AE788F622EF0AAEA38D4A203A3DE02145226721F0672368C9C3972C0E428001CB5F3E548D8A92A2086DDCD3404DC8D7AD3B168C9565656968CB6DCBAE25256A2550A24A8F119E5A939F6D2A1F1DB4708B9EA56EB92694A3F91D47E21352492E0539D7ABB76E668F14DFB8EAD4916BFD36D260A55209197E58CA72E7A914D65ED24053CB05366E87AB0C8DD898565CB5937625AEE3FBB5790A98A537896C04290E123290099394E67BD3A1B494AB971A1A5F32286D0FD1254F5151D5C6B407ED96B0A8BB6C988503DF2FBFDB3A5D18CC29ACC48720DC03916ADAF6D0E7A29F256C4D2D4D7B1F7EB0CAEF186DA429B1C5291C898CE35FF03E154AC66D49387DA7BC94B277B40C187B03288B9B839A6782092E680660D0FEF219877318EB17C5D6A51E02A19926662750797293FA54D4CF14E1A6618C929014450903833D726ED16AD9B86504A41760039CA8DC75CF964D1108E0C4ECAE0282B85BE05BEA50F7441E240933055103AAA0D57F01B326ED4DA09992CD0A9269A13C34EB4E6626CEE4B60A20153900B396E17A718F91BFFD484965388EE56F30F69C4DFDC1C7D29B72902E5496BC24A961033E10905733F973AFA0BF03B616270D22482BFA1613BCE7316C9FC9C6B1158A989492A72082F5BB68F6E6EDE91F3C7ECDDECBDB7DED69BD9C27775B05862F1ABBBBBEB165F79B69DB8B1B265C71B3726F94DA54507C2F10A0C47109D04D7B1F0BE1DC44D289A934212C43E8D96AC18778E7FB5BC4F270D315209D453859EC7EFCF2FD38FF00868FF0F9D8BF61EDC9ECD6C761163871DA4561ECBF8F6256ED37F8979F7909B8E15BA948510DA96B400A04A408EA6ADDB3F64CCC3EEEF176E39E7EE833CD850F69EDC978A0A42412FC3E927537272EB6A474F2D597C2C2CAA19CC04926739991E64558A58DD46E9150C05F2BF7FDF3AACE5198A26956FB7A0F4859D65F449B54B0952BF3150890489CC769FF0035B924E64F38412863514D29EFDD61DA13C0909D32CE349E7F3AC428000ED9C5744660A20828820A20828820A20828820A2082880D013A434715C4A52635D0733E63CBD27E49AC29DDCB7334F661295881F3B70B57A31032CDA95AF11C23D44A567581CB2D3E87CFCC4D2A847CCA6A1FC9FF00A76CE25D202D0CD5D6B9E99F4F285B252028721A4FD7EFCE68124A54EE1B4ABB6869E4FD62176949DD0140125EA720DAF13E7CCC789546474F8C44E9EB4B8486DE1BBD2F76F7C222F0D8A549582350F4A1F6E69AE90C71071E470A1D6C2ECDD3C2B28054B4E907A0F78FE99738A9C532E6198A6A55DECFCC9E6FF889F94BF9A37C66327ADEE3323DE51803DA237888DD8EEEB1272C9F6158ADF866CB04B15287E2AE1378E8B6BA286C4159690EC98D009CF3AE67E39F13CAC2E0E623E601BA82010781672FD68FCE24F0682A5070E5CEF3B90F6193D34CDAAD47C05B97DD6A760701FE6AA529DC471A3F8DB975C1C4E9372A2FF0A9591211E2409D220738F9C5F1476FA7178B9E12B25D4A72F7E5FACED9C5E36728CBDC2588D054BEB6FBBB068CD178DA3F97A51038D4412233FCD267ECE42473AE19860A9D341BD4B9A72E943C2B4CEB65C3633E5CDF9854E08615043D079794610DB6DF7EECB7758DE17B35B518BB785E278EAD4CB4E3AFB4CA029212139AC82278801AF4ED5633B344D96E949721CBB11E57E2E0EA75852626662262E6B2776E2953472E006E4E32A9D7256098D26CEF5AB36EE957B87620DA5DB3C410AF11A295B7E283E2881FDE008CA4D57B19B254146840BB8CF5CBD34AB648FC9332525425EE924FD2A152D43973B753175AEED0D82DB8E871D924A8281267302626239F41AE7510306A9531B74E795B9716A126CFC2BBCBC39502774803FDA6F4A50573D5F36A3C453CFAD6496C92274FD7B0CCFC226A670CAF96C19890720E0F6AF5E91B1C329C1602AE685ABC4D78BB13DE1CDBF1169257F98C935B4D2E413435FB43C929DD491CBEF0B5250B430712B2B7828C2145303EB94E7FECF6A208B6B6CF6C98D97C2D965281C4E880207500FEBF648ACBFD2DC5FDD29DF5D6114CA4998A9AA776FA41CB870E3F710AE17B533B396B88DDF0B4C5C8570717BA4C2883ACC796B3152F879BBA801A96EDEF586B3128528907EAB299A94A3FBCE25F0DBFB57D837364E05BABFCA2665427403F4A5FE71CC6990FD5FF00A68D4A524314823944ADADE5CADB0ABB1C2F999049100481127204474F5ACFCF3CF9FF007A7B178025200601B26B4493572404F1106796647CF39CFBF9C1AC89E331F6FB98C14036A1F2F7CA152F24924C4798FDFF005FF0E25CE4B5090323637E7194A400C403D3CA0F151D7E63F7A53E70FF0091EE3F31961A0EC20F151D7E63F7A3E70FF91EE3F3030D0761078A8EBF31FBD1F3926E49EA3F3030D07611429C041CC47CCFDFD9E75AAA62425DC87B1A558D58BF4841490EC6AC5F9FB7868E3A0CC68222749E7CFE1F731F889A14336ADEF6BE64B74EF0572BE5EC4365391C51FE32F5981CAA1672C31006B5A3716AD1F9B51AA21D224A99D4286E2F6B647DF286AE3C24E6679C0E5DBFCC1A8A98B735CAF7A353FBCAB0BCBC33D774F014739F3EEF9D042887DB0D80BE119F389CB2CE7E597EB4DD5212B75352EF7EB5BF1BF3192E641DE2C0B51D837273AE75FDC20E5CB1DA4E5060E5E597D99E54894A6596ED41E4DCE164619776A0AEF55FBB53DE70CDEBCB4420F1293C6359E1E7E6723DFF006A497884A33D5EB422C3D7A7AAF2E4CEDE66514D2A5C9A37936472AB6B6ADF630D209085091D3AF7CFBFCE9AAB1E0160CCF7AF2E3A694A3F19346154523E9BEB9B574BB7DDA2D6B8C67C452A55AE5DC7ACF61F66699CDC3CAC42CCD252E58BE619BB0FCEB69393B14CD4A66D068E0B93A00DC7A677788A7961F920C939907AAA32D675EDFB5446325FCA0C94801C55ACD666D6B5A6594487F8270C91705AA32FEA8E1C0AC050DD859397574F1651C2A36ECA54128BA201E22F24FE74B27DE911C31564F0862A6A3192C0DE62A02F4B8AF0A8B9D3AC41E3B152D0E4941520177FE497161A7106F78F928FE2DBB15B6DED89ED59BAADC4EE6AD2E76BB6DF0EBFC42DF197EC50E5F611815A5EA195B8A754C4B96EA5DA1599508E341E409AFA47F05C4E9D8594B52F744B0874070B99BC5BE815762CEFABF3A16D3DB484298AEEFF0053D05C39D1F27ED1F4C9FC2EFF008576E6BD89376782DD5861D698B6F62F2C5BB8C7B17BF69879D178E23C52869FE04BFF00D22E2DB857E588AF6E6C4DEFF111BEEFBBE807E7988E4BB6A789F8A5AC6B95ABEE83ED1D6FB662FEE9A530CBE2DEFEDD69FC482A29494F14A4240CE38040E511153310F17E3265A46609090091A1500028FA99A208528820A20828820A20828820A20828820A20828820A208288C1B1E4622C8517CE7209233E5D87C7EE056AA0E1A970EEFE5E5FDC4392BFF002D3A035367FB716BD5A1B5CA0859D60E606B3A0EBCB5D29EE1C2001FC5AAEF91033EFE9778B5C82F2D23302BD5CF7FEE1BDBDFA4DD2AC432F95A48E27787FA425322546234CCF5A6F3F109966AD9E57EAE1EDC84218C47CC96C0820E952E2DEF4E514DF620D589425495BAA5988687114E99ABA6BEB50988DB52643FD429FF001B80E72A07A57CD9A2125ECB9AB5021248268CEC2BCB437C8D0461ADE5EF9F03DDF2B8AE14BC556EA08770CB321EBC656530D7F48C14FBC413968272AA76DDF1548C3C8528CD48DE0AA0354B0A3D476761A45F3647867118A904A5135250DF510C95BDD8B55AC7DBE9F5AE0D8FEF976F6CF6D76C0BCC6CA60AB75DC0B07B8E24BA4BC8857E29872504A5CE152383311E83C75F123C72667CF9689C4825565790639D29DC45B65F870C94B6E80B2C58DE99915D7DE7B316172E26DDAB77D216DB01484A19023C31EEB6003CC2409EB90EF5E36DBD8CC4ED0C4CC53A8A4A8B3127339BDADC8BC492B64894031008CF98E356CB84463F77C57DC2E7134C9FC81DCA32F28F879F9A7B32419652542CC4D3AF535E43843799869B292087292E01E5A535CE9E51A4FED97ECB167BF1D8EB8C4301BA4DB6DEE1A855D6CE3ED2C2429D6541E752B5A4170921B4A404F3D6AFD864A1526803B51AE5FD2CD4D5B5899C24C0996D34EEB00EA55AA4B579D3AB523597D8B7DA8719B1B8B8F673DF42DBC33799B38EAAD6CEEF142A65ABC6C296E23F0EB7CF8AE2BF0E84010224E90669962B0B2D414126A75671A8F47BF1B43B5253499BCA56E7FB52685C67A8FC36B1BD7B41BDAB6D9FDA3C3B08C430EC542B14586D8B84B405B8881C4A5A8FE43C52939E5C849AAD62708122D517A7DBF1C758587CB6E62805DFF7CEA7331B1764D86D16CB788507DA43A8291301480B00FF00E50623AFCE2E62371553714DD2DC3CF843654D1310A084EE94962141B36714E1ED843E514A8952125291020E47A4C773A4524E4DDFAC0874B254C546A48B70D3F5CDE282A09899CE88521BBA871C2929809044CEA403FEFF00CD10459FB5FB228DA572C8FB810C281742F22A00A4FBA331263AD64D4B8EC32F79F18C25C0637D6FD7F4F16AEDC6CE62D88B186E0D8238CDB61F62521C0B5142D4094295C213910485418F3EB4E5134331240C9EDC73F6FA4202490EA212497B73B07CF5CEDC22F7C36CADF0EC36CD8B54B9F8A6529F156BFCAA3A9208CC89F803E55933D0003BCC4F4A060DC283AD235095BA814009664B03BC5EEED4D3DDAE125DBA5078C20A8004742911DE0F90D6B6F9C923F9163C47E632997BA18249BD48735E90B250E2755031A664FE9F7D7A644C49B1B71FC1F28CEE81FED6E8D0BA5C310449E79E9F5A5A54E00665F2714BB3706FD46DF2F827B7EA2AF13B7CFF00C52BF3C7FC4F7107CAE09EDFA83C4EDF3FF147CF1FF13DC41F2B827B7EA0F13B7CFF00C560CF190238D0C06550D13D2FE91515C266333C8EA343F7D41EF48AE79A249715619F1CF8BC3298965301CB534CF96AD488F75E0924198E5CA74D7E51E7CB5A653A7F501E86AFF7CEBA7185E4497FA8D746B821F877B886EA7651C5233981A4C1E7FA7975A899F39F9370AD0D33BFEF94A22582580D2B4E4C32CBCF4884BAC4D0D4950CA4C81D0643EF4D2A29588625DD8E4EDDDE9D00FDCA4AC1A942960010FE6FEBF9702206E31795A9495108E40C65027AFC32E7999D1EC99C9F95957BB8D3BDEFC1EF232B03BA03A4139DAE68CD4F588A7B1A09513C66675D63CBA4C72F2A61899A9A8D3A3D457B8ED0E65E042812D7E078FF005C8365160E2FB50F357CEA52B70A7DD1C20E60C673A7D2A071588704037666E1986249A9B0A521DCAC03390976BE560180ED7A8F588E671D174616A5372732E401EB398D2674FAD41CCC4A92E1F5A82DC3334AD8B748768C1512424BB8A351890D95799B3EB1E3F752E05347C74082E2992541A1C8ACF29F9812749A4A4ED598957CA724921D892D56A8A5F4CF2CA2C986972FE4849025A92974B800A8E6D77A74899B5B96C302E3882D8FEFB8041691060F88BD131D73CC559B09B3713B4C2404ACB8191B16E1EF566783DA98997265A9C804B8634373AB30F3F58D66DF56F5B69F69AEBFF66F73986AB1DDB3C4D4DDA5C62A965773678234F14F8AB2F307C4B7529852F84C66B4E7005764F027803153F1524FC951FA93FED26AF7B5BD968E3BB7F6AA10A98C4077FA8667D8143CB81DAAF63BF61FD85F67AB8BADACC630EB4DA2DEE6D1A1ABBC5F6BEF5A6EE6FECDDE12E169ABE290FA121B714C90A27DC0139E95F4D7E117810E0B092553A5B6EA5156FE2585B3CDB83306B4723DA9B495316A0EA00B80067CEA4657FD3746EDEC997DA4BF66861A751925C6212952A6145440CF31A7527A8AF470C327084C90929DC09A10D421C79373A1BC41151554925F587F6987F86E1BA7F87F14E7FCA5BC90A8109CF5303AFD2B68C449252103852207EF441155104144105104144105104144105104144105104144105101A823586FE1A788A89023B89F4039F9F3CE26886A24BAF7DABC5C79FDBF709388490547967E5CA474F9D2AE5292C0B80E73AB07D7D1A1EAB109901945A81C74ADAF6B4312EB09539E18487140F12801940804911A012263A8D045336E6D0F912D41D5BC012F663A70F31F7470F8A4CF98108FAAB6ED6E27D5852F1A87BFBF687D96DD558DC5A1BE6AE31A752A0D329710A712B33038642A012274F21AD714DBBE2A4E1CAC0987783B906CD7B33776AD23B4782BC173F6DAE4CD5CB2892E08431DE50E34ED9F131CB8C537B98C6D5638ADA27DD7957F78F151B774A8B484A15C2DC209E2128E139F5F879E3C63F10D7284F4FCF25E8DBDAB59EADABD69DFD2DB23E1EA30F2512C48012025BE8E21EE199DCF5BC5E789EF677876564CAAD2E5869B4A470B4DADD060680A4440813DF58AF2B7893C5B371F88581394CA51600D2B980FC5F56CE2CD27E1FE1A63138696A531BA4123967C7F30D6C3DA0F78B83B8CDF5F8F12D9C2014FF54C0490939129039AA7D7CD0D95819B8B48592A20D781E39FA7770F11B4FC07874214061900814012033E46C6BC34E11B87BB5DE7D9EDB58B5737A017E0150000209D75248E9DE222A57158718445824839DDF80D0802E2C738E59B6FC32BC30509481BA92E428304F26F5EB19B6D5D6195171284A9E792461C56250D650E8569C2160C403999ED4DB0BB5BE58352F61A5D8FE78D6958A062E5AA5CC4C956EEE827E62452D66A70E995A39E9ED2DEC6786EF431B5EF67636E0605BD2D9B52AFDCB8B250B66EFCA3DF4B7C6DA4BCE1F09B2889993C22662A465E2C4E0E2F9BBDCB585EBD7A460630A1411BA4A55449193382E7CB2D1B28BB372B7B8D6FA766F08C3B6C30C361B5FB2AB5DB5EA9D694D38A2C381A69C95CACF88DB3C5240041D291C420292A25CA8E99F40D419E798A88DFFCA4A52A2A2129E3463E8C7CBCE375DB43D6D8759B0E125DB5E16C99954248488D0E806A3E555AC5A4A4D18D7B9FE9EC7864C013D2EB3425405072F6DDCC4DB8506548238541111CC8038BE73F4A6B785641242492E6AFE6DE4D0D5CE5EBFA510E6112BE12467E9FEE8820F17BABE3FE683404E9041E0B4E1E356AACC8273F89EDFEF2A6CA5D6B53C3280AC8A04BB66DF7FD73AC38430D11904E7D333EB98FDAB099A967292E75CBBEBD21352C87A5B2B9F510938436A281200E9A67EBF1D73A4D53D8900103A8AF7F7CA14402B485503E45FF0071478BDD5F1FF358FF0020F1F3FF00F68DF70EA3CFF114071434FF003F28A7D2A712090790059BCCDFF0636DC1C7A7EDE3DF157D7E67F7A5BE69E3FF00D47F106E0D4F97E2144A8900C9F89AD0CE2FFC88E153DEF5F6D09A831223D93D4FC4D63E71FF0099F7D23115AD7C29224C88033F2E7DC7D2939B30DDDCD4D2BE432AE7C2B0C268DD981C8CEBD0444DC3D3232D79F4CBBE71D728F5A8E9F3CB5ECFAD4D9AAFDFA448E1D02990BB0E23CBF77888BABE0DA549900A41E7D758FA1FD8D45CE9E374B1249B575EE05ABC3289D9186DF214C58E57F7C8F908B1B11C4614A3C4009D391EE467A7F9F3889F3D89255C6940E791F79E462C984C216140DEEC7AF01C323665EE28E1716105412065073E7F2EB90EF49A71C65B0259DEFF006ADF477AC4BCBC206629760323EADDEA784405C62AF1260939F39FAF2E5F62939B8B13050826AE4F32F47A9BF43A98712F0AD641AD2DCB830F53EAD416543F1AF9E22B994920E9968ACCFF00AA8C98B7CEBC3EF5F57FC48A3083737774D83B8E7C2B57EB11CFE396A494B162E2D5D4340CE9A46BDBE798A68B93F309DDCF8350B0AB707D2164E082412EEE1BF0282A5871ADA18AB6A1385B4F5DA9567676F6A92BC47F19EE36DB7F9878F9C02A483E1CF3F3AB17873C2188DA78B96B420A92A21C106B66C98B65D6D68ABED6DA88C1A8CB538525D88B82D96601EF7A59F1AD86D2ED36FF00F1C5EC86E4038C5885F818EE3376169C11B4190A558DCB1202800E0055978804F3AF6AFC39F83537188905521CFD25F7356FFC7F0E5C8B98E5BB7FC48196EB7002B30E05988D5F2BB9063A21ECEFECBBB2BB93B3B8BBB5BC563DB6989250E5F6338B2D171705E00952597C2439C08952120E890065CBD75E15F84F2B650953178748524057F0FA49A1BD78FE35E3DB4F6BAF12A539210B25812EA0C6AE1DAB4ADBBC6D43185DC22D941453F8F70FF59CCE0A672E13993EE9220CC6990AF47F87A461F66E1D329490964D52D57028CCD9D49BBF68ACCC2A98492470CF9D7B0A51B2B35C7616EDDB5BA5B6C242049F774E227DE3EA7CBCAA466CE33E62E612E49D5D8643B40CD4666CA1E52704144105104144105104144105104144105104144105104144105104365082260013AF327A4E9D7BD6C775282A3C7A37BB5CF2B64A9094B921CBE76BB53F37D612582E2480600D3BE475FF005D73CAB28589A93BA6B9FBD3A5B37AC46E210BC492104824B66396BC6E7A4620DE56D55BEC16CC6D1ED0E23728658B7B7E161457C30E3885211993AF194819F481CEB8D7C45DA276561F13356580048F79FBB6564F0AF86E762B684A96141467281005427759DEECF46D7331C0FDBDFE6BB61B4571B5FB557173756B7F7370AC2D84A94B2D25B5A9214EA579252612531CB9578D36DF8D24637113A52544289500C4644834D19CF7BD63E807C2FF000A0C2C99026049A26A43DB9FBAD2916E365D0865C60B28790A21453207003088CCE7C3A939033D6BCD5E35DA3889D8D9B2D2B5339CF50F4CBEF933347A464EC69094A54100D01A0A71D1B3BDEB6CA6977F72EA5B2E5D3CA527229E33C1972CE72EFA6623957309784C41C4FCC9AB5105540496E2D417ADAACF5858E124C807FD2481FF002090E72BDBA0E377876FE266F2DD36AFC847090824C09F5EA73E73E55D4F61ED5C3E124A11312E406A3353AF6D38C5776861244D0B4A659753B9201EA7B5B367B88B9375BB7F77B31B516D8638EA4DB3CEA42425478632C8E91AE703CF3AC6D8C7A31AE24DCD0352967A1CFF0021A39BED8F089C5A26EE86742D42F5604D4FBF38EAD6CD6256F8B612D38F2212B6905975B03C46E5238B80F2E23AE432F855657839F25615BC4A545DAB48F29788B64AF0F8F9B292485A56A0A3504B1239D8370CE1CA2D14029B0E14A493FD50AFEBBA0FF6BC7FB872CB9181DA4B0F315258A9CE9A1AD73AB68E00F5833805FF00C88B905CD38D39661F942186E0F8260388DF63187D9376D8BE221B176586D286145B4F0A5498E124A84C93FDC4EBA177331E9615655883F6B97CCF1E9097FDB6729D2B585CA268332D5A86A5453BD22E86FC37ED1C2E03E33924F9C9397393CF9795454E5A66390E730C055DBAF5AD2038652549485303425ECDE5F8EB0D2DF883294AC10A05591CB9C0FA5317093BA1F2F3D3D817EAF50A12992A356229C33F2851492A888CA75F4AD9EAD5B3DBDB7585C2D2598DEDE9EB1157AE8B595AC920E813AC69D81CE39F6ED5B8965445C33E5771A671B0FA8B023BC376AE43A92A85B60735989F2CF3A57E41FF0090EC6141294A2C18F27FC4542EB3949246706411DCF3D72F2F5351B3F0E42CB114A3D72B7285912D2C413517D28FC0BF67B52D0ED17262012083A8FF007FBFD2992C949FA95FC72BBEB7E9E6F48D7E52544B3685E80B727B7317E31529B71490EC9E15732639C72D73F865DAB51302C920D7969A6B1A24A524CB7FA93957CB87BBC22E079082B0DB8E0027DC93D7F6F8674E65C852C12C726B7BFDD396E152DC852C06C9C0F7EF486A9B97145005BDC02B244149F7639ABA4EA3B53D97845EE0217D01B57F27F30A6F4B01DD2D5B90E5B9C3E7D06DD29538EA53C5CB8B31E734AFF84B607E65F2DEAF60FF00DB884D1350B24043366580E858BC2A56866DD0F29C4292AD384C91A6BF326B6FF0D4120EFA4DA999E37AF956ED0893F3262920335C9603A5AD6FC4541C6CB45E0B1C004EB9C67397C3E347F88B037B7837AEA066F76A4608216106E73CBBFBC8670D7F148B84788D9201919E625391883DB979646A3A782951483F57FB790BE9F6CC69094C904AC28D4532714A023AF9F5311CF0528CE507F4E5F7DBBD35549529998EA2FD6DC214978A97295F5659528ED5ED668B471552D0B7110490066273CB965E79F39075A8DC4615402B8580C9F2361D3F713985DAB2414A4025DADC756BFDC5DE8F60E245D528E444C9CE7E072E5AE7D3BC557B1095209DEA905B85E9663F8E0C22DB83C7CB580024DAE037126B5886280532A492ACF9778D39C7D00E5511377F78BD1AB47160EDC395AB13D2E727E5EF121FB3E43DD07578897DB46797CA39FF009E9AC79080C46DB1859C6493551604D47014AF58712714852824062726CBAEB51C4D189AC5B58ADD7816EFF085FF004009047BAA2AD3863948D39FAD58306BFF0026426730DDA9F36AE44D844E26592905354B5FDF9E9A4686EFE7DAAD5B9D71D63FF8D75888504DBE18CCB97F72A5100218641054ACC683CB3AE8BE0FF05E23C558B9385C390153160382C5C9039350B3B5A22B1FB6246CF4933121F74D28E5875FBD8F28BA7D987747BE4F6D8BF5ED96D7AF1ED80D85696CBBFCB1B2FE19758AB00E69BE65614DBED909F7338E05F306BDF3F0E3FE9D71B82C3E1E7E25285164A8920F3A022FAC79CBC5FE2F96BC6CCDD2456C0DC654A135D4BE71DDFDD46E8B77FBABD9DB7C236570DB2C20B084B770EDBB4D30F5DB89305CB852238D4544924E664F2AF6A7833C2383D858542264997F312901CA5390B03AD0371F3E5B8EDACBC4AAFF0042AB515001A5327E757B5632F33832DE74B8B5B6CB2D41B55DB1871523DF2E9D0C91A7C66AFB35723700932C390CB7008045B77C9F3ED58198B54C2EED983E808F76B44D38C5C298E149487B21C44E4403064E6648D6ABB8AC3E296A2652F72AF4240E541D188FCC6C929DD0142B9B01EB43F8878D24A1B4A5512358D279C4F539D4860E5CD44B1F34BAB5CCFB6F7531AA8824910A53C8C41441051041441051041441051041441051041441051041441051043777FBBD3F4A471333E5C93DEDD35B5B27BC20B964AB3ABB31A665AD7F7942493A8FFB65F234D3098848739004FAFE5F2D05EB99402660268F70C2946E9EAF4CE39FBED86FDFED726C375387BCB61FDA0B865DE3428A54A6EC5E6EE5D120660A010759935E74F8DBB4C7F8589054582486735E5D3CAA6F1D5FC133E5C89C99BBA3E63D145A84598B86278F9135D0ADFF006CCDF6CA33688C3ED54BC3F0FB661B5AD282471969B4B8A94C0CD609E526329CABE7AE236A23FEE93025542A56772E736D7879C7B1FC11E235270F23E61DD550148A067D29DC51DDE359AD31242EDD2A194F16B99993224E5967D3A41D4D3F6E2C4EC6296E0839641C3E76A35BFBF4F6C1C54AC761659DE0E52F767CB98EB9E90A9C5B8753F319F3E833E59546CB90952B402F6FC5A2C5FF006E4CD1FC778351DCDDB43F704520FE65F8B2D34DAB83C3E2E220C1CC488CF3D7FD53B4CA4A40001BD855EB4E3CFADE18E2763225A553141212C487A373BF067B1E622DEC39DC4EE36F70C66C1B71C487D216B40240D33919CEB9F78D32A732E554580A13AD3A5FAF58E7DB57132B0626B94064AEECF50410EF9F9DC651DB5DD95BBADECA61887C12EF809E30666613F219FF00AA7330BA500D4805EDC32E0DEB1E2CF19CF44CDB98B54A6092B70D620E7A3E5AD5AF1929B679F08E51F31D33F9D20A4B80D4BB69C62A0A98CEE49D74FC7E22972D87171AB28898CA3E3113FBD24A940BD95EAF6E367F6D194CEA6E834269EC1D79E4FC3CF1DB68788540348CD664447727E79FCEB41280C94C387EA1252014A812378BD694B6B4CB4F410A8BBB6BE1F88B45256C2B24A92414929C95047FE535B9C1EF10A09D34D33A1E77A9A9BC47A42925295AB7940A9CF3B4149AA46EB500E63F43DF287096DE0CEDC6F68C31BD5DE2DD6C5A2D0B1B378A63085A8A54BB3B42FA07BC9008339C4E67AD247E972F67A8AF63D7A670EA4286F900B917032A1BF7F6C627367B1356D7E15698A7E0313C33893C4AB475A2CAF3CA382627EE69B4CC490A0056D41571A3D05FABF287895251552F77424DEF7D5BA45CCE2508570A1B75A4803DC7870AE6332477EB4D274F0E58A8035367045E819BEF1AA5616905D2A2E7EA4D8D7DDFEF0E5BCA472CBF5A899D33E616666CF539C6628657893D70EB508166CE683EF051912648CB590279EBA56F86016424DC640DEF5A8D5A9F68D0EE20EF3328D1F32FA7BA6B568C07BD0DF0DEEC93AAB1C3EC2FAE569047130D1704FA1EA4CD5930F24EE86E3F8B53F19B98C942557482DAC5B9BA1DEC63DB518DDC318A61F8930DCA4A03AD29281209D09EFCA9862538B44C2995BFBAF42976156C99ECDC4DA1D8C2EFCA7615663A5855F95B2A38D365D65FBCB9F7D32DFBBC2179F207E3FB522DB43559EAAF3AE8F5A3660B884F7112D164B7035D7227CB2ED0FF00C1B77C26D9D5F0AD04F12504011CA06BA77C8D6A46D014066139DEB614A572CCB7A335A8804A7743E79D32A1B93DE97CA558B1B52D1638CE70224139EA3CF38FAEB9E5231E4FD456DAFD458E7A310465A90E619AF10B490FBA4F5719DFF1EB68E76D1162E2AD90494A0E5399F7B333F7A5650898EF33F95DD9DAE731A30CF8BC2E8C52264B0E589B870C18D4B1635E511EE72F5FBFBFDE9E2774074A6A28DF8CB9901F856135A50B2295D29D295E3083D60D3ADA9E54C919E9CBA48F872E71A532C5A0EE9A00F73E8DC287AE8D0F30B212952737D398B33726A7A8367E2187B526129F2CB967E5DC728806AA98D949FAB334AE479EB5ABF38B8604A52C1A8C38D455EBA3FEA2CBBCB54A5C5A529C8691A67A74D34CF3E9AD414F94A09533391424F034E15E00671654282A4834B57817CFA4415C5B44E51AF2F872D23E1D39572BDB00FF009C5245942A347AD5B964D951A35C2A93F3455CB8AB5BAD3BD62DFBB5B12BB77ED0108523FA8B6F27648260F381C8E42BA3EC89811B2901490E00AB0FF90BEAE34F58B6C80A520AD330B043143D03A481422D60733A473FBDAA775DB118DEF977418E5F60AA4A1DC45D379C56EDFE19D297184B61634502749D7313D3D3DF01673F8830AC187CC40614D1DC176B9F28E75E25DF1266098BDE9890BA82E03BDDF46F4A47D0FEEEB0AC3767B66F67B0AD9CC22CF0CB57B0CB30E8B660328E14DB3441844093339819F9D7D8AF0B2B7B66480C0112D16E43D3DF0F2A6DF2A38D98A52B79D4ACDC062437BBDC878C849C3B0B5BCB471053CDC2968041CE388C8F31F1CEACA43EBCB23CF588389CB55214CA4B69284094849C88831A72ACB0160D0438A20828820A20828820A20828820A20828820A20828820A20828820A20828820A2086EEFF0077A7E94D31DFFF00CE585AA4E7937BB46410A4E8439639FEE8CD0D3C4E151C8CA4F3C81F5FF15052A6142580513F5540EBC3C8BD21171BEE6CF9F2F7EB1CF0DE75F398E7B4961966C1877000F02173C31776A348CF4274D33E599F2A7C75C699782C48CB74B00399A9E1E5C4C5E3C3D3D52D52C8240075E3A75B679DE24B6F360ED76A2CDFC2AE116EE256DACB8A700519E12A1C24EB072F87A7CE39FB489DAA402C42D65CDB3F75B1E11DDF61EDD560C4B5952D40148FA4E64B59F5ABF2CE91CD4DBCDC56D2E09757D7B8532877094AD45843416A772278F2480089074D75D4452D3B1226282D4C6EEAA64295A67D5ED1E92F09F8DD1264CB96A9A02801F49559FAB80C476E91AF8F5AE2EDDD2AD5EC2AFDB5A55C256A6149464489072CBD339ED584CE483BC9E058795C9E7EDA3BB6C5F19E1674A1F3160D01AD43D5B3CF85F4192F6D84ED0BD76BB6B2C23115AD6501372185FE1CF10E4B1AC139F965953C97884A98960D7CB2F75AD6B9C6BB77C5B874E1D7B8B48FA496040A8CEEDC5B91D2374BD9FB73AFA1D4E25B43689376B5256D29683293075E2CC6A34FA654F113921F788B6445EACD5F5EF1E62F1978C49337E54CAD6E68CF5CF896FC88E8561086B09B166CD49953408940F7784FE5D633032397A9A693B1A90A670CF4663D4971F71A479EB6A62958DC52E7BB1597BE97A07A3FDE26D18A5BA6650AED034EBCB2F49AC231214097A86A1258BF3CB8FA188DDC59A3B8EBF8E10B3D78D299012485DCA541A3FDC9294E8BE62797A7ABB42D24124D4E941D7A3716A1B46802CAC245377B17A86A7ECD9A916CDEB372E6CCE296616945FBB6F70B616A24240690E2CC9D46432F2EA327294A72A9A367FD1B65DA30B44C0B0A25935DE7CEFC2CCFEC4637DC3ED1398B6C9B5875F2D6AC46C6EAF9370FA892D287E25DE0E151CF2488CEA570F286E0373A914AE5DB816E75289511308DD25DB2A8A1CF2B7171190F15DBAD92C11CF0B15C770EB120C13717286C083067888A6B899692E02439CDB917E3D7808708FE40B3F0E9CFEF0C13BC0D80C6DD6EC6CB68302C75E91C16B6F72D5CAC139C040CC2B39E711509884EEB860746AE5C6AEE3C99E1C4B4266391BF2DEE41670072A80D9DBBC4B3D8707407ECDDBBB22DA789BB76C86D939716481D7288D66634A819C95256480A15E34CC0B55AB778709292A017B8B4B67535D6835CEDA8362DC5CDD5BA6E2E140BE4A92A6C93E20083C2091DC099A69353354951357676BFE6D7785B79091F2D09DD4A6B664D5EDCC9FB3522A6EE21C2DA9A71074952606463F7C874A60A42F78D77781241B7DC8EBC60157D058EB6B7786D89DD3785A9973C4BA5AEE891E1B4A05ACA06635CFEF2A7D8374919BDCDF86553CFCA130779F7923E934A026AFD69C6DE9AA3ED21BDFC4F7718687F03DD5E25B5F893E825955AE0CABE4F1651C45242B98D34D672156FC2A920241602973AFDFF00340D19001208592C482E5C69F9AD7368E79621ED19ED878A20DDEC6EE5DBC0DE7CA821177805F5BBA8014784A92D92448CF29EDD2AE183C260A74A0A5896F9EF370CEBD34D22630FBA258DE3967E6F522E29C69711682F6EFF00891635748786CDB564D13252C5AE28DC2409C872CB97E94EBFC1D9E5D928366603ABF3E873BC258854A0E00481A1142EC3A9A1F748F1BDB9FE237638D3CD8D9D6DD6121BE071EB5C514E12539F11919493CB410234ADCE03670500D2F3776A534B3DBEE2B10D3C7D5F4D53C1FCF97F778BD6C36C7F88F39709B8FE478606A4152556D8A710C84889E5AE5131F04CE07679144A1C02723971A6A2A223662544BB727F5C8768EACEE131CDE3627BB6C05DDE961AE31B6AA1703154B0D3A8B710E90C94F8DFD4CDBCCCCE7A64455136AC8969C4912F76A5D85880F6B53FACA236619A85B07A16A3354D838BF2AD6335A995940594940E8A107C88CE0E597F9A6C25B07B3666FE9DADC2E61D4A9B368EE793BF07AFE1B9BC205D053E085A4AA0FBB3A6A6239CE910640E951F8C40DDCEDDAB9532EB9E8625F0F88989FAAA00C8DE872EE7A72882BFB27735171A42359528803EB1D7E3D22AA98B96778F603DDC8AFE6B12B276B0412198B86701F8B7F62869AC5917C508756994B9C310B6C820F69C87A89D2A2572F7D2A49B31AF2E4FD43EB174C0E24CE91BE48622A03925E9EB977362602E16933EE91A6BFB7F9CA7CAB93EDD93BBB4142C4285EEDD43D3A73AC2F869844C046ADC5AAC74FEA2031369BB96D0B295A45B927FA6002B9CC4CEBA4C8D055E36691FF6B4822A1AE38DB5CFDB45AF0CA280B62499A1C0A9DD2054707E6F68D62F6862D5FE19B378A5D34D24E1D8B5826D1C4262E1017885BA1C927498E434D729AF487C059BBBE21C2906826247BA35685B57CE285E28584A26805C90AE21C8F304BD357B523B89B076E977663671F42DC8FE51619AC82A8366CF3191EB98F9E55F657C1EADFD932142C65A07601F33AC79636F157F9B3028241049648A317AF5D22F46F0F6DA7D572CE6EAC0E32B882448AB5D5CD9B2D78BC41D5F867FAE3D624D09E148100750349E7598CC5544105104144105104265C4804C1CBCBF7A208A92A0A008FB34411556017D473BC105660828820A20828820A20828820A20828821B9CD6A9CC6500FAFEA3E95B2D01728A48B83D59E8F08AD7621C31FD3FEB8B4337340498FD74FF3F66ABE642C6FB07A1619B077B81DB410BE1E5A66104BAB3A75BDEB4CF5B4738769DD461DED4D7AEDD9E14624122DF8B20AF0ACE17C33E7CB96A6BC73F1FD1B983C5354EE2AA78D7AD79522F1B170EFB840A5AAFAFF006D4E45E325DF5CAD372EA8FF00D8883A94A89000D728C88D39659D7CC7C74E5276BCC00D02D4FA5CF76FD17CBAA6CE947712086A0F263C01E34CA978B6EFB0F6D68530E34CB96C4150428711CE54796799E7A0D69D4DC7A81DC2A2DA13437E5E5C1C459B0D8C9921695A54A4B3074D0D29F8A7ABC630C5360B66AF5D5ABF9532A70AA494B29CD47EC69AE62954ED0144B816D18FBAB3D5F9BC5D367F89F1D2032671090D42A3F917E7E861E615B2983E1A84348C1D91E19399613399EBF4CA220E5269ECADA29B10096AF1EDE5C1EC6338FDBD8FC5952CE32690A006E8592035D867F9B0353191F0B7F0FB3424218433000C921307A65E596A2333CC56CADA2EB3F532438A13C46BCCBF168A1ED44E2B144FD6A5139972FDB950EB43130ABE4B878D2A949D0C920C7791E5E9D6A2313B4089CDBC40A31A01D736D0657E310E9C1AE582142BFF0090FBF3A57411E7E2BBFCFA4FFE54BC8C7B8037C971AD2FE7A0E1CA364E15C394D4E8187663A738F1AC4494DD28A813645AE1139FF508E28813CBA7AF598C3E31D2FBD40CFC3CF2A071EB18548DD5210515980B280D3A6A6D719E70FF0013C45855962188A9C436D5AE1B76209E1054E5AB894CCC892AD273FA54CCBC5216410A601B3FB72F6F084DC229081288256B25414452EE413536A7E99F9A9BAADD46F776DDEC6319B7DAFC4300D97BFBEBCFC33585DF3F6D78DA1372F2547840E01C473491320D4EE1B10552DDCD05CE63CABEB11B88409738241B268466C1AFE7FB8D82C07D923661929C4368F6CB6E7682E78F89C6B18BF4DD5B13C52470A84F01E8796998CC5CF0B046E9AF6FCC6A824281A1E7EECCFE90DB6EBD9D6DB04B91B5FBB0BB7EDB14C3CB6EDD5936B0965696C26006DA01454A4A4954F5EB4C572828300F7A69E96BDDE838C3B94A00B29802FBBC75CAB57B7EA3316C0EF5AC31DC22D70FDA6BB6706C7ECC06556D72E25872E5685704210B3C4B242499FF00CBBE6CD783DF0429E868C2879963C837385A5CB085A949AA660FA83580058A5ED72FC6B6B65DB8BA61EB6FC438461F2907C673FA485240C9415CF88099E73CB96666CE64394B1ED91EBCF4AE51A00259500A33534A3EF10E73E3D22D6676A2D97722C6DF86F94494F8EDC3A91DCA81073CA0EB977A80C5E1771C94BB3D4873CB85BEF710E08702A43642DEFA45E2186EE59699B8653C4C7BC97169120A8F16455D34D3BD452677CB5005E97229FDE79757786DBDBAB528289DE23E97766A503DF9430C45AB5B80953A8B7B82CE6943802A39E999E5DB3D3AD4A49DA3BAC1EB70097176B3F47CEBC6164EE8496078D03D73D0B0ABE4211670966F909BD0D2592E65C0D27850383DDCA3213FAEB066B49DB7F13294532D4B6B80096F2F2F586FFE62649F9656481404B392F6AD1AFC9AC21E7E1DCB51EE072120444FC2639469DB3CB44BFF0052634577D63AAB97DE364E2933AE4115BDB4E3CCD0E9A3B806D968E271A74BE7252B8667391993CBBF291DEB7FFD478C5172B9A49A9A9E5EFBC2A12B2B2C65EE64FAB572BDADF984D572D5B49517929EF97DE9D67B01347FEA1C633954D1CC9D5BDE5C6154E1173582370ABBB926AF9BE94072AD22D1C6378585618E38CFE29849464438B01C075CC4C8F3D4CD4D60E79C523E62CEF28805CBB8E64FAF03689FC0783F138C489C6429454CEC974364CDABE678674B5BFF00763669C70A2EB16B76C4E85F48F3CA7598F2E5CEA4E54B4AD3F5915E7951B8D5BEF944B2FC118C949DE95852A2057E93E54248A8E59B52166B6B366B10B8371618DDB38B7238509B84418906409F2D7BD34C6E191BA4A5493CEE08BDBF711B33C338B961A661A605077210775F51A30ED487779883CFB7325F6CE60A254387288EC00E474CE7AD371A8DD51AEA2869A55E9534CAA5EF1098CD8F3A5AAC6EC41151A7DC1B8E516FAD0149242383FF00150F7A679888CFCE2A384A065920558DC3D2AEE6BF8CA2CBB35065604A4E8589C9AF7AF1B54D2B7888B86CE720F68F9F7E5A7948AE41E221FF00F60A615DE1956E1C76875865BCD038977A55F3D03D7CB586B7486936E841C94E8565CF2E994E93D7E02AD580504ECA4B962400E4B661AAFC34CDA2D38652F789BEE07A1B02C34CFBDAF58D58F680B05B981E156ED82A0317C39413131FFF0020C2A600EF3CC65F1F40FC079C3FF51E140723E627D79D85F93C50FC533184DD6B6072E55AF677CE91DBCDDC2148D8FD9D4AE4286156120EA3FF0088D083F7A57DA1F042F7B6361C1B89693E498F31EDE2FB426E5C0E51901BE7E9FAD5CA21A14A20828820A20828820A2086ABFCA7EF98A208A9B5A528009CE4F4FDE88214F151D7E63F7A208AC104023434411ED1041441051041441051041441051043424176648198C86B33AE7D4F2E9CEB72B0894544380FDAAF9D73F758D0C82A0082C9258BF0E9EFBB3779B511023EFAE63A547CB5267853101DED7CC00435BCA1DC8099742483C34E141C9F9DDA39BFED41835E607BE3DDA6D6B4EB6C61C1DC4538A3CA5148056DA1A652B50112A260126BC81FF509B3969C162D6038DD57A6597B7A068BF787A6A0A65A7526FCCB11D0F1F31190F12B9B775A17691EE2DA69606449F701927A1C88D2457CB9C760D5336C4C0DBBF5AAEF5B923F27CF5EB3B26515A5082012C4D4519B2AE9606B70D9C5A0AC45374B2E953C8493010080070E472D0091CA399EF50DB492A918829776A1BE8E34CB5B6978B0AB6792948CF403882E4DC71E368F5174EB47FA086951A07733E797AE82A3D33560BBBF7E99F2EDCDD05E12623F8A95517724654E068E3D6137311BC5288710C0573E10A803947783D065DE9D2316A0C5EF7735D5B2EA75ED04942D0485134E3CF2F7A9AD2103E2BDF9A00EA24651DB3F4FF30B7F9A3FE4D4362FDDCF4A3FA187E89D2401BC0122D6A7BB74891B674B6D21B3991327E7D4741F604B398264E9856282B9D6D6D5F5E995984F54A2B200FA4D8162EDF872C7D21E25D52A20FCCE5F3E54EB0F2660A9272A039D2E3803ADFA4372B969A048ADC365DFDE9155BB6A40BF796B4A9A5A99F1500CAF2309CBF42721CF3CE730C85B5DB9870C2CFAE9979D5099889614974D43B1614F3D784629DF6E3589E15B2D6B86E08D3EE3F8DDC30D071A0541B6C5C212E874A4C89415012623BCD4D4B0A29156398A86E9F9BEB099C54A24EF2052C5AD950B9CEFE958CE7B01B396FB31B3369875BA43695DB34E909007F51E425C72748256A56B9F51315352710508092EE00CD83E79F768AEE38A553B7921C39627B53F079D69177780855A29859515924833A664FCE69C22782C5CB96BE7CC72D1FA43505887EBEC7DB9437B4B336CD3ECA5280E5D0212A0202A27883A4EB0321D01D29F4B9C802D7B161C2EFEEF6CF72B0552D4C92106A186F558E5E75ED5235577DBB97631B617B4F845CBF8663F8105DEF0DAAFC2B4B82DFF0054A5600E257BA888E67999A5C4C964592E320C395AA29A3BC3B46252E096034F646BD838D2301EE877C9BC0DF862F7FB2B8AD85D61786600B4DA397A869D67F121AE26F890E1252AFF008B33949351D89DAF2252BE4A83D2854C683D7ED0FE561C4C47CC012806A4B004B9A51BA7946EBEC761385600828B6538F2930971DBE292BE29CCA5423E27B557315B4254E2C96009B5B56EEC6E358557825B10028D1DC697D3A68D9BBB5ED717816E908754A49009F0CFB9CB4CC75F2F4AAF4E214A56E9A1B75AFBBF0D2139781536F14B1D0B057BB71BE70DD6F2D078ADDB6564EBF884C83CA323CF3A4521492E083ABBD7CB9C657842A052EC750A63CEA29A5B5E061DB6FADC424BAE1B75FF007376CAE06939EA94F53CC9FF0034F913A40401365A49D583DF577CBAF48899FB216A5EF6FB816AB13AD73EF7CAD15A956FFDCFDD93CFDE1CF5E7CFEF9D6462304A1FFBA1FF00D21F857A5DFCE1B8C3AF0EC93522F99F3619F9DF449DBD62C9B539E2385B482417152729249CB972CB2E5DA4B0B2B0B394375294EB4039796A7CA27707865E2421294A4A945AD5B81CF51EB9BE9F6FB77D69C14AACB0CB974DC12A48F097212447E6820C67CB908CEA613B224CD62025AE73D2D567B768EC7E1AF8798DC7C895304B092A624B149BBD69516F2E31A5F7DB73B418B5CB97577885C7F5CCAB85D564341A9CA408333967CEA4A5600490C94848E54AEBE5FD8AFA07C3BE07183C32244E40DF005C71073BF967A88B2F16BAB9BB928C52F50A339F8D1107CB9E5D35A7024EE8259C0EA3A53DE516E1E0A9332A10914190CC64F5BBFB7885636AB1ED9CE1559629882DE6CC92B7945A235CA35CBEB03AD31C44BDFDEB56874193D1CD731ADCE510DB4FE1E7CC967712900E5EB460FE6EEF6BEC76E6BDA4715B9C598C131A7D0E71A90D85BAA247432547F49CF5EB5E9FB326CD5B83726EFA3035B37E291C9F6E7C369A9139611500ABE905FE90EC32A8B657B88DFD62F59C518372CB8D28702567C320A0F1267239E7F669AED7D98BD91B3D78C98A1BA12E4039364E19EB4EF58E358AC0CCC22BFC7285A194B1F58666398A366DC18EA623DE09530A7828702499139C831A1D73FA9E506B814EC4276CED4299043EF3026E58F0EB7616EB17295F2A682A0487BF7E0DDA2D8BB4BD78F5BB8CAC25A649E34A8905526047A83AE9E622AE188C1AF66ECE0998090006A386A3E6D5E80D1DA2DF859E9F944D015062F7E5D88B91768C67BD2C1BF98BFB3D874B7E2E25885AAEDF889294FE1AE995AF8F2241201881DF38AEEBFF004F928E2F6FE0D69240F9A1C500351C6AC337E51CF7C52779334BDC28E55615CBDE79C760F64C26DB01C2590326B0FB341F34DB360FCE4CF5EB5F68FC264E1B64C8704FFA48B0B505A8DA0D34A5BCD7B4D0A998A98A51FA8A8E766367ABFAC5D68706700998CF97EB5615ED1DCBA559D0073F6EF118A94CCC4679F2E1CE29FC5B61C2D190A1033D331220FDC73A25ED0130B00DA960D76BFEA115324B13DE9EEF15A9F4A53C460F9199F21F3D6A4E52D3303EF2453335B69EFB422B9BBB6AF1FEED9E45DA1A7F32689E11055CD23F30E922644F2A6B371699733E581BC750FEEB52D0D958E420EE962AD054F5B0EDF6857F1CCA44AD40189099851F2075CB3E54E64A8CDD136BD39E7942A9C4A5428CFA77E3EF431E26FDB5202E14892442C7BDF09EDCFF00DED35489555CC401997B35DFDF9D21ECA96B9A010186B966D0D5DBF69394923E9CF3D62753032F8D42E2F6E60B0C4838896FA6F0A7E7BF0E21DA706A2CF4A805ED5EDEB163E37BCFD8AD9E5BAC6278F61CC5F311E2D82AE5B4DD278B3482D28C891046B919D2ABDB53C73B3B6661158A993659003B05269A67CFCA1D4BD933A6A884A084E4A214C75620D5B3A44161BBE9D8DC52E536F6F72A1C4603AB52037F107F59F94D3B67FC65D918FC60C2A14872ADD774EADAF06FC52313364CE96E4D8396D00E95F7C5B2A5AE316370DDBAADDD43CD5C025B79B50534A2333EF75D0475AEAB86DAD2715864E225AD242802038CC75E76E05A23CE1D61DBFDB70D51CFDE9AC488B8495A91C2A1C312AFED33D0F3FBE944BDA895CC0862E6D415FD18D3E529897142C469ECD2D9650AA161C4852743313DAA550ADF4856BCFEF1AA925258DE2BADE35828820A20828820A2086123C4E1EE0FCCFD8F5ACCE1FF00F156AC8053F2F64FA43A425E50E6A3D89A428540850E9233E7F647D399AAF6CC9CF8B32ED555FA9E1A8E35D1A358D3FF006C4D89BADABDD4E309C212A38EDAAAD6F6C5C6C1F150DDADC26E2E380A4710E26DB2150340796BCDBE30F860ED6D8B895A51BE4CB2ED930A8B708B46C09AA1302033259DF4539FEFBC6B3EED36C5DDB5D82C3F145A8A6E380D9BCDA8C14AEC57F8658209247116C9CE67B57C89F887B2E6787B6B4F985051B8B5D5980ADCF3E9A976A76FD893D9090E1DA8721916CF83BEA06513CBBA0D2CA262232D27FC6A3E72753C6315B4FF00C99A5649356BD78B67A533F4BBCAFAD00D19AE6C47BA7AD6176EF4883C5A77E5A473D24F61CAB444D2A65025F424F2E1FDF9EAB97BB4BB54BDBB55BBBB370878973C44858D0E99F2FD29E4B9656C5C1D4E9FDFEDA192D3BC4901ABCADAB663FB7BC3E6F9FA73CF2F59E7AFCE9CA70FBC452D5200BBDB27D32F586CB96C5C9BE41C9F4A768593F986BDFF00CF6A7689252057A1EB70DDA13521245125CBB96AD3DD38087CD7F6FAFEB4FE4A294E14CEE7F64F610DD520B12417E0FE6E3216D6247F061865370A59E1BC30533A701811A46672CF974A9995294102A0939569D1BDF488D5813173129FE528FD593BE6D9BE79C4D3780E137D6ADA714690FF0081EFB256124833C530A079C69965E712B225050AB06A56B57CCE6D9BF9B888EC42E682844A40512FBC482586AF67A9D6D71130CDDA14D27C3F7509F71232FCA9012072C801FB73AC295B8B24F2D1E9E8F73FD420B94490141DAA684D4FA7AF2857F140F3E7CE72EFAFD3D2964CC0082F4C8034D6C4FAE67A468A934A22B4CAA7DFE8DE28BAB852916C5A265B52B8C89CB88C0075EB3AE7C8D3D44D06A08E5956C7B674849324EFA8A92C0E4CD6E6EF6B8A33C597BCCC758C0B6471DBF7D21C1E034D2F9FFCF2D899CB32AD3BF5A5FE6EEEF68D972D5FB3539C6C892920100DFA5FD9ABC61CDCDD8E0D856CDDBBF86E1CD337B89BB72E3CEA1A4A16B2A794A0544004C71644C6B3E74EDA7337B12480CFF6D3DDB47A58F092C19037CEE8171950E63A17E4632D3ED356CD169D584BAE0924182273E79F3CA7A79C45C3E94B2B53A58CB1404B105867F76B71315D9AD2865012E7880490BE2E23A9E7CFA72E9446CA439706BC7DFE624D2BE21A8FB3CB5F58F5A21BAD172C5F30D78F7C4299CE008D4F5F3CB2FBD6929A58022E3F223558019B378497759812353399CC7C40FACE79F3A6C92C41766F7E578869D27E6CE600D081ABBB0E6F7D2CCD420617DEFEDD1D98C02E4B6AE15B8DAC20E801823B733CBA4198CE7F674D4EF07BD1DB8364F6CC9EFC3A5F83B63267E224A948DEDD62011435A3DCFBAB54471EF6A77818A5EED0DC397CF2DE6DD795C3C4A24264E838A6047FBABC60A6A77413502835E75BB79B5338F69F823610F91246E00E91D18662B619674CAB139698A85DAB6A27358EBE5940048CBB4CE841069FAE68D69975D72FBD62F58BD9CB9135920D05486D1FD8D6DA9A1CC450264881CA673ED32232C865E7A4B45CF21C034550B5A8DC79EAF0909CB9640215A501A375F4FC442DF620C2D21B5000AC11CA67965D73924D3499358904BE6E3F2EDDB48C7CF5CCFA06F1D3CFDF73CB155F3B89E0D8EB18861EEADB8702814A8A465E519C1E7AF3EED953774850259E9A65C73CBCAB0CA6EC59D892B265A88502EE1F5B5EF9F28EA0FB3DEF06F719D9962DEF1F5BB7496F85C2A5126048124E790D0CF3ED3517E319FF0033C3F32593BC4A1541A3E94F6ED78F32F8F7C3E246D09BFE9EE904D8354BBB5FA9D2F58D8672FDE369E0824159EB1A9E59F9F502673AF37787E4997B5F79882262A9D7DDC8E2238FCDD9C5134FD2D66A3356F5D21F5836AE04A543DE57BDDF298F9199FAD74DDBDBD3F05BA1DC8038E55E3FAB343E4C8F9729E808157A0FEBD8BC634DAFBCF1F7A3BACC178A4DE5D5EC26419F08A17CB98CF96401F5EFDFF4E3B3CCADAF84514D3E62090464F5AB797A1A8E6FE279A1299AE4FF0015371A1717EF7FCF607086FC0C36C520C14DB30982607BAD2464272F8EBDEBECEF8551255B2E402104FCB450B3FF0011CB4FEAC3CCBB571E99589526BFC959B677D726B696313CDAF23319C4472E994F3A9C9B8390A2019690CF50900F2D0B7AE511A31C998FBA4022A75AE753AE55EB0CEE6CCB8A53ED28A5460C1ED965EBEBF1A6337032D03FD30D43EE9E63918CA4AE654B9734EBFBCCDF934276A9712541E54C64028F2CC69F0EFF00AD7F1188998759FA983EA476D457DE4BA2402FBC2FA5DC7EB514E358A14CDBB6FBCF209F117054A5C78420671CC77CF9F7353B85C6603FC713710B921412E4A88DF06AD77AD3FAB16EBD9614B2B4A4BB50354B9C83036AE7D59C595B51B6FB29B3D6EE3D8CE2D66CBCD4C34CBE80EE5FF8AB9E407EB54BF1178FB66EC996BDC9F2C14BD4292EE1F9578E6D9C49613642D44028209BBA73A3DBCEDE51AC5B43ED3570FDC5E615B01B3D8BDEDFA484B18B6296BE2604E28C66879B54A929D164686BCD9E2FF8ED2B0DBE9918A7237836FD2828CC781351168C2EC898AFA0B849008DD05E9AE8C6313E26D7B42EF0093B5FB59806CC60EE199D8EBDB9B3C4D0D13201E3F74382418D2418CABCD3E20F8F78F5CE9865E2E6B026D315BB7E05BD2968B061B6484A424A3798DC8ABDC3D9DDF99A42DB3BB9DD9AB4B858C471DDA3DA8B84C156258EDC22F2FAE179921D78895250470A33C911AD72FDB1FF005098AC4C95E0A662E66F12410566B51C74CADC749D93B31A57F1019E940DCBAE9190118260B875BBA9B6B271AF0D24216A692932260830232D620F3E951BE17F8AEB95B4E54E54F213BE2A554BB3DF4634CF9445E376728021208CCB8F5A1A643A4671DD163CCE2B84AF062E14DC614A511240510E2CA877D079F202BE85FC29F8928DBD230D86F9FBFBC121B7B80A55EDC8966B068A7E330E641528A497BD1DDADCFB53A1319B5DBB52ED0B4DF10B9040274300C1EF981F3F87ACB666CE44E948C4160E01AD19C6B6CF47E0D7AECD5942DD2D5720356D502CF7D2272C12B45AB6173C512675939E7FA768A94284CB2509B0B7BF7CE1B6FEF926BEEC07010F2B119828820A20828820A20861C12E13A1E674CA75EB39E5E75B4D27FC75268CC4D79B81C896A71870957FA613C4F2677EFF00685384F14E5DE3AF38F3EBE7EB5AC14A54AC5FCC66FA89D2845001DB2F2A425314C014914BD788BF9F3D0C59BB4B602E59BC66E528751736D716EC323DE243CCADA59E13A81C5273981D00AB26D1C148DA5B2E6C854BDE3B8ADF252E1CBB0E4F7B75B895D9F89DD5A595BA1D2E41B91A17AF2B7511CAFC2D86375FB7D8E6EFDF4A9168E5CAAE30B5A0016CE97D4ABAB84B44E4A502A85009FCD97535F26FFEA63C1ABC34FC6CE91288AA88094B50BE5C3981CB3EC1B0F1EF2A5A8029A0606ED9160FA96BB01D22FDBC68DDB8BBB62196571C2DBBEE39EEF320693A8D6441E95E024E166C8529131C292A21B2FE5C6B4BD348EB3B397F370E8A3EF5C9CB3BE74E34B81110C5D715C7E1C1293A059C9073F4CB4CF28A792533010E6CF42723CF89E7120A97424B74773CA95E462EC6141A425A52D2B52466A4990673CA796639D4D6186E9AB16CB5B96F3F2A888F54B5281205C921DDEFD7F30FD1708E60E71A67F4D73CBE93528898803439BB71F6DA57386E517240BB54549E14ADA1C25F4710C8C7A7FAF9F4F4DBE6A29F50739387F5F48DBE48527F890780D0F2CE1EB770811AE5DBAD3C9335096AD7C9BED7FD6A92A4960DC7A5EB4B509D4758A96F5DBE0A78D0184478024C833EF710E5273CA321E553322685331D5AD4BF13DAB5D3364BC3A0951090952BF9716B1A72B73AE9376AFDCFE1C21F7029432053311A419E80F3F9549CA98C28AA6A48ED66EB7AE70C57242545D00306A0727F35F28789B84B00340CC6A44C7BD04E874D35CF2A8F9F39A6286F501B8208B7F41AD0CA6E1C95380467D3806D5F8985C5C9390933D24FEB23E535AA278554AC86B0767BDC7F40469F208B247507F07D61CB2E10D5C051953BC3E11CC84C6B33A03EB4F25CF600DF4E1ABDFCBA36692A428A907E9003EF0CEA29C3C8C5A1B65B3EEED5ECAE2F81AD683717EE5A2995289F0D2961E0B7028E664A410235269E23140A4835245079675E3E5C630A9133E6CA28291283FCC16274A5AEFF007BC31C1F046367916366C2521BB26C2484819A9491C4469CC4CEBFA56B1CBDE9E55A9763C35F7E64C4C4840548521CB960F6039F9EBD225AE116F7772E3CFF0019414C2008907860C8D333D34F9533A126E3CFD4F9F942A842A5CA084B120E76A9AB7AD7AD629B3B12CB094215EEA492924E704CE7F1EDEB58850A80A1BE6D6F387801403C5CB90CE33A234242886A1ADFF4FA43776E005409D739D065A9E7C8F5CFCE91981CD5D8B5B87F5E70DA6A4EF312472D381E7D793C473B720716A75D20E639E5F12338D7B068A705B8B3FB7A9C9FD690A6170E14B0AFE4A7140F4FC5AFCA35ABDA06C9EC4765AE54D254B752D2CA12904A879C67CA7AC75A96C34D4A1282097CF362F9DDCE56E2C2D1D8FC0625A315BAA01814B3D32A803BEA79C7212E12E5BE2B72DE2E859525D5786003900A233E2D3CFE11955B30389010904D40E5CB91CF933691ED3F086270E8C3CB48DDDEDD00136AE65EAD66FDD66EDF1342521014AE119252341DA35D0C1ED9F39A915E212A1722B4C9FB9FBDBB474199814CE4FCC74AF785C5F2FBEBC3524BA5DFCA09D673C8E7AF5D3D3E3CA9A2E6E76BB1CB4BBD7A74AC4362364EF1748CCFE3B353AD4DA2DBC6F114B4D32E369754B24CF081C880200A69367B8209ADBE92FA5DFDE8E23383D8A4CC054906BD0374E56D7998B5B10C51779E1212E21B724407494F4D633D20F6CE9B99C4B24292C3F8BE45A963AE917BC26C992894EA4151DD3FC402598DCDAF993FBDEDF65D45DB2CAFF10B4389584F096C92233EA0E7A03976279D43EDB9DF3B04B94A2E7748615A1D070F4AC7923E2F61654AC76254801201A0CC6A1B91E0D1BBC9BB63C4432A42F8D24498CB91CFE73D74AE4B84C38918FDF0199449360DAD6ED5A37DA3CED89967F9298BB8059F9D4E608EE0C5CF66A0FDC80D25442000531AF126065CC08EF19F6ABC0969C604A12E4121F3BB120307F4BF3888C57D3208240556A6C1C66467A6BDA30A5DB2BC63DA7F74F84DBAD017833B8AB97E09C921DB74B8D822352065C519E5A44FAFFE026C6323178599BA2AA15E3439F3ADFCCC71DF15CEDD4CD17A299893ABB5A9AEBAD44764AC5D53EC5B0692B090DA119CFF0062129303331918EC62BE9C787538A4E1A4EE9DD0501ABF4D0545FDF91F2FEDB96B56354966FA8B1ED9BEBF6CE9131E21B74A54EA5652A895019274CC9390113FB55C7FCC44A40F9EADD201724D389EB7F4D21BC8C2CEA50D6E75F77E19EB0D6F7136ED185DD29E6D16A94951714A809004AA4E8204C98CAA0369F8BB65ECF96A5AE6A0EE8352A4B5B57F2BF78B260B08A528259D4726BDF5B0CDBF6DA81BCEF6B2DDFEC7DC3D63678BA31DC59BE248C2B067DBB8BF5AD23F2A590A0A2A9CA23E735C47C47F15F634854D1F3E51500AFF00724316A06CBDD2D16791B2B78A7E8AE6E2F67FBE5525AED18A99DF26F8F78D85A2F706C39AD98D9FBFE34B0C630D5C59ED1B484129529F4A4F08E28E264FFD08EB5E58F1A7C7FC461715324E1314532D2540042C806962C4D19A99F38B1613C3E850F98505D4CC08A060D4E3A33F286F83EEBD8BEBAFE67B578E6378A5D9505AEDDEB90FDA49CD4025C1307CB3115E72F14FC72DA38D331271733EA7702629EAF70F6D74E959895B11200013F50CC870391616D7F35C9EC5AE0B8484DBD85A069A68421A4B690D891AC72922550333F1AE3D8CF1EE2B684C56FCF242890C55EA0BE60B3F9089CC36C800074017CAFCAAEE39D3562F0E9788DB110AB5682644C204FCCC44763F2A7123112F1A9798A1BC41CC568F6F7DA2451B2806DDA13572EC73AE75D1E0172C3612E59B4842B4571244667B69ACCFC2B8D6DAD9D8A5F889A4AD46515644B014E9DDBA64B0C1A93BC998DF5301BB6A5C97F4F2CA29BB5BB7C10D9E042345F0E47399024F3E53AE5E553F324E2767CB4CC0A208DDB38146D19FF3A986B88D9E8520B3922FBCCEF6D2FF009B45AD866D07FF00816D93174DAD630EBC75B4DCA947DD4121284F88720389648483AC7781EB3FFA7AF1BCDC36D4C24B9D38A46FA036F367673A80C2BD328A16D9D9EA017F48200A86AD7FBAF08DE3B2B862F059E20CA7DC71A42DC1A95788D8292206866467E55F62BC27E24C3E3763C9226254F2D1621DE96ADFBD41BD0C72CC7CA5CA5949AB6F55249B96E1A75EC22EB654168E21224CC1D469AD5A02D333EA4D8D5A1ACA0426AF7CEF427DDCC2B598560A20828820A2082B06C791821B05242B965ACC41EDE79D42A3682A6633FC32490F548371715360F7E02F585424945297AF5CFA450B751060C1E922467FE321E952EB929952D5319886AE43573473AE7CDE184E594AB749607372DF80FF009EB6E5EDB3D77885BDDA4AB82C82D2100E4E0793C264660F083F426743A61B694B5A6648762BA298DC07760CF5F22F9C3BC1CDA906C0E5AF63C99FD446897B5AEEC2E7F96DB6F0F0041FC7ECC3BE290D025DB945CBA90E8570895042279E4267515E6BF8D3E0346DEC2E2A7225050285127774196AD47C9E8D78E8FB0F68D65214C145986603DC8A548B1A1D230CE01B5B6FB5383DA5EB2A0DBEB425B76DE785495B4036B0539C4A924C11A57C9CF1F7857FECFB6A761F7373756A04377CAED6CFBBC7A2FC3A913300958AD03837A8E0EC4B6B571138DD9A5E1C208438661472332799CFBF6F49AA22B06A975673477C8E6DF819923368975A0272040AD9DA81DD837F50FD9F12CC780EAF8968CF8A7AC75EDDA0E99CD3698B12AE403CFDBD5A90D16029F75B81ECFE90F9AB9194E7AE720F5CA333EB34DD5B458DDC73FBD9F4E8E2F0D148214D523337E8E58439173A67D39C65F1CBE1E95A0C7392A05EB4A870D539E661DA255052ED762C391AF3878DDD6B9FCFFCFEBFAD3E958E342540D01A9B599BB1B5A34561F41DBF43D44495BDC7BA9274CE7BFAFEB9F99A9AC3635C02145F47CC11F8A54654786536433D393367E9E96A65128DDD8C803E7A09CF31A7C797954AA31E4A4EEAAE2D4EAFCF817A3F0862B906A4D6CC19ED7EBD61D78B2AD411E93F2314DA6620A94589B9A3F3C837B7864B94E5ACDC7F47CE1CB6F0C88C8C41981F4394F6F2ACA67106E7AFE7BDE8D7D234F95BA2C0F9935E5587497A10003ACC91E7E83EBE95212A783572096EFE9A793BC226555C01D6E3CBCEFDA00F1D38943D4FE84D3A4CE049A654D7DFB6307CA1C3853DB432753C6E295EF13F1F8EB51B893BD3093776603261EF8BC399602502A2BD2C4DB9427E17657C3FC5378DDC6A3B887CC8E16D23CF5F3FDA8845441510F0939A2BCFF5A05481AC651FC875F4310376E70BAB13A46435FAF7AC4C04023DB3DF85A1E270E26241677AD785743DA2356E8D4188F3F8CFEC7D4D47CE21CD0E556A5B8F07F511ACB0252EC03721E963CFFBB5F1FC1DAC5AD5D6AE1295B6E2542089047DE9F104D29869E1EB514A71CAE0B71EE0D62DDB1B69AB0D325AE5962935D4E7DAFC1A39E7BEBDC83AD3AFE2B86DB10254A8424C19F200CF4CC7A4D5870D88DDF50E73E5CEF46E3468EFFE1BF1B7CB952C7CD3BC00DE0FDEFA79E6F411A717D8662B862541D6821482AE20B0A0A80729D397C2454989E4DCB9CF3FB8D3FBCBBE6C0F19C99D8742553379D981555B817F2E76A45BCDE3AF070B6E96C198304E506273396791F5CE915CF228E69535A7077E1F9E57EC26D2958A1BC374B805C31E9F887AAC6F0F527C2B9E052849311CC4E527EB4DD53C005CD4D8BFEFEEF6A343D9B889724198161219F260D42D4F7E96D59E10F6D26D35ADB5921D4B2A74090232C8F29190397C2A3CCF24FF002163AB654CE8787E220F15E38918013126686014012AD417A3F316EBAF55F727B14BD9BC36DDB525521B4A8920EA44EA40F3CE464072A87C5E20A94506A05186B9B823A37121A8D1E56F88FE2197B5B15366214FBC7573F80FD684E95D86B5B22FDCADC1C86B1D3F688F8E7CAAAF3E4EE2FE6002B91777EB98CAA3AC713C5E2D23FD304BD180234A9EB7CE2E54307C36DEB7716D2D869F72E14150901B42949923B2753F2AB3F8687F938B932C1FF700AA0A694EAE699935BC436227ACA666FB1410C9003A8DDE8F95BB691AE5EC70FA7783ED65BDCC72F9D7B10B6D947B086F0C57178ADA0BF6CB6DFF000E4103310A098D3CCD7D0AF835B351253859850E06E9A0B97D2C45B331C5FC64A56E4E29504BD89341C0F3B6763CA3B5789ED2E0DB3B64A7AFAF2CB0D65A4125574E2590001275204C011E9E75EE3C3789365ECED9D2D33A6CB42D08662520EA796AED1C706CA5E2A66FAA5AE639A2921D357CFF005ADA91A3FBD2F6EAD8FD97B97F66B63ADEEB6AB691D516996ED128BDB52E8C802942828827A6BAF9F16F1C7C5FD9F804CE12A7241485070A00F30694D6B9F289DC2786A615552425814900D35DEA368D4EED1AD8EE31ED33BE7BA2BDA67D7B15B2B78AE26ACB0455DE1F88A1854487DB54A01524F4820FC3C57E3BF8E789599F2B0F8A5D94C02C80C5F27CB3EE6B16BC16C192809594A41A312056ACC33A722DCE329ECBEE5B77FB20DA6E1786B78E63EA016BC571665BB8C483BA9525F8E3E29933E43BD79536FF00C4EDB98C9CB32F1338A544827E628EA00ECED7358B3E1F62860771CF10F40039A01F7E228D1976CAF2DAD2CDB65D0AE36C11FD503C4009F7475E102027B0C88AAEA36D6231C8F998A9855354FBC564953D75A677CBC8CC49C0001212C4021BEFD4371A5C0842E3681B40842608F42627A6BE7A6994655178BC22B100A92C49773D684D6A5C7A7187C8C0A52E48734A016167A5AC1D8171D61A0C40DC8F149E12A9CB498819C93AE5FE62A167603112BEA028330FDB27B96F505E1F4B90909DD0C40347B8A934CFD34D63C37103527B020F61F5E9972D2914ED5C66114005AE94352CCFA5FD87857E50C9B3FF006FBEB0ED9BA1C31391981D0CF4CF4927A6B9F4B56CC54A992C63A78057724EA1B335F3CAF1133E6A513B74F604E63306F6CA9A0AB8768BAE1E124E5A723D758F803CBE34DB6C6D2C2CF96654B6DEABB52C5B57FD8D03467E599A9DE48398A3BD19B91FE8E4F696DEE12BC6B66F116AD65376B4B772DBA9C96855A10F40234E22800E42454C78076FAB63ED492B0A665A58823506B466F7A9883DAB800B0A7191737AB68F97172348CEBECD9BC73B6BB0D87AAF9D42715C2D4FDAE2ACAD50B6C36EA99B62B495482A4360898CF3026057D6FF0081BE2F5EDBC1E0E4098A51DD4821DC0343C1C1ABBDF2668E3BB6B67FCB9AB601D4AFA435581ABF106D71A3398DADB6585B414233E9D394768FF55EC9C34B32E5A42AA77479811525A0CB5141B8F7EC8A438A711A414410510414410560D41E460862B695C648227F7FDA7FC72AADC9D958846D6FF309FF0049CD896A0CC7EF3E30E12AFF004F745EB539177B7A77E109780A05464124CF9F3E9973F972922CD8B989561D72C36F100303D5FDEBADE3A7C92B5022BCBF40DE1838CDE36FB6B6548F0D321C4A89CC1CB2F39EFD472269D230389978BF9A15F4B92439AD6BEE96EB1B4A1F2D41CD012E06B959DF96A6F169E3BB3CF63AFBB657A8B6770479A710F5BAC152965C6C89283EE9851907D6A5F68E0656D0C22E44C46F132D40821F22053ABFF6F162C26D64480192833014FD4431605DB514B59F5D390BBCED96C7370FBE1BBBEC45A5B3BB4C5EE9B187DEB69526CF0E52C00B4DEB86196FC57DC096C8D4E4649AF9B7F1B7E10E315B5F13B4E525A4EF2D4285B95B864D51DBD11E10F14C8998144B0C16000A4E85C5F893972BC64EC531469DBC63F95BA8711E1B4ECB64282D2EA12B49491120A4F5F3AF0FF89E51D8D889926602E85148E2DD069DFAC742C1E2062929B97772CEE0D998E86F5E10F7F18AB85788E4A565290A072208196BD62738EDA455490938D4EF21C82F703D1F2A67931D2243FEDFF4FD36353A0A03C0E674CC712E1A749C81CB399E594E79FCFA73AAD6D952F0153BCE34FB0EEFDE911F3B0C50A2925CD9CF0CC77AE5CCBC3A0F1CB3CE791CBACF3EB9EBFA536C0CF5626589801A9B171CCF2B5A9C328752253201567964039A5A1E36F19D4E99F7CB223EFAEB52B2D6A04006835B06AFB6AE42B4817298D183BFBB5FDF37CCDC840824C8CC4E9EBD4F6E644CD4AC9C49481EB6B65DFA529C58CE4D1C0BDE9F7F3EF126CDEB41241041904401033F97CA633315228C61490C6EC286CD6A397D79B5CDA3A6A1CD081C39B69516D224117CDAA08E20349CB5119CC79CE7EB4E3FCE4B80F56B92C6DC0E9CB943338770E01A92EF7AE7D3434E90E91760F2313D33D3B0FF0073DA9DC9C5A580A1275E15A55CB54EBA3011AAF0E4243379F637FC3F387ED3A1690648D753F7CA3BD49499C0B35CE6EC03396CF2E875A886A431208AE60C384852B457C499F9FEF520858A3B1247507367E7EDA34514A6E9F20DEFCE1276E034E14C4981A673D3EF29A426252A39823F5ECD23644BDF4024917E63837B2F0A25D2A12065E47F7A4FE582F7A5EDF88C19605DC3F11F8F75D0C2A1E200100C7A79567712C2A789F6FE4234F941DFB1B9FB7F51E195273D4E7F3AD0A085820D01D687DE543181F4AAB56D3945B778DA8DC2C83CF4E5EA0919F5A4A6CE480451C6B7B3BE6C226F0CA48949A3DEA00AF57AC462D0B920900721CC91D79FED51F35495367EF30E4728426618AD6A21EB5A1ABF7B71F286E0381D25C292DC0084A7946B97DE51AE7484B1B84B92CE2DC1D9E093226C92FBC79B906F4FBF631058DE1F638A214CBEC8532A10414827969397D3D0549C9C60401BC016A55ADCBD5BA67160C163A7482085356A145B36E35A07E3A55F5976EF719B338E3B746D5BB965C7408E04A12DA55C3CA0729EBF1A79FF00714121BE9A56C071E4F4E6747A742D89E319D83DD1366380DFC4D5C3F37F77A46B2621EC8370EDDADD62F8A5B5289095384119CE7EEC4F5E99D657B450522A2BDF3357AB7BE7D6763FC59C2E0D094CC51A001DEFA3D7BE94E30F2C7D929C438CF8D736EB4A0FBE56A25644F972D23E191A6AAC6855986957E1C39E5EA0C9E3BE32E0A7CA32E5BD410F41DAA4F3CEDC6362B633D9EB65F035DBDC780DAEE5B852961283EF01391039C6667B742115CF46E9622C5F869FBA1E51C9B6E78E66638CC32A6A92953B1DE6353570FCCFEA873E3569658682C30829E0425290008C9207FAE9D6A03138B44B9A4A8B819BD6B5AD0F3CDB368A64CC5E231690B98B2AE65D4C4E7534FEAC21EE1AFB6C073C549515FE58823312013991969FB53156225E2C89680429D83655B3D7D2AD4D0D7F152A615956F11C9C963A83C7DEB61EF676F86C86ECF6BB1568B366E61F62B4FE22E3DC2E9B86DC6D3E12841570A8C1D62BA3782F62AE5E225CF56E9485051B937D326D29E71133C94975294F50340E35F7DEFCFEF629F6ABC3F753B27B6F8A61FB3B88ED0EF1768EF880ED9DA8BAB7716DDE3C18F1085070A5285A44E6400790AF69F82BC6F81F0E61A5A6784BA11761906A3915E2FEB5E7BB7F64AF6829C12525DC3BA4E8E3576EA6368D9C2FDA37DA2F13FE77BC8C69DD8ED9FC45616CE0B82DC5D585E30C24884BF6EECA525C4F091C8C9390D281F103E37CE5E3662309885A6539000511FEDC803C433D468F0C703B1918597F2CA522F972D47EDEE1C18DB2D82DCA6C16EEACD0E1C370EC5B106D2957F37C4D969EC4BC4199587C0078A46473AF3178ABE256D2C7159FF226105DC95927851D9EF47EB5112F2F00898A094A149ADDBE9367761620EBD6ED78DCE34965F5B96B7B74A57BA1285B92CC0C824091EE819013CA04E83914FDBB3F1138AE74C5A8135DE24FBEA732F60D3B85D9492005212025DE9AE741DDF3ADA1156D23CE0F7D8B4E28C9C4A7FA82720788C67DA35F854CE071F805247CF92925AEC1C1BBF4D444A4BD88CA13113266ED7E97A11986AD2FC03666B0D5370BB9578AE2CA8AA4EB33197C8683975AAD6D19EA56349C2AB764B80C3EEC776D4CDE99461783F94ADD0000097767D437322FAD6249A6ED9413C62546072CC7D67CFE13562D95890129138953E46CD6E0FDE9E51A2E510E52D56BB9623F2FADC3C78B6C2544344840D04C7E9F0D2AC8B99859B2C83287D4340E3A3BEA1AB9C6C896581FA4645857DE77308159491999FD3EFF007E9558C7E064A945494A5817A8D33A574CEFC214DC2C6B5CB4E2F0A22E0275981D4F799E71150F88C79449560A4D1767B369667BF9718AFE27013264E2A06E5E9F6F60F3B05C5EA0260851D7BCF6F53DA3AD57D5B371F289C44C98A29772378DBAD8B11A3E4CF47F879265202564DAF535D3D8ED9C95A62B6FE33368E5B5C2D170875B52820147BC929053AE401CFA537C3ED9187C74948554298D58B83AD7AE5D03445ED259099891BAE59A976BF96675CA312EEFF1373751BFA7F67710BB6ADB6776E1D4ADB507382DAD956ACF8812B39252A71C54467C4A98CF3AFA77FF004BDE3593825E08E2541481BA0906E3277E2CE6BCAD1CCB6D23E6054C4CB1BE9A25C6B43D1AB5B1A56B1D4EC32E9A36CD80B4A894254983F99244A543A820820F39AFA7F83F1061F1F85978992C10509B35683DDFBC731C5A0FCE59C89A6B76F66CD5E53156186705104144105104144108A8428F9CFC73ADF786E367FB778502C2535CBDDF2D229A6B3524BF166E8DEB942714A913273CF9F2E43A5353F4D48A8EE3BFB31A2D05E82B98B1868E351390F3CE79761A79E9583894804B81467E85AAE6977FDC6A2528107773BB569E768E677F11CDB0C0F07DCC6D1E1D890B773107D36E709B25709BBBCBA43E92836ED932B0CBBC0A5F0E6919F979F3E2C4F9733033904228955DB31968FCBB476BF03E0819067EF2895EE9097A067BF03E7A472EFD94F7E3B59738633B17BD8B7B7C2F1A59745862AB4AD9F16D82CAD84F8CFF00BC4A58F0D10040564328AF953F13766CB99B467AC005D6A3AD09B5BD34B8CBBCEC492C25BEF53270C72A81AE95B51AF1BE7637A875A43ADBE5F6CF170BBC5C41624899C811A11CA32ED541D958444A400774024DEE2ED4BE5FA8BD26480809005402F571A64C694B0B989C6EEC04C0D7427940EB3946703D22AB9E2BD9E89A8580CED7E3477F4B6552222F17860AAB5791A65D2F51FDC546F805646349CC881CFB7FBF5AA7E100C3A0201AB97007134E4DE79BC252E584CBFA921C700FA0E95B707AC3B45F080273D73FD7B7EA741CA45130383E791CB2B7A084A64B241296B8A5B5D2997E9EB0F9ABB0A0924CEBCF9E9A6A7B7FBA7489A1C54B771F815FEE23A6C925C1A0E1EACDEEB687A8BA190904E59C9E646BAFEBA74A7B2D6E1F7806B3963D7D3F55868AC31277999B571CB85EF539DDA241BBA1C2923E1F0C867FBCFA5644C014E1C936A023A5B5E6611128824D9F5D2F461687EDDCE5F9BEFBE79794F5CA9EC99C090D716D43DC53D7F508CC94452A470E9DDBF312B6F78021327AE5273E5A7FBA9A913451E8783E76E3EF50D0D26C81739817BE7C06991E31248BD498D27439E60FA1E7CA2A5513ECCD4B3D1C77D3AC3432C66FD7FA8A16B4B8B9009273CFAC7A74EFD666B2A9E1CD09E34F7D237480031CACDF77E3A43969412224E713DBB4749CFF007AD7E790F4BDE9FB84964166637F7EB0E909073398E5FE7EFE5419CF93721FB86CB98C0B676D7DF1FBC2B5AFCCFF00E6F7D61A9984162F5D2DD33FBF3881BDFF00FB0BF4FA547CE72A249046447DFAFEEF13D842F253C00EAF58897397AFE948C3E979F4FBC377397AFE9442910F73CFEFFEB4411EB6CDB2DA05680A590413009E713F71442A852C00C12D567EBC5E115DB594FE448CB2C81F9E5F4A216DF570F388F73094B8E179A4008511000E913CE338144604C228E09E37AF5F7DA1445BF8060888E7C8F231D873EF44677CB3325B46A5DE195C3216EA960483107D35C872FBCAA1B1D24A86F11ADA84BBDDDBEFC1A24E44D1B9420062E2A03F4C859891D2156ED867967A8E7A89888CF5D341DAA1F08F2E7821AEFA675AB59FEEF0DE74CDE71955CE7C75ABD6343BDBEADF686FB61B67300C21D72D2CB17BFB7B7C49E6D4A6C2DB5DF32D80B52722085100284679F4AECFE1ADA2254B960AB404BD2EE3B72A9882C5A86EA998DB893CB8F95BAEDB6E13D983763BA3D91C1EE5BC399BFC5EE6C2D2F1C75D6997125F7196DE278B841FCEA3CFE3CEDF8DDB72E54B24CC724506F123A720F4D78D22B6B5CE9D34A10909961F7CAA8AAD8A69DCB3F3778CF78A63F6CC214E9B7658B8094A421A484A4250385B006A3DD007D00CCD71BDBF8E189C42A606AD28294B5F53CEB7D21CE1B00508A954D00BBA9CD497356B062FC39B4639BDC7B12C4D6A6DB754941910091F08F2E5DFCEA838E1BE556A963C789E2E6E35B5225A4E0C862D42CC0587BAE6F720521807EE6DE1A714A52D2249CC9839F3FDB23CF5150A6532AC75ABB6AE78FB689AC3E0F7402E920D9854FB2F9BDA3DFC6BA3593F2CBAF3D396835CEA4244BA501B1BE7719FA6A748999787DD4821346E8697B7AC5DB85BA576CD2944E7C53D400A3A0EA0F5EA6293561C99AE1D9C06722AD9E5ABFF00422BB8E4EECD239D0FB6D28E4C5C4C3A32391E93CBE7A8F4CA3BD58307240DDA0B5989D7954B573FB3121C343A99CFAE75341C000E50000504325EA3CBF534CF14CC5ECD5E5F4C6628FBFBF8D5357249C715815715FCF0EBA3EB1B265A58BA5B98D79E7F98F2419CC65AD48ED29DB982292C193471FA61CCBD60549770C082E2CC69D2E215C26FEE9DC41E64320B5625210B293EF78B32674C8FCFCC57199F8829DA454E28B198A07700D5FF004080F5881DA1856A549503571CFBB659D7478C5FED13B2371B41B2831CC19D533B47B3AFDADEA5E68F0BDE125F6DE7405247147828502274E55ED9F81FE269782183056032902A585C020F534FB6747C7E08AB788723EA7A38A70F77B3D6378B707B7B6BBC7DD86CDED8DA5C05B86DFF000772D85494BB645368B2A03FECA6D473CC99F2AFAF5F0EB6AA369787E42C4C0A2A407AD7A8E1D1F23AF24DAB855231AB94414073BA45055CE9D5867AC6CD57A062BD05104144105104141A0274821051924FD690DFFA9812E6AD90CD8FDBBD2352A0FBA7CEDAC794BA405B0362EFD1FF0010A01F533F51C9E1A2AFDA4AD6C702CA9B8E22008CF3C8CE7F7DE9962C7CB04873EE8F5E1E6D95551294B248200701EB9D3F1EE90DD58836A4DC1085245BA14E28AB294A50546328D07330488AAA62B13B8953920A4289198B97BF3D3CD8AE65A9050ECADE20063992DE5DF83C70DFDA0308C53DA3BDA57F97DEBAB6363B6096EA2C6D41294DF2EFADA1C55D20CB6B2CBC9E268A47BA60EBAF8E7E2DF8C932F1589C31994015F4EF3B1008B3DB5FB08EF5E0AC37C8D9F2F7C0DE6AD8BB97626E6A6A1F8F18C3FB47ECDD6D87ED134AB8C47107459B9386BAD3A14E24982A43AA2326C1848098F7644D7807C73B6133B1335654F551777ADC1BF0FD523AF6CC98997BB5A8636A6552CD9B9C890CFC364366F07BFC2708B4B2BB536A7D8441282A28293920E9255C31C5AE7AD72E46DE4CA252179977229DEBCB99D62E122724A4070C33353C1F5EB5E81A2E24F1A44127976FD07EDA74A8DDA1B6538896AFAD2487A3BBD5AC09CA8D946D37FD4FFC7461EFB3B738F0B2E2A1D0A002B91999F211AFD67388AAB9C4BA94AA33DFC9CB1A3C315000D81072FCFA884D771E0E4A24C69C267FC73D7B1E74A2279A90A26D6B31F75AC69B81BF8D356E3AE55890B6BE416D27333ACEBE7039FD9A7A8C4501053C43FB670D952BC631FE3A540BB31E845F36ABC48B77A88E6077313F3F874F853A4CE71424BDD89667FD7B1091C0D281C7176E7D1BCF263128CDD254849139839120C41F879473E94A267310C4BDEB979E6DC5E194CC2906D6E4FD2943AB5B330F9BB94C6B19794FFBE733DCD3C953C13A72B1CAFC1C5FCB268A95914039DBF421F35789809F78F48EBF796524E7533879EC0390DA3F3F400E6C0D2F0D26C87FA5A9C8BE5E63D6B9C48B5700C448EBE7E7F1F873135288C40342486BB1A7BFEA1B2B0DBA93F4853DB5F327F5CE1E22ED2980788EA2674E739E5AF3CEB2B9EC7F950330259ED5E37E1AD2F0CA64920B817C9A9D19FBE6F0EDABC40000E2275D75ED964639FAEB5A0C439FE56737166AE74B65DF46EB9248219AEC452CFA57F6CFA44BB174D142409CE7F365D7B76F8D6558A2C18B1A66D72F91FD00781762B94A62E03E5FAA7A4394BC8509063EFF005F856AA9F675543D01704F17CA9701AF0D8CA5120EEA8B543547A5CF768B7EFDF425F58E6408EF20E7A9D23EF3AD8AF7EC4E4EC4B70A74ADE2C1844BC9045F3ADFDF488972E10391CA7E197DC510F100877CDBDFBF3868BBA41204191FAC511BC34710A767872F3F4FDBD28821C356E80DA78BF3738CBE7F7E7440E0355B480E1E16A8C8039F2D75FBCE32F2A23054407A9CEFE7124C36DB2C2595092999F5D2328D3EC5109B2D4ADE0A2125E84FE2BEF8C475C59A9D27878403D49FF7A7C0E9D688583EBFB6B5BCB288E368A6D5C2AE1319C8F975EBD49CB91ADB13212AC31555DAEC694CDEC4DFCAAF0B0C46EA00722B716377E197DA164A1291A09E754F520CB9C9235AF0D1C3F2E0E2958426621C3024358D3F7C757C9A310FB40EEE0EDE6EDAE1092D0BBB2BAB1BAB22278D28B7BC6DF7818132A4A2044F43578D97354896921541DBEFA6BC223664DDF514545CEF1700F7C99835ABCA32EEC86D17F37D8DC1136CD949366DDB25C7C43893628432EF11131250784822728A4B6A6D39A842920B8B67AF46E8C2199900CC0B0A502FFC41649B0A8F4CBD623B107AD6E5C5E6E2F382A519929C95E920FCAA9B331866A89726E35CEF7E5167C0615E50243F1CEBC8699E67388A6908615C4D0CE79F4FBEB1E94DD52CCE340EF4A5D9CDE85BA5A25E5C80C10121BFF217F6D5ABC2CA40721C580547398CC41E607D018EDD7518204EF29245F8335B2A55DBD1CD17004BFA40492D9FAE7E86AFC63CF01BE9F4F2E9D2B7124203311C68077B6B9C29F315C29CFAE79E7133689E06D0907213CCF53F79C69CB2ADD321D4E41A376CC598D73115DDA65E6D1201AF2341DBDB9A44F5B93A8F21D0CF3F9FD6A670B26A29A92C3D3BDFCA23A24D1A791A7AA4800D1886FC7BEF7821AB90083A0EFF00BFAD4562177702C79585FCA99C108ACC0D0CF2EB974EFD2A0D52809A565BD2B933166CF9C3A4A5CBE432D6FF00DC362E01208206533239FC39F5F86B50BB63103E5290E5D8D7CA96BF1E42D0BA50A5073BA34D7EF15B37EE5AAD2B65290858578E63DF24084441CF339CF2E432AE458C49FF0024AD2186F397B9ADF46074D4E50CF15864A812A033624DB50347B5B2D6B14D9B571892B106AF54971AC4187985A3320A5C6D4DA723AC050991EB39575EF03F88666CD5E1C15EEFD686A961F50F4AB7E1E2AD8CC227EAFA458D8703A52AF90CF568B0FD9331EBCDDA6F276F373B8A5D04E0E8B9B67F669BF10F02BF13C77777E18510930A589E0CC1F39AFAFF00F00BC668C56C0C24B54D752928497232C8BE742F71DDE394EDDC0033D4B523EA0EC5BFAF2D63AEF5F41A394C144105104144105609604E81E086C5414A206467A743A799EDDCD343FF00BC6A0FB8673F878457FC8E56FCFEA3C518498FBCE9F4914E9EA4FE217921C025E9F9311EA6D2975C75510A02644CC40EBF1FD269AE3801289CAA48FC1D783BE74021F8A25290EE6F7677A76E2CE6DC2CFDB4BF1856018D5EB64A549B37CE52238585F4E7979EBD66B98EDC9E5089CC48FA1449E878E59F0A350BC8E090662E525601DD26B424B90731AB5F83691CCCDD4356588AB17DAC712955F5F5E5CA5D5C02A2597DD6D3EF6A0C0CB58E5957CD5F8CBB4272FC47899695AB777D4C0167A1CAE6AF4E7725E3B8787E684609296C870ABD331703A8222F5C470DB7C495F895B214E2566094CC4188EBF4CA72EBE57F11E1E74F4AD6497A972795EADA67D62E586C604B7D4CCD98AB57ED61ABEB0DDFC1028173878652204690398CBEFB5719DA089D2A6299C313AB54F1274C998F08B2E17690A00A532A8EED40D634FD45B17964193040100F4E5DFEBA76EED70F2E6CE35A825F8FB2F406DCA827E562C2C0726BC7866FEDAA62354BE06C27A75F4CC0EBE7DB3E55ACF0A92B292F562C03D40ECE33F485400B5125C0A7A33F4881BC7413CA679F4FBE7977CE45665CD63987B81E4783F1D0BDA1CCB96EA029BBA9B5AFF9FBC356AF3812124E63F7D4F5F334F11345DD8E9996F5E196A61DA70E0B101DF3D32CADDC3DE8F0FDBBD0AFCCA811A93F300E59C098CFB9D69DCB98406714B17FD8B37BCDC9C28091BA05726FB5B958359A82262DAF416D2388F38CF3991C81EB3F38EA326794B3392EC4EBC49776E3DE223172B72636E8A52835F4E36E3122DDF640A8E5A139E44C67CBEE29FC99CC41C8DA9CC6AD5E1E511D324850702A323FD39E50E917C018E2CB9EB23319EA6A630F3892C72ABE5CF5F6EEF0CD72B781A116C980CA262DEFB2199E5AF78FA8CA474A939739E9F503E6071AEACCF943654B20B338399B7A7DA1637C028C100E53999F4C8C4E7D7AD0B985C392F5B7DEBEFBC64E0C285535EBA51EEF91BBF1061D377C081EF721A93FA7D6739D2693336F550A8ABF2BD7A7286D3304E480917A86B7603D4D75CA45AC440481C5A6B9E539763F31FE76F9F5B06F3ECFF7867336706074ECDCFCBD987EDE240089F8931E79447DEBCB22702CD57FF8F0C8DFF3C4086EAC00161D48A7EBAD32CE185D3E1C714BE67498CBAF79CFE7CF9C8C82E9F7DB4CF81E79292E58969DD1D6235C744E7F7E67A9FBEEBC291EB69E3015966796BE9E7E74410ED0D1CB98FB39988CBEFB9042A4418A21BA955739F97EA1CA3F30F5FA1A235F9838D32F6605FE63E9F4144642C6448F2FD4534463E6F151F7CE105B3C6A2A024E4797974D7F7E666A41697C29A3B8A9D397E6ACCD0D5734905CB0CAAD4BB77F79C79F86FF00C7D23FC7DF5AA74D40F9E684D49715E9F807C9E35130A894B8C9ABCADA583FE690A8B14DEDBBF6AECA982CB8953660825685465A183F09CAAD1B3641296C886E4DEDCDEAF7AC6AE5F526952EF97703CE30CEC4E38DD95EED1EC6A8F05C6CF3ADF829D14A17CB53878473C959F6A63B5F0CB014F6BD3DE95A178D92927871EB945E7F855B1FD3590A503C52733EFF00BDDF406A80B5FCB9C47F17E87DFB348B66CEFA64241CA84B71A574D32E791E1764FC3FC54CE1415B31622A479BE61AB4CFD0C86F8073705A90A04802201F4A9712A868321F904B5FAC60CC466A0F7ADFCE00848E533D62994D9612FA1D453D83EC504682725CEF100017CBD7D9F29063F2A2639C41C8EBAFD08EB4EB0F237D20DDD89A56BF815B31ED1018C98664E5682DD7A0313D6DCBCB4E833E8627976D2A664C90801C574EE0D087AF38690F0B9C23873D351D67F6CBE149E24356CFE6037DCBC10C9C7323973FD797A49FF5355EC49604D33FB7BFC410DD4E8EA66633F8F7FDAA2A79694559B2892D9BD2DC5A0FF2025410E6F52E5FB701C74EAD5C7233275EF33AE79C7D39552368CE2A252EE1CF50ED7ABE46F0FE54F490C7DD6F7B71B7DA85105B047AF4D4663AFD63D2ABCAD9C66FD6CF9E55604E4281D9CB5E9CB49CB1BA4920BB3035035234D49BD32CA6F04FF953E71F08F9FF00AE5580A5E0D48209494A833508ABE5E5C1AD15DC496DE21D4E7E902E336D3AF9346A6FB495CE2BBB9DE26C0EF5F034ADBB7C26FC338F968101D45EBACDAB25DE18E2090B2654401A7427E82FFD3DF8C97270D8390A9845500D7FF21DFD98A2ED8C37CCDF3A822D62416D73D1F32F947786BEDF479FE0A20828820A2082B04382350D0423E17BD20FC7BFA521F24EFEFBEA18FAD3DEB09A90492411580B64822467E7FB5390BDDDE24528CDC183DF8F0B7185659DD0C47B73F6310F7E16A6DD436616D14024E878950207FAD79C0A678D5FCC945097048CE8CE5B2357FB71877267A10BDE5B9B51BD72A458DB75875C5DECB6376DC4853AE61D74A46A724DBB8A39C4FA0F2F3E79B5F63E23132E7310C50B26A43063D4D1A85A99449E1F1D2654C4AD2183B119124B0E0E0F91E71CC7DC03CDB78662D6B700B86CB10BB45C30982E33E2DE3A10A713FDA15C8F31074135F32FE366097B3FC49893313BC42D5E635AB3EBE6CE4759D838C97330882924067EBF8E71B14E58DAB0FA2DB80C3852A4AC0050A044FBB9004A4644472CC579A76A6D5C2CC2A925237AA0D85EDF7BDEC0DA2D322715A4A81293902F6B56D434A5BCC45388336E0A9B42488033CBA7F831975CBAD4713E1DFF00B8952E58649ABB55BDFE844CE0D730A52B529DC9601C677FCB77D31BE3764A3C4A052224C73044E9F5D7302321155BC4E1E4EC452BE724109D450BD0655AF0D38C5C301342C01F507FF769970D39B73118DEF1F0CAD6D282894C024091FEB9FE99CD53F1B8A463310664A1BA1CB3160CC464387BB0B4C895BE9DE01C3E59F3E16CF567310370AE324E639E7E83989E5FA69AA2896A772483AD7D93E50F25C95381666636B0AFBCF867185B738894A81132333EA0F7FA75269E4A965C1736CED5CF3BD80FD987F2A5D1B93D7304DB8BF68593C7FDC72E93CFB7CFF6A7299643D546B93FBF5F387E84B07D4797BE9A4485BDC708824FBA3B9D7D7EFAD2C990A507DF23AF5D38F11D1A22717277E61666B55F83D439F489469D2B88240E84FEDE5CF97C9E4A429000FE4033387CEB71AFBBC46AF0E6AC017D0575191BEB0F1B5AE75240EE7FCF4F49EC2A4A4952581CF9BB072D7F2CBD192F0C5D8BA6DAD7DD0F0C8E92F6EA591AFC7FC6911D27D2A5252C30A87A3D6FC03D6D4B521AAE42F7EC00193776B663B8BC39257248574CA4FCFCBCE7E94AB2D44AFD1DC9D7A37EF285D32C0480454660DEA2FE74ED0B0714343F7DF38AD0DAC08CC1F7F68D572C2ACC3EDCA86164DCAC0E73D79FD72F81D3CE912B50140E732F5EE7EDFDE9FE383763CCFE0085917BC3C8F2FBC8E83CBBF334899DBAC2C43BEB93035D350D784578601CD0835A0FD71E10F5ABB42D299E2988D3A73CF954DE17100A035F314278BD7D1A9D622E761F754D501DDCB8BE56BB5FA457E1970FBAA10399C819FD75FB9A72678D5BB76BFEF8C246436BE9DA9F8891B76F85213AA87EBD33FF005F183FC814FBB57CC7BBBC24A400D56E7D7417A5A251A64902018E53E7F4CFB0AC89FA8FD757D783C375CC4A417E36FB711083EDA90E28149F203B0CBA65F79E547CF72CCDCF2E758899D8D42565390D6F09FE2380C9428913901E87AF5A772D3BE01D74CB57F7EA23418C41661424F1FBFE383C02E02D51C0A493FF006FF5DBA7952FFE31DD7ABE999F2BB369F78748585B0B12F7B7DE1DA1A52E22339F9524A94437DF3E4C215DD6FE4F5B337DFDFD9EA1809480A20913A41E87FD7FB9DD58A4A257CB2EC5DC5B577EF91A68623E7255BCC0B0F798E87DD28586D133FA75EB3CB9F2390CAA1BE519B38A85002087676E2C3FA2337AEA90C039248776F2A97CF3F21482CA6CAE8DEDC00BB27213E1A3374920A678498804C933A0F302D3B3D69414A480C5C16C88033073CEFD291A4D5AD52CA65969818825DEEFE63B738D24DBEDB9C0377DED43B33835F3FC09DE2FE2835C0A486D2AC3ED429297E620CA804EB988E8697C66CF998B973264B49284B6F100D09B7986AF28565624EE21DC29EC431A5E9CF8756AC6D25DAD0D043AEBAD2D4E0E24A50A95709CD32239A4F7CF9F3AE678FD913118A2681CB90470CACCFDEDC4C5A701894996135B0EAEECD5A8EFC018669BA64F17BA470827DE033D7439CFE952182C27CB29DE5001AE4B00D6AE9A30E62D12C10660040234CAF47D1B5D3BC3138A32501C436EAE54470240E210634FBEF15253664B427743161C0F2AFBE1902A9C028D4A9406AEDD731D61C33749791C7E1B8D8E8E260EBDA6A0F138A4A7FDAEC6C050F0B5ADF624C36560940D161455672EC03D7AFBA449D9BA16522149CF22AD3C869DFCB4D69FE071682907779BF17FCF688D9F832164A957B36A19F5A56F9F289F69D6DB4F115A4F380738CE7EB91F954F4B99BC90ADD773A39F57F7C5A18AA510696199B7714FDEB0E53C2FB7E236EA013AB64FF504728F4FF3AD23889732623E942BE907CDAE2BA5883CA90D953128594281E7979B7BEACD16D393EF24A0680AF248D39E9F7D6ABB8AC36254584A5B1E05AE19F8D3B5612389402DBC003627D7FB0DE6611530A0A212B43875F70CE7AFCB9C7A659D456270D8A5A0A132261CA8836CEFC1AE7CE3230867B4C133753715A7076E5E9788FB9429912E10913A9C819E7E9CFA4D55A7EC4C74C98E30F38392EE93577B8A802DE54021CA6589742B0C9E3A59A9EF9C38B6426E5A406DD6C83202A72272E7E9EBF0A5E56C6C52505270D3778D2893DB8BFBAC213E724024AC07C89146D3A8725F95E2EDC1F09750B0A2EB5CA73EDF64FAC9CAA2B1DE1BC7E20B891343116496350CD42F5D7FA82C4E20027EA0A73FED6D5A96D4D3FB8B6F7C1BBFB4DB6D8AC5B087956A0AAD977AE2EE2238AC10AB96F8091AF13606712623335DEBE11A71FB1F13864CC9733712B41208E233CA95D32A8885C60F99254776956A57335B90CD901DE3A7F5FA248F3641441051041441051041441056ABFE27A7A882193EDA65797FC8524C8FFAC1EBD7A7AC9A6337FDCFC3D4379460F0152439FCDB2E3C9A22311B5172EA6DD79B2FB2FB6E03D16D9466398F7B3EB4CA700A95301762936E51906BC88E5F9F28E4818DCFFB4D6D5EC662292D605B7EF32BC1D6E7BACA1766C179DF0C9F7412E2B329933A8D4D7CFDF8EDE145E336962B13B942546D900C2BC29C9BB751F0F4E57F8682972D47009CDF96B4A5D9E3688DC5AA516CDA96953B61C456B541E20F105B20F4E129D7B467957CF4F15ECF3B3F1CBFA4277546ACCF5E6E5AEDA5EF5B8E1674C04925442B22FCA9CD8BB80DAC33B94A16F39CD27848F513F0A4F66ED02256EEF55B95B8BFA16D22CF849E7752924B55B2A1E2EFF63DA2C8DA048085102241FBFDFAD527C5A83890B533F27AF17B39E5578B161B1664EEDCE64E57D491E6F4D2310DF31C6FAD406A731969DF239CF49CFBD50F0F8764B171C7F5EFD04742D9988F99870ADE3567626E5B566A56E395A229CB52675075CF2F49EF3F5CA9F210ED635A119717A3F5E59C4BA660480A772FC185756FBF0A0864A678544427D7A67D2453C9729DB2CEF7A57D294E5AC3B97352D40C0B683576D7CA29F0BB27EFD29EA25B5198E65ADE97872165550A3DFDFE22B4359E83D34F5CA94F9645037BE548673D637D8DC69C75B57FACA262DDACB4F86BCF4D7F7D4F3A70843007B7ABFBF5864B5B3EA7ECD7AC390214B1D08D3D69CA406043977A8A80C7EEDEA1E192CBA8D5F4CF2896B6E5F7FF006A7D2D0C904DEEC3BD61AAD63789A97F76C9EF0F29E243243FBAC60170F0526BFE47DE519829B1A13CCC1053199FCD5CE0855B742541249044E7CB49FDBE039E54B4B9E515A002F5AF419817BEBD5BCD92958AD40A8D47937189961C491131FBCF5D233CFF004A9097377F3A6751A52BD3CE2371092806AED6E00E67ED6E222E9B0B42EB285C4CF4E601EBDE239FEF272249981296724D1F2A9AF3FC1C8C40E2715B856E5865ABB726157AF9C4FB162604A7A1CA472063D7EA7BD490C0934DD069907CB835B5D2B77020E763807482EEED50E2AEEE69C69AD844B23096D684AD60151C8F5CB9E79FC63BE7AC7CD93F2E69435F30DA3B7E3AB06110F366898B726996ACCFE8CE7AF086AE60CCE5EEF6E5D27D0CE5FEAA5B0E96003529EA6BF9E3485253D1C9AB9ABE9FA7885B8C3421F52909F76004C0EDDE7A7CE9FABE9431CDF7BD6E3366F3D22770F301483C18EB9559BBB79C3450F0647965988C867F4E9CA34A8A9F340A02ECE031AE4FCABF7BBC48865243D7F3CFEFA455E3712667D0647EFCBA9E548FC9F992CCC203F70C3BDC7A738653D20ABE9CB8BDDB9FB162EF0D9C741CB2806013A1FDF4A889D3C492524B35F76FF8E57A563544A2A06EFD5AFC32D7A5A1CB0B6EE91E0A9400642811944AA639E7C8C771CAAC9B1569C64C4246EDEB93B8E635E3530AAE40975DD2EB66A529D01CB8C7CC77F14CDF9E27BB9F69CD81BFC2EFD617B118B205CF86E194B589AEDD242A22006E467CA7B477DF0B786938FC0E2F086582B9E84AA5AC8000DC054412C58E90EA5ECDF981134A084E8433F3C9DED51C23BADBABDAAB6DE8EEBB65F783865DA2E19C470AB452836BE21E236C32873249227881273D7BEBC3FC73B226ECBDA139003142883A79778929527E54C1282482681EC5B4E2332D4E4F192090EE182E90402252AD44C1E13D3420FC338AE4D8EDB0AC3120120A6843BBE4FABBE5DA26A44D32D5BAA72E29720357F41B37B88696D6A9504BCB2A434A909520C75060F98EF9FC9BE0B6A2B1AB4A12B2497CC16E9E553D21CCDC6EE4B2CA049B05337170F4F2B4480B1B8B53F8AB4745C253EF78774A2B4FC04F5F98EE2BA1ECAF0CCEDA094CC082ACD88705CE74EFAE4E5A20B15B551BAA4EF096A3729A372CABDCD6E6E9BFB5FB376AD78B8E5F5AE10FA5243BC4EA18B64C12014851CA4013AC98EF13E9F066293382132949723F8A481E9C34E4F1569BB6D3281419AA5EE9242965D44939B73A35338B77FF0077B77CD2D4D5AE28DE3CE03019C1DE6AE5E39CC7083A9CC0D64D744D85F0FB153F70190A24B0FE3DB9F3E111D37C409208DF14ADF5D756FB5ACD01886F796BB95A3677775BC3BB7CF086DDFE55C76AB3191050734FCA39E75D5F66FC1D9D88097C37F201C14126B6A31A0EA5A910F88DBE92A7DF0791C8D296CFECD488C5ED17B4A6D09E1C03774FDB30ACD0717C2AE90424E93C32272CFAE7356D93FF004FD3310949FF0012EC7F8137E9D9C6778889DE25912D442E72535A396B86A9A5BD9AD5EA775DED7F8BDAA2FD8676570E75F9E2B47137CD38D41812D819150CC6798AB76CFF00FA6DC2CC94F370690B0CE4A0022D67193B75B8A3B997E324225309A9292285DC16E2F51D351530DEDBD987DAF76956538A6D36CCE1ED4C7B9777AD40503966201D34D7AD3FFF00D9AB03BC01C1CB482D532C7FFAD5C3F5F26589F1B2508514ACAC8FF6A4BBF4773C47DC45FF0084FB126FC5BB768DDEF0E2E332E0B3C56E3F0F9CC16E53232D7F5CAB63FF004CF8100B616496ABEE25B90FA6BA655D33819BE37132BBD3522B42C08D2E696B5ACF998BBED7D8EB7CCC883BC6BA911A628FE79C83F9479721DF5AC7FECD18225BFC29433ACB19016A1AE79E5C1E317E2E249AA8825EFF0082CFF9EA6D6C4BD8B77DF89626F0777A37EDD884F86EB2318B808536EA7856387860852499D35E82ACBB13FE9B64C85A66A30B2928490412802D95B80FC55A1F7FEAC4AB0E874CC515BD80B87BFEB9DDE3AFB5EEA8E530510414410510414410510415AAFF0089E9EA2086B7124122252329EFF3FBF8B19BFEEE9F682231C5388B76C28053CA2785799004F3233CC72E94CE6BEE299AC6FEF568C8B87D6388FF00C52F7ABB3BBBEDAADD6B96AC5D39B6CBBDBAFC2BD6012432D8758FC42AE543FA890599E18E8794D79B3E2CE1B0AAC3CFDF03E66EA892C1F5CF4E9D5ABD9FC15B2E6E2704A9CC0C93BBF281077854EF026D5398E7AC65CDDEEF16C36EB6630CC6F0AB8FC4A95676DFCCD09585B81C4B484E406842C2B881CC19915F2DBE2761D29C7CF12C06DF351C4D45299E95BE51D065EC6DD5268F7BDEADE7622DADAD95FF009EB0D5B25F752E7094E6A104242722147411967AEA7ACF32D9B2267D34AB9CAEFF006F47B189991B294E027701A3839F6E3EB5D22C8C476B306C41F559DBDD34B7F4E04AD255C51A44833F18D09A4F6CE0B7904A810C0966A1FC37BD625E46CC57FBC2695041E5ED985E2DFB9B55A417142352126263B8E91A76D73C8D2578620B252284D142A75B8E00F23163C12C4A40402C2C374D388ABF0AFB10E4B6E15240854C72CF3F972EDCAB797870186EF30453830E1C1F8C49A2752A5F997E3C85EDAD6193D6F0E2840032D4769FAF96BE74F65C9DE4D1249A01981CE8DC8F387889E08A966E37AB52A1FA7F690B73CF847A034E938726C03EA5DCF973B08748C4351C97CEA416D0B8E7A7185516AB1052011DB9FEB97C8D60CB656E903B38AFE5B85A109CB04EF6F73D5FA72F6D4906D250334EBD35C8E91918EDDB48AD9282E1D8F0BBFBA43652BE92A0687337E9E77E25E160C29C25620054403AE5391D3CA9FC990017501C9A834CAFD290C674DDD0C286CD9BF11A0D3D6D0F5A49447167D87AF5E84D3A4A2B5AE9FD4332B2471CCFA43D4A4A9214220FC72CAB785E5AC04805DF5EBDE91413026915FF0023D3D042D14F18EFF7EB4D8DF3772FDF2820E34F7A6333F9AB9C10DCAD5F886D0028F8AA30672000CF8BA65E9F11496EA8AC685CDE9419F514EF1B9004B51A029A134715F3D22E8B0B65BE0F014FBA7324E5EF699F3FBCF5A90C2A14A50487617239BF60F5EED15ADA53D32D248CC540671CE8733195306C25E6EC99E25227DE397427AC7FAEA60D5BF67CA2C97A91600D07EDC76D68DCFB1D8F24AAAD90E19BB7A718B81AB55208E2E123E711967AEBF4AB3C99296714D5A9A8F36AD44434CC4A8B3E6ECC752097FEA1E1B67D49050501267224E711F7CB954262E48FF20B00C097A0CC163E8FAD6B09A66282805D9D8101F5CEFA72CE18BCCBC38812920EB1DF58F2E7D0C75C95932E9A6BAE7EB125266924390C2D50F415E86D119728096CF101C40667D632CA7BF3F5ADB10B094901ECFE97E0C6BC0F0892933095259C02406B5BCF5E5C1A2CEC4042A412069976C81D33F3FD0D5771130826CCF400D6FAB53A69C226654C06854406E9C8F319D43C44A6FDA6DF6AC940F88E85A92A3F97DC049063AC65F5D6A730E12AC0B9DD7637A9E47953D3842CB93BDF58766CBA926AE7DB5EED98C41ABB75E690140B0A09254323248047C33D34AE6FB5E62C4F5A52400F91625EFDAA2D47AC3B9528001D2406CDB4A75CBD28C621F1EC64E03678BE24B2536F8759BCF5C70FE672195AD01BD24A4A7DE274F4136AF07625B132C2D4FF005076342E685FB6BC8343D421139280DF5289DD24000006B5C9DB99CB26F8AAF6EBDB4BCDF06FFF007838A9755F84FC420308B852BC40BB36D4942923300F1B6082328AF6EF808C8FF1E4AD4582836F5890C7798926E07763589D932E504EEB0A52845D801CEB7CEBD23B37FC15F7CB8CED86E6AFB777B417EAB9BBD902B656971D52816EEAE1D2C8682C9221B48072E523491CE7E29EC1C2E2B6962276113FE8A80202D8A8A825CBF026C29C4B52313E5032BE61037D2A0CC03873EFD873D8B6AE1413738580A0A6D633232214A2A11A99EC34AF17F8B3654CC3CE58DD206F1A686D53AFEAF0AAE58090B60481FEDCF5D1EE6BDE13C5EFF196703C51BC0ACDBFE6584301C4A31042BC2BB2B495816BC32A594C7BC32CC8D75A6DE12D98B998B96ECCE9705DEB40D6D056D4269159DA139482400A21408DE4B306C89FBC6BCEEB5BDFAEFD715C4B0D5DF60BB2F6D62F29B76CD2EDC59E24B4F12802DB79CE499131911CABDE5F0D7C2523132646F212B2424071C017ADB3E0383C5036BE38E1A5AE62C929059DEBF51005C9CF8E71B8BB27EC2FB3B89B76F8A6D9ED7ED1E297AE2C9B9B07AF90F5982930021A7133C2A2339D743AD7A67667C1D938D08C40908292C689B934E3C3DB18E6BB4F6EA913968485D0515FED2E1D835CD6B9BD2367765FD99F74DB1CEB16D866C761EBB929917AED833C4484CCA9C0264E7399931D44753D83F086448521F0EE035D2185726D397EABE76F621614B52D2056809DE1C6ED52FC79659CF0CD8AC0B0D65B0C61564D38DE9E1B290948E5A0CBD79FC2BAEEC9F0260F0A9015252E007DE48C8532E178869DB56729759C5292ECCAC83BB87B7AF089D18724A4B72584447F408491D00D3BFA73AB6C9D818294001290198064836CEDAE54D4B988C9BB4C12CA56F914FA9CF5D32C8D3BC7AC614CDBA83BE33CEA89FF00F6AA67CC67E5FEE2909B83968594CA410336D45AB972FC42C3173152C268126A00C859868E21FA909223810465A8F39E823427CA915E1C9AFCB7A55DB203ABD3DB984CAD4EE951A8ABFA694EBCE17693C08E1002626001909E9FA8EB5812D219D0464E406A6B7E9AF184D454413FEE3ECFBBF584D4DB866081D3F5FB3D7E3B7CB4A88FA7300903234A9E3DE19AA54D2E778EE8AB3B1A7BA65DA18BD64B716D289013EF78C53F98FF00D6391E433E5E662D1853265482C9A32775C060D77F366D7842D2F18A928092E487A1B8E219D896E55346789EA46310510414410510414410510415AAFF0089E9EA2086970471251FF79F8A472FBFDA98CDFF00774F3682239E50532FCC715BB657DC0009FF007F6299CD2D2D674493025DC3B5C5B9F1EC3F6C3807BCFDDF2F7D7EDB7B518DE3A97719D98D83532D7F2CB9FEBD9B6AC4AC4B40B6CAA5293E280A3FF909D419F137C6AF14A70B8AC4614AC823783386B1D1ECCDFBBFA3FC1189972363CB4B805AD402EE4906ADA64FA3455B57BA8DE46C0E23885C6EA4AD9B7B3522E1581A83C1A7D025C0D22D99038E402003919F8FCF2F1763063F1F34BEF6F2CD2F57A357F74ABB45E13B430CC085A083BC1DC528D4E2FC5FCDA9D99DA9F69EDF0D862F82DC6C4B7B1F6CD2516E9BD770FBBB274F00285B8870120F1147171644C8275AD363EC733A585897401E81AF9FE6BA662A61F68E0F07BA9993F794B2774CD507357A13CF2E91963769B92C6B6230C38A6D3631758AE36A70AD4871F53CDA55E21C805C2C08239CF789A8BF116004996BB16A65462D7C9BBDE8F58954ED992A2109A519E8C5C6473F224114CCE60BF4BAEDBF1BE84B6E70C14A072190813398D67227E7CC66A01986F760070A6638E5911AC3DC34E48427754A50A9BBD0F1B3D6E3F5169B6D7F54C8124E51209D7A99EC738AD928208FA41E14CE9FBA7AC3D97354A2EF50C5BF23B7A8872F5B4AC98D6232FD60FDCD3F9325C5807A923ADF2F7CE1E89EC5BEAB5C56B736FB0A425F85EDF2FF00FE4D3912C3B96E82ADCF28792E6D01766C9DAE3C8F0CA1C22D55C2397CBA763D64F4D05349D2885BD0699655E7DBAC60CC4851049232A8CEF7F64E96854DA280399F847E95B4B95BA5CDF2ABB72F7A9A420B9A6C1BA1F5D7CA1C36C10800EA3969FA7ED34F522828C746FB4315A8B924BF2FEFEF48AFC0EFF3FF0014E25A094824004703EACFFA221BAA687D1AD7CF979D042C84F0A427A4FCC93492BF91F7943D45520FBBC375FE53E9F514DD7FC8F4F410EA11A6CAB9E67D608298CCFE6AE704327314B4B7B945B38A48B8585A5906388983300E663B4763AC4961F0A66201670D76E26E5A8789A0E2F0DF133D32D0A1BC58EA6EDC3EF78BDB656DEE4DAB9E28595A9692041260AC11944E635CE0F6A929185DD50200BE966C8356C598B5E968E79B6B68B0500482C43F77E347A072285DE33BDAB45AB76904442465A119099F53CAA7E47D1BA416CB466B79DF2ED1CF66628AE6106A4A9989E3ECD4085C9813F2EB53327115634D06BC2F56A97F4891932B7C0DE0FA021FEFC3830B887CDE6CA08C8906077EBF1FD32A6F352262C9157B51F953BBE9084E64CD2906CC468EC096F271CF488EB911247F8CE073EA273D73ED584A08A873AB0A67F91ECD1590B3BD514E1AB54FBEB10576725CCC4465CC41FBF3F8534C67D20BE6E3D07A889A90BAA493FC5E838EBC05F5AC59D7C499E433CB94683D4E507FD554B1AA62483C4D6C497FC8112B2945D24D5CD46B58C15BD0DA74ECA2B09BF52F8038E96A6624BAE25B83A4FE61CF3CA7954A61B1891830924D4103880F56B0CF21CE2D9819489B2DF7492DD32F315B74317BE1CEA5B63F1474B86EDDD0A3FF009A52AD4CEB320E939F9543694933662940E74E3C0F4C83D21499282544E45DBD1D9BB5F5E30AE2CCE138D377982E22A5A19C4592CB8B948042D0A4E5C4623DE396B9EBD5DEC7C47F87392B3A82E2F43ADFBD7BC3254D9921237777792E6BCEC39DFDB8E72ED4FF000B7DD16D66D5E298E0B92A77135ADD5A7899D5695183EE480788EB333A4E55DF7C39E3C184972E509E400000EAA076167F4FC46A36B848DE2EE0B1029997A598D6B9000B0CF9AF87DCE0DFC3CBDA9B6B764307BA2F6178F5CE18866C50B4A8FBACA4A816925293EF3B23203E157FC76D71B63672B1213F313291F5CC4FD5FC9DB78F90CF3E1166D9D3938C9414A3F4AC58B034D327AEA03738EEA6C5ED939B7F81E17B476166BB4188B2DB854A6FC39F7539C82275D395797BC6EA94A9D34B3073609A5E8CDA9BF7687DF291293BA15605B78FD5516EC4339E7AC648462372D5E165F6C2DCB64A4359122EBC44C2C1FF00BF00C8467E99554BC398E9585C6CB4A887DFC9812E68EF5A7BA44162F0895A14B4A4B170C4684D40B7DAFCA2C3C69FC736336A6C76D764AD0B4FA9D4AB14B1610A090D88412A691D51C4A12635F4F6CFC39F1961F0A8C3A77C02371AAD987E15FD8E341DA9B344D1312B4A54820D161C1BB16ABB1AE7C23A61BACDBAC076FF006558C5F0FB86BF98786D0BAB60B4788DBC984AC29092482A5856A79F6AFA6BF0CB6B6CFDA1B0A4E20EE1514A5CD08AB371CB36B5737E09E20913B0D8F3200795F5329AA033B1C8B74A335A336D9BD70F34D2DC6D293C2A0490414F0E4338E63EB1CABADE1E7618A3E86049B00199FD05FA031569A908DE0E09241BD6EFF9F6D1236E14B68294482641CF9490397A7CBAD3933124FD3514B446E2012694F633E3F68F1693A491DFAFDF9D369AB510C0916B58DB8D5B8F7A088E54B2E6BDCD7D214524FBA00CE0FE9D7CE95972D3BA3786F1D4D49CBD479F3894C3CC9611BAA351976E514F0A872FD7E95BFCB47FC476873F32528DEBCC57B9F48F0156A01E9A4E9F1158F952BFE09EC232F2FF00E447323ECF154AFF00F2F851F265FF00C13DA31FE987216FA073F7A7A47A41E11A73264FAE7F1E7CFC8D44E30CF4129964849B0141C853AFA110D664A04BB528F4A060D4E3CF5EEF2A4A330510414410510414410525F346F6EB1F7F76AE9C608F098127956E7EA4D33D79C10CEE13EFB5713EE3721439FBD9081E7AD359B294C585FECDEFD3382216F3FA0CE30EA892916370E003586EDD6A503DF281DFA5466255BB2A627FDC50BF43D2364075241B150B73A5FA472A372F7D69B4DBC6DEB5F1B0368CDDDEDA072F52D06EEDD368B7529F19CCF8A0A21327F29AF9A7F1E70B8A9FB7F13B8B213BCA60E6943F7D28C23B278713393B39265A8540606BDC7B6EE23653F9433785CC58B858B8414A0149E12E04C2071E5272034823977F1C6D0C1CC93882B9877B7555AB9BF2D687ED5116057CD9450877DE04B582732696E022B76C2F1A2A53178F31C6078ADB4E292DA80038613CF5939913234322CFB276C48C3C912E83E96233F3CE9CEB1B842A784AD602CCB3F4BD59E9467FC660BC327180E366DEE5A696D907FADC32F4F33C46739D7CB2CE6AB5E23DA32F13F3371218D2D4E24B52A6BD75787A84E2490A0B395892C45079675CE8E231DE3584C3AEB76EB25B0014970FBFEA4469CB98CAB9FA702A9BF586152C34737E072EF170D9B8A526484CC724D88A695E009F6CF161BB62E5BB854E70100C426675331D065AF6D7232A0C0947D4A0EF974C9FA92FCB48B0C89A16414921C3DF81197BD0985525B500A854C4729ED9F91F2F9D2BF2CA064C3BFA0896952C901414F7BD7CC73FB410DF43F015B25612DF4B9AD6872A3FB685144A033960D416E0D685836952530400064244FAE46905CBDE53D1858396F4B7B31877ABBF1850201D483E46B2943172DC2355390C3AF28A0A903224C8D634F4A581000A026BCC0E3EED0D56EFBB964D9B7AFF0051E05A39854FA476EFE797A56E2790C1879F330D57FC8FBC8452563903EBF7F7D4F30A029D4FA7E3FBAC494921494A7302BD3DF0786EB39475FD08A67301770D5D780FEBCE1E478D34B796A6D00929FCC6321D3BE7A691396B48250A5D69535FBFB2D094D9A9942B736E9091212EA9B70F841295A94E2F242781254428F2240CBAD653B3A64D5E75209ECE40FBD435E9947CDDA6896EE199DDC76ABF38C0EC398C6DBEF430C6B016DD461D83DC2C5EBCE85062E02C40F00A642A083C53CF95593058612E504AB87F63234198B1BC57F1FB553312A4A6EC5B8532AD33BDB578DFCC330765BBA60A4250D969B0B6FF00B8A92D804C72958273C8EB5226407253FEE6F629EEA1A2878D54C9B2D4564935B59AADD80BD2FC22EB7D3C2E148C8240CBD3CFE3D6B7F94B0C1A9CC96D32310B2B045453343DF4D0DF23EF330CDC4A95319CC46B94452E994A4B39A6A1C1CF3FEA9133280400E0E6F4AE62D7E3D6251949F051A640CE7D634EFF00AD3A4495302492F9BD8E61EFDB5BC47CF46F4D2CE0EA3F35D1A22EE96912241CE08E7E9A1E5DBB8AC4C589798A3DAB6D2DF885A4A0A540105DDED4D0FEBF316FE26F22D98F19638D2B07DD466A11AFD75EFCB2150D8C9A54F50F561E879BD4F0CA25A44B24A83170DC882F6D695CAD163DE5EB0B4832532600244F2898F2922797C6A78B49528872378DEA1AA0E6FD386994BCA410AA82D421813A9FDE87AC692FB5D6309B6B5D8EC259722F716BF49B6208E1E162ED953BC4467F9721DFD6A5A5ECF9A8C1266BFD206F1BEB47A53339DAE22E1B2E7265A260291F500C4F3B3836AF1ED7D9CB6291B3D67C4485B56160544FE551F05A2634E608131CA44D57A74C0B5996DF55452F9BDEBD472AC667ACB9600825C11C6AD9674666A56977C87DBBA6987FC2B6E063842CAC0F155C442473839CFA18D4D4263F19FE1B38600936626BAB0F5883C4052D4A3BC72A3D052B5BE7179A509C3D1F8F425A9F08AF879A5294492A19408CFCA62622A5BC3A9C5EDA9D2E561D4A495AC0A920D1474A1E5F7262255226294523799E86AD7CB857EDC63E5EFDA3C6C46F5FF8945ED85EE2B6D8B2EC6E6DD6EE1D66FB6FF82A670F4AC05347F292519E998E5AD7AE767F85B6DECDF074C33004C9C4CB054B5056F9DC538DD2455B3AD8D23A6F86B66A9787960A8EF245413624D7F5C4E423B41BB6DB1699B3C2F67B09B54DAE1F66C8650852381D012809C827DDD4035E5CF14E07153F18BC3209DE2A50705EDD6BD1F37D22E6BD82B9725539442830B9A8F20039EF6AD4C677B5C4829696C32EDCDF5AC96148405FFC827FAA75809C81D469558C2F84B6A22709A12B2C527783B1AEB99B695B88A76D532F09BC4A9225A87D6972E96A3A45B8FA69101B49BD4D8FD8FB7B9736871EC159C5EE9050BC29DB96D372A1051C0D30A3C45C283A7581CB2EEBE0AF0F6DB9D3244B419C3EA43BEF80CE3B5BD961144C5E3B0B30A93BC9176B3D439E6DD48A868CE9EC4EB6F1BC4F69F15C2ADF11B7C06F956EBC351788E148238FC75003DCE1528CA4A41F7609D32FAB9F077C37B5A4786B0C95CC50225A6E540D783717E46D48F3C78BF1D286D198037F22CCCF6A9D0F2E1DFA34DBF72B7D564D16C2D9FF00954660A48900467200CC4448E46BBB60F6763E4801531AC6E69C81D5F818A42A74A24CC6249C95566D07EF3E7170DB0FE8A40293DF3826615D32E9F3AB14842D29014A7A5483FD9075FDC339877944DC7BA7BF48A94839E52272E7F2D69D5086207322BEFA43428AEF1079353957EE6F09A9B5932263A67972D07DE758750A034CAA47D8FDB8C26A94A2CA49DD15BD6F971B7B68F381CEA7E7FA8AC12B218100EA493E4C2309973011F50E4CCFE515065CFF00B01DA4FED5A7FAAEFBE1DB43F985BE5CDFF926DA9F4DD68AC36A004904FAFED434D37507A56B956DFBE7A0DC2161AA1C73FC74E3092DB5CE4091CA34F9FDF2E54B0DD23EB1BC75F67DD21CA160065024EA0DBBDFAC3BAD613828820A20828820A208299FFF0013DFFC608A57F94FA7D453A47F11D7D4C10DDF8F060F323E4AAD5740A26D422BA0AB0FEA088CBB48B8B7C4D09125766F3601E7C6C2D1CB3F4F4EF5078D6DC5EBB8AFFF0012CF96BFD46E8A282B20473D3EF1CA8DD0DE59E13BDBDEEEEFDC4A2DF11B7BCC3DCB79012A712FA9CB85708D4FBAAD3FC47CF8F8D5289DAF8A2C1DD437855A86E74B3DF9D5E3AF787676EE0E4AB7C2420170F7E0D9FE6F48D9FB860F8E70F6D6129414124640C00A39F3333023ACE75E2BF10A77710B0E5B7A9A71E8DC6EEF16613F7C024558DF3F3152CD5E54115DEAC2565214141294891D426398D41CA399A819001994766CC039676D21C61C28252E0877B86A0A0FB7BBC03EEE7CBD3C865D796BA79CD36C7C8242980AB3B7953B0D29D21F4B99B94670E3B67EBA18B5F1148515AB2931A73119F7190F5F9D454A4196189001B83F6D6BFD44EE08EF252470BE57B83CC748C7F89B79AA67231979E7D7282477CF9450A5B549059D865D3F35C9E2D582965C51EDA3369E62FD2AF10215C038721CF3D73F514D262C176CDBC9AFDA2C9291F487A0F3E0DD83BC7BE2F74FDFAFD29AAD443005B3FEFDFDA139D2CD58B92DEA3200E86154BC024684E73198D7CC7D4FA51F30015F2B7AC611299357A7DCFE72FDB2A1D498EFE5FBD67E624D8BF01EDBCE02821CD0B778A090492343FB50169363D7286A45C5473A18F2B1F3124EAD9D0B79BC325214E49CF32EFE9053C97FFBB3D3FF00C8C3E904248245DEDD7DF48A1424A472CE7E54CE665D7ED0F45B2E968AADB1145ADF3768B489BC0BE124681A4C9CE39FAE47B56924172055FD06776FC5DDA23B184298B91B8ECD6CBBDDF3AF9E2FDEAED03F68DE178261DC49C476A9C5B36A10616916EE252EC419CD249C8491153F8697BC037F2B8E44E7F76F3CAAF8D55C062C1CBD45BB0F75148D98DCF6C261BB2781DB317ECB6AC64341DB979491E2294FFF005132A2388C255913A659F3A9995242432DE80114CEF6BE74ADDB8C5231F8A593FE92D3BA4B1292F66703B7AF33911A65E17EE3A82434954889394738E63C84F5D2B64A4A560D48EE0303964F0899E160214A0C457B5DD87BA50DA57C5F18970EA7231D801FA67DE69625CBFA70A46A1625A025352E74A76FC7482B216406A7BEB07CF660C4BBD5BD6B0A17B81A827A83DBA4651A7C7CE905E328500B3676E2D99BF3CA3225A96A7E447137AFAF017881BBB9009EA0664F7FA93DB4A6D327EF87D6E33A65C07AE50FE46195BD7714ED5F77F4316A5D5DF8CEDC34B3EE3404011C24913D73FD35CB3A63392A99517ADCD00C8367E5CE26E4481402E68E34177A587B61164A8B2EADE79F70356ECC9E251E1481AE73CA44E83A8EB4C7FC3330871987CB3A1E397DF211232A45992546C031A353DD7D639EBBD67D7BD2F686D8ED99C39E4DC613B26F5D3976E36AE26D25E652EA388891F99394F7E75318A5093B30CB269BA7D9CA83A71BB58F0D861F29D41880D6A662E4E678F2D63720E265F09C1DA02586DA68919710690903DEE7F96464749AA061C0998A2D72A24127BD85F2ABD68F0BAB084A416372D471C0B1B0D7FB89862CDD5A5B6C2C84AC852C4C0FE99E2D07FF0058F5D4532DB98054D4D03DADCE9906EE486B58C309D8437200A97A53B37AF36A4618F6AFDFD617B8CDCC6D1EDA5E5E21ABA187BD6F66CADC016A71C42ED814A4C12429409E1E7DEBA97C27D80A5E330EADD72E0B0150C7D915A986C30DF5292A0404B17670496B393668F92CF61ADACC5778DEDABB61B778FDCE1AE5C5DDE5C3DF8ABA5137696DCB77FC3971449108238794089022BDA7E295FF0087E0ED9F8647CEDE5CB9817BDFC28437CBCCD039E56BC593646397855A92E404B3659676E22DE71DC63BEDD9BDDA63785DA5B3D8A6D1ED0E2AF3E8B4C3B0F28BB0B712AE14B686810A3F98447EE2BCD5B3FC21336C6D641F96565732859DDF8FDAA6BCE2D98AF10FCBC210A5D02490E4B0605DEB90AD5C0B3E51BB7B0DB01ED2DBEAC3ACDCB2B3B0DDC6177A125C7F1B6EEB0AC7576EB208532A48292B2D994F2823BD7A63C3FF0003A66270B295330CC5490A7523AE61F87615A479EFC5FE33960CE32A689894A98896A06A49F537E2D6A08DE0DD77B0D6EE36510DE23B6C85EDCED428216F5D6D986B11B7F189926C94E242F873FEEE5C23CBBBF817E0A4AC362251561D0374B90A486A31D3A6768E398AF16CD52D43E6292836282CB15A3B71D33D408DE9D8ED91D9ED8FC391618261587616BE1E1FC3D830965A427904A52343EB9D7AD761EC846C6C1A30B2C04A4240205A8CCD4B0FC52299B5315FE5E21530A8A80620A8FD5C4E557A1034AE917531861656E3A552E3BA9CC9D343CF29FF007532E3511191276AC96194B64C90499F333400C19DF89821C5660828820A20828820A20828820A20828820A20828820A208299FF00F13DFF00C608A57F94FA7D453A47F11D7D4C10D5F696E363848100CCF998F9C7F8AC2E893EFDEB0432B5656D25E0EA924B808CB311075E472311E95078C1F4A8FF00E25FB1B7711BA54032732A04770FE91C96DFFE0EFEE7FDA7B01DE7BEA4DB6CEED638F358938825202D8B616F6FE31C91FF0022870CC939011957883E2FEC75CFDA1889A949DD724122E19CB71CEEFD63A3F87E624E1D290A04A5810E433D2CF99D286E7439AF13DAE690966F6D1C172E3C8438A6D83C6E04BC9050A201C804AA5463313A45786FC5D81323133090D53C29506F9B7957845FB0528CD6A64F517BBB6B4391EB4312D698BB6BB76CBCE78AE11C4A5A0F124CE704F54E87A10455264A82166A58DDED4A6BA1A166BEA5AC12F04B290A20D03B35BA70E459F9452E3E8733492274931965E5E5DF9E959C4CD4A839209019870E1C58E56E158D178662000CC6BAE64FE053B3C46DE2D01044891A9FA77AAFCC50249A804D2F6E96D5B9DE25F674B526EE4351EA471D453D78463EC56E5B0B5403AAB2006599E874CF974CF4A66B5BB8D7434CBCE8C7D88BAE0124848CDBB706777E9D9E2D371E0A515007BCE5A08EFD3F51AD3598B2976C98E8F6BFE338B0A65D057CBDF4BC781C49CC4C7A7EF4D973BEA05A87F593FDFD6135A0BB38A7DF8F6CA2A0F84E59769D7EA2B099848CB3BDEE6F58DD082C069ABD5EB483F129E7A7689FA9AC85105F5B8C8C6AB946FAF6F4A43943E8E111244EBD0796BCF4D7E228DF21C814BB54F6E6619CC940925883981D1B23C7FA8582B8A72D22B50A20867AF0A7584552D2A0D6EE59B3F7D697A4BA90A2933232F3A7D256A32C9B31BB90CC7DF484012956E0C9EAF5D7AF68590952F4103A9D3E5349AFF91E9E82174CC648FA8F427DE70DAE2DD01E6545A5AAE42FFA0E04CA120C05C9D47126440D29E61653A8646C0581777A59C5002C6ADC218E296774800126FC1DDA9F739906315ED8DBB877BDBBDBF7F0DBCB8C2F0372EC2D2D34572BB96D2949483EE901C92A3D3A9AB6E0F0C9012C32CF3C83EB91E19D22A58D9AC561C824170FA8B59AD4195728DEC43F6649716871370A6580A00001292DA7802A73900E731CC015349C2950752686D72D6E05BFB0E050D0312A4A17BA8AA5C977A5DCD8000BBF1AD9A1D7E2AD30EB72B79F6DD53D9210D2829633FEE1946B947CB2A49586A12D5D1980CAED4F2E1942682564862199C91F4D43D0C37174CB5EE292B4EAA055119FBD999E9E5E54CD69081BBBB9D0D39E5E94CF8C3C4CA5101ADA9D3B01F98A17895B2464B4ACFF00D5264FD3FDD24A2C0D5A85A1CA70EADDFE2E722D7AD5E8FEEB11CE62D6EB511C7C2AFF00A28C1196597CF49E7CAA1A7A8FCC56E96395487FCD3311272708B094967A685EE323CAC6910189620A6415FE1DF753AF1368919F33DB4131972CF5D10951D4826A732D5B86E54C9F4893912536DE4EF13FC49FAB27719EBA3748B22E71A4B2E29E55B5CBA2EA652DA24B013A97C4FBA2093DC024C53996904A5F3C856D77F22F1332F0C58170929AFD428AE01AE72FEE347BDA7BDA2B05D99B17B617642E5DC576BB14429969AC2D697BF04EAB206EC3678D0005C9C8C70ABA5384A10087506704B102859DBA44BE1F0EA5201DD6A5998E41F969AE9AE2BF65CD92DAED986714C6B6E6E2DAFB6AF1A71A798BA654B7434D15A95C2E2DCF7D2B0CAC2607F703CB2A8EF10CE929C3CC4E1BE67CB0004EFDC16FA9DAD5B3338E158B361B0FFE8A42B74BFF002045D886CB2E7EB1BCED5A06169BD1FF0022932B3A12633F9F3CB21D32AA16CD56F62DDDDCB8CCF16CF874348D9694B948CA8D91D1AEDA8F289CB472E9C4ADD688525F292C273E24041FEA8580722A12131AC8D79DBA7E193325870093BAC746350EF5A3B74AC46E211BAA2EC0203A9EC7787D246AC4579B8B3C7CF67F197DA3DE4E2988609B2F82E078FB9B16DB776E62AF5BDBBC6D4786DA5D4A9653FD3E10E26655D2626BD15F06F64E156B54D24A674BDCF928240DE2AFE54B939BB539C35972945082B295124B949A370EF6C8F111C3BF62BDFBEC56E9F7DB8BE33B4ECBB74C5E38DB4E2D80DAD2C061A5B4E0794B50093A83DC1ED3E93F15EC3C462F64E0E59412890956E8DD3FEF634147AFAEA61E61B08F34AD2D5ABE82C1E9DB4D1E3B84E6F77723B578BEEEF7B1B15895A3AE6CE623E2E2B62875855C137172CA130DB64E498515711194D33F875E0E48DAF2BE74820A56090A48D5C30B39E19B35210DB52CFF0089312E2A8527E922C4350D0BD69561CE3EBAF70DB7DB3BBD5DD7ECB6D8E149B276DEF70E61B6CAF855C0AB765B655C1C2602814E647388E95EFED93B1B052364CA5AA523784B00D038602D6637BDDB998F21F8A70937098DC44942E7195BE548517624B921474766190193C671B1B1612F2D2F22E2E9700B6ABA85B2D889FE9481034F38E74EF038CC1E1E794206E92CCCC18E6DCF955ED1CFF7267CC2A25543406DD0519B5FB44FB16A8528DC84F0B8AC80E402728E67B0CFE5562F9A99B5497196B5BF9E94EF1BA8104BDFDF285822E94A2A2A401C86632CE86CF4FBC6B0ED1C7C23C4E1E2E7C3A7CE8822AA20828820A20828820A20828820A20828820A20828820A2082738CF499E5FEE993FFA963DB837EF95608A57F94FA7D453B47F11D7D4C1142085028E9FBCFD7F5A260FA6B627DF2BDFA406BFA888C52E45937E202233EC3213CBEF5F481C6D88176367AB81FB1F6AC640048700D45F9C73BBDB4ED2D76F361312B25A02AE70961DBBB479A00BCD3AC82FB6904E69E371091035903BD79EFE20EC438944E9A52080959A8B9A8BEBD2DE7D23C37210501690EA5338B545DB3B3BF5E11CF0F65CDF33BBC0D8E7303BFC4D08DE661576F5A5DE0B70E91722D98BB5B2C28B0545DCED11C7310419D32AF9FF00F10F667CA9F3CEED5D54B70007DB3716B4762D8D854B254BFA521AAAB559AFA9B10E46A1A37AEDF13FC234DDBA894A9284F10320F1912A93D02A63E51A57009D30C85900589BDC70E8ECC43C5EE56CA0A961696622FA3B56F63DAA4C3F6F1B03FBB9EB3FB18E93A475A88C663C00CFFCAF534EE78548C9D9E911989D9E12545B30F6737E163C352D0CEEB1A4F1292173DE40F3E47BC6BF4A8F4CEF9A1C1770F7C8FBCFCE34C3CADD56EF2D72B657D0708B6EEEE7C624E5FAEB98F4F4E9A655A2945D81A70378B460259041160CF6FB50535AB3E7588570FBC40D01E53D8E7D629ACD986EE082FAB9E7C88EC45A2793603DE7F77FEE2A49040D3CBA5335ACB105DDE872CBED90A40A43D6C72391841C71295904E7974E9E63CAB644D094D5C9A75A9D7BFA438972FE9059DF5E19D6AC7AC51E2A3AFD3F7A0CD0C18ADF3ADBFB8C2E580E2E74BF937BE50FD820B608D0FAF4FBED419D57AF26A767AFAC32584B97EE687BF38916F9FA7EB58F9B5BAB3AE96D3DD28346AB4328B1E795C70F385916FE2282A241E71D32D63B659E5CEA4E4A8FCB0F6604F1D399D34615AD2227ACA66001F7AA4E8FE5EED12ECDB42047088D35FD8C759EFDAB604296F91D796919F9A1850726A8F3E5CFA43830DADA538DFB88564B23212759D6331FA8EB378196EA4B338F322F9E9C75CCC30C42C1DE2145D8167E1D6E1FAEB688DDE46CCE358A6CE9C5B654B4AC52D9A2B67F371F191970F067A8E46AF78291BC90401950799CB872BC5431B38296524907EAAD82AF50D7CDFF004D1687B3EEF2AEB11BCBBD97DE45EAF0FDA4B05F8776EDD385AB65A5454A60254EFBE47860033A9F4A9A4E1C10067AB301C1F83EADC338A96310A415AE5A4AC82084A43EF7D81E2236BAFC60CA6DB6ED1DB7BF4C8297ED141D20CCCF109D3B1FA5359F204B191E4C417B64DA9EA2F785306954E482A96B96CEE169637A900FA7586D70E36C8287997D694A07BEA124822609CE6328F86794C362250756F05240B1B71A5B2BE8EEFA4C61E46F91F2D52DC64554E1974CF4A345A78862D60C13E030F29CCFFB5249F841CFBC729E42A2672909A872D42FABB06E1C866F13987D9D38B29625EE8018241721858E8796BD2CF771F75DB85F8B6E80CC8CDB49FC5360092A76623ACF20338A40E18AD214452E08AE6F7AE7601F311292F03BAEADE50B50FF001391CDC83634F26318E76BF7B3B2DB2695AEE76C30D5BADE6AC1CDF2157EA3FF00F8D2C1CCAB4CBB839D6ABC3942410A1C52FEC53F1CE1DE170D28CC2932085021E62922B4A6E9CDBC9818D42DB3DFFED66F2EFAF365761AC6EF66F0F30DDCE2D7AD2ED6F2E90B0655873CD9217971054820020999CDB297B82A1AC090EEC5BFBD72A0113F87C1209AB2C38A1A80C459F8DF5F4B4367B7236585DDA717BC69FC6B14795E2DC6217094DC62EDB84F1152DC202928049009FEC1234A6EAC60466E32B3DABA9A1E1CC5DA611874A52280301A07D1A9973EB9C6CDECCE002D50C3885A5E48193A832328F74AB4949C95AC28543ED99BBF835281350DF8772C7B985C2D2964B860EE721A71EED1950A816020EA040FA4F2F38EDDEA9FB266286281BB28DCD454737ADDF8EB0D96B01C8AB8C83935E2DC2BF731459BB76A6DCB603F0ECB6A4C5C0949826550AE51A65196B15799939909FA98060EE003D79387EBC6184E5209DF512A77649AB90294A694BF3CE354BDB797816CFEE17783B4589E1D85E35F87C21C16CF620D26E0A16B6968570A9511EF473E5E95E8CF83B881FE66180A82A4872F67F66BF686A89DBC80427E58ABA2C29C2F6A9CCBC7E7F8AC6AD1EC4F69B1A699B7C314FE2B7B9211E0B251F8C7920339E7EECC8313957BE676C74E236326629D6528428331624034CEF4B5380A43A91B4A54A3BA4849CEC32E0C18937FB18CA1B078EED65FB89D9DD85B8C7D6BB94A9C5358629654E2DB05D48692DC924A802246B9F4A6FE1190946D64A9406F6FA5FA503FA35F94436DDDAF2BFC7584B541B1A73AE7ADAE35A7DC9FF00ADBEDEEE33B8CB0D89DE760BB45636D80A9E4E1F79B40C3EDBEF876E5C59E35BB214042424A63223AD7A802D6BD98128A3A0333F2E9E4794798BC61B411326CD015F5025CBB8EBC03F4BF3FA3AE1B90095A9B4A523DCE1273026049D328F2E5CE6A387C1E326E306EEF1651AF992E0706E79E714594A41BA779F2D3AFEAD5E5258738B72D92A7014AA4E4441D48CFE15D0F052E64B94913410B6ABBEBC7AC37C5A5299CA092E29D283F70FA9EC35828820A20828820A20828820A20828820A20828820A20828820A2084CAC82440807BFDFCBE349264952DF4B9CAD953D9E461354D4A5A84FAF4E5D22A90A919FDFC694002433DB33190B72CCD0D5B205C3A24C2635EE272F3A4674E64B641CBF5EDCB90B429761FD9FCC5ABB605430B79F4E41B4924692049CBEFAF3D61F1002D254E33E341CB4F5BDE8A22592450BB8B57BD3EF1CEDDEE5EBB77846D23B6D2E855A3C5E6DDCC02D34B29E103FB721C4491974CEB8F78C76A61F766E14A7EA00A5D403BEBEEC63AF7857045587429EA5AEEFA51C69C8691F3C9B1382EF176237B1B5DED03B349B9B809C4102E70BB1F11568A61A7576CE16D94C7BC1BE252A4FE6D6BC61E3FF000C2B68AA72E4AF7492A2082CF5E0E0F91CB9F6ED838340094CC01480CE15504BD3414636CF8C759F76BBFDD97DE66048C5EDEF9BB5C4DB4368BCC22E1C422F9A7A78172C0515005614AE7EE8122457963C43E119D83F9AA54D1F4924806B716B67714E0D48BFCA969420237286C52030622EF67A65967966BB0BF37C62D945D4A512A5A33427DD98528686328EBDB3AE2BB64CEC32D49DD2589A81C59B2A8BB67E51198E9297A86166199B1CF26F748A54F38B5A97242742093323DDD3BC1D33D33A4B03895995549078821C1BBBFA8E1C618CAD9E662B7D2C00A97762723CDAF5F48A937FC1F99975644E89D667CA7BFD73152482A591603B5C53DFAD22670F8732CEE82EFF006DEB30E3A08F42FC585A5B5A02B92844465E9DBAF2CA96183F98C4A921C9600B538E7F8E01E24501207D44150CB5E747CF4A1A9BC29C4842415109EC624EBE53DA951B18ACB99A91A024E94D05C545E8748092737F4E828DDA239E5A54EAA0C8E4797E9CF2E79D466270870E482A496D0BF7E2C7979C6C9C4EE108524B3163AB0E7AE659EB68F024AB3047DFDFDE751AB9A11A77A77F5FBC6DF337FEA0925F874E3A44B5A7FC694F3060FC7E3F4AD133F7D411BADAE473B1ECDCE8D9339EAFE4A6140ECDCAFA9F7AC4FDBD9B8E890A4671A98F3D7E35272B0A66241DE009C9C3679F6D6F58899D8E4A09705C8B916C867CB56CDE24D9B752141A50E229FEE198D0739F8FC0F3A723FD3FA0924E82C5B4B3FBCDE22E6CF4CC5EFB64398A7DFDBC4DB164E2C26074EDF1D79E87A9F83B9127E62812EC0E4FE6D97A437998842695D5EC73B71A44EB5847E2994B6F04F87A029FCD139E664663EE6ADBB3F0CC52EED537771C05F3047A8887C462D0EADD249346366E0D973CF4CA5B0FC25FB058432F2CDBA89E26D6A24C7602AE5833F2C00C28D931A67C7AF18839F342CA8AB76954DA8E00F32D66A8886DABDCF6C9ED9B4FBEE34BC2311B8482EE278725B62F5C291014E3B1C4AE180019D32E74F95B424CB05252E450167EE4DF4E0CE620A64DDC5804037DE0CD7B1B79E8D7731AFD8BEEEB7A7BB8E0FF00F02DA36F1465B595706D25D3CF4A78A4001B006432F9654CA66325CC2490CF9022957CF8FBCE1F499B2D49092CE4977E3A96D1F3D2CF0C93BC3F6810FA8E3183E0570C242415E1EC5CAD0B84804A4930731E951B3D6A9B41D2ED4356E9A6B5D626B048C3211BA120977DE663772C7ADAB4D22C4DB4DE3EF70B0B182ECF30D5C807DE7ED5E08E239CFBB2489988CA39D464CC395134B9C9DB5D072A7E62CB2264B003173CF875A575A4609BDC3FDA2B6F1A8C5F17B4D9AB57894A9CC11EBAB4C40A78A21C2A904C6424E4093AEB90B4C90CAE9DAB9B1A534787416822961951EFA7BD625365BD9C7F0D709BCDA0BBB8DA0BB510A55E62AB17373275295AC4CE7F28E8698E227CBB0FB70360DA5AAFA98732E720067D19D9FB0F76D699FB08DDE6138516D2CD9B4A2D8050EB8DA7C46CE521063204E59C6550F8898E5F4D73ED5341EEB12B271728252D7CC585697B3FBD62F746CC593A80A4ADDB77844AD82105E11925C3FDC00CBA807A45442D678BE4F6F51FBA1D0C3B5E3DE8908296FA8915D2963A69DE1FB762CDB302DD2CB4C944C2191C2DC927DE8EA7F32BA9EF4DF14AFF00230EB9207D6CCD9307C81EBC223D58E44B5EE83BC2EE6A4B9B7E05B5E292587418253C33966491FEF2E5FBD5691255B3E6FCE58700BBD09E5DF40FCE1413153599DCF1605F9B59BFAB4561DB8B45A96521FB55A7FA8D89516C9109244C244E797298CE9F61F6B1DA1351874214E54002DC6E3D96CE80422B94A2E09AE47DD072D0D59E386DFC4F76F36B37A5896CEFB2DEEDF137862FB4EEBF6F8E3985BCE78762CF1377091745A254D9532A504050FCDDB2AF6E7C06F076D09F3F0B8C4A52A09295044D7293CC58B33F2E05CC5E217B8E0A9DBEDAD1DF2A519E30C7B3C7F02DDCDECCBB61B4BBCFDA6DA8C79C7FC1BC7F0655DDBDD61E5E570BAE2576EEB67DC5384C89CC124E75EF79C572B00304B4A65CE284A775144D0370AF5376D229F8EDA0B913944294D56AD752D4E36CEEE5A3B3BBA7F635F65CD91C53086F03DD2ECA5B5C58F036D5E0C12CD172E848482A79C48F79440CF2CE67AC34F0FEC49F2F1E99EACD4EE4EB9171CB4B1AC53F6CEDB2A92A00AAC4104FE38971A67668ED0EEBF63F65F66F00B5B0D99D9DC1F03B4286FC3FE5D6A8B67084C157104E473F5835E88D9C52AC2225101F75A9996CFD4EB4B51F8A6D913311326CC0A356706C2AE19F8B8CF8465F72D564A0F88B2129FCA1592A00FCD3A904476FACB6130B2652B7CA06F5C1233D1C7B073886C295214525CB6649D2CDEFCA246C82C329E3E1933F97439EB9E7D7A5389C5256775F893C87BFBE9B4F52553094E801ED0F2928460A20828820A20828820A20828820A20828820A20828820A20828821056A7CCFD694979F4FBC3399975FB4548D4F97EA2915FF13D3D442C8FE43AFA1847861D7951AC69AE5D7F4A633BFDD425DB27A37EA16171971D22D9DB04716097794C20E5E87E3E54CA60FA59A8CAB0D787B787B21492A507AFD239D5E9E75CAFA472EB7B6BBE385ED5B587AC2568C3AFFC4CD420AAD9EE09033C8C46933A19AE35E35D94162762022A012EC3425FA51A3B078627844896934219A9EFC99AB1CC8F676DA96362771B8E63BB5364C62BC18BDE5A5F5B38DF8CE94DEE2EFDB347857D0382267B682BC51F11B6EE23662E7A5256129DE176D6B43D7A5C10F1D8B63E24290900B12DC496E1AD3D6CF0E778DB8CC1300C291BC4D86DA156C762375E15CDC5AE27749B1C3AE9774525A43086C4AF3720A4CFBC40D4D795F69788317B4F12A940AD414A20DCDDED56D795ED176978BDD4B29C8206EB64DABB172386958C6569ED8988EE871CC3776BBC9C3F16B5771542B87692C9A28B171B6DB0E871376EAB3494119E9D349A9BD8FF000E311E2097F35525DEBBA524294EF402C7CFEF11B8BC4826F40ED63CCB0D5E835E51B3FB31ED35BA5C4F0AB6759DE560092EF11F0B10C559178933987532633C93CB21DEB5C7FC1FC7E16614CB90A005BE9200A3E94E361A18464ED34246EEF3330A1153F67AD5BA5232059EF9362EFC8559EDAE07700E858C41B50D01E44E4476CFE134EDA3E01DAB8376953A8F6490E43816FEBBC48C8DA2852AA439156F215FDB9D1AB78611B4985E2EB439678CBF76E3874B57D2B615063DC00C9D33E53CCD50B696CDDB382DE644EFA49228A661CAE683AB718939535332C5ECC4D0FE7F65B38BC6E6CDE5301C7AE2E186C8FCEEAB875EA488FAE5F1AA4E2B696DB90B2DF3C373671A0ADF5A01D2AF658429802951B109A90E730DF6B68F0CEDDE436DA52DBFF8842491E2F105CE706543A69A11232AC61F6963A78FF5FE6151615243EAE3CF3F485BFC32A62D4C81E37F2CC919DA245BBAEE4E9CE09F5EB0465D674A9EC2A04D00AE845F79A94CC1737E40E9AB84E10243333D8E5F625FD4F794B5B900A3B4FC01FB8FAE469DCC952A5A77814BD2BA7B6B0A528D688EC561D92A2D4670DFBAF0F4BC5E36174084EBDFD7EFAE91D05444EDA8B904849342C188D3F54AE7567AD3F1D288DE167E67F75356191AD691775921B79285989333A671CBEFA73CEA5B073D7894256A241CCD8F3AF4BF9443952852C479FBD738BB6C996C464339EFDB3FAEBD39558F06A4A4D4D465626B4ABBE9F9CA22B153164DCB0A96E56ADCD7D22E4610D04241E181F18D403E67D0FA656BC1CE09DDBDBB3FE69CB8C424D52C28FF003FAADC3BDAFAFAD651A4B320C8111AE8341A8D3F69E756191884EE9750B52CEF9BB1B574E10C56A5870778B7FB8DEAC6F415B5DBBC392B4B44919B640D73072198ED9FF98A8FC56206FBBD0DD9AB4D7AD75A50445CD2A54C04B5097E595EAF5AFB30C2EACAD710052BE132208CBB46BF0133CFA014DD3880A7751072AF4D791BEBC21CC85949FAADC457DF4AD9D9E229DC26D6DDA36E8F0804CE47501464E5DC9903ECE4CF2186F31ADC9EBE599EF4898C3E24029290ABE55CF4FBF18B2F11D9DB77D4726733DA3BEB1ACFF9CE813C1A953E95D1F537D183DD844D49C45C8DECB831D73D2B9768861B3987B29085B6D29C4CCC0067B826397A10353A963397BEAF7DBA655A5A1F2318C0024B97AFB6A37EA1B39845B2092DB423B247307EF99CB28A6335EA2A79E97CAD5CB4AB34394625D4050BEB56E373DA1839837192EA5B0907310348EA0FEC7E951F312E906A497A135D0E55E5487D2F12919E54073E601CBDBC47396FE04C1397FDA728F5CC69CBD3234CD5289C800E5AEF77CC77870310F7722C5BCF33DA235D471B8489F41F03FBF79A48A04A49530E3A9F21D6374C833485901813C9C9662C1EBEEA4C51E17FF6EF97DC5203069DA0B1299CA8814142E6D636CF31CDDA464832C0A800543D2ADED87DAF83B7FF00BD5C3774BBBAC7B1CB87026FD4CA6D70EB30522EAFEEAEC9B767F0ADC85381A75C429C23348CF235D93C05F0A4E3B112270C3B82524326CC41AFBF3610DB178C4A105EE1D99FFA1F637223497D93F702E5AE258A6F877ACDAB13DE06DCBFF8CB87AE41791B34C30B51C3D36EA7878B686EED56DA5609FEA1194F3FA23F0C7C2C3C3F8792A52370212059AC2971426FEE951C76D015FA99DFB54D39C74556D2BF0EC052022324A522070A7241CCC6691396B3975AE9B8D299D8B0B4DB53A5AEFAEAF9DF3A76D09E263A81241A35C9C9DAFE77AB9CEECD8E6BFF00E6ECE468E0D27A8CB2E79FCC9CEAD3B2100292482F4AD0E9735D08E3D4C50F6AAC90A25D8851F7D2F4A9B523A5FB12230CB11C837A8CF90CBE1F1F4AE95B3EC19C30CE85EBE9AC51316B652C3D1ADAF21958916BC64958800F248F5FBFBF2B0A1B74019522292A1BCFA1A8E632852D7FE14FAFD6933736E96E9082FF0091E9E821C56235828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE863D52638CC0CE3CF2EB4CA6921EB666E0ED0B45B1B440DD61D7368810B75042547F28273127E1CE99CC202483983E4CF0E2424858551A94ABD639E5B7FB2EE5AE2D8E5AE22522CDF4F8772A689CD0F20A722A81A28820CF58D6A87E244A67E1E6CA672A0459FA51F3D2F5238F43D858AF96948DE619134CEDFB23CA3827ED7B816F1B703B67865DECC5AAF1ADCE63B89B3738A58D925DB8BA67C1B969D256DA21848F1D4A32AE93135E40F1F7C3CC46D9993B76593BE4D4268D5CF4EB7E21E3ABEC6C76E9402A3955CD6FC38BFEAD6D7B69FB55619B63B05B0581EEE302C7717C6DF5E181EC2F0BB64BE2D976CF5A150BA65A3C48E20954C89C89E55C9367FC12C4271816BC3D029C9DDAE76A5B2E758BCA71DF403BC59867C087F3F2A868DA1D97DC15EEFAB0CD99DE76F4367DA699B2B0B3186E0AF5A94AC45B32CBE9BD61E04428A791191322BD25E0DF87B87D9E895F3248FA4016AF1CB8B7F548DC563F75249512E0D9B8919BF71C5818C9B8B7B296E5F1B2BBB1B178260EFAD08416F09B0B761A4290908E3402990E28895AB9A89922BA54EF046C89E9DE992251240A1482C4B5DE9E561C43D7266D35A6690925B30D46B57DD39C623C6FD88B622ECACE1BB47B4F8324CC270DBB6984A7A00026321EBD339AA5ED7F865B271214061E4D41B203D7855DFDE913184DA0490E4D6FD18F43AF78C4989FB136F1709BB7AE7767BEADB5C3EED9016C338FED03AD614A58121280CA41827256999EE2B926DBF82DB3F129294E1651A963B81F3BD2A38D7C8BDB3058F620EF03931CDC67D2D50DD22DE6F799ED7FECF771C1BC7C393BC6D9DB7242AE7056AFB15716D27995BC420A881993D0F399E5FB4BFE9EF0F396B50C2A2D40101ADA6EBBD0B70B459B0D8A964B8201615058D879DFB50B5636DB735ED6FBBEDEB5BB0C3C95EC863A6517382E301BB1B86169240058E22A495C710CB30418AE29E27F8313365CD98518764A49A25059874ABBBF37E0D60C2CF46EA4156FB13FC8826B9BBBBFE9E3692C71766F57C2CF8859569723FE050D4292B920883D79FA8E11E22D9188D8AA9837149092C0976001ABD9F5AF9801DF2A64B525C0045C01573DBCB2A6B5996F14B761E0CF18700221C410A6D5397BA474D3B9D473AE74BDB334CEF92545AD7FB3DDF952D686388489B294424A5C588EBD2AFA54D327BE30ABD6DEE11C611A415981F1CB9EBCF2CF5A9FD9FB317B4589058FD5514399E2E48B53F351C7E15552524EACEE6F61C2FA3B6822F9B47168E101E41E8127AF31F2CC48F2E73E30A7027E530200C8D2B5D3F37D1A2AF3E490B2C9525EAC47BE1EC345D56778E048F789D34267F5D3B4C65E54F30F34EF3B86A3DA94E957074D2D11B3A4B92E90C5AEEDA65ADB43CDE25D1882A47BC124E441CA23D7591AF79ED53D87C504DCF177FDBF0639758879F214092C487C85B43C3F1E724DDEAD4212B132273F2CC73F3CA338A94958C02E68D9E8C0E9E54600C464C96A3BCC09CB80A6B4E1971B44AAF106CDAA5A85174482A0070FA199F3CF5E8669ACEC63AC8717CECDD48BEBC4F3860708B528A98805D8313D5C0F2FB4465BDCDC34E95A9529998075F4E5F2A47FCCD19C35496EDECB768593875020949A7FE26BCE9FD4387EF90E38A570E662720740074FAFCA8FF2CD5CD7A7A5CF06E7587D26514A47D2435836AEEF4E3C3B34352FB2AD5B9F41F3F8655918C04583E7FA76F46CA1D252B702A3913E4DE7C2211F682EE56BE121063DD034CB9448F43D474A513337C02146B93FB7F487282ACC1E7CB81FB6799BC2CDAAC513E234E11CE123303CC83F5D73E95BFD2D577CD9ADF9FEF846CA3382BE921F8BD2DCEED71F8641E530EF1065B2949D0A840F5EBAF98AD7E48517B067EA74BF11C98B6AF6419C024AC826B6726E496F2ED945A18A5A49E3F11B4E44813CCF58CC72E9D6B070C9AD3CF37D1B23AF0AE920998B7018876EBC98D47166BF216AB64ADE79A8E14B31C4F1C9A3C59A615CCFEB505B424CCAA520B0D38B66D9E9956D13D879A99720155D87D39E76F77EF1686DAEDBE05B01805EED1ED2DC270FC3ECDB538953EB4B46E826470DB9564B512008EA40A9FF0006EC79F8AC7C92A42F777C646B517FDF0E2219E231E84950DF7DD150F6719F6AE9A8CF99780BBB4BED81BF2B0DAF7AD9DB6DD2EC7DC3BFFE3F8462485A138AF8882DDCBB88319B0F165F6FC5B4524E47849AFA4DF09FC3587978590A99280FA126A90F4029E85B2F28AA63F6928957D74AD03FEC6BA1CDEF1D14B6C26D10B7B05C3385AC3184B097DFBD01372F78094942429320A1A52785B06084848CF5AEDFB4D48C048DD943758300037B033F5CA2AD89C5AA6A8BABB1E7D746E05E913CFB8D396AD3AC92B687B80EA4F8709398E597EC2B5D91BD8A4852C0E04DCD79B53F0E2A223D73094A9E8189B9F6FD9FAC5F3BBEC31FC4715B6798294A50B1C5C5209CC1E5AE433D4E626BA36CAC391BA7938E0F677E40DABC6299B594EA5358D40AD181E1EC115B08E92EC8D83ACE1966B52870844473919139FDF99ABDE0E584A4166E038801AEC6D4D2DC2287895A4A94337A12ECCF97AD59B8C5F0A525488FEE20CF4D7CFE952454539D2AE333A74D7D888D0A2093AE4D4F7EF575ADC10D007A9D3CEB20B807580972E7385AB318828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE862971D482519CFC3F63EB4C66FF00BA9A7DABEF585D201501AD7A0BC473F6A5E049E9CF33F7F4F432CE6074B9205C578C3A42802C680B5B87BBEB1AEBBD3D8543E9BEBF21C7137A905411986BC311247298D67F4AAB63702B9B38923E9341D8DE97E97A50B189AC0E33717BA19810D4E5A3BD4D7F348D16DA5D90C1F16B6BBD9FDA2C16C31CC31055EEDDDBA6E5C4024A8F0858E1064444E446424547AB64E15559A849A33103D68C7EDD0C74DD8D8B2A4A54E7A1E77007DAE6312ECE6E8F74183624F5CE1BBBAC35772957126F2E30B6086D59E6870094F0E83908D795339FB3B65C9FA932D00B6807F4E7C9B48BC4AC613280DE34B826C3977CB5B464271F7025586E1E52A62021BB56B3619198090819240CB4D48911A88F5AA44B27E5002E404B060D60DCB534AD5DC4663316A7FE4C2AC41B5E9CF216111CAC39FB64969F480E0FCC120C0E2322273D0E63581E555BC66D0C50584A0AC26AF520355BBD7CC4478529642AA756CEDF7CEBC6E5A21FB6F7A232CFD3E47D3A7C61B2319895FF0032B2FCEE6F4E27A7189492B54B00B9CEF7716EB51E9AC4270076E96CDD24861A23C328D64E66493D73F29E722B6F98A5B15A49702E0DA9CE822670B8FDCFF71F3670CC2D473EAF156321BBCB33875CD9E1D7387A870A85CA389CE1E73CBAE67D295DC94B4D51C983BBE5D470E71352B6CEE007798F0E81A97CAC5F9C68B6FBBD92361B6FD6BC4F64F13BFD92DAA92EB177B36F3763FD64C293F8F5A015F04800091913A646A8FE23F0DE13684B984CB495149674826D6B711C6F13185DBF91517CB30CD5D0F1B75AB4604C037DFBE5F664BE636237A9855F6D8ECB29618636970365FBE5DB320E4E62376EC368805324468ACA6BC7BF113E144CC67CF5489143BCCC9E6E5EB4AC59F05B5B7C004BBD5C105DEBDDF5E79D3A49B9FDE0EC4EF4B08B6BDC03686C3104B88E316F6F72DB974DA880A5B6E25130B42A52A1C8823B5793F6CFC2BC5E027AA6192432892774E5C481C75AB919C4F8C4054A71A33F6D3F7CB5CC76EFDBB37AA6D97DEF1983932FAB2544689D4E4397999CA9AE0D32B633226B0DDA1DE6D08FC30343965092F0C569214012450E8E28D90A0BBEB58B818DA3BB5DC00FA030B100B69052948190201D02B224EBDE69AE37152F1538AD0CC49B72F6FAD2948ACE236780ADD04AC027EA2C7D916AF570232560D8C21C424A97079927FD03D23CA3A53742B749AB3E7EFDBC4462B6791FC53958D5F4F36BF578B9D2EB6F283895E47BC67E59F6C892234D69EA66669533DEB7F38879B8577494D4065532E596773969126C148CC39E8159E9D20C680FFAA709C492C0A83F7EAEEF9F4B8B4464CC1A41FE1C5EC2FC73E34AE50AAEF434A28E398CCE7073EF041A426E21492594FF00D0A7BF468DD18305208043EA1FEDA367D228FE663A9FFF00D87ED487F94BD4F61F98DBFC2F7BBFA8ABF19C598224EA0AA08F9FC7215B7F9254010A19BBB7979F58CFF86902A97D4D07D87BBC1F8A13AE7A73FACE959FF2A9BA5EA6E0866F2039D5B9C63FC66760903437F207D4748709B849410A201391279687F5FF00753585585CBE2337F64E55D73C86BFE3A82AD4C9AA3ADCBE7C21A3972D0D60CF5F58D481F5E5D2A4A4A42981E6065D69AFAE90AA30EA51277496CDAE03707CDA20EF318650A5B08202D319E5CC48CB3CFF005D69F252281B8659F67F2A5290FA561CA40510CF4622D5CADA58D62D5BCBC6A49B8B94A1339852C800753F0EB9D394480B60A0CDFEE6615B548ABF67A43F461CD4B127219EBA7A03C1EB18C76DF791B21B1F85DE6338AE316D6CCE0CD974599B8421EC51C5025B6DA41203C50B0124488E2EF3574D89E085ED7095097BC090FF004B923B7DBCA19E2B1424A424BBFD5AB27CF2BD29EB1CFF0052F6E3DB476A8DFE32DDE6CC6EB706B8219B05872D177ED255C33E1AA597015B61407454F6AEFDE0EF849364AE54F121AC689FA4336A38393E6CF153C5E3021240512493BCA37CDB78FE7AC6F66CCECDECB6C16CF58601B1986B768D59365B2E25A4216B5180A52CA009E23267299AF54F86F672F644A952CA5B7404D29976E1DDC18AE4DC495AEAA2CF99ABB73FD680677731656D7366B75C3E0BCA12E1C84EA79E672D663F5AB6CFD9EBDA83751BCA243E6F9643C867935A044A2B2491AB7B66B0605EFC8C37B5B668B0DDA30A2B6D2A30A104925524C9EB9919FD26A5766ECB3834A65AD0410F96BA599EC2FE6D0C718D2DD35000A92EFF0070FC5B5A0631B29BA6D9C21E65C08C8A92743D729F203F6ABCECD96C94D2A72CC8143CFDD6B145DAAB7DE2E5FA7A5FCAFC6379F0867F0F87B0D10470A743DE0F3E5570C3A5887B1D2F62FC2F147C5CC725AEECF7D0FA5B2CB9C9D2B3087352DC72F3E5EE911BF32AC547B96F7AE435876CFE41E66B32CDEB4A379C2E92E906FC7AC2B4A46D0510414410510414410510414410510414410510414410510414410929064C6739D6E9504BBBD5BEF0D972D459859F5E1C22A4248249F2A4D41C11EEF0A24177666D61B2D8714E958238491A93947DE7F72D664A529D9FFAB37BFD2C181048B438E0CB5CFE5FBD22AC312962F93D3AE61BCE3255F56F0E8FDA2D3C76DEE31143F60865A29527878DD4CFE607F29194C76CA0674CE7210414EE90A66A8B355DFF00BABE4D0F30E374098A5115B3DF2B75B3DF48D29DE7EE81EC25F7313B2BDBC05C5296FB2870F8644CC25206801391CF3CEAA3B4B0F88FAF71442AC0825DAE486D1DB3B6B7BEEC9DA0896849B80CE3CA9FAE51AF97187B56F76B45BBD7EC37925C4BEAE149207BD09034267A73354DC4E0F686FD56A524E44927370030E2ED7ED17295B5D0B48029C2DBDA1E35E0DC6AF093682CBC1AC398694167FAAFF0FF0057A92950E799D40A4D3266A48DFD5944F503476E35BC626CF135254D52CEF6B86D5FBD7842F7987AC2D50A5A814A4F13C6564902412390CE04E4075A96C3E0B0CB4BAD0144DAC7B07FBE79D214958A44A001EF7B5455F9BE82916EDCD9A9274D394FFACB9E91D795666E1306827FD31FFD23ECF9D3DD1C231C951228C0F56767F23DDD806868E58DB78056DA26E553C5C63DC1D2329D2751F2A8D9D2A42086450568056CC2EFDFC9E1EA26850749619B96ECC6BCFCAB4B3EFF000643CA2A76E6E1067F2B4A1C1E5A1F8CEA08A62B54AC9200B3066B655A7439584384A966DDEAFE54F2D22199C2D9B275D5B4DA145407BEB48F117023DF235E824F59E95193247CD984DD2694B75F36CB430FB0F2E71008530D41208FB65E94D6CFDB0D93C236B70CB8C2717C2AC1FB6B84942C964294A4AA66788473F3C8F794311B0B098992A1364824E7BA33E80B3EA79E462D380C61925017500D49B65573FA191168D19DB3F664DBFDD29736E7D9B719698C5D6A5DCDF6CCE22FB89C2D0106786D2CED42540B89E22A0755281CF2AE29E32F86F83C7CB9BB92424A829B71201CFB777148B8E1F6E484240500695736CC5DBB6515EEC3DB771CB1C5D8D94DFCEC662FB2DB40DAC30EED13160BB2C0F891092EAAEAE55C45110AE2CCF9675E33F1B7C0ADB7899D357835AD287247F3720540A03A6B1292FC418520B8B86000147A1CECCFA3BDF4E87ECB6F036476B9B6DFD9CDA2B1DA16D684B89BBC3EE9174DBB29E2284AD33C4A6F342C7250E935C3319E12DABB0712AC0E2513173525B7D94451FD68DCDB81504F933C6FA0009360CDC0F2AF5CF9647C331B5292A952AD4A084FFF0022513248919E607603CF952A36362C23795296903FE40D7859FA13F686CB4058CB872396777E2F1778C6EF2D582B0A53EDA38214DF110BE331EEE70424913032F95436254BC2A94952542D71A6648E1D6D9444CDC1A4A8FD22AE48D3BB68F9B70222455B4D756C9694B0E2D4E09094495088D472F21D472AD64CD334B82C4317D35AB9B4305ECF0A2E052EF60EE7DDFBC4BDBED236FB4DADD65EF19C305B09F78198CC6713FE69962B1E64CD2820AAA6B46F7A9D78C339929129450A42891983FB1A8A5EF12C9BE44A78DB75949FEE713C20749E629346D12A3541166B55FA1B76E302512D401092736724F6730E1FBE6ED9A0E825E4A808F07DE27CCCFF00A83953C9334AD8258BDA9DEC5DE3099466160821B23CEC18D73FCC26CE32DBA9E2216D000E4E0E1518EC7F61F0A9093835CC75070EE4795EB5E59F3853FC298EC03926A2EC28ED5157340417F2886BBDA74A2E0B6DA1F7018014D00A403CE6397FB3AD49499A70E7E5EE289CC81D3BF377A55E1F4AD90552C15EE8A5CDFABE61F9579C20F63C86C02E3E1B075E3504F0889CE63A7CBD44D6096B9AB4B2147A6668E7FAA1CA30766194EE46EB3029A3D5BCEB9FDE31DED7EF0B67F6612710C4710694CB82438DBA928102082547AC0D27D6AF9B23C3789C79425093BCA6BF16CAFC0FE03422BDC94EF5E7FD30CEBEC6986F43DA1DAC5AF11846C65CBD7F7B70781A4D9AFC585188E2E054E848FBCBA76CCF851B4F18942805004A49B8A38B822A1E1B2B69C9942A0588BB3B38BE64F4BDF45F6437138D6F1D386637BDABEBC6ED2CD65FB0C2AD5C5254F052B8E31261E1EF24C24B607F6933CABD3DE01F86E76761651C4A0129097701E9AB8AD341776CC45076C6DB96310A4805AAC435DAEF903C637170BC1B07C22D6DACF0CB0670CB5B3425B6AD6C5B4B2C3C94A42429E424C29440E23A1E23AC57A2B65E070182C3A50A949DE48000DD1F8C9F26EB157C4635539F7598DFBF3E4FAC5C4EB4979A42AC98436B392894F0A0C18CA3393CCE93DA92C64844D98552C6E8B06B3741DBEC6B08494294A05F788B3126EEC39D756BC0F5BA516E52B0B0A508514446B999CFB919139CE862AC7B0F1387C26EFCF402F4767A5466D6FC67589CC3A928B9761504D6DC789CB8D5CD54D9FB12ABB6DA652B5238F20449CC826791F9F7CAAD8AC08DA2A4CF900250A62C030B72F75393C5736B632589AABD99BA72A37168DE9DD6E0AB432C2D480880932444E5241FDF3ED52985D9AB92A00D599F5176D03DCF1245EF147DA0B4A8296429839005CBD3D7CB2358D9069B21090001023A72FF00433A99972F728A72DA9AFA51F93DF58A5E2120BA83821C56BAF2A7B1A429C0AEC3EFB4D0B46F5B30C7DD623D72F7AD9DEBC5E1CB7926398D7F4F80115B253B800E17D7DFEF38712C86DD1FED1EFC88852B68520A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821A3EE34D92A2015467D48F989F81A6B324EF0248008CF5EDA5EB61942885FF00B4AA8198136BF6EBD22D6C5B0BB5C6D05B7DA42873E248394F2907A673FA9062713852A72433D2999B657F76A9895C262BE4021C90C0DECF90CDB80F28D76DE1EE5517CCDC5CE16D842CA491C020C81D00EBD0EB2222A0F13B394E0B2800EF43404D9F2B795227F09B5104805401C876A5EDCDB5AC6B35AECF5EECFDF2ED2F6DD6485405291F3CC8F3923E7509336792A50DD37BB54BE4697E7A44E236900032AFFED2E74ADAB9D9B5176892BFC33C5714B4A40040CA34C88F4F88CF5CE95460FE5A40666A3B1EA3856E087B16A557FF00304C6DD37CC963636AD9F969AC5AB79849930939EB9798CBAC4D369D215BA4B07197AB73EC61DC89C01363625EF4A9A9A38D74B59C413F61C1C49888EB9779EDDB3EF50F89C392E4675E56B7323C985E26E4CF70327B686EFF00AE15E56D5E589E239489CB43CF97AF3FD62A24C9625C647A6B968CCF7E31252A7848157D2A19C5387463E8D10AEE1DC4147864C667E323423EF2D49A66A5EE2C0341A350DA8783FDEB133879E0241DE07870B3533FC86CA21DFC3553A13E59FC2048CFFCE993B4AF7D208343D9F90F7A43D4625259E95701E8E3813A674842D2D9D6DF5B686020019BCB494A5723FEDA98CBAC75E9178DC399885101DC663EC6E3FA6178749C502A636C8022A5AAFEA22C5DB5DD5EC06D9A56CED7ECD5AE22873253CDD9B6EB99F3E258D4E93D7AE7547C76C654D52814BBB801A95A58FBEB50EC62B46073770C39E7C9B5D2358769BD8D5FC18DEED1EE5B6E719D92D176381BF889B2C2D970020A516D6E9C92E2C4AA224CE872AE7F8DF84382DAF89562A74894B98A2FF5A6A5854971D6834ADA2C982C7A53280DE6200706C5ED9F5357E04C60C637ABEDA5B98C69CC3F783B1B866D6EC55BF1A9CC6707B0BEBEBF36EDA54BF13C77086F88849CC889CF28AAEEDDF83982C3E194538745029BE9E1614AD39D2B7A449C9C626630B3B333E75FC3FDE919A775DFC477737B73776DB34E626E6038A61EA71AC52C318798B7B9B67944801D6B8A5292B04A246600033AF2A78F3E1A623040E213865224CC2AF953770842F74B16362D6247F6FE5044C53392736233B5FF0059E85B6C70DDFE6EE31265E36BB6DB3EAB87024DAA1EC41A0662600067211315C50F8731B266EE2028024D81D73A73CFCEB1228C0254086C9ACE03F215EF9D844B61BBD1C2AF8AD4D63D87B970DE65DB7B90A61433238153C80131A6A3A53F95E1433803350EB3A8E3FDD2EE6174F86D33C0594824D4E9E60FBB6717261BBCC43C1DF1F1266EDB6B3E169E0BC87627B453A1E0EA809964D724BB771EEB01F0DA10092814B960FED8449FFEE8E10E5AB6E1BB2C34A2A002969470C18248073CFBE94FA4783E72082892A615FE2FDAD715E26819A103B225A0BEE80012C5AEC73B8D323CA23717DEAECDD8E1EBB84E2C2E16904F84D3E9528F6893AE63B7ACD494BF0D62890912D49721C37767EF9706784FFC244B56FB208A31A6F646BE74AF58C4B79ED47B2B84D8285CA5EF1D5E22521213E285490264F32411D6262BA56C6F86EBC6E1D334C92544554525CB90F56EA78E60444E2F172A42C85123402A939D6AD4CF2B5B2C2D896FF76C31E7DC6B64306C43145BE48652F30B7904AA40808327CBE9575D9BF0B5689809901A87F8E8796A2B1098BDA89DD2029935B1F79BD9DF5156A309DC7EF7F7C0EA5FDE25F39B2981CF1A2DEDDC7ACDC08992149765209232EB273CCD764F0D7C3F32572CFC948008B2780D00C868DEB157C5ED10EE54C0BBD682E00CAF616A9E91B47BBADC2EEFF621808C3B0CFE6F7AC0138BDD32D3EB0B4C92B0FA6089339E672CC577ED87E14F952D2E9600682ACD4B5816FB457311B40289216F53C5891EDB96869995A64786385C0B0320419000C824764881A888F4AB72657F88D2AC2D4A12C3A31A55FF005159C54BF9EB52C3D3B8D6A59EDCA14F00F5F4E7F18229CA092A152473A5453843032FE5922BD7F1D7F1136D5E356B668429292A1324F39396BAEA0F202A4E4E154B1715A37AB5383119D3284FFCA1243B81773A5FCECFFDB1685CC4D7C2DB5C5240809D2644EBA9E43A72815252B66294A02C4B1A5AF5E43A8A645E3076ACBFF9E55AF36CAC3A3F08D8CDDB6EE55768B5BC799E10A2492A4F43DFF4CEBA1EC89224E1820DC5B4BD5C9D39E715CC6E3133662D64B019937BB8A3DCF1E91B8582E0B6D84DA2128400A4A7A69FAE675F96553491BA092CEDD3DDACFC0D62A98BC52A7ACA45100B30CF9F0F662E2617C6DF144493F414992E49D622E7A774A83BD8F7685AB10C141945BDD21540CBCCFDFEB446C8CFA7BF48AE88520A20828820A20828820A20828820A208FFD9, '1', '2021-10-06 01:13:39', '1', '2021-10-06 01:13:39', b'0', 0); -INSERT INTO `inf_file` VALUES ('427.jpg', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFDB00430006040506050406060506070706080A100A0A09090A140E0F0C1017141818171416161A1D251F1A1B231C1616202C20232627292A29191F2D302D283025282928FFDB0043010707070A080A130A0A13281A161A2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828FFC0001108017F038403012200021101031101FFC4001C0001000203010101000000000000000000000607010405020308FFC40051100001030301040507060A08030803000000010203040511060712213113415161811422357191A1B115233242C1D1161752545572749394B2242536537392E1F0264362083334374482A2F163C2E2FFC4001C0101000203010101000000000000000000000102030405060807FFC4003811010002010204030507030402030000000001020304110512213113415114223371B13235617281A1D11552C1233454910642B2E1F1FFDA000C03010002110311003F00E5000D57E96000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832600905ABD1F0F8FC4DA356D5E8F87C7E26D1EA307C3AFCA1F35F1DFBCB51F9EDF564006572800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000115001E49F5480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060C9802416AF47C3E3F136CD4B57A3E1F1F89B67A8C1F0EBF287CD7C77EF2D47E7B7D400195CA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000454007927D5200000000000000000000000000000000000000000002407DA9692A6B24E8E8E9E6A893F26262B97DC84928B67BA9EB1A8E6DBD206F6D44AD67BB8A931599ECC3933E2C5F6ED11FAA2A09D26CC6E8C44F2AB9DAA05EC74AABF6184D9B55AFF00DDDF2CEE5EC4949E4960FEA1A6FEFF00AA0C09AD46CCF51C6D5740CA4AA6A7F753267DF823B73B05DED795B85B6AE06A7D758F2DF6A6508989865A6AB0E49DA968997301E517D5ED3D10CE000000000000000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF500065728000000000000000000000000000004BF41E9EB75E9B54DAD95ED9E3C2358D5C70EDC7ACE4EA7B14F62AF5865F3A27718DFF948638CB59B7279B6EDA2CB5C11A8DBDD96BE9FA165CEF549472395AD95F8554E7C957EC3ABAE6C94F63B945152B9EB1C91EF6EBBA9727334ED4BE86F14D58CA7927481DBCE6B13B950EAEBAB9BEEF7064E9473D3C71337732B719E3EE2B336F1636EDB3631D717B15B78F7F7E9F24681B16CA29EE3591D352B15F2BF97777AF7131D47A4286CFA7BCA24A87F96B5513B9EAABC5A89D98CF12D7CD5ADA2B3DDAF8347973D2D92B1EED7BCA060032350000000000000000000000000000000000000000000000000000000000000000115001E49F54800000000000000000000000000000000000063217FDFAC9D58F4A525B6DECBD6B391D4D46BC61A245F9C9D7AB29CD3D5ED2621873E7AE18DEDDFCA3CE51FD37A6AEBA8A454B6D32AC2D5F3A793CD8DBEB5EDEE4C9275B7E8FD2EDC5D677DFEE2C5E34F0E12362F7AF2F6AAAF71C8D49AD6B6EF079150B3E4DB4B3CD65343C329FF0052A7C1381172DBC4766BC62CFA8EB967963D23BFEB3FC2695BB47B9A46B4F63A5A3B452FD56C51239D8F5AF0F71DFB1E89D41A9EDD4F71BBEA3A88E2A96F48D8BCE55C2F2CF144F7155390FD41A178E8EB3FECB1FF002A16ACEEE7F1498D0E2ACE0888999EFDE50A8B63B6A545E9AE55B23D79AA6EA7D87D1763B65C79B5B5C8BDBBCDFB8B0EE956DB7DB6AEADCD57A4113A556A2E15D84CE08F684D6516AC6563A2A39297C995A8BBEE45DEDE4CF0C16DA1C5AEB75D6A4E48B748EFD9127EC966A3C3AD3A82AA07A72DE454C7F95508954EADD53A5EED516DA9B836ADD4EFDD7B676A488E4E6985E0B83F43751F9B369E99D7977FF11BFC8D22D1111BBA3C2F516D6649C79E22D1B7A43AC97FD29A85772FD69F936A9FC3CAE8F967BD138E3D68A685E341D5C34C95F60A98EF16D5E28F8573237D6DEBF0E3DC43B0746C97AB8D8EA92A2D754F81FD6DE6C77EB379298F789EEED7B2E4C5D705BF49EB1FCC39EA8A8E5454C2A73EE058A8FB1ED09158F6C369D4CD4E0A9FF7752BF7FBFD641EED6CABB457CB457185D0D446B8545E28A9D4A8BD68A44C32E1D4C649E4B46D78F2FE3D5A40021B00000000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF5000657280000000000000000000000003260EB586C35B7C9256D0B1AEE89115EAE76319CE3E0A45AD158DE593162BE5B72638DE5A343593D05547534B22B2662E5153E0BDC4F6D90566BAA886A6E6D6C5434996E234FF00BC770CF1F611ABC693B9DA6916A6AE362C48B85563B7950B0AE73A69ED0ACF2576EC9D135AC7638EF3B9AFC54D3CD7ACED34EB32EF70DD364C7CF5D4EF14AC6F35F5F462B750D8B4DA3A929A26BA46705644DE4BDEBDA6AD1EBAB3DCB14F5F4EB0A3D513E7111CDF12A9739CF7AB9EE5739572AABD664B7B1D7BCCF562B71FCFCDEE5622BE9B2D1BC58D6C73A5F34EB58A8C4557C38CB55ABD68402FF7CADBE552CD56F446A7D18DBF45A84F765D717D5DB6B282A155ED871BAABD4D5EAF72911FC19ACB85EEE14B6E63563A7915155CEC22679214C3314BCC64F2F367D752D9B0D2DA5E95BF7AC7AA38090DDF48DD6D544FAAA98D8B133E92B5E8B823C6E56F178DEB2E0E6C19304F2E5AED2006CD0D1D457D4360A385F34AEFAAD4F8F61699888DE58AB59B4C56B1BCB58FB535354554891D2C124CFF00C96372A593A7F67F0C2C6CB7A547BF19E898B86A7AD799D0AED5561B1B560A18D923DBC1594ED4C7B791AB6D56F3B638DDDBC5C1B92B1935778A47A79A1743A0EF550D47491C74ED5FEF1DC7D8874D9B36AD5CEFD7409EA62A9F1B9ED0EE3322B68A28E99BD4ABE73BDE71E5D5F7C91DBCB5CF4EE6A22215DB5168DFA42D36E138E79622D6FC5DE9366D588DCC75D0B97B158A872EBF42DE695AAE8E2654353FBB771F628B7EACD473CCC8296774F33B9377117259F6375CDB48F7DF1606BF1BC891FD54EBCA98F265CD87ED4C4B7749A3D06BFA62A5ABF8F928CA8A79E9A45654C3244F4E0A8F6E307C4BF116D77E8248D3A1AB8D8AAD72A71445EE5217A8B67B86BA6B2BF971E8645F82FDE64C7ACACCED78D9A9ABE01931D7C4C16E7AFEEADC1F4A8864A699F0CF1BA3958B8735C98543E66E38131313B4C00008000000000000000000000000000000000000454007927D5200000000000000000000000000000000180A4CB67F65A693CA7505ED11B68B779F85E3D2C89C51B8EB44E1C3B704C43167CD18693796FE9FB551695B3C7A9351C6AEAA7F9D6FA17261CE7753D53DFDDCF99C1D58DBE5C60A6BFDEDAE6C558E5640DEA6A226530DFAA8BED534B545F6AB51DD64AEABCB73E6C5167846CEA4FBFBCB6E66FE1BEC9DAE6377EBA18B7B7539F4B1F344F5A27BD0BC46FD1CBCB6BE9AD4CF9BACDA7699FED8F48FF2816CEB453756256495334B052C0A8C6BA2C2ABDCA99C71ECE1ED4265F8A0B5F5DE6A53FC86E56AA685D96A45F42E13B373873E95FCFF00CA9F028E491E9F5DFF00E6513111DD5C56D4EB6F7C98F272D62768E9BAE45D90DA7F4CD4FB23FB8B26C940CB659E8E8A29165653C4D89AF5E6E444C654FCA4B23FF2DFFE653F4FE85E3A3ACFFB2C7FCA85A9313D9CEE3183363C75F1727346FE9B205B50B3EA9AABBD4D65BA6959676D326FB12A3753088AAEF333D857DA3ED7A8EE6CAAFC189A46246AD499193F45955CE3DC7E93AFA58EB68A6A69F3D14CC58DD85C2E1530A7274B695B66996D425AA391893AB55FBEF57724C2732663AEEC5838B785A79C5CB1BF4DBA7D5D6B7325650D3B6A155666C6D47AAAE72B8E3EF3F3A6D3BFB7977FF11BFC8D3F49A1526AFD9A5D2F7A8EB6E1056D23239DC8E46C8D76530D44FB08B44CC6D0AF08D463C19ED7C93B46CA7CCB237CD345144D574923918D6A75AAAE110B1FF14179FD2141FE471E742E8DABA3DA2A535CE2456DB99E51D2373BAFCF0663C73FE531C527CDE92DC4F4FC96B52DBCC46EDCDA3E9AB4D9B4F58E28B14F7557B299B331708EE19739DEA5E39E79535A92AA3D4913B4B6B0CD35EA9FCDA5AC7A61CAEEA455EBCF0EE72779CFDB25DFE52D58EA58DD98685891FF00EF5E2EFB13C0DB9DD6CD59A1E965A8AEA6A4D4540DE8D1F2C88D59913922AAF6A630BD4B9267BB9F4ADE34F8EF977DE67BF9C6FDBF4F5416F16DAAB3DCA6A1AF8963A88970A9D4E4EA722F5A29A858D0B9BB42D32F8E4DD4D4F6B8F79ABD7511FDBCBDBEB2B84CA2AA2A6153A94ACC6CEB69B3CE589ADFA5A3BFF3F2964004364000000000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE5000000000000000000000000074ECB7CAEB2BA575BE548FA54447A2B51738CE39FAD4E6022622D1B4AF8F25F15A2F49DA5DCBAEAABADD697C9EB2663A1CA2AB5AC46E71CB9162DCA1FC21D0ACF244CC9D1B5CC6AF5AB7A8AA2DB433DC6AE3A6A462BE47AF57244ED52796D9EB3424D0D3DD5EC9E86A9729D1E556254E784F1434F3D2B1B453BC793BFC375192DCF6D56F34B46D33E8AEA46BA391CC91AAD7B570A8BCD0CA16FD65874FEA755ACA791A93393CE7C2EC2AFEB27DE7CE9744596DCADA8AB95D2A3173991E88DF12DED95F38EAC73FF008FE69B6F4B44D7D776AECBEDEFA4B5D4D7D43771B51F45179EE275FB7243DDA9AB28AF171A9B5CC8C65448AAA8AD4545C725C2F592FBDDF16F953F2069D5661ED54926CE1AD6A7344F7103D4164ACB1D524558C4563932D95BF45C570C45AD3393BCF933710BDB0E1A534BBF2D3BDA3D5F7BB6ABBB5D29169AAE76AC2E5CAA3588DCF71C3077748E9E96FD5E8C4CB69A35459644E58EC4EF3667930D77DB6871A3C7D6E58AEF36B4BC69BD395B7E9D1B4EDDCA6477CE4AF4E089DDDE5979B3689B5F9A89D22A72E7248BDFFEF81F2D437DA1D236E6D150318B528DF323EA6A7E5394A9AE15B3DC2ADF535723A495FCD57ABB93B8D488B6A3ADBA55DABE4C1C223931C45B2CF79F2876F51EADAFBC4AE62B960A6FEE5BD7EB5EB23CBC7060F46ED295A46D58707367C99EDCF927790D9B650D45CABA2A4A466FCB22E13B113B57B8F8451BE591B1C4D57C8E5C35A9CD57B0EBC4B73D29748A5960E8A656E51AFE2D722F34E1CC5E676DABDCC18E26D17BC4F246DBCC2C6B65B6D7A2AD4EABAC91AEA854C3A554E2E5FC96A7615FEA7D575B7A7AB379D051E5710B579FAD7ACD0BDDE6B2F556B3D6BD17098631A98462771CEC1AF8B4FB4F3E4EB2E8EB78A73C781A68E5C71FBFCD3AD93D6B9974A9A4CF9B2B37D3D69FFD9B57ED435DA6B55D4B51566A295525E89FD59E7BABD5C5148D6839961D5743BBF59CAD5F61DDDADC28DBAD2CC9CDF12B7D8BFEA63B52BE3ED31D261BB87519238673E39DAD4B24371B75AF5B5A1B5346E6B6A9A9E6BFEB357F25C9D855573A29EDB5B252D5B1592B170A8BD7DE9DC6D69DBD5458EE2CA9A755E8D78491F53D0B23525B29B56E9F657DBF756A9ADDE8D7AD7B5ABFEF9889B69EDB4CFBB2AE4AE3E2D86725236CB5EF1EAA8C1E958A8AA8BC15382A28C1BCF3BD9E40010000000000000000000000000000000008A800F24FAA400000000000000000000000000000004B62D9452DC6E14D474C999A77A46DF5AFFA71F0261B47B8436F8A874ADA9F8A3B73516754FF00992AA75FAB2ABEB5EE3DECBE28A821BC6A6AA6A2C76E85590F1E72393FFA4F138D43A5EF17EB5576A06A31D1A39EF915CEC3E454E2EC263AB897ED0E6E4C94B6A37C93B569FF00CA7F8847510B4F6157748EBEBACF22F99335278D157EB27077B787B0AB10DFD3F7296CD7AA4B8C0ABBF03F2ADFCA6AA61508A4ED2D8D6E9E35182D8FCFC933DB55F56BF51C76E89D9A7A06E17BE45E7EC4C215E9F4AB9E4AAA996A2672BA595EAF7B97AD5572A7CC5A7795B498234F86B8E3C83F49ECDAE34F5DA3ADBD048C57430B6291B9E2D72261514FCD87B8A5923CAC52491AAF5B1EAD5F7135B72B0710D0C6B6914DF6D9FAEB982B9D8EDCE066908A3ADAE8D6A5F50FC3669B2F5555E09C5724EEB2BE9691A8957510C0AECEEA48F46E7D5932EFD37789CD82D8B2CE2EFB361EF6B1AAE739A889D6AA7E7AD65AD6EB26A7B8FC9179AA650B64DC8D237E1BC111171E3922F74A999F70AE62554EE8D677E13A45DD54DE5E499C60D2C7798E6EF55A0E114C13CF79E6DE3D121A6D69A8E1A98A65BC55C9D1BD1DB8F765AE44EA54EC52F4A2D534357A424D4316EF46C815CF6AF36B9138B17C781F9A910DDA5B955D35A6B2DB14CA94954E6BA4677A2E787BB3EA222FEACFACE178B5115E4888989FFB8F36B54CEFA9ABA8A99955D2CEF591EABD6AAB93E58E27A05267774E2368D9BD60BB4F63BBD357D2AFCE44EE29F94D5E6D5F5A122DA65B608AB69AF96C6FF56DD5892B31C9B2638A77679FB4873932A84FB492FE10686BC58645DFABA2FE99479E689CD513BB394FFDC5A3B6CD2D57FA57AE78F94FCA7F894010C9843255BA000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF50006572800000000000000000000000000012DD0BA8686C3154F95C323E57AF9AE6222F0EC393A8EF93DF2E0EA89BCD8DBC2367E4A1C808638C558B73F9B6EFADCB7C31A799F761D4D394EFADBC52D2367921499DBAAE62F1443A7AF6D8EB3DC618A3AA9E68E466F7CEBB795173DA722C35CDB65E292B1EC57B617EF2B514E96B7BDC37EB94735344E6471B37115E985771E65662FE2C6DDB667C57C5EC56DE7DFDFA7C9C6A1AC9A82B22AAA57AB268D72D54F82932D47AC28EF1A696966A6779639132AA89BAD776A2906C054C96BE1ADED169EED7C1ADCB8296C749F76DDE188911CF4472EEA2AF15E782F4B23AD36AB5C105354D3B62DDCEF2C89972F69456015CF83C6888DF66D70DE25EC369B4577995BB5DA734DDCAA5F34956C59DEEDE7392A132B939170D9BE51CEB65723BB1923787B50AE5155392AA1D8B56A0B9DADED5A5AB9309CD8F5DE6AF82987C0C94EB4B36E78968B3DBFD7C3B6FE712F85DACB70B4CAACAEA67313A9E9C5AE4ED45439E5B162D61417C44A2BB431C72BF8223B8B245ECE3D671AF7A01EDBA40B6CF3A8A593CF6AF3893ED42F4D4ED3CB9636953370BADE9E2E8ADCF5F4F387D7669624CADDEADA88D66521DEE5DEE23FAF2F6DBCDDFE670B4F4F9631C9F5B9657D44D35EDCE2B269F8ADB46A8934CCE8DA89CDAC4E0ABF615314C11E25A72CFE8C9C4AF1A5C55D0E3F2EB6F9867ACC036DC077345AFF00C556CFF17EC251B5D5FE9741FAAEF891FD9DD3F4FAAE957FBBCBFDDFEA7536B336F5F29E2CF06439C7AD57EE352DFEE23E4EEE19E5E159267CEC84AA130D9C5FD2DB5CFA3AB911B493AF9AAE5E0C77FA90E43286CE5A464AF2CB95A5D45F4B9632D3C922D7B1D1B350CD2504AD91B2A23DFB9C511CBCF0BEFF00123A8B93BD45A5ABAB2C6FB9C4B1A46D457231578AA2673F038284629AEDCB13BECB6B2324E49CB7AF2F37587900191A8000000000000000000000000000000008A800F24FAA4000000000000000000000000000000C2B55EDC378AAAA22027A427B7DCDA365965A16A2B65B9CCEA9953FE945CE17FF00892DD9DAA7E28EE1C3AAA7E0A4476BAE4A7BA5A2DCCFA14544C6227AF87C1097ECEB09B23B8F0EAA9F829963ED6CF39A98DF495BCF7B5B7FFB95231AFCD33F550FA1DAD11A6AAF54D7B29699ED8A38D8D7CD33933B8DEEEF52D766C7ECDBA9BF595CAFC717239A99F7158A4CBABA9E25834B6E4BCF551E0BAABF63D6C5A7779157D5C7509F4164DD7373DE98429EBADBEA2D572A8A1AD66E5440EDD722725EC54EE5422D598EEBE975F8757BC629EB0D606327D994D52E6E5296A1517AD2272FD846CDB9B447796E69A6A2EA6B46533FD2E2FE742C4FFB40222D4D9F2D4779B273F02B7A1656D1D7535545493ABE091B2B5AE85D8556AE533C0ECEAED4577D54FA67D75BD635A747237A389FC5171CF29DC5B7E9B39B9B14DF578F2C6DCB113BA30864FA792D5FE6951FBA77DC3C96AFF34A8FDD3BEE29B3A5CF4F57C81F6F24ABFCD67FDD3BEE1E4957F9ACFF00BA77DC3639ABEAF883E8FA7A88DB9929E66A76B98E4F8A1F14767B3DA0DE27B4BD926D9AD7FC9DACEDEF72FCD4EE5A77A7739387BD108C9EE095D4F5104CC5547472B5E8A9DCB9FB0989DA58F3523263B527CE1D1D5543F25EA6B9D12261B14EE567EAB97793DCA72C9AED7E344D61D3B795452C7267B578A7D884285A369534979C982969EFB3000219C00000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE500000000000000000000000000000000000080005920000000AA1E8B1F456B58A2A54A3BD4D8731311CEE4CEF2762F7F795C031E5C55CB1B4B7345AECBA3BF3E39FD16F576AAD332488B53D1CEEE48E743BDEF53A13592C35F44CA9968E08E191A8E47AFCDF05F615269AB6FCAB7BA5A6C658AE473FB9A9CC9DED52E694F6FA7B6C0A89D2F9CE44FC94E4685F0456F14A4CEF2F4FA6E2339B4F9353A9A56623B74EF2F9DDB6750CAC74B68AB54EB48E5F39BEA472724F6901BA5AEB2D550B0D740E8DC9C979A2A76A293ED93C756E8EA279679168DA9B8C8D578679AAA7FBEB3BCDB8D9F533EAEDB2235EF89CADC3B9AE3EB34B57364C569ACF58861C9C3B4DADC35CB8E3C3B5BB47AA25B26A5E92E557549F4638D1A8BEBE3F61C3D7D56955AA2AD5AECB23546278271F7E4B3F4FD95BA6ED754C8DCB3B95CE7B7098554C7042A2AEB65C96592A2A68EA5AB2395EB98D79AAE54BE1BD6F966FBF46BF10D364D36871E9F6EBBEF2E6032A8E6B951ED56AA75298375E776D96BECB2A52A34FD452393290BD5BE0BC7EF2B4BA53AD25CEAE05FA92B913DA4CB6472B9B71AD853E8BA34763BD14E3ED0E9FC97534FFF00E54E93DAABF71A98BDDCF68F577B591E370DC593FB7A23200371E7C0000000000000000000000000000000115001E49F54800000000000000000000000000007DA878D7D237A9D33117FCC87C4FA533FA3A9824C7D0918EF63917EC08B7D994BF6C0F576BCAA6AF26431227B1549B6CE7FF292E3EAA9F8290BDB1468DD7123D39494D13BDCA9F6135D9C7FE525C7D553F0532D7EDCBCFEABFD8E2F9D51ED84DDA9686E1574352F464956C63A2739708AAD45F37D6A8B9F02F4CA769F91ADF4F3D64D4F4F4713E5A8911118C67355EE2C28748ED05226EED554B13A9AB5DC93DA296DA36D95E29A0C59337893922B33E52BD6491B1B1CF7B911AD4CAAAAF043F3F5EA2875B6D4960A273BC9267231D2C69CD8C6F9CE4FF7D67DAE5A3B5DCB472255BEA2AA1C79D0A566F6F78678FA8DAD8D5CE86DB7BA8B6D6D2AC771A95DC64F2734DDFF0094A8A9C3EDF61333CD310C5A6D357498B266C578BDB6DBA797E2B4AC1A46CD628D128A8A3E93AE591379EABFACA4811AD44C235113D4641936D9E7F265BE49DEF3BCB184EC4184EC432031B184EC4184EC43200C613B10613B10C803CAB1AEE0AD6AA77A114D4FA0ACB7E85CAFA665354F36CF0351AE45EF4E4BE24B4113113DD97166C98A79A93B4BF2DEAAD3D5BA66E7E495ED4563F8C5337E8C89F62F71C593E8397B1327E93DA5D823BF697A98D199A981AB3C0E4E68E6F578A653C4FCD8EE2D7276A60C36AED2F69C375BED78666DF6A3BA7BB57F3A4D3CFEB75B98AA40C9E6D7711DC6CD4D9E30DBD88BEDFF00420645FBB370EFF6D5FD7EA000AB7400000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE50000000000000000000000000000000000000002C00000000001F482274F3C7146997BDC8D44F5952B1369DA1636CA6D8E8E19EE52A265C9D1C6AA9D5D6A43B565C9D78BFCF33155EDDEE8E344EB44E09ED2C7D412B34D68A4A68977667B12262A73DE5E6BE0995207A06D6B71D4502B93E669FE75FE1CBDE68E3B44CDB34FE8F4DACC3315C3C3A9DE7ACFEA9DCCE4D27A11ADCA24E91E329D6F77595452D4CB4B591D540F564EC72391C9DA4DB6AF74496B21B6C6ECA429BEF44FCA5E5EECFB481A1934B49E49B5BCDA9C673FF00AF18B1CED18FA47CD65D2ED2A9FC9A34A8A2996A31E76EAA6157B8F69B4AA4FAF6F9BC1C8A56461C9927D9317A2238EEB3688E6FDA16FC17ED357F448AA5226C8BC9B3B3757C17B4E45FF67CC7C6E9AC92F7A42F5CB7C14AD53872243A7356D7D96446A3967A5EB85EBC113BBB0C7E05F1F5C53FA33D78A60D57B9ACA47E68EEEBECE20A8A1D552D354C4F8A5485779AE4C2F343E7B564FF008962E3CE99BFCCE2C5B3D4DB6F71C572A6463E66A6EE7939B9E6D52BADAB393F096344C2E29DBFCCE2986FCF9F798EBB3775DA5AE9B86F2D6DCD133BC4A16003A0F22000000000000000000000000000000008A800F24FAA4000000000000000000000000000030A64013CDA7E6B6834CDD5BC52A6912355FF00AD31F79AD69A9D676CB33ED9436FAB4A37EF6F316937B3BDCF8F89B14C897ED924D0A7FE2ACB51D22679F46BC797A957D86FD06D6AB696869E07DAE199F1C68C5916654572A26338C193A6FBCCB8B1E2462F0A948B72CCC6D3FF0071FB23D60A7D57A7EADD536DB3D5367737737E4A5DF544EEEC242BAAB68B95FE8753FC127DC7DD36C75A8A9FD4F022F674EBF719FC7257AF1F91E0FDF2FDC4ED5F553263D565B735F05667E6D776AADA2F0FE8753CFF00324FB88EDC29354D75E52EB35A2AD2B9AF6BFA48E9B772E6E30B84EBE084A976C75EAA9FD4D073FEF97EE0BB63AFE3FD4F073FEFD7EE1EEFA94C7AAC73BD30563F56AFE156D1BF33AAFE093EE33F853B465FFD1D57F049F71B3F8E2AC44E367833FE3AFDC6536C757FA1E0FDFAFDC3DDF563F66CFF00F1EBFB357F0A368DF9A557F0483F0A368DF9A557F0486D7E392AFF0043C1FBF5FB87E392AFF43C1FBF5FB87BBEA7B367FF008F5FD9ABF851B46FCD2ABF8241F851B46FCD2ABF82436BF1C957FA1E0FDFAFDC3F1C957FA1E0FDFAFDC3DDF53D9B3FFC7AFECD5FC28DA37E6955FC120FC28DA37E6955FC121B5F8E4ABFD0F07EFD7EE1F8E4ABFD0F07EFD7EE1EEFA9ECD9FF00E3D7F66AFE146D1BF34AAFE0907E146D1BF34AAFE090DAFC7255FE8783F7EBF718FC7256FE8883F7CBF70E9EA7B367FF008F5FD9A926A7DA33915AB4753854E3FD09086525A6AD75050D05652CF4F3544ECF32566EAE15DC571D9C3DC4F936C95B9F4441FBE5FB8F8E8FB83B54EBEA8D457089B0D3DBE9FA456A3B28C544546A7BDCBE0368F566C739B4F4BDAD8A2B1B7979CF9381B56AB4AAD735AD6AE590323853C1B95F7A9123EF70AB7DC2E3575B2AAEFD4CAE9573D48ABC0F818E6779DDD6D363F0F0D69E9000086500000000000000000000000000000C19300482D5E8F87C7E26D9A96AF47C3E3F136CF5183E1D7E50F9AF8EFDE5A8FCF6FA80032B94000000000000000000000000000000000000000B00000000012FD9A5B52BAFCB3BD33152B77D7F5BABED2225B9A3E99BA7F46BEB2A3849235677F7A7D5F763DA6AEAAFCB4DA3BCBABC1B4F1975117B7D9AF5945F6A1745AABCB68D8B98E99BE0AABCC92ECF28E3B5E9892E350DC3A66AC8ABD7BA9CBDDC4ADE9229EF97C6B132B2544B973B9E11578AF827C0B1768B5CCB669F8ADB4AA8C599123444E68C435F2D76AD30C7EAEA68F2F364CDC432768ECAC6EB58FAFB8D45548AAAE95EAEF51AC8A39837E3A4443CCDED37B4DA7BCBD000954306401D5D3D7EABB1D4BA5A554735C98746EE4BFEA6B5DEE53DD6B9F5554A8AF77244E4D4EC434C15E4AF3736DD59673649C718B9BDD8F27900191840000000000000000000000000000000115001E41F5480000000000000000000000000000000259B2FBAC741A93C8EB38D15C58B4D2B579657822AFB71E270F525AE5B1DF6B2DF322AF42FF31DF94C5E2D5F61CD5CA2A2A2AA2A7254EA2C5BF3135A68E86F50222DDED8DE8AB1889E7491FE5227BFDBD85BBC6CD1CBBE0CF197FF005B749F9F94FF008482AE9E24D87365E8A3E956919E7EE2678B9133929CC96E4772A6AED87D4454F222CB4B036195BD6D76F27B95389512136F263E17CDFEAF37F74B2002AEA8000000000000000058BB0F8A3935157B64635E9E4C8EC39329F490AE8B1361B2322D457292472358DA3455555E089BDC549A7768714998D2DF64675F2359AD2F0D6B5111B3E11113098C275120AACE97D99474DC1B72BF3B7E444E0E6C489CBD9C3FF729E6DB6EA6D59B40BADC5DE848245A89A57A61AAD444C357D7BAABEA381AD2FCED457D9AB1379B4ADF9BA762F0DD8D392E3A9578A9333B4CCB5EBBE6F0F079562267E7E51FE5C2001475C0004000000000000000000000000000000003BF6AF47C3E3F136CD4B57A3E1F1F89B67A8C1F0EBF287CD5C77EF2D47E7B7D400195C90000000000000000000000000000000000000196B55CB86A2AAF62264CB1AAF7B58D4CB9CB84253B4BC827743B38AE9988B55590C2BD8D6ABFEE3AF1ECEADB1373575D3B913B15AC4F81AD6D5E38F37571704D664EBCBB47E32AB816CB74BE94819F3B246FFD79F39F78F93F44B39F92F8C8EFBCAFB6567B44B63FA0E48FB592B1FAAB9D376E75D2F34D4C9F41CECBF8670DEB5279B53B8A52D053DB61546EFE1CE6B7A9A9C13FDF71D8B63F4ADBA7596DF352C52AA6EEF23B2B83DDCA9F4D5D67E9AB24A79A54444CACB8E1ED35AF9F9F245A6B3B43A98387F81A4BE1A64AF3DBCF7F245B6516BDEABA8B8CA986C69D1C7EBEB5F670381AF6E9F29EA19FA3766183E699D9C39A96B5B1B69A3A1F24A09E28E2E3F464455CAF5E72466A367543222F93574E8E55CAEFE1FF007134CF5F16725FF45753C3737B1534DA7989F39EAAB0137AED9D5CA1CAD2CD0D42272CF98ABF123770B15D2DEDDEAAA299ACEA722653DC6ED72D2D1D25E733683538637C9497300EE54C283234DE800480000F2002C0000000000000000000000000000000022A003C83EA8000000000000000000000000000000000ED692BFCFA76F11D5C397C2E4DC9E1EA919D7E29CCE2810AE4C75C959A5BB4A71AC6D4B6CA49AF1A72557E9DBBB375EC6F28D55728D54EAE3C97AB910545251A33543AC6E9E92B61F2CB355652A299533CF9B93BFB53AFD66C6ACD2294B49F2C69F93CBAC7226F2398997C3DCEEE4EDE69D65A7AB4B0E49D3DBC1CBE7DA7D7E7F8FD51107969E88744000480000000000007574CD35D2E35925AACF9DEAE674736170891A2E55557A93B7D878D3F64AFBF5C19496D855EE55F3E45E0C8D3B5CBD44C6ED78B7E8DA096C9A6A549AE9279B5B7044CAB57ADADEACFB93D64C7AB47559FAF838E37B4FEDF8CB5F5A5C68EC9676E93B0C88E631735F50DE0B2BFADBF7F821040AAAAAAAAAAAABC5557AC1599DD974F8630D36EF3E73EB2000360000000000000000000000000000000000001DFB57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6AE3BF796A3F3DBEA000CAE48000000000000000000000000000064C1D0B25AAA6F35CDA5A36E5EBC5CE5E4D6F5AA916B45637964C78AF96D14A46F32D4A6A79AAA66454F1BA491CB846B533927564D9E4D32364BACDD0B57FE5B78BBDA48E286CFA26D8D7CBE754BBEB632F91DDC9D49EE20B7FD6572BB6FC71C8EA5A65E4C8D70ABEB5E669F899337C3E91EAEF7B269387D62757EF5FFB63FCA6EEA9D33A61158CE85274E0A8D4DF7F8F6156DCEA23A8B954555347D147249BEC6A751A88864CF8B07873BCCEF2E76B388CEA62295AC56B1DB67726D5D7B9A1489F5AF4444C65A9BAABE27267AEABA8E3354CAFF5BD4F8221932463A57B4356FA8CD93ED5A65E40305B661DE59000D8DE59472A72554F529B305C6B29F1D0D54ECC7E4BD4D403963CD6ADEF5EB59949A835ADE6937512A3A5627D591339F1E649EDBB4785ED6B6E74CAC775BE3E29EC2B23260BE9B1DFC9D0C1C5F57827A5F7F9F55BCB43A6754C2AEA6585B3AA6731F98F4F5B48A5FF0041D75035F2D0392AE24E3BA9C1FEC21B13DD1C8D9237398F6F16B9AB8545269A6F5DD651B9B0DD57CAA9F96FE3CF6F8F598BC2CB8BE1CEF1E92DEAEB347AEF77534E4B7F747F984338A2AA39151C9C1517A816D5FEC16ED554495D6C7C5E538CA48DE4FEE7779555653CD4750F82A58AC958B87357A94CD8734648F4973F5FC3F268E627BD67B4C3E20C193339EF2002C0000000000000000000000000000000022A003C83EA8000000000000000000000000000000000000614EDE96D4B70D3952AFA2911F0BD7E769E4E31C89DE9D4BDE9EF38A60989D95C98EB92B34BC6F12B0DF66D3FAD58B3E9C9E2B4DE1C9E7D04FC237AF5EEE3B7BBD88436F565B8D96758AE7492C0BD4F54CB1DDE8E4E0A73D1551C8E6AAA3938A2A2E153BD17A949759F5F5DE8A04A4B824375A0C6162AB6EF3B1D9BDF7A293BC4F769C62D460E98A79ABE93DFF49FE51045C99276AED077B4CCACABB04EEE2AADCBA3DEF7A7B907E2F5954DDFB26A2B6D73179239DB8BEEC93C933D978D7E3AF4C9135F9C7F9EC82026B26CC75335331D3D34A9DADA84FB707C9366BAA57FF431277AD4331F1239656F6FD37F7C7FDA1E09D45B34BAB1BBF5F5F6DA38FAD5F36F63DD8F7994B0E8CB53B376BF4B719539C144D4C2AF670CFC49E59F356788619E94DED3F846E83451BE591B1C4C7C923D70D63132AABEA26B6BD06B0D3F97EADAC65A681A9BC8C5722CCFEEC757BD7B8FACBAF696D71BE1D2566A7A16AA63A79911F22FFBEF5521973B8D6DDAA9D5171A996A265EB7AF044EC44E4883DD5667519FA7D88FFB9FE23F74AEFBACA265B56D1A4E97E4DB5E30F97FE6CDDB95E69EDCFA8861E51307A2932D8C382986BB523F99600043280025600000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF5183E1D7E50F9AB8EFDE5A8FCF6FA80032B92000000000000000000000000120D1FA7D6FF005CF8DD32450C288E7AE32E5CF5211F3668AB6A68645928E77C322A63798B829939A6BB57BB369ED8E9922D9637AC792D6752E95D36DCCEDA7E99A9C77FE724FB4FA52EB4D3CC7E237244ABD69163E053F23DD2395D2395CF5E6E5EB3C9AFEC713F6A665D98E3D7C73FE8E3AD63E4B8AFBA7EDBAA99E554D53F3FBBBAD918EDE6A772A15EDDB49DDADB22A3E95F347D52429BCDC7D8722DF5F556F9D26A399F149DAD5E7EB26F6DDA44B1B11971A44957ADF1BB0ABE0A56299B0FD8EB0BDF51A0E213BE78E4BFAC7641DB4B52E7A3129E6572AE1137172AA496C3A1EE3707A3AADAB494DF595DF497BB04A1DB43B5747BC94753BFF93BAD4FB4E05E75FD6D5C6B1D04494AD5E1BD9DE77FA133933DFA56BB295D2F0DD3CF3DF273FE1094250696D36C449920595BD722EFBD54F2BAA34B54B7724647BBFF00541C0A9E59649A474933DD23DDCDCE5CA9E10B7B26FD6D699944F1C9A74C38EB15F92D8ABD2DA7AFD0F4B6D7C513978EFC18C78B79107BC690BB5B65545A774F0F54B12653C53A8E35256D4D04C92D1CCE8654FACD526F69DA44F1C691DCA95B32E31BF1AE157C0AC53362EB5EB09F1B41ADF8D5F0EDEB1D9075A4A8E93A3E825DFE5BA8C5CE491D8744DCEE32B5D551BA929FADCFE0E5EE44257F8C4B5247BCB4751BFF0093BADFBCE15DF6895752C732DD036991786FAAEF3B1F613E267BF4AD76234BC3B04F3E4C9CFF008424EDB6697D371A36A920E9719574D87397BF1F71E3F0AF4BCB1A325466EFFD54FC3E054D34D2CF2BA49A4748F771573972AABEB3C389F64DFADED33289E3B349E5C38EB15F92DAAAD37A72FECDFB6BE38A444FA54EA889E2DE441EF3A3EED6D7F9B02D4C5D524499F6A751C2A3AAA8A2A86CD4933A291BD6D5C139B5ED1AA216232E14AD9D7ADEC5C2AF811C997175ACF341ED1A1D6FC68F0EDEB1D908F23A8E9773A1951DD8AC5424363D1772B948D5A889D4B065155F2271C762212C4DA1DA5D1E5D4751BFF92AC6FDE71AEBB45AAA8639B6DA76D3B57948E76F2FB303C4CF7E95AEC9AE9387609E7BE5E6FC2212DA082CBA3E95D1AD5246E7E15EAF7E55EA9D78EAF035AA35669AA97AB6A3122F2557C394F815255544B5333A5A891D24AEE2E73972AAA7C488D1C77B4F55B271FB563C3C38E22BE92B764D3DA6B5042AB6E74314C9C51D02A22A7ADA56FA92D12D92E4B4B339AFCB51ED73792A2AAA7D8685354CD4B2A4B4F23A395BC9CD5C2A18A99E5A999D2CEF74923B9B9CB95532E2C56C73F6B7868EB35B83538E27C3E5BFAC767CC00677300000000000000000000000000000000115001E49F5480000000000000000000000000000000000000C003200212185C271C267A97AD0C804ED3DDF48AB2AE36EEC75752C4EC6CCE44F89F575C2B9CDC2D755AA75A2CCE545F79AB83284EEAF875F41EAB22E65739EBDAE72AFC42222270320895A221E4C80000000001200090000000000000000000000000000000000001DFB57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6AE3BF796A3F3DBEA000CAE4800000000000000000000000064DDB6DAAB6E7D279053BE758F1BC8DEACE7EE3E75F41536FA8582B617432A26775DD8579E37E5DFAAF38B2453C49AFBBEBE4D5001650000197183AF1E9DBBCB4EDA88E825753B9BBED9131C5BCF2724AC5EB6ED2C97C3929B73D6637650C9843AD6DD3B77B8D3A4F4B412BA25FA2E5C3729DA99C649B5E2B1BCC98F0E4CB3CB8EB33F27254C60E85DACD70B56EADC69A4811CB86AAAA2A2F8A2A9CF4E02B3168DE117A5B1CF2DE36914C19530595650F4793AD53A76EF4D4CEA89A865642D4DE572E38276F322D78AF795A98AF9379A5667672000140C9800003AD169CBBCB4EDA88E825753B9BBED9131C5BDA56D78AF7964A62C9937E4ACCEDE8E51930096260004A40000000000000000000000000000000115001E49F54800000000000000000000000000000185036AD9433DCEE34D454AD474F3BD23622F6A9743F4DE8FD196D864BE3595133FCD49266AC8E7AF5EEB392271F81586CF2B22A0D676AA8A876EC4D955AAABD5BCD56A7BDC5A5B5CD2B72D40943536A6A4EB4E8E6BA2DF46AAEF2A2E533C3ABB7B0C958DA3770B8966B7B4530DEDCB49EF30F355A4B4AEAEB33EAB4F24704A996B65851588D7A753D9C3B53AB257BA0B4749A86FF53495AAE869E8B854A27D2DECAA6E278A2F1EE2D0D9369BAFD3F67AB6DD11239EA25DEE851E8EDC6A261155538657BB3C3079D13554B0EB3D59429B8C9DD5093353ADC98E3EF5F796DB78DDA11ADC9863363C569B4476969D737679A7EBD2D7574B4A950DC6FF004913A5DDCA7D6771C29C0DA5E85A2A2B5FCB5624DDA76E166898BBCD56AAE11EDF154CA72C2E7860D6D61B3DBF55EA8AC9E8216D4D3554CE95B2ACAD4DD472E551D95CF0CE3867860B1AF141F27ECD2AEDF23925753DB1D1B97A955B1F34F14276E9B4A273469FC2C98B24DA67BC6FBABED9A684A4B8DBD2F17CF3A9D573143BDBA8A89CDCE5ECCA7B892DB23D9FDFEB1D6CA2A3A474D85C6EC4E8D5E9D6AD77055FF7D477FE467D468186D146F48DF251C70EFBB8E115111CABE1922745B30B22E528AF957E5B1F37C5333CD5EBE08994F69131B76567575CF6BDF2E49ACEFD36ED1F8CABEDA069A4D337C5A68A47C94B2B7A485EEC671C9517BD17E2871EC3047537DB6C33377A392A63639BD4A8AE445453775969FACD397875256B925DE4DF8E744E12A2AF3F5E79A1A9A6FF00B4B68FDB22FE7429E6F498ED33A5DF9B9BA775A3B55D2D67B46974A9B7514704EB3359BCD55CE1517B54E26CEB67A97BA76DCAF0E923A157622898BBAE971C15557A933E2BDDD735DB5FF6359FB4C7F071D8D46AFD3FA02A9287E69D4F4BD146A9F55708D47782AE4B4C46EF398F5D9ABA6AD2B6F7AD698DFF000E8E43AD7B3FA49FE4E99B6D64EDF3375F2F9CD5EC572AF05F1227B44D9DC16BB7C973B12BFC9E2F3A5A772EF2B5BF94D5E784EBC9583955CAAAAB955E7DE48A4D6D7E75A62B6A572B69591742A88C4DE73718C2AAA67970226636DA61D5A6835382F5BE3CBBFAEEB0B65FA52CB78D27155DC68239A7591EDDE555CE11787594FD6B1ADAC99AD4C35AF7227AB25F9B18E3A162FF001A4F89425C13FA7D47F88EFE6522D1D224E1D92F7D5668B4EFB4FF002B37641A6ED37BB657CB73A38EA1F1CC8C6ABB3C1319211AE28E0A1D5972A4A48922822930C6A2F044C21676C13D0F74FDA13F950AE3693C35CDDFFC6FB106DEEC234B92F3AFC94999DA23F84700055DC00000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9AB8EFDE5A8FCF6FA80032B920000037AC75CB6DBCD1D52265237A2B93B5ABC17DCA5A5B47A08EAB4ABEA226377A07B256AB53AB92FB973E060C99BC3BC5663BBA7A4E1FED583265ADBAD7C94F82D1D95D0363B4D555CCD45E9A4DDCBB8E5AD4EFEF55399B58A0486BE8AAA34444918B1AE3A95AB94FE62B1A989C9E1B2DB845EBA38D56FFA2020BAAC71C162D150C93469F334FD33D1C9C55CA9BCA9ED5C113D9F69E8AF12D45DAE8DE998B22A318E4F35EEEB72A75A71E5CB9911AA8DAD331D2192DC12F16C78EB6DED68DFE5081A31EE6AB9AD556B7E92A2706A76A9E50B86E1AD2CF6AAF7D0F412BBA25DC7AC4C4DC62F5A734E5D7833A9B4ED05FED0EADA16312A959D2C534698E93AF75DDB9E5C7914F6B98DB9ABB44B2DB8145A2D1832C5AD5EF0A74F4D6B9D9DD6AAE1155709C910B4F64B1B24B0D52BDAD77F497734CFD461BD2DE2C3A6EB27A573F153348E9665646AE54572E7CE5EECFB09B6AE62D34AD779571F04ACE1A66C9962B13EBFFEB81B1F5F9EBAFEAC7F171C8DA8AFFC56FF00F099F6926D9DD67CA3A82FD54888D64AAC73513879B9763DC7CF50E9B9EFFAD5EEC2C7451C6C49264EDE786F7FC33EDC3178AE79B5FA746F5B4D6CDC3298B0F5F7BFCCAB005C7A8EF16DD2F6E6D252C50BAA91BF350639762BBAF9F8AFBC8169CB14DAB6AABA69AB12196356AB9563DEDEDECF7A631836A9A8E6AF3DA36872753C2FC2C95C18EDCD927CBD3F5464162FE2CA4FD28CFDC7FF00D1CDD43A1DF66B44F5EB5E93245BBE6245BAAB972273CF793ED38A6768952FC1F598EB37B53A475EF0B0ACBFD8AA3FD85BFC88413416A3B5DA2D33C37255E95D3ABD311EF70DD6A7D84EACABFF000551FEC2DFE4423BB298209AC555D2451BB76A5C89BCD45C26EB4E7D6622B6DFD5EA7356F6CD8231CC44F2CF7EBE8835DE782EDAA24922CAD3544CD44CA6155382722DED4B5EB62D3D355D2C2C73A246B58C5E0D4CAA2272EAEE21F4178A3B2EB5BBC53C123FCA266471F46D4546AF7E553B509CDFAE505A6D72D65546F9216632D6222AAE571C9553B49CF69B4D6BB7462E198AB4C79EFCF116999DFA76DB7531A8F50D55FE581F56D8DBD1355A8D622E32ABC578AAF77B0E4265CE46B532ABC93AD549356AC3ABB5840DA06BE2867C22AAA615A8D4E2BC17B13813DB957DA345D143143499924CEEB1A89BCFC632E72A9B7E3785B52B5EBE8E25787DB596BE7CB97DD8FF00DBD7F4538F4731CAD7B55AE4EA54C28452DFB2DFADBABE3968AAE85AD95ADDE58A4C3DAA9CB28BDBCBB17895CEB1B2FC897C969D8AAB03DA9244ABCF757ABC1514C98B51CF6E4B46D2C1ADE19E0628CF8AFCF49F3ECE3977EADFEC857FF81F6147A17FD7B29E5B3CADAE544A5E8F32E796EA2657260D6CED6A4BA3FF008F579F1E7AFAC7F2A011AE56B9C8D556B79AA27043C97258356D9EBAB9B6EA589F4EBF463DE62358EF5617811DDA85860A564572A385B12B9FB93358984555E28EC7B7DA5E9AA99BF25ABB353370788C13A8C3922D11DD5E9F4E8A4E8FA458DE8CFCADD5C7B7916168BABD376AB52544D5113AE1BBBF22BD8AAE6AE3E8B729F0EB3A769D72CB95C9B4B0DAA7742AE46F48C5DE56E579B91138278936D45A26796BD20C3C270DEB59C99A226DDA2237FF00B54C5EB65FEC551FEC2DFE44227B4DB0524148CB95344D8A457A32646261AE45CE171DB9E1E24AECD84D1547CFFF0002DFE4435B519632D2B6875B8568ADA2CF9715A77F75461E991BDF9E8D8E7639EEA6495E824B1433CD517B9A2599AA8D8A2918AAD4EBDE5CA633D9D9825157AFA8E3AEF24B6D03EAD8C76EAB99C33FAA888B936AD9AD13B56BBECE2E9F8762C98E32E5CB11BF977955460B9B54D9A9AF9627D5793AC356D87A68D55BB923571F45DF035B65D1B1DA71CAE6B557A777154CF5214F6C8E49B6DD9B3FD06D1A88C336E931BC4EDFE151E1CBC1A995EA4EB55EC430B945547261C9CD3B0B62A2FDA7B4DDDAA69DB03DF52F955F3CAC622AA2B955DCFB133D474F5A5AE96EFA72A6658DAB2471ACB148DE7844CE33D8B823DAE62637AF4947F43ADA979C79626D5EF0A50F4D6B9D9DD6AAE132B84E484E3675A660B8A495F708FA48A37EEC71AFD1739138AAF6E3284AEEFABACF64ABF2148A47BE3C239208D1519DDCD3DC5EFAADADC948DE58B4FC222D8633E7C91489ECA73031DE5B1A9A8EC17DB3A55A54D2D34F237A48A773918AE5EA4777110D05A763BD5CA5756377A929B0AE445FA6EEA4F5732D5D4C4D66D31B6CC59B84E4A67AE1C768B7376945DB1BDF948DAAF544CE113A8F05BB7BD5D6DD3B55F27D2D1748F89137DAC446B19D78E5CF1DC6C4715A35B595D3A41BAFE2C47AB51248DDEBECE463F6B98DA6D5E8DBFE874BDAD8F1E589BC796DFE54D983ED594EFA4AC9E9A54C490BD58EF5A29F1373BF5702D59ACED20002A000000008A800F24FAA400000000000000000000000000000001B36DA292E15F4F4703A36CB33D236AC8EDD6E5782657D782CBB97E1DE90B440E4AC4ABA654566236F4AB172C6555B9F6E53815631CE639AE6395AF6AA2A39382A2A75A16659F6B55D4B44C82E56F8EB646A63A56CBD12B93BFCD5E25AB31E72E6EBF166BCD671D22F11DE27FF00B4D765EDBABAD75B75D4324AB5154E4DCE993755236A705DDC26EA655DD5DFD656D414373D59ACEE971B055454F347374AD91F22B17755551B8C22AAF04E29DE7AD59B49B95F28DD474B0328291FC246B5EAF73DBF92AEE1C3C08AD86F35B60B9C75D6E911B33515AA8E4CB5ED5EA54ECE05F9A22366AE9B459AB1932CC445ADD223CA13CBE5E75F5BEBBE4674D34B2B9C8D64F153B7E7117B177797BD09AEAC992C1B319E9AAE6E92A56952955D9CABE47261CBED5555F122ADDB34BD1A23EC91BA4FCA4A9544F66EFDA41B576ACB8EA99D8EAE56B208D731C11F06B7BFBD7BFD98226D11DA5829C3F3E7BD2B931C5223ACEDB755D50CD35F3661BD6C72AD5CD43B8D46AF1DF46E1CDCF6E5150ABB66D65BCB359D13D292AA9A381EAB3BA462B111B85CA2E7B7960D2D19ADAE1A5F7E281AD9E8E476F3A07AAA222F5AB57A95496546D8AA16354A5B3C5148BC9CFA857A7B11A9F12DCF129F63D569A3262C548B56DE6DADB4C1F29DD74FDB69918EAF9164C22BB1C155A888BEBC2FB08737485DB4FDE6CB51728A3646FAE8636E1E8B95DECF57A8E5B351D63F53C37BAD72D454C72A49BB9DD4C27D54EC4243A9B6892DF56DAAEB7320F23AA654A625DEDFDDCF9BCB8732B368DF796CE3D3EAB4F4AE0A444D769DE7E69F6DB3868C8FF698FE0A75AD7241AC342358E7E3CAA99617AA7D493185E1DCA992A8D69B419753DA1281F6E653A248D937D25DEE5DD84385A5F54DD34DCCE75BA66F46F545921913798FF0FB899B44CB4E9C2B34E9A2BDAF13BC3E957A2F50D35C92896D55524AAB847C6C5746BDFBFCB1EB542C5BA682B1DAF447945DA356575341BD24D048A8AE7AF1DD4EA5E2B84CA761A71ED8E548D3A4B2C6E913ADB51BA9ECDD5217ABB595CF53AB1957D1C548C76F369E34F373DAB9E6A47BB0D9E4D7EA2D4AE48E488EF313DD676C42BA39B4C4F468E6F4D4F33955B9E3BAEE28BEDDE4F02BCD5BA26F3417CAB482DF53534B2C8E7C32411ABD15157288B8E4BD5C71C8E0586F55D62AF6D5DB65E8E544DD722A65AF6F62A7616353ED8E7489A953668A495138B9950AD45F056AFC47344C6D28B69F55A5D45B2E9E39A2C956C974FD5E9FD3F3FCA2C58AA2A65593A35545DC6A222222F7F055F1294D5F5CDB9EA7B9D646A8B14B3B958A8B9CB51708BE2888A493546D2AEB79A57D2D346CA0A67A61FD1BB79EE4EB4DE5E48BDC840C8B5A3688867E1DA4CB4CB7D467FB56F2640055D900000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000171E8DA88EF9A35B4B33B7B76375349DB8C613FF8AA14E128D0FA9A3D3B254A54C52CB0CDBB848F0AA8E4CF6E3ABE06B6AB1CDE9EEF7875F836AEBA6CFB649F76D1B4A6775CE9DD9C369D331D43A148F08B8547BD7CEC75F5B94D8BC52FE13699B6CC89973A486454C752AA35DEE55F610BD6FAAE2D410D2C54B14B1471B9CE7A4889C57184C617D7ED37B496B6A6B3D962A2AC82A247C6AEC3A344C61573D6A9DAA6AF8178A45F6EBBBB71C4F4D7CF6C336FF4B96223E70EDED52E294D638A89AEC3AA9F877EAB70BF1DD36B6613324D2D1C6C5CAC723DAEF5E73F0542B9D637D4BF5D52A236BD903188C635D8CA76F2FF007C8F3A5F5154E9FAB7490B52585FC2485CB8476392E7A94C9ECD6F07963BF76A7F57C71C4A734CFB9B72FE8F86A7A6969350DC239D8AD72CCF7A653E922B95517D8A5C3A4A1928B4B5147548B1BDB0EF391C98DDEBC2F6703851ED06CD335AFA8A6A86C8DE288B1A3B1EA5C91FD55AE9F74A27D15BA17D3C12262491EA9BCE45E6984E09ED52B6AE4CD1159AEDB33E0C9A3E1F6C99E9979B9BB424DB2D9124B3D7C8D4546BEADEE4CA617E8B4AD75348B36A2B9BDDCFCA246F823951090E8AD594BA7EDD3D35553CF23E49964CC7BB8445444C715EE22972A86D5DCAB2A58D735B34CF9511DCD115CAB8532E1C76AE6B4CB9FAFD5E3CBA2C54A4F58EF09E6C753FA4DCFF00563F8B898DDB51D05AAE1494750F5E96A1C89C3EA22F255EECE3FDA159688D474DA79F58EA98A593A746A37A3C70C6739CAF79A5ABEF10DEEF4EACA7648C62C6D6EEBD133C33D9EB31DF4F39334EFD9B9A6E2F4D270FA56931CF13DBF54D3699A716A62F95A8D999634F9F44E6E6FE57AD3E1EA2B6A5ACA9A4DEF25A89A1DEFA5D1C8ADCE396704FAC1B40829ED51535CA9EA67958DDC57B11151C9D59CAA71209767D24B5F2C96F6C8CA67AEF35922222B73D5C15781974F17AC78778ECD0E2D7C196D5D569EDD67BC79C4BEDF2BDCB8FF58D6FF10FFBCF94D70ADA889D1545655491BB196BE6739171DCAA6A21E9BD66CF2D63C9C9F1B24F49B4AF1B327FC1547FB0B7F910E36C8D3FA8AB3F6A77F2B0E5506BBA1A7B0C16F75354AC91D3242AE4DDC2AA371DA73F43EACA3B0DB27A6AA86A1F23E65951636A2A222B5A9D6A9D873270DF96D1B79BD95788E9BC7C36E78DA2B313FB34B50FF6F65FDB19F61606D23FB1F55FAD1FF3A1575D2E50D5EA675C636C9D03A76CB8544DEC263298CF3E04A3566B5A0BC58E6A1A7A7AA64AF562A2BDADC70722F538CD7C5799A74ECE7E9F5986B8F5516B6DCDBEDF8F77336673321D55123F199237B5BEBE7F61616AEBD45656C12D4DBBCAA27AAA6FF0C317861173DBF614B413494F5114D0B959246EDE6B939A2963DB76894D25224577A47ABF1873A344735DDF85F871275386D378C911BA384710C74D3DB4F7BF2DB7DE276DE1B169D62CADA87A5B2C2F9256B72EE895A9C3D7822DAFEE53DCAB699F536FA8A27C6D73712A7D2E29CB87124EFD7B65A389CDB75148AF54CEEB6346267BD7FD14AFEFD77A9BD5C1F5556E4E3C18C4E4C6F6211831CF3F372ED0713D5D674DE178BCF33E91110E7A17B6A2824A9D3159140D57C8EA75DD6A75F9BC8A250B366DA3D1B6955B4D4D3F4CD44DDDF44C78F12FABC76BCD66B1BECC3C0F53830D32D735B6DE3F942F47D2CF57A9681B4E8ECB256C8F544CE1AD5455CF67678962ED4E546699E8DDF4A499A89EB4CAFD86BC3B40B4246B23E9A78A77226F31AC4CAAFAF3F120FAC752CBA86A63548FA2A58F8C6C55F39557EB2E3BB063E5C9972D6D35DB66CF8BA6D0E8B262C7939E6E9EDB34F5A74F587CBABE9A3A89A38D1F2BDEDDFE3D8D45E073E8F5B54DCEB62A1B2DB1B1ABDC88AE72E775BD6E5444E18F5A9F2B06BFA46DB23A5BB4122CAD62315CD6A39AF4C63976F69F2B9EBCA58617C760A148A477395EC46A7B13ED31C62C9369E6AEF3FB36FDB34D4C549C1922958EF111D6521DA871D2927F8ACF89D0B3FF0062A8FF00616FF22108D55ACE82F763928E3A6A9648F56B91CE46EEF05CF6E78F2E47DEDFAEE820B053DBDF4954B2C74C90AB911B8CA371DA57C1BF8711B79B2CF12D2FB55EFCF1B4D76FD5EB679A628AAEDE973AF8D27DF72A471BF8B511170AAA9D6B9F81F6ACD75494150EA4B2DAD1DBAEE8F7B1BA8AA9D8D44CAFB8E368BD60DB2D3BE8EBA37C94EAE57B1ECC658ABCD30BCD3ACEDD5EBBB3C2F74D436F592ADC8B87BA36B3DABCCC96C7926F3CF5E68FD9AB8353A6A69A9E0E48A4C77E9BCA5B13EAE4D3CE7DC11ADAA7D3ABA46B5308D5545E18EEE470F653C74BAE787CF3FEC39147B42A75B6F4374A7A87543D1C8F744898C2E708995EC5434B486B0A3B0DA568EA29EA647F48E7658D4C71F131F81922968DBCDB7FD534939B1DF9FA444FF8EE8AEA37B9DA86E7BCB9C554889FE654FB0B9D7FB1ABFB17FF00A147DD2A1B5773ACA9635CD6CD33E44477344572AF1F693FFC3CA04B22512D3D4EF793F45BD86E33BB8CF3363518ED7AD368ECE570AD6E1C3933DAF6DB9BB7EEEDECC26649A5D91B172E8E57A3BD6AB9F82A15A6ABA59E975157B6A5AE6B9F339ED554FA4D5555454F053EFA5B51D4E9FAA73E26A4B4EFFA712AE33D985EA5276CDA159A68DAB5305431E8B9DD7468B8F795E5BE1C93688DF764F1B4DC43494C3932725A88851E86BBD5504554C4818D91BBC8C7B951E89DE9824FB257B194972A6739AE959322AAB573BC8A98E1DD96AFB4E76A6D7E957472525AA17C69222B1F2BD51151392E113E2442C178AAB257B6A69153B1EC5E4F6F62FDE5FC3CB931CC5A1869A8D1683554B6199988EF2B2752EA9A7B2DD24A6AAB42CAB8CB64554C3D31D59416DD592D450F4F6ED3B52B4EAABC6356F15F51F06EBFB2D5C2D4B951488FC6775CC491117BBFDA1AF72DA1D2C54AE82D14922BB186BA4446B1BD8B84CE78FA8D78C56988AF27EEEB5B5F8E26D97DA2397CA2223741B51543EAAF95751240FA7748EDEE8A44C39BC3AFE3E2734FB544AFA89E49A672BE591DBCF72F5A9F3C1D4AC6D110F179AFE25ED6F59790012C4000000008A800F24FAA4000000000000000000000000000000000005800054000580005800000005400120002150001200094800090000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F4614C9850960C9801564C80580C29930A40C000AA59064043C8009480000000000000003D00025E40010000B0000000000000000AA193201000003C80091E8005800007900048000000022A003C83EA900000000000000000000000000000000000160000000000016000000000004A0000400000000000090000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F400097900040002C00000002A0000000000000000000000003D000240001E4005800000000000000010000A800000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B00000000000000000FFFD9, '1', '2021-03-13 13:10:28', '1', '2021-03-13 13:10:28', b'0', 0); -INSERT INTO `inf_file` VALUES ('5e8609290e915c4fa8b08e67.jpg', 'jpg', 0xFFD8FFE10DFA4578696600004D4D002A000000080007011200030000000100010000011A00050000000100000062011B0005000000010000006A012800030000000100020000013100020000001F000000720132000200000014000000918769000400000001000000A8000000D4000AFC8000002710000AFC800000271041646F62652050686F746F73686F702032312E30202857696E646F77732900323032303A30343A30322031373A32343A3135000000000003A001000300000001FFFF0000A00200040000000100000320A003000400000001000001C20000000000000006010300030000000100060000011A00050000000100000122011B0005000000010000012A012800030000000100020000020100040000000100000132020200040000000100000CC00000000000000048000000010000004800000001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD9FFED160050686F746F73686F7020332E30003842494D0425000000000010000000000000000000000000000000003842494D043A0000000000D7000000100000000100000000000B7072696E744F7574707574000000050000000050737453626F6F6C0100000000496E7465656E756D00000000496E746500000000496D67200000000F7072696E745369787465656E426974626F6F6C000000000B7072696E7465724E616D65544558540000000100000000000F7072696E7450726F6F6653657475704F626A6300000005682168378BBE7F6E00000000000A70726F6F6653657475700000000100000000426C746E656E756D0000000C6275696C74696E50726F6F660000000970726F6F66434D594B003842494D043B00000000022D00000010000000010000000000127072696E744F75747075744F7074696F6E7300000017000000004370746E626F6F6C0000000000436C6272626F6F6C00000000005267734D626F6F6C000000000043726E43626F6F6C0000000000436E7443626F6F6C00000000004C626C73626F6F6C00000000004E677476626F6F6C0000000000456D6C44626F6F6C0000000000496E7472626F6F6C000000000042636B674F626A630000000100000000000052474243000000030000000052642020646F7562406FE000000000000000000047726E20646F7562406FE0000000000000000000426C2020646F7562406FE000000000000000000042726454556E744623526C74000000000000000000000000426C6420556E744623526C7400000000000000000000000052736C74556E74462350786C40520000000000000000000A766563746F7244617461626F6F6C010000000050675073656E756D00000000506750730000000050675043000000004C656674556E744623526C74000000000000000000000000546F7020556E744623526C7400000000000000000000000053636C20556E74462350726340590000000000000000001063726F705768656E5072696E74696E67626F6F6C000000000E63726F7052656374426F74746F6D6C6F6E67000000000000000C63726F70526563744C6566746C6F6E67000000000000000D63726F705265637452696768746C6F6E67000000000000000B63726F7052656374546F706C6F6E6700000000003842494D03ED000000000010004800000001000200480000000100023842494D042600000000000E000000000000000000003F8000003842494D040D0000000000040000005A3842494D04190000000000040000001E3842494D03F3000000000009000000000000000001003842494D271000000000000A000100000000000000023842494D03F5000000000048002F66660001006C66660006000000000001002F6666000100A1999A0006000000000001003200000001005A00000006000000000001003500000001002D000000060000000000013842494D03F80000000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D040000000000000200093842494D040200000000001400000000000000000000000000000000000000003842494D043000000000000A010101010101010101013842494D042D00000000000600010000000A3842494D0408000000000010000000010000024000000240000000003842494D041E000000000004000000003842494D041A00000000033F000000060000000000000000000001C20000032000000005672A68079898002D0034000000010000000000000000000000000000000000000001000000000000000000000320000001C200000000000000000000000000000000010000000000000000000000000000000000000010000000010000000000006E756C6C0000000200000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E670000032000000006736C69636573566C4C73000000014F626A6300000001000000000005736C6963650000001200000007736C69636549446C6F6E67000000000000000767726F757049446C6F6E6700000000000000066F726967696E656E756D0000000C45536C6963654F726967696E0000000D6175746F47656E6572617465640000000054797065656E756D0000000A45536C6963655479706500000000496D672000000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E67000003200000000375726C54455854000000010000000000006E756C6C54455854000000010000000000004D7367655445585400000001000000000006616C74546167544558540000000100000000000E63656C6C54657874497348544D4C626F6F6C010000000863656C6C546578745445585400000001000000000009686F727A416C69676E656E756D0000000F45536C696365486F727A416C69676E0000000764656661756C740000000976657274416C69676E656E756D0000000F45536C69636556657274416C69676E0000000764656661756C740000000B6267436F6C6F7254797065656E756D0000001145536C6963654247436F6C6F7254797065000000004E6F6E6500000009746F704F75747365746C6F6E67000000000000000A6C6566744F75747365746C6F6E67000000000000000C626F74746F6D4F75747365746C6F6E67000000000000000B72696768744F75747365746C6F6E6700000000003842494D042800000000000C000000023FF00000000000003842494D041100000000000101003842494D04140000000000040000000A3842494D040C000000000CDC00000001000000A00000005A000001E00000A8C000000CC000180001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD93842494D042100000000005700000001010000000F00410064006F00620065002000500068006F0074006F00730068006F00700000001400410064006F00620065002000500068006F0074006F00730068006F00700020003200300032003000000001003842494D04060000000000070006000000010100FFE10DD2687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F003C3F787061636B657420626567696E3D22EFBBBF222069643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E203C783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D6574612F2220783A786D70746B3D2241646F626520584D5020436F726520352E362D633134382037392E3136343033362C20323031392F30382F31332D30313A30363A35372020202020202020223E203C7264663A52444620786D6C6E733A7264663D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D7264662D73796E7461782D6E7323223E203C7264663A4465736372697074696F6E207264663A61626F75743D222220786D6C6E733A786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F2220786D6C6E733A786D704D4D3D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F2220786D6C6E733A73744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F73547970652F5265736F757263654576656E74232220786D6C6E733A64633D22687474703A2F2F7075726C2E6F72672F64632F656C656D656E74732F312E312F2220786D6C6E733A70686F746F73686F703D22687474703A2F2F6E732E61646F62652E636F6D2F70686F746F73686F702F312E302F2220786D703A43726561746F72546F6F6C3D2241646F62652050686F746F73686F702032312E30202857696E646F7773292220786D703A437265617465446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D65746164617461446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D6F64696679446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D704D4D3A496E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D3232623834663439646366312220786D704D4D3A446F63756D656E7449443D2261646F62653A646F6369643A70686F746F73686F703A64633333616566382D343164372D343134372D626566652D3133623366363839326632642220786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D702E6469643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222064633A666F726D61743D22696D6167652F6A706567222070686F746F73686F703A436F6C6F724D6F64653D2233223E203C786D704D4D3A486973746F72793E203C7264663A5365713E203C7264663A6C692073744576743A616374696F6E3D2263726561746564222073744576743A696E7374616E636549443D22786D702E6969643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222F3E203C7264663A6C692073744576743A616374696F6E3D227361766564222073744576743A696E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D323262383466343964636631222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222073744576743A6368616E6765643D222F222F3E203C2F7264663A5365713E203C2F786D704D4D3A486973746F72793E203C2F7264663A4465736372697074696F6E3E203C2F7264663A5244463E203C2F783A786D706D6574613E2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020203C3F787061636B657420656E643D2277223F3EFFEE000E41646F626500644000000001FFDB0084000202020202020202020203020202030403020203040504040404040506050505050505060607070807070609090A0A09090C0C0C0C0C0C0C0C0C0C0C0C0C0C0C01030303050405090606090D0A090A0D0F0E0E0E0E0F0F0C0C0C0C0C0F0F0C0C0C0C0C0C0F0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC000110801C2032003011100021101031101FFDD00040064FFC401A20000000701010101010000000000000000040503020601000708090A0B0100020203010101010100000000000000010002030405060708090A0B1000020103030204020607030402060273010203110400052112314151061361227181143291A10715B14223C152D1E1331662F0247282F12543345392A2B26373C235442793A3B33617546474C3D2E2082683090A181984944546A4B456D355281AF2E3F3C4D4E4F465758595A5B5C5D5E5F566768696A6B6C6D6E6F637475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F82939495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFA110002020102030505040506040803036D0100021103042112314105511361220671819132A1B1F014C1D1E1234215526272F1332434438216925325A263B2C20773D235E2448317549308090A18192636451A2764745537F2A3B3C32829D3E3F38494A4B4C4D4E4F465758595A5B5C5D5E5F5465666768696A6B6C6D6E6F6475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F839495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFAFFDA000C03010002110311003F00FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8E35D5BCC737C2D3C9BFBFF666A389DAABAAEB92D09964A9F7C78D5CFA56B736CD2C94EF538F1AA82F96F534916762EE10D78F8E112B54DEDED35BD3EEA09B45B992D25620CA14D3265239BD8EDBCD5E6BB286DA2B8BE79A375FDFA924D4D3205B0232DB5BD4EF199998E5459C58F6A9ABEA16F71CB9114EF9125B120B8F3A5CDA026573418AA583F34D616346AB5298A09A424FF98F2DD0F80D2BE18691C4925DEBD7DAB05B61522434CAF2C51C6FBA7FE7122F60D17CBBA84175B333D4D7E6329E172714DF5E6AFE7ED22CE1043865814FAAB5F118F0B9A26F8C7F30BF306DEE7549AE2C8889391A95FA71E1499BC4758F3D5037A77ACDEA0AB47CBAE4E30713366E12F35D43F302DA14901531CE7ECCA7C72C11718E7796EAFE6ED57516663AA12A0515431E99608B8F2D430D9A677E524F3FAA4F5A9AE5822D0750978B98B8D140D8E4C63B63F9843BDC13F64532431B1F1AD0C5DB916EE72D8E362656ACB7457BE4BC3606368A13F2553F7E5321BB5F0EEDD0B6F916C0141ADD0558F5385BE2690CC5536E98B682985A4527312ABF1A6F5C9F44527A6F5255114979C48EC4E424136EE70A2D2593E54CA2516432D265A76A6F6B5FAACACBE041E995F0B319DE9DE5BFCCBF37E8C54E9FE619A075E8A1C8FE18699F88FA4FC9FF00F395FE6ED08C0BACAB6A71A302D2BFC5B0F98C890D8323EA6F247FCE5769BE63B8449ECD62F50F5D875AE564360C8FA2EC3CC5A46B32DADF898514F2F4EBD72B21BF14F74FF4D7626F1F53F8A192BF5207B785320439FC4115A4693711DBDF5F5F12CE8C0D913D857B640865CD910BAFAE46A41FEE46F95909115A6CE4BB46B98FAC20D7214C643662170CF7323C858AFA27E2FA314452DD56DE2D4F4C9F94A6B1827AF862DF163FA65C8FD1C2C11EADCA80D716F09EC33DE42A6D1472A2824F861069AB502C331D3BCB3E55F3C412795FCE9A746D05DC6CB0CEEBBD4A9A6FF3399784BA4D445F8C9FF3931F9253FE507E61EA96B145E9F97B57919B426A6C402C4D3AF866C605D3E41BBE5BAFA5230FC32DB583B90724F865D8B930CC5BCB5A16375C55AC5578E98AB78AA8BFDA38AAA2F7C55A3D7156B155EADD315560D8ABFADEFF009C6EFF00D677FC84FF00CD73E56FFBA45AE5A39349E6F68C28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF917B754FE45FBB34FC2ED532A855A803C71E1551370C0E3C2AADF5A26361ED863155D0DC52840DFC72C2A39A6893B3D0124F8D7205B423E172F227A6C401D86D9516714AB5F0D52FD80A139193607916A21A49641526A722125825DE9F335C1F4C75ED96C434929D699A6C96C434DD0F639708B519B2F86D62F8446DC7EB1F0971B52990CB0D9871BE87FCB0F341D3236D0D5B8C6E3E2981A1FBF28E17231CD35F3479E9A06B8D356666080FC7CAA4D6BDF0F0B9919BE7FD5BCC7246F2B3BB10C4EC4E3C2994DE7979AD87666AFDAE9921171331B2C0F56D4F996EFF003CB045C5931D8EF2A483F765822E3C93012875EBB1C988B4108794A034D865910C68BA38D5CFDACB0048895EF171AE4C36479A0A470A7A6580362A4738A2F877CC49C775A4724E0D32149016B354935AD71A4A1DD6BD77C7853689173C4000D282981B835EBA75A0AF8D30316FEB00F53CBE780C5810510B7617A1A7CB21C2C68DA6FA7EA011872EBE39021BC16463520EBC791A11BF8640867128FB5D46EECDD26B2B9642A6A021A6408660BEA2FCB2FCFDD73CBED676DA8D64D3C301752BEE42FCCE56437639517E927903F33746F37E9D6F35B5CC6CC69C5188FE272B21CE195EF305FA4D63FBD6531AAF4047864086E8E4B486CAF94DD3C40F0427627A64086D8CD96A5DDCDA59B81C5A07EAC065720CA52B09035922C373792515250683B641116276C6D6D61BBE6F53302029E9BE2DF179F4113DAEA124A8F54249515DB16F0CA34926E2FE49AEE5291C6018F7A54F860465161EA22FDB4CB9B1BE11ABC42946201CC9C45D46A60F8AFF00E73E6C935ED07CAFE6151B69FEA733E1CB966C6127479A3BBF21B5802DEF21BB07F772A9A2F6CB896A8B7129F492423FBC15197E12C7338F7CBDA14FB8C555475C55CDD7156B156A98AB78AA8B1353BE2AB6A7C7155E3156EA7C7157F5CBFF0038D9FF00ACEBF907FF009AE3CABFF748B5CB472693CDED5850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91688D3E8CD770BB55732D29BED5C3C2AA125C2826831E155317408208D8E02155E1B85AF4C8951CD358A7AEC0640B684DB436F56492BD16B9596615B5884496D2F7DF6CAE41B2245BC82F22E370C08A6F82213221279612262C82A46E7E599100E3CCAE5B8127C2F41C732621C6949524D42354F4A234917A1AE47306A2535D3BCDEBA4425797FA536DCC1FEDCC76FC4509A9F9B4384B899EB24952C6B5FE38D39824C1F50F30477E480698D24CAD8EDC5C8D85474E95C9C766360A4574C1CF635E9EF930D6404B3D13EA5541F0229BD72C01A26023D4B200A41E5D969BFDD9688B498A9C8A643CC30A7422BD32241B4C601C9CD0D0D4622D78559E6DA85BE9CB031A4148391EBD7EFC95A3758ABD0572A31B6611B1823A838384A95415A9D8EDDA98F09415600537EFDB070962DFD589EDEE477CA8B782D7D5877207CCE16629B36E3C4570F267C214BD23C80EE4F4C2427802690DB9461BF5CA484009D470F214276A6FE232B21980A5CBD19290CC580EB4DE83DF2B660332D27535212DEE8FFA3C9B487DB20591D9EA7E53F3E7983CB371CF47BA75B588D42722361ED5CACD22322FADFF002DBFE729E486FECA3F324A5B4F43C6EB7AD6B403F6B2B2DF0917D9AFF997E53F30E976D75A2CF1C72CA0114615DFE9C8172A322F48F2E1BBD5F477844BCCF02EA6BE032B937028CD596783CBD6EAE486690291DF2A6C890F3BF35C434FB6B478C9AC8A0B530D37C4879A9BFB99670B1D41AED5EFF2C0DE0B228A4BA8602D3935603D3A78FD1912CE554CFF004DBBBDD461B5B6949F4D3BB6DFAF32313ABD48BE4F08FF009CBD8E0D47F29B5582DF79B4BF4C311B9F889E99B081D9D0E789B7E39EB9664FE87818D4B86E5F7E5A1C5029425A239806C20F8732B0726190DA1CF7CC86A531D462AAABD7157375C55AC55D8ABB15506FB47156B155E3A0C55BC55FD72FFCE367FEB3AFE417FE6B8F2AFF00DD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91745DBAE6B5DAA0270038DFBF4C557A007DF1B569937DBBE025217C042073DC654C931B4B9E50CA83AF638153ED2A660AE69F7614A367BA58ED6466DC57BE210497946B3748D33508EB930030322C65AED519B7A6D930C0A4B25EA976A1A6581AD2C9AE872FB4704D38D012DCEFD72B6D40CD37A94DCD07BE2CACA024DF7F0C56CA8140C8FF00BB32CBD8569F0F7CAB27369C922D18005B7B89916CE2B561340E5BAB2F4EB92C64B5D943DB5FDB89F5295B5385DAF559A094950D1CE7B04AEF99B8C2D95595FCC31E95FA5A2F2DEAB79369A4C971E6692CA54B64886DBBF1E1B7BE654698F1747A07953F25FF00357CD5E47B8FCC3F2CF921F5AF26DAC924BAB6B8AEDF686F20A01B713919D1482F2ED2EE9AFF0053F4EEAE9567B5774B4D35A8AB291B1591BF678F6AF5C85320537786D4C727D62D7D2746ACB0024AAB57E1A37BE16C1BA0A592333C1F5AB6956F6452D6B040A646283AFC2B8B2D91111FAC46DF5AD0357B7907FBCF3A594ADC97BBF4ED8D30F103505E5DC61A19341D524914F1B6B916725593FDF9C698D3094C2BC17577C9A69749D5DD17E004584A7930F1DB6C698198519259239ED629ECE48EE637F5EE6CEF94DAB7A0DF64D1E87010C6D165EFA492CFF437FCEC1AD7982636B06996E39B2843F0A8095272AE0B6424C9F59F2D79A3CADA9E9BA7F9E7C8D3686FAFA7FA33DD1786BC056A3985C85331262333C3A54F76F7BC648AB4B360D5AF80195D16C12513E60D2CD80917D45D661916331703F0A31DDBE818981642749BC3AE6906375955CC900F87512A429FE19594FE60222D35781D3EB68CAD1034926660015F9572B3129FCC840C7E65D1D24BEB4B581E196ED089EE402E021EE32070CAAD7F3211EFE61B4168AB6D299934E50F75301F184E8085EF90F02523417F34193E95ABBEB4AB7361A9FA4427EFD88A72403A53C6980E92498EA8047DBF9C7CB567070FAFC915C4CE561708580643F1127B54E0FCA49C886AA2CCF4DFCE48343113DBF98273C2842D0D36FA71FCA172A3AB8BE9FF00CBBFF9CDB4D1FD0B6D435C905A2AD18F0A9FF896425A434CA7AC14FAC348FF009CD2FC9CD42C53F4D798CACC46EA631D7FE0B043465C6FCE29EAFF00F393FF00939ABD91B3B0F33299266A44F22AA8527BD4B659F932D90D6EEC1B4AFF009C92FC948F548E1D6BCDBEB7D5488E20B10E0B20DAA581E9954B4843B0C5AC0FA4F4CF3168FABC116ADA4C424D0EE943D9DEF51231DCD3B653E018736EC9A8E21B326B4D5ED26FDD28E20EDB6D8D535DDBC63FE7231043F97F76F6EA5FD68D8B83BD681BAE646271B34453F1A350B93EBFD65BAC723023C3E239B1C54E8B53B294BF1309FB5C0E4332C38504337F1C2CD662AAABFC3155F8ABB15587AE2AD62AEE15DEB8ABB80F1C55DD36F0C55D8ABFAE5FF9C6CFFD675FC82FFCD71E55FF00BA45AE5A39349E6F6AC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90949CD3DF35AED52FB89CF2AF7C55B86E091D7E78AA21AE147461F7E02A39A924D50F534F0CA99A334E620B96D86F4AE054F2D6EFD2473D3C3154A750D59DAD254AF1F88648734179BDEDD33C8C49D8E4C302C72E27356DE9930C6492F362E77DB26D6A44FC66A69B7538CD38D42523B1FA72B6E435483D7156B155F63A7CDACEBBE57F2EC774BA6C5E65D66CF4A9755A8E708BA9021600F600D6B93C70123BB466354FD9DB4FF9F49FE51E9B35B5DF9C7FE725E596D2C19259EC276B48A07400311EA48EBB7C865808ADA838F7BBEA8D27FE704FFE70B7F2CBC93ADFE62EB5E4ED2FCFDA1F97AD1F53B8D68CE66458A1AB332885B893F4E5D007DEA4EFDC5F217E7E7FCFC07FE716353FC95F327E49FE4E7952E35AD3FCD1A73D92DB5DE9DF548AD1A421898DE956229B1CBE2A0D9B7BB7FCFBAED6DAEFFE7DEDABC11C097125CEA9E608E58A641C5CAD0F02C474D8EF91931E27CE5FF386BF901FF38ADFF3939F947F9A5E46D4AC20D13F3DE4D4AFA3D5B502693D8AA5C31B692CB911EA29FDBA74FA3229E2A7E6C7E75FE48FE62FE43F9FB55FCAFF003FD93DAC31B9934FF32509B7B8B752CD0949A9C492805403D7037465694FE5779EB49FCAEFCC9F267E62EBFA147E6CF2EE9F1490DDE9774291BF26A6F8B2E2EAFDABFC97FF009CC4FCA9FCF4F37697E48F21FF00CE3B5ADDCD7052DF51BD5B3AD9D9DB103D4066084034DC570B1E305EEDFF00393BF9B5F917FF0038B736896771F9223CD9E6AD663E3A258D869FF588BEAA48520BA275A9D862C38DF24AFF00CFC07F285102BFFCE28EA5A6B472F2BE54D1A4243F7A829818193E5CF2EEB1F945FF0039A1FF0039BFA5493F92469FE42D5B4CB5D2E7D04C660314D0D43332281435070B0326BF337F28BCA9F919FF003F16F267E5FF00E5ED82683A169F269B7D6F08FDE822E95988A3D41D80C89E4CE25EFF00FF003F7E5B6B6D7BF216FAED56EE1B8866F5D446B172F848FD803B9CAEB9B3069F945A4FF8720F3D7902F7CCBA4407CA305FC0757B66735684CAA5B90FF572BE8DAFDCAB4F397FCFACEEF5A9560F2669B26AD218AD25536AE12579540001F528C7B5460970F716278AB9BE8CF3FF00E497FCE0E7E5E7E5C69FE7AF387E5468DA6F90EF8441677470419BEC02858124FCF23C239D7E3E4E29B7CC49E6EFF9F50CE925A2F93B4A8B4E1113C84120527C38FAB5AFD3938C224F543E93FC95FC95FF009C13FCF1F2BEA3E60FCB0FCA9D1F52D0EC646D3EEEE9E378D870A93D5DBC32D18815DDE0B79E65FF009F5A683AA6B3A4DE792B4AB0D6B4B9A7D36FE25B7763CE0AAB0E5EA53AFB75C9C71041BA7E10595CE9716ADE686D3E258B449B5DD4A4D123AD185A191BD15A7871A65BC23AB5926F67DC5FF3827AD7FCE27E9FA779F3FE865346B2D425D52E61FF000CC570865F4A341FBDA85652A49A1EB8384364645FA0ADE64FF9F54F0E2FE56D1154776B7907FCCEC7843689C97DBEBFFF003EAD240B6F2B684EC4D14185C024F6AFAD80C026539232EB55FF009F5B229F5BCA9A1AB20ABA7A7202A3DFF7DB618E30D5C459F7E5FF0090FF00E7DF7F9C370BA2790BF2B6D35DE5F66FADEDE6FAB236FD67595941DBBE1300CE32931BFF009CC4FF009C6AFF009C4DFC9FFF009C73FCD3D534FF0021E85E59F375CE85247E5495A765BA92F792F130866DD857B0CA66221CAC5399237D9E1DFF0038E06E1FF24BC8D6FA85CDC48EB67037D52742BC18C62AC09DCD7357A900BB9C123D5F4B695A658ED26C48DC819824539F1281FCC5F2E5A79A3C9FAA5A7107EAF03F15EE7E16E99386CD59793F083CE5A73699AFEB5A5BC6D088677081C52B466E999F8CBA3D4C5283B5B59A9054AA1A5733226C38110866FE39364B315545FE18AAFC55BC554CF5C55D8AB5CE9B53157733E18AB7B9DE9D715750F862AFEB97FE71B3FF0059D7F20FFF0035C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EE4B96A57F0CD6BB54BEE6E4F2FD78AAE86E01502BB62AB1E41CC1F7C05211724A0FA7E1953247B5D0458CD771D302AC9756E0B4AE2AC5EFF0053332B28F1E9921CD058C5DDC9A1C98605209A72C684F7DB2618C96890713936B5093F7854786F8CD38DBF476F6CADB96AC542DF462ABFD318AAA691E55F3379E7CD9A1793FC99650DD799AF254BAD31DD8AC8AF1B7C3C69EF976201C4CE5F60F993FE70D3FE739BCCF6ED6FE636BAD4D0A7A0BA64974C55430141414FC72EA01A2CBF643F2F3F273CFDA2FF00CE0F79D3F27751D3560F3D6A7E56BAD3AD2D236678CCF22154058926A49DF7C9C764136FC52D1FFE701FFE72CB48B23A6C3E43D327E0C6E11A590B4CA587B532C0520D3F6A7FE70B3F25FF00307F2DBFE70CB52FCA9F37592691E78BBBFD6E6B3B02DD56EF8984D76EA01C892C0C9F94DF94FF00F389FF00F3995F93FF0099EDF98DE46F2ADA43ACF97B58B9B9BFF5A5741716D34DCA84568C0AD6981417AE7FCE7FAFFCE51FE6E79534AF35F9F3F2AB43D1FF002EBCAD1B32EA1612BCB7E1CA1F51AE118D5072AD074C590953F38FFE71DF41F23F993F327C9F61F9CBA9DDE9DF96FAE3B23DCB201688E1C22891CF40316CE27EE04FFF003953FF0038D3FF0038DF77A57E43FF00CE2AF97F45D77F31FCC37D67656F7518A6957724DF097B9BD427E3626800C58195B18FF9CAAFF9CCDFCF4FC80D7BCAFA67E687FCE3DF94F59BED56CC3691AFD83497715B5C16A2A4323861EA03B85271636FABFF002FFF0038507E40CFF9F1F9F7E46D13C8B05BDA9B9D3F4E4445935042AC10CEACBB48C69B0C5812FC5DFF009C15D5A2D67FE7381F58D3AD6DADAD7CCBAE5CEAD690D688B677723CB1C6941D830DB16264F56FF9CB6980FF009FA17962F26790A01A3C56CD08AFC512BA95FA2BBE25B81671FF003F8D92E6E35DFC86B458964B3FAB48F6A53790B537046408641F93B24769776F1C5A8D8BDC5E5005AA9AD32A21B8153B8D1ACADF59F24FD5E27B49CEB5640015A8FDE83B570034CB9BF793FE7E412ABFFCE01F962299A79644D5F458DA471425D6A77F6DF2C8C6A9818EE5F822DA1697A868B63A7E97A1869E3B413DF5D92F5F5075EF84367007EF97FCFA0C347FF38C9E7F8608E44B9FF10DDC61C0FDA11353EECB049AB806DF17E12F9AB47B1BAFCC0FCCEB8BA8DA7BDFF156A70A3396A02262C6BBF8938253D9B3806EB5E3B64FAAB416104933FC0DC4D7EC8CC7F14B1F0829A683A75C3FD616C230D727F7CA091B8F91C7C52918C27967E5AF2D4C04779A2A4DE22AFF00D71F14A784226DB4BF2FEA7AAD9F93BCA1F97771E62F34DF4C9FA3B4FB38E4964E75A091954D4283D4E4A323252007E937E427FCFA63CE7E6BD624F38FFCE42EA16DE50D126845CC1A268937AB24A08A94B9E6D5414EA2B970B69343DEFAFBF303FE72AFFE716BFE708FCA571F975F92DA2D9EB9E72107A561A1E8CA67B496FC01F15E4C0B1526A6B4C8CA7B338C093BF27E59F9CF5FFCCAFF009C81D6EDBF31FF003BB537D6EE21B8F5743FCBD8E42FA6D9467EC96E276A53BE60E6CF5C9D8E0C3B6E1F657E5BFE6369D731586871B246D63122D22A1B745A50468C07ECE61711939F5C2FA534DBE8E15925460EAE054D72328B7C24CC22D5AC61D12EA696CBEB7CA290B102BC7E13918AE4E4FC43FCFDBED3F5AF3EEAA2CE0F41D256DA94A6ED997093A7CE1E1FEA48CAB1C8FCFD01C57D8667623B3AF229D96A1D8ABB155CBDF15546ED8AAC1D3156F15770077AE2AEE03C7156B9D36A74DB157733E18ABFAE6FF9C6CDFF00E71D7F208F8FE5C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D34BC51D4D0F8E6BA9DAA5D757887900C2A71A55B6D7229BB0AE34A897909F881D877C041506914D7085128E2A32AA2CB88285DDE7100A372E23B634578825125F3B6DE3DB0526D0734E0296AD08C9008291DD5D541EF920C0A4C65777FB27E7930C485FCC81BFD3930585174720E677DA9824530148B0F5141BE41B2D48B91D8FCF15B6BD4C56D917917CEFE6DFCBCF3E68FE74F25D8DA4FADE8686E21BDBD1FBA4E07970AF89F0CC8C3C9C5CFCDF7349FF3F5EFF9CA09EC6E2F7F40F96EDEE2C9C5CDC4A63A3948C50D169EDE39750B71DFAE1E46FF009C8DF3C7997FE70D7CC7F9F77D6D65079CF43D126F318B287FDE7668D4B05229D0853DB26021F945E58FF9FADFFCE5A79B35516DE55F22681E62D56E938AD859DA9967DABFB0057B78614BF5BFFE7113F3E7F303F3EFFE71A6FF00F34BCD7656107E6269DAB6B5A78B38978242DA7FD8475A7C2DB1A8C04354DF9BBF941FF3F0CFF9CA9FCDFF00CFA87F28345D1BCB916A1ABEA975A7BCB321458A3B4765E4CD4EDC70522934FF009CF1FCF6FF009CA8FCBB54FC9DF3CC3E4CD4B45FCDAB77FABC1A0167BE8560F85BD6561F0D6B51F2C5987E547903C85E7FFCE1F31E95F90DA75CE97A4DCC5234B6925EBFA51B3F2E410B7892705864FD16F257FCFA23F3F26D7B44BFF33F987CB7E4EB2D2CACD0DEF97A57FAFA5C210D14B5634E4AC01AD70A0BF577CE1E75FC81FCA3FCB5D0BCB7F9F7E7DD07F32353F23411CEF26B7325C6AD737D0F499537AB531624BF32FF00E7323CE1F9DBFF00392DF975379D3CA7E4D9FCB9FF0038CFE50893559ED75188C37B3C51FDA96341406234F84E1A60FCCAFC9CF2BF9BFCFDF9CDE47F2C7E5B79864F2479AFCE0F1D9F917558E43088E40A5C7AAC3703883D31E140897EB27E5E7FCFB5BFE727B4DFCF1F24FE6C7E63FE61689E709343BC49F53B89E691E765414DAB4AD6B5C69B86CC2FFE7EF9AD68DFE37FC9DF2EE8BA9A4BE67F2DDBDCBEAF6D237C36EB22928CDE0180DB2259805F3C7FCE28FF00CE04F9B3FE7277C8B379FED3CEF2E942398C3C1E42073EA05011EF913BF26775CDF5A68BFF003E80F35DB6ADA36B1ABFE62B5E3E957F6F77F57E65AA20903D055BA9A5300891D14CC17E927FCE507FCE31CDFF003909F913A5FE4E5B6A8FA49B39ECEFCDFF00EC97B4D954EFDF2C0C0CC9DDF9B23FE7CF5E6CB5D3445A7FE68CD0DDBB5651EA3052BDD766A644829F10BF463FE710FF00E717AF3FE717FF002A75DF235E6BF36A771A95F4DA9497719F84348A568373BEF954C90A245F9F1E67FF009F44F98B5AF37F9975FB0FCC06B6B3D7B50B8D4C42F211F1DCC86460C037515C4094BA289D17C03FF393DFF38B1AC7FCE29F9FBC85A4EA5AE9D56D3CC32395915890415F72727E1D06CF11E5115ADBC0BC0ACCAD3B3189E9B75DE990E109E22AF02A25CA98A4775EE7B60A0C6CBEB5FF009F6E24C3FE73B742F456393FE752D5CC824EC9C7E265F714DB2E8061225F657FCFCFFF003C3F35FC97E6DFCBAFC96F2179A27F2BE93E74D264D47CC3E6289FD3B9611CDE998B9D3BA8E9965048912FC9FF002E796B4CF2F6A1746D8A5FCB75704DF6B7A99ADCBC86A4C8A6BD77CAB200DF025ECD06A30454B7B39648D29FBFB81D251E0C7C335D962E7E29109E69570F65730DF69E56CA20DF15B45B4751D5BE6731E31A72B8ADF587E5979ECDFABDB5F5C28E2005E47AFE18261BE05F56793754B6B9B7BDD2DD11E3BD8D979B741B532B00B39BF217FE726FCA5FE19FCC1D4EE238EAB732332D3A1A96E999100EAF5043E588DA30F351BE22DF1A9EA0E67E2D83AD9157A1F0CB98BB7F0C3452D12075C08B5CA46FBE2AA8C46DBE2AB01DB156EA3C715773A6D4C16134EE67C31B5A6F883BD7AE3687701E3855FD72FF00CE367FEB3AFE417FE6B8F2AFFDD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87A96FEF941ACBF8E623B3B0963DF5F16DA5AE34B611515DDF541F571A5D9318B53BD42A1E4AA7ED2E0931927706A3CC0E9BE52D61166E7638B38A5E6EBE33D4E2D8103717049C52833FBC23155616C42F21DF15434B1D3B62A868D7E36F0F0C5894746A3DBE8C582BB461BE43155168462AC93F2FBF2CFCE1F9BDE7FD1FF2EBC9776965A8EAF19905C4E6900A1A7C7976271B31DDFA2BA47FCF9FFF003D7597F43CC9F997E58B4B688049A0B3123CA57AD18AEDF7E640F268B7EC4F907F217CA1F937FF0038F179F955E75D6E26F23C1A335AF9A359B87280447FBCAB9AD12872616DF1CEABFF003963FF00381FFF0038BD6BA743F96BE5BD23CF9A8D847C5755F29411C972838D2B3CEC2B5DC8241C905B5BFF003EB4FCC58FCF1F979F9AFA45BDB470DBEA3E63D675CB68140E5026A2EC544B4EFF00150E4BA2F0DB17FF009F7DFF00CE324FF963E63FCDAFCFEFCCDB44B09FF4B6ACDE5AB8B8F84DBC31CECCF23927F6C74DB010CB81F96DF9DDF9D7FF002BE3FE7253CE9F98D6F74D045A7CCD65A2E9970D50A9033C3CA01414E4054E56436C616CDFFE712FF28FF257F327CF9E6FF31FE72FE7149F963AB796353B69BCBCB6F75F56B8942307356F0AE459786FD51F38F93BFE71CFCE8D7B3AFF00CE71F98B48B4344BB5D3B5DE01005028483E032A32A3CDA4E2277A79DF977FE7DABFF388BF9C724FA9681F9DFE67FCC6BB8EA6F35A1A8ADDB0A750CEC07864F8C745E0A7D95F97BE4CFC8BFC81F25FFD0B3F99FF0036D7CCFA7F9B4496BA47977CC577EBDF4905C8A0B58A951C00FB2B931913C07B9F1A79AFFE7DDDFF003895F947E615F32F9A7F3CF59FCB2D465BD7B8F29DF0D405ACB64ECC4AADAB863C4A5683DB26269AA1C932B9FC9FFF009C6DD4E4B4D31BFE73E3CEE249C520787CC4435C9EA55985795326770C385F15FF00CE607FCE3DFF00CE35793FC93A9FE677927FE722AEFF0035BF320CB15BDBE9DABEA02FAEAE854A30AD6A780ED95C837C075A7C55E4DF31FE71792B429EDFCA5F991ADF923465E12CD616174D00776151B2E634B6673887D0DFF38F9E6FFF009C92F3EFE7CFE58F92FF00E576F99F50875F9E3D66F2CA5BF77A5BD9C80C9148A76A3807614C8F38DD72712517E82FFCFD9BF3BBCF5E43D53F2BFC95E46F376ABE50D47CC9A7CBA8CF75A64ED0168E297830629BF6F1CB9B7146F67E4949F9B1FF0039096D688A9F9E7E6F8AD66FDFCB72DA8CA013ECD5AFE382DCA9C283F6FBFE7D73E78F3479EFFE71CBCEFAC79EBCD5AC79AEFB4CF30DDC2BA85EDC34F27A0B192A159EA695A9EB8251704737E2FF009DFF003E7FE720AFBF30FF003022B5FCE7F34697A7DAEBF7D69A7410DF3A2450C729F4D68294016836C31A05CD8E332890C035DD5BCF3E67D574EF30FE64F9EEFF00CECFA07C7647509CCECBCF614AE4E73586911714D00BE54BA9663752A97D3E2AFEEC022A6A3E5989293951D3D2B5AB7A48ED5FDAFE3862584B1BEBEFF9F69C9EA7FCE75684C3FEA4ED647FC933991170F2C69EDFFF003F6FDFF3EFF26475FF0070139A7FD1C60916A897C11A8C06541DF8C9CA998F22E5C0A7769767EA8B08FD9ED9448B971679A34DCA08E393ECD77C85B75DB34B4D4A5D2EE2196CBA0209A64245CAC6FA93F2F7F32121B8B35B9702BC565AFBD3DB220B64F93C6BFE7316D6CB516B1D6AC183B3AD5A9F4E64C0BAAD445F9DD35A43EA99631F13EF2FCF2FE275A614A6E782D075CBE05690E243D3DF2EE882BC0E79596B937C78ED819479378B2762AEC55ACC79736D1C9BC4312578CB43592EEB920C097F5CDFF38D9FFACE9F905FF9AE3CABFF00748B5CB87260F6AC2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF864BB048AACD51DB311CEB4BC2B147612EE01C56D17621DC0AC98ADA65E8307525EA2BB8C124129D5B45D38F4CA501306040229D716C8A58E28E49D862D88571C9F6DC629548E36A8DB154D235AAD08E9DB1541DC42687E1FA7154A1D5D0F43BE282A91C8E0F4C58F0A3519A9BEC3B62BC2B8891BA2938AF0B21F2279EFCFF00F94DE7DD13F323F2F2682DBCC7A3AFA3682ED3D5818B1AFC51F7CBB1CA9C4D40DDEF1F99FF00F39CFF00F3963F99305EDCF983CE163A19D22DDC48BE5D88D8BAB28AD1F89353F4E5DC40971E9FAFDF975AC7983CE1FF003EDFFCC2D67CC3ADCBADEAFAC793AF6692F6F5CCACAEC87A96F0C9476B5A7F387A7BE85A5F97E686F0C4B71A859A08A7863264776DF812A09AEFDF240AD3F707FE7D29F951F9A9E58D67F327CEFAF794AFFCB3F979E6FD06D2D74586F289F5A962209786B4A13D6A72D06C289D3D0FFE7EADF9D7E75FCBCFCB8F2D7E4FF95F4E9747D37F3126922D63CDB6EA5623146D510C6CA2AAC4FDADF7C494F1EEF91AF7FE70E3C83AA7FCE05F92BF3AEF2F5BC95F997E5B8A7B89B5A998AC37BEA48591645EA49A0A13EF9592D8323E2BFF009C7CFC90FCC1FF009C9CF3F6A1E5DF285F695A3F99A0478754D4EFA15781907C3CD50EF5A6F91B6632ECFD44F20FFCFAB7F26BF2AB40D53CD9FF003943F98B1EAF1E9122DD31D16E0D85B451A7C6C6757AB301DE83A60113F0419DBEF0F30F9D3F2CFF00297FE7157CDDF985FF0038E51E8F77A2E99A34D3E87AB584002CA507C25DB882FDF7A647C2A533B3BBF9ABD5FCC1E62BDBFD3BF38B52F3E1D5FF00332009E6CB79656692289588A59C486BC597C06110A62723F717F317CA1E4DFF009F8A7FCE1B683E61F29DEAA79DFC9B6E93C371250BAEACB12ADCC53746E24D763921162676F3AFF9C76FF9C4AFCACFF9C2AF256A3F9DDFF392BAF68DAC6BB25AC8348D2EEE1F56DE1050845489C37C66B4AE4B8D1C4FC98F3C683E4FF3F7E6A7987CE9A0F95AFF00CB7F97BAD5E493E91A34D227AD21690B17B72BF654D4103C32B3367E3523BCC3368DE5ED38437CCF631C29EAC4D72DCC48631544A0AD49A532A3BA7C6B7EAA7FCFAF3F21AF74CB6F31FF00CE577E62D9AE9F1EAD6D2BF93BD61C560D302B7AF32F2A5140527135F00C38ADF0C7FCE507E6BC1F9E5FF3923E60F3559336B1E4BF277ADA2792A590F34B9B5726B3475EC1AB91F136761A7C24EEF13D4A2B98216F556DEFED9374B08928CA3C0D76C7C47272E2D9FB2FFF003E9130C7FF0038CDF98534B0936D279BAFFD6B75D8AA08A9C7E8CB89DBE4EAB83D4FC42B8373FF002B0FF346E6C618E5B6B7F36EA8E7D75E4157D634041F0C864950761A68F34C66823B9FAC35E7A572978ABF0C0BC42537E99852CCEC052AAA97948E11B154E30923E3000EC721E2309CC24B3CE90432F3902146A3D4F427A65F09383972D3EC4FF9F65C7327FCE717971E44204FE4DD65E13D792F03BED9990E41D74F2713DD7FE7ED2449F9FF00F92E10F22FE5F9CA7B833E5732B10F862E5828B84A5655AD5331E45CBC6126D3AF59262937EEF7D81CC79172E2F55D2984B0523352AB5DB204B918E36C8F4C9E559024919604D2A72B949CA80A679663EAD494CBE9348414FA32024DB241F9EDEF35FB18ED9C35C431A101FA819938E4E0E585BE39D634AB9D26FEEA39A268D2662D096EE3DB2EE370E5898E354B6FF7E6463938D38D34D18D88FA73281D9C5915363C7A76C8940709053734381B03B9A78E2AB81077071575478E2ADD3C329237656EA1F0C900C495DD865803592DE4A9812FEB9BFE71B3FF0059D7F20BFF0035C7957FEE916B96057B562AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF86BB8802C67311CBE240DB460B32F63B1C57899159D94483A7CB15E25595139003AE465C97891F6DF00CA9215659878E2D914A669013D6A7B62D81411BE21E18A519137BE2A8C57A6F8AB52BD57DF154A6615A629014E35DFF008629A469140B8AD2262C5682DBA92EE182EA4897D5B636D227A6366F588F8581F6C944B46585BF40FF00E70A3FE70BFF0024FF00E723FF0029B5BF3279AFCCB2E85E6CD3F54FD1B7D1CF7CB1F2A8279716604E5FC449B718C2BA3F4B7F3B2EFF00283FE71B3FE7103CF7F9456BE72B18EF350F2ECFA4796A059D267BDB87144850231219B975392053E1DEEF8D7FE707F47FF9C0DF27FE58699F9D5E7A920D17CE3645F4EF33E9FE629BEBB0472C5F6A58ED983503B74A0C9DA38084AFFE7217FE7E75E7BF365C5E7907FE719F438FCB7A1D9BB245E63302FA77D68A6A9F554D84551B9A76C78E9A678492FBA3F267F36BF20BFE73B3F246D3F2E3CE2F6ADE69D3EDE14F3568B7AC8B7B693DB95E53432C86A3D4707ECFBE0333C988C469F327FCFCB3F353CABE53FCBAF26FFCE267E5CDFDA3C1E60317E9B4B77594D8C5624344ACC8763215A1191E3A663097E57797752F3AFE5FF9C6C7CCDF943A9C9A0F9CF47B37B69ADC3304BA5917E290814069EF94F8AD834F27D89FF38B3F927AAFFCE6FDA7E64798BF3E7F37350B297C93A92E973E8C3516B68AE39C65D8B46CE015A8A5732465003038E4FD4FB9B5FF009C5EFCACFC8DB6FC88F3D7E61E976FF96F73A61B09B4D8665F5F8B1DCB4D11635DFAD301CF148C322F85A05FF9F51FE534B65AAF9524BCF3E5F69779EB5A587D6E6BA592E54502399556AA41E94A644E701B069645F0D7E4CFE707E71FE4DFE6779E7F353F27ACA7B7F2BDEEB5777FAA7901F91B67D325959D04716C81E8C454657F9A8B68D148F47EAA587FCE5D7FCE207FCE64F97A0F277E7DD8CFE44D68148A2F29EA333219A56D898E455E2373B03F7E40E51F51E5E4C65A390DBABF3FBFE735BFE7193F2E7FE71D6EBCA4BF931E6B9F599BF306493F44F97BEB7F5C7B6892AE2854B05A8A0C81CA48B3C9A8E9A47A24BFF3851F919E41FCF8FCE08BCB7F9D5E708F47BEF273A5EE8BF97374C527BFF4784AEC676A2B2AF75EE36C1C6472EBD57F2E62FB7BFE738BFE730D64B5BBFF009C5CFF009C7DB8B4B9D4AE02D96BFAD6931886D349B68C7096D02A1E279A93BAED8F89E9B972FBDC8C7A49134FCD7F2F791E1F2BD8A68176E65963AD2F474AB6E687E67304EA2CBD060D36C9D5FF00962CDEC2E4C7290D6F197694577A7CB271CD6DB9F4FB3F537FE7D471DBC1FF0038CDF9836D79756F682FFCD9A8A47EB4F1C6DC425391566046FE39B033B1B793CF4F170CC03DE7EF7E383E88DABF9ABF332F6D2329158F9BF538A57471C64549295DBED5731F3CEA2ECB1E2B0B64B2FAB6DC295ED9A83959F8450935A7AA80863180EB571D695CB2191AE78497A47FCE3F7E527E5A7E66FF00CE4DE8BF97BF9B2B736BE4AF3858DC5D45789762D544B6F1928399200E4453E9CDB69C931BBE4EB73E120D53F757F207FE70C7FE718BFE71AFCE927E65F912FE4935C165716D61ACDEEB114F0C16970A04CA23671527C4666125C2188F73F2B3FE7E3BF9A5E4EFCDFF00F9C87FCBEB2FCB3F30C1E6A87C89E5FB8B0F31FD554D22B812972BEA74AD08CA67CADBF1E3DDF31DAC4D05A3A188C69337A8439E4E1BFD6CC69173A18924F4C0BA048EF98E4B950C4F51D01855631D5C01954E4E4C31D3D46DF46944493053B8AE63CA4DA229835ADEBC6A5222C22EBB64449245AB5B5C4A54C33C541EF9938E4C4C2DE59F9A3E5C4BCB14D4ADE3DED50AB53DF2D949A32627CC778E915B014A4B5A1CC8C527559E348462CA23AF565AE6C22EB25CDCA390DFB64CB3839A315C836114B7D35C50EA53618ABB155C1C014F0C8916825AF572403025BF532603025DEAE5822D64BFAEAFF9C6B35FF9C74FC823E3F971E55FFBA45AE0661ED78A5D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF881BC880420F5CC3E20E424B0A857A1EA4ED8F12B24B50B4218D31E20AA8F08670CBB9ED809B0A39AA03C41076395F0B604BE5662C6870F0B30504E1C9AD31E165C6D29E277FA7070B21205171354FC382928CF8A83E78D2B8D698D2A12406B8A625A8D0D7A6D8B2B45B23300145698AD85F1EDB1EB8ADAA4A225884FC4CD3AB045B6AD0153D5BE8C429A2868F47BB86133689E66D47465BDBA56BFD32CEE6585789FB529E0402465832531E005338FCBB6FA84CE751D4B53D461B17E766D79772CEAF20E8C15C9030F8BDE98E11D11F0795F499EFEDAF6F2C266B595F85D69026222007FBB997ECB57C30F8C19F83BDB33B782934292BC7E8C4ECB672C2823F4231B2D78815DB6CA67985B64710EA91EA7E5A437115F68D25EF97EEA32FFA4F52D3EE5EDCDE06FB3511914E390F1E9B3C081768DE5FD3ED8FD72E26BBD7F5E0DB6AB793BCAF427B1724ED909E7B671C1001E86B6EF2DC590922A49044CAFABA1E2483FB240DF7CA8E50DBE0C52883F2E6D4EB125EC771AA59E917959750B0B1BE96DBEB128E858C64549F7CAFF3738F271A7A404BD4B4AFCA0F20CF6D75A85CD86A90996129159DE6A12DD0527BD5C9CA726AF24F9B762D180ED0FC95E5FD05E19F4BD0603769271769155C18BC68475F7CC796693B0C7A50F52D3ED674B48A28163B4912E1A66754142ADFB0C0751EC72BF1A4E6474B163FABFE5BF943CCB3DC5D6B1A12EA3716A39D98B522DA49246EB491402299911D4D7544B4B1287F227E4F59E81AD5C7992EAE2F3EB112D346B2D46E1EF7EAA0FDA0A64AD36F0C9CB59C5CCB8FF901D143CF1F94BA579AAE96F74992E3CADE648DAA3CDF6933C721435E6948E8DF1034EB9286B047CC2FF2782ED17F2EB4DF2AD9BD969566F737F74419BCC533F3993F9B9330E4C5B213D582092E54745188D833187CB62EAD134DB88792A75D40F53FC73046716D98F152B4FE598AD6DD2D6CC85957EC5CB0A807C48EF96C753109CB8F886CF269BFE71FC4B7D793E99E62D5B4A17B5B899AC6F26B783EB2E7E26F4A3206F99B1ED1A157B3A89682E5C54CA34AFCA7D23CB5A63D9C76B2DDDC475996F4C86AD3B7DA771FB44FBE5597571946ADCAC7A7203CF75FD0E64998087A1F8B35E32370D384AE0D338C0E49F4DD47C2C45687B6646292CB00609E67F2EBEAF0D8DC5DC93DB6B36CFC6DEFEDA5689E28C9F8802BBEE336DA7CDC2E0E7D2C65CD8A6A3A0EA36B2B45A7F9B35FBC8C7C715BFE91B85141D57ED77CCD3A814EBB369611E5F794CB42B39B42944DA3DD8824D64F3D75661EACAA4ECCBEA1DCE512CE1A2189EBB1D84090ACF0C6C2D8AF0F58B16E4DF2CA279A2E6431A0534EF527AA2D77CA2598391114CF346D3E7867B762945E42B944B286FC71E3E4FA7F44D352F2C21089CCF115DBDB293305B0E0932587CBA3D27458E8CC3714FECC00B0F0A439B17D4FCA324619C2D3AF41FD99930986420C0753D0A76B1BCB59D39C12EE58F63965F1726196161F1E79A3CB8D63A8CFCA32B6FC8956CCBC669D26AB1960ECBCB91614543C53E599F09874D381054A46F4E95D81E872EE265034A4F2F1343D698096C26DAF52B8A1557703155C411D462A8377F888AE203592B79FBE48062EE7EF93B6041772F7C9713120BFAF7FF9C68FFD671FF9C7FF00FCD6FE54FF00BA45AE066393DB714BB15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8779E6690D0E6BDC86E0B62C55A9D0D6B8AA7B1454C555F8814C473508693A9CB59A5E480C49E98AB4CE9E18AA1A465236C05945742699536F1047092A078E2B61716DBF8E15B08391B7AD701482A9130DB026D16ADB1FD78ADADE4395715B5CC6A062A9859FD93912D914FACBEC37FAD95C9BA09CC1906F8A6B0A0645AF8E565124EE5B5E56640EE320531482C21F4EE0AFF29DF2B9330CEACE0F56829B9C8368E4CDAC6C8B24629D3205B22F49B3B43FA35969534C81722095DBD8BF3A50F5CA8B97065B6766FC7EC91909392190E9DA51E60F1A6F539510D822C94E9842EE2B4182922294BE9CBBFC3DF1A6D10413E9C95E9808D9918A3AD6C100A53AE505ABC3569B4C47A10BB8C57C3455AE9E00E9D714786EB9D2B9A3F14DE9B62830A0F10F35689708F3388C77C945800C0A1B0924B69D5D00DF7CCCC658CA2C43CC9A64B085600D3332127032879C5F44D1D651B3014CBB8DD6E68EC9569E93493D373BE4096BC707D0DE5ED224BCD3238D81217E2194CE4EC2186C27B0F95E4120223E9ED98F22CCE9CB2BB2D12485E12E869514DB2B3272F498082FA3BC976F1FA31C6CBD80C00B9B2C4F5CB6D22065A85FB5D72C12689E35F75E5C826423D304E4C16838DE5DE70F28FA16FCA18FE12A4B003FB332B0C9A270A0F913CE5E598A54B82F0FC42BDB33232B755A885BE51D7EC24D3EE1A3E344EA332A05D2E68531CB9903428D5E99931710841897950E5A98F25656C595ABAC805315B5479401F3C56D2F91FE33BE4C354B9ACE7EF8B1773F7C55DCFDF157F5FF00FF0038CFFF00ACE1FF0038FDFF009ADBCA9FF747B5C9ABDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88316FCCD45335EE42630C7C17891F11D862AAE55A3FB5F862AA7CC9751DB08E6A164BD4E58CD00D192493F67C71552654F1E98AA832AF6EB91290B797134C832564620D6BDB1557E551B1EBDB1542C8AC687016512BE3246C4E0656881228DBC715B5E11CEE294C56C2AD0D003D7B629B4CACC1A53B9C896D8B20B34655607B9A8CAE4DD04EA089F20DF14C63AA7153E3BE56512656AC0D9EFE1902CA2C7A01FE94CD4D89DB2B9320F44D1A22C54D36A641B43D174E882B0E4366E9902D917A259DB936C4506FD32B2E44175B598E7F677AEF95972E0CB2D2D502EE3225C90C86CA10A46DB6574E481B270E8A474ED8D360012CFAA73AF15EA71A6C0109258B03BAD3011B3202D523B609F6B314B2E04D22B3590034AD714702362B38D4D08A62BC08D92CE26864A0DC8D8E2C670D9E75E64D0627B39A4352789ED928B8A214F04F4608659A2058B96A71236EB97424C65040F9A34E89EC95C28AF1CC98CDC1CB17806B5108838E3DE800CB3C475D9216A7E5FD3A7B8B80238C31276180CD9E1C4FACFC9BA25D0B4F4DA1019539357C331E591DBE1C2F4FD1740FAEC9C12352E3AD76CC796473469D93DC796E24291B4604886A6991E2B6EC7800667E5DD3440E9F0D0786112672C6F5FB14B68E3024AD587C3B65824D13C69CA476CD41BFB6D9609B41C4A77FA1C17F6B22320208EF97E39B899A0F913F337CA4B6E2E0DBC436AD4D3E59970C8EB33E2B0F827CFDA605F55B851D76FD599B8E56E935189E113865050F8E66C0BAAC91A520A4003B66406B05554D3AFD38A6D706A1AF6C56C36D20A7738ADA14B124EF930D6D54E28754E2AEA9C55FD837FCE337FEB37FFCE3EFFE6B5F2A7FDD1ED726AF6EC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88EB5527A8EF9AF72138584000F862AB580622B8AAAAC0BC4B6D5188E6A1033851F3CB59A058A952062A876E3FD715506A74EF912BC90EDF6B2B5E254AD00A615E25367618AF129FAA5B6F0C0520ABC75207BE0648911B1236E98A11A88C314DB60126A7E8C59C135B35DC644B745925BAED95C9BE09EC0BF08C837C559C5181CACA24CA6DC7A9694F6C814C52DB7B73EBF4EF95C9987A5E876C788DBB641B4727A3E9B685DA314E832B2CE2F46B2B6263094C8172609D5AE983903E395972E0C8E1B001694C8C9C909A5A5A8AF4E9869B849363682831A6626BA2B44A7D9C69B04D42E2D12A76C8C86CCC4B74B4DA1AF4FA3304B7DA6F69684F1D8605B4CC590AD298ADA30598F4DB6ED8944B7093EA9610CB613A9515E27F5620B488BE60D5F4C486FA62ABD1F7FBF260B19063FE62F4CDA08EA2BC72624E0E58BC2354B0E572DC96A9434F9E4FC470B82CB37FCB4D05AEB534E70FC3CBA91F3C066E5E2C54FB7B4ED02D6DED144680394A1CA2537678A349BE91A6AD9CA5F852BDF2894DC8B013A36A269D98AEDDB0464D9020B26D2ECD232A4AF4CB049259A5BAC2FC435053A659C4D134E3D3B7420F2C989341451B988008879061BE4E33A71F246D83F9B7CB36BA8E997521505CA93FAB32F1C9C2CB8DF97BF9BDA0BD95D5CC623A0DC8FC336584BA6D563A7C937D66DEA91D2873658CBCEEA0520658FD26E077D81CC98F27094F0AB44818ADA8B362B6B7AE4C2BB15762AEC55FD837FCE337FEB377FCE3EFFE6B5F2A7FDD1ED726AF6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A0B7896BB6D9AEB72116C388EA3DF1B553E05BEC918DAAA51C2F1E43082A94DDF21DF25C4CAD2AA495D8E3C4B68696564D88C78D6D62B926A41380C946EAA2367351B0F7C8DB2F0D50055346618DAF86B1E30C2AA7AE36BE1A82A146F886C7A6048852696F172DE98A784A64B1AAF5EA7A62BC255982D0D06F8AF0950E209D87CF10120F0A696686A36C0436C66192DBA1DBA6552722124FEDE2240E9ED951939312AB340C29B8391E69E1B647A78ADBF1EF4C8908BA46DB5848CE1C5284E57209137A2E836CCC428A5477CACB744BD434BB378594BD083E1954A5BB7443D074EB477A11403DF21C4E5420591431716F8874DB225CA8C29378D4505075C8916DDC48BB65A374DB0ADA6C232C36A615E3A44288D054A934C5B233B509551C6C0D7232E4DC0A10C04B0D866010DE3284DED6DD956B4191B65E222429077180C93C48F8684712363913365CD21D4D084954746072226BC34F9E7CCF02C124EED4249DA9F3C98935C9E37AF34B2B829F647519306DC3C91B49ECB467D52EE2855284EE49C375CDA31E2B2FA6BC83E4C86CA38E568D79F723227239F0C74F6EB4B13EA0DA8A17A1CA897240A4E96C569F0819598B2E1255C5B46801A6E3AE08C59C2242716691BF414A78E4D914D2283E3156D97240B4C85A36508CB452464F8DA4C54EDA89255892064E32B6990A446A33A3DABC22B475A0CC9C73A699C6C3E1FFCF3F2C7A51C978C8ACA63AFC3D7B66D304DD46AB1ECFCEAF30DB98DE4923015549DBBE6DB16EF2FAB86EC2259FD56E46B502999575B3AEE02A7CC7BE4830229631A9F6C242A91563DF224D32112570141BF6C226B54B4B81E3878969776AD7256B4B4B01D8E2B4FEC23FE71977FF9C6EFF9C7C3E3F96BE53FFBA3DAE4D0F6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A889788DF6CD7539086B99B8D6871A5538666618D2A20C8C0548E98D2A0E6FDE0A8FBB1A54BC2D1E871A540DC805F7F1C6954F9704AD37E98D3387344464BAEC298D37F120A6B794B7C24E34BC48A855900E5DBC71A5E257DA62140DD37271A5E24C625E031A5E256049231A5E2452AF2071A5E25F1435AEDF4E4834CF74CAD63A1F6C816706456895207BE51272E0CAADE1A2034E994C9CA8F25EE9C8D298C4ECD80A75A5C7521299125AA4CB9221146AB4F880DF2A2562CC7CAEB59D790DAB9025CB845EC16F10E4B45DBC731E5CDC880671A58A28DB22E6E309C2A0E75A77C5CB099451A918B021116F1FC74F1C5253A48A806D8B54954A2D3F8E2D9050E0B5A78E097272A28848158F4E9984425191A0414CAC8641A6A02476CAC86C0BD245515F0C810CC1A63DADCE1629187864405E37CFDE636699A6205687A64C313BB03B7D224BFB9E012A2B97458F876F5CF2D792A38E786478A8DC7C32333B2638A8BDE749D320B481005008194B7009FC50C75D862D8023046A0785316C010F20500E29A57B324134C2A426292B066C0D642A3CAD4A62D6421C5C145624EF5DB2C816B942D0525F173C589A65F02C0E379AFE66E996FAAE8570B40CE10D3F0CD9603BBACD5637E4D7E6158C9A7DFDCC0148018FF000CDE603B3CA6B31EEF25039027DF326F7757214D85F965D171A4E2BF2C99601BE3D3A65127231A9323576E9910C64A0C8D920C56A96AD0E58155D0035AE495FD83FF00CE337FEB37FF00CE3EFF00E6B6F2A7FDD1ED72618BDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A8F54702DC7305BD2695FD57E9424E2A898542F520E2A887914A15F11D71542A9AD452A7C7154BA7942494A6F8AA5D31323020D2B8AA22180135770569B8C5944EE8E411D28B8B6A1979198A114DBAE2AAF28F4D775E55F0C556DA71E4E7895A8C551EEEA829D7C062ABA08DA46240A0C55341198D6A472F962ADC13A92CBE99153D7161229DC101A06AFD19596704DECFED57C0F4CA24E5C198DB30740A053DF2993971E4ABE8947A7DAF7195B34F74A819650FD457A64496B3CD99C712CF2569C41A6C72B25B718671A0D9849148A139025CD84767AD58C01D5052847539496E8C7765768521A2952D4F0C0E66308812564340684EC3172404CE1734AF86282138B70052A7AEF4C5849368D948F0F6C5AA4B1C507DADB16D8286E7BF4380B9314744D4ED98A42551989208046F9590C8284C5BEEC810D810AEEDC0F6C8109972633AD4B5B765A9269D7234E3C4BCC24D39EE5DAA6B53D31AA72602D3FF2DE80AB74ACEA0EF5A530F139508BD86DECA389A3E294A0C04B394682747E08C7C3906B015ADA60E7885208DEB8B301184D462CC0404A18EDCA9E18B346D8802B5607160423FD440C7DB162434F32018B59096CD729E1B6374988492EAED549A0CB2326528B1CD465FADA3C4DF65D78D0E6CB049D5EAA2FCECFCE9D1E2B4D6AE233462E49047BD3377824F2BAB86EF96678C452C89D402733E06DD0E6145439004ED991170A4B8508AD29932C03741E19449C8C6DF25029C77C8863258789FD9C218A1D901AD053BE5A154591BB1A6495FD84FF00CE32FF00EB377FCE3E57AFFCAB5F29FF00DD1ED72618BDBF15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF89F0E3D33BE6370B90957306400773B63C2A893C9057A531A5414B39AF107738D2A6360038353D31E154BB508584E08FB23BE34A81F41BAF8634ADD1B74AFBE3C2A0A32D41F9E0E14F1353B32CAA4277A63C2BC49B7C0D082CBBE3C2BC484A537514C785789A1148F22D477C78578995C16E91C4848DC8EB8F0AF122B8464531E15E2524B74120A0EB919041DD3B55548C6525BA2BAD1AAF41E3BE5127320CD6CD78C60D329939514DA35E681B8D77CA645927FA70008DBE79592C3AB2FB280C8E1E9B1E99025CAC4377A3E8500E6A4FD39592EC71C5EA7A75B5694E990655453A11716DB172F105648A86A7BE2E5008C8F614C58108849CD7AF4C5A64994539D8E2D5269AE0B122BF2C5B20A911248AF42712E5453D8A9435CA2412BCD011E195C83243CCCBE34AE564360404C418A403C36C8D32E618B5E219BE06DFC31A6B1043DBE9C88EAC57E795C9BE019569D6D142438503DF2A2E4C4D0653115722831059C8D84C245063E98B00142301771D7BE2CC05766DB16C010ACA64AD0D08C595226D548A8AE2C486D890C77C5AC8519588077C2C084B26734EB954CA46C92DC826BBED8C249914B48F8C0FA7365824EAB54762F867F3DA0FF738E69DBFA66EF049E5B56777C797AA05CCBB53739B5C6E833F34BD97AE65479B8325C3651932C02ECA24E441AA0C88632688184315608BC47CB2D0AA4C8BE1D724AFEBEFFE719F6FF9C70FF9C7E1E1F96DE54FFBA3DAE4C317B6E2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88C69196127AED9570B9096DAC8649D09D80618F0AB26963050B571E15484A8697C287070AA610308CD41AF88C3C2ADCF2ACBFB1F11C78556B47C63E5C7B74C78552891B91200E27C7052A6FA64609DCD70213292D95E4A70A537AE0295CF6C586DB64789544DBB12AA13EC9DCF8E08CAD53386D49A129C6992B545CC68AA03538F6F1C6D54EDCB4A695C6D5368AD893CB9F4ED913BA2DB9A42B48C0DBC72A945BA324C34BB33248007EA6A4D328945CB8167013EAEA13EDD7BE5243951927DA622C90056D8D4E52609326436500120402BEF95CA34DB0C76F41D3AD38471ED94C8539B8F15335D2217F500029EF95172E269EA9A7A88E38EA2A69BE066237BA6E6207E2AEDE18B91134E238D3BF862DE26AF1C7CE9BF1C549B5AABF11F638B4C8A3D361F2C585371C7CBE2AD37C52364CED5796DE180B7C7226491D3F6EBF4640B3E25B27C3DEB4CAC864248095B96F5A65526D0508CFB78E479320503E887979D694ED9599B6844B5B86150DC699519338A6F6E802019592D802776D1D5280EFE3823CD289766E3403A65BC2B6A28581A15A0F1C7859892282961B1DCE3C2DA0A998985487EBD4E3C2C81B5D1A322B1E75A63C2B24BE49DCB9DBA63C2D6A4CEEFDE871E16B2859A1928183D699465145318DA477AF242A0D0B1390894CA0878F9B3A9A54115AE6C7049D4EAE3B3E30FCFBB7923D45AE78F2AEDC7EECDCE1C941E53571DDF1B6A16ACB3C8EC69CB7E3F3CDBE09ECE8B34774918D0D3C333625C1986E95EF97736B6CAD3BE5320DD02B9412064445245AF1193DF080BC2B0AB02464C15E1586363DF1B5E17F5F3FF38D029FF38E3FF38FE3C3F2DBCA9FF747B5CB03597B6E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D98A8B7639072125B39544C3E78AB27797F75F462A948156A62A88A30C554E163F584E5F67154E27E0D0D075A62AC7648CA82701546E95381285F7C8143339230D1864153DF2252A0A08201195211D0C695078D7C718F34A39A48047C76072C548AEC8E69C0D41EB8AA63A7C144E647CF154CE175AB8F7C082B1A1F524141D4E466CE2CA34AB6F488246F98F37331B2066569157282E4C59269F6CC5D4A8F848D865726639B34D32D97EB09C865322E6620F41855508551B28DB289976100C974992928A8DF2825917A04120E2A7C70B743927B6EDEA003B62D88958F93118B64516917100E2CC287A7F113E2716B3156040F9628E144C4B45DF7C578530B55EB812228A1CA83205B5425E546C8499452E7E54CA4B70429EA3C32259072FDA39410CC146A005699021B01B4CD015400E4086C0532B7978AD46301452792351CB76CBD00A2163E54DB61BE2CC145A41B74A571660AC922A0DB6C5B6254516BC875C5050BF54E4EE695C581287961E1DBA62D64A02694468478E63E50CE058FEA24BAA9032B8865296CA5C9A28E33C7AED99D846EEAB57C9F257FCE4246D0C493B2ECDDE9F2CDCE11B3CAEAB9BE25D56759642C050140299B6C01D0E61BB139012C69F4667E37026BD010287AE5E1A951BF865726C8AE465005722DA15D5D7EEC2AA9453BD3AE2AEE2BE18ABFAEAFF009C6BFF00D674FC82FF00CD71E55FFBA45AE5A39349E6F6BC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EBA9D962318514F1CA2DBD2086568E74237E4DBE36ACCE37F5223DB1B543A8E2F5EB4C6D51AC57D3E58DAA5F50581AD0D76C6D5305E4C8057E9C6D5053A108C08DBC71B5405BAFA73F20DBD712ACF6C6E8AA54A06DA943912944170E6BC403E195A15D2E022BD5474DB0412C76F2F19A4214D07B658AA96FCD8835E7E3ED8AB258A65861DE9B8E98AA5E977C653C68C09A9C5053DB39C33A92A0E426CE2CC6DD8351BA517A663CDCCC689854B5CA6F9417262F56D06C8488A37F63944CB7445A791C0F0DE2A28A8AF5CA497371067F6567249C7634A7DACC79173E316496561E8C80F224E524B221964638A281BED930D914DECE765A7C35C2CD3B81F93569D4E2D91473B6DD3166146353254D29BE285850F2229B62AAE8EE9B7018AA6768F4EA3AE2551ECCA83C72B2C908F286AED909328A11C8A74CA4B7041484006942476C052A51824824532B21368F8EB5DF61E390219829824818053B656436028F80A82141AD71884996C9BC4AAA011BE588053355AA29A52A77C5B01560CAA37C5982879248DC30AF4C59C4A0165547206F5C524A3519284FF375C5AC940DDAA052791C5812C62F1BE02C054A9E994E4512A414BC1EDD5C8A1F0C8C53C4E6712A20540420AE66E1165D76A4ECF9B3FE724B4F79FCBB1DD2C615947D91ED4CDCE10F35AA7E736A49E9BD1CD0F1155CDA61E4E833F349C0A0E43E23E199D8DD7CDD52DF115A13DB2F0D4D9A93D32B93645408F888AD37C8B6856403BB6154482B403962AA8154FED9C55FD75FFCE35FFEB3A7E417FE6B8F2AFF00DD22D72D1C9A4F37B5E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF876BBE87315C8485CF160DE06B8AB2DD364F561FA31555941018E2A88452D01F962A955584943E3B0C5538B771C77FBB156AE1D1D4A8EA70C552A02928F9E48A197589AAD3DB22528D63C72A4202EA7288287AE304B1A7959E5A7BE58A9D5BCAD12123BD3156E5D4491C4B6F8AA8C37039160D5A9C50591E9B745A5515EF909B38BD1ED5FECFB8CC79B998D3AB14E57287DF282E4C5ED7E598D43A46DE198D939B918D92DD411A5DA35075DB289173F10675A5BC7E94629BD331E45CF804DE8CCD551B786524B221388549550763DF2D8F2484DA24E00649926D6DDB16C8A3DFA62CC23ADE35E35F6C59D34235E67DF15A44FD5C374C569AF4590EDB602B4BDB91C8162A251B7ED909328A83A353AE525B8210A357A6053C9B58DC6FC71402AA0B1143B7BE408660AF5661DF2B219828BB695BD51BF6C88E6C89D936FAE84E35392620B23B5BB8E48802462D81AB89929B362D80A5227ABB0E58B3057AA826BE38A928D8CA804571604A1AEDD781DF16B258E3CF17C5191CB91A8CAE41ACC964482E3946A9B0ED8C42789A82CE732B2AA1E20666E1145C4D472795FE7CE96F2792E591A3FB009CDC610F39A97E4E6BCE5EF64A6C17E1A7CB3658DD06A39A5F08063DF3371BAF9B7407A65E393535C4572B9364541E262C48E9916D0B789185555436D8AABAAB53157F5DFF00F38D5FFACE7F903FF9AE3CABFF00748B5CB472693CDED7850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87BBB5531935DF31E9C863A543921B61ED8D2A6FA4DD324A200070AD2A7AE1A54E75173071F4C0656FB44E0A54C34F904B0716006DB61A54B2E222B72A00AA93D7052A342468952C41231A543955506452491B50F4C2020A1A83D415385871325D3E4F8B8F6E38299DA6373444E4BD7DF0708674C7EE1E4956941B1C1C20208A4BE38BF780B57E8C076502D386904501E00134E87236C8458C4B2C92CA6A00DFB640C99885A3AC80F4E466635076C788B194190E94DFBE06BDF2066CE117A759CCC4AF4D865129B9708B35F2E446F2ED44BB007F67283272A317B669F69F5495668EA76037E998F236E4420C87D2378E1CECC3F972B21CA86CCC749B3A471835AF7CA65172A136530C25187C35CAF80368926D1C2397235A9ED92029B446D328E20C37AFB6165C29A4302A01427E9C590D915C1586F5C520A362015401DF167C4E650096A9AE2BC48A85CED418AF1225959874FA3015E25AB6EFD5853293265C2E3180694EBB642526622AA2C95C7C24D72A25B4042B69D3A49CB882A0EF91E25217B5A3FECA60E363C28792D66542C62F8475A6478923642B46C3A46D8136B6349C3AF08CF23DCF4C40DD0648EB9B19446B21A863D874C953113455A7AB1A0E47638D33135D7771E9AFDADFDF1A6CE341C127AA58D7A0C04536C668E499D76FC7032E26A5BBE20107AE2C52A9EFA490F1DA98A0C6DD691722CF4E4D5D864A301269C9B328D32131373F4D4D7AD4648630A192470DBC70BCC8A0DC336E87A53333144071353C982FE6C68306B9E45BF515F552363C53C7369843CDEAA443F147CC3A4CB6DAC5F5B5C03188A4603E55CD96301D2651658DB22C5550DF2CCB8389382C415515CB9A0C5771CA6452154283414C900D814E445180AA9C6C4B71A6C3224A53058C507BE438D5FD727FCE36EDFF0038EBF9063C3F2E7CADFF00748B5CCA8F20D079BDA70A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8749E4AC447B652DE9347F131A77DB1557B6AC3386E9BE2AC8AE5C5C427F9A9B62AABA7B98D4027154C4C625607BF6C550579CA31C7BE2ABA08CC916E31415268087C5AD34B4E51B03F462D8134B97E51FD18B68415AA076901F0C05126A5B602A5464648097CC484653D32B6C4A963A927C7BE565B62B91FD30E3C4E218493CD1A4E532FCF2126507A969FBBA8F1198E5CB83D5FC9B6D5BAE9DF292E541ED92A18ADD683282E54026BA2C2EC39B0D8644B7443D0F4C8D782E5527222190C71AF31B641BC04C52104834EBD316F8A67142076F9E2C9305B72698AAB0B638AA323B7341B62C9CF6C7154C2DAD136DF154E560840F703014851692255F88019410DA95CF7766A08E601F1C810C9049AA5BC469EA8DBDF2B21B0228EAD1488C88E3938F872045325B15C4951591720C11C2E55455DD597B8C55DF5AB56EC98AAEF5ED88FD95F7184319206EAF2071C3D41926210735CC7140A43D77ED8B20C62FB52E4E141F6C5B137D2C92189E8C36C05B2298CAC1109C8B3B486F2EC28DCECB8ADB1A7D7218A5E25FA75C56D33B7F355A5BD393800E5B02C08B4DD3CFDA7A2D0381F4E49908D2D5F3FDB199B8C808E1B0AF7CBB1C9C6CF0B4A0F9D67BAB6BFB49B7826560A0FBE6CB14DD0EA30597E74FE7368325B6B97B7B04748A51C811E273638A7B3A2D462E12F9DA60F1BA07EE73371C9D76514887015A83C065D6E21E6B7204A40554FE1841D99A9C9D701296E28F7AF8E564AA37A0CAED5FD707FCE36FFEB3AFE41FFE6B9F2B7FDD22D733A1F48683CDED39243B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8739D15050D6994B7A56838C8A53A72DEB8AAACCDFBCF87C7154E2DE86024FDA036C551B6EBB6E37C551F1CA237523B763EF8AADBF40F1FA83ED1DF156ACE5E30D0D3962828D58E3937A5716B5748B7A1FB23A62D817CA6A287718B68528488CB15EF80A24AE5CB0C8C9012BBB4F877CADB12C8C1DC0CACB6C50EC84B1E58B0927DA3C6038206F5C849941EA7A38F526507AD36CC72E5C1EDFE4F83D39B95329939507AE9ACD1A2D3E119417371F2659A55BFA70F151DB225BE219469B190429D88CAA4E44427D6EAED3053F6720DE032686D01A6C698B604D52D1788A038A5328ED8F15DB6C5518966081B7CF1555312203418B2433E2ABE3623BD3155579F82925BA024E2AC5AFF5A8F81A380720437304BEBDB89598A49F09CAC8641266B8946E646FBF2B21B436BAB4F1FC21CFCF2B904AE3ADDCAF499BEF394B05875FBCA504E7E938AAD5F30DE29DE7A62A887F32DC471971354F4A610C648287CCB712CB4692B9260190C1AB4D31285AB45A818B30EB6E7753FC7B8AF6C5B1E81A7C451197A055DB0499DD35773908DB8DB22BC4F3ED56EE5A482BB0AE2BC4F2DBFBB732B166A11E18AF124536A2EE4297240E94CB20CE25080DECB25217600F8EF8934D9619058E9FA9F2462599BB1DE9928CF76899B67B67A56AB7118528294EC3336191C2C98ADE51F9ABE4D9A5D3EF649E127D0879A353BD333F164D9D06B70D17E7FDFAC4CD70B30FDF40E4474D86C7BE67E2C8F3DA914972492301EA50B77CCC8C9D613BABAEF4AE025B61BAB2004D3240ECCCB6F12D2A7224AAC0FC7E8CAC9558F3B76A7CB236AFEBAFFE71A8D7FE71CFF2049EA7F2E3CAA4FF00DC22D73610FA47B9A0F37B5E490EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87FBA8BD4048194B7B1D95BD16A1EB8AAAC3FBC353F3C553112FA6A476C553AB12255A8EF8AAF9E321AA3B74C5549AE015F4D8EF8AAC4AD76E871414E6D7B138B5A6C801E9E18B6042DC6DF3C5B52DF50A927C701449176CFEA353B646480985DD972841A74195B63152BC1C8EC0E565B62A4D4635F0C430927FA42FEF07EBC849941EA7A0445AE51BB0EB98F272E0F7DF2E22D40194C9CA83D12CB99611F5DF6CA0B9F886CCEB4D0C38AD3E8C89E4E44597E9F0FF00A415237DB2A939116530DA8F5850641BC06490460103C31649B2C6B4C551491B6D41B62A8D446A0F871569EDCD09A6E7164817B73BED8AA1243C176ED8AA4379764065AD6A08C55874D652DCEC95381B9520D0AE08355241C890C9171F961E43464A8F97F66565B0233FC191B293C7E2ED954F932E88197C9A00E998CC12CB8F2B8B78DA5E05F8761DF156297F6621AD206DBBD31563176EC6328B0B29AF5C218C90964D289B743D724C0335D3999E52A548F8716619DE89680B863D716C6573968D2918DFF6A980A4A4924C4F20FB7BE4516C475754653C37AD6B8ADBCDEE74C92791A83A9C56D42CFCB5732CDC1622E09EB4CB22764893D3347F216E924D1F1EFB8FECC848A99BD2EC7CA9630AA82AAC7AE40163C4CA6DF4AB5800E2829F2CCA84940619F99FE5A1A8F937549EDE1065F4986C3C01CCFC52D9D36BA1BBF1A35FD2CD96A5A84338E327ACDC54FF00AC7363864F27AD0C6648CC52943D466C205D213BAF4C9B978BBD156E393D0E36CA489BB4E2A3B57204A1219A52B5C892A8749F91A57A6564A1FD7F7FCE346FFF0038E3FF0038FE7C7F2DBCA9FF00747B5CD9E3FA47B9A4F37B6E4D0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88FE09E89206F986265C86217D18790FE1928CAD5640FE91DF2684C42ACA093B8C2A9DE95F01A1FB3E18AA6578547D8D81EB91B4A41229E7CB2064847C0EA29CB718612B2829FC7E888EAA37F1CBA835A26DDD016277DB225B0284E19CD17A65664DA103242114B30EBD30192D5AAE9FFDE644C9908B241CE489D4EE00E982D980C4F50B52AC59453DF06CD8024EBC91B89EF9125B238C1E6C93493FBD51DB2B914F000F5FD094ACC9C45052A731E45B601EE3E5621A401B7AE504B9B08BD5ECA14AAB22D189EB98B3951765860299FE9502D15996AD90E22DE22199E9F6D1FA9EA71F8CD2A7236DB10C9E1894B82474EF8B626B144ACE7E793114A611464B713D3C325C2153A8E3000DBA0D8E0E10AAAC0A8DBEFC7842AAB0F86BED8F085B40BF5C7842DA577708E2DC0531E15B62F3E9EF2B13C490712026D1765A5246DFDDED9512BC4C892DE355A7015A656496C125C88A29F08CAC96F8C95C01D29D72B2CEDC638DBED2D722634B4A0F676EC0D23049ED9548522987EABA7C6C5FF74BF2A0CA49626DE75A8E99C8B462314AF4A61848DEE903BD278F4708F511EF5CBEC32E109FDA69C435553E223AE3B278598E9903C34EC3BE1B09A4E652163241F88F5C8C9B211058B5DFED6FD6B9149800C6258DA4675AD47718B510A967A6C4CFF147518B512CE74AD3ECADD59961018904138AC4B2B49232B420500F9603BA69689A388D176AEFD71A452256FA9FB59206992716CF16A9A65E69B3012452C6FCA33DFE1399FA736EA759B97E31FE70E94BA6FE656B564578DAA3B3431781A939B9D3879AD6403C655A49EB34E794A5882DD36068336511B3A1C9000AA00074DB2B9158121176E55483DFBE52665CB8C6C29DF5C301B361E22A62C6E6766AF235C9B02104B38434069878583FB10FF9C653CBFE71BBFE71F1BC7F2D7CA67FEE4F6B9B087D23DCD079BDBF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8DAB09F719801BD8DDC8A4849EC77CB2294B5C736AA9CB1531B69285636FDADB0A19143FBB5AD7A60554F53D45627B602942BA77F0CA8A143D4DC01E38C0D154FE02C621E19719288A362069F3CACC9B045308E2046FF007E5664D822A7731064000E991253C2A7A7DB7EF3A64789908B2BB5B6AF30456B8F1331143EA7A627A65A831E26C1160A6CF94D41DB6C04B6C62CA746D3099936AF8E5722A43DA746D302F134DC65132CE01E9BE5C88ADC5076398F22E7630F63D1A20F22A1F1CC69F376388507A3D9C3C19401F4641B87366D610D29B6F8B6C53A4401C7862CD31B789CB123A65A392A610C3273C2AC8228C71507AD3155EF18A53BE2AD32EDFC715413AEF8AA19A307AFD38AB696D19EC36C0555BD140360065549010B22D180F7C810C8158401F3CAC86624B3991B9391E16C8C9DEB0C4C5B4168DC8405ABD3299452C72F6F1199878E6398A6AD875ECAA5C90054E400A4F0D2053E371B77C3C48643656C6B5A6D4DB1E254E12260BB63C4AB5A195C30F0C902DB89239AD253CBF56499C9237B57491B6A16C5A24995AC0C083DF16892730C8D1EC72405A225182E881D70F0B2B51376A49E477C7856D512ED36DFDB1E15B649A15D1127C3FEEC0CB4FA0E6660D9D6EAB72FCAFF00F9C90B196DBF342F66238A4AC493F7E6E74E5E73561F394A156460BF66B9B2076745946EA7FC72A996B886BD42A72AE6E643925D7331634C980892493DCFDA51DB6C980C4A56CE49D8E4C06A7F645FF38C1FFACD3FF38F1FF9ACFCA5FF00746B4CCD8F20D079BDCF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D880E040E87B66006F492FA2F88803AE5914A1C5B7186BC7E2F1CB108781585C46CDBAA9C2ACB15E3684803738154955A35663F6476C05285594BC9C6B55AF4CA8A157D052E2837C8F567109CDB3AA808D8993688A6B0C44B0A7D93DB2064D8229EFA01635A2D09CACC9B0456081581F86A720649E15D6F6AC1C7A6BC71E26422C9AC6D242D535A63C4CC4532BFD3CBC068B534C789988B036D34C731F82849C789B04597E8765C654257204B121EB9648B18400509198F32CE019C688A82652A286BB9CA497371F27B068CA81D582D0F8E5122E7E3E4CF6CCF29D2BD3C322DA39B36B4AF3F84D17B62DB14D56A5B03364368E811011BD284E5D1E4A9B200402A389F1C2A8F49102AEDBD3738AAE3221EA31543927715DBB62A82949036C550F473FB471556457A801A82BB9F6C555E458A31549BD4F639021925B35DB80CA2DD189E8DE190216D45EFA38AD889621EA53EDF7C810C4C92A4BB8DA29A46958B28F8129D72206EB19A0D2EA607D53C9D3F9299618B68CADB5ECB7069E87A71D3E2343944E0DB1C9691DD7EF83F01C58577198F28B609B1B78A560C492483F6B299C68365DA2ACEDDCC82BBE55C28675676A0AA80BF1531E154D52C588E98F0AAE5B1707A75D8E4A21B71A12EF4F2A84AAD0F8E58CE4C4E6B26939A96E2F5F84E2D1256787D2B16319E52C42AD20F018B449E6F79F9A5E52B099ACF51BD4B6B984F16151BE5916B2692D93F387C822A1B5B2BF223254BC4BED3F363F2FAE24A0D6D9B7DEB4C697899345E73F28DE11F53D5D2A7A02C31A5E2665E5DD574C9264F4F555256A428208DF2FC45C2D46EF833FE7278423F31E36DA482653507A13439B7D39741AB8BE3F6565BCB84635556345EC01CD903B3A2CA374422214625457B65536B8849677605E86832500E4C521B8B97527E3CB00625262EEECC791DCD7260312B94E4C06A7F64DFF0038C1FF00ACD3FF0038F1FF009ACFCA5FF746B4CCA8F2683CDEE7850EC55D8ABB155AE683E9C554F97B62AEE5ED8ABB97B62AEE5ED8ABB97B62AEE5ED8ABB97B62ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88BB53C866006F5971082E0D3BE5914A16E00488FCB2C42550D19E83AD76C2A98DBC844BC3DFA6054E2E29F56603BD3014A4515564CA8F3423C5C0420F7A65726DC7CD745704B8232B25C9AB6490DEA22A6E2B5CAC96C8C593433ACB1AEF9025B04535B4B70E188A1DB20649E14FAC6C55985464789970B281A7848C328C3C4D9108EB6D3DA78DAA2BB63C4CC063B71A3137205325129AA4EACB4A68DD6829824C4866305B32B2023B663C8B38B35D1A03EAA6D9492E6630F56B106109951E6E6C59D69DF100D81B073673A6FC4AA69D7BE2DB14E917E3C59A7D6B6C48461D0EF96C792A751A711BE155C57DF157703E38AB5F4E2A849BA62A82798462BBD71541B6A616B5AE2AC7F51F31D9C1192CC63A77C910D8C02F7F30F4BB763CB520A57AA93FD99590C0B179FF003C3CB167270BABC593DABFD99590D04A47A97FCE48793ED2A91852C47C27DFEEC111BB59953CAB56FF009CAA82DEE78DAC21A3AD1401FD99710C2390DA5F27FCE4A6BFA821FA8D89E0C09E407F665120DF1C858D45FF00391BAEDAFAED776C556BDC7F6663C839519BE91FC9EF3EBFE61426231805D4B961ED954837C256FA2AC7437AA9E3F4655C0DCC9EDB4C78CD48C3C0A9DC160481515C1C2AACFA79A834EF8914DD8D0379A79E1F7E06526177962A03963C585787BE2D1248D61963B1D453ABCB1B08FE74DB16893F32BF313F293CFDA8F9AB50BE8209A5B79A4668F8F402A7DF32314801C9A64C462FCACF385B6D73A4CF2D3BF13FD725B215D7F2EBCDF34CB1D9E893C751BB713D7EFC7657A0F977F243F30A7991E4967B343BD09A7F1C695F5FFE597E526B1A5DBC6DA96A0F34CAF5662D5D89E9D7251E6D1946CF1DFF009CCDF253680DA3EB11356474EBDFA1CDAE9CBA0D587E7F593C9373965D9DBAD73640ECE8B28DD16A7E07F1ED954DAE218BDCDC0124895E8694CBB1F26F88D9239EAE4E5A031921F8D065803595226876EB9301ADFD94FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A0F37BA6143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8294F845330037B52D4B29AF7CB2294AAF6BB8CB152D8D5830A547CB0B13C930854870DBD7C72122C2253953585ABBE54496C4A1BFBC6F9E441552641238567283AD7F86322299E306D98F967CADABF98AEE2B5B3B62C8C69EA01DB31CC9D8E385BEDAF227FCE2EC17515B5D6B32155900A293FB5BFBE5129B9F8F102F43D57FE716EDA2B988E9CF5403EC76FF89663CA65BBC10F25F35FE476B9E5FB932C687D193E1555ED4FA72066C7C10F3E5D0750B0B8F4E5571C4D0D7009A462A6616D632491014AF11BE59C4CFC20BCD9DC4428B551ED931309F0D012DB49CD59C50F8E094BB94C02636B1134F1C8711699C53368A452A791E9B60B6BA65DA0C94750C706CE442DEA763229E15DF289F3765879334D35C55476F0C8B7B3EB023E103618AA7D18AB0DB02DB27B16F8554F6197479330980DDC006A3C30A551862AAB18046E31545718986C82B4C585A57716ACD5E228322B691CDA75D716F8493BD32B2516F3FD674BD4DCBA4523A73040A1E99124A5E3BAE7E4DF9C35F467835BBB8977AAABD3F8E4F88A402F1CD4BFE71BFCE6F3D06AD732B576ABF5F9EF82D9D16357DFF38C5E757A97919DFF0098FF00B78B218D8A5C7FCE3179D43F22BCCAF4AFFB78F2639310E1427FD0B379CC48ACF6EBB1EE3FB720723891C459FF00973F203CD715C436F39F4A0604391B536F9E4253722185E97A27FCE37581BC59757B812AF2ABC2C6A0EFE15CA8CDCA8627D4BE51F22F97BCA10C49A3D9C5048ABC4B462808EFDF2A9CB67271E3A2F52B68AA828287C72102DE629D5BD9B4AA07877CB835909BC569E9815CAE4C0AAB428C0D08F837CA81B402424B733060D18415E95C2DC0B0ED474F6A973B835A0F0C5B0C424F1C216A196B4C5A6710105736314EDCC205E1B103BE0B21C59C2F9249756B69103CE352464F88B5F865298A6B78A5A450278D699602BE19661653F35154070DAF8659369F7D0DA144745FF4821547BE46CDACA1B6EC37FE7263C99179DFF2D64586D926BCB088C826A55C0E2C7AD7365A693A4D5C03F119A136BA9CF6922F131C8D191EEA48FE19B8C727439318B5194888DD21D890787B6DDB26402B080616EB44AB6EE6BC98F5C9844A21047ED1CB034C821DBBFD3930D12438DC9AE58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4F37B9E143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B535CC00DEAF28EF9645528BA1C8E58AA10C60B8AE2A5181789C045B590982FF7669E191314829431FDE36532D9BE22D52D2C9F52BE82D233467351F466365C941CCC18ACBF49BF21FC950E9D6105EDCDB2BD003C88F9E611CAEDB1617D71FE2ED0B4B8E21385E286813C0E512C8EC71E057B7FCCAD0EF6EE386270A76037CA2591BCE165F7369A4EAD6CF2CC527122FC209AD32BF111E03C475DFCB0B2D424966B78946E69B63E22F80F329BF2DEE609654856A17ED532D195071525571E49BB86BCD0ED93191071A437BE567442CEB4206DB6113B6AC90628BA7345395F7E98789C5945329ADB8462BD69D71B6BE156D224E33818F137462F48B49887515EC32B917618850679A4C84B2FBE06D7A3E9CDBAD76C5594DB8E4C3154E6D5C89197C32D1C9984DE13571852886FE38AAAC7D3154C228BBF638A6959A21DC74C82D21999882380CAD692C9ECFD53BA0A9DABE1919288EEE8ADE6B65F4924EA29838DC8F0D092DACA8793C8013D1BC31E36631A5773F003CAF01FA4E3C4D831B1E96F2047DEE86DEE72139ECCBC2B496EF568492A9722A7E798A7228D3282B5C489EAC373561D1413959C8DD1D3A274EB7964B80D2C859ABB2E40E46E1829E8D6914CC1226B6E117FBF48C8F1DB2963A65B6D6E11176AED96C0B5109D4238A82075CBAD810ACFCB8E5732D6425CED22568763D72B896043A38A39012454F8E49B6297DC5AF21257A0FB38B7249FA3958B6DF4E2D3916C1A423ACBCBB1DB22538B1F131ED53CBE8FCA87AE20B6F82C364D0258A60231C93A93938C97C047C505C5BAF43B6596BE026B6B0C976D645BED452127E583AB899B1D3D3AD2DC6ABA76B1A6CC39ACF6C63507DD48FE399D84D3A3D5C2DF87DF9F7E50FF0003F9EB50B20BC6970CF4A7F3B31CDB6296CE872E3A2F1CD4855D641FB4BBE650DDC7E4C4AE362C3C32C6322969FB67241A64876EFF004E581C7921C753963497F655FF0038BFFF00ACD1FF0038EFFF009ACBCA5FF746B4CBC72692F73C28762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B360BD730037A3E4A1E9DB2C8A529BB42C76CB10A50AF165A8A625211B55C622D8494E52786C77A8C998ECD60EE83BCF8AE9388A506F4CC2CFB39F845BD1FF2CB493A96BD68047CB8CAA6B4ED5CD5E59DBB7D3E3DDFA93A3D8B69DA6DABA0F4D1211555D8663176D8A2F2BD72D751D7353962B3321084B1504D32893B1C71D952DBCBBABE9EA26657046F5EF98F26FE009EE8DE78D5B41BD1CCC9344D45911892001DE99595107B868DE79D1B5B31AC92FA5310014069BE36930658D6A8E1DD40E128F81BC72C69945299F4A421AAA0D7C46581A0B0DD574359012117A1ED9312A6A9C5E51A9E83C2524201BF618789C69C58F5D69DC410476C789AB85274B5E126DF0D0F518F137C22CBB4752028356DFA9C376E5C0507A4E974053B7F98C2C9E83A6CA15803DA98AB288E7008A62A9AC2E480C3BF5CB63C998E49A42E69D4E14A395BA62AACADEFB62A9BDA5D536206D8B35F7373CA945A5720B4840ACDD09CACAD221232BD6BF3C84CA62375D2AF53D0E637139A12B9622FF0D49E5B6F8789B404A2EB492CA69DB071338B1A9BCBCCEE47106BED919CB66D88DD47FC2E3FDF43EECC4B6F115787CB8D1C8A40200ED902590A661A6E841543155A8F6CA8A788271E97A478D6A3C3082899B08E801D854E5F02E3109AA82A0153990C4869A471EF954CB590A2D2B32B0200C840DB54C25A4B89050903C32D6714C963F5A3DCD0A8DB16E4B64B295492010B5C5A72289825D8455A7ED655334DDA734BBEA32CA28687E782DC9E2583494460B201C9B71F2CB014F10448D060906EA3EEC9028E25F1796914F258FE9196C5C4CC2D36B6B45B53B2B03DC8EF97E39EEE9F518DF9A7FF0039C1E5223518FCCD15B8F4EE295217F9797539B2C32743A8C6FCE1BE9B8832EE55968066CF13AB9ECC50124B549CB4B594249D4E48354940F4CB038F2511D4E58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88089A86B9801BD338CD40F1CB22969E30C32C420D8713B6291CD6D4E4A00B1C8B58D46E69979AA681CD40FC7331F019ABD4BB4D353E9EFF009C74D21751D692A952B535A78669C9DDDDE101FA397F6CB6DA3D360563A01DF2120ECB0B7F96FE5B8F503777862ABD08AB0EDBF88CA661D96309BF99F4A3043246918E9D8663C8373C0752D0F50796436F096321A37C35DBEECAE99458DCB65AAF96E48EF4A4B50C0D02B78FCB101127D05E48F375D6BB6612E418CDA850BCB626B4F1CB0071E6CFEE66658C7BE594E34C149A525D1AA3AE46450030AD4EC83B31A6F91DDAA51613A958D0F4A6DD71DDA845864B6A56423EFC6CB7C629EE92854283D6B9747937067DA79A32E4959BE9FBB8FA31564A83718153C85A8A9F2DB2D076660A6B136DBE1B4A354EC3F1C2AAEA4D3154742E148AF862DC119556C8324C6DE256A74DB2B28559630B95CF92421D979661B900A87A7BF4C0CE25B30F2ED8B60696C4160481B74C05B224DAAFD487F2D7E8CACC5B812EFA90F0032042D9575FDD0E23E9CAC861C454DE124FA9D7DB214CA3225673F4CF4CB62C885C353111AB6E3A65CD65506A91C9DB2120C0B6F771D36DABD7238F9B44D0E675AD69972628BB797D571C7609D716F64B58A587871DE98B4CC162B7F21D31F8769872194E45C7612F87519A46A274F6C886EE229B44E646066D9874F96482F116416C22E23A64D788A756F2AAC4151030AF5CC989D98917BAA344D37488610E0E78BE6AFF009C9CFCBF4F347E5EEA73BC5FBCD3E2661B54FD963E199D824E83541F83FAA5A1856F216D9ADA5650A7AECC7B66EB09D9D0E6D8B0FEA58E5E5AC1D9072F7DF2516B9287ECF5ED96071E4A2A773963490FECABFE717FFF0059A3FE71DFFF00359794BFEE8D69978E4D279BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EB35F7CC572138A74DB2415A634196054B67900E44E487355B1CE38D2B96EC8282B9AB74F1CA665880A912F22CBDE99ABCE5CCC5B3EEAFF9C4EB113DD988815E25AB4DF6CD69767A626DF647999435D5A5BAB1D880403FC32B93BDD3F37B97962CD6D34832280ACD0EF414CA245DC621B30AD5A77B849A302A6A77CA2459494B4AD209812478C115DC951FD32316A1CD3AD5F49D15B4D91DCC3EAAA134655EB4F964993E64BFF300D235631DB30085C8F82806C7DB1453D5F45D7E4D52D54D6A683F56147084DE0BB3C9C4B4DB619645A728A49EE7799DFB1E992A68A627A944199EBD4EF8D2D30A9AD944BF3C6928AB440B28A61566BA79A30C559A58BFC43E8AE2A9F46FF10C55388EE00551E191BDD04A3A3BAA8EB8414A363B91B6FF003CB1B02312E47CE993661328DEB43E3DB16E099C4E38FF000C82A2606A656528D2A5C0A75C84D5BF4CE6310DA1A2877C890DB169537E99590E405754DC572239B656C98C511A74AE4E419C10D7111A1F7CA64E4001085780DFE9CC793090097CD7263A953F17860873681CD26B8D4E58EB5A6F97AC92A7BD9A405877E9938B4C9AB7BC9D09CB29A095433DDC8E4AD7010D68F82EEE0515D6BEF819C5368272159E9C69DF16F82223F307A4425457A62DD1016DF39D5F871FB4A28299092C804A6386EB4B928C84A9EE722C53D86EA3640CFF0068E2A98DBCF0D462A9EC13D221C3ECD76CCBC5C94A6B67744115CB1C2CE16F9AB4B1E63F2E6A1A4900FD7A090014FF00248CC9C45D06AE0FE76FF3A3CA4FE54FCC6D7347652AA9348C05283AB1F6CD96293CFE68EEF03BA6FDE483A10732E25A2B648E7152773BE5C1C69F35315000AE6445A96E5A036C407F661FF38BBFFACCFF00F38EDFF9AC7CA3FF00746B4CB43833FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B31D2B98AE426E47C3920A8694EDB6F9605482ED982BD01AF864952E86670D435F961B414D50730396D909A0370370B8907B7539AECCE5637DD7FF388F76A359642E05617A0AF7CD74C53B4D3737DAD359B5DEB30730410C280E63C9DEE9F9BD5EE3513A558B2745F4F8E5327718B9304B6D4629D679188EA69BE63C99496DDF9DEDB46B231B952D355547707C72316A1CDE15E63F38EA77F2C896933047A8A2939364C22DF48D42E6669E7E72173553D7157A56853DCE9A1622080682A715672D70DE9A3AB862FB900D72D838F991729E56E186EC7A81D726D2905FC25CA9FF277C558B5CDA9049A6D8AA95AA71931565567B32EF8AB2BB37A11BEDDCE2A9E46FF0010A9C55358CD40DF21D58946C792641191E58D811B1D6993661368998003C316F4D6273415E990423918D4532B294EED8065DF6F0C849513C465242789A2828720437464B553C7AE4087263255A002B4E9910376CB454520E3D69ED864DD0536219C0EA3C7289736F082BB1C50D3AF8E63C98C986DE4AC3950EE0E087368EAC3758BA99281493F2CBD125897130B346FDA66A11938B4C9111C92B15A6FEC32C0E396596B6D298D0AA924F51896B45C92C36A959402E3AAF7C8B6458E5FF99A0A18E21E9F0AF3AED8B7C5875C7984090BF30057662716F8A79A379A8C328726A95EBDB2052433C9FCC16DA94694515EE46458F0B514913505413E0315E14EED0C408E5F0FCF6C53C29D2CD1A2715229D46F97E33B302AD6F78A1BA81F4E4F89AA70B09B5AEA9CAE91030658C153FECB327149D36AF13F22FF00E7387C9B168FE686F3446800BE6259C0DAA6BDF3618E4F37A8C745F9A7786B7136D4F8B3638DD7C85256E09ED9787167CD408A66445A9665A1BA2FECC3FE7177FF00599FFE71DBFF00358F947FEE8D6996B813FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B33D37AE62B909B337C24788C2150E57E1396854A665FDE0C4AA4F29A4D5F7C802828E0F545DFC36C24A02E97EDB53C33132072B13EABFF009C5AD5E3B7F345BC6ED40411BF8D735F986CED34BCDFA88F12B6A36578375E20D730A4EF74FCD11E719DCE8F2CD16E6BC49CA64EE317278326AB710C14E5BF2E998F26526317AF79AA5F3210480A29918F36A1CD97683E45BBB86599E33C4D0D48C9B27A641E5FB0D360637340C47C18AB1BBFB6B494B7A43A74C550FA4A869DA222841A0CB60E3E6667058D09A8EBBE4DA503358061257F9B154A27D257D36FE98AA4034E546229DFAE2A9D5B5B22815C5536854290A3A0A62A9E47D302A2524A151E191EAC4A670CC7EFC90649847374CB1B022D26AE4D984E6396A06FB5316F098C6D5A64109A44C2A32B294D216A50D76AE4648298FAAA76C890805BE55CAC86D896F9656439112E26A322DD12A65C0EFF003C8C9C9C6D7D657A65126F086BA9818CF8E63C98C983EA32F10EC3C7A6087368EAC1AF2F19A4A7865E8936B7C562A1DF261A648ED37518849CA4DA996071E48ED7BF31F4AF2D69F25D4AEA0A834AFB62583E6AD6FF00E7226C2732CF030660C40A1FECC8B38A3BCB7E7A8FCCF6F73717527A224A7A5BD2B8B7C53237D1CC5E2AF348F7AE2DF1627A87E63C76529B0869198F6A0EF902D8032DF2B79D6FEEDC0E478B7BE4534F6FD0F5096499096DCE2B4F4225E5E1F175C5691261936A4DC76E95C9034D13E6EF425FF968FC71E26C10B08CB698D9D02B739240791AE64E29381AAC3B3E3CFF009CDAD163D5FF002CA3BF02B25A30634EBB54E6C71CDE57578F77E2BCF2195DE43FB44FE1B66DB0F27479051428EA3E79921C39A1E41B9F9E6445A90A577CB83745FD98FF00CE2EFF00EB337FCE3B7FE6B1F28FFDD1AD32C7027F51F7BDD7162EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87DB371502A2B98B4DF69C13D01C90554E3B7D19312094A275F8FF005609482B1EB8DA6F964225055E3625900049F0C9A014D110167327C238EC4FCB31F240B938E41EA3F935A8FE8AF31DB4AB2846332802BD413D7303340D3B3D2C85BF5FF4FBEFAC6876376AC1C7A43E319AF90A77DA722D34B906FF00CB573DDC3120663C8BB9C4367CFB35ACCF70B0202CDCF751D466392999A7A8E81E5AB7F53D69286408A48F0C62D319025EA16D3456B0085221D280E499DA4B7BA7C9A99268691EF418DA5E5DE60BA83439191E550D5FB24EF82D52DD0754FAE6A30B28E20FE396C0868CA1EC8564540C632011B31193B684ADC1624914DF738ADA94F1A985A8C09A614816C6CDB92C4D3BE282295046CBD01C55150EC77FC7154F22208EB8AAB2005AB9162533840A75C21923E351B64DB0146C69B64EC3208A89CF2A5698DB784EA17D86F90B54D616AD28722529AC6F414272242AA2CC01153898B0E0368F4DC546FF002C818B6C415F46F7CACC4B9116B953A9A7CF20634D91284B89000486195483978C84A4DC7C62AD4F7CA241C805B966AA1DFB65120C64C33569F843235413D86463CDA3917973DEF2BA615AEFD32FB6264159AF9A12ECC85815D864E2D5229249E6048924DC230AD01EB9686821F337E6C6A3ADEBF6F1D8D8A4A07A8DCD97B838086145E59E5AFCABD62E21ADDBBAF26E546FA0F8E459C43E91F2CF96E2D234B68AE18C92C207A2ABB9F7C69BA3B2AEA725EDB594AF65138918100537C5B8178FE9DE5BD66FF547BABE57ABBD547B64241B4483E92F2CE8A6CE18A886A06E70527883D934189F9AB73E86871A5E20F4069278F8904D3C7052F105C6ED89AB392DED80DB44B9B5F5BFF29B23BB91090554BE113C4C5AAA55AB5EDF3CC9C4D3A88D8D9E47F9E9A41F30FE5579801AC92C51B32C23AD02935A66C71BCAEB31905F8377711867B8848A18A46047FB239BAC3F4BCCE7152418076DBBE65C5C19858EBB9DB2F8B4A1580CB04806E8BFB2CFF9C5EFFD667FF9C76FFCD63E51FF00BA35A65A393813FA8FBDEE9858BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF874B265328CA593246507853C72259C513C07139596D0935D28562721D5279311BC929375CBA1C9A24BE0B90268E872F8F26013B9650F1EE72126FC68DD12FDAC351B5B98DB8B472015F6CC2CE36761A73BBF5CBF267CCA9AFF966D6D24903148C0A66AB287A1D2C9EF3A5AA3C9FA30AF10FBD735D91E8714B6615AEF96C695E6084C43E0998548F7CA29A739B7B3E89E598CC6B3247EA19D0034DE996403878B9B2EFF095959C5F5ABB70AA054A9C910E482F39F3AF9B340D26C192C028B85560E57B900D32B21982F8EB53D425F345F4CD2A91463C09F9E565B014C740B2D46CEEC39AF18D870F964E0C66FA4B4DB8379651ACB27C400D8E5B17166956A21E262886AA456B9634F54B2332383B6581C8835E9301B8DF0144D690475C0C694FF6CE2B48F85C01F2C569188D520D698AD2650B50628A4D633D314D23636DBE58A8B6D1C73A62E60E49A44FD37EF8A53BB6906D8AA64241B6298F36CB0241CB9C9149B5ACC1471AD2BB656BB2600823AE40ADA1A7038B37865534DA493C828731CB740A4B3C94AD3AE51272E054DAE1BD322BDB2892C8B17BEFDE73E7D32B71E658826968D7264A7535C21A2D327D2BD40401D475CC88AA42FE528A69099146F99015747E43B157E7243EA03D0787E38C92194DAF9574C8900FAA8DBDB20C9CFE5AD3CCA812D40F1DB154F57C91A75C45536C3953C3FB714A4375F9736C2559628F804EBFE75C8948445AF97520223A74C0A9FDBE962CF7036AD4E2A9DA32BC746C550727A49B03912CFA2025B845DAA3DB20D40EE827B9574702868466463E4E55EC93F9C6E3D6F27F986253F11B4947FC21CD962745AE2377E0879810C7ADEAA87AACEFFF001239B6C3C9E3B55F594A17F8E67637026B24077FD796171D02EBBE5526E0FECABFE717BFF599FF00E71DBFF358F947FEE8D6999D0FA47B9D7E4FA8FBDEE99260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF861D3DE432034DBC72964CB565278537DF2259C51C6600152C2BE19516D093DDB13CBDF23D5279308D403ACA3623C32E8726892193D65742548F039911E4C03258F9B415E276CAE4DF8D49039755A94A1AD7E5989945873B0BEE7FF9C71F39AD95CC3652DE0EC3893F3CD7658BBAD34E8BF49F4D9C4C12F512944AAC9E39AEC90779872A6B75045AA442EA420CF17D95EFB653C2CF24AD9FF94B596B3B6953D1FAC49C6853BA8F1C9014D111458679F7CD173E94886630F20691FDF890DC0BE62BB6B9D42E984E8E6366F858F7A9C810CC1645A779360216644E04EF9510CC1640DA298978C49CDA9BD30C42C98F1D46F6C2F56DDB946A4F4CB22E3CDE84B492C83BB0666DF2D69EA81876276DB261C88372321620900D3A602C8A0E414DFB604521F73B8FBF15A5652C3A0C5691F1F2A2FEBC56933849A5295C569348C9D85715A46AB506FF004E290162960DD3E9C5BC724C627A002B4F1C529DDB38DA8698AA6AA4F615C5239ABA1EE72E6DB541280CA396F5DB2056D324B903E127E2CAD6D7CF23189FC29D72A9A82C7AE255E81B7F0CC72DF0293DC39505A9D3289B95028069DE9D0D3C7289A494AAE999D08A6F5DF2B699157B5B55600D37C21A93AB6B3ABD38D76DF3222AAB3D8AEC547CF3202A360B3429B10580F881C64C8223EAE9F6792FCB20C913069A240EC08057ECE2AEE735BBF02E062A8EE64C4C18862DD32254242E8166AB0A6F812A978C161AFE38AA412DD98E062AD52062AC4DB54B862C0D46E72126CE88492FE43B16A6443472288B5B8E714A7957A664636F32F4A035894C9A16BEA4D57EAD257FE04E6CB13A0D74DF86DE6D503CCFAE85DC0B96A7DE736D8793C9EA0DC98F053E199D8DC19B9CAD3AEF96171D06E2A76CAA4DC1FD92FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD333A1F48F73AFC9F51F7BDCF24C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85DD35C96DF2964CB6023E1F9E44B20BA47FDE1DFBE5526E081BC7A2935E8323D527930FD45CB4887BE5D0E4D1253673CE1073223C9806516854C237CAE4DF8D12618E343336FDB31E4E66366BE45D767D175482E623455606BF7E61E58BB1C137EB17E5579EA1D734AB485E60D23280457E7EF9ADC917738723DF2D678ECAE638E75062946C7B6F94F0B9B1DD1535D496978CF6BF0C53281B63C283B21750D223D6007B800D7C7224282803E4ED387A4428AAE4086C05192E8F15BC5C621B814C810CC1632F697AB3858A22EA7A90322366576C7353F2BDE5CDCA4E632287241A26C820B0921B658DF7232D691CD4A5B431C6C476C9872209210DC8961BE02D94A72313B605E15200814C5695D6BBE2B48D4278A8F6C578531B76E9B62BC29B420938AD261E9B1FA714D2F119FA462D815D63DE98A53680D0818AA6F149414EB8AAE6980D89CB99F12D5605948EC6B5CACAF12A7D6292EE77C815E245CD755888F11954D416352CE7D43ED98E5BA086B89B92F1F1CA66E5C4A5D24C146E731E4A4A57713165F8776AE56D5229B69DCDA95C218B2AB5421AA4F514CC88AA37EAE5F71D33202A8C917A2373C6BB63264103FBB06A64A78E4192610DD451A37192BE3BE2A96DC319E4E4B21A0C551714AF1B202D514C894847CBE93A87D8918158F6AB72681074A74C55894D73C636538AB16B9999559972326D1F4A4C2EE477A1AD322E393BA716F70638580EAC4664636523B286BB2341E5FD79D8F10D6B21DFFD439B1C4F39AF93F11BCC8E24F30EB0E0D435C3107E939B5C3C9E6729B293667637126A2CB5AE5A5C7502BBE5526E0FEC8BFE7183FF0059A7FE71E3FF00359794BFEE8D6999D0FA47B9D7E4FA8FBDEE79260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85EB109D5771E394B24EE19497451D3950E44B208D724C840F1CAA4DC1037B50A4378647AA4F263B7B18AC6C72E872689206EC51A2653D32F8F26B08F82E48A440FEF295E39093918D3FB23F595759AA225EA7FCAED94172E299412FD5A2223FB75F8328C9172B1CA9F48FE507E663685756D0DE5D985C90B1A13B577F7CD7648D3B4C3983F4F342F325A6BDA35B5C3DC235D7006300824FE398C767698B202C860D46692358E54A18B704E0B05BA62D35B6BD77DBA0C890C63128A79D8107964086D102AC932B00246DBB9C898ADD2296EE2B643E8C425E5BB31ED95914CE3BA167D4A2991B946108F6C431940B13BCBC049111AD32624D3E19B4ABEB13382AC2993130DD114974E3892186F8DDB6092041DCD46D8AF12E6EA4D36F1C57897091456A715E2565993615C578C2656CEA69EF8AF104EEDA4407738A6C27B132151BE295540189A62CD1023351B7D38AA24232D0914C55148DD29D31559373AEC32DB544DB9A0F8BE9C812869C7C7C874F1CAC94B6F229000395CCDA84AA68DB996A6DDCE63B7C36414CE95A577CA66E540A45792D09DEA331E6C88B41C2FCE4006E7C32B6B9448DD9259C81283A64C45AF8939FAD3715E0475DF2E0BC4135B7BD2A9566CBC49788295C6A1137DA3CA9D4612CE26D8F5F6A9044A5AAAB4DF761FD723C2CE982EA5E7AB3B105566524D796E36FC71E15A63C9F9AB6B1D47A8A5BE63FAE34B4A4DF9AE92238128592BFBB507AFE39190544695F99324B308EE25A027615FEDC8D26DE956DA8C1A8C0662D56E831A5B63BA93FC7C23A927B531A543456723C3FBD4A313F86464D8262A90ADA70462426F91693024ECB5ADCAA0929448D8733E19763906194F0879FFE736BA343F26EA571EA7A69776AE96EDFCCC54803EFCD86298797D76404BF1AE617524D2CB74BC6791D9A415AFED1CDBE290AD9D1CE24EEA7C18F419990C81C498A5AE8C06E2872EE305C7A52E058ECB5CACEEDC1FD8DFF00CE308A7FCE35FF00CE3C8F0FCB3F290FFB935AE67C3E91EE75D93EA3EF7B964983B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BD3BEC652C938B6FEF53FD6C89641399500ABE5526E090DF3B32B11D40C8F549E4C7AFDE4E31FE397439344905217668C78E644793584C2C406BA27F9475CAE4E4637A6796B49FAFD95DBA0E455AB94D5B951E4C7EF266B5BC6B775A50D304A2CC4D7C26EBD7496194C7E97C48D5EF985931B918B23EA0FCA5FCDFD5B48BEB6B6D4EF19AD9481F131A537F139833C4EDB06601FA51E59F3FF9775DB2B764950C8CA3910457F5E53C1C2EC6192DE8D0C7672422789AA08AED91B72E050F34C84A88C74FB59025BC6ED2C8DF3F0C899354A289496A8CBD2BDB21236CF0C50922D011E390A6E314BA4B22416A634D44255246633BF638D3021033905B7F0E996C5ACA0682B5C92AC734247E18AA8337BFCF1572B74FD78B594CEDA6A0A62D914EADE652462CC325B6605462D89B4282A3BD71668EE031558ED8AB68DD3C3155772A77C9AD2989950100E56534A46707A9C84969A1254D474CA8A40DD648F5539516D8A4B350354E5126F821258048390DC0CA26DF14B638945C71E5C4D3AE463CD728B8A6358E05E4641B75DF2C70F850ADAC5B16E0660BC4D6B5C9C53C0D4FE71D2ACA2224B95A8F7FEDCB578581EB3F9B1A3DAC4FC640C4D42D3C7EFC945B2029F38F9ABF379DE597D19DD63A9E95FEB926C7906A1F99CD71EA52E9AABD4127FAE2AC557F301DE46ADD356BE3FDB8AA656BE75BD915E4B79CB2A1A36FDFEFC8C9059D7947CED24B7F18BB6661C803D7FAE455F61F973CE960B68891EE0EED5F1C559347E6182E6752B106A9C55939B95940658F8823A64486A3CD0CEF5AFC19590E4C64A2FE9B2FA4C2866EDF2C9C22E0EAA5B3E40FF9CA7F308B7D046911BFC71A9F86BF3CCEC71793D61DDF9A864E681D8FC4D527375861E975929521B91AEDE399020E26492E33A13C5B7236CB40A68B4D2CE28A4EAB9600DA0BFB03FF009C6A017FE71CBF2000E83F2DFCAA07FDC22D73363C83AFC9F51F7BDB324C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85CD3C715A1EB94B24E228DC303B75A8C896514F44323C058D3EFCA8B70499EDCB24B5A647AA4F2492F638CAAFF91F6B2E87268925A5E07F8D2B48F63F4E6447935854B3E4B73327ED15247DD95C9C8C6FA0BF26AC66D5D2F6D22512486A287A6541C8E8C6FCFDA1A586A5710950B75093EA0ED936B32A79F192E1220A4D2A39291954A1698CD562D4A485158BB2C8A762329389CFC59DEF9E40FCD2BDD0960334F2B46E42F52694FA7313538A83B3D36A1F767917F3C6C350B782092EC06A00431A78660183B5C595F44693E60D3F558D7D39939103BF8E53214E7C260B295B66E21832303D286B94CB666775DE8488EA781A1F6C31DD944D35246EC6A23603B922992A64648A11A98B8820B569418D06B24062FABC2D683D4996887A531A6B25884B751B92C84D0F8E16050F57FB5514C285BEA57BEF8AA9B9F7F962AEE42837C5ACA2612716C8A3A17756152298B30CB2CE71C455B16C64115C28A55A9418B3470B943D0E2AE3206E877C55B57A0F7C5548CFC07C677C9B6D20649CB37C26801CACAAAC659B71D32125562DC76AEE72A2AB7983515DF2A2CA2955F3D15941F88D29944B937C1A8A4021F8CEF4CA26DF1631A9DD7A3C9D1A86B4C8C39B29724A9EEE49E3203354E58D54C4758B3D4562F5226DCB5363BE4E2B4C2A5D0754BE722494F1EF56396AD05A7C8B6654FD61CBB1EC7A64A2B4935E7E5C79767564907C4C3C324AC0F51FC93D2262CF6E7883526BB62A935B7E45D8FA9B9A927AE2ACCB4AFC83B510CCFEA705E42A323241677A0FE53E83A5C81A62A597C722AF51B0F2BE90CEA96BB1514A2F4C55153583E99708A895DF638AB2386FDFD3459051FC3034CB9A2D6E19876C8F0AF1D34D342CF1CA4F1FAA2B35D7CBAED9918A3BB81AAC9B3F327FE7257CD967AF79AEF2D74D9DA48E0E4AEAFB6E2BD33638F1BCDEA4D97C82C5D763D3B66E30C7D2EA66511000C4572DE4E24CA356D6126BFB44EF86D880C92C2CE20061E26F8C5FD757FCE3780BFF0038EFF90AA3A2FE5D79580FA349B5CCE87D21D764FA8FBDED19260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BB6F848AE52C9904352B5F0C896514D3D7E36C77CA8B704AE3943AC9BEF91EA93C921BBFB2FF004E5D0E4D124854D2198FF94BFAF2F8F2601358471B966F18FF0086424DF8DF5BFF00CE24D8A6A7E63B9B6715564634F7198F234E544585BF9F9E5A934FD775396342055B7FBB1136B9C1F3100C614E4370B96036D06C20E54F8078D72756DB09334D247FA1C629B9EF9467C761CCC597853D827BFD3254B8B6BE642A6A141CC09E27698350F58F2A7E73EBFA4DC470CF3B988951CABE14CC49E276F872BECDF23FE7858DD476EB3DD8694815527E5ED9893839A26FA16D3F306DEFE28A55911380A28AF5FC32318A99D2723CCC6F10233A229FDAC970A0E54AEEB5C834C9030BD578C8E4C6BDF1E16A395E4DE74FCD485A64B586753DB63FD98F0B039103A66BAD7D124BCEBCBC30726C89B4F45EB1A2F2DCE2CD1092357AE2A88F888EB8AA834850D3C31605562B923BE2CE2895B86AD6BD716613AB4BB7000AF5C5B03238AF8FC3BEF4C59A651DD934DFAE2A9925C57BE2A89593E1FA314C79A065763BD726DF4A22BD7E9CACAF0AAACC13BE424BC2E6B8AFC43B6545045209AFB8BF5CA8AC50571741DAA4F5CA64DF04BE7D43802AA731E6DF148E59BD77A3FD9AD4E461CD390D04F6CCD998C291BD32C71B8D4EE6D2240640BCD5B6E3FC72617898FB58A732E4045EF962F1A51A8CB688AA88FF001D77C9C59C656C3A7748E4E6D27C35AE49938EB9A728547DC8C55522D734F520C7154FCB154C63F30B49F0C44411FED29DAB91920A5375AAF2B9553217A9ED9157A77945B99568C1E05A8D5F1C559B798AC80B713AA0E406F8ABCDE3D44F221CD181A53080E3CCA6D1EA238F5C20346495060DF999E7087CAFE5C17AB2859EED1C15AEFD08CCCC31757A89D87E54F99EE6EB5CF30EA3A93312B2B311F4939B5C50D9D266365881B52546D999195075F38DABDB5A9EC3194DA2504F60B08D8AF8F7CACE4651C4CBAC3490C071E9E190395CA8627F58BFF38EE9E9FF00CE3F7E45C7FEFBFCBDF2C2FDDA55B0CDCE23708FB83A3CC2B24BDE5EC59635BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85884F361C76CAF8536C96DC111904D6A301816424D4A58C5C075A65462CC6441C41E1560CA5C9E80654765394525D76A423B31095ECD96E336D12CA18F05E69242AC0B484107B6C733230348134E0FC0EA6849910814F964278C86F84DF60FF00CE1AFA8BE6C997890CB5427B6F98594539D8657B3DBBFE720B44F56E352AA8320526BF40CC7E2A679214FCFAD422F413895A713C4E591CAE14F6485D8351286B5CCA84C14464F40D0A20D0C709A127BE3964006F88E264377A544A16AC797E19892C81CEC008418B78D5951D6BE04662642EDF164A099E9E2EED2E565B29CA1435A1398920E58D500F50B0FCCBD6A0F4E192770F0ECBC4ED4F7DB2996CCBF3024CDED7F37358E01259E4E245363FD991B41CAA7A97E61EA7771FA705CCD461B963FD98DB0F1187DA6A375A8DFA09E4919F97DAED8DB1337D27E58965B5B3854B971D70F0DB958A7419A457ACD2AB576F0C781B78D90C37CB51F153E79122990926B15CABAECE3E9C090B6491493DCF8E282143D555F1F962C86C8859EB4A57DB1640A696D24840DF167C4C82094556B5C53E204EA09169DF14F1A3A19949FB58A414DE27523ED8F962C816DD4788A0C9B68CA165630A41EB4D8E40848CA12C9E4E3FB5F3C810CB8D086E9551AB5395485053249E694B3F2076F0CA0C911507B8526B5E998F2986E8EC954D3879295CA8FA999CA229B69D6F1CF22ABF422A708853564D4090A6616FA65804AFC5CA985C7F1107776E2353E99A8EC3240AF88C3AFC4EA181A508E8327C6BE2306BCB3672F20635EA41CB319B6DC79186DFC7292CA49A65DC2DBE284858411732558B1E95C7857C5097FE9178643C5453DF1E14F8A11BF5DFAF71E6CD13A0A2F1E87E795CC5309660CAF42B41EAA34BFBDDF6AE52649196DEDBA3AC91C6A21554A374C1E2065C69DEB17D722C9A3908269D7263763E2878E3CB28B89030DEB52C3A53261C7C99022CDF47042D34AFC238FED13964604B87972BE3AFCEAF345C799357B8D2F4F98FD4ECA80723B1AD6B4CD861C6EAB3650F99E6B7BA8AF3882BE99D9877CD9E3141D5E49A0EE2DC076006C3265C594952DA2A76CAE450236CA34DB28E591405353D7316526F8637AF68BA242630596BB6527239718BFA78FC884117E47FE4D443611F91BCBAA07B0D32DC674FA7FEEE3EE1F73CBEA3FBD97BCFDEF56CB9A5D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF858B4FB432AE36EF0D94C1F6457A77C789061488210F4C89DD81539220637E0C15E9F0B7865660C244524D756F13A52693D47F019761C6E31905B67E5ABED43F756D68EAAFB89E9B0A66C61065198B425DE8B7BA7DD4114CFD036D95640E66220BEC4FF9C378DD7CE37019830E62A335D99D8E10017D63F9B7A7A6A3AB6A7005E47D36DBE8198526DCA6DF997E77B23A6EAD25AB0E2A0D7200D38138B07922A10C33271C9AC459B79526E573E9B7602992CC6C3958B67A75E5A7308CA3A8CC493B0C692359B89375DF28C8E6C792BD9C6E26238E63C925131C00CEC5C5083B644C6D946549998D5694C1C0CB8D1B1395E31815AEF8F02F1BD5FCABE5F49D16764F8BAE3C0BC4F5AD3A16810474D94ED86A9CAC4764E919B983F7E25B814DE201A8CCD4272A93644A690F1029C8E41B0146FAD40003B0C5928B4FEF8A559273F0D4F862A9A5B5DD286B8109DC57CA08DF0B105358F50403ED7CF16C051297B08228F8B3051E9A8A01B3F4E98B3B6CEAC4FED64896622B7F4913DF205988A067BD249F8B204B608A0FEB47725B6CAA6526282B8BC201A1CC599445269AF5FB5731E4DBD17DAFA93480F63928868996716303222B74DB2E1071AF74EA3770295230F84B6A53B32AF23BD71F097898EDED5C1F871F096D8D4F0121885EBD72CC71A6C81B63B77A6990310BB9AE5CDAC12FF4AB80CDC50D0F4C558EC9A3DE3BEC877F6C551B65A2DE8956B1B52BB653910636F54D134C962319910E6290D9183D46C42C7C05295DE980067253D7A655B76DFB665422E34CBC8AE2ED959C0FB3FCD968838939879279F7CD7E8594D630B9591C1008F7AE5F8E0E1E49BE6986D2E66B998CE4C8EC49673EF99D8F675D96492EA9A6709AA13BE65C4B8336373E9D234AD45EF84968E04759E8D2B015427299C9B61167BA2E84EAF1931F5CC6939110F67D1F4BE318F87B65326F8BFA35FC955E1F937F94A9FCBE4CD047DDA7419D5E9BFBA87B87DCF29A9FEF67EF3F7BD372E69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF855B670AC2A330CB984B2785D5A23C4EE46C300938D3C8037146EC0D640A57B1EA73271C6DC59E7013FD17CBB7FAEB98A106353D588EB9991D3B85A8D50112F59D1BF2CACE1557BF01993724E5F8F03A39768B3EB2B0D26C08B45317A454D401F16C3C732BC3D971F68BE7EFCC1D3E117D1DCDBB5631C8041D7BE60E78D3B9D2EB789F437FCE1B5928F37DC48C4A6FCAADEDDB35595DFE973F117D6DE76B8853CCBA848F19742AC38FDD98530EC4EEFCF4FCE7D0AE26D50DF5BC263889E5D3AF4DB292D5283C3230655657431B275AF7CB612A6A31A651E578C9BE1C5A94A65933619E30F7148792460EFB653273F1AF4B1ABB029C89E87C3289B9B16EDB4CFF004A3F0F5F6CC7924A3C6845A6E741D7A530C5814DA3F2DB4D4A2D3DE99246E9B59F955DAE230141A7B62BBBD7748D35ACA255DABE00615B2C9238C83C9969ED95973709D912B1FC4081F31912E48298C7C788D8E552660A2D08A743EF90660AA7A95D80E9D31656EE05BF6A98A6D772A7C35E9B62B6898A4E3D4D7145A244DDF9D315B442DD11D1B1640A3E1B84A8AB6F8B65A6D1DC42109A9E98B3077524BA534DFE5809724144FAE0A9A1A6DB6449660A02595BFDF832A25B0150FAD71DB9572B994CCEC8692E958D28731A4D112BE38BD42083D7B656D97B325D36D5415240F965D8E2D332CC15408C00287C732E107189B2B7E207ED5465BC010A95E638B0AE3C0150B2DB07E8B8F00543A699CF9D453C32328D3762431D138B54D18785320DE8693CBF0CE45502D3C7156E2F295B83560A47CB154CE0F2E598707D351C4F865536704CA6D16085032D001945365A47724C33A90A7805EA3C7271834E4C94C63CC5A8C0B6EDC9E840DF3371E375B9333C3755D61A4574B67F1ABE640C4E064CFBBC875ED367D4A61297F881DC9C988538F3C96A56DA488630CD1737237232D8871A52B492FF00449A798BAC3B78658254D2425FFE1E666DE2A1F9644CD90C6C86C3CBDC40AC5DBC321C4D831B38D3F468D387EEF7A6F9592D822CEAD2C5234038819596603F7D7F27871FCA4FCAD5F0F286883FE9C21CEAB4FF00DD47DC3EE792D4FF007B3F79FBDE8D9734BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF84F5A9238F5CAA50699EA135805C2D19413C7A0F1CA841D7E5D4BD77C9FE4C9F5955BAB9531A36FB8A7F0CDAE9B15BABCBABA7B25BC363E568B8428AD2D3E13B75CDC474FE975F9B54642929D43CD1733551578D7C3251C4EA660B1C79EEA4E530908600D30CE1B231715A437D65F5A82269F76DFAE6A75317A5D04097D2BFF38A5603FC513C69B50F519A5C8F59A4818BDF3F32C8B6D7EE550D4EF503E8CC4C8EDA06DE35E6CD274ED634C8E1745F5C2F2DC6FDB31645BC45F0F79C3499F4CD4E482088842DD40C6326A9C55BCB703DBDDC25B66722B97036C22FA334EB45963889EE06093998D91DB69F1FA87E1AE5191CD8F245DB5845F5ADD46512E6929EC1A746D253877F0C8DD2631B66365A3C2101283071B2E0641A7E9B6AB2F22A0536C7897813496D944AA517E11D71E35E0463C28C415E94186DB63B2E580602DA0AA88B88F6F0CAA4DA0B74A641902A65A84D3164D09A9D7155F50686BD77C55DCC0DB90C554DA6A54F2C516A26EE9D1B16C06D552F883F6B0330518BA937F37E3859834AE97F4FDACAC96C1345AEA15523976C812CC4D4DAF474E5BE544B671A88B82CD4E5D72124CA7B2AAB0E42A7BE504B18B23B331FC3B8C039B6B27B39A35A6F9978A2D190A73F5D8F8D2BBF6CCBAA71495CB728DB636BC4ACB301B8F9636BC498DB3ABF518DAF126255154103AE4265C8C25AA467ED0CADC97048491B0C5556910EE31550692256A823DF2B9ADD216EEF23E34AE5643194D846AFA82420B33058E952C72EC637703365781F99FCDF662678397A8A4D0919B2C7074D9B3BCEE7D5EC0C9584D10EFF004E6588389E2DAFB7F4AF4811906B80C11C68897479C39A3D01E8BE19514A9FE8B71F69B204A695974DA007803EF4CA8C9CA84764C6DED78EDC0636CF85905B45180BF08069BE368213650028A0FA3157EEEFE50FFE4A6FCAFF00FC04B44FFA80873A8D3FF771F70FB9E4753FDECFFAC7EF7A265CD0EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85F8ECA6827585979C84FD919084FC474B9674F6CF29F906F35036D773218A18D833A95FB437DB719B1C3A1E274FA8D43DA2E0C763686D6D2216DC06CE3BE6D30E8F81D5CF2F11610F34D76CEB212EC8767CCC3300535006ED2AB986E56455F4CB03FB54CC7F1699CB7539675B32AB335030DEBB532B9E76EC1877633ABEBD05BC4817E3095DEBE39AFCDEA7A8D0E301F49FFCE3379B34BD275C3753CAABF58466DC81C4F875CD5E6C342DE931914F72F3ADEC17BACC9A94171F5A4B9DFD21FB35CD7CE36E44254F2DD5E40F74AC253188D3E28FDB31A78CB951C8F3BD4BCA69E67B826C23334CBD471FEC395F0D322049E6DA8F93752D03518E4BC89E28D5BEC95207DF4C2254C6389EA9A33F3B58E48979851B8C4CDC884699569EEACE6BD5FF000CA652722324EBD158255940E61BB6545927D6AB1D43EDBEE47865728DB644D32A8A7884600F0C1C0CC4ADAFAC952283BE3C0DD18DB27B39964B73CA3DE9F6B1E06C186DD1A90A6A77A9C9C62D528515707AED84848D950380A2A37CAA41902A4CC7B0FA3214CC490EC549353438190921A42AB53CB14F1297390814AD3B62B6A2C66F7EB8ADA8BCAE2B5E98AD201E46AFDBA62C97FAE07FBB2A7BE2CB89DF5C03ABD0F8E02CB8DB5BFE34F8ABF4E506569051B1DF7203E2C896C89561755FDBC8D3305556E7810FCAB4ED8382D24A252ECBB57A7D39138523252716B7C626525B901DB11869978CC9ACEFD64A7C5C72F87A5AE53B4DE394935E5B53AE5BC77B35108B8EE82903957DF229114CEDEE62E5566E43C3DF1663127705DC0A2B8B3181305D460208A74F7C05B618F854A4BF87C46001B2D06DA8C6BBF2FA3088ADA1A4D622029CFF001C9702DA17F4AC4C681BE23D05729CB1A5AB405CDD731BBF0F01918C2DC7C9B3C4BF35FCCF268FA60B6B78DEE2F27158E34AF434DEA332F1E3751A8C8AFF00959F947A8F9D3433AAEA90B5BFAA2A3983B75F119B1C717499A565BD67FE71E6F9B549EC74CD4B9F04E6005EE7B74CCC842C38E254C2A7FCA7F39795E57730C9731C7D5829FE991941B23240C3785A76B4BD06DEE22DA507B6634E0E4455269E35902A2FAA9DE40731CC5B8056F5410027D9FD939518B9319505E8CE36AE222C84938B13CC8A8E9D708091BA7885760570A781FBABF947FF0092A3F2C7FF00013D17FEA061CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8797343B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D2F23F91A57BA4BFD6D6BC0D68D99B874D4F199B556F6FBFF00315959471D8E9F1AA0A7024019B9C18F85D466CD6C59E49EF25615E4332A52A0D50DCB2DF2D6856B70C52551CE43DF31324DCEC38B88D3D353C81A7CB0F32AB551E03FA663193B0FCA3E7DFCCDF2B2E9FEABC7B2C7E1F4E53293938B4F4F9C6F56297D485DF7198E64EDB4F0E146E83AFDC797196E2DE46AA9A00091D7E9CC6CDB876719D3DDBCB3F9BD24F2C31DE0DA94AB1FEA7308C1B0667B4D94D69ACB0BD12208D97E3151D3289636F8657A07911B4F7D723B3D2E146909A39DB7CC738DBE395EB1F997F96F6BAE687305B355D42DA332D55454D47B0C8F03938A76F86AD6E6EFCB17173A65F42C9F1955E429DF0183920B2BB7BC4616F2C5B16DDC65660CC165F14EB3463B9032071B30532B566E2C3B83B65538D1499526D019BBD6990E16719A6917C5DBA63C2DF19A6D6F7CB1008C7E8C785BE395344BA420107AE061396E881329C892A0DAD663C8D0ED9592CC054571DF2BB6C017F2B7FDA1BF7C2A8599ADE876DBBE2A82372A361D3A0C5541AE7155295D4AD477C52934EC6BB6D8AA0C87F138AA8307DB7380A43AAD502BB7865062DA0A3E1269D7A60A6C0510A5BF98E34D80ABA3316515F98C69369846687AE16B4C2075322A96D8F7C55328A7F498156AD31564767AA23108EDDB08544B5EC55DA4FC724C81444378A5A9EA7BF5C2CC14C92F401F6F6F9E06C1277E9458EB593AEC37C84CB6715A849AC27412F4F7C8829421D6A25AF292BE1BE580AA026D6226DC3FE39602A841AA52B2C64B329A0032AC82DC5CF9B81E8FA0797EFF00CC36DF582AC8AA3AD30C62E064D45B23D2FF002E746D666FABEB1682EAEE27FDDB915A27874CCCC61C0CB2B7BEC5E5C8B43F2FBD969AA96E889B050053F01997034E0CE16C3BC93A446D35E6A37975CAECB32853E03A665C25B38C63BA6F3C3CEDB526BEB5496201B83151EFED82526710F942FF00F2B62F34EABAAEA1631FA2F393450294A57DB31E45C8807897983488FC97713E9FA8CA1A624844277CA0B7C52BB760F0C4E05030A819590C81A45AF5C14CC14D74F6F888F0C7859829D237C58D3305FBB9F945FF0092A3F2C3FF00012D17FEA021CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8796B43B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF911B5D4CA4450905BBAE74F1C603E6D3B48AE67FACCEA900FDE16A6D9682038A626D9EF97B49957795D99CFEC9195CE6E660C6F47B1B58EC87AAF540BB961D4661CE4EE74B87D4191C5AFAAC65616692836E5B65066EFC600F1FF3E4D71AB45708F1045607E21F4E5329B64703E3BD62C6EECB539792FEE8B1F88FCF31CCDB04292D9AE9C158E18C484915AE57C56C8DA31A49596358E416F21EA54E44840059C68FE69D574B44824D51BD24151F16E7D8E63C837C6DEEDF96BF9A30697AC437F733A5B98C8A9E5D7E798F272216FBDBC9DF9E9E4FD7AF7EAF7B7111F56309212474C003978362F14FCFAD33C9F3EA31DFE8572B34929E46314A54D7C301736DE23636377C39471820F5F6C8101B0499559B2DBA8F59E847619590CC14FAC751B37996105CB374DB6CA671B613932D59618940988453D0F7C8F0A04D136CD6F2352390BA9FDA1BEFE18385B064A593E9D74D30689498C9DD8E3C2CC66461E76A80354A81BB65538EE9F15B87528DDB846416F0272B316C8E54DE3BC454025A06EF4CACC5C98E45296FE05DD4B37B5321C0DE24BA2BC570095007BF5C8B0326E59EDE9BB004E28B4B5E48F7A1A8C56D41A44DF7C56D45A4DB167C482797AEC315E24135C76A62BC4A06E0D7A75C4A89287AB43D72921B414545734A53E9C785B01B45ADC8F1C785982AE2E42D0D7A74C14C89D95D2EEA2B5DF035DAAADD92C17953DF15B4CE0BB006EDCBDF15B44BCE78F247A3FB6109050E2EEE01FB44FD392664A69697B329A93DB147123FF4A3014240FA71533A434FA846D148EF394310AA81DF018DB28654A6E3518B9DBAC324B2198D1CD3A60106CF142A299A4BC92D622F2040086237DF2622BE28651A77947CC5A9C4F35BD83945E8C4102996082F881EB3E4EFCA9BD9D44FA8388EA7918FE5898BAAD7E4DDF4559E9967A26872A40024C828A0EC09C9083AFE3280F24DBDEACF7535F5BA2C8EC5A075DFE1DE997C4522ED966AD33DA5A4934D2963312A213D299785E152D23CBF696D62D3ABB191FF007A2BDCB76CB449A670DD4BCD4C2CF402DC4249715529F3DAB80C944698D7953405B5B06BB9A61140D1C923CDFB5D2BD32B25980FCBFF003D4B379FFF003D6EF4486FCC7A769D39ACAA7ED509EB9021982FA1F54FC9D96DF4DB7BFD27525BB9258C39B52C28BB0D85322907778AEA52AE8F70D677C443780D046761F7E2C814CEC599516534A30AEDD30365A6515E425FE26A7B61676FDE9FCA021BF297F2B997756F28E8841F63610E74783FBB8FB87DCF21A9FEF67FD63F7BD172D68762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EF578F9B5C06FDDBF4CE9B8DE267A6651E54D1967BAFADC9BA72AAE552C8E29C1BBD62DE25826E4AB45AE56656E6E0C28FB8B9068427241F697C72B9F276F871F0EE94C97B4256184257314C9D96395B10D522BB9CC8D23058687965129399116F07F30E857BACDF35B58446572D4F8728949651A4E34BFC8DF335FC6918B3912693756A76FBF2B126118D966FA67FCE2079E3569D2425E28DBA7F9F2C4C9C918596BFF00CE13F9AA29D1E5BD255853896E9FF0D944A4DD0C4CC2CBFE706B5A9E359DB5858C2EECBCFF00E6ECA2526F8E265563FF0038CDA7E8171691DF7994594A8F4F50494E4476EB91126D11E17A95A7E487956EAE62177E6E597881D6407F8E032660A7179F957E4CD35D2DE1F32C444A28C798DA995993602A69F929E539E932F9A6293BF0120C812D82491F987F2C348D2EDBEB1A7EAA048836F886E7EFC46ED3964C33FE55FF009A2FECCDDDAAFD7517A01BFF001C970B57131F6D13CF3A6481DB4B6B5B68FED02A454F8E3C28F11136DE77BCB598417D6E4229A31A634BE2338B4D6B48D6A25442179EC6BE380C2D81CD45BBAF28385F5EC65A93B8A1C81C6DF0CC92CBA4EB91A13E9B3D3BE40E37331E54BCCDA9DAB7EF6D0923DB2BF0DCA8CD53F48A85E722346C7ED2F8661CC516CBB516D4ED5BED311F3C82AFFAEC741C5B63D3E58AA8B5E27F362AA2FA82F4AEC3BE2D96817BF5AF5DBBE29B59F5A88FED62B6DFAF19EF8A82A2648EBF6BAE45B42BC6CB4FB5BE1640AB2B8DB7C0D815B92D3AD70164AD1B0A75CA9AD7F2DC50EF8551D0135A5715477A8513956BBD310CA3CD6FD61BAD324CCA9BDF49F663EB8B548A3ED2C750BFA705635F0C5ACC99E795BF2D359D7F538AD591845506507C0FD396E38DB0964A7D476DF933A0D959033C4867812AEC7B6DF3CBBC363E2A47A4F937C9BA5DEDDEABA95DC29145BF027AF1FF006B2C18D7C5629E7CFF009C98F23796F4ABBD13CB56714B76A0A0950577029E1ED93F0D7C57937E5BFE746B779ACC375AC4AD0E9CC4B70EDC6BF2C84E14E3E63C6FAAB53FCD9F25F9AEDA0D1F43981BDA8590AF5AF7ED80069E07B5E83A3AD8E9B6019FD4927456E47B03DB260278588F9D0BDE6AB67A65BF660580C902ACD043E8C3A7C1D2A02B8F96264C4861FF00987FE997DA7E996FD178F35191E2470A335A8DA0F265F5869B66D3EA4B6CCA0815DD908C921F9C3F96FE439FCB3E7ED77CC1E77D224852EE6768DCA6F424FB9C3487D831793349D5EC21D5BCBBADB441E3E6D64ED4E1ED4C348B7E587FCE45F9ADF47F3B0D3667A346FC5A64F6A60E1660A1FCA5F98F1DD086D6693F771A84563DC78E34D80D3DA2CEEF4FBD50F1CC391F7C69982FE81FF26E83F287F2A829A81E4FD0E87DBF47C19D061FEEE3EE0F25A9FEF67EF3F7BD232C69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8BED12FA6D457F46FA12ADBC7F626A7C47E6736E72BCD5193DAFCA1772C114D67796EF4894FD51E31D5BB72F6C899A63A6B6609AB5DA32C37B6E2DD587C2E452BF2C78DCDC5A4012093CFBA5D95C5C4123AA9B7157693A7EAC13C9B39630D30CD5FF003318397B28A39E2ECD18AFF0CC4326D863A62B73E79D575085C4517A61F6F886DFAB29949CC807D51FF38D7F96B36BF24BE60D7A33C62F8E30BF64F43BEF98F29378C40BEE7D22C74E69E9269D0C76D07C10CB1AD18BF45AFB655C4CBC1E1DD9E8BFB58ED1ED0C421BF857933462881478E266DF8E16F93FCD9F9B3A89F3543E5DD06E92E5E7904370EC6BC2BD48DB2894DCD86114C9FCEFA4EB5E4DF2D0D6EE7CD33CD77749CA3B3864DAA7B5331A536C38E9E45E5CFCBEF30F9C746D43CE7E64D66E20B0B2532DB425E858FB0C89C94C463B64BF967F973179E359223BABDB6D26DEBEBDD31A6CBE06A32072527C17977E75585B796FCC53E81E54B9BBD4A68BE15773C8F2DC640E56DC7A7B286FCAFF002B79ECCC351D62C6F9A0421B801F0F1EB959CAEC31767F13E9997F303F2DADECC68BE67D3A6B4BB20707028DB6C4E1198863A8ECDA28BB3F307935EDBD0F2EEBB25AA1FB2B2BD313A92D3FC9A82D7B509BF41DC2C9AADB5F475256456ABFCB251CE4B4E4ECFE17805ADC68374F7306A7693F224F0940D8E644276EB3361314A5FCB71DB96BED36F0C31F22521734232F0C2386C59661A17994D9010DE5D212BB75C90882931A7AE681AF68FAB442DD6E22172B5E418ED919419C7210C953CBDA4EA2A566A7ADFB253ECE63CB6726398B18D47F2CE695A4789223131AA377A7DF98192365CC86434C1755FCB7B8B552CB1866F0EDFAF2A316CE379BDEE87A8DB170B6D29E269D36FA3234C81481A3BD462258245A7B645210F34BE98F8C1030B7525C6F2035058838B3115212F03591CFB53148802A6DA8C6845198E2C8E20022A1BB59A95241F6C5AC48A3967229C6B4F138B30510B73D37E98B74510B703ECD7AE03BA65B045070AB50D91E171BC42AA92EC64AEEB9131489A36DAEC3380DB0F118084892266BD759111006889DEBD71886C81DD1F0992E18C50C4657A7C210572CE16D243D3BC97F957AF798E482792310C524A1645E8426FBF5EB8F0B8D393EB1D1FF002374CD2AD24B8FACC8B2409CBF7A76247D38F0B8D29A0B4DF33689E5E3793CF730C571A7D79F134A8197618B10789E11F993FF003955A5E97697F6FA0A9BABC98323B49BA8EA36F87325AE669F188F3B7E6079FAF9ADAD2F561B59FD46B94534201A9006C3C70DB8E7290C5B4AD3E1D275392DB592F717334A03C8FBF53DB27C69194BEACF2AF93E2D6E1161A2A492974A3B36FC411DB2B99B6C8CDED5F941F9172796BCC4FA84AD2CE8CFCA6F537E277E9BE56CF8EDF74C691C2A8109E1025501F6C3652082F3BB1AEA1E6A7BCA739223C78FECED8DA683D06F1115A198578A312DEC72F8C0485A90180C006AFE6C9243F14708DA982500189A66B1C4F1488518AA4B5E5F25CAA52A6069E4DE67B48BCC7E67B6D2DADD25B585C7AEC07C54077CABC621AF64279ABF2B6EF4DD2B5AD5741BE6B484216823534A0A0EBBE4865B6C1005F879F9B02E6E7CD9A80D61E3BA9E1958073B9DB26269E00F3089B568627BAD3D12358E4A1E636E3ED960368D83D2B43F3C4F63259C11C9CE5968272DF641EF4DB274178807F551F9093B5D7E45FE4BDD350B5CF913CB92B11D2AFA65BB7F1CDEE1FA23EE0F2DA8DF2CBDE7EF7ACE58D2EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90FF00CB7F20CFABEB70F9784FE9BBB0569CD76FA727E3B8A3474FD1DD03F23BF2F3C93A589BCC5E60B79AEDE3E4119F707EFF007C7C76C8E969F1C7FCE4679DBCA97925BE9BE5331C6DA651649E3E8DC698F8EDF1C34F985743D435AB73A95C5AB244568B514F57DBDF01CEC8E34D74AFCB3F36EB344B1B65B6B63FB4C074FBF29395022CB74FFC91D5CEA169646F0CB792B82B02D6868457299657271C5FAB7F90DF96FA8695E588AC2E2331968C027E81941CAE6460F7693CA361A1E8F705C896E5DC145EFCBB1CA8E46E10BD9F397E76FE60587923CA7269D6404DE66D67F72186EC81E9BE0395C8861A60BF911F93BA0E956D75E74F38EA0B3DC5CC06ED8B36E8C6BB75CC79657371E36216F637DF9B9F9A52D868F792CBE5AD35E9287354A2FDDE198F2CACE589ED7E70F2C5C6B0963E42F2E5C1B68B4F939DEBC6688E0F63959CAD4715259E7AF3EE89F933F97B37956C5565F325C2141243F6F930237A57227236E3C5C4F19FC99FC9EF3579E357B2F3B7982E85BDACF299409BAB2F20DEDE390395DBE97476FA57F323F30348FCBD8C68F62F6D3B88F837115DC0A7BF8656723D0E9B40F813CDFACB79A75A6BE9E0145242328E80E0F11CC9F65F131F9AC2248F925F4B6EDE08D4C81CAC4F6481D1434AB8BFB2BB8A73AACD71A746F59A177AD4F7C9C32BAFD4F66D07D412F9D7C87AC79623B2D3ECA38F5644A34B415E599B8F23CE6A7414F0F3A6EAF7777248B3B95AD16253B53E599D8E6E8F2E1E03499E9BE5C56BD53AB192DE2247276DB2F127127165D7FA0E8F0317F2EEA85EF1002C8ADB93E18CA4D6229B7953F33A6D26F5346D6AD65424F1FACB0FA3AD330E72722117D2D63AAD9DEDB42F6B79CD5D4155AE634B9B971E48AF5AD89E372BCD7C72B219A1DACF4FB9E4A6C57813B371EA3C72B21B2293DE792B49BB25BD08D49F6FEDC810CC3CE75CFCAFB296390C4A2B534A7FB78B787916A1F965240EFC54D05698B6061D7DE50D42353FBB240E9F462CC31B974CB8B7E4B25B9AF8D31672E4848D2584EE87171AB74D61B9A8E25295D89C5B150951DF1640B4B28A80A773DB14CCEC9AC658A0DF22E2A3ED62326C7A1AE34B68D58A15824653F18E831E15B645E43F296A9E67D5E1B75899A194D2B966385948C9C2FB83CAFF0092FA779295353D5A2170654E410EF4AFD3991E1A0E77A4E82DA4699F5ED6AE255B3D3ADE3630C55A55C7418F86D32CCF3DD5BF33AE7CE574749D20496F6ECDE9B4E36047CE98F84E34B23CEBCF1A3792FCA7A1EA926BBAA97BEBD80FA4BCF7E743D725185328647E5DEBFA8C32EA57C2CE212DA991B8B91534AE4A98E4928F9735ABDD1EF0DD69B251CAB7A918F9634E29927A350BBF32B5ACB1DBB3DFB5C207A0DFED634CA2FD64FC8CF29C1E5EF2B0D66F63A5CC9081F17662A3010D8F77F23D85DCB6FA9DE5CC815667261AF8646922D3CD6EEC69D62189A168F8D7DF1A6C8DA43E4EB4FAB9B9D4661B4D5E24FBE34CF74E755BCFABE8B3C8C68ECEDC7E9E9878E934520F29DB1B2824D4E71BDC92149F7CAE5918905956A139B4B19A73B7D514927FD615CA253B6B312C23C8F6AD35FDFEB972B54B824424FBE5129313128BFCC0FD23079435716F2B969636A460F4DB2D8DD391189E17E06F9FFCB7AE0F34EA9A85FD94CD01998F220D2996C4B0902C7749D26F7CCD7834686136494AA9229C865824E348909B47E4F86CB506D288E57711A09325C6E399C83FAA2FF9C7E80DB7E437E495B375B7F20F96E33F34D2ED87F0CE9307F771F70FB9D2E5DE67DE5EBB96B0762AEC55D8AAC7DC7D38AA9D0E2AEA1C55D438ABA8715750E2AEA1C55D438AAFC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF233CB9FF0038C3E4DF2ADCBEB13B133D0B1911C0CC3B2E7ECFCE5FF9C95D5A6B1F346A1A7E95AB4E6C625612C5CC96E229B03DB1B29A0F89DEDDEF00926B97974FF5394909AFAA47BB63653C2FA87CC9AF797F56F2279774DD25D34B4D3A86707FBD6A0A751BE365061B337FC8DF2C5E79C752B7D26D6F2E0CAEEA11B937122A32B258460FD2CD3FF27FCBDE569F47B4B9B432EAF28065BC6DF8F427299172618DF40456B6BA6D9C16FA4C4102A51E4661D69EE72891A732106272C4F737978F79C94DADBC970B272AA1F4C578D077395D972B1E3DDF9E76B6317E6E7E6FDCDAEA08F69636B318F8CA7ED509FB35F96425272B829F42FE69F927CBDF977E4FBCB5B1FAE896F63315A4924C4A7A8694A0F0DF28916D8079F7E5DDB5EF907C986636E96B7BAC9ACD7DC6878B03D0E512939118A6307E6459E97A6DCD968086FF00CD3316F4EE07C67936DBD2A72B2594B0DBCCBCB9F94BE65F327999FCDDE78B1B8BA4327A932C95E0141AEC08DB2264E4E9F4FBBD4FCFBF9ABE57F2AE8F0E81E52E7677F0A18E242F550D420EC32B26DE8F498007C75AEDF5D6B378B7DADDCB4D7B292CBBEDD7C32B327A0C31012DFADC21FEAF343EABAED118C5283DF07139825174B3C0842B583B13D2B91254CE285BAB580C5EAADAB41714FB1FB253C699289759AA31AD93BF21FE5BF997CF5AA25B7942D9E390B52E6465257DE9B6676393CB6AA9FA0BF97DFF0038C4BE5FB186E7CD3299AF1497996BFC33618E5B3CA6B620CB646F9AFF0025F45F3497D3AC6330A8F843A6C7C3AE64893AE9C5E7FE59FF009C4B6F2E6BEFA88BA9E78B90608EE5878F4C12935883D1FCE5F91FA16B366919822B5BC450A27550A6B4CC49CB7722317CD97FE5DF30FE5DDECA90C72EAB696CD44F4EA683000D8F40F2E79AEC35E884733AD9DD746B7907C55FA7010CD983EA0F1AFA3C1404F85180EB9590D812B7FADCADCBD6F84F4036C810C834F248AB406BDB7CADBD21BA53293CD41C5B42552E936F221AA038B20C2B54F2BC3217A44BB83DB16C3BBCCF54F2A4B17F751803E58B5F0B13B9D1E5B706AB4FA314243346F1FDA53BF4C50A5146DC838041076C0589927F096E03236C0A6F6C582FC3D7FCEB931BB548A3A0D2A6BABC820B40CC2660251D7AE5A22D7C4FD0BFC98F24E95A1E9D6B7A2D985F08F90673515A7865F8A3BB4CF23D4FCD9E6780AC36D247CE78E3ACC3F6683AED99341C7F11F21DDF9E17CF3E61BCF275ADF243A7D94865BB8D0856A0EA2B5F6C691E25BD5935BFCBEF2569062B7A34F0A7266EADCBFD6C683025F9C1F9BBF987A879ABCC37C25AAE903E1B5727627C0602144A9E07E85AB1755670AC4D77C1C2C2791D64B67A6DC898BB2CBB8849355DFAD463C2D5C56FA7FF00203CAB16AFAF433BBC73C664570817DC1C785BE127EA25D4634ED0934E0BC04DC5828DBA0ED9121CDC401E6CF7CB6D0268F089CBAB2814A1A7DF829BC4425FE6C65BF8AD6D636E3561C877E38D331009F689666F74B92DE195614B215766F6C69B0462C1FCF9AFE876D2C3A341AA4308545370ECC0EE7AF7CC79C776C1008D7F39FE5FDA687656D77E64B5630D0944700D7DF7CACC14C22C4BCD5F9C5E4792D27B1D3F5980FD6C2ADC55813F08A0A6FB640E32D6718653E49F37F93EEB4286C1756817D221A3F8C035EBBEF90F08B0F0C273AE79A34C3A7CF099619CCBB2B5410C3DB7CC8863A0E44202980CDF92FE44F3BE963EBBA72FD6AF3ED3A902B5C3C0C258C3E78F3E7FCE23685A523EB9E5EBAFAB6A963FBB823076A2F4040EB83869C69E10F9423FC92F3C4BE66FAC49A6CB33C8D46B8553C4FE18971CE9EDFD0E7E5058CFA67E52FE5769B72A52E74EF28E896D7087A8786C21461F78CE9F4FFDD47DC3EE797D40AC921E67EF7A2E5CD4EC55D8ABB1568FBE2AD547862AEA8F0C55D51E18ABAA3C3157547862AEA8F0C55D51E18AADC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF30EE7FE3932FFBDDF60FF7998EE4BF25BF357FE537D53FE39BFB5FEF6F5EDD716D0F1497FDDBFF001C5EA7FB9E98B745253FDFDAFF00BC7FDE0FEFBFB9EBDF23264793F4DFFE7143FE3BBA67FC707A2FFBC7FDE74194B18BF42B56FF0094853EC7D8FF0077F5E9FB194CDCA83C8BCEFF0061BFE521FB5FF1E7F63A9E9ED98F272E09DF927FDE49BEDFFBCB27FBDFFDEFFB2FE3953938DF1A59FF00E4EBB4FB1FEF50FF00783FBAEA7EDE464DF27D01FF00395FFF001CEF2EFDAFEF63FF008C1DBAFBE53258F3625F985FF92AB47EBFDCAFFBCDF6BA663C9CDC6F00FF009C69FF0094FA7FEE7ED0FF008EAFCFB65679B9717EA37997FE51BD43FDE3FF00799BFDE4E9F64F4C94F936E93EB7E3179D7FE531BAEBFEF43FF7DFEB9E998E5E9B4FC921BDFF008EDDB74E9FEEEFB1959E4EC23C936D3BFE3A375FEF1FDB1D3E5DB029F8ABEB3FDF27D8FF009E790973627E2AB17FBD717F75FDC8FF007A7EC7D39383AFD47C5FA1DFF389BD2EBFE385D0FF00BC3FDF77EB99F89E675DC8F37D49AFFF007D71FDF743F6FECE6645D066E6C5344FF7A24FEE3AFECFDBEB99117124CCAD3FBE7FB5FECFA60C9C9AC3CD3CF1F69BEDF5FF0075FD398736F8BCA74FFF00A587FBC7DFFE3A19747E9497CB7AEFFCA552FF00BCDF6FFE95B80A43D7A1FF00792DFF00BCFEEC7F7DD722DB1504FB67EDFD1959641565E9DF2A2DE12997ED606D0843F4E2C825571D5BED7D38B6B12BFF00DAFB3FECB14179F6ADF6BFDD78B51611A8F5FF00757D18B192017FBB3F67A603C9804543FDD8C805926D69DF2E8B44F9BD2FC89FF1D6B7FEEBED8FEF7E797C5A25CDFA15E5BFF8E6DA75EA9FDD7D1F865F071F27262BE69FF8EB6A5F6BFDE47EBFC32E71DF97FE4FFF00C995E66FF7BFFDEC93FBBFB7F4FF00938ABEC7BDFF00943F52FF008E77F70DFEF47F7FF47BE2AFCCCD7FFDEDBBFF007A3FBF7FB7F63FD8E1632E4C6A3FB4DF6FE8C0D3245C3FDD5C74EDFDEF5FF638583EDFFF009C50FF008E9C5FDCFDA5FB5D7A8C0E4C1FA41E6DFEFB48FB3FDCF7FB3909399064D63FF1CF8BFBBE9FB3D320DC3E2C67CC5FF1D0B0FB7F647F77FC71671F8A62DFF28CEB5FEF67F74DFEF07F7BF4E167F37E67FE65FF00C746F7FE526E9FEEDFB5903CDBA3F178737D97FF008EDFFCF6EB8127E2952FF7FF00F4B5EBDFAE2D72F8BD3FCA9F6D7FE526E9FF001EFF006708607E2FA3EDBFDE1D1FFE523E8BFDFF004FF65930DD1E5D5F5BF977FDE0D27FDEFF00B2BFDD7DAFA72054A7FE6EFF007960FF007B3A8EBF47DAC816324FB4DFF8E7D97FC733A0FB5FDEF4EF902C1F62796FFE51ED07ECFF00C73AD7ECFD9FEE57A7B674DA7FEEE3EE1F73C7EABFBD9FF58FDE9D65AD0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD9, '1', '2021-03-13 12:45:48', '1', '2021-03-13 12:45:48', b'0', 0); -INSERT INTO `inf_file` VALUES ('6edb3893-8ec8-4bf9-aa64-c04f1c7ad98e', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010305010101000000000000000000000304050206070809010A0BFFC400431000010302030603060406020104020203010203110004052131060712415161137181082291A1B1F01432C1D109152342E1F13352620A172472164325345392E2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004311000102040306040602010303010803010102110003213104415105126171819106A1B1F0071322C1D1E132F114234252081562161833437292A2B2D224258234FFDA000C03010002110311003F00FBF8A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A0AC4C7CF97DFD89ACEE920903F71909243FB3CA2953A948260E5AE5FEFEFD29962312647F261DADAB54FBB46C10A2D60FA966E70826F595BA5941E25A7FE44A4825BE9C63513CA69A276A214A097A9E03D63265A85DBDF46841EC5AD187C5BBCE0696AFCA56A0904F2039FCAA524AC4D018D5BEDC3CFD886932709658834BD0F0E56F3CA1E22E10B820183A1EBF4CB9CD6B326196A29A1B6B623B74F38525AC2D20DB510B05054C4E5D684CC2A6602BAFF71BC7B4A07CD9F841149580633FBF5ACC11E832268823DA20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20840820C73A5029934B8D789F7DA140A64711AF13F87ED142BF29F4FA8A6D88C289E0920391507D9F66D0D558B097A0245BCA9D7FA363108D34DDAE2172E38BE137E13C0A0608F084104E5F43A193CEABD8AC18C3106D7A5E95AE76A59BCA1791395398105EC3ADBD39DB268B6B10C5F0D18A0C3577187A9E42B5B958372743EEF3D2069A4803AB0FFBC8C2AF777C066624B736FEDA9A44C4BD90B9D2BE7192B552C843AB3A97D1C7F717BDB3ADBC96D6D2925053970E900465CEA6F0B8A18B97F31DC9624FBCB4F60464E90642CA14929539704311C0F9FEA1FB7CFD3F5A9295FEDEBF784614A710422BFCC7D3E828821447E51EBF53441155104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104450C4D92F5D301B70BD6DC3C400FCFC63FF00D79E70067D09F4A6EB9E106B400E7C75F6348C33B8F21786AEE2AD254C254D3E90EA5D5AD6A4C2184B492A25E3FDA08120FE99D64ED09094B93500D33A3F0B521AAB05316680B121FBD3D8EC0C72B7DBCFF894EE97D96762F197705DA5C2369F6F9E6D6CDA6016578C5E5DE18F825B3F8AB54AC38CF1485A6332248D0D5476EED793F2D5BAB4835A3874E7EFFF00F422DDB1360CE99392152D6427759C12921BCDBD75AC7CA1ED6FF11EF696DBEDE6E03B7F6FB718AE0F64E634D1B8C0ECB11BB61B72DDEBB69086C5B85907FA440209233D2B8BEDADBCBF9A425550A167CCB3B50F6341D23B76C5D8084491BF2C01B85BE90D6ABBEB6BF4AC7DC57B266DF5CEF13721B0DB518825F17B89618D2DF55C4F88A5A5B6D2A528992789526739EDCBAF783710711B2E5AD4492522A79F1F7E51C6FC6385186DAF3D2121292430019837A46CFA7DD05474807EFE357795FEDEBF78A94548585A428640F5A710426BFCC7D3E828821447E51EBF5344115510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510478639C7AD10422B70699F61F0D47D34F5A208B57157D9B3B945F38EA6D8B48756950570B2E808952AE4999091F97A647ACC06D3C4090824E8FA3D2D7E1A1830A37E72505FEA2DCE9AF5F58F9FBFE279FC5A30ADC058E31BB6DCF5FDA6D46F5F1369CB0BDB5B3713796D84A5E4F85E2145BAC3CCAC5BB8A5C990148988CEB96EDCF150C2EF8DF096041AD9BFE35B1CFBB88EBDE16F09AB1CA4FCC969992BE9282DBCAADDFAB335358F90FC671FDA5DB2DACC7769F6E318BDDA5C5F137957CEDC5F3EBBB603AF953A5A42DC3C50C9596C24C70F0C72AE57B43C6431130A44C24926E4BF06A7E7817AC76FD9FE071225A54248140C426D9E94F3E2F0CF67F1042F1861576C16BC2C4B0F36E1A4F0A045D37A13D3224E7998D6A2D13978D58512540A852F73E5435F661C6230A9C0A199B752ABB0A80457F0D7B47E871FC3C2E9CBCF65BDD95C3AA2B5AB0F70499984A9B09D73FCB15E96F044BF97B265A48AEE8A9CDC9FD7947977C6F33E6ED89AA77049E548DF55FFC47FF00A8FD2AF72BFDBD7EF14C8A58FF00893F7D29C4102FF31F4FA0A208511F947AFD4D10455441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041A510435372388A40CBA99E5AFDFCEB2C7431B896A29DE0CD5A674E9F78592E020120FA7FBADB715C3BC25315F2802ACFD9ED0C9CBC487FC208717EE9515244A13099827404C7DC56E656EA0294E1DFAF271EFAC371880A56EA475D3FA7F53A3C4BB8AB49B755CA92E04A78CF01FCEA4B73C4B039848127A0A693268403C01BE747A7EE91252A42A6B338720727B3DEF46FC47CEE7F186FE29985EE1F652F3747BA1C4DAC4B79BB4E872D1D5DB3C975FC1036471F096161EB75B8CA95196640EE6B967893C4F2113D7841FC88604B642ADF97D6863A6787BE1A6D0C74B4ED10A1F2CEEA9206F6B906D0E5FA3F1FB79B578EED16358A6D56D05DBF7FB538A381FC4F16C61C5BB8A153C494A1A7D5EFF00080A28009FC99682B89788F0D89C7854C94A2CADE2E496725D8B06D341DCC77FF0A6CC97B1CCA4CF4A545346AE547660DCB3B0E1157CEBADB8943CF5C34C13C43F0AA8599CC95F2CC991D672D6B96AF63E3913C952D4C55A9B5333F961C834761978FC0CCC37D284856E8029C297E35CF389AB3C66D117B84E1B609E2BCBABDB4E07AFA080A6EE1B27888CE55FDBD7A9AE89E1DC0ACFCB4AC97053C474ED5766CE398F8A12662672A596A1208003D3FB7AE75A47E875FC353F1AAF643DD5BD7E86D1706C6E38C36084C071213139990273AF50785E42A5E025A5A8406F795ECDC9DE3C83E2C27FEE73526E925CDEF6F4CBAB1BF41B8C2D05398311DAADB2D2433E4F5AB574EF1578ADA494A003DE96820520924E5F63CA8822B488007DEB4411ED104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104332D00B2A264F41A67FE32FB9A0162595D1F4E1EB0AA57BA8AB801DD850D4F7EBCA14CB4F80A5C6A73F21A7BE4E5A23713382CEE876163D7D3BFE60B124DC36DB82DE42AE20054E69232D46920FCE75D50C4CFDC40054ECEC1C503D7FAE1CA16C061FE6A9DA97E4C4971CEBDC0A67CC3FE259EDBFB39EC5FB88C6714BEBFB556DCE2B66FDBECAE1FE2A3F1172E3A54C5CA92D1525D596D2EA55EE194EB19556F1B8D4A50BDE57D441662E406B1A38EBE917DD8FB24E2D7266CB42BE56F0F98141C100B0619E649D4F38F811DB3DE2E2FBE2DBEC477BBB68E5F5D6D0E23777772117854E5BB69714E78296C392B03C352444E59655E7BF124D3336B29408A28B9CD9B2CA9991C4C7AA7C307FC4D8E996DBA4245281FA50E5EE8F67DC630E3D69885E5DB1174EA901808465EE2B8444E7F9634FAE74D14BDE90D9B503BB8EB763566E8F1954F06728D2F5BFE9F2F530861F8C9BC69CFC69875AE1E20AD424E49CBEF43553C6319A684107D8D732EF607AC5870B3C26592AB1029ADC55B5C9BEEF10B6F77737FB71B3563624A9C7F6870461A08CCF0BB88DAB6E4013970A8CC0F955B3C3E80A2839EF0E771DB8F7CA29FE22DA0942561CD942EFADEE1BB3F08FD407D92F6311B15B82DDC60086FC216FB3D873E5311EF5D59DBBEA310352A24F53CEBD29E1D4B602506144E5EC97F2C8671E50F13CEF9DB5710B705D43EEFC3311B3496C01CC7C8F79CBE1FA54FC57615A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821B3AB4A544150062403E5590905CD011E777E30DA62941C55893AD2A1BF5E50D9B7D2B497152809FEE5E49CF2CB49C87AD68A9852145C80900DE9C857B3422941597DDBDC900F9FEF9B461DDF76F3F04DD76C3E2FB658EE256B8761183E1F7777757172EA5A014CB2E38DA10A5909E35A90123AA8819CD56B68E37702885391966391F7CE2E7E1ED9E274EFA9255660D4AE4DD6DC5A3F385FE203EDABB55EDABED378B6338BE2574ADD8ECF623776FB0586B8EAFDF2CF131882AE995294C90B7590A64B5A82273AA06D0DACC6602B2581B9D41AD4F1AC776F0FEC69625A1210024350240BD4F0ADAD6F3D78731F17984B16E2C98B661B9485787C172424812AD358907A6715C7F6A6304DDA0B50373AB82E38687DB978E8F2D230F204A14614E1E61EE1B90E062C2C57690DBBA96D0C85DAA3881E24CAC98911CB23CE3E4269D024CABB535A6B6EB6CDEF586292A54F05A84E560F62C5BF3E916A0C4EEAED38A5DB07C312C809320E796401CBEE2273AE624154FB9626CFDEBE6F67D4889C4EF26428D430A87CEAFFDE71B1BEC8BB0979BC6F68FDD0ECC23C172E6FF001D6AE5697412829B2B862E3300124808300E522AF5E1B96EA41A0A8E6DEF8DAED1CA7C598B32BE692A20310CE6F4635E55E01F48FD46377F689C3B63F666C4A63F0B816156F0065C4CD85BB6AC8F29498AF456C30D8443061BA18767C838F7C4F9DF69ACCCC5CC59B93F97F26CFA45EE1415313975A9B88E8F68820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20886C47F0E9429D5BA50BE24C4A8246640239CD658B3B75E7EEB5F36704952C92029B32C481D7DB72A431C582DF612CDB381B6D0DA9C7DCE284A5284859248D321399023946551F8A5A82083762E03B3694CC8E76D042D2A484946F060E03666B4E6072CFA47C5B7FEA1FF00E2238D31B43B3FECA7BAAC7949FC4A710636E6F70FB950FC280843F68875C657EE789EF27FA91331D6681B6311F4AD5BEDB8F404125EED99E3766D0C749F0EE1C26624A430514F61A7A91CF4A7CB7EEEB0DBA432B6F197495DA3AA7B0DB85A8F1DCA9F70BB7478D43DFCCE64684E7CCD722DAFB40852F749CDC3DA829AE7C63D01B064A44A416B80030D296D5EC7D488C8D7D8C97EE5618052D70A5000D3DD10743A4899D0CCE46A80B9E6662F7AE5C0B335684D1BA718B1CF91BD4614A583D2A75FCF786A2D9BBA1FD4D79CFA4E7DC8D0E43B0CEAC7296AF9391A0D2BC3F6D5A7186987C2EF4C14203DEC0D4F98D3EF148B06ED78D981C374A4C003FE9F231E4395474C4EF4D14BDDB2B135AD0FEEB689B9D86DCC39A1B162C6BE753EBC6E3A93FC19B76771BC2F6F3D8252992EE1BB2CF5CB974A20A90D7E22C8A9AE230401C439F38F4E85E1B961E58FA6AC6B7E7C69F78E03E392A499C9245281AF7AF2CDCE7AC7E8C585B29B6B3B46131C2CB0DB690232086C240CBB0AEFFB1C3615219A9CB38E0B8B24CD24B3B914E0D7B5625DBE7E9FAD4BC358528820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A3C41C6524111FDC7435A15805AFAC11E2DD4A412015C65091268F98343FBF79F9410DD37D6E484A95C0B248285101498EA279F2A3E60D0C10BB8F36D23C45AA11CD59401D4924563E60D0DBCFF001C7CA08F5A79A7D01C656971B54C2D06526323047435B82E1E0852B3045256018CFEFD68823CE31D0FCBF7A208B571E6FC4F01A09754A5AB88140948E15030B1D3A538972BE64B52B78242323405C93D843DC24D4A5D0A6B356ACF50E39DB8D738E7DFF115F6C4D9AF637F67FDB4DE063772E1BBBAC1AE2DF03B2B2527F1CF5D38C396C9534DA882A0D3CB42DCE1CD284CF4AAAED9C64BC382F352E410CE32C9AEDCDB5689FD99B3558C50051541B9142E4EEB3D2DAF611F975EF2F7D5B63BEBDE46D36F3F6C7164E218DED5E3776FDD3AEBEB75C66D5178EA6C9BB752C952562DD4843892609C84015CA36EED295B8A295EF1ABB106D50E34CFBF38E95B2B644CC3142D6592902CF60CCFC18FF548CF1B05BB1DF0EDE26CC6C96C06D46D0D9A1294E197383E18FDD372EC078DC2DB0470C9CA0F2CCF4E1FB73C45829626A9588952D52DDC4C50750D031B9B679657E8381DB72B01BA161F75B7788AE763CFB0CA376B63BF8757B536D1DBDB963763B4ACADE1C454FE11789038BDE1242758C8E473CC93A57259BF123032316A48FA994438DD3D4135ABD357789C3E2BC2CD48514EEF16003B379B77D62736B7F8737B57EC6DA1BCB9DD86D2DEA1292A09B2C1EF1C591130014807FD55B303F11F67CF425090D40EE0573A375BD4BF087DB376F613133025050A0F5620B372377E753A18D3DDB3D91DABD8BC66C702DB3C0712D93C5ACD6E26F2D71CB65D93C82B82D8521C1C43887E59D4C413CED9B3F6B49DA0B4992B1BCA228E0BF519B699C5BA662A54DC2AB75988EA0B3963DEFCCDCC7D13FF00E9CDDDBDD5EEFA37D5B697765E1B7828D9DFC05FBE8E1688B861C4385A77A119647D729AEC7E1C401F2E8080CC59CF337A172D5AC79DFC7C903E6BBA9DC84A43A8B3D407AB67A0ABC7DB058A38D86D695A5423549904C09835DCF6497C3279379C701C511F394002189BD0D4E6D1209494CCC671FAD4AC368AA8820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A4AC0319FDFAD10479C63A1F97EF4410718E87E5FBD1041C63A1F97EF44115032268823DA20828820A20828820A20828820A20828820A20860F2149716EBAFF000319402A80206797CE9057F23CFDF7BC11666D2EDADBE06C1164D1BD7D2098653E249F4CF4CBEF2C41166E05BCBB7BCBA51C630B7EC9CB8570A1C71A0DA441E104151CA4C41EC2688232C5BC9654B5A85CDA3E029224AA124663A089F97C48224ECDB61A6108B7484340A884A4400493390CB5A591FC4756EF0439ADA08457F98FA7D051045344116D62CFDD61C9BABDF716D0485A52A24F021225D24682132673F4A8ADAFB59381C217207D24BE74239E55F3D61EE130FBF346B4E01F2AF0C88EA23E367F8C3EEF77F5FC42FDA8706DC2EEA2EEF2DB775B1572A6315BAB75DCA6C6E5388B4D3AE788B6789A5F84B43807101C24419AF2EF8CFE24CBC0CE9FBD3095249F96970519BEF54D9B22CF7B18E9BB025FC94277F777BFDEAFF713715CD99983F988D9AF63EFE047ECE7B90C1B0FBFDE660ADEF076990CB2F5E5A6256F6D8A61697D438C8436F36160024F1839C8AE05B57E2999C66113882778108564697269525F3F38BD7F9094C94EEAD237B2984351ACE5BB3D63B05B19ECE9B98DDC61CD33B2DBBBD93D9BB665294B16B85E176F68F909802108004981A6624F3135C43C4BE3138A54C57CC7DE2436F56A4F17A5CEBCE23B153C4C56E041537FF1121D2332C6C34F4148CB78761B6966E8559D93F6481012C7861B291119240301433F2D35AA12F18668F9EA2CF5AF0D78039641B3A4252E6808604115078F0A173C34D5A24317167736E59BE65C711C2414AC05020F9E5E5CF2E734BE0FC512B09352952EC46741AD29AF730EF67CE5CB9A3E42D285121EE120D09B7534C985E38F7FC473D89374BBF1DD4EDA6D3B3B38D61BB6384D91BB671CB7B4659B8B95B2953A0AAE024AD45296C2046931AD778F03F8BE4CF99282144311BCE456A2DABD6B9DF9741C16D4C42657C9C42E5B28109DD35B5779ED95ABF7B3FF00F4F9EEA319D90DD0EDC63D8922E16EED0DF8B5B75BE1456EA307BFB8B702559ABDC4011F488AF68782270C6C894A0E4A8249734B86BBFEBCE39478DF1BBF3378A80037C12E1C3D1F5173D6B58FA6FC25C53962CA94C9B739A7C2524A48E131307918915DFF00662372424337D3F88E233CBCD59077812483CEBC35FB448D4942505104144105104144105104144105104144105104144105104144105104144105104144105104144108AFF31F4FA0A208A68820A20828821647E51EBF53441155104144105104144105104144105104144109ADD4B7A83F7FEC51045958D5E3172EBD69E25CA1600109308CFA798FB148ABF91F77AC109605B396885975E6C5C2559C3E0288E7CF2E9DFA56B043EC6B6770BBCB77FC4B0687829E2654CB490E056B918EA069C851046161B6DB43B3B72E30AC3EE6EF0F61442129694B5F082604640E9CBFD10465CD8DDB6B2DA6C383E8B67AC9F6F272D1E4043A0CF240CF3D7BF6AD3E60058127562D5CBBEBEB045EA8B84ADA0E942900980958856B12474E7E559F9BC55EFAC11EA882B81993F2C86BD3E7419841673C6BD7FBB41082EE1A6D6B438A08298CD4400644E46B066D0D5563EEF19170FAC6B27B4DEF217BBFDDE6337B68BF1B14BE43769855B33EF3CE1BA5FE1DD52500F11084B9C448D0024E715C8FC7BB653230D3D1F308514AB76BFC6878E7DB57AC59F64618CD505252C10DF31EE4AACC1ABAD79651AAFB8ADD4586CBECB8C7EE6DED95B7D8FAD7758962A1224B6EBAA759487A3C42B6D973848568A112057CEFF89BB7277CE9FBB354594AA856A5D99F8E94B333C5FF00012CA081421830565A1F4A371E7B09636C6C4ADB45D5CBE98042DE5F12CAB55051FF00A857E5E511E47CF3376B6297356D316CFAB539D5B36F3AC4F7D6A4212B4CB3BAE086A0193529D33AC797AAC42ED4DA0A2CF810A9F1784F8E04823DECF3FBD29862264F9A1D44DEAD7BE7C6FE56B0D44909720A9943F893F4B8B3701A449B988ADBF75B425C504A4788E895929039F6323F5A55789F978420ACB806A491E76A0E19650C66CA284155537648A015CBC9F9B690DBF1A5FF0076EADD95248E4993DB5E9DC4F5E75CD7696D5988C428254582C3E6CE79B71FCC35953D52D745117A83DFEFEEF8A37C96F60FEEFB1F6EE2D9B364E5B969D4292381497429052444199C875AED1F0C36B4F9B8BC3A43B1525EFADF4EE474CAC92316A423E62D64A88A026D4AF916D3A45C3EC57B23826C66E3367ED365F09B5C3106EB1277FA4C21A5A94F5FB8E294BE0E64A8C1EE3AD7D51F84A93370787047D44249241E3566E57E4358E61E2A9E664C9CA2B5105BE924103CF37A664C6F95AF1F80DF88657C2388832248072F8D7A525A021200D07908E7A15BCFC0FBE5CA1C5291B414410510414410510414410510414410510414410510414410510414410510414410510414410510422BFCC7D3E944114FBBFF0064FCFF006A208A8249008220FDF4A208F780F51F3FDA88214488007DEB4411ED1041441051041441051041441051047848027E5D688222DF773E7EA72E5AE7F64FC48220578797AE4BFC392C8CCEA741E7AD22AFE4608B86C5AF0841CBAFC3B9ED5AC10929775F89B801014C80380998329CE3B7DE74410CADAD6C9DF1BF1366CA8CC9E3427424E79F59E9441186DD79EC1F780EB966DF87875C2D03C240842211072190939F39FAB259AB07073228FEFF0030466C2E2AE5F6024FF4D29E254130AE2483D391F856AE753DCC10A5C5C1B40FBEA9E11C013AF3CBEFEE300AB3513C6D04446216CEDFAEDDC4ACB49852DD5494C2520193D3219498AC2D442165CD12A373A18C8B86BB86E71CE5DE862973BC6DFEFF00212E7E236536023F1E12A2AB77DCBFB70A678A4F028A1D1CF307A9915E2DF8C1E334ECEDA33F0666B315021F813DC7987E71D4FC39840BC1A5652904E6CD6377A0F74BC66FB36DBB4C2587D88E06F8901034080AE14E404649033E990EDE20F16EDC4ED09B30EF05051373435B8C87DEF16642129510033588018937ADE95EDC22590A0E202D26028498D67CFF00DD51654B0BFA88CCDC31CFAD72D1ABA43C4AC001EA78DBAF0D0BFDD839289199E83D358E5D3AF5A6D8C9D2E425449A797E32CB9D32541053BB40C439D1CE5C7335147610D56E24B9075E632EFF007DF99CCD57B158EDF96B093420D34D2D5F778D9787DE946809AD49176F74E59BC535503825E2A7B004EF2AE7526A0B7E7ED158992CA66804B549616EADEF84620F68571D4EE9F1566D64DD5CDDE1AD3694FE6295DEB685E999C952794666BD1FF0AB602D38AC3929FF00720B805AE3D7EE7A494B5A84BC8848BF3D03E9D78D236AF725B3AD6CE6C060384840496ED10EA931C2429E4A5D5748F789CFE35F55BE1360BE460E43803E8431B56DC78646B58E6FE235154D9ADFC722F4F747AF2CA33D5BBA3C24F1647A65CB21CFA0AEF4A67A5987A7BE778A6243121C1E5D6FFDD216F151D7E63F7AD6378AC104023434411ED104144105104144105104144105104144105104144105104144105104505694983AFA7EF4411E78A8EBF31FBD1041E2A3AFCC7EF441078A8EBF31FBD1045054D289F7E09E522474D3CA882105DBA97F957944E4743CBEF9E74410E59429B6D295192264D1042B44105104144105104144105104144105104144109389242BDE0001CCE9FB4D1045B57B74865478B88C4CC73FF1209F5D288225B0E75B7ED1B7384E723319E47BFC7D6932824921BDFEE32013610B2D694C8022798EC7B47C72ED4990C723CA164CA0AAD85BAB642FDCF78667124A16EB5C6DFF004C0993EF264492AEDDB23DE88DFE466DD03EB9790C83968B3711DACB1C39C2D2EEED9F79F3C286587029D0498F7933AC91F5A23030E4BBB86E5EDF87E229C130379EC42EB13C490DA997FC35DA367FE46C47BC5615A7148E1035ED35ACDC12B70AF79AD406A59DDFECDC21BCC1F2D401B17E3EF236B18BEC2036DF0B412956504F200E9941D341A77E906711FEB7C904EFBB1739F063EB0A84A481561A8F67B656A44462D78D7862DDC9487149F7E3DD94107CF5C865AE50273B1E1B63CD9F2FE605BB07202AB5C855B8D78F08748C0AE60DE410DA532D6F56EFA462FDEFEF230DDDFEC5E278D5E5C22D12AB376DED7C4586C97DE41619E19227FAAA4E633CFCAA8FE2ADB523C3B266AA7AFF008CB5B82A1FF13C5A8C73CB38525ECE5CC514A6AA494BEE976E63D75EEFA05B91B0C75DD9DBCC5B1C478DB41B497770FE2D7484AD41DB745CB8BC3F816A1C4A86149078B2E432815F24FE39F8E93B43C518932261DDDF50001D2F47A5ADEC760F0F608CBC000A71F4FF00B8D0737A57FB8D87B5BFF0D3FCB1E65E408010B526100E5993CB3CE73E95E795ED799356E54482753AB96E678826260E11EA92E03B101FB51DCE629F68B92D0165A4B4B3C4A124A939A7324C4E50454B48DAA809DD20BB5E8C7F5EB09893AB5CDC90694AB7AFE21DA4CE71A9CBBE83EB95426D19D3315BC104806C051EF42C076D7ABE486247BF6D10B70EA19B8216415023DD1911F1D7FCF6A811F3503E52F7897E94AB74A7BBBF96B4AA5697BDEEF5E9D876878D02E20B8AFE93600256E7BA8CFBFA67DF49AB16C7C3854E4AA60012487F2B3D9ED71C6ED1058993BD314A4B3E82FA656E1D58C618DE4E3981DCE2182ECE5C62568E8BBBA415B61E49092CBA858E313919194E875CB4F587C3618695370E5D0900A6EC0BFDEF566A5A12FE32D60A4BEE9A0772CEC35A8B746168DD2D9CC5ACAD3F0564CBCD5D7896D6E96FF0EA0B0809653F9A208D07F800CFD0AF00ED5C14991210264BFE2960142EC2FD0DB5E158A26D2C24CC4C954E52552824A89F9819C12599E873CED1909CC52DDB70B706404E4223300F977F9D77594B913E58989C44A0E0382A0EEC38FE69DA2AD2F662948DE4A98126A74761D34E70A22FDA5E8950F3F5FDAB55AE52003F3659A904850CBDE709CCC1290F576CEDD6D6E6444A34F23813C326674923BCEB07C865A5335E325A4B0208D41E5D3386AA96A45F26E07D8CCC0AB9099046604F0C67E5AD23331E94644962C067FF00DB6F65A1B99890ADD37E7EF5B3C788BB4A92094A927A1107EFCF3ED5A2768EF16DD20D1DC0CF8D7D2174A0AC021AB50FFD7AC565FF00FA89F3CBE84D4A4A0A58DE2CC6DEC0F7D9F3F2D4ED4ADAB4E5CFFABC79E39FFA8F89A5770EA3CFF119F92BE1DE2B4BB2341E99451B8751E7F88D770F0F7D2140A07B1FBD3AD6A43163946A43163945548AD6524D0306E756E3188A0AC0EA7CBFDD227120121879FEE0838C743F2FDEB231209018579C1092AE1093041FBFF34F512D6B48506AF4848CC67666E37F231EFE21249804C7435932D42EC1F9FE23433C26EDCF2FFF002848DE278CA122549891CC489F877A426A8CB2D4347A024D9CE7FBBD28635389A80002F9BFE3D87EB09AF1065B5842D412546005644F909FD67E94C958F4255BAA0D56AD3ADF8C60E2802C401DFB33C7AE2D2525D198ED9CE5AEA7FC548C9DD9A84ADE8A7A8346F7C6F02A7ADDC27E9362DDF87115ADA1AFE2D80095389491FDA489F818A658BC6C9C3024AD34A9721DBDF0D03830E657CC9A5820BD1A9ADBFBB738B4368F78BB23B24C2EEB68F19B1C1ED500A8DCDFDC22DD8000CC95ACE83E755D9FE2BC2C956EA88E7A51DCFBCE26B0DB1717894BA10A3C0073D83FAE91A6BBD8FE257ECB5BA7656E621BC1C171E75BE20BB3C0713B3B9B90A4EA0A14AD7B76A64BF1C60104825D9EA18DBF7C62CF80F87DB631D284C4A02378D1330282868E32D7567D239FBB45FC797D98ED31FBD6AD30ADB7B9B7B72800DBB366B4AF2FED21C00F383A66075A8099F14B672715FE36ED49005BAE74EB6E313137E16ED3C3E1FE74E22953BBBCDAE9D39C7537D943DAB3653DA8F77184EF2F636C318B3C1B17F185B5BE2CDB68BB3E03A5959525B5149F7812209C88E8455EB656DC95B51095CAA6F65C3D7AE6C639FED4D953366A9495D4A0B1777ED973D637090EF124129209131D3E3156058280F43C8F2E1C620D13378B311A93D721CA2AE31D0FCBF7A13F53366FE4FF0088557F43BE515020891410D431AA54141C47B446D051041441051041441051041441142E214329313D4FEBA510441DD61FE31396B3A67F5FBE7144116EDC58E2ED38A45BBFE1B00FBA9E25089CCCC69D75FA524B51721E9EEFEF9DA1E61D28287500E4E6389F7588F5D9ED01822E675CF8D47D7335A43A094E4057AFAFB31430E5C38DDED93E034FA1290BBB57BA973881885E731FBF9D101166715CBFA3D85333990D706D8FC2BDDBEB809BABB0A2A4B8785680AE23A1226040D3A40E704614486622D576F6E7215B68F1925A49084050485240108D0002123E1197A695AE331625C929CCD88E4D41C751DA18CD413535009B8F3F261AF011497614467AFA76EBEB1FE6AA5225AE662F780533DCD337FA587BB57368AC48954CC137F74A9A30A5E18E236D6D76DF84B212E6AD9D0A888309D27400E7CE3A55F25E32660A56F95B0082F91A248CFC9F4E912180C7294A00541B8CDB3CCB665EA0718E597B6FBB8CEF0369B61B73F845CB96CFE2578B7AE54CAD4996EC1D6AEA1C89905082065067400D78CFE37F8C4A7FC994164B058A13620F117BBD0718E9BB0F65CA9F2862124013189529A841D73FBD3AE68C1997B05B7B2B266D90CDADAD95A5B97B87852A71A61B69C515692541473CABE5CF8C14ADA3B5E762007056A2146B43E77A791D22FF00224A30F2848241DD01F7454BD6A1D988E2ED17336DA5E22E3C443EB4E7C2D90A333066333D32CE67CAAB08D9EA2E40A92CCDCAD46EFC808C198949284A4A121C1DEE232F4EBAC4DDBCBCDA5650A6C1905247BC08CB31F4CCCF5A7A8C1AA8198B54E8F95B8356D0D17300A3D4E6FF007FEB38916DAFFAC18D32FD33F5FF0074E656CF35A10491522CFE8D5E5943698BDEFF00711A9B69FD311C231A6F0F0ADA2C5ECD769B397D84D95E70C071E756DDD024E454532476CF41CB28901B004C4098CE74B922D50DEEA79624CC095AC12B3BCC5CD5218656E02B7C8EB801BDC96F571869C631BDBCC5ED5974903F95624F200049309E21D08E5CA9038656115BCCDBACC2D6ADBCBED1BAD6925560750CF4008E397DE2DC77D8FF000A7AF6CEEEEF6EB789738C30B5AFC7388A576FC64CA4A5447140F9721573D81E2B56CD5A1456A1BA430701BCF26A1E1A1AC7CC595294459C5412E4B74D2FECE44C1F731BCDD97BD373856DF628B602006138B624F129012520980069198CF5EF5DCB60FC619D8308099EB1BBA28F0E34F40618CF4A672548504AD2F621C3F1D4E5700DE2FDC3B6977D9B1CD2157ED5BED132C294A5DD3097EE94F02660AC91309CBB1CB4ABCC8FFA81DA4852509C5CD01C0AACB3578E435111337092C277004A5811BA96043BD59BF558C93B37ED2EC17136DB4BB3D88583A212A58B50D3614041CD674CE672EF5D0B617C73C562952D33F124A54D5DE27CCAABA1CF38839FB28B1DC52C924B6F3B6B4D2FAE7D6335601BD0D8DC7941FB6C79AB37DC88B4B9B94204CE49080499EBD08EE4D773F0F7C42C163928F99392EA6FE4A0D5B9A97B674BE510D88C0CD4072016D3F96879F6ABF01191BC67EF5B4B8976DD76CE094BF6EA2551CD5C432939673E75D7765EDAD91884A54B992882D5DE490F9558F971A8688C560D2545D2CACF7A84B016CE8C5BD6CF5B6E069210DBA5D4670E2D4173D4714C64646556F9123093A5A66A11294156290922F46A3380CED9C2C896508B330ADC96FC5AD9C48B6E92331946503AFAC79D23895A70E92D714DD1DA83DDE82125ACB543317E3C21D0526341E801FAD468DA254A6097E3EC7BEF0D97308B5341FD7E5BEF5A4A4E994F2FF1A7C3D69F4A9E99A2B43D9E9E46F639776EA9CB0ECAAD3A67D7CEF0BA220693F3D4D616A4A5443B935157E37FECEB0A4B51525D5724FDA2BA44A4ADFF00AE83DF38DE102412634FDB2AD7FC71C3CBFF00D608F2B230E9F607EA086EE708566067CC810329FBEF4BFCEF94022CD4B1AB572311B389DF60F6C8FD87BBC15A1C600F9B5873BD1F58525CBF983EA4D746A5CEA0E82185F3B656ADA5E7DC5214A39F86614A8319CC4C1C8672396B934993D0B503BC1D4ED5CBA16032275A43D95B3D730EE84D732065760CF907A88B3B6AB6DF65765B0F5631B478BE1985E18D214A55C620FA185A40199E224267BEBEA29B4C9725492A2536A03F661EEB4687B2B62CC98BDD32D4496FA98EEE84BF06FEE3955BFDFE30BECABB8BBCC5B0D6B68713DB3C5EC12529B2D9BBAB3BF4F8A50A29496F8C2A01D408CB903542DB3E3093B2E62B0C998A0A4B8A1A6BA81AFA3DA3A36C5F00E37192913552A57C823EA0C77EA28D6F4E85A388DBECFE3CBBECDBBBEBAB7DD3ECF613B3D8195AD2D398EDB3F6D8B96E4F0AB89973878C8CE4643280245738DA9E3D54C27FD4357ABE5C6B9D2F46D6B16AC3FC3D129BFD206B761992DCACDDDDDA39D3B6FED7FED39BF5C5311B8DA3DE66276F86DD70F16096D8B5DA18680490B4B76EB51090A1DF3CA6A8B8CF15AE62C8DF24AAF527EFE4CDCDA2EDB23C1C990A4112D346B8C9EE28FE51AE78DE39676ADDDA71AFC6DFE22B0A3F88BA8778972493C4A20E67BF3CA342C7FEFAB50BDE97AD69E9E51D4B65EC544B4005291BA34A59CF6EFC811185B0E606278AF05B3AB37B8B62D85DA35689325297EF1A60C379900A57396A290C0C85E2F69267392EA15A117EFADC6B5884F154E461A42E582032482006B7E473CB468FD14FF8766E72DF72BECB3BB4C19C6CA2EEDB0D174F248851388F8770272CC8F167EF2F5578370DB9869273600EB517E793B5695BC7913C598BF9B8BC44B3FED53825994F577E047D9AE23A1A93C494ABA807E226AFF882529000A65C6CFE6DECC52B0F55BDCB9278302DE7CFD60041CC5664972068FE6F0E27D52DA8EB710B2343E7FA0AD95FC8F3F4A42328302346FBC57588560A20828820A20828820A2082882122851513208310348A208560741969DA8821A3D6C1C515152B38C81D0F68A457FC8FBFBE9CB942B2E66ED353E5EDF586CAB04ABFB9D1EA63F4CFBD6B0B7CEA30207FFEA9F6880C6F6751895A1B66DE76DD6A20975A5702D4279A867A081D46BD0119130D492492D9E598EDCF8C2D85E088C330F45936FBCE2923375C502B3273CF4D39FA5119F99CDBEF639B5BEF12008B5050AF154948F796BCC99EA7A74E7F5A467618CF0031700B3FE3DF2816A0A41248B331390B505B87DEB152805A4B8D9E21049CE4E43B4F4FBD4AB84C0224A82D4056B517A93C3AF663157C6EF952B75EFA114390A7363722ED68B7AFEE12DADBBEB8712D34C3370E34851E152FC36D456540C03F964768CC542F8A368CAC360E67D607D2A6FA99AE3CECF9D4D6253634A9C54860E094B8625DCB1CB4C9BCAFC45DB7F691D911ED23B53798B0BA7F15C11E6ADF675868A14AE37982D5C00951E3954641199244D7CE8F8C38D9D8A9F88521649758BD0D59A8C19B2B47A5BC298290AC1CB92B037581340E480F9687BE5568CBB84E39BDDDBE71972C1BB6C1B01BA585316F8925E63134B6A5492EA40291C5AA0E85275E55E47C46CE54D9A4A85779553EEAF52D121B5548978829960519D839A00D5152D4BF03C636D763765EFB02C350BC42E7F1576A4F12E1456DF144C0E283049F5035AC4BD937FA43BB00C41E449B0CBCEEF15F9B8A2A59417E2A0EDA70635ED98117AB16AFDC3697941A41512385220009240D27BCF7A7C8D904B7D15F27F2D7422838C3533C2014825441B90E7BBB43D459B89E69D3BCFDFCB4D29C276492A622DC1802296B1E6FCDE105621F3B59957E6FF88A6E703B2B8683A96909BC2656EC09510444919E42227A6B06A625E125CA921012A2B63BD620F07F7D2F088C5CC44C505281416DDB922D723956A5853587B6B87B4D33C0F296A580608323CB965AC79F28A86C5ECD4CEDE0DF5170187BFED9A8F189B899A4FD0CC4DCDDB872D3CE133873438D456E05E5C1044089D3991D79C54327C3938A8B254483F4BDABC72A5A03314A29DD2376CAD6DCB3E6C6D94242DDF7521170195849212482441EB3D80F86752786F0E63A852086B81A5FD321F78DBE9DD26CAE19F3A738F51645B5296979CE1207FF001B8A2D8408C91DF9FC69E0D97324ABFD451749FE24E79F115AB7A65A6EA492E91FFCC456B98BDBADE2DCC67671389A148FE578392ACBC47191C7E64C6BDC472EE2A57098F5E09492950013A65DAB95C1343586EAC3862417E7DA8C29EF40D8C712DCEE1D8CAD6CAEFD5835E364290E614E861614731275FDEAD381F8838BC090113961233DE37EED969DEB0CE6E0D2B2494D6AECDE85F864F9E822350FEF4F7560376589BB8FE12DCC26F9E7AE6E3806790100E444E9A4559F0DF1AF6AC8094A71539280400CB56B5CC0E43BC319BB39054E101CEA32BE84B7F6D431943607DA57673137D9C07692CAF301C552AE05DCDF368B6B0796A248F016A32ACC00ACBF3111DFD31E02FF00A81F9B80932313892576FAD7516E24F13DEAF1058BC1A82D4121806B51DF2F57A74A46D2DA6236D72C22E18790EB0B48521E4AB89B5057BC08568723967CF4CEBD0FB07C6B276F041F9A0EFB31DE70FA82E5F87488C9B2181A392E0822BCDAFCC5697687CBC4ADEDDA6D450B794A2470B602940CEA474CB289D0E95D43038144E4158DD60017C8BE64B1D73636BDE21E6A56926967C891CBD3BD9E1F255C680E04A803FDA47BC34D47DFC6955484CA528A4BB1CAC4559BBDA90C26129C8F4BBBD843A654481FF975D79C5472D6EB22AE0DC9B30CBB7087D20BCB079FDA14592001D67EFF004A7A9237732D702F5261588EB8BC0C29280CBAE951CFC34C84CF33F7D69CA64EF237F7D22B626A5DEDC9ABFAAE5AD6AF71CE2BB8B945BB5E32C1298931A8F3F2CE7A4674829494920A998B7AFE3DD1F1112DE356F72B73C169D5A1A897801C19CFF74F633D0014B8952E6A77C9497147A9A3BF2F4F386C70AA98A4B7FB89B7DF367E50C76876B304D9AC02F369318C42DAC308B0656F5D5E5C3A96D96508924ADC3EEA6025524FC63484C7997252A5EF064BB817BD1AAC28EE747B9896C1E109989941277CEB6D79E8DA18E0A7B647F1CEF672DCD59639836EF71DC376DF6B6C92F31F87B4B9B5C46D9BB8014801286DC0B052A1EF4E7293A72A26D3DBF2F0FBDBA40A666CC2E3D0E61FBDE3666C45AD43E67D24336E50915BE7406C3A068F93CF690FE27DED2DED3D8CE22FBDB71896CA6CB3AEB9E1E0985E217564A530A51848B7E2289E18303204F3CEA958CF1B1438334B00400154CF5E83BC5E70BB092129FA0BB8A33E62BC41D7D19E352F655AC731FC4978B5C620ABB2FAB897738B3CA73117540FBE5F5E739E692732233E75CAF6FED39FB4710A9A851AB9727D2B5E14A748EDFE1CC148938044B28E7415E56B1E3EB4CDE19526DA54DD895369F79C00F1E594827B0FBE74E9F2F12A7FA946A6AEFEC657CF8C4E2A4E140277464C186B5CFDD1A14C3F6999B26CA584DB32FE61C7D43856E6A004A844C4C08EDD2929180C44D58241041CDF3CE95EC38E51A7CF91203A4806BCCB52C33AE6D912F18537938DCADEC41CBCC482585202DA65CCD7C6A480509332003249D055830BB1672EAAE14A6BD73CB8D5E31FF7C932412E2C74A30CEB95697A56CD1D0DFE14FECC175ED3FBFCC3EE2DEDAE2F3677642F70FBCC5D7768E34BC55C0FB019500524A16DFBFC530418ED7CF0F6C55267CB74BD45817A5DB8654D699C722F1A6DE42BE6913004905892181A80E6CD501AEF5CA3F431D9BB0B7C1306C2B08B56C2AC6DAC2CAD136CD2415B26D5869A1EE400904A24EA20798AF49F8730624C8410186EB579598F1F5B078F2FEDCC519939656A054544BA5D98BEEB74A3BDB52232234A3E1254A82607E5F8019F3EB53D8B6000E7EA3F0623F0409054482C00A5AAEDE5F8E752223D73AD30EFBC092F42DFDFB6873882C87F7710E11A1F3FD052CAFE479FAD611945C13AB7DE2BAC42B0510414410510414410510414410510414410520A0CA3EF8FDE082B10422AFCC7EF9511973A9EF14D106F1D4F7860DF8CAB8BA4BE10AB684F8204951CA4F148826748F2E735A9C5A650751B02CEE7EF4E7A16778C09BBC580AE84063EEC6A6F9443629B4786601875DDF62453656B6E852CADD86D30013CFDDE5CCF6D74AE6D7F1548C14A51DE09DD06AFA5433177763D69430FB0FB3158B50F9680ADE672059B57CCD581E2F1CDFDE56FCB787BC1C6F12D9DDCD5ADB5CD98E3B5BDC5313438BB669B7125B51C35E6090161255C53202C0D6BCD7E36F89328A66CB137250A9B5C3DF507A3F38B860362FF008DB8A5218674B659B50DC509AE9168EEABD92F6236318BDDB2DA2B21B57B758E3CDBF7CFED0A1ABDFC1BC1D24FF2F2A4F88D8014A8933091E9E5CF106D795B5A6AD5BDBEE54595506E0E64D281B325A2ED85DA3FE1CB32FE61960060A0A62E1A879E7964CF1B9B63B1D86E1B6ACB8C3447B89290E2471A724FBA3A246881D001CEB9D62B664B52F7D018073614CAA3EEF4E108AB6B4DC54D50984153B1527302C78DB8005DC9891B64F128B440E10787CA63491A7AD272F67241FE2031B8041200E55E34EC0C6AB98A0EA2C5DCDC9E1C3BF9522585B86FDC48303CB9E7AE9F3A792F673D5A8C031D682DD1BF30C264E5283871AB0A9B0B547BEE785D95F0FF0014ED1B2C33EEB16CC1AF260DD4F7D10F9A599D479B7A8CA3D09E1CB3F5D6994EC0284C6018756BFBB423F3EBE66833D6BEF8C7B4A48D9C1C2D6064F47BD6AFAE5C7BC3844DDE00062D71E9D385E8D14139E5F993981C8CC4FCBECD4EC8D9F86491BC9191B015E7D87EACE12A041191BEB476EFCA1322091D3F6A974C9C24B05928A248A00F6CBEF0B82E1EC4E9CCC56940201CF3CBD7A695CBFC452A69C72CE1DFE5BB0DD2D95CF3F57845530A0EED2F753D7367D6A2CF9F5ABC2ECAF87F8A869783C44C0CA4AAA2D56E1771F9B88D7E6162412599EA73D397210C8E0F6C1F55F2DD5071504A240D073CA7A7E9DDEA36229406FA40725BE9E37CB3BB346BF31CB6EA8F162C6D639F56D213B976D5D4969DB64BE902389490A1D33F3D3F4CA96FFD3A08344922D720F4AD9C3F93C6C4004A98BF07E568B2368762764F69EC97677383376D7290A2DE24DB084396EB2642D0F1CD241CE6397A544213B4B66E387C952D3292A0480481A5851E95D7267845782DF3BE405050240CCE7A54B861E4D5318B707B4DE4EEAEF14EE0B8CBDB5FB3A544B96F7AFBB7CE5AB4924F0A12004208048E7A67CABD2BF0F7E224ED9864A67E216D2F75C1516AF33F8FC4362B6703FC5212EE2A08347B7EFD2367776BBE2D99DB05A70D52D16F8C3502E2D5CE04A90E1904044950CC73123E75ED1F097C58C163254A926783BC00502A1C19EAD6627D728ADE3302B1FC523743B8CEB9E56CE8391158CEC16A2DAA0057BA4A38648D32E5F0D632CABB16076A4ADA32C2A52810A17497EB47CFF262066E1EA686DA6432D0713C4F111E58ADCF0506E3DD72552279126358E47965D28988DD9B7725C9D052312D3BA902DC0C3C52D2A882329D48EDDE9FCB4921C0BFB17FB7DE3788F7D01FE34F8A5942735ADB3C2B3D33CF29D7D7AE44E9A99128953BB6593E5EEEEF187AFA9C873310B718B58D95A3A1E778AD5A0A2EDD5C94964093C456BD00027B0EF3548DA9B6C4B593BE46ED6FD43D6B5D736BB53748ABDF22E282A19B9F7BE4CDC7DF6F5FE2F5ECE3EC4D86E202E2FAEB6C36B196969B6D9ED9272D2FCA6E4A6129BEB6E30B0952C8200CE388C659D77FF5FE1E4A861953909995AA94C2E5DFCEE6D5368B56CED96AC44B44C4A014577C815625830B39B13C0B111F15FEDC3FC6A3DA8BDAF710BDC3F0AC7F1DDD06C3DE3AEB565846097379818BDB75A8A529C4184AD4DB9C42240CB356550FB43C609C4AD72E4CC1398FD664AB791517D0EA7AE6C22D5B3F634A97BBF4925FF92C7D4FABF0A7ADA395F84E078DDE622EE33893ABC531ABA597AF2EC294F5ABE552A0E070C2D4B20F12C9D5649E66A83B4F689C5297F2D4ADD36DEFE56620E82EDCFA8BF6CDD9E12120A4134AD08EA7FAD38C648C31FB5FC4A18BF47E19F1C291E100949E44C9CF21F03C8553B1180C5CF5B82ADD7767367D2FEA783C5BB0F864A775EC187D5567B90E07F4C4466CD96B816F72B6997896C04F01E29CF84731D3C8FD625709B2CA640F989753177048F57B171CF361163C2E21725210927746552D7FEE9F78C86E5F3C2D5E01D3F96667E1AC1EFA7956B330528120A6A08CA9D72E17ABD61EAB10B2C9049CCD781E6F4BDDCE6498C4B88E32BB40E3B7971E1B685136E4AA38D45449199CFDECB2F8D2B230B2CCC0C81CC0A3D05B3BD39C44E3A74C092A06CEC3837524FEA31DE39B4F717EB16CB42DFBABC7ED6CEC6D900A94FB974EA18494A355105C4E911CB4AB56170B2804B804532041AFDF2EFC22998EC64E439DE51BBD4B0FEAF957B1FBF2FE04FEC896DB81F662C136DB1FC33836D36C6D85D622A5B205D34D78CA72D64A93E20059746BC87202AFFB0B67A4AD13129B33306BD1B3399A76BC71DF166D19931464A95F4AB789075150D503DF48EEFD95BDBB3C4A67371E990A8CB52223489CF90E935D87038712B0E80C599C96BB0CDA81B839EB1C7F1B89F9B3D8549D7514AFB01CDA25D8694D3010A571112A999D4F144F3A6D8E98CB1734A0FBD876BB44A6046ECB2090E58D0713FAF6F0A224054093965EA6B6C2972391F407EF0A62BF80E7F88748D0F9FE829C29DCB97E36CA1293FC7B7A98AEB585A0A20828820A20828820A20828820A208283404E90426A58989223A18EDA73CF2D4532F9DF327096902B4734F7CCFEA36092438F7EEDFA8A38D3A052893DFA7953B54ADD04BDBDE43DE51A2F7902A070ABF93088C77114A2E0B1E138B331C604A64C6A67BC9903F5AAE62B6D4AC24C3294952C82CFCDDB3CF2BF384C6F28D378F04F36F7ECC2AE5DB698E24AF212A29CF834FCC7ECF6A98D9D306D097BE92CE1C0A7637F6F0BA70EB51DDDE21C3B17B67A03FDDE2DEC5B1FB3C3ADAE31572ED962C2C5B5B972FBEB096CA5292612AD388C10419CFA662A9DE2CC6AF65AD692ADD090A2429B9D5FCBABB185E56CC9BF3A51049269BA5DDBB5732281E39D9B7BBC0DADF687DA0B8D99D8470586C8D83AA6713C56E54B698B86C9215E0BED92DAA0A5691235307531E55F1E7C424C84CE97BE428053170C2F6FC9B9E317DD9721184402A439A1500DBC454D985B36343934664DDE6EC300D8AC0DAC330C75C200972FDA523F10F3AA3C4E9538912A4F19504C9FCA44F39F246DEF16CFDA78B5844C56E952AA0F13C69976062C93B169284FCA4A0518850147A061C5F57A5728C9E30D65B4B4D332EA1325C5BF9BB394709D067DE72CA29FEC3D978AC6292BDF25370E4BD6EFC2B50D4E358AFE2FE6CC7650E0C580CDECF7A1C83EB0ED4DDC7861A4B9C484880567DE8E84F6E5F0EF52F8AD97364CCDC25E81C1BBD6C19A86F0E30A7E5206F01BCEE5FF007EF46786ECD9B8DAB889124C920F3EBA09FF0011148A700C5C8F2ADED63966E4DEA61D2A7053B9150D70C29CF5FCF08921319EB4ED18548CB93DFD0FBE10D94B2682803DA84F33EC426A7529E44CF97EF4B09433096E03F50814A8DC8E4E5BD228E20A923E741C3CA374BF36FC424A9449AEF1E469D29482B53874D40602CD6B743E50B4A0524124B747A0A353D6E1F8414DE648985B74D9E9563A519BD5A1E226240AB5793F23584CA0924E59F9D47CEC1E35544CD2903FF2229470DC7CFAC2E89D2C2402AB727EB0BA084240CCFC2B28C3C84A00C44BDE99A90E686B535F2E1C6194F52A62DC1000E3F703EE62AE31D0FCBF7A5449C2972896906C1C0A33F0A75E9946A14A600914CC67A450596DC254B52E0C6423C8EBCFE548AB0C924EEFF10EDD790A6679E90A198A09A11BC727A0E2457850FEA02C3491FD3409FF00CB9F63CB23CFE1DD33849AFF004EF30E0587DE83EF78513369F536562D6A171DC8E6D10EFD95C5C38A0F381A6103DC4B248F132829781FCC397918D66965E0F0870FBB3100CD62E480E789CDAB6E22F487D2F1084A494BA89762AB26AC4A4D18B1B0CF85DAB9625F49B77382CAD888526C00429D11FF00ED1A2A7B81A9EB3542DA88C5E1967FC75196905C6E929B170E539DB33D2D0D66265B28A54A528D5D4D47B80EEC0BF105DAA5846BD6DF6EFF0013B1C5DCC6F76C9561F8F2B85C78DC4B56F745B0090C168712D5C20F10CFDE396822C7E11F1963F6762A4A66E21659401FA8B1008096CC9D72D6EF11388C2198414335406E3776D0D99B3E117EEE67DA770EBCC753BACDB65BB85EDCB29F089BC29658B85841582C970F88B052019E73CF9FD00F85FF001230F3244846217BCA5000B9A1714BD620315B266B19A94B807EA09FE4C7986A3871F88DCAB3BE57876C8BA520BCFF00190B41FE9848CD3AF2298CF31CE73AF4361F684ADA4533A5325243E42841E26BD74CAB159C4A55266143021E87D5DBD323A3C4938BE00550549001E2198331A7589135609612100EF2599C97146615BF6CEB1B4997F3684B1CF2D5A87F3EA230E6F3B7C5B2BBA7C32E718DA3BD69087504B5685C407AE1491010CA164712B888100EA467A550BC5BE26C26C991314B9A93BA0E632E9A8BC4A61F644D99BA405104DF235BF12CD4EACD6E6E6DB6F5F7E5ED28B7F01DDFE16BD87D81794B6EE318BF62E30EBEB8609502BB47DA25B59D609C80226BC87E34F8E7B3F674C9C962A3501B758F98EED46A71964786310A620B39760F605F95A3125A7F0C1F673C69C462FBC5C2DEDBFDA0716A7AEF10DA466D71271F7D47895C4E3A9E25210A242330427872E9C2B1DF154ED19AAC6C898B421C90016A0241602D6F4A5CC741D8FB31586C3225A92193725EBE55E74FCE16F685FE0B9ECADBE0D9C7ED304D9AB6D95C69B6949B17B0AB4B3B2610B2212A5292D9500204C09E94B6CBF8B0654C08F9AB05446F1DEB9763636A1AF4CA9328F9685329296A1147B54BD28F947C9E7B6CFF000F9DE87B186DE5CE0B7B762EF615E717FCA719B65BAE043613C4A4DD5C1425B1EF282120089D6BB3F87BC6183DA625283998AAAC16297C99ECF9F6033899C16365A5410C2AD6CA8D90FBDED1A02EB88B0B979448BC55B94153AB1C725794A5594C48E233D72E47AE6CE99849884A952D2491A034EA4F5A18B4E16626687B0CDC50F56C88CCD416ADA2ECC27690D9DDAD65695A161247826502139807491306329EB90AD316100ABE52581B5393861CE1D89E25CCE160722E2D5BD74EF172DCEF01BB7B7712B0F12A040800807389CF4FF0476859A852890189CAB53517BFBBE50E918E949014402CF7FC57BB4611DAADA6B9C6826C9A2E361A2B5B4B54849CF8B32390233D2233E54F307B3E6CC50AD1FB1F5AFDDF9C56D1DAD21285380287477ADC5AF9DA3AA7FC1DFD86B6EFDB13DA576371EC730A69EDD76C2DE1BADA2BDB961C55B5F29482E590B470A4B2E16DF6929702A20E99D5CB67F87F1535490154A67F4B1E5996A5F80731CDB6B788B0F21330A81234003F02DA0ED4BC7E93FB01B1D65B21B278760382DA37656F63676F66D5B9406DB422D9B43321090350991020FAD752D8BB25785968DE7269BD5156F2E39FDA38C6DDC71C74F5A83115DD29A5C017D403C8DE2EE4E1A5B750B4A885092449E193398112739CFD7CAEE89E94CB32C83BA02402C09D58EB9FF4E6291330330CD0B05AEF52280B0E41FCF8C4A21B73800594F144652447EFE597D2A33152CCC5BA012D6BF12D5FDB651338649948017FC99A99313CAF7AD7BC7A968A673067EFF7ACC80659FA816B5AB61A429387CC4B0A177ADBCBF10AA41020F5FDA9C13BC49D75ED09CB414062DD3A9FBC55588520A20828820A20828820A20828820A2082B06C73A1A6B04357092A910620C73F874D29B09252AF9C4589ED773A7E381261647F11D7D63DE11911023CB39FF13E5F0A5D33E5CC05233A000F31521EA74E7570F084EDEAB351AEF4B5BEF0D9684A5D04244281E3312721967F4CBD73A85C76C413D66600924D4D3215AD037BAB08DA4122C0F3AB7E351AF1CA20EEAE59B017F7D7AF34D61E96C952D6A00200499CC809198EDE672A8A3B5E46C1428CD584A520D5C0667E79BFA8689297294A28009330FF001EBAF0229F6BC6816DDE37B53BE6DA4BCD8DD8CBA5586C660EF70E23888716DA71343A78D6961D6E5B7BC35052083A695E6AF88BF12E562F1D3A5A673B3815A160455F419F48B860F0DBA8131613F31817D1A819EA1F3F3E394763B63B03D89C359C23006529B27004DF82948B953B3EF28F04020B854A93CB3CEBCAFE2BDA29DA6B9A42C2829F37B917B8E033B7030FC214CE48278753F8148C8ED5A316484DBDB28ADA4E609226559A81390C8935CC8ECCF95882A6DE0083BC03839973D79035B4094A941C8097CB870A690FDBE7E93F7F1E9F3CBA06C4C6A70410924815AD038617FB76D633B8751E7F8852A4F138BFF2166685120B541AE9C1ABEE820DC3A8F3FC414D44D39953F03FB8370EA3CFF108B8E70923E9AF2EF59F9BC55DFF0070141CABEF8C3271D83E5FE34CFE347CDFFE6E35FDF383715C3BDFDF1685DA3C4DA4F6F8E7AD1F37FF009BBFEE0DC5708528F9BC55DFF706E1D479FE20A3E6F1577FDC1B8751E7F8828F9BC55EFAC1B8751E7F88294FF10CE0666EBD9BD34A59E33F2D46CC7BFE20AD0E1021C6E8074A7DC463E5A8E9E7F88A82E0465975EF9F5A6EBFA32A644501F7CA32259259C41E2F74FC7FCD22AC484D013C2B4E8CFDED18F96751EB0D1D77357D807383DF5FA0CE9A2A7059D586AF5E27DFE5D252C18A401714D5DFA8B70866E3A0F383CE35D3CCFE9F3AACED762853598DF3A12FFA6D2B19DC4B73E6F4E74AF0885C55FB8B1B471F48438FDC148C3CAA55E004901DE23FD9C40F2CA35E754A933D3227A565552A1BB57DD635DE177E0F58D0A415802C9BB1707EE465FD574CB7FBB977B6B311B0DE56C95D2F0FDBBD970ABFBD5DAB85A4DE21094B81B940F11CFE8B452412012632D0FA3BE1EF88132848054CC520DAC14053A1F79EDBA4EF02DBA5D801A86AF2BFDF4CA7ECA3ED9580EF81DC4365B1B4230BDACC0128B4C42D710E06431F854A9B2E942945690E2195384919EBA1AF7DF8476DE1BFEC72F10A9B2C112E84A9896B76AD3D9A86D2D8E573153132D4402EC915AB87000635ADE9D1E28DF57B746CDE07B46E6ED776CEB7B59B5C54AB774618A45EB36CEA9328F13C1571A0093AE723C85517C63F1651B2513512E781BBBC1D2AF3BF00F916BDA37C16C73F4AD482294045B982F4EAD666B0C3381EEA76FB7938B33B59BE4BC7EED9B858B8B4D9F4ADD5DB59A490A48FC2BE084710E052A3533E55E57F15FC6156D33364AA7A95BCE03ADF5E3DC5338B461309B80580160010389CB8D73E31B8786E0D6186616C5934A4D859DAB6136D676E435200192DB040CE01CB339EB9D712DA32D1B794B9AB65397AD49AFF006FD2A1844DA48410000F99E7906F74D6B0AA5CF1471F006C49012040001C8C752209EB3355AC561938196A909002402E05B33E67DDE25E52B725303900C59DBF157CBA45550D253B93D243B3827A0E99FE61B2D2E4B8A5DFDE6FEDA39EFF00C4A7D97704F692F672DA8C1C5AB08DA0C3B0DB8BDB1BB0848B91F850BBA7385C82B1286B87DD1A6B3CFBD7823692652A424A9882C43B5A9A9B74C83DA16C0CB22728B9214CDA0028D90ADCF334D7F3D2DA1B16B66715BAC19E654F39657F8A58DDF12415715A3EEB08E2D39B79157975AF56F87B1699F2905C10522CF980DE6743ADDE2EB83514802AC59C727AF95A95B8D71F5962096C9466985AE12A1060A89032D321979CCD58A724A8D29C6CF4D58F935844899617F5172DDBDE66FDA14C4F1305B3067DD33DFD674CBFDCE68230CEA0A22B5BE872A0ABD33E30D27912D0541419BF8E46BA017E59579C3EC5ECD637BC4DB7C1361F044ADEC5F6A313B2B2C25A6B894A2872E1A6AE8F0A7DEF75B70A8C010019D60D8F676155BE9A549C85068F6E428FC294A36D9C7A50140920006FCBEFA77148FD383F8597B1BE13EC77ECE9B05B0C8B060ED462F8622FB687130DA7F101C7D28BC612E3BC216327783DFE4234AE95B2E514A529003D1DF2FD373BD9C57906D6DA2899355F52884BD07F153BBB9CC69CDA3AE167C66DDBF10242C0293C208100C0D7392209E5D2AE5202826B66D69937DF93C5594ADF2540B82491571D21D4099813D79D388D60A20828820A20828820A20828820A20828820A20828820263A9F2D68820A208681242C922049F9CFCFEF9D656DF254FA1EEE47DE164FF0011D7D4C567E3E550924B4D014480E737E3DDBBC22BFA9DB36F2688176E1F55EBD6ADA92D9F7787C6301C912A2D811300E7940F2CEAC7326E1E561D3316A0FB8A26A0E54DE7ECFAE90E64A52900A92E4359F8B3DE8DD41D234AFDA1B6F71CC5F6AF07DD46C4DD326E6E14E8DA4BAE35163096F843ADA6F548CD83728E24B1C63DF30398AF1E7C61F180C11C4A24CE228AA24B53BBFF0064F3B3ECBC3A66A1334A46F1D722096637D3B9CE2736476551B35875AE1F62B0CB366994BAD9097EF1E7614F9BB23FE44870A8B71A24E7CABE7EF883C6B88C4ED25FFAAA037D55735726E5FCE9468B44A9094824951DE1549341C86BC7F4D7BDBDA9171F8D7084BCAC94D23FE088E1E2819F16A74D49CA9CECFDA7FE531592A7D59BAFDC5BB88544B480C09E04D48FB7944BF0210785B2A299C8AE264EBA72074ED560DD9653BC012E1CE84578D630941DD01443825C8170F4F7E50F112013AF413D35CBE039D454FC52A52BE82522CC29AE9A91ED8C6CA4A697D037BE66292F2418827AE83FC7C2A57058B2A940A8DF2068393D89CF3F383743DBCB9D9F9E547F2F3C71FF0053F114F3FCA1A9FF00EA1F98CB0D07610D5E738946011A73CF4E51F7AD63FC9FFC8F71F9BF970818683B0868A4A892441E809F43C88158189FFCBCC77B8F7DE061A0EC21E30785B4854939CC79D60E24E4AF31FB818683B08578C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDEB2312A71F5663307C9AB06E8D076838C743F2FDEADB809C9387493BA685F9F11ECB528C6022C0123967941C63A1F97EF49E216835052189766AF36CEF7FEF0520906CC5E99F384D464935018A9EC0A4101AC469F7AFE348374053F0B69C63CA839B88DDB9AE8F977AFBA5E009038F3860FBC12E2926728CB91CBCFB7DE74CD38B4998C0DC970FC082E01F3B5DCE65D210E12EC4077198734CA9C61929C2A39653AF2F84534C7A3E64B531269C686BAE66F67E758DCCA4BBE438777A57852FE69BC8B552136F745D26F012DAD59A590DE64B44FE52ACE48D4F3E55CE31E172E7024167B8B38201E1957D18423F2C6FB8FF0069B0A9BFFB9BA37DE2DABA4E1D86B57CFADD0E61CCB4BFC5BBC414E94290A1FD654C70415083309ABEF8576A2E4197F591BAC6F6CEE39726B17221432986E9DD0A361CAA47366CC671C32DB0DD66DAEF1FDADF15B9DC762EC6CAECD38FA5ADAAC4F0E7DCB26EF90E5B1427F00F5B8E071C6E5C4BBC792579098AF42E07E2A1C0ECC18233C83BAC06F3573ADF2D39BD225A4E065AA4EF280B5185DEEE286ECC0F6CE3A59B89F642DDFEE52EF15DA0B172EB6A76BF1816EEDE62DB49E15E3EC3C904BAAB67C00E264A9404C9223A5722F1778AB13B5D530A6728EF12CCA26F77AB7A733708CCC2A0252120005DC9A10D5191CEF9F1AD36DF8906D92C3656B0911E33F9BE0F31C407E549C9234E181A571BC527186715EFAF77789724EAE6E5A909A30CA4555BAE1FE94BB372233B9191B3188F71588A53E0B2CD93CD2A789DB9054F0067349D01CE0796719558F666D91839604C249CCE766677B758D172AA9980A86E9A007E93615705EBC7F6DD09FC3FF4497164192B3EF66ACE275806009E5E54DF17B4938CC4BA4BA4F4FB56BDE967021D4B5A94002430CB53FAAF46BBC2C0CCE4479D26A414B4C71676177A9AB5A1DCB4B800B91C74C872A7E22036A70D6B1EC1311C34AD4D97309C52D9C4A8C21C17166F37A664E4A8F3D62AD1E1CDB22462A5277C065005CD4641B9F57ED0FA56F61953269495209484253553D89577E62968FCE1FDBFF76D71B9BF68BDE16CFB1641AB45627717569E2B640578CA76E1D288024CAA7202799EBEC8F877B4062E549ABB800BB31CDD9F9FE22C52567752A0E1C02791AE5A3E59BC73C6C31238978778AE161370B7810A3C21AF09453EF8D13C6734C6B945762992525767A03C2DAD4D5B83C4E4B989F92096E2EC4F1035AFDE9085E622CBEF1B62F21840506D574EAB8584B8A84B4852F40A757086C7F728800666A470780F98A480379449167A0FE9FD3855F6B6304B0ADD20000876008F4AFBD5BE9CBF8057F0C3DA1DE9EF2309F68EDE9604E5A6C86CC3EDDDECDB57D6EA43B71E282DADD425D470293C694AD2A428120826ADF80D9AC5F70D19E99D074AFE9E3906DFDA43EA4EF92B3BDBA1D817E14F76A47DEC5B60F6966194DA39C2CFE1D86322250DDAB4969A4B519084A52083CB402AE184C304904023785CD05079380DDACC1F97E371049672497A641C9AD34FC708BAAD0CDBA0CF16A27AC18CFBF5A9C9619091A08D64282A586CBEE4C39ADAAE2CD9EBC1A1682B30414410510414410510414410510414410510414410510414410D1C5F0AC891AF3EFEA3FDCD65C2D1B82E72A645EB58DB786EEEE7FB78A3C5EE9F8FF9A8AC6CAF912CCDCC027B5ECD93FB35D635DB7FFBD7C3775BB3AAC75E702B1828718C1EC10525DBD7AE3FA1C48689973C25AD2A907DD1279E7C4FC69E3D3B2B0F365998A4965004A99E95B1BD7B7689AC1E1C4C60A70090F43AFA5188AE547B6ADEE7766718B5B0C5B793B5FC573B47B6AE21EC6D2E7129766D30E2861C1A0B1C6D9532A471956B1EE98AF0CFC42F162B6D4D9E04C2A0EA04825EAEDCB2C9BBC5E70125084A120252080523DF0BD5DEACD48D85B17416112A99923FFA926075C84039FCABCCB8DC2CC38B54C20D54E1F2AE629476353689854A19003570C7D2255B74189D0F2E533944FF008CEAC3B331064EE87634B919599A9D4D78D2032D346038D05BDF778ACDC42A24F91D7E67F71156D97B437D206F0B35EB600D34D73A5E0328640371BF90872DDCEB9EB1CF3FA8D7B99CBE0DA7054E2FBD7B1CEEFA311EF211A992ED60DA7F5142DEE2513273E93E5D7B67E7CE9FE154508DD2E1ACC7524BE46BFDB9AC6532D21C100B379BF28A7C5EEAF8FF009A75F378ABBFEE37F968FF00888A819CFAD1F378ABBFEE0F968FF88828F9BC55DFF707CB47FC447857C2624FA7FBA3E6F1577FDC1F2D1FF111E78BDD5F1FF347CDE2AEFF00B83E5A3FE220F17BABE3FE68F9BC55DFF707CB47FC441E2F757C7FCD1F378ABBFEE0F968FF00888F3C5EB3DF3FB9E7525276B7C997B80B76EAF6AE59346BF283D83720FE8D1EF8BDD5F1FF0035A4DDADBC18967766F7C6B7318F95C13DBF5078BDD5F7EB51B3717F308DD51CE8E1ABA0FB40658C92FA9200E4D9FB7178F3C533CFCE73FBF5A66B24A492493C4EA7EF1B09696A80FEFA53AC47BE789C51CFD7EFD2A00E20A71052E5277B2350DEEC05B5685E52185817EA5EAF97B109559D28F9D87A312D5269AF6A690AEE876DD0FA35619E2171EEDBD838827F16974B57490786CD2D82A70B8BD1B0A00E63588D73AA76D4C12B7882D7A70E5616393F1840A1017F31949DDBB00CA761AD5B96B1A75BD1DBABCDB0BC7773BBBA7DC7B115BC96B1FC6DB59534DB2A5074A7F10D9E20435C6885039E54B6CB92B97BA0687AB545B8BFBAC6FBA972B20BE5BD91AD9ED761FB78CD3BADDCE6C6EEBF0A69BC30B5797EA6C38FDF39E1B8F3B70E8E3789740055C2E1508E5E750FB57138B958F212A59008A034ED5039106B68728C5A952C2024A124B7D4E0E840AB7BA59865AB14F0979F5C80B981CB2072CF969E8672D2A6366CC1380F9C5DEEEDC0D457EFAF11BCD595EE84814A123B822BA8B9F2314820C919093F5A90C64AC39964A521C0B518BF072EDD2372779B80CEE48BB0FEB8E4C551F68485851129C81A3FDBAB7611A2A56F26A2952458B67D73F4A9A380C345A0E1002889E84C1E672FAFED4C367A9631010B777CF2B75A8E5AF2604AA5CDDD043037CD8543F1A1FDC435DDC30C922520C99394F6FBC855D6724270BBDA26ED4B015F6EE468F13D8594A98000EC4DF4FC9E432A45818FE36AB76EE5F6B34B4A6D2A03FB83A4214394829267B738154995B53E56D0090B23EB19DC38AFEBA0D0582448489441009ABEF0700E4D42DA6BE71F187FFA81B65B08C037E5B0D8F61CC36C0DA56F1255D38848485A99B46C09226482A233F809AF777C12C48C56137DCA8A44B097399A171CB5E22968D1531686046E9259920330B061CF2CA8098F9AFC6F16C3F01B753EA32CB6A507594C12A2EA88494A4E47878B889E5F2AF50A2415CE09A0700D4DFE9E5635A67D5A155E384B90EF522C1A94CC6A3871615AF4A7F8567F0FFDA8F6FADF5607B3C6CAE99DDB60988DADEED1634A6D69B7BB4A568BBB66937052A65C0975A2D2C2B39C84E756CD95842A29DDA1166B9BD68294F6F1CFF6E6D51BB30EF1000CCD0BB017273A796B1FA6EEE1B72783EE3776F816EE764F0DB2B0C2706B0B5B44AED594B4B70B0D3695AD65109254A44CF73ACD5E7098408028038161439FE4E669D0F25DA78AF9CB2B2A721D8136F6E3F119BDBBA6D572D59356EB86C1F15D08FE9A4C1391CF5333D0CFACAFC94A4DB26A5037403D88ADA91BE52A193820F1EFEDA272C8116E906322AD34D67D35D0D6C030034871292120A4351AD9DFDD6BAC3BACC2B051041441051041441051041441051041441092DC28272C873E9973CC51190926D5EB088BA9310358E79F97F98AD54ADDC8C2BF256CFF004F272FE622B55C25313AF6CC72FDFAF23956A99814486208B8BB7BE0EF0CA7CE124805DDF2EBA8E51EF8E989391E5D23E3FA8A5189200773661EC778DE42FE6B310E6DC39E5A373D18C44BD769F1C85B6B6D103FACA10D679895729981DE7589A692A72A5E2F70B14DB4B86D4FECF3A3954B09CC96B817E94108BF74DDBDB3B74A5071A6D0A7096C923810095A87284804AB3119926293F104E4CBD9F3959EE1672327CADC6FCA1597237949033A17CB9D9A85B4B738E66EF0312B5F684DF658E1F863C87704DDABEE1714EA81B2C4977AD85280E194BAA61C411C8A142BE76FC62DB13C4FC42113084EF29802697B6597A728B66CFD9EA202897766EE351CA9AC6CB216C5B617716EA6E5B52186B86253FD101032D2047BBA488E535E503B4953274C1314E5C80F9B12736CAEF61C62F385D9AADF9403020135BB90FA66F5F2E3E32E301094B4AE28049464548E70A1CBB4F2A8FC62A52D5BE12695B720D7BB77AB878DF120C89850BAA8163BBAB73CE9D4C4BD9A177297148040409F7A73D724F726047523D22D78B4CBA80435DAFECBD7D61B7CF4DC8507B53F2DC871E8ED4871C9250E36648287010A1048981391891FAE54AE1B6AA779AC468CF7E9D69C236131EA283DBF6AB5BB42C8511014A1EF0CF3CC40CC1CFE3C888AB361B1E998016A0E1AF31F717BD046DBE38FBCA02F804C127A9075FDFEFBC2F33692504B120E675D33FBB508D21C4B96575AFEFCFCBFBF3F11D95F1AD7FEE5FF00946FF238F9FEA1637ADB2C29D5C908CCA47E6CC9D073F39AD86D548A10934B92470EF1A192BDE0901DEC6ADD69FB8A9ABF6DEB537694381BCFDD508518E83E1FAC56DFF764FF00C5376B9F7CB58D7E590B0870E7476F4849171E3B62E129712DA89038801106338319F5A708C57CC1BC081D5BEFEF58D5437494921C33F0F7EF48F5B790EAC368701513192B2FAD6FF38FFC8773F98D49090E6D0E5C696DACA0AC122261479FCEB266A8162A1DCFE6308585A428380758F034E75CBFFB4FC2B1F38FFC8773F98D89604E91E96D43FBC7C48D7CA4FCA9BAD13261041735B1F5367A7BA460170E338F3C357FDFE07F723E9594CB980015F38CC78A42BFEC08F3FD33FA52884AF371A3BD3AFE3F3047810A9C881DE48FD294620124B8639935CBCE084D6CA8AA6419EF303F7EDF6602660662B1466B9625D2EE4039BEBA52B6BC2889BB818B56CF7F56F3D2F08A93C399223D7EFB0EB564918B461A5042EAC2EC3F67D3362F0B09C86722BD1FDF0AB6710B7D6B7AF337EC34E20377CD29AF1164F8B6E1485364B247E59073EB94F3A88C66364CC0A1BA93BCC5C8167A65D385EB684D6A96A5A16EA1BAEE9C94FA8A8A1BF522AD18CB77DBA7C0F60938B5D3015718B62AE788F622EF0AAEA38D4A203A3DE02145226721F0672368C9C3972C0E428001CB5F3E548D8A92A2086DDCD3404DC8D7AD3B168C9565656968CB6DCBAE25256A2550A24A8F119E5A939F6D2A1F1DB4708B9EA56EB92694A3F91D47E21352492E0539D7ABB76E668F14DFB8EAD4916BFD36D260A55209197E58CA72E7A914D65ED24053CB05366E87AB0C8DD898565CB5937625AEE3FBB5790A98A537896C04290E123290099394E67BD3A1B494AB971A1A5F32286D0FD1254F5151D5C6B407ED96B0A8BB6C988503DF2FBFDB3A5D18CC29ACC48720DC03916ADAF6D0E7A29F256C4D2D4D7B1F7EB0CAEF186DA429B1C5291C898CE35FF03E154AC66D49387DA7BC94B277B40C187B03288B9B839A6782092E680660D0FEF219877318EB17C5D6A51E02A19926662750797293FA54D4CF14E1A6618C929014450903833D726ED16AD9B86504A41760039CA8DC75CF964D1108E0C4ECAE0282B85BE05BEA50F7441E240933055103AAA0D57F01B326ED4DA09992CD0A9269A13C34EB4E6626CEE4B60A20153900B396E17A718F91BFFD484965388EE56F30F69C4DFDC1C7D29B72902E5496BC24A961033E10905733F973AFA0BF03B616270D22482BFA1613BCE7316C9FC9C6B1158A989492A72082F5BB68F6E6EDE91F3C7ECDDECBDB7DED69BD9C27775B05862F1ABBBBBEB165F79B69DB8B1B265C71B3726F94DA54507C2F10A0C47109D04D7B1F0BE1DC44D289A934212C43E8D96AC18778E7FB5BC4F270D315209D453859EC7EFCF2FD38FF00868FF0F9D8BF61EDC9ECD6C761163871DA4561ECBF8F6256ED37F8979F7909B8E15BA948510DA96B400A04A408EA6ADDB3F64CCC3EEEF176E39E7EE833CD850F69EDC978A0A42412FC3E927537272EB6A474F2D597C2C2CAA19CC04926739991E64558A58DD46E9150C05F2BF7FDF3AACE5198A26956FB7A0F4859D65F449B54B0952BF3150890489CC769FF0035B924E64F38412863514D29EFDD61DA13C0909D32CE349E7F3AC428000ED9C5744660A20828820A20828820A20828820A2082880D013A434715C4A52635D0733E63CBD27E49AC29DDCB7334F661295881F3B70B57A31032CDA95AF11C23D44A567581CB2D3E87CFCC4D2A847CCA6A1FC9FF00A76CE25D202D0CD5D6B9E99F4F285B252028721A4FD7EFCE68124A54EE1B4ABB6869E4FD62176949DD0140125EA720DAF13E7CCC789546474F8C44E9EB4B8486DE1BBD2F76F7C222F0D8A549582350F4A1F6E69AE90C71071E470A1D6C2ECDD3C2B28054B4E907A0F78FE99738A9C532E6198A6A55DECFCC9E6FF889F94BF9A37C66327ADEE3323DE51803DA237888DD8EEEB1272C9F6158ADF866CB04B15287E2AE1378E8B6BA286C4159690EC98D009CF3AE67E39F13CAC2E0E623E601BA82010781672FD68FCE24F0682A5070E5CEF3B90F6193D34CDAAD47C05B97DD6A760701FE6AA529DC471A3F8DB975C1C4E9372A2FF0A9591211E2409D220738F9C5F1476FA7178B9E12B25D4A72F7E5FACED9C5E36728CBDC2588D054BEB6FBBB068CD178DA3F97A51038D4412233FCD267ECE42473AE19860A9D341BD4B9A72E943C2B4CEB65C3633E5CDF9854E08615043D079794610DB6DF7EECB7758DE17B35B518BB785E278EAD4CB4E3AFB4CA029212139AC82278801AF4ED5633B344D96E949721CBB11E57E2E0EA75852626662262E6B2776E2953472E006E4E32A9D7256098D26CEF5AB36EE957B87620DA5DB3C410AF11A295B7E283E2881FDE008CA4D57B19B254146840BB8CF5CBD34AB648FC9332525425EE924FD2A152D43973B753175AEED0D82DB8E871D924A8281267302626239F41AE7510306A9531B74E795B9716A126CFC2BBCBC39502774803FDA6F4A50573D5F36A3C453CFAD6496C92274FD7B0CCFC226A670CAF96C19890720E0F6AF5E91B1C329C1602AE685ABC4D78BB13DE1CDBF1169257F98C935B4D2E413435FB43C929DD491CBEF0B5250B430712B2B7828C2145303EB94E7FECF6A208B6B6CF6C98D97C2D965281C4E880207500FEBF648ACBFD2DC5FDD29DF5D6114CA4998A9AA776FA41CB870E3F710AE17B533B396B88DDF0B4C5C8570717BA4C2883ACC796B3152F879BBA801A96EDEF586B3128528907EAB299A94A3FBCE25F0DBFB57D837364E05BABFCA2665427403F4A5FE71CC6990FD5FF00A68D4A524314823944ADADE5CADB0ABB1C2F999049100481127204474F5ACFCF3CF9FF007A7B178025200601B26B4493572404F1106796647CF39CFBF9C1AC89E331F6FB98C14036A1F2F7CA152F24924C4798FDFF005FF0E25CE4B5090323637E7194A400C403D3CA0F151D7E63F7A53E70FF0091EE3F31961A0EC20F151D7E63F7A3E70FF91EE3F3030D0761078A8EBF31FBD1F3926E49EA3F3030D07611429C041CC47CCFDFD9E75AAA62425DC87B1A558D58BF4841490EC6AC5F9FB7868E3A0CC68222749E7CFE1F731F889A14336ADEF6BE64B74EF0572BE5EC4365391C51FE32F5981CAA1672C31006B5A3716AD1F9B51AA21D224A99D4286E2F6B647DF286AE3C24E6679C0E5DBFCC1A8A98B735CAF7A353FBCAB0BCBC33D774F014739F3EEF9D042887DB0D80BE119F389CB2CE7E597EB4DD5212B75352EF7EB5BF1BF3192E641DE2C0B51D837273AE75FDC20E5CB1DA4E5060E5E597D99E54894A6596ED41E4DCE164619776A0AEF55FBB53DE70CDEBCB4420F1293C6359E1E7E6723DFF006A497884A33D5EB422C3D7A7AAF2E4CEDE66514D2A5C9A37936472AB6B6ADF630D209085091D3AF7CFBFCE9AAB1E0160CCF7AF2E3A694A3F19346154523E9BEB9B574BB7DDA2D6B8C67C452A55AE5DC7ACF61F66699CDC3CAC42CCD252E58BE619BB0FCEB69393B14CD4A66D068E0B93A00DC7A677788A7961F920C939907AAA32D675EDFB5446325FCA0C94801C55ACD666D6B5A6594487F8270C91705AA32FEA8E1C0AC050DD859397574F1651C2A36ECA54128BA201E22F24FE74B27DE911C31564F0862A6A3192C0DE62A02F4B8AF0A8B9D3AC41E3B152D0E4941520177FE497161A7106F78F928FE2DBB15B6DED89ED59BAADC4EE6AD2E76BB6DF0EBFC42DF197EC50E5F611815A5EA195B8A754C4B96EA5DA1599508E341E409AFA47F05C4E9D8594B52F744B0874070B99BC5BE815762CEFABF3A16D3DB484298AEEFF0053D05C39D1F27ED1F4C9FC2EFF008576E6BD89376782DD5861D698B6F62F2C5BB8C7B17BF69879D178E23C52869FE04BFF00D22E2DB857E588AF6E6C4DEFF111BEEFBBE807E7988E4BB6A789F8A5AC6B95ABEE83ED1D6FB662FEE9A530CBE2DEFEDD69FC482A29494F14A4240CE38040E511153310F17E3265A46609090091A1500028FA99A208528820A20828820A20828820A20828820A20828820A208288C1B1E4622C8517CE7209233E5D87C7EE056AA0E1A970EEFE5E5FDC4392BFF002D3A035367FB716BD5A1B5CA0859D60E606B3A0EBCB5D29EE1C2001FC5AAEF91033EFE9778B5C82F2D23302BD5CF7FEE1BDBDFA4DD2AC432F95A48E27787FA425322546234CCF5A6F3F109966AD9E57EAE1EDC84218C47CC96C0820E952E2DEF4E514DF620D589425495BAA5988687114E99ABA6BEB50988DB52643FD429FF001B80E72A07A57CD9A2125ECB9AB5021248268CEC2BCB437C8D0461ADE5EF9F03DDF2B8AE14BC556EA08770CB321EBC656530D7F48C14FBC413968272AA76DDF1548C3C8528CD48DE0AA0354B0A3D476761A45F3647867118A904A5135250DF510C95BDD8B55AC7DBE9F5AE0D8FEF976F6CF6D76C0BCC6CA60AB75DC0B07B8E24BA4BC8857E29872504A5CE152383311E83C75F123C72667CF9689C4825565790639D29DC45B65F870C94B6E80B2C58DE99915D7DE7B316172E26DDAB77D216DB01484A19023C31EEB6003CC2409EB90EF5E36DBD8CC4ED0C4CC53A8A4A8B3127339BDADC8BC492B64894031008CF98E356CB84463F77C57DC2E7134C9FC81DCA32F28F879F9A7B32419652542CC4D3AF535E43843799869B292087292E01E5A535CE9E51A4FED97ECB167BF1D8EB8C4301BA4DB6DEE1A855D6CE3ED2C2429D6541E752B5A4170921B4A404F3D6AFD864A1526803B51AE5FD2CD4D5B5899C24C0996D34EEB00EA55AA4B579D3AB523597D8B7DA8719B1B8B8F673DF42DBC33799B38EAAD6CEEF142A65ABC6C296E23F0EB7CF8AE2BF0E84010224E90669962B0B2D414126A75671A8F47BF1B43B5253499BCA56E7FB52685C67A8FC36B1BD7B41BDAB6D9FDA3C3B08C430EC542B14586D8B84B405B8881C4A5A8FE43C52939E5C849AAD62708122D517A7DBF1C758587CB6E62805DFF7CEA7331B1764D86D16CB788507DA43A8291301480B00FF00E50623AFCE2E62371553714DD2DC3CF843654D1310A084EE94962141B36714E1ED843E514A8952125291020E47A4C773A4524E4DDFAC0874B254C546A48B70D3F5CDE282A09899CE88521BBA871C2929809044CEA403FEFF00CD10459FB5FB228DA572C8FB810C281742F22A00A4FBA331263AD64D4B8EC32F79F18C25C0637D6FD7F4F16AEDC6CE62D88B186E0D8238CDB61F62521C0B5142D4094295C213910485418F3EB4E5134331240C9EDC73F6FA4202490EA212497B73B07CF5CEDC22F7C36CADF0EC36CD8B54B9F8A6529F156BFCAA3A9208CC89F803E55933D0003BCC4F4A060DC283AD235095BA814009664B03BC5EEED4D3DDAE125DBA5078C20A8004742911DE0F90D6B6F9C923F9163C47E632997BA18249BD48735E90B250E2755031A664FE9F7D7A644C49B1B71FC1F28CEE81FED6E8D0BA5C310449E79E9F5A5A54E00665F2714BB3706FD46DF2F827B7EA2AF13B7CFF00C52BF3C7FC4F7107CAE09EDFA83C4EDF3FF147CF1FF13DC41F2B827B7EA0F13B7CFF00C560CF190238D0C06550D13D2FE91515C266333C8EA343F7D41EF48AE79A249715619F1CF8BC3298965301CB534CF96AD488F75E0924198E5CA74D7E51E7CB5A653A7F501E86AFF7CEBA7185E4497FA8D746B821F877B886EA7651C5233981A4C1E7FA7975A899F39F9370AD0D33BFEF94A22582580D2B4E4C32CBCF4884BAC4D0D4950CA4C81D0643EF4D2A29588625DD8E4EDDDE9D00FDCA4AC1A942960010FE6FEBF9702206E31795A9495108E40C65027AFC32E7999D1EC99C9F95957BB8D3BDEFC1EF232B03BA03A4139DAE68CD4F588A7B1A09513C66675D63CBA4C72F2A61899A9A8D3A3D457B8ED0E65E042812D7E078FF005C8365160E2FB50F357CEA52B70A7DD1C20E60C673A7D2A071588704037666E1986249A9B0A521DCAC03390976BE560180ED7A8F588E671D174616A5372732E401EB398D2674FAD41CCC4A92E1F5A82DC3334AD8B748768C1512424BB8A351890D95799B3EB1E3F752E05347C74082E2992541A1C8ACF29F9812749A4A4ED598957CA724921D892D56A8A5F4CF2CA2C986972FE4849025A92974B800A8E6D77A74899B5B96C302E3882D8FEFB8041691060F88BD131D73CC559B09B3713B4C2404ACB8191B16E1EF566783DA98997265A9C804B8634373AB30F3F58D66DF56F5B69F69AEBFF66F73986AB1DDB3C4D4DDA5C62A965773678234F14F8AB2F307C4B7529852F84C66B4E7005764F027803153F1524FC951FA93FED26AF7B5BD968E3BB7F6AA10A98C4077FA8667D8143CB81DAAF63BF61FD85F67AB8BADACC630EB4DA2DEE6D1A1ABBC5F6BEF5A6EE6FECDDE12E169ABE290FA121B714C90A27DC0139E95F4D7E117810E0B092553A5B6EA5156FE2585B3CDB83306B4723DA9B495316A0EA00B80067CEA4657FD3746EDEC997DA4BF66861A751925C6212952A6145440CF31A7527A8AF470C327084C90929DC09A10D421C79373A1BC41151554925F587F6987F86E1BA7F87F14E7FCA5BC90A8109CF5303AFD2B68C449252103852207EF441155104144105104144105104144105104144105104144105101A823586FE1A788A89023B89F4039F9F3CE26886A24BAF7DABC5C79FDBF709388490547967E5CA474F9D2AE5292C0B80E73AB07D7D1A1EAB109901945A81C74ADAF6B4312EB09539E18487140F12801940804911A012263A8D045336E6D0F912D41D5BC012F663A70F31F7470F8A4CF98108FAAB6ED6E27D5852F1A87BFBF687D96DD558DC5A1BE6AE31A752A0D329710A712B33038642A012274F21AD714DBBE2A4E1CAC0987783B906CD7B33776AD23B4782BC173F6DAE4CD5CB2892E08431DE50E34ED9F131CB8C537B98C6D5638ADA27DD7957F78F151B774A8B484A15C2DC209E2128E139F5F879E3C63F10D7284F4FCF25E8DBDAB59EADABD69DFD2DB23E1EA30F2512C48012025BE8E21EE199DCF5BC5E789EF677876564CAAD2E5869B4A470B4DADD060680A4440813DF58AF2B7893C5B371F88581394CA51600D2B980FC5F56CE2CD27E1FE1A63138696A531BA4123967C7F30D6C3DA0F78B83B8CDF5F8F12D9C2014FF54C0490939129039AA7D7CD0D95819B8B48592A20D781E39FA7770F11B4FC07874214061900814012033E46C6BC34E11B87BB5DE7D9EDB58B5737A017E0150000209D75248E9DE222A57158718445824839DDF80D0802E2C738E59B6FC32BC30509481BA92E428304F26F5EB19B6D5D6195171284A9E792461C56250D650E8569C2160C403999ED4DB0BB5BE58352F61A5D8FE78D6958A062E5AA5CC4C956EEE827E62452D66A70E995A39E9ED2DEC6786EF431B5EF67636E0605BD2D9B52AFDCB8B250B66EFCA3DF4B7C6DA4BCE1F09B2889993C22662A465E2C4E0E2F9BBDCB585EBD7A460630A1411BA4A55449193382E7CB2D1B28BB372B7B8D6FA766F08C3B6C30C361B5FB2AB5DB5EA9D694D38A2C381A69C95CACF88DB3C5240041D291C420292A25CA8E99F40D419E798A88DFFCA4A52A2A2129E3463E8C7CBCE375DB43D6D8759B0E125DB5E16C99954248488D0E806A3E555AC5A4A4D18D7B9FE9EC7864C013D2EB3425405072F6DDCC4DB8506548238541111CC8038BE73F4A6B785641242492E6AFE6DE4D0D5CE5EBFA510E6112BE12467E9FEE8820F17BABE3FE683404E9041E0B4E1E356AACC8273F89EDFEF2A6CA5D6B53C3280AC8A04BB66DF7FD73AC38430D11904E7D333EB98FDAB099A967292E75CBBEBD21352C87A5B2B9F510938436A281200E9A67EBF1D73A4D53D8900103A8AF7F7CA14402B485503E45FF0071478BDD5F1FF358FF0020F1F3FF00F68DF70EA3CFF114071434FF003F28A7D2A712090790059BCCDFF0636DC1C7A7EDE3DF157D7E67F7A5BE69E3FF00D47F106E0D4F97E2144A8900C9F89AD0CE2FFC88E153DEF5F6D09A831223D93D4FC4D63E71FF0099F7D23115AD7C29224C88033F2E7DC7D2939B30DDDCD4D2BE432AE7C2B0C268DD981C8CEBD0444DC3D3232D79F4CBBE71D728F5A8E9F3CB5ECFAD4D9AAFDFA448E1D02990BB0E23CBF77888BABE0DA549900A41E7D758FA1FD8D45CE9E374B1249B575EE05ABC3289D9186DF214C58E57F7C8F908B1B11C4614A3C4009D391EE467A7F9F3889F3D89255C6940E791F79E462C984C216140DEEC7AF01C323665EE28E1716105412065073E7F2EB90EF49A71C65B0259DEFF006ADF477AC4BCBC206629760323EADDEA784405C62AF1260939F39FAF2E5F62939B8B13050826AE4F32F47A9BF43A98712F0AD641AD2DCB830F53EAD416543F1AF9E22B994920E9968ACCFF00AA8C98B7CEBC3EF5F57FC48A3083737774D83B8E7C2B57EB11CFE396A494B162E2D5D4340CE9A46BDBE798A68B93F309DDCF8350B0AB707D2164E082412EEE1BF0282A5871ADA18AB6A1385B4F5DA9567676F6A92BC47F19EE36DB7F9878F9C02A483E1CF3F3AB17873C2188DA78B96B420A92A21C106B66C98B65D6D68ABED6DA88C1A8CB538525D88B82D96601EF7A59F1AD86D2ED36FF00F1C5EC86E4038C5885F818EE3376169C11B4190A558DCB1202800E0055978804F3AF6AFC39F83537188905521CFD25F7356FFC7F0E5C8B98E5BB7FC48196EB7002B30E05988D5F2BB9063A21ECEFECBBB2BB93B3B8BBB5BC563DB6989250E5F6338B2D171705E00952597C2439C08952120E890065CBD75E15F84F2B650953178748524057F0FA49A1BD78FE35E3DB4F6BAF12A539210B25812EA0C6AE1DAB4ADBBC6D43185DC22D941453F8F70FF59CCE0A672E13993EE9220CC6990AF47F87A461F66E1D329490964D52D57028CCD9D49BBF68ACCC2A98492470CF9D7B0A51B2B35C7616EDDB5BA5B6C242049F774E227DE3EA7CBCAA466CE33E62E612E49D5D8643B40CD4666CA1E52704144105104144105104144105104144105104144105104144105104365082260013AF327A4E9D7BD6C775282A3C7A37BB5CF2B64A9094B921CBE76BB53F37D612582E2480600D3BE475FF005D73CAB28589A93BA6B9FBD3A5B37AC46E210BC492104824B66396BC6E7A4620DE56D55BEC16CC6D1ED0E23728658B7B7E161457C30E3885211993AF194819F481CEB8D7C45DA276561F13356580048F79FBB6564F0AF86E762B684A96141467281005427759DEECF46D7331C0FDBDFE6BB61B4571B5FB557173756B7F7370AC2D84A94B2D25B5A9214EA579252612531CB9578D36DF8D24637113A52544289500C4644834D19CF7BD63E807C2FF000A0C2C99026049A26A43DB9FBAD2916E365D0865C60B28790A21453207003088CCE7C3A939033D6BCD5E35DA3889D8D9B2D2B5339CF50F4CBEF933347A464EC69094A54100D01A0A71D1B3BDEB6CA6977F72EA5B2E5D3CA527229E33C1972CE72EFA6623957309784C41C4FCC9AB5105540496E2D417ADAACF5858E124C807FD2481FF002090E72BDBA0E377876FE266F2DD36AFC847090824C09F5EA73E73E55D4F61ED5C3E124A11312E406A3353AF6D38C5776861244D0B4A659753B9201EA7B5B367B88B9375BB7F77B31B516D8638EA4DB3CEA42425478632C8E91AE703CF3AC6D8C7A31AE24DCD0352967A1CFF0021A39BED8F089C5A26EE86742D42F5604D4FBF38EAD6CD6256F8B612D38F2212B6905975B03C46E5238B80F2E23AE432F855657839F25615BC4A545DAB48F29788B64AF0F8F9B292485A56A0A3504B1239D8370CE1CA2D14029B0E14A493FD50AFEBBA0FF6BC7FB872CB9181DA4B0F315258A9CE9A1AD73AB68E00F5833805FF00C88B905CD38D39661F942186E0F8260388DF63187D9376D8BE221B176586D286145B4F0A5498E124A84C93FDC4EBA177331E9615655883F6B97CCF1E9097FDB6729D2B585CA268332D5A86A5453BD22E86FC37ED1C2E03E33924F9C9397393CF9795454E5A66390E730C055DBAF5AD2038652549485303425ECDE5F8EB0D2DF883294AC10A05591CB9C0FA5317093BA1F2F3D3D817EAF50A12992A356229C33F2851492A888CA75F4AD9EAD5B3DBDB7585C2D2598DEDE9EB1157AE8B595AC920E813AC69D81CE39F6ED5B8965445C33E5771A671B0FA8B023BC376AE43A92A85B60735989F2CF3A57E41FF0090EC6141294A2C18F27FC4542EB3949246706411DCF3D72F2F5351B3F0E42CB114A3D72B7285912D2C413517D28FC0BF67B52D0ED17262012083A8FF007FBFD2992C949FA95FC72BBEB7E9E6F48D7E52544B3685E80B727B7317E31529B71490EC9E15732639C72D73F865DAB51302C920D7969A6B1A24A524CB7FA93957CB87BBC22E079082B0DB8E0027DC93D7F6F8674E65C852C12C726B7BFDD396E152DC852C06C9C0F7EF486A9B97145005BDC02B244149F7639ABA4EA3B53D97845EE0217D01B57F27F30A6F4B01DD2D5B90E5B9C3E7D06DD29538EA53C5CB8B31E734AFF84B607E65F2DEAF60FF00DB884D1350B24043366580E858BC2A56866DD0F29C4292AD384C91A6BF326B6FF0D4120EFA4DA999E37AF956ED0893F3262920335C9603A5AD6FC4541C6CB45E0B1C004EB9C67397C3E347F88B037B7837AEA066F76A4608216106E73CBBFBC8670D7F148B84788D9201919E625391883DB979646A3A782951483F57FB790BE9F6CC69094C904AC28D4532714A023AF9F5311CF0528CE507F4E5F7DBBD35549529998EA2FD6DC214978A97295F5659528ED5ED668B471552D0B7110490066273CB965E79F39075A8DC4615402B8580C9F2361D3F713985DAB2414A4025DADC756BFDC5DE8F60E245D528E444C9CE7E072E5AE7D3BC557B1095209DEA905B85E9663F8E0C22DB83C7CB580024DAE037126B5886280532A492ACF9778D39C7D00E5511377F78BD1AB47160EDC395AB13D2E727E5EF121FB3E43DD07578897DB46797CA39FF009E9AC79080C46DB1859C6493551604D47014AF58712714852824062726CBAEB51C4D189AC5B58ADD7816EFF085FF004009047BAA2AD3863948D39FAD58306BFF0026426730DDA9F36AE44D844E26592905354B5FDF9E9A4686EFE7DAAD5B9D71D63FF8D75888504DBE18CCB97F72A5100218641054ACC683CB3AE8BE0FF05E23C558B9385C390153160382C5C9039350B3B5A22B1FB6246CF4933121F74D28E5875FBD8F28BA7D987747BE4F6D8BF5ED96D7AF1ED80D85696CBBFCB1B2FE19758AB00E69BE65614DBED909F7338E05F306BDF3F0E3FE9D71B82C3E1E7E25285164A8920F3A022FAC79CBC5FE2F96BC6CCDD2456C0DC654A135D4BE71DDFDD46E8B77FBABD9DB7C236570DB2C20B084B770EDBB4D30F5DB89305CB852238D4544924E664F2AF6A7833C2383D858542264997F312901CA5390B03AD0371F3E5B8EDACBC4AAFF0042AB515001A5327E757B5632F33832DE74B8B5B6CB2D41B55DB1871523DF2E9D0C91A7C66AFB35723700932C390CB7008045B77C9F3ED58198B54C2EED983E808F76B44D38C5C298E149487B21C44E4403064E6648D6ABB8AC3E296A2652F72AF4240E541D188FCC6C929DD0142B9B01EB43F8878D24A1B4A5512358D279C4F539D4860E5CD44B1F34BAB5CCFB6F7531AA8824910A53C8C41441051041441051041441051041441051041441051041441051043777FBBD3F4A471333E5C93DEDD35B5B27BC20B964AB3ABB31A665AD7F7942493A8FFB65F234D3098848739004FAFE5F2D05EB99402660268F70C2946E9EAF4CE39FBED86FDFED726C375387BCB61FDA0B865DE3428A54A6EC5E6EE5D120660A010759935E74F8DBB4C7F8589054582486735E5D3CAA6F1D5FC133E5C89C99BBA3E63D145A84598B86278F9135D0ADFF006CCDF6CA33688C3ED54BC3F0FB661B5AD282471969B4B8A94C0CD609E526329CABE7AE236A23FEE93025542A56772E736D7879C7B1FC11E235270F23E61DD550148A067D29DC51DDE359AD31242EDD2A194F16B99993224E5967D3A41D4D3F6E2C4EC6296E0839641C3E76A35BFBF4F6C1C54AC761659DE0E52F767CB98EB9E90A9C5B8753F319F3E833E59546CB90952B402F6FC5A2C5FF006E4CD1FC778351DCDDB43F704520FE65F8B2D34DAB83C3E2E220C1CC488CF3D7FD53B4CA4A40001BD855EB4E3CFADE18E2763225A553141212C487A373BF067B1E622DEC39DC4EE36F70C66C1B71C487D216B40240D33919CEB9F78D32A732E554580A13AD3A5FAF58E7DB57132B0626B94064AEECF50410EF9F9DC651DB5DD95BBADECA61887C12EF809E30666613F219FF00AA7330BA500D4805EDC32E0DEB1E2CF19CF44CDB98B54A6092B70D620E7A3E5AD5AF1929B679F08E51F31D33F9D20A4B80D4BB69C62A0A98CEE49D74FC7E22972D87171AB28898CA3E3113FBD24A940BD95EAF6E367F6D194CEA6E834269EC1D79E4FC3CF1DB68788540348CD664447727E79FCEB41280C94C387EA1252014A812378BD694B6B4CB4F410A8BBB6BE1F88B45256C2B24A92414929C95047FE535B9C1EF10A09D34D33A1E77A9A9BC47A42925295AB7940A9CF3B4149AA46EB500E63F43DF287096DE0CEDC6F68C31BD5DE2DD6C5A2D0B1B378A63085A8A54BB3B42FA07BC9008339C4E67AD247E972F67A8AF63D7A670EA4286F900B917032A1BF7F6C627367B1356D7E15698A7E0313C33893C4AB475A2CAF3CA382627EE69B4CC490A0056D41571A3D05FABF287895251552F77424DEF7D5BA45CCE2508570A1B75A4803DC7870AE6332477EB4D274F0E58A8035367045E819BEF1AA5616905D2A2E7EA4D8D7DDFEF0E5BCA472CBF5A899D33E616666CF539C6628657893D70EB508166CE683EF051912648CB590279EBA56F86016424DC640DEF5A8D5A9F68D0EE20EF3328D1F32FA7BA6B568C07BD0DF0DEEC93AAB1C3EC2FAE569047130D1704FA1EA4CD5930F24EE86E3F8B53F19B98C942557482DAC5B9BA1DEC63DB518DDC318A61F8930DCA4A03AD29281209D09EFCA9862538B44C2995BFBAF42976156C99ECDC4DA1D8C2EFCA7615663A5855F95B2A38D365D65FBCB9F7D32DFBBC2179F207E3FB522DB43559EAAF3AE8F5A3660B884F7112D164B7035D7227CB2ED0FF00C1B77C26D9D5F0AD04F12504011CA06BA77C8D6A46D014066139DEB614A572CCB7A335A8804A7743E79D32A1B93DE97CA558B1B52D1638CE70224139EA3CF38FAEB9E5231E4FD456DAFD458E7A310465A90E619AF10B490FBA4F5719DFF1EB68E76D1162E2AD90494A0E5399F7B333F7A5650898EF33F95DD9DAE731A30CF8BC2E8C52264B0E589B870C18D4B1635E511EE72F5FBFBFDE9E2774074A6A28DF8CB9901F856135A50B2295D29D295E3083D60D3ADA9E54C919E9CBA48F872E71A532C5A0EE9A00F73E8DC287AE8D0F30B212952737D398B33726A7A8367E2187B526129F2CB967E5DC728806AA98D949FAB334AE479EB5ABF38B8604A52C1A8C38D455EBA3FEA2CBBCB54A5C5A529C8691A67A74D34CF3E9AD414F94A09533391424F034E15E00671654282A4834B57817CFA4415C5B44E51AF2F872D23E1D39572BDB00FF009C5245942A347AD5B964D951A35C2A93F3455CB8AB5BAD3BD62DFBB5B12BB77ED0108523FA8B6F27648260F381C8E42BA3EC89811B2901490E00AB0FF90BEAE34F58B6C80A520AD330B043143D03A481422D60733A473FBDAA775DB118DEF977418E5F60AA4A1DC45D379C56EDFE19D297184B61634502749D7313D3D3DF01673F8830AC187CC40614D1DC176B9F28E75E25DF1266098BDE9890BA82E03BDDF46F4A47D0FEEEB0AC3767B66F67B0AD9CC22CF0CB57B0CB30E8B660328E14DB3441844093339819F9D7D8AF0B2B7B66480C0112D16E43D3DF0F2A6DF2A38D98A52B79D4ACDC062437BBDC878C849C3B0B5BCB471053CDC2968041CE388C8F31F1CEACA43EBCB23CF588389CB55214CA4B69284094849C88831A72ACB0160D0438A20828820A20828820A20828820A20828820A20828820A20828820A20828820A2086EEFF0077A7E94D31DFFF00CE585AA4E7937BB46410A4E8439639FEE8CD0D3C4E151C8CA4F3C81F5FF15052A6142580513F5540EBC3C8BD21171BEE6CF9F2F7EB1CF0DE75F398E7B4961966C1877000F02173C31776A348CF4274D33E599F2A7C75C699782C48CB74B00399A9E1E5C4C5E3C3D3D52D52C8240075E3A75B679DE24B6F360ED76A2CDFC2AE116EE256DACB8A700519E12A1C24EB072F87A7CE39FB489DAA402C42D65CDB3F75B1E11DDF61EDD560C4B5952D40148FA4E64B59F5ABF2CE91CD4DBCDC56D2E09757D7B8532877094AD45843416A772278F2480089074D75D4452D3B1226282D4C6EEAA64295A67D5ED1E92F09F8DD1264CB96A9A02801F49559FAB80C476E91AF8F5AE2EDDD2AD5EC2AFDB5A55C256A6149464489072CBD339ED584CE483BC9E058795C9E7EDA3BB6C5F19E1674A1F3160D01AD43D5B3CF85F4192F6D84ED0BD76BB6B2C23115AD6501372185FE1CF10E4B1AC139F965953C97884A98960D7CB2F75AD6B9C6BB77C5B874E1D7B8B48FA496040A8CEEDC5B91D2374BD9FB73AFA1D4E25B43689376B5256D29683293075E2CC6A34FA654F113921F788B6445EACD5F5EF1E62F1978C49337E54CAD6E68CF5CF896FC88E8561086B09B166CD49953408940F7784FE5D633032397A9A693B1A90A670CF4663D4971F71A479EB6A62958DC52E7BB1597BE97A07A3FDE26D18A5BA6650AED034EBCB2F49AC231214097A86A1258BF3CB8FA188DDC59A3B8EBF8E10B3D78D299012485DCA541A3FDC9294E8BE62797A7ABB42D24124D4E941D7A3716A1B46802CAC245377B17A86A7ECD9A916CDEB372E6CCE296616945FBB6F70B616A24240690E2CC9D46432F2EA327294A72A9A367FD1B65DA30B44C0B0A25935DE7CEFC2CCFEC4637DC3ED1398B6C9B5875F2D6AC46C6EAF9370FA892D287E25DE0E151CF2488CEA570F286E0373A914AE5DB816E75289511308DD25DB2A8A1CF2B7171190F15DBAD92C11CF0B15C770EB120C13717286C083067888A6B899692E02439CDB917E3D7808708FE40B3F0E9CFEF0C13BC0D80C6DD6EC6CB68302C75E91C16B6F72D5CAC139C040CC2B39E711509884EEB860746AE5C6AEE3C99E1C4B4266391BF2DEE41670072A80D9DBBC4B3D8707407ECDDBBB22DA789BB76C86D939716481D7288D66634A819C95256480A15E34CC0B55AB778709292A017B8B4B67535D6835CEDA8362DC5CDD5BA6E2E140BE4A92A6C93E20083C2091DC099A69353354951357676BFE6D7785B79091F2D09DD4A6B664D5EDCC9FB3522A6EE21C2DA9A71074952606463F7C874A60A42F78D77781241B7DC8EBC60157D058EB6B7786D89DD3785A9973C4BA5AEE891E1B4A05ACA06635CFEF2A7D8374919BDCDF86553CFCA130779F7923E934A026AFD69C6DE9AA3ED21BDFC4F7718687F03DD5E25B5F893E825955AE0CABE4F1651C45242B98D34D672156FC2A920241602973AFDFF00340D19001208592C482E5C69F9AD7368E79621ED19ED878A20DDEC6EE5DBC0DE7CA821177805F5BBA8014784A92D92448CF29EDD2AE183C260A74A0A5896F9EF370CEBD34D22630FBA258DE3967E6F522E29C69711682F6EFF00891635748786CDB564D13252C5AE28DC2409C872CB97E94EBFC1D9E5D928366603ABF3E873BC258854A0E00481A1142EC3A9A1F748F1BDB9FE237638D3CD8D9D6DD6121BE071EB5C514E12539F11919493CB410234ADCE03670500D2F3776A534B3DBEE2B10D3C7D5F4D53C1FCF97F778BD6C36C7F88F39709B8FE478606A4152556D8A710C84889E5AE5131F04CE07679144A1C02723971A6A2A223662544BB727F5C8768EACEE131CDE3627BB6C05DDE961AE31B6AA1703154B0D3A8B710E90C94F8DFD4CDBCCCCE7A64455136AC8969C4912F76A5D85880F6B53FACA236619A85B07A16A3354D838BF2AD6335A995940594940E8A107C88CE0E597F9A6C25B07B3666FE9DADC2E61D4A9B368EE793BF07AFE1B9BC205D053E085A4AA0FBB3A6A6239CE910640E951F8C40DDCEDDAB9532EB9E8625F0F88989FAAA00C8DE872EE7A72882BFB27735171A42359528803EB1D7E3D22AA98B96778F603DDC8AFE6B12B276B0412198B86701F8B7F62869AC5917C508756994B9C310B6C820F69C87A89D2A2572F7D2A49B31AF2E4FD43EB174C0E24CE91BE48622A03925E9EB977362602E16933EE91A6BFB7F9CA7CAB93EDD93BBB4142C4285EEDD43D3A73AC2F869844C046ADC5AAC74FEA2031369BB96D0B295A45B927FA6002B9CC4CEBA4C8D055E36691FF6B4822A1AE38DB5CFDB45AF0CA280B62499A1C0A9DD2054707E6F68D62F6862D5FE19B378A5D34D24E1D8B5826D1C4262E1017885BA1C927498E434D729AF487C059BBBE21C2906826247BA35685B57CE285E28584A26805C90AE21C8F304BD357B523B89B076E977663671F42DC8FE51619AC82A8366CF3191EB98F9E55F657C1EADFD932142C65A07601F33AC79636F157F9B3028241049648A317AF5D22F46F0F6DA7D572CE6EAC0E32B882448AB5D5CD9B2D78BC41D5F867FAE3D624D09E148100750349E7598CC5544105104144105104265C4804C1CBCBF7A208A92A0A008FB34411556017D473BC105660828820A20828820A20828820A20828821B9CD6A9CC6500FAFEA3E95B2D01728A48B83D59E8F08AD7621C31FD3FEB8B4337340498FD74FF3F66ABE642C6FB07A1619B077B81DB410BE1E5A66104BAB3A75BDEB4CF5B4738769DD461DED4D7AEDD9E14624122DF8B20AF0ACE17C33E7CB96A6BC73F1FD1B983C5354EE2AA78D7AD79522F1B170EFB840A5AAFAFF006D4E45E325DF5CAD372EA8FF00D8883A94A89000D728C88D39659D7CC7C74E5276BCC00D02D4FA5CF76FD17CBAA6CE947712086A0F263C01E34CA978B6EFB0F6D68530E34CB96C4150428711CE54796799E7A0D69D4DC7A81DC2A2DA13437E5E5C1C459B0D8C9921695A54A4B3074D0D29F8A7ABC630C5360B66AF5D5ABF9532A70AA494B29CD47EC69AE62954ED0144B816D18FBAB3D5F9BC5D367F89F1D2032671090D42A3F917E7E861E615B2983E1A84348C1D91E19399613399EBF4CA220E5269ECADA29B10096AF1EDE5C1EC6338FDBD8FC5952CE32690A006E8592035D867F9B0353191F0B7F0FB3424218433000C921307A65E596A2333CC56CADA2EB3F532438A13C46BCCBF168A1ED44E2B144FD6A5139972FDB950EB43130ABE4B878D2A949D0C920C7791E5E9D6A2313B4089CDBC40A31A01D736D0657E310E9C1AE582142BFF0090FBF3A57411E7E2BBFCFA4FFE54BC8C7B8037C971AD2FE7A0E1CA364E15C394D4E8187663A738F1AC4494DD28A813645AE1139FF508E28813CBA7AF598C3E31D2FBD40CFC3CF2A071EB18548DD5210515980B280D3A6A6D719E70FF0013C45855962188A9C436D5AE1B76209E1054E5AB894CCC892AD273FA54CCBC5216410A601B3FB72F6F084DC229081288256B25414452EE413536A7E99F9A9BAADD46F776DDEC6319B7DAFC4300D97BFBEBCFC33585DF3F6D78DA1372F2547840E01C473491320D4EE1B10552DDCD05CE63CABEB11B88409738241B268466C1AFE7FB8D82C07D923661929C4368F6CB6E7682E78F89C6B18BF4DD5B13C52470A84F01E8796998CC5CF0B046E9AF6FCC6A824281A1E7EECCFE90DB6EBD9D6DB04B91B5FBB0BB7EDB14C3CB6EDD5936B0965696C26006DA01454A4A4954F5EB4C572828300F7A69E96BDDE838C3B94A00B29802FBBC75CAB57B7EA3316C0EF5AC31DC22D70FDA6BB6706C7ECC06556D72E25872E5685704210B3C4B242499FF00CBBE6CD783DF0429E868C2879963C837385A5CB085A949AA660FA83580058A5ED72FC6B6B65DB8BA61EB6FC438461F2907C673FA485240C9415CF88099E73CB96666CE64394B1ED91EBCF4AE51A00259500A33534A3EF10E73E3D22D6676A2D97722C6DF86F94494F8EDC3A91DCA81073CA0EB977A80C5E1771C94BB3D4873CB85BEF710E08702A43642DEFA45E2186EE59699B8653C4C7BC97169120A8F16455D34D3BD452677CB5005E97229FDE79757786DBDBAB528289DE23E97766A503DF9430C45AB5B80953A8B7B82CE6943802A39E999E5DB3D3AD4A49DA3BAC1EB70097176B3F47CEBC6164EE8496078D03D73D0B0ABE4211670966F909BD0D2592E65C0D27850383DDCA3213FAEB066B49DB7F13294532D4B6B80096F2F2F586FFE62649F9656481404B392F6AD1AFC9AC21E7E1DCB51EE072120444FC2639469DB3CB44BFF0052634577D63AAB97DE364E2933AE4115BDB4E3CCD0E9A3B806D968E271A74BE7252B8667391993CBBF291DEB7FFD478C5172B9A49A9A9E5EFBC2A12B2B2C65EE64FAB572BDADF984D572D5B49517929EF97DE9D67B01347FEA1C633954D1CC9D5BDE5C6154E1173582370ABBB926AF9BE94072AD22D1C6378585618E38CFE29849464438B01C075CC4C8F3D4CD4D60E79C523E62CEF28805CBB8E64FAF03689FC0783F138C489C6429454CEC974364CDABE678674B5BFF00763669C70A2EB16B76C4E85F48F3CA7598F2E5CEA4E54B4AD3F5915E7951B8D5BEF944B2FC118C949DE95852A2057E93E54248A8E59B52166B6B366B10B8371618DDB38B7238509B84418906409F2D7BD34C6E191BA4A5493CEE08BDBF711B33C338B961A661A605077210775F51A30ED487779883CFB7325F6CE60A254387288EC00E474CE7AD371A8DD51AEA2869A55E9534CAA5EF1098CD8F3A5AAC6EC41151A7DC1B8E516FAD0149242383FF00150F7A679888CFCE2A384A065920558DC3D2AEE6BF8CA2CBB35065604A4E8589C9AF7AF1B54D2B7888B86CE720F68F9F7E5A7948AE41E221FF00F60A615DE1956E1C76875865BCD038977A55F3D03D7CB586B7486936E841C94E8565CF2E994E93D7E02AD580504ECA4B962400E4B661AAFC34CDA2D38652F789BEE07A1B02C34CFBDAF58D58F680B05B981E156ED82A0317C39413131FFF0020C2A600EF3CC65F1F40FC079C3FF51E140723E627D79D85F93C50FC533184DD6B6072E55AF677CE91DBCDDC2148D8FD9D4AE4286156120EA3FF0088D083F7A57DA1F042F7B6361C1B89693E498F31EDE2FB426E5C0E51901BE7E9FAD5CA21A14A20828820A20828820A2086ABFCA7EF98A208A9B5A528009CE4F4FDE88214F151D7E63F7A208AC104023434411ED1041441051041441051041441051043424176648198C86B33AE7D4F2E9CEB72B0894544380FDAAF9D73F758D0C82A0082C9258BF0E9EFBB3779B511023EFAE63A547CB5267853101DED7CC00435BCA1DC8099742483C34E141C9F9DDA39BFED41835E607BE3DDA6D6B4EB6C61C1DC4538A3CA5148056DA1A652B50112A260126BC81FF509B3969C162D6038DD57A6597B7A068BF787A6A0A65A7526FCCB11D0F1F31190F12B9B775A17691EE2DA69606449F701927A1C88D2457CB9C760D5336C4C0DBBF5AAEF5B923F27CF5EB3B26515A5082012C4D4519B2AE9606B70D9C5A0AC45374B2E953C8493010080070E472D0091CA399EF50DB492A918829776A1BE8E34CB5B6978B0AB6792948CF403882E4DC71E368F5174EB47FA086951A07733E797AE82A3D33560BBBF7E99F2EDCDD05E12623F8A95517724654E068E3D6137311BC5288710C0573E10A803947783D065DE9D2316A0C5EF7735D5B2EA75ED04942D0485134E3CF2F7A9AD2103E2BDF9A00EA24651DB3F4FF30B7F9A3FE4D4362FDDCF4A3FA187E89D2401BC0122D6A7BB74891B674B6D21B3991327E7D4741F604B398264E9856282B9D6D6D5F5E995984F54A2B200FA4D8162EDF872C7D21E25D52A20FCCE5F3E54EB0F2660A9272A039D2E3803ADFA4372B969A048ADC365DFDE9155BB6A40BF796B4A9A5A99F1500CAF2309CBF42721CF3CE730C85B5DB9870C2CFAE9979D5099889614974D43B1614F3D784629DF6E3589E15B2D6B86E08D3EE3F8DDC30D071A0541B6C5C212E874A4C89415012623BCD4D4B0A29156398A86E9F9BEB099C54A24EF2052C5AD950B9CEFE958CE7B01B396FB31B3369875BA43695DB34E909007F51E425C72748256A56B9F51315352710508092EE00CD83E79F768AEE38A553B7921C39627B53F079D69177780855A29859515924833A664FCE69C22782C5CB96BE7CC72D1FA43505887EBEC7DB9437B4B336CD3ECA5280E5D0212A0202A27883A4EB0321D01D29F4B9C802D7B161C2EFEEF6CF72B0552D4C92106A186F558E5E75ED5235577DBB97631B617B4F845CBF8663F8105DEF0DAAFC2B4B82DFF0054A5600E257BA888E67999A5C4C964592E320C395AA29A3BC3B46252E096034F646BD838D2301EE877C9BC0DF862F7FB2B8AD85D61786600B4DA397A869D67F121AE26F890E1252AFF008B33949351D89DAF2252BE4A83D2854C683D7ED0FE561C4C47CC012806A4B004B9A51BA7946EBEC761385600828B6538F2930971DBE292BE29CCA5423E27B557315B4254E2C96009B5B56EEC6E358557825B10028D1DC697D3A68D9BBB5ED717816E908754A49009F0CFB9CB4CC75F2F4AAF4E214A56E9A1B75AFBBF0D2139781536F14B1D0B057BB71BE70DD6F2D078ADDB6564EBF884C83CA323CF3A4521492E083ABBD7CB9C657842A052EC750A63CEA29A5B5E061DB6FADC424BAE1B75FF007376CAE06939EA94F53CC9FF0034F913A40401365A49D583DF577CBAF48899FB216A5EF6FB816AB13AD73EF7CAD15A956FFDCFDD93CFDE1CF5E7CFEF9D6462304A1FFBA1FF00D21F857A5DFCE1B8C3AF0EC93522F99F3619F9DF449DBD62C9B539E2385B482417152729249CB972CB2E5DA4B0B2B0B394375294EB4039796A7CA27707865E2421294A4A945AD5B81CF51EB9BE9F6FB77D69C14AACB0CB974DC12A48F097212447E6820C67CB908CEA613B224CD62025AE73D2D567B768EC7E1AF8798DC7C895304B092A624B149BBD69516F2E31A5F7DB73B418B5CB97577885C7F5CCAB85D564341A9CA408333967CEA4A5600490C94848E54AEBE5FD8AFA07C3BE07183C32244E40DF005C71073BF967A88B2F16BAB9BB928C52F50A339F8D1107CB9E5D35A7024EE8259C0EA3A53DE516E1E0A9332A10914190CC64F5BBFB7885636AB1ED9CE1559629882DE6CC92B7945A235CA35CBEB03AD31C44BDFDEB56874193D1CD731ADCE510DB4FE1E7CC967712900E5EB460FE6EEF6BEC76E6BDA4715B9C598C131A7D0E71A90D85BAA247432547F49CF5EB5E9FB326CD5B83726EFA3035B37E291C9F6E7C369A9139611500ABE905FE90EC32A8B657B88DFD62F59C518372CB8D28702567C320A0F1267239E7F669AED7D98BD91B3D78C98A1BA12E4039364E19EB4EF58E358AC0CCC22BFC7285A194B1F58666398A366DC18EA623DE09530A7828702499139C831A1D73FA9E506B814EC4276CED4299043EF3026E58F0EB7616EB17295F2A682A0487BF7E0DDA2D8BB4BD78F5BB8CAC25A649E34A8905526047A83AE9E622AE188C1AF66ECE0998090006A386A3E6D5E80D1DA2DF859E9F944D015062F7E5D88B91768C67BD2C1BF98BFB3D874B7E2E25885AAEDF889294FE1AE995AF8F2241201881DF38AEEBFF004F928E2F6FE0D69240F9A1C500351C6AC337E51CF7C52779334BDC28E55615CBDE79C760F64C26DB01C2590326B0FB341F34DB360FCE4CF5EB5F68FC264E1B64C8704FFA48B0B505A8DA0D34A5BCD7B4D0A998A98A51FA8A8E766367ABFAC5D68706700998CF97EB5615ED1DCBA559D0073F6EF118A94CCC4679F2E1CE29FC5B61C2D190A1033D331220FDC73A25ED0130B00DA960D76BFEA115324B13DE9EEF15A9F4A53C460F9199F21F3D6A4E52D3303EF2453335B69EFB422B9BBB6AF1FEED9E45DA1A7F32689E11055CD23F30E922644F2A6B371699733E581BC750FEEB52D0D958E420EE962AD054F5B0EDF6857F1CCA44AD40189099851F2075CB3E54E64A8CDD136BD39E7942A9C4A5428CFA77E3EF431E26FDB5202E14892442C7BDF09EDCFF00DED35489555CC401997B35DFDF9D21ECA96B9A010186B966D0D5DBF69394923E9CF3D62753032F8D42E2F6E60B0C4838896FA6F0A7E7BF0E21DA706A2CF4A805ED5EDEB163E37BCFD8AD9E5BAC6278F61CC5F311E2D82AE5B4DD278B3482D28C891046B919D2ABDB53C73B3B6661158A993659003B05269A67CFCA1D4BD933A6A884A084E4A214C75620D5B3A44161BBE9D8DC52E536F6F72A1C4603AB52037F107F59F94D3B67FC65D918FC60C2A14872ADD774EADAF06FC52313364CE96E4D8396D00E95F7C5B2A5AE316370DDBAADDD43CD5C025B79B50534A2333EF75D0475AEAB86DAD2715864E225AD242802038CC75E76E05A23CE1D61DBFDB70D51CFDE9AC488B8495A91C2A1C312AFED33D0F3FBE944BDA895CC0862E6D415FD18D3E529897142C469ECD2D9650AA161C4852743313DAA550ADF4856BCFEF1AA925258DE2BADE35828820A20828820A2086123C4E1EE0FCCFD8F5ACCE1FF00F156AC8053F2F64FA43A425E50E6A3D89A428540850E9233E7F647D399AAF6CC9CF8B32ED555FA9E1A8E35D1A358D3FF006C4D89BADABDD4E309C212A38EDAAAD6F6C5C6C1F150DDADC26E2E380A4710E26DB2150340796BCDBE30F860ED6D8B895A51BE4CB2ED930A8B708B46C09AA1302033259DF4539FEFBC6B3EED36C5DDB5D82C3F145A8A6E380D9BCDA8C14AEC57F8658209247116C9CE67B57C89F887B2E6787B6B4F985051B8B5D5980ADCF3E9A976A76FD893D9090E1DA8721916CF83BEA06513CBBA0D2CA262232D27FC6A3E72753C6315B4FF00C99A5649356BD78B67A533F4BBCAFAD00D19AE6C47BA7AD6176EF4883C5A77E5A473D24F61CAB444D2A65025F424F2E1FDF9EAB97BB4BB54BDBB55BBBB370878973C44858D0E99F2FD29E4B9656C5C1D4E9FDFEDA192D3BC4901ABCADAB663FB7BC3E6F9FA73CF2F59E7AFCE9CA70FBC452D5200BBDB27D32F586CB96C5C9BE41C9F4A768593F986BDFF00CF6A7689252057A1EB70DDA13521245125CBB96AD3DD38087CD7F6FAFEB4FE4A294E14CEE7F64F610DD520B12417E0FE6E3216D6247F061865370A59E1BC30533A701811A46672CF974A9995294102A0939569D1BDF488D5813173129FE528FD593BE6D9BE79C4D3780E137D6ADA714690FF0081EFB256124833C530A079C69965E712B225050AB06A56B57CCE6D9BF9B888EC42E682844A40512FBC482586AF67A9D6D71130CDDA14D27C3F7509F71232FCA9012072C801FB73AC295B8B24F2D1E9E8F73FD420B94490141DAA684D4FA7AF2857F140F3E7CE72EFAFD3D2964CC0082F4C8034D6C4FAE67A468A934A22B4CAA7DFE8DE28BAB852916C5A265B52B8C89CB88C0075EB3AE7C8D3D44D06A08E5956C7B674849324EFA8A92C0E4CD6E6EF6B8A33C597BCCC758C0B6471DBF7D21C1E034D2F9FFCF2D899CB32AD3BF5A5FE6EEEF68D972D5FB3539C6C892920100DFA5FD9ABC61CDCDD8E0D856CDDBBF86E1CD337B89BB72E3CEA1A4A16B2A794A0544004C71644C6B3E74EDA7337B12480CFF6D3DDB47A58F092C19037CEE8171950E63A17E4632D3ED356CD169D584BAE0924182273E79F3CA7A79C45C3E94B2B53A58CB1404B105867F76B71315D9AD2865012E7880490BE2E23A9E7CFA72E9446CA439706BC7DFE624D2BE21A8FB3CB5F58F5A21BAD172C5F30D78F7C4299CE008D4F5F3CB2FBD6929A58022E3F223558019B378497759812353399CC7C40FACE79F3A6C92C41766F7E578869D27E6CE600D081ABBB0E6F7D2CCD420617DEFEDD1D98C02E4B6AE15B8DAC20E801823B733CBA4198CE7F674D4EF07BD1DB8364F6CC9EFC3A5F83B63267E224A948DEDD62011435A3DCFBAB54471EF6A77818A5EED0DC397CF2DE6DD795C3C4A24264E838A6047FBABC60A6A77413502835E75BB79B5338F69F823610F91246E00E91D18662B619674CAB139698A85DAB6A27358EBE5940048CBB4CE841069FAE68D69975D72FBD62F58BD9CB9135920D05486D1FD8D6DA9A1CC450264881CA673ED32232C865E7A4B45CF21C034550B5A8DC79EAF0909CB9640215A501A375F4FC442DF620C2D21B5000AC11CA67965D73924D3499358904BE6E3F2EDDB48C7CF5CCFA06F1D3CFDF73CB155F3B89E0D8EB18861EEADB8702814A8A465E519C1E7AF3EED953774850259E9A65C73CBCAB0CA6EC59D892B265A88502EE1F5B5EF9F28EA0FB3DEF06F719D9962DEF1F5BB7496F85C2A5126048124E790D0CF3ED3517E319FF0033C3F32593BC4A1541A3E94F6ED78F32F8F7C3E246D09BFE9EE904D8354BBB5FA9D2F58D8672FDE369E0824159EB1A9E59F9F502673AF37787E4997B5F79882262A9D7DDC8E2238FCDD9C5134FD2D66A3356F5D21F5836AE04A543DE57BDDF298F9199FAD74DDBDBD3F05BA1DC8038E55E3FAB343E4C8F9729E808157A0FEBD8BC634DAFBCF1F7A3BACC178A4DE5D5EC26419F08A17CB98CF96401F5EFDFF4E3B3CCADAF84514D3E62090464F5AB797A1A8E6FE279A1299AE4FF0015371A1717EF7FCF607086FC0C36C520C14DB30982607BAD2464272F8EBDEBECEF8551255B2E402104FCB450B3FF0011CB4FEAC3CCBB571E99589526BFC959B677D726B696313CDAF23319C4472E994F3A9C9B8390A2019690CF50900F2D0B7AE511A31C998FBA4022A75AE753AE55EB0CEE6CCB8A53ED28A5460C1ED965EBEBF1A6337032D03FD30D43EE9E63918CA4AE654B9734EBFBCCDF934276A9712541E54C64028F2CC69F0EFF00AD7F1188998759FA983EA476D457DE4BA2402FBC2FA5DC7EB514E358A14CDBB6FBCF209F117054A5C78420671CC77CF9F7353B85C6603FC713710B921412E4A88DF06AD77AD3FAB16EBD9614B2B4A4BB50354B9C83036AE7D59C595B51B6FB29B3D6EE3D8CE2D66CBCD4C34CBE80EE5FF8AB9E407EB54BF1178FB66EC996BDC9F2C14BD4292EE1F9578E6D9C49613642D44028209BBA73A3DBCEDE51AC5B43ED3570FDC5E615B01B3D8BDEDFA484B18B6296BE2604E28C66879B54A929D164686BCD9E2FF8ED2B0DBE9918A7237836FD2828CC781351168C2EC898AFA0B849008DD05E9AE8C6313E26D7B42EF0093B5FB59806CC60EE199D8EBDB9B3C4D0D13201E3F74382418D2418CABCD3E20F8F78F5CE9865E2E6B026D315BB7E05BD2968B061B6484A424A3798DC8ABDC3D9DDF99A42DB3BB9DD9AB4B858C471DDA3DA8B84C156258EDC22F2FAE179921D78895250470A33C911AD72FDB1FF005098AC4C95E0A662E66F12410566B51C74CADC749D93B31A57F1019E940DCBAE9190118260B875BBA9B6B271AF0D24216A692932260830232D620F3E951BE17F8AEB95B4E54E54F213BE2A554BB3DF4634CF9445E376728021208CCB8F5A1A643A4671DD163CCE2B84AF062E14DC614A511240510E2CA877D079F202BE85FC29F8928DBD230D86F9FBFBC121B7B80A55EDC8966B068A7E330E641528A497BD1DDADCFB53A1319B5DBB52ED0B4DF10B9040274300C1EF981F3F87ACB666CE44E948C4160E01AD19C6B6CF47E0D7AECD5942DD2D5720356D502CF7D2272C12B45AB6173C512675939E7FA768A94284CB2509B0B7BF7CE1B6FEF926BEEC07010F2B119828820A20828820A20861C12E13A1E674CA75EB39E5E75B4D27FC75268CC4D79B81C896A71870957FA613C4F2677EFF00685384F14E5DE3AF38F3EBE7EB5AC14A54AC5FCC66FA89D2845001DB2F2A425314C014914BD788BF9F3D0C59BB4B602E59BC66E528751736D716EC323DE243CCADA59E13A81C5273981D00AB26D1C148DA5B2E6C854BDE3B8ADF252E1CBB0E4F7B75B895D9F89DD5A595BA1D2E41B91A17AF2B7511CAFC2D86375FB7D8E6EFDF4A9168E5CAAE30B5A0016CE97D4ABAB84B44E4A502A85009FCD97535F26FFEA63C1ABC34FC6CE91288AA88094B50BE5C3981CB3EC1B0F1EF2A5A8029A0606ED9160FA96BB01D22FDBC68DDB8BBB62196571C2DBBEE39EEF320693A8D6441E95E024E166C8529131C292A21B2FE5C6B4BD348EB3B397F370E8A3EF5C9CB3BE74E34B81110C5D715C7E1C1293A059C9073F4CB4CF28A792533010E6CF42723CF89E7120A97424B74773CA95E462EC6141A425A52D2B52466A4990673CA796639D4D6186E9AB16CB5B96F3F2A888F54B5281205C921DDEFD7F30FD1708E60E71A67F4D73CBE93528898803439BB71F6DA57386E517240BB54549E14ADA1C25F4710C8C7A7FAF9F4F4DBE6A29F50739387F5F48DBE48527F890780D0F2CE1EB770811AE5DBAD3C9335096AD7C9BED7FD6A92A4960DC7A5EB4B509D4758A96F5DBE0A78D0184478024C833EF710E5273CA321E553322685331D5AD4BF13DAB5D3364BC3A0951090952BF9716B1A72B73AE9376AFDCFE1C21F7029432053311A419E80F3F9549CA98C28AA6A48ED66EB7AE70C57242545D00306A0727F35F28789B84B00340CC6A44C7BD04E874D35CF2A8F9F39A6286F501B8208B7F41AD0CA6E1C95380467D3806D5F8985C5C9390933D24FEB23E535AA278554AC86B0767BDC7F40469F208B247507F07D61CB2E10D5C051953BC3E11CC84C6B33A03EB4F25CF600DF4E1ABDFCBA36692A428A907E9003EF0CEA29C3C8C5A1B65B3EEED5ECAE2F81AD683717EE5A2995289F0D2961E0B7028E664A410235269E23140A4835245079675E3E5C630A9133E6CA28291283FCC16274A5AEFF007BC31C1F046367916366C2521BB26C2484819A9491C4469CC4CEBFA56B1CBDE9E55A9763C35F7E64C4C4840548521CB960F6039F9EBD225AE116F7772E3CFF0019414C2008907860C8D333D34F9533A126E3CFD4F9F942A842A5CA084B120E76A9AB7AD7AD629B3B12CB094215EEA492924E704CE7F1EDEB58850A80A1BE6D6F387801403C5CB90CE33A234242886A1ADFF4FA43776E005409D739D065A9E7C8F5CFCE91981CD5D8B5B87F5E70DA6A4EF312472D381E7D793C473B720716A75D20E639E5F12338D7B068A705B8B3FB7A9C9FD690A6170E14B0AFE4A7140F4FC5AFCA35ABDA06C9EC4765AE54D254B752D2CA12904A879C67CA7AC75A96C34D4A1282097CF362F9DDCE56E2C2D1D8FC0625A315BAA01814B3D32A803BEA79C7212E12E5BE2B72DE2E859525D5786003900A233E2D3CFE11955B30389010904D40E5CB91CF933691ED3F086270E8C3CB48DDDEDD00136AE65EAD66FDD66EDF1342521014AE119252341DA35D0C1ED9F39A915E212A1722B4C9FB9FBDBB474199814CE4FCC74AF785C5F2FBEBC3524BA5DFCA09D673C8E7AF5D3D3E3CA9A2E6E76BB1CB4BBD7A74AC4362364EF1748CCFE3B353AD4DA2DBC6F114B4D32E369754B24CF081C880200A69367B8209ADBE92FA5DFDE8E23383D8A4CC054906BD0374E56D7998B5B10C51779E1212E21B724407494F4D633D20F6CE9B99C4B24292C3F8BE45A963AE917BC26C992894EA4151DD3FC402598DCDAF993FBDEDF65D45DB2CAFF10B4389584F096C92233EA0E7A03976279D43EDB9DF3B04B94A2E7748615A1D070F4AC7923E2F61654AC76254801201A0CC6A1B91E0D1BBC9BB63C4432A42F8D24498CB91CFE73D74AE4B84C38918FDF0199449360DAD6ED5A37DA3CED89967F9298BB8059F9D4E608EE0C5CF66A0FDC80D25442000531AF126065CC08EF19F6ABC0969C604A12E4121F3BB120307F4BF3888C57D3208240556A6C1C66467A6BDA30A5DB2BC63DA7F74F84DBAD017833B8AB97E09C921DB74B8D822352065C519E5A44FAFFE026C6323178599BA2AA15E3439F3ADFCCC71DF15CEDD4CD17A299893ABB5A9AEBAD44764AC5D53EC5B0692B090DA119CFF0062129303331918EC62BE9C787538A4E1A4EE9DD0501ABF4D0545FDF91F2FEDB96B56354966FA8B1ED9BEBF6CE9131E21B74A54EA5652A895019274CC9390113FB55C7FCC44A40F9EADD201724D389EB7F4D21BC8C2CEA50D6E75F77E19EB0D6F7136ED185DD29E6D16A94951714A809004AA4E8204C98CAA0369F8BB65ECF96A5AE6A0EE8352A4B5B57F2BF78B260B08A528259D4726BDF5B0CDBF6DA81BCEF6B2DDFEC7DC3D63678BA31DC59BE248C2B067DBB8BF5AD23F2A590A0A2A9CA23E735C47C47F15F634854D1F3E51500AFF00724316A06CBDD2D16791B2B78A7E8AE6E2F67FBE5525AED18A99DF26F8F78D85A2F706C39AD98D9FBFE34B0C630D5C59ED1B484129529F4A4F08E28E264FFD08EB5E58F1A7C7FC461715324E1314532D2540042C806962C4D19A99F38B1613C3E850F98505D4CC08A060D4E3A33F286F83EEBD8BEBAFE67B578E6378A5D9505AEDDEB90FDA49CD4025C1307CB3115E72F14FC72DA38D331271733EA7702629EAF70F6D74E959895B11200013F50CC870391616D7F35C9EC5AE0B8484DBD85A069A68421A4B690D891AC72922550333F1AE3D8CF1EE2B684C56FCF242890C55EA0BE60B3F9089CC36C800074017CAFCAAEE39D3562F0E9788DB110AB5682644C204FCCC44763F2A7123112F1A9798A1BC41CC568F6F7DA2451B2806DDA13572EC73AE75D1E0172C3612E59B4842B4571244667B69ACCFC2B8D6DAD9D8A5F889A4AD46515644B014E9DDBA64B0C1A93BC998DF5301BB6A5C97F4F2CA29BB5BB7C10D9E042345F0E47399024F3E53AE5E553F324E2767CB4CC0A208DDB38146D19FF3A986B88D9E8520B3922FBCCEF6D2FF009B45AD866D07FF00816D93174DAD630EBC75B4DCA947DD4121284F88720389648483AC7781EB3FFA7AF1BCDC36D4C24B9D38A46FA036F367673A80C2BD328A16D9D9EA017F48200A86AD7FBAF08DE3B2B862F059E20CA7DC71A42DC1A95788D8292206866467E55F62BC27E24C3E3763C9226254F2D1621DE96ADFBD41BD0C72CC7CA5CA5949AB6F55249B96E1A75EC22EB654168E21224CC1D469AD5A02D333EA4D8D5A1ACA0426AF7CEF427DDCC2B598560A20828820A2082B06C791821B05242B965ACC41EDE79D42A3682A6633FC32490F548371715360F7E02F585424945297AF5CFA450B751060C1E922467FE321E952EB929952D5319886AE43573473AE7CDE184E594AB749607372DF80FF009EB6E5EDB3D77885BDDA4AB82C82D2100E4E0793C264660F083F426743A61B694B5A6648762BA298DC07760CF5F22F9C3BC1CDA906C0E5AF63C99FD446897B5AEEC2E7F96DB6F0F0041FC7ECC3BE290D025DB945CBA90E8570895042279E4267515E6BF8D3E0346DEC2E2A7225050285127774196AD47C9E8D78E8FB0F68D65214C145986603DC8A548B1A1D230CE01B5B6FB5383DA5EB2A0DBEB425B76DE785495B4036B0539C4A924C11A57C9CF1F7857FECFB6A761F7373756A04377CAED6CFBBC7A2FC3A913300958AD03837A8E0EC4B6B571138DD9A5E1C208438661472332799CFBF6F49AA22B06A975673477C8E6DF819923368975A0272040AD9DA81DD837F50FD9F12CC780EAF8968CF8A7AC75EDDA0E99CD3698B12AE403CFDBD5A90D16029F75B81ECFE90F9AB9194E7AE720F5CA333EB34DD5B458DDC73FBD9F4E8E2F0D148214D523337E8E58439173A67D39C65F1CBE1E95A0C7392A05EB4A870D539E661DA255052ED762C391AF3878DDD6B9FCFFCFEBFAD3E958E342540D01A9B599BB1B5A34561F41DBF43D44495BDC7BA9274CE7BFAFEB9F99A9AC3635C02145F47CC11F8A54654786536433D393367E9E96A65128DDD8C803E7A09CF31A7C797954AA31E4A4EEAAE2D4EAFCF817A3F0862B906A4D6CC19ED7EBD61D78B2AD411E93F2314DA6620A94589B9A3F3C837B7864B94E5ACDC7F47CE1CB6F0C88C8C41981F4394F6F2ACA67106E7AFE7BDE8D7D234F95BA2C0F9935E5587497A10003ACC91E7E83EBE95212A783572096EFE9A793BC226555C01D6E3CBCEFDA00F1D38943D4FE84D3A4CE049A654D7DFB6307CA1C3853DB432753C6E295EF13F1F8EB51B893BD3093776603261EF8BC399602502A2BD2C4DB9427E17657C3FC5378DDC6A3B887CC8E16D23CF5F3FDA8845441510F0939A2BCFF5A05481AC651FC875F4310376E70BAB13A46435FAF7AC4C04023DB3DF85A1E270E26241677AD785743DA2356E8D4188F3F8CFEC7D4D47CE21CD0E556A5B8F07F511ACB0252EC03721E963CFFBB5F1FC1DAC5AD5D6AE1295B6E2542089047DE9F104D29869E1EB514A71CAE0B71EE0D62DDB1B69AB0D325AE5962935D4E7DAFC1A39E7BEBDC83AD3AFE2B86DB10254A8424C19F200CF4CC7A4D5870D88DDF50E73E5CEF46E3468EFFE1BF1B7CB952C7CD3BC00DE0FDEFA79E6F411A717D8662B862541D6821482AE20B0A0A80729D397C2454989E4DCB9CF3FB8D3FBCBBE6C0F19C99D8742553379D981555B817F2E76A45BCDE3AF070B6E96C198304E506273396791F5CE915CF228E69535A7077E1F9E57EC26D2958A1BC374B805C31E9F887AAC6F0F527C2B9E052849311CC4E527EB4DD53C005CD4D8BFEFEEF6A343D9B889724198161219F260D42D4F7E96D59E10F6D26D35ADB5921D4B2A74090232C8F29190397C2A3CCF24FF002163AB654CE8787E220F15E38918013126686014012AD417A3F316EBAF55F727B14BD9BC36DDB525521B4A8920EA44EA40F3CE464072A87C5E20A94506A05186B9B823A37121A8D1E56F88FE2197B5B15366214FBC7573F80FD684E95D86B5B22FDCADC1C86B1D3F688F8E7CAAAF3E4EE2FE6002B91777EB98CAA3AC713C5E2D23FD304BD180234A9EB7CE2E54307C36DEB7716D2D869F72E14150901B42949923B2753F2AB3F8687F938B932C1FF700AA0A694EAE699935BC436227ACA666FB1410C9003A8DDE8F95BB691AE5EC70FA7783ED65BDCC72F9D7B10B6D947B086F0C57178ADA0BF6CB6DFF000E4103310A098D3CCD7D0AF835B351253859850E06E9A0B97D2C45B331C5FC64A56E4E29504BD89341C0F3B6763CA3B5789ED2E0DB3B64A7AFAF2CB0D65A4125574E2590001275204C011E9E75EE3C3789365ECED9D2D33A6CB42D08662520EA796AED1C706CA5E2A66FAA5AE639A2921D357CFF005ADA91A3FBD2F6EAD8FD97B97F66B63ADEEB6AB691D516996ED128BDB52E8C802942828827A6BAF9F16F1C7C5FD9F804CE12A7241485070A00F30694D6B9F289DC2786A615552425814900D35DEA368D4EED1AD8EE31ED33BE7BA2BDA67D7B15B2B78AE26ACB0455DE1F88A1854487DB54A01524F4820FC3C57E3BF8E789599F2B0F8A5D94C02C80C5F27CB3EE6B16BC16C192809594A41A312056ACC33A722DCE329ECBEE5B77FB20DA6E1786B78E63EA016BC571665BB8C483BA9525F8E3E29933E43BD79536FF00C4EDB98C9CB32F1338A544827E628EA00ECED7358B3E1F62860771CF10F40039A01F7E228D1976CAF2DAD2CDB65D0AE36C11FD503C4009F7475E102027B0C88AAEA36D6231C8F998A9855354FBC564953D75A677CBC8CC49C0001212C4021BEFD4371A5C0842E3681B40842608F42627A6BE7A6994655178BC22B100A92C49773D684D6A5C7A7187C8C0A52E48734A016167A5AC1D8171D61A0C40DC8F149E12A9CB498819C93AE5FE62A167603112BEA028330FDB27B96F505E1F4B90909DD0C40347B8A934CFD34D63C37103527B020F61F5E9972D2914ED5C66114005AE94352CCFA5FD87857E50C9B3FF006FBEB0ED9BA1C31391981D0CF4CF4927A6B9F4B56CC54A992C63A78057724EA1B335F3CAF1133E6A513B74F604E63306F6CA9A0AB8768BAE1E124E5A723D758F803CBE34DB6C6D2C2CF96654B6DEABB52C5B57FD8D03467E599A9DE48398A3BD19B91FE8E4F696DEE12BC6B66F116AD65376B4B772DBA9C96855A10F40234E22800E42454C78076FAB63ED492B0A665A58823506B466F7A9883DAB800B0A7191737AB68F97172348CEBECD9BC73B6BB0D87AAF9D42715C2D4FDAE2ACAD50B6C36EA99B62B495482A4360898CF3026057D6FF0081BE2F5EDBC1E0E4098A51DD4821DC0343C1C1ABBDF2668E3BB6B67FCB9AB601D4AFA435581ABF106D71A3398DADB6585B414233E9D394768FF55EC9C34B32E5A42AA77479811525A0CB5141B8F7EC8A438A711A414410510414410560D41E460862B695C648227F7FDA7FC72AADC9D958846D6FF309FF0049CD896A0CC7EF3E30E12AFF004F745EB539177B7A77E109780A05464124CF9F3E9973F972922CD8B989561D72C36F100303D5FDEBADE3A7C92B5022BCBF40DE1838CDE36FB6B6548F0D321C4A89CC1CB2F39EFD472269D230389978BF9A15F4B92439AD6BEE96EB1B4A1F2D41CD012E06B959DF96A6F169E3BB3CF63AFBB657A8B6770479A710F5BAC152965C6C89283EE9851907D6A5F68E0656D0C22E44C46F132D40821F22053ABFF6F162C26D64480192833014FD4431605DB514B59F5D390BBCED96C7370FBE1BBBEC45A5B3BB4C5EE9B187DEB69526CF0E52C00B4DEB86196FC57DC096C8D4E4649AF9B7F1B7E10E315B5F13B4E525A4EF2D4285B95B864D51DBD11E10F14C8998144B0C16000A4E85C5F893972BC64EC531469DBC63F95BA8711E1B4ECB64282D2EA12B49491120A4F5F3AF0FF89E51D8D889926602E85148E2DD069DFAC742C1E2062929B97772CEE0D998E86F5E10F7F18AB85788E4A565290A072208196BD62738EDA455490938D4EF21C82F703D1F2A67931D2243FEDFF4FD36353A0A03C0E674CC712E1A749C81CB399E594E79FCFA73AAD6D952F0153BCE34FB0EEFDE911F3B0C50A2925CD9CF0CC77AE5CCBC3A0F1CB3CE791CBACF3EB9EBFA536C0CF5626589801A9B171CCF2B5A9C328752253201567964039A5A1E36F19D4E99F7CB223EFAEB52B2D6A04006835B06AFB6AE42B4817298D183BFBB5FDF37CCDC840824C8CC4E9EBD4F6E644CD4AC9C49481EB6B65DFA529C58CE4D1C0BDE9F7F3EF126CDEB41241041904401033F97CA633315228C61490C6EC286CD6A397D79B5CDA3A6A1CD081C39B69516D224117CDAA08E20349CB5119CC79CE7EB4E3FCE4B80F56B92C6DC0E9CB943338770E01A92EF7AE7D3434E90E91760F2313D33D3B0FF0073DA9DC9C5A580A1275E15A55CB54EBA3011AAF0E4243379F637FC3F387ED3A1690648D753F7CA3BD49499C0B35CE6EC03396CF2E875A886A431208AE60C384852B457C499F9FEF520858A3B1247507367E7EDA34514A6E9F20DEFCE1276E034E14C4981A673D3EF29A426252A39823F5ECD23644BDF4024917E63837B2F0A25D2A12065E47F7A4FE582F7A5EDF88C19605DC3F11F8F75D0C2A1E200100C7A79567712C2A789F6FE4234F941DFB1B9FB7F51E195273D4E7F3AD0A085820D01D687DE543181F4AAB56D3945B778DA8DC2C83CF4E5EA0919F5A4A6CE480451C6B7B3BE6C226F0CA48949A3DEA00AF57AC462D0B920900721CC91D79FED51F35495367EF30E4728426618AD6A21EB5A1ABF7B71F286E0381D25C292DC0084A7946B97DE51AE7484B1B84B92CE2DC1D9E093226C92FBC79B906F4FBF631058DE1F638A214CBEC8532A10414827969397D3D0549C9C60401BC016A55ADCBD5BA67160C163A7482085356A145B36E35A07E3A55F5976EF719B338E3B746D5BB965C7408E04A12DA55C3CA0729EBF1A79FF00714121BE9A56C071E4F4E6747A742D89E319D83DD1366380DFC4D5C3F37F77A46B2621EC8370EDDADD62F8A5B5289095384119CE7EEC4F5E99D657B450522A2BDF3357AB7BE7D6763FC59C2E0D094CC51A001DEFA3D7BE94E30F2C7D929C438CF8D736EB4A0FBE56A25644F972D23E191A6AAC6855986957E1C39E5EA0C9E3BE32E0A7CA32E5BD410F41DAA4F3CEDC6362B633D9EB65F035DBDC780DAEE5B852961283EF01391039C6667B742115CF46E9622C5F869FBA1E51C9B6E78E66638CC32A6A92953B1DE6353570FCCFEA873E3569658682C30829E0425290008C9207FAE9D6A03138B44B9A4A8B819BD6B5AD0F3CDB368A64CC5E231690B98B2AE65D4C4E7534FEAC21EE1AFB6C073C549515FE58823312013991969FB53156225E2C89680429D83655B3D7D2AD4D0D7F152A615956F11C9C963A83C7DEB61EF676F86C86ECF6BB1568B366E61F62B4FE22E3DC2E9B86DC6D3E12841570A8C1D62BA3782F62AE5E225CF56E9485051B937D326D29E71133C94975294F50340E35F7DEFCFEF629F6ABC3F753B27B6F8A61FB3B88ED0EF1768EF880ED9DA8BAB7716DDE3C18F1085070A5285A44E6400790AF69F82BC6F81F0E61A5A6784BA11761906A3915E2FEB5E7BB7F64AF6829C12525DC3BA4E8E3576EA6368D9C2FDA37DA2F13FE77BC8C69DD8ED9FC45616CE0B82DC5D585E30C24884BF6EECA525C4F091C8C9390D281F103E37CE5E3662309885A6539000511FEDC803C433D468F0C703B1918597F2CA522F972D47EDEE1C18DB2D82DCA6C16EEACD0E1C370EC5B106D2957F37C4D969EC4BC4199587C0078A46473AF3178ABE256D2C7159FF226105DC95927851D9EF47EB5112F2F00898A094A149ADDBE9367761620EBD6ED78DCE34965F5B96B7B74A57BA1285B92CC0C824091EE819013CA04E83914FDBB3F1138AE74C5A8135DE24FBEA732F60D3B85D9492005212025DE9AE741DDF3ADA1156D23CE0F7D8B4E28C9C4A7FA82720788C67DA35F854CE071F805247CF92925AEC1C1BBF4D444A4BD88CA13113266ED7E97A11986AD2FC03666B0D5370BB9578AE2CA8AA4EB33197C8683975AAD6D19EA56349C2AB764B80C3EEC776D4CDE99461783F94ADD0000097767D437322FAD6249A6ED9413C62546072CC7D67CFE13562D95890129138953E46CD6E0FDE9E51A2E510E52D56BB9623F2FADC3C78B6C2544344840D04C7E9F0D2AC8B99859B2C83287D4340E3A3BEA1AB9C6C896581FA4645857DE77308159491999FD3EFF007E9558C7E064A945494A5817A8D33A574CEFC214DC2C6B5CB4E2F0A22E0275981D4F799E71150F88C79449560A4D1767B369667BF9718AFE27013264E2A06E5E9F6F60F3B05C5EA0260851D7BCF6F53DA3AD57D5B371F289C44C98A29772378DBAD8B11A3E4CF47F879265202564DAF535D3D8ED9C95A62B6FE33368E5B5C2D170875B52820147BC929053AE401CFA537C3ED9187C74948554298D58B83AD7AE5D03445ED259099891BAE59A976BF96675CA312EEFF1373751BFA7F67710BB6ADB6776E1D4ADB507382DAD956ACF8812B39252A71C54467C4A98CF3AFA77FF004BDE3593825E08E2541481BA0906E3277E2CE6BCAD1CCB6D23E6054C4CB1BE9A25C6B43D1AB5B1A56B1D4EC32E9A36CD80B4A894254983F99244A543A820820F39AFA7F83F1061F1F85978992C10509B35683DDFBC731C5A0FCE59C89A6B76F66CD5E53156186705104144105104144108A8428F9CFC73ADF786E367FB778502C2535CBDDF2D229A6B3524BF166E8DEB942714A913273CF9F2E43A5353F4D48A8EE3BFB31A2D05E82B98B1868E351390F3CE79761A79E9583894804B81467E85AAE6977FDC6A2528107773BB569E768E677F11CDB0C0F07DCC6D1E1D890B773107D36E709B25709BBBCBA43E92836ED932B0CBBC0A5F0E6919F979F3E2C4F9733033904228955DB31968FCBB476BF03E0819067EF2895EE9097A067BF03E7A472EFD94F7E3B59738633B17BD8B7B7C2F1A59745862AB4AD9F16D82CAD84F8CFF00BC4A58F0D10040564328AF953F13766CB99B467AC005D6A3AD09B5BD34B8CBBCEC492C25BEF53270C72A81AE95B51AF1BE7637A875A43ADBE5F6CF170BBC5C41624899C811A11CA32ED541D958444A400774024DEE2ED4BE5FA8BD26480809005402F571A64C694B0B989C6EEC04C0D7427940EB3946703D22AB9E2BD9E89A8580CED7E3477F4B6552222F17860AAB5791A65D2F51FDC546F805646349CC881CFB7FBF5AA7E100C3A0201AB97007134E4DE79BC252E584CBFA921C700FA0E95B707AC3B45F080273D73FD7B7EA741CA45130383E791CB2B7A084A64B241296B8A5B5D2997E9EB0F9ABB0A0924CEBCF9E9A6A7B7FBA7489A1C54B771F815FEE23A6C925C1A0E1EACDEEB687A8BA190904E59C9E646BAFEBA74A7B2D6E1F7806B3963D7D3F55868AC31277999B571CB85EF539DDA241BBA1C2923E1F0C867FBCFA5644C014E1C936A023A5B5E6611128824D9F5D2F461687EDDCE5F9BEFBE79794F5CA9EC99C090D716D43DC53D7F508CC94452A470E9DDBF312B6F78021327AE5273E5A7FBA9A913451E8783E76E3EF50D0D26C81739817BE7C06991E31248BD498D27439E60FA1E7CA2A5513ECCD4B3D1C77D3AC3432C66FD7FA8A16B4B8B9009273CFAC7A74EFD666B2A9E1CD09E34F7D237480031CACDF77E3A43969412224E713DBB4749CFF007AD7E790F4BDE9FB84964166637F7EB0E909073398E5FE7EFE5419CF93721FB86CB98C0B676D7DF1FBC2B5AFCCFF00E6F7D61A9984162F5D2DD33FBF3881BDFF00FB0BF4FA547CE72A249046447DFAFEEF13D842F253C00EAF58897397AFE948C3E979F4FBC377397AFE9442910F73CFEFFEB4411EB6CDB2DA05680A590413009E713F71442A852C00C12D567EBC5E115DB594FE448CB2C81F9E5F4A216DF570F388F73094B8E179A4008511000E913CE338144604C228E09E37AF5F7DA1445BF8060888E7C8F231D873EF44677CB3325B46A5DE195C3216EA960483107D35C872FBCAA1B1D24A86F11ADA84BBDDDBEFC1A24E44D1B9420062E2A03F4C859891D2156ED867967A8E7A89888CF5D341DAA1F08F2E7821AEFA675AB59FEEF0DE74CDE71955CE7C75ABD6343BDBEADF686FB61B67300C21D72D2CB17BFB7B7C49E6D4A6C2DB5DF32D80B52722085100284679F4AECFE1ADA2254B960AB404BD2EE3B72A9882C5A86EA998DB893CB8F95BAEDB6E13D983763BA3D91C1EE5BC399BFC5EE6C2D2F1C75D6997125F7196DE278B841FCEA3CFE3CEDF8DDB72E54B24CC724506F123A720F4D78D22B6B5CE9D34A10909961F7CAA8AAD8A69DCB3F3778CF78A63F6CC214E9B7658B8094A421A484A4250385B006A3DD007D00CCD71BDBF8E189C42A606AD28294B5F53CEB7D21CE1B00508A954D00BBA9CD497356B062FC39B4639BDC7B12C4D6A6DB754941910091F08F2E5DFCEA838E1BE556A963C789E2E6E35B5225A4E0C862D42CC0587BAE6F720521807EE6DE1A714A52D2249CC9839F3FDB23CF5150A6532AC75ABB6AE78FB689AC3E0F7402E920D9854FB2F9BDA3DFC6BA3593F2CBAF3D396835CEA4244BA501B1BE7719FA6A748999787DD4821346E8697B7AC5DB85BA576CD2944E7C53D400A3A0EA0F5EA6293561C99AE1D9C06722AD9E5ABFF00422BB8E4EECD239D0FB6D28E4C5C4C3A32391E93CBE7A8F4CA3BD58307240DDA0B5989D7954B573FB3121C343A99CFAE75341C000E50000504325EA3CBF534CF14CC5ECD5E5F4C6628FBFBF8D5357249C715815715FCF0EBA3EB1B265A58BA5B98D79E7F98F2419CC65AD48ED29DB982292C193471FA61CCBD60549770C082E2CC69D2E215C26FEE9DC41E64320B5625210B293EF78B32674C8FCFCC57199F8829DA454E28B198A07700D5FF004080F5881DA1856A549503571CFBB659D7478C5FED13B2371B41B2831CC19D533B47B3AFDADEA5E68F0BDE125F6DE7405247147828502274E55ED9F81FE269782183056032902A585C020F534FB6747C7E08AB788723EA7A38A70F77B3D6378B707B7B6BBC7DD86CDED8DA5C05B86DFF000772D85494BB645368B2A03FECA6D473CC99F2AFAF5F0EB6AA369787E42C4C0A2A407AD7A8E1D1F23AF24DAB855231AB94414073BA45055CE9D5867AC6CD57A062BD05104144105104141A0274821051924FD690DFFA9812E6AD90CD8FDBBD2352A0FBA7CEDAC794BA405B0362EFD1FF0010A01F533F51C9E1A2AFDA4AD6C702CA9B8E22008CF3C8CE7F7DE9962C7CB04873EE8F5E1E6D95551294B248200701EB9D3F1EE90DD58836A4DC1085245BA14E28AB294A50546328D07330488AAA62B13B8953920A4289198B97BF3D3CD8AE65A9050ECADE20063992DE5DF83C70DFDA0308C53DA3BDA57F97DEBAB6363B6096EA2C6D41294DF2EFADA1C55D20CB6B2CBC9E268A47BA60EBAF8E7E2DF8C932F1589C31994015F4EF3B1008B3DB5FB08EF5E0AC37C8D9F2F7C0DE6AD8BB97626E6A6A1F8F18C3FB47ECDD6D87ED134AB8C47107459B9386BAD3A14E24982A43AA2326C1848098F7644D7807C73B6133B1335654F551777ADC1BF0FD523AF6CC98997BB5A8636A6552CD9B9C890CFC364366F07BFC2708B4B2BB536A7D8441282A28293920E9255C31C5AE7AD72E46DE4CA252179977229DEBCB99D62E122724A4070C33353C1F5EB5E81A2E24F1A44127976FD07EDA74A8DDA1B6538896AFAD2487A3BBD5AC09CA8D946D37FD4FFC7461EFB3B738F0B2E2A1D0A002B91999F211AFD67388AAB9C4BA94AA33DFC9CB1A3C315000D81072FCFA884D771E0E4A24C69C267FC73D7B1E74A2279A90A26D6B31F75AC69B81BF8D356E3AE55890B6BE416D27333ACEBE7039FD9A7A8C4501053C43FB670D952BC631FE3A540BB31E845F36ABC48B77A88E6077313F3F874F853A4CE71424BDD89667FD7B1091C0D281C7176E7D1BCF263128CDD254849139839120C41F879473E94A267310C4BDEB979E6DC5E194CC2906D6E4FD2943AB5B330F9BB94C6B19794FFBE733DCD3C953C13A72B1CAFC1C5FCB268A95914039DBF421F35789809F78F48EBF796524E7533879EC0390DA3F3F400E6C0D2F0D26C87FA5A9C8BE5E63D6B9C48B5700C448EBE7E7F1F873135288C40342486BB1A7BFEA1B2B0DBA93F4853DB5F327F5CE1E22ED2980788EA2674E739E5AF3CEB2B9EC7F950330259ED5E37E1AD2F0CA64920B817C9A9D19FBE6F0EDABC40000E2275D75ED964639FAEB5A0C439FE56737166AE74B65DF46EB9248219AEC452CFA57F6CFA44BB174D142409CE7F365D7B76F8D6558A2C18B1A66D72F91FD00781762B94A62E03E5FAA7A4394BC8509063EFF005F856AA9F675543D01704F17CA9701AF0D8CA5120EEA8B543547A5CF768B7EFDF425F58E6408EF20E7A9D23EF3AD8AF7EC4E4EC4B70A74ADE2C1844BC9045F3ADFDF488972E10391CA7E197DC510F100877CDBDFBF3868BBA41204191FAC511BC34710A767872F3F4FDBD28821C356E80DA78BF3738CBE7F7E7440E0355B480E1E16A8C8039F2D75FBCE32F2A23054407A9CEFE7124C36DB2C2595092999F5D2328D3EC5109B2D4ADE0A2125E84FE2BEF8C475C59A9D27878403D49FF7A7C0E9D688583EBFB6B5BCB288E368A6D5C2AE1319C8F975EBD49CB91ADB13212AC31555DAEC694CDEC4DFCAAF0B0C46EA00722B716377E197DA164A1291A09E754F520CB9C9235AF0D1C3F2E0E2958426621C3024358D3F7C757C9A310FB40EEE0EDE6EDAE1092D0BBB2BAB1BAB22278D28B7BC6DF7818132A4A2044F43578D97354896921541DBEFA6BC223664DDF514545CEF1700F7C99835ABCA32EEC86D17F37D8DC1136CD949366DDB25C7C43893628432EF11131250784822728A4B6A6D39A842920B8B67AF46E8C2199900CC0B0A502FFC41649B0A8F4CBD623B107AD6E5C5E6E2F382A519929C95E920FCAA9B331866A89726E35CEF7E5167C0615E50243F1CEBC8699E67388A6908615C4D0CE79F4FBEB1E94DD52CCE340EF4A5D9CDE85BA5A25E5C80C10121BFF217F6D5ABC2CA40721C580547398CC41E607D018EDD7518204EF29245F8335B2A55DBD1CD17004BFA40492D9FAE7E86AFC63CF01BE9F4F2E9D2B7124203311C68077B6B9C29F315C29CFAE79E7133689E06D0907213CCF53F79C69CB2ADD321D4E41A376CC598D73115DDA65E6D1201AF2341DBDB9A44F5B93A8F21D0CF3F9FD6A670B26A29A92C3D3BDFCA23A24D1A791A7AA4800D1886FC7BEF7821AB90083A0EFF00BFAD4562177702C79585FCA99C108ACC0D0CF2EB974EFD2A0D52809A565BD2B933166CF9C3A4A5CBE432D6FF00DC362E01208206533239FC39F5F86B50BB63103E5290E5D8D7CA96BF1E42D0BA50A5073BA34D7EF15B37EE5AAD2B65290858578E63DF24084441CF339CF2E432AE458C49FF0024AD2186F397B9ADF46074D4E50CF15864A812A033624DB50347B5B2D6B14D9B571892B106AF54971AC4187985A3320A5C6D4DA723AC050991EB39575EF03F88666CD5E1C15EEFD686A961F50F4AB7E1E2AD8CC227EAFA458D8703A52AF90CF568B0FD9331EBCDDA6F276F373B8A5D04E0E8B9B67F669BF10F02BF13C77777E18510930A589E0CC1F39AFAFF00F00BC668C56C0C24B54D752928497232C8BE742F71DDE394EDDC0033D4B523EA0EC5BFAF2D63AEF5F41A394C144105104144105609604E81E086C5414A206467A743A799EDDCD343FF00BC6A0FB8673F878457FC8E56FCFEA3C518498FBCE9F4914E9EA4FE217921C025E9F9311EA6D2975C75510A02644CC40EBF1FD269AE3801289CAA48FC1D783BE74021F8A25290EE6F7677A76E2CE6DC2CFDB4BF1856018D5EB64A549B37CE52238585F4E7979EBD66B98EDC9E5089CC48FA1449E878E59F0A350BC8E090662E525601DD26B424B90731AB5F83691CCCDD4356588AB17DAC712955F5F5E5CA5D5C02A2597DD6D3EF6A0C0CB58E5957CD5F8CBB4272FC47899695AB777D4C0167A1CAE6AF4E7725E3B8787E684609296C870ABD331703A8222F5C470DB7C495F895B214E2566094CC4188EBF4CA72EBE57F11E1E74F4AD6497A972795EADA67D62E586C604B7D4CCD98AB57ED61ABEB0DDFC1028173878652204690398CBEFB5719DA089D2A6299C313AB54F1274C998F08B2E17690A00A532A8EED40D634FD45B17964193040100F4E5DFEBA76EED70F2E6CE35A825F8FB2F406DCA827E562C2C0726BC7866FEDAA62354BE06C27A75F4CC0EBE7DB3E55ACF0A92B292F562C03D40ECE33F485400B5125C0A7A33F4881BC7413CA679F4FBE7977CE45665CD63987B81E4783F1D0BDA1CCB96EA029BBA9B5AFF9FBC356AF3812124E63F7D4F5F334F11345DD8E9996F5E196A61DA70E0B101DF3D32CADDC3DE8F0FDBBD0AFCCA811A93F300E59C098CFB9D69DCB98406714B17FD8B37BCDC9C28091BA05726FB5B958359A82262DAF416D2388F38CF3991C81EB3F38EA326794B3392EC4EBC49776E3DE223172B72636E8A52835F4E36E3122DDF640A8E5A139E44C67CBEE29FC99CC41C8DA9CC6AD5E1E511D324850702A323FD39E50E917C018E2CB9EB23319EA6A630F3892C72ABE5CF5F6EEF0CD72B781A116C980CA262DEFB2199E5AF78FA8CA474A939739E9F503E6071AEACCF943654B20B338399B7A7DA1637C028C100E53999F4C8C4E7D7AD0B985C392F5B7DEBEFBC64E0C285535EBA51EEF91BBF1061D377C081EF721A93FA7D6739D2693336F550A8ABF2BD7A7286D3304E480917A86B7603D4D75CA45AC440481C5A6B9E539763F31FE76F9F5B06F3ECFF7867336706074ECDCFCBD987EDE240089F8931E79447DEBCB22702CD57FF8F0C8DFF3C4086EAC00161D48A7EBAD32CE185D3E1C714BE67498CBAF79CFE7CF9C8C82E9F7DB4CF81E79292E58969DD1D6235C744E7F7E67A9FBEEBC291EB69E3015966796BE9E7E74410ED0D1CB98FB39988CBEFB9042A4418A21BA955739F97EA1CA3F30F5FA1A235F9838D32F6605FE63E9F4144642C6448F2FD4534463E6F151F7CE105B3C6A2A024E4797974D7F7E666A41697C29A3B8A9D397E6ACCD0D5734905CB0CAAD4BB77F79C79F86FF00C7D23FC7DF5AA74D40F9E684D49715E9F807C9E35130A894B8C9ABCADA583FE690A8B14DEDBBF6AECA982CB8953660825685465A183F09CAAD1B3641296C886E4DEDCDEAF7AC6AE5F526952EF97703CE30CEC4E38DD95EED1EC6A8F05C6CF3ADF829D14A17CB53878473C959F6A63B5F0CB014F6BD3DE95A178D92927871EB945E7F855B1FD3590A503C52733EFF00BDDF406A80B5FCB9C47F17E87DFB348B66CEFA64241CA84B71A574D32E791E1764FC3FC54CE1415B31622A479BE61AB4CFD0C86F8073705A90A04802201F4A9712A868321F904B5FAC60CC466A0F7ADFCE00848E533D62994D9612FA1D453D83EC504682725CEF100017CBD7D9F29063F2A2639C41C8EBAFD08EB4EB0F237D20DDD89A56BF815B31ED1018C98664E5682DD7A0313D6DCBCB4E833E8627976D2A664C90801C574EE0D087AF38690F0B9C23873D351D67F6CBE149E24356CFE6037DCBC10C9C7323973FD797A49FF5355EC49604D33FB7BFC410DD4E8EA66633F8F7FDAA2A79694559B2892D9BD2DC5A0FF2025410E6F52E5FB701C74EAD5C7233275EF33AE79C7D39552368CE2A252EE1CF50ED7ABE46F0FE54F490C7DD6F7B71B7DA85105B047AF4D4663AFD63D2ABCAD9C66FD6CF9E55604E4281D9CB5E9CB49CB1BA4920BB3035035234D49BD32CA6F04FF953E71F08F9FF00AE5580A5E0D48209494A833508ABE5E5C1AD15DC496DE21D4E7E902E336D3AF9346A6FB495CE2BBB9DE26C0EF5F034ADBB7C26FC338F968101D45EBACDAB25DE18E2090B2654401A7427E82FFD3DF8C97270D8390A9845500D7FF21DFD98A2ED8C37CCDF3A822D62416D73D1F32F947786BEDF479FE0A20828820A2082B04382350D0423E17BD20FC7BFA521F24EFEFBEA18FAD3DEB09A90492411580B64822467E7FB5390BDDDE24528CDC183DF8F0B7185659DD0C47B73F6310F7E16A6DD436616D14024E878950207FAD79C0A678D5FCC945097048CE8CE5B2357FB71877267A10BDE5B9B51BD72A458DB75875C5DECB6376DC4853AE61D74A46A724DBB8A39C4FA0F2F3E79B5F63E23132E7310C50B26A43063D4D1A85A99449E1F1D2654C4AD2183B119124B0E0E0F91E71CC7DC03CDB78662D6B700B86CB10BB45C30982E33E2DE3A10A713FDA15C8F31074135F32FE366097B3FC49893313BC42D5E635AB3EBE6CE4759D838C97330882924067EBF8E71B14E58DAB0FA2DB80C3852A4AC0050A044FBB9004A4644472CC579A76A6D5C2CC2A925237AA0D85EDF7BDEC0DA2D322715A4A81293902F6B56D434A5BCC45388336E0A9B42488033CBA7F831975CBAD4713E1DFF00B8952E58649ABB55BDFE844CE0D730A52B529DC9601C677FCB77D31BE3764A3C4A052224C73044E9F5D7302321155BC4E1E4EC452BE724109D450BD0655AF0D38C5C301342C01F507FF769970D39B73118DEF1F0CAD6D282894C024091FEB9FE99CD53F1B8A463310664A1BA1CB3160CC464387BB0B4C895BE9DE01C3E59F3E16CF567310370AE324E639E7E83989E5FA69AA2896A772483AD7D93E50F25C95381666636B0AFBCF867185B738894A81132333EA0F7FA75269E4A965C1736CED5CF3BD80FD987F2A5D1B93D7304DB8BF68593C7FDC72E93CFB7CFF6A7299643D546B93FBF5F387E84B07D4797BE9A4485BDC708824FBA3B9D7D7EFAD2C990A507DF23AF5D38F11D1A22717277E61666B55F83D439F489469D2B88240E84FEDE5CF97C9E4A429000FE4033387CEB71AFBBC46AF0E6AC017D0575191BEB0F1B5AE75240EE7FCF4F49EC2A4A4952581CF9BB072D7F2CBD192F0C5D8BA6DAD7DD0F0C8E92F6EA591AFC7FC6911D27D2A5252C30A87A3D6FC03D6D4B521AAE42F7EC00193776B663B8BC39257248574CA4FCFCBCE7E94AB2D44AFD1DC9D7A37EF285D32C0480454660DEA2FE74ED0B0714343F7DF38AD0DAC08CC1F7F68D572C2ACC3EDCA86164DCAC0E73D79FD72F81D3CE912B50140E732F5EE7EDFDE9FE383763CCFE0085917BC3C8F2FBC8E83CBBF334899DBAC2C43BEB93035D350D784578601CD0835A0FD71E10F5ABB42D299E2988D3A73CF954DE17100A035F314278BD7D1A9D622E761F754D501DDCB8BE56BB5FA457E1970FBAA10399C819FD75FB9A72678D5BB76BFEF8C246436BE9DA9F8891B76F85213AA87EBD33FF005F183FC814FBB57CC7BBBC24A400D56E7D7417A5A251A64902018E53E7F4CFB0AC89FA8FD757D783C375CC4A417E36FB711083EDA90E28149F203B0CBA65F79E547CF72CCDCF2E758899D8D42565390D6F09FE2380C9428913901E87AF5A772D3BE01D74CB57F7EA23418C41661424F1FBFE383C02E02D51C0A493FF006FF5DBA7952FFE31DD7ABE999F2BB369F78748585B0B12F7B7DE1DA1A52E22339F9524A94437DF3E4C215DD6FE4F5B337DFDFD9EA1809480A20913A41E87FD7FB9DD58A4A257CB2EC5DC5B577EF91A68623E7255BCC0B0F798E87DD28586D133FA75EB3CB9F2390CAA1BE519B38A85002087676E2C3FA2337AEA90C039248776F2A97CF3F21482CA6CAE8DEDC00BB27213E1A3374920A678498804C933A0F302D3B3D69414A480C5C16C88033073CEFD291A4D5AD52CA65969818825DEEFE63B738D24DBEDB9C0377DED43B33835F3FC09DE2FE2835C0A486D2AC3ED429297E620CA804EB988E8697C66CF998B973264B49284B6F100D09B7986AF28565624EE21DC29EC431A5E9CF8756AC6D25DAD0D043AEBAD2D4E0E24A50A95709CD32239A4F7CF9F3AE678FD913118A2681CB90470CACCFDEDC4C5A701894996135B0EAEECD5A8EFC018669BA64F17BA470827DE033D7439CFE952182C27CB29DE5001AE4B00D6AE9A30E62D12C10660040234CAF47D1B5D3BC3138A32501C436EAE54470240E210634FBEF15253664B427743161C0F2AFBE1902A9C028D4A9406AEDD731D61C33749791C7E1B8D8E8E260EBDA6A0F138A4A7FDAEC6C050F0B5ADF624C36560940D161455672EC03D7AFBA449D9BA16522149CF22AD3C869DFCB4D69FE071682907779BF17FCF688D9F832164A957B36A19F5A56F9F289F69D6DB4F115A4F380738CE7EB91F954F4B99BC90ADD773A39F57F7C5A18AA510696199B7714FDEB0E53C2FB7E236EA013AB64FF504728F4FF3AD23889732623E942BE907CDAE2BA5883CA90D953128594281E7979B7BEACD16D393EF24A0680AF248D39E9F7D6ABB8AC36254584A5B1E05AE19F8D3B5612389402DBC003627D7FB0DE6611530A0A212B43875F70CE7AFCB9C7A659D456270D8A5A0A132261CA8836CEFC1AE7CE3230867B4C133753715A7076E5E9788FB9429912E10913A9C819E7E9CFA4D55A7EC4C74C98E30F38392EE93577B8A802DE54021CA6589742B0C9E3A59A9EF9C38B6426E5A406DD6C83202A72272E7E9EBF0A5E56C6C52505270D3778D2893DB8BFBAC213E724024AC07C89146D3A8725F95E2EDC1F09750B0A2EB5CA73EDF64FAC9CAA2B1DE1BC7E20B891343116496350CD42F5D7FA82C4E20027EA0A73FED6D5A96D4D3FB8B6F7C1BBFB4DB6D8AC5B087956A0AAD977AE2EE2238AC10AB96F8091AF13606712623335DEBE11A71FB1F13864CC9733712B41208E233CA95D32A8885C60F99254776956A57335B90CD901DE3A7F5FA248F3641441051041441051041441056ABFE27A7A882193EDA65797FC8524C8FFAC1EBD7A7AC9A6337FDCFC3D4379460F0152439FCDB2E3C9A22311B5172EA6DD79B2FB2FB6E03D16D9466398F7B3EB4CA700A95301762936E51906BC88E5F9F28E4818DCFFB4D6D5EC662292D605B7EF32BC1D6E7BACA1766C179DF0C9F7412E2B329933A8D4D7CFDF8EDE145E336962B13B942546D900C2BC29C9BB751F0F4E57F8682972D47009CDF96B4A5D9E3688DC5AA516CDA96953B61C456B541E20F105B20F4E129D7B467957CF4F15ECF3B3F1CBFA4277546ACCF5E6E5AEDA5EF5B8E1674C04925442B22FCA9CD8BB80DAC33B94A16F39CD27848F513F0A4F66ED02256EEF55B95B8BFA16D22CF849E7752924B55B2A1E2EFF63DA2C8DA048085102241FBFDFAD527C5A83890B533F27AF17B39E5578B161B1664EEDCE64E57D491E6F4D2310DF31C6FAD406A731969DF239CF49CFBD50F0F8764B171C7F5EFD04742D9988F99870ADE3567626E5B566A56E395A229CB52675075CF2F49EF3F5CA9F210ED635A119717A3F5E59C4BA660480A772FC185756FBF0A0864A678544427D7A67D2453C9729DB2CEF7A57D294E5AC3B97352D40C0B683576D7CA29F0BB27EFD29EA25B5198E65ADE97872165550A3DFDFE22B4359E83D34F5CA94F9645037BE548673D637D8DC69C75B57FACA262DDACB4F86BCF4D7F7D4F3A70843007B7ABFBF5864B5B3EA7ECD7AC390214B1D08D3D69CA406043977A8A80C7EEDEA1E192CBA8D5F4CF2896B6E5F7FF006A7D2D0C904DEEC3BD61AAD63789A97F76C9EF0F29E243243FBAC60170F0526BFE47DE519829B1A13CCC1053199FCD5CE0855B742541249044E7CB49FDBE039E54B4B9E515A002F5AF419817BEBD5BCD92958AD40A8D47937189961C491131FBCF5D233CFF004A9097377F3A6751A52BD3CE2371092806AED6E00E67ED6E222E9B0B42EB285C4CF4E601EBDE239FEF272249981296724D1F2A9AF3FC1C8C40E2715B856E5865ABB726157AF9C4FB162604A7A1CA472063D7EA7BD490C0934DD069907CB835B5D2B77020E763807482EEED50E2AEEE69C69AD844B23096D684AD60151C8F5CB9E79FC63BE7AC7CD93F2E69435F30DA3B7E3AB06110F366898B726996ACCFE8CE7AF086AE60CCE5EEF6E5D27D0CE5FEAA5B0E96003529EA6BF9E3485253D1C9AB9ABE9FA7885B8C3421F52909F76004C0EDDE7A7CE9FABE9431CDF7BD6E3366F3D22770F301483C18EB9559BBB79C3450F0647965988C867F4E9CA34A8A9F340A02ECE031AE4FCABF7BBC48865243D7F3CFEFA455E3712667D0647EFCBA9E548FC9F992CCC203F70C3BDC7A738653D20ABE9CB8BDDB9FB162EF0D9C741CB2806013A1FDF4A889D3C492524B35F76FF8E57A563544A2A06EFD5AFC32D7A5A1CB0B6EE91E0A9400642811944AA639E7C8C771CAAC9B1569C64C4246EDEB93B8E635E3530AAE40975DD2EB66A529D01CB8C7CC77F14CDF9E27BB9F69CD81BFC2EFD617B118B205CF86E194B589AEDD242A22006E467CA7B477DF0B786938FC0E2F086582B9E84AA5AC8000DC054412C58E90EA5ECDF981134A084E8433F3C9DED51C23BADBABDAAB6DE8EEBB65F783865DA2E19C470AB452836BE21E236C32873249227881273D7BEBC3FC73B226ECBDA139003142883A79778929527E54C1282482681EC5B4E2332D4E4F192090EE182E90402252AD44C1E13D3420FC338AE4D8EDB0AC3120120A6843BBE4FABBE5DA26A44D32D5BAA72E29720357F41B37B88696D6A9504BCB2A434A909520C75060F98EF9FC9BE0B6A2B1AB4A12B2497CC16E9E553D21CCDC6EE4B2CA049B05337170F4F2B4480B1B8B53F8AB4745C253EF78774A2B4FC04F5F98EE2BA1ECAF0CCEDA094CC082ACD88705CE74EFAE4E5A20B15B551BAA4EF096A3729A372CABDCD6E6E9BFB5FB376AD78B8E5F5AE10FA5243BC4EA18B64C12014851CA4013AC98EF13E9F066293382132949723F8A481E9C34E4F1569BB6D3281419AA5EE9242965D44939B73A35338B77FF0077B77CD2D4D5AE28DE3CE03019C1DE6AE5E39CC7083A9CC0D64D744D85F0FB153F70190A24B0FE3DB9F3E111D37C409208DF14ADF5D756FB5ACD01886F796BB95A3677775BC3BB7CF086DDFE55C76AB3191050734FCA39E75D5F66FC1D9D88097C37F201C14126B6A31A0EA5A910F88DBE92A7DF0791C8D296CFECD488C5ED17B4A6D09E1C03774FDB30ACD0717C2AE90424E93C32272CFAE7356D93FF004FD3310949FF0012EC7F8137E9D9C6778889DE25912D442E72535A396B86A9A5BD9AD5EA775DED7F8BDAA2FD8676570E75F9E2B47137CD38D41812D819150CC6798AB76CFF00FA6DC2CC94F370690B0CE4A0022D67193B75B8A3B997E324225309A9292285DC16E2F51D351530DEDBD987DAF76956538A6D36CCE1ED4C7B9777AD40503966201D34D7AD3FFF00D9AB03BC01C1CB482D532C7FFAD5C3F5F26589F1B2508514ACAC8FF6A4BBF4773C47DC45FF0084FB126FC5BB768DDEF0E2E332E0B3C56E3F0F9CC16E53232D7F5CAB63FF004CF8100B616496ABEE25B90FA6BA655D33819BE37132BBD3522B42C08D2E696B5ACF998BBED7D8EB7CCC883BC6BA911A628FE79C83F9479721DF5AC7FECD18225BFC29433ACB19016A1AE79E5C1E317E2E249AA8825EFF0082CFF9EA6D6C4BD8B77DF89626F0777A37EDD884F86EB2318B808536EA7856387860852499D35E82ACBB13FE9B64C85A66A30B2928490412802D95B80FC55A1F7FEAC4AB0E874CC515BD80B87BFEB9DDE3AFB5EEA8E530510414410510414410510415AAFF0089E9EA2086B7124122252329EFF3FBF8B19BFEEE9F682231C5388B76C28053CA2785799004F3233CC72E94CE6BEE299AC6FEF568C8B87D6388FF00C52F7ABB3BBBEDAADD6B96AC5D39B6CBBDBAFC2BD6012432D8758FC42AE543FA890599E18E8794D79B3E2CE1B0AAC3CFDF03E66EA892C1F5CF4E9D5ABD9FC15B2E6E2704A9CC0C93BBF281077854EF026D5398E7AC65CDDEEF16C36EB6630CC6F0AB8FC4A95676DFCCD09585B81C4B484E406842C2B881CC19915F2DBE2761D29C7CF12C06DF351C4D45299E95BE51D065EC6DD5268F7BDEADE7622DADAD95FF009EB0D5B25F752E7094E6A104242722147411967AEA7ACF32D9B2267D34AB9CAEFF006F47B189991B294E027701A3839F6E3EB5D22C8C476B306C41F559DBDD34B7F4E04AD255C51A44833F18D09A4F6CE0B7904A810C0966A1FC37BD625E46CC57FBC2695041E5ED985E2DFB9B55A417142352126263B8E91A76D73C8D2578620B252284D142A75B8E00F23163C12C4A40402C2C374D388ABF0AFB10E4B6E15240854C72CF3F972EDCAB797870186EF30453830E1C1F8C49A2752A5F997E3C85EDAD6193D6F0E2840032D4769FAF96BE74F65C9DE4D1249A01981CE8DC8F387889E08A966E37AB52A1FA7F690B73CF847A034E938726C03EA5DCF973B08748C4351C97CEA416D0B8E7A7185516AB1052011DB9FEB97C8D60CB656E903B38AFE5B85A109CB04EF6F73D5FA72F6D4906D250334EBD35C8E91918EDDB48AD9282E1D8F0BBFBA43652BE92A0687337E9E77E25E160C29C25620054403AE5391D3CA9FC990017501C9A834CAFD290C674DDD0C286CD9BF11A0D3D6D0F5A49447167D87AF5E84D3A4A2B5AE9FD4332B2471CCFA43D4A4A9214220FC72CAB785E5AC04805DF5EBDE91413026915FF0023D3D042D14F18EFF7EB4D8DF3772FDF2820E34F7A6333F9AB9C10DCAD5F886D0028F8AA30672000CF8BA65E9F11496EA8AC685CDE9419F514EF1B9004B51A029A134715F3D22E8B0B65BE0F014FBA7324E5EF699F3FBCF5A90C2A14A50487617239BF60F5EED15ADA53D32D248CC540671CE8733195306C25E6EC99E25227DE397427AC7FAEA60D5BF67CA2C97A91600D07EDC76D68DCFB1D8F24AAAD90E19BB7A718B81AB55208E2E123E711967AEBF4AB3C99296714D5A9A8F36AD44434CC4A8B3E6ECC752097FEA1E1B67D49050501267224E711F7CB954262E48FF20B00C097A0CC163E8FAD6B09A66282805D9D8101F5CEFA72CE18BCCBC38812920EB1DF58F2E7D0C75C95932E9A6BAE7EB125266924390C2D50F415E86D119728096CF101C40667D632CA7BF3F5ADB10B094901ECFE97E0C6BC0F0892933095259C02406B5BCF5E5C1A2CEC4042A412069976C81D33F3FD0D5771130826CCF400D6FAB53A69C226654C06854406E9C8F319D43C44A6FDA6DF6AC940F88E85A92A3F97DC049063AC65F5D6A730E12AC0B9DD7637A9E47953D3842CB93BDF58766CBA926AE7DB5EED98C41ABB75E690140B0A09254323248047C33D34AE6FB5E62C4F5A52400F91625EFDAA2D47AC3B9528001D2406CDB4A75CBD28C621F1EC64E03678BE24B2536F8759BCF5C70FE672195AD01BD24A4A7DE274F4136AF07625B132C2D4FF005076342E685FB6BC8343D421139280DF5289DD24000006B5C9DB99CB26F8AAF6EBDB4BCDF06FFF007838A9755F84FC420308B852BC40BB36D4942923300F1B6082328AF6EF808C8FF1E4AD4582836F5890C7798926E07763589D932E504EEB0A52845D801CEB7CEBD23B37FC15F7CB8CED86E6AFB777B417EAB9BBD902B656971D52816EEAE1D2C8682C9221B48072E523491CE7E29EC1C2E2B6962276113FE8A80202D8A8A825CBF026C29C4B52313E5032BE61037D2A0CC03873EFD873D8B6AE1413738580A0A6D633232214A2A11A99EC34AF17F8B3654CC3CE58DD206F1A686D53AFEAF0AAE58090B60481FEDCF5D1EE6BDE13C5EFF196703C51BC0ACDBFE6584301C4A31042BC2BB2B495816BC32A594C7BC32CC8D75A6DE12D98B998B96ECCE9705DEB40D6D056D4269159DA139482400A21408DE4B306C89FBC6BCEEB5BDFAEFD715C4B0D5DF60BB2F6D62F29B76CD2EDC59E24B4F12802DB79CE499131911CABDE5F0D7C2523132646F212B2424071C017ADB3E0383C5036BE38E1A5AE62C929059DEBF51005C9CF8E71B8BB27EC2FB3B89B76F8A6D9ED7ED1E297AE2C9B9B07AF90F5982930021A7133C2A2339D743AD7A67667C1D938D08C40908292C689B934E3C3DB18E6BB4F6EA913968485D0515FED2E1D835CD6B9BD2367765FD99F74DB1CEB16D866C761EBB929917AED833C4484CCA9C0264E7399931D44753D83F086448521F0EE035D2185726D397EABE76F621614B52D2056809DE1C6ED52FC79659CF0CD8AC0B0D65B0C61564D38DE9E1B290948E5A0CBD79FC2BAEEC9F0260F0A9015252E007DE48C8532E178869DB56729759C5292ECCAC83BB87B7AF089D18724A4B72584447F408491D00D3BFA73AB6C9D818294001290198064836CEDAE54D4B988C9BB4C12CA56F914FA9CF5D32C8D3BC7AC614CDBA83BE33CEA89FF00F6AA67CC67E5FEE2909B83968594CA410336D45AB972FC42C3173152C268126A00C859868E21FA909223810465A8F39E823427CA915E1C9AFCB7A55DB203ABD3DB984CAD4EE951A8ABFA694EBCE17693C08E1002626001909E9FA8EB5812D219D0464E406A6B7E9AF184D454413FEE3ECFBBF584D4DB866081D3F5FB3D7E3B7CB4A88FA7300903234A9E3DE19AA54D2E778EE8AB3B1A7BA65DA18BD64B716D289013EF78C53F98FF00D6391E433E5E662D1853265482C9A32775C060D77F366D7842D2F18A928092E487A1B8E219D896E55346789EA46310510414410510414410510415AAFF0089E9EA2086970471251FF79F8A472FBFDA98CDFF00774F3682239E50532FCC715BB657DC0009FF007F6299CD2D2D674493025DC3B5C5B9F1EC3F6C3807BCFDDF2F7D7EDB7B518DE3A97719D98D83532D7F2CB9FEBD9B6AC4AC4B40B6CAA5293E280A3FF909D419F137C6AF14A70B8AC4614AC823783386B1D1ECCDFBBFA3FC1189972363CB4B805AD402EE4906ADA64FA3455B57BA8DE46C0E23885C6EA4AD9B7B3522E1581A83C1A7D025C0D22D99038E402003919F8FCF2F1763063F1F34BEF6F2CD2F57A357F74ABB45E13B430CC085A083BC1DC528D4E2FC5FCDA9D99DA9F69EDF0D862F82DC6C4B7B1F6CD2516E9BD770FBBB274F00285B8870120F1147171644C8275AD363EC733A585897401E81AF9FE6BA662A61F68E0F07BA9993F794B2774CD507357A13CF2E91963769B92C6B6230C38A6D3631758AE36A70AD4871F53CDA55E21C805C2C08239CF789A8BF116004996BB16A65462D7C9BBDE8F58954ED992A2109A519E8C5C6473F224114CCE60BF4BAEDBF1BE84B6E70C14A072190813398D67227E7CC66A01986F760070A6638E5911AC3DC34E48427754A50A9BBD0F1B3D6E3F5169B6D7F54C8124E51209D7A99EC738AD928208FA41E14CE9FBA7AC3D97354A2EF50C5BF23B7A8872F5B4AC98D6232FD60FDCD3F9325C5807A923ADF2F7CE1E89EC5BEAB5C56B736FB0A425F85EDF2FF00FE4D3912C3B96E82ADCF28792E6D01766C9DAE3C8F0CA1C22D55C2397CBA763D64F4D05349D2885BD0699655E7DBAC60CC4851049232A8CEF7F64E96854DA280399F847E95B4B95BA5CDF2ABB72F7A9A420B9A6C1BA1F5D7CA1C36C10800EA3969FA7ED34F522828C746FB4315A8B924BF2FEFEF48AFC0EFF3FF0014E25A094824004703EACFFA221BAA687D1AD7CF979D042C84F0A427A4FCC93492BF91F7943D45520FBBC375FE53E9F514DD7FC8F4F410EA11A6CAB9E67D608298CCFE6AE704327314B4B7B945B38A48B8585A5906388983300E663B4763AC4961F0A66201670D76E26E5A8789A0E2F0DF133D32D0A1BC58EA6EDC3EF78BDB656DEE4DAB9E28595A9692041260AC11944E635CE0F6A929185DD50200BE966C8356C598B5E968E79B6B68B0500482C43F77E347A072285DE33BDAB45AB76904442465A119099F53CAA7E47D1BA416CB466B79DF2ED1CF66628AE6106A4A9989E3ECD4085C9813F2EB53327115634D06BC2F56A97F4891932B7C0DE0FA021FEFC3830B887CDE6CA08C8906077EBF1FD32A6F352262C9157B51F953BBE9084E64CD2906CC468EC096F271CF488EB911247F8CE073EA273D73ED584A08A873AB0A67F91ECD1590B3BD514E1AB54FBEB10576725CCC4465CC41FBF3F8534C67D20BE6E3D07A889A90BAA493FC5E838EBC05F5AC59D7C499E433CB94683D4E507FD554B1AA62483C4D6C497FC8112B2945D24D5CD46B58C15BD0DA74ECA2B09BF52F8038E96A6624BAE25B83A4FE61CF3CA7954A61B1891830924D4103880F56B0CF21CE2D9819489B2DF7492DD32F315B74317BE1CEA5B63F1474B86EDDD0A3FF009A52AD4CEB320E939F9543694933662940E74E3C0F4C83D21499282544E45DBD1D9BB5F5E30AE2CCE138D377982E22A5A19C4592CB8B948042D0A4E5C4623DE396B9EBD5DEC7C47F87392B3A82E2F43ADFBD7BC3254D9921237777792E6BCEC39DFDB8E72ED4FF000B7DD16D66D5E298E0B92A77135ADD5A7899D5695183EE480788EB333A4E55DF7C39E3C184972E509E400000EAA076167F4FC46A36B848DE2EE0B1029997A598D6B9000B0CF9AF87DCE0DFC3CBDA9B6B764307BA2F6178F5CE18866C50B4A8FBACA4A816925293EF3B23203E157FC76D71B63672B1213F313291F5CC4FD5FC9DB78F90CF3E1166D9D3938C9414A3F4AC58B034D327AEA03738EEA6C5ED939B7F81E17B476166BB4188B2DB854A6FC39F7539C82275D395797BC6EA94A9D34B3073609A5E8CDA9BF7687DF291293BA15605B78FD5516EC4339E7AC648462372D5E165F6C2DCB64A4359122EBC44C2C1FF00BF00C8467E99554BC398E9585C6CB4A887DFC9812E68EF5A7BA44162F0895A14B4A4B170C4684D40B7DAFCA2C3C69FC736336A6C76D764AD0B4FA9D4AB14B1610A090D88412A691D51C4A12635F4F6CFC39F1961F0A8C3A77C02371AAD987E15FD8E341DA9B344D1312B4A54820D161C1BB16ABB1AE7C23A61BACDBAC076FF006558C5F0FB86BF98786D0BAB60B4788DBC984AC29092482A5856A79F6AFA6BF0CB6B6CFDA1B0A4E20EE1514A5CD08AB371CB36B5737E09E20913B0D8F3200795F5329AA033B1C8B74A335A336D9BD70F34D2DC6D293C2A0490414F0E4338E63EB1CABADE1E7618A3E86049B00199FD05FA031569A908DE0E09241BD6EFF9F6D1236E14B68294482641CF9490397A7CBAD3933124FD3514B446E2012694F633E3F68F1693A491DFAFDF9D369AB510C0916B58DB8D5B8F7A088E54B2E6BDCD7D214524FBA00CE0FE9D7CE95972D3BA3786F1D4D49CBD479F3894C3CC9611BAA351976E514F0A872FD7E95BFCB47FC476873F32528DEBCC57B9F48F0156A01E9A4E9F1158F952BFE09EC232F2FF00E447323ECF154AFF00F2F851F265FF00C13DA31FE987216FA073F7A7A47A41E11A73264FAE7F1E7CFC8D44E30CF4129964849B0141C853AFA110D664A04BB528F4A060D4E3CF5EEF2A4A330510414410510414410525F346F6EB1F7F76AE9C608F098127956E7EA4D33D79C10CEE13EFB5713EE3721439FBD9081E7AD359B294C585FECDEFD3382216F3FA0CE30EA892916370E003586EDD6A503DF281DFA5466255BB2A627FDC50BF43D2364075241B150B73A5FA472A372F7D69B4DBC6DEB5F1B0368CDDDEDA072F52D06EEDD368B7529F19CCF8A0A21327F29AF9A7F1E70B8A9FB7F13B8B213BCA60E6943F7D28C23B278713393B39265A8540606BDC7B6EE23653F9433785CC58B858B8414A0149E12E04C2071E5272034823977F1C6D0C1CC93882B9877B7555AB9BF2D687ED5116057CD9450877DE04B582732696E022B76C2F1A2A53178F31C6078ADB4E292DA80038613CF5939913234322CFB276C48C3C912E83E96233F3CE9CEB1B842A784AD602CCB3F4BD59E9467FC660BC327180E366DEE5A696D907FADC32F4F33C46739D7CB2CE6AB5E23DA32F13F3371218D2D4E24B52A6BD75787A84E2490A0B395892C45079675CE8E231DE3584C3AEB76EB25B0014970FBFEA4469CB98CAB9FA702A9BF586152C34737E072EF170D9B8A526484CC724D88A695E009F6CF161BB62E5BB854E70100C426675331D065AF6D7232A0C0947D4A0EF974C9FA92FCB48B0C89A16414921C3DF81197BD0985525B500A854C4729ED9F91F2F9D2BF2CA064C3BFA0896952C901414F7BD7CC73FB410DF43F015B25612DF4B9AD6872A3FB685144A033960D416E0D685836952530400064244FAE46905CBDE53D1858396F4B7B31877ABBF1850201D483E46B2943172DC2355390C3AF28A0A903224C8D634F4A581000A026BCC0E3EED0D56EFBB964D9B7AFF0051E05A39854FA476EFE797A56E2790C1879F330D57FC8FBC8452563903EBF7F7D4F30A029D4FA7E3FBAC494921494A7302BD3DF0786EB39475FD08A67301770D5D780FEBCE1E478D34B796A6D00929FCC6321D3BE7A691396B48250A5D69535FBFB2D094D9A9942B736E9091212EA9B70F841295A94E2F242781254428F2240CBAD653B3A64D5E75209ECE40FBD435E9947CDDA6896EE199DDC76ABF38C0EC398C6DBEF430C6B016DD461D83DC2C5EBCE85062E02C40F00A642A083C53CF95593058612E504AB87F63234198B1BC57F1FB553312A4A6EC5B8532AD33BDB578DFCC330765BBA60A4250D969B0B6FF00B8A92D804C72958273C8EB5226407253FEE6F629EEA1A2878D54C9B2D4564935B59AADD80BD2FC22EB7D3C2E148C8240CBD3CFE3D6B7F94B0C1A9CC96D32310B2B045453343DF4D0DF23EF330CDC4A95319CC46B94452E994A4B39A6A1C1CF3FEA9133280400E0E6F4AE62D7E3D6251949F051A640CE7D634EFF00AD3A4495302492F9BD8E61EFDB5BC47CF46F4D2CE0EA3F35D1A22EE96912241CE08E7E9A1E5DBB8AC4C589798A3DAB6D2DF885A4A0A540105DDED4D0FEBF316FE26F22D98F19638D2B07DD466A11AFD75EFCB2150D8C9A54F50F561E879BD4F0CA25A44B24A83170DC882F6D695CAD163DE5EB0B4832532600244F2898F2922797C6A78B49528872378DEA1AA0E6FD386994BCA410AA82D421813A9FDE87AC692FB5D6309B6B5D8EC259722F716BF49B6208E1E162ED953BC4467F9721DFD6A5A5ECF9A8C1266BFD206F1BEB47A53339DAE22E1B2E7265A260291F500C4F3B3836AF1ED7D9CB6291B3D67C4485B56160544FE551F05A2634E608131CA44D57A74C0B5996DF55452F9BDEBD472AC667ACB9600825C11C6AD9674666A56977C87DBBA6987FC2B6E063842CAC0F155C442473839CFA18D4D4263F19FE1B38600936626BAB0F5883C4052D4A3BC72A3D052B5BE7179A509C3D1F8F425A9F08AF879A5294492A19408CFCA62622A5BC3A9C5EDA9D2E561D4A495AC0A920D1474A1E5F7262255226294523799E86AD7CB857EDC63E5EFDA3C6C46F5FF8945ED85EE2B6D8B2EC6E6DD6EE1D66FB6FF82A670F4AC05347F292519E998E5AD7AE767F85B6DECDF074C33004C9C4CB054B5056F9DC538DD2455B3AD8D23A6F86B66A9787960A8EF245413624D7F5C4E423B41BB6DB1699B3C2F67B09B54DAE1F66C8650852381D012809C827DDD4035E5CF14E07153F18BC3209DE2A50705EDD6BD1F37D22E6BD82B9725539442830B9A8F20039EF6AD4C677B5C4829696C32EDCDF5AC96148405FFC827FAA75809C81D469558C2F84B6A22709A12B2C527783B1AEB99B695B88A76D532F09BC4A9225A87D6972E96A3A45B8FA69101B49BD4D8FD8FB7B9736871EC159C5EE9050BC29DB96D372A1051C0D30A3C45C283A7581CB2EEBE0AF0F6DB9D3244B419C3EA43BEF80CE3B5BD961144C5E3B0B30A93BC9176B3D439E6DD48A868CE9EC4EB6F1BC4F69F15C2ADF11B7C06F956EBC351788E148238FC75003DCE1528CA4A41F7609D32FAB9F077C37B5A4786B0C95CC50225A6E540D783717E46D48F3C78BF1D286D198037F22CCCF6A9D0F2E1DFA34DBF72B7D564D16C2D9FF00954660A48900467200CC4448E46BBB60F6763E4801531AC6E69C81D5F818A42A74A24CC6249C95566D07EF3E7170DB0FE8A40293DF3826615D32E9F3AB14842D29014A7A5483FD9075FDC339877944DC7BA7BF48A94839E52272E7F2D69D5086207322BEFA43428AEF1079353957EE6F09A9B5932263A67972D07DE758750A034CAA47D8FDB8C26A94A2CA49DD15BD6F971B7B68F381CEA7E7FA8AC12B218100EA493E4C2309973011F50E4CCFE515065CFF00B01DA4FED5A7FAAEFBE1DB43F985BE5CDFF926DA9F4DD68AC36A004904FAFED434D37507A56B956DFBE7A0DC2161AA1C73FC74E3092DB5CE4091CA34F9FDF2E54B0DD23EB1BC75F67DD21CA160065024EA0DBBDFAC3BAD613828820A20828820A208299FFF0013DFFC608A57F94FA7D453A47F11D7D4C10DDF8F060F323E4AAD5740A26D422BA0AB0FEA088CBB48B8B7C4D09125766F3601E7C6C2D1CB3F4F4EF5078D6DC5EBB8AFFF0012CF96BFD46E8A282B20473D3EF1CA8DD0DE59E13BDBDEEEEFDC4A2DF11B7BCC3DCB79012A712FA9CB85708D4FBAAD3FC47CF8F8D5289DAF8A2C1DD437855A86E74B3DF9D5E3AF787676EE0E4AB7C2420170F7E0D9FE6F48D9FB860F8E70F6D6129414124640C00A39F3333023ACE75E2BF10A77710B0E5B7A9A71E8DC6EEF16613F7C024558DF3F3152CD5E54115DEAC2565214141294891D426398D41CA399A819001994766CC039676D21C61C28252E0877B86A0A0FB7BBC03EEE7CBD3C865D796BA79CD36C7C8242980AB3B7953B0D29D21F4B99B94670E3B67EBA18B5F1148515AB2931A73119F7190F5F9D454A4196189001B83F6D6BFD44EE08EF252470BE57B83CC748C7F89B79AA67231979E7D7282477CF9450A5B549059D865D3F35C9E2D582965C51EDA3369E62FD2AF10215C038721CF3D73F514D262C176CDBC9AFDA2C9291F487A0F3E0DD83BC7BE2F74FDFAFD29AAD443005B3FEFDFDA139D2CD58B92DEA3200E86154BC024684E73198D7CC7D4FA51F30015F2B7AC611299357A7DCFE72FDB2A1D498EFE5FBD67E624D8BF01EDBCE02821CD0B778A090492343FB50169363D7286A45C5473A18F2B1F3124EAD9D0B79BC325214E49CF32EFE9053C97FFBB3D3FF00C8C3E904248245DEDD7DF48A1424A472CE7E54CE665D7ED0F45B2E968AADB1145ADF3768B489BC0BE124681A4C9CE39FAE47B56924172055FD06776FC5DDA23B184298B91B8ECD6CBBDDF3AF9E2FDEAED03F68DE178261DC49C476A9C5B36A10616916EE252EC419CD249C8491153F8697BC037F2B8E44E7F76F3CAAF8D55C062C1CBD45BB0F75148D98DCF6C261BB2781DB317ECB6AC64341DB979491E2294FFF005132A2388C255913A659F3A9995242432DE80114CEF6BE74ADDB8C5231F8A593FE92D3BA4B1292F66703B7AF33911A65E17EE3A82434954889394738E63C84F5D2B64A4A560D48EE0303964F0899E160214A0C457B5DD87BA50DA57C5F18970EA7231D801FA67DE69625CBFA70A46A1625A025352E74A76FC7482B216406A7BEB07CF660C4BBD5BD6B0A17B81A827A83DBA4651A7C7CE905E328500B3676E2D99BF3CA3225A96A7E447137AFAF017881BBB9009EA0664F7FA93DB4A6D327EF87D6E33A65C07AE50FE46195BD7714ED5F77F4316A5D5DF8CEDC34B3EE3404011C24913D73FD35CB3A63392A99517ADCD00C8367E5CE26E4481402E68E34177A587B61164A8B2EADE79F70356ECC9E251E1481AE73CA44E83A8EB4C7FC3330871987CB3A1E397DF211232A45992546C031A353DD7D639EBBD67D7BD2F686D8ED99C39E4DC613B26F5D3976E36AE26D25E652EA388891F99394F7E75318A5093B30CB269BA7D9CA83A71BB58F0D861F29D41880D6A662E4E678F2D63720E265F09C1DA02586DA68919710690903DEE7F96464749AA061C0998A2D72A24127BD85F2ABD68F0BAB084A416372D471C0B1B0D7FB89862CDD5A5B6C2C84AC852C4C0FE99E2D07FF0058F5D4532DB98054D4D03DADCE9906EE486B58C309D8437200A97A53B37AF36A4618F6AFDFD617B8CDCC6D1EDA5E5E21ABA187BD6F66CADC016A71C42ED814A4C12429409E1E7DEBA97C27D80A5E330EADD72E0B0150C7D915A986C30DF5292A0404B17670496B393668F92CF61ADACC5778DEDABB61B778FDCE1AE5C5DDE5C3DF8ABA5137696DCB77FC3971449108238794089022BDA7E295FF0087E0ED9F8647CEDE5CB9817BDFC28437CBCCD039E56BC593646397855A92E404B3659676E22DE71DC63BEDD9BDDA63785DA5B3D8A6D1ED0E2AF3E8B4C3B0F28BB0B712AE14B686810A3F98447EE2BCD5B3FC21336C6D641F96565732859DDF8FDAA6BCE2D98AF10FCBC210A5D02490E4B0605DEB90AD5C0B3E51BB7B0DB01ED2DBEAC3ACDCB2B3B0DDC6177A125C7F1B6EEB0AC7576EB208532A48292B2D994F2823BD7A63C3FF0003A66270B295330CC5490A7523AE61F87615A479EFC5FE33960CE32A689894A98896A06A49F537E2D6A08DE0DD77B0D6EE36510DE23B6C85EDCED428216F5D6D986B11B7F189926C94E242F873FEEE5C23CBBBF817E0A4AC362251561D0374B90A486A31D3A6768E398AF16CD52D43E6292836282CB15A3B71D33D408DE9D8ED91D9ED8FC391618261587616BE1E1FC3D830965A427904A52343EB9D7AD761EC846C6C1A30B2C04A4240205A8CCD4B0FC52299B5315FE5E21530A8A80620A8FD5C4E557A1034AE917531861656E3A552E3BA9CC9D343CF29FF007532E3511191276AC96194B64C90499F333400C19DF89821C5660828820A20828820A20828820A20828820A20828820A208299FF00F13DFF00C608A57F94FA7D453A47F11D7D4C10D5F696E363848100CCF998F9C7F8AC2E893EFDEB0432B5656D25E0EA924B808CB311075E472311E95078C1F4A8FF00E25FB1B7711BA54032732A04770FE91C96DFFE0EFEE7FDA7B01DE7BEA4DB6CEED638F358938825202D8B616F6FE31C91FF0022870CC939011957883E2FEC75CFDA1889A949DD724122E19CB71CEEFD63A3F87E624E1D290A04A5810E433D2CF99D286E7439AF13DAE690966F6D1C172E3C8438A6D83C6E04BC9050A201C804AA5463313A45786FC5D81323133090D53C29506F9B7957845FB0528CD6A64F517BBB6B4391EB4312D698BB6BB76CBCE78AE11C4A5A0F124CE704F54E87A10455264A82166A58DDED4A6BA1A166BEA5AC12F04B290A20D03B35BA70E459F9452E3E8733492274931965E5E5DF9E959C4CD4A839209019870E1C58E56E158D178662000CC6BAE64FE053B3C46DE2D01044891A9FA77AAFCC50249A804D2F6E96D5B9DE25F674B526EE4351EA471D453D78463EC56E5B0B5403AAB2006599E874CF974CF4A66B5BB8D7434CBCE8C7D88BAE0124848CDBB706777E9D9E2D371E0A515007BCE5A08EFD3F51AD3598B2976C98E8F6BFE338B0A65D057CBDF4BC781C49CC4C7A7EF4D973BEA05A87F593FDFD6135A0BB38A7DF8F6CA2A0F84E59769D7EA2B099848CB3BDEE6F58DD082C069ABD5EB483F129E7A7689FA9AC85105F5B8C8C6AB946FAF6F4A43943E8E111244EBD0796BCF4D7E228DF21C814BB54F6E6619CC940925883981D1B23C7FA8582B8A72D22B50A20867AF0A7584552D2A0D6EE59B3F7D697A4BA90A2933232F3A7D256A32C9B31BB90CC7DF484012956E0C9EAF5D7AF68590952F4103A9D3E5349AFF91E9E82174CC648FA8F427DE70DAE2DD01E6545A5AAE42FFA0E04CA120C05C9D47126440D29E61653A8646C0581777A59C5002C6ADC218E296774800126FC1DDA9F739906315ED8DBB877BDBBDBF7F0DBCB8C2F0372EC2D2D34572BB96D2949483EE901C92A3D3A9AB6E0F0C9012C32CF3C83EB91E19D22A58D9AC561C824170FA8B59AD4195728DEC43F6649716871370A6580A00001292DA7802A73900E731CC015349C2950752686D72D6E05BFB0E050D0312A4A17BA8AA5C977A5DCD8000BBF1AD9A1D7E2AD30EB72B79F6DD53D9210D2829633FEE1946B947CB2A49586A12D5D1980CAED4F2E1942682564862199C91F4D43D0C37174CB5EE292B4EAA055119FBD999E9E5E54CD69081BBBB9D0D39E5E94CF8C3C4CA5101ADA9D3B01F98A17895B2464B4ACFF00D5264FD3FDD24A2C0D5A85A1CA70EADDFE2E722D7AD5E8FEEB11CE62D6EB511C7C2AFF00A28C1196597CF49E7CAA1A7A8FCC56E96395487FCD3311272708B094967A685EE323CAC6910189620A6415FE1DF753AF1368919F33DB4131972CF5D10951D4826A732D5B86E54C9F4893912536DE4EF13FC49FAB27719EBA3748B22E71A4B2E29E55B5CBA2EA652DA24B013A97C4FBA2093DC024C53996904A5F3C856D77F22F1332F0C58170929AFD428AE01AE72FEE347BDA7BDA2B05D99B17B617642E5DC576BB14429969AC2D697BF04EAB206EC3678D0005C9C8C70ABA5384A10087506704B102859DBA44BE1F0EA5201DD6A5998E41F969AE9AE2BF65CD92DAED986714C6B6E6E2DAFB6AF1A71A798BA654B7434D15A95C2E2DCF7D2B0CAC2607F703CB2A8EF10CE929C3CC4E1BE67CB0004EFDC16FA9DAD5B3338E158B361B0FFE8A42B74BFF002045D886CB2E7EB1BCED5A06169BD1FF0022932B3A12633F9F3CB21D32AA16CD56F62DDDDCB8CCF16CF874348D9694B948CA8D91D1AEDA8F289CB472E9C4ADD688525F292C273E24041FEA8580722A12131AC8D79DBA7E193325870093BAC746350EF5A3B74AC46E211BAA2EC0203A9EC7787D246AC4579B8B3C7CF67F197DA3DE4E2988609B2F82E078FB9B16DB776E62AF5BDBBC6D4786DA5D4A9653FD3E10E26655D2626BD15F06F64E156B54D24A674BDCF928240DE2AFE54B939BB539C35972945082B295124B949A370EF6C8F111C3BF62BDFBEC56E9F7DB8BE33B4ECBB74C5E38DB4E2D80DAD2C061A5B4E0794B50093A83DC1ED3E93F15EC3C462F64E0E59412890956E8DD3FEF634147AFAEA61E61B08F34AD2D5ABE82C1E9DB4D1E3B84E6F77723B578BEEEF7B1B15895A3AE6CE623E2E2B62875855C137172CA130DB64E498515711194D33F875E0E48DAF2BE74820A56090A48D5C30B39E19B35210DB52CFF0089312E2A8527E922C4350D0BD69561CE3EBAF70DB7DB3BBD5DD7ECB6D8E149B276DEF70E61B6CAF855C0AB765B655C1C2602814E647388E95EFED93B1B052364CA5AA523784B00D038602D6637BDDB998F21F8A70937098DC44942E7195BE548517624B921474766190193C671B1B1612F2D2F22E2E9700B6ABA85B2D889FE9481034F38E74EF038CC1E1E794206E92CCCC18E6DCF955ED1CFF7267CC2A25543406DD0519B5FB44FB16A8528DC84F0B8AC80E402728E67B0CFE5562F9A99B5497196B5BF9E94EF1BA8104BDFDF285822E94A2A2A401C86632CE86CF4FBC6B0ED1C7C23C4E1E2E7C3A7CE8822AA20828820A20828820A20828820A20828820A20828820A2082738CF499E5FEE993FFA963DB837EF95608A57F94FA7D453B47F11D7D4C1142085028E9FBCFD7F5A260FA6B627DF2BDFA406BFA888C52E45937E202233EC3213CBEF5F481C6D88176367AB81FB1F6AC640048700D45F9C73BBDB4ED2D76F361312B25A02AE70961DBBB479A00BCD3AC82FB6904E69E371091035903BD79EFE20EC438944E9A52080959A8B9A8BEBD2DE7D23C37210501690EA5338B545DB3B3BF5E11CF0F65CDF33BBC0D8E7303BFC4D08DE661576F5A5DE0B70E91722D98BB5B2C28B0545DCED11C7310419D32AF9FF00F10F667CA9F3CEED5D54B70007DB3716B4762D8D854B254BFA521AAAB559AFA9B10E46A1A37AEDF13FC234DDBA894A9284F10320F1912A93D02A63E51A57009D30C85900589BDC70E8ECC43C5EE56CA0A961696622FA3B56F63DAA4C3F6F1B03FBB9EB3FB18E93A475A88C663C00CFFCAF534EE78548C9D9E911989D9E12545B30F6737E163C352D0CEEB1A4F1292173DE40F3E47BC6BF4A8F4CEF9A1C1770F7C8FBCFCE34C3CADD56EF2D72B657D0708B6EEEE7C624E5FAEB98F4F4E9A655A2945D81A70378B460259041160CF6FB50535AB3E7588570FBC40D01E53D8E7D629ACD986EE082FAB9E7C88EC45A2793603DE7F77FEE2A49040D3CBA5335ACB105DDE872CBED90A40A43D6C72391841C71295904E7974E9E63CAB644D094D5C9A75A9D7BFA438972FE9059DF5E19D6AC7AC51E2A3AFD3F7A0CD0C18ADF3ADBFB8C2E580E2E74BF937BE50FD820B608D0FAF4FBED419D57AF26A767AFAC32584B97EE687BF38916F9FA7EB58F9B5BAB3AE96D3DD28346AB4328B1E795C70F385916FE2282A241E71D32D63B659E5CEA4E4A8FCB0F6604F1D399D34615AD2227ACA66001F7AA4E8FE5EED12ECDB42047088D35FD8C759EFDAB604296F91D796919F9A1850726A8F3E5CFA43830DADA538DFB88564B23212759D6331FA8EB378196EA4B338F322F9E9C75CCC30C42C1DE2145D8167E1D6E1FAEB688DDE46CCE358A6CE9C5B654B4AC52D9A2B67F371F191970F067A8E46AF78291BC90401950799CB872BC5431B38296524907EAAD82AF50D7CDFF004D1687B3EEF2AEB11BCBBD97DE45EAF0FDA4B05F8776EDD385AB65A5454A60254EFBE47860033A9F4A9A4E1C10067AB301C1F83EADC338A96310A415AE5A4AC82084A43EF7D81E2236BAFC60CA6DB6ED1DB7BF4C8297ED141D20CCCF109D3B1FA5359F204B191E4C417B64DA9EA2F785306954E482A96B96CEE169637A900FA7586D70E36C8287997D694A07BEA124822609CE6328F86794C362250756F05240B1B71A5B2BE8EEFA4C61E46F91F2D52DC64554E1974CF4A345A78862D60C13E030F29CCFFB5249F841CFBC729E42A2672909A872D42FABB06E1C866F13987D9D38B29625EE8018241721858E8796BD2CF771F75DB85F8B6E80CC8CDB49FC5360092A76623ACF20338A40E18AD214452E08AE6F7AE7601F311292F03BAEADE50B50FF001391CDC83634F26318E76BF7B3B2DB2695AEE76C30D5BADE6AC1CDF2157EA3FF00F8D2C1CCAB4CBB839D6ABC3942410A1C52FEC53F1CE1DE170D28CC2932085021E62922B4A6E9CDBC9818D42DB3DFFED66F2EFAF365761AC6EF66F0F30DDCE2D7AD2ED6F2E90B0655873CD9217971054820020999CDB297B82A1AC090EEC5BFBD72A0113F87C1209AB2C38A1A80C459F8DF5F4B4367B7236585DDA717BC69FC6B14795E2DC6217094DC62EDB84F1152DC202928049009FEC1234A6EAC60466E32B3DABA9A1E1CC5DA611874A52280301A07D1A9973EB9C6CDECCE002D50C3885A5E48193A832328F74AB4949C95AC28543ED99BBF835281350DF8772C7B985C2D2964B860EE721A71EED1950A816020EA040FA4F2F38EDDEA9FB266286281BB28DCD454737ADDF8EB0D96B01C8AB8C83935E2DC2BF731459BB76A6DCB603F0ECB6A4C5C0949826550AE51A65196B15799939909FA98060EE003D79387EBC6184E5209DF512A77649AB90294A694BF3CE354BDB797816CFEE17783B4589E1D85E35F87C21C16CF620D26E0A16B6968570A9511EF473E5E95E8CF83B881FE66180A82A4872F67F66BF686A89DBC80427E58ABA2C29C2F6A9CCBC7E7F8AC6AD1EC4F69B1A699B7C314FE2B7B9211E0B251F8C7920339E7EECC8313957BE676C74E236326629D6528428331624034CEF4B5380A43A91B4A54A3BA4849CEC32E0C18937FB18CA1B078EED65FB89D9DD85B8C7D6BB94A9C5358629654E2DB05D48692DC924A802246B9F4A6FE1190946D64A9406F6FA5FA503FA35F94436DDDAF2BFC7584B541B1A73AE7ADAE35A7DC9FF00ADBEDEEE33B8CB0D89DE760BB45636D80A9E4E1F79B40C3EDBEF876E5C59E35BB214042424A63223AD7A802D6BD98128A3A0333F2E9E4794798BC61B411326CD015F5025CBB8EBC03F4BF3FA3AE1B90095A9B4A523DCE1273026049D328F2E5CE6A387C1E326E306EEF1651AF992E0706E79E714594A41BA779F2D3AFEAD5E5258738B72D92A7014AA4E4441D48CFE15D0F052E64B94913410B6ABBEBC7AC37C5A5299CA092E29D283F70FA9EC35828820A20828820A20828820A20828820A20828820A20828820A2084CAC82440807BFDFCBE349264952DF4B9CAD953D9E461354D4A5A84FAF4E5D22A90A919FDFC694002433DB33190B72CCD0D5B205C3A24C2635EE272F3A4674E64B641CBF5EDCB90B429761FD9FCC5ABB605430B79F4E41B4924692049CBEFAF3D61F1002D254E33E341CB4F5BDE8A22592450BB8B57BD3EF1CEDDEE5EBB77846D23B6D2E855A3C5E6DDCC02D34B29E103FB721C4491974CEB8F78C76A61F766E14A7EA00A5D403BEBEEC63AF7857045587429EA5AEEFA51C69C8691F3C9B1382EF176237B1B5DED03B349B9B809C4102E70BB1F11568A61A7576CE16D94C7BC1BE252A4FE6D6BC61E3FF000C2B68AA72E4AF7492A2082CF5E0E0F91CB9F6ED838340094CC01480CE15504BD3414636CF8C759F76BBFDD97DE66048C5EDEF9BB5C4DB4368BCC22E1C422F9A7A78172C0515005614AE7EE8122457963C43E119D83F9AA54D1F4924806B716B67714E0D48BFCA969420237286C52030622EF67A65967966BB0BF37C62D945D4A512A5A33427DD98528686328EBDB3AE2BB64CEC32D49DD2589A81C59B2A8BB67E51198E9297A86166199B1CF26F748A54F38B5A97242742093323DDD3BC1D33D33A4B03895995549078821C1BBBFA8E1C618CAD9E662B7D2C00A97762723CDAF5F48A937FC1F99975644E89D667CA7BFD73152482A591603B5C53DFAD22670F8732CEE82EFF006DEB30E3A08F42FC585A5B5A02B92844465E9DBAF2CA96183F98C4A921C9600B538E7F8E01E24501207D44150CB5E747CF4A1A9BC29C4842415109EC624EBE53DA951B18ACB99A91A024E94D05C545E8748092737F4E828DDA239E5A54EAA0C8E4797E9CF2E79D466270870E482A496D0BF7E2C7979C6C9C4EE108524B3163AB0E7AE659EB68F024AB3047DFDFDE751AB9A11A77A77F5FBC6DF337FEA0925F874E3A44B5A7FC694F3060FC7E3F4AD133F7D411BADAE473B1ECDCE8D9339EAFE4A6140ECDCAFA9F7AC4FDBD9B8E890A4671A98F3D7E35272B0A66241DE009C9C3679F6D6F58899D8E4A09705C8B916C867CB56CDE24D9B752141A50E229FEE198D0739F8FC0F3A723FD3FA0924E82C5B4B3FBCDE22E6CF4CC5EFB64398A7DFDBC4DB164E2C26074EDF1D79E87A9F83B9127E62812EC0E4FE6D97A437998842695D5EC73B71A44EB5847E2994B6F04F87A029FCD139E664663EE6ADBB3F0CC52EED537771C05F3047A8887C462D0EADD249346366E0D973CF4CA5B0FC25FB058432F2CDBA89E26D6A24C7602AE5833F2C00C28D931A67C7AF18839F342CA8AB76954DA8E00F32D66A8886DABDCF6C9ED9B4FBEE34BC2311B8482EE278725B62F5C291014E3B1C4AE180019D32E74F95B424CB05252E450167EE4DF4E0CE620A64DDC5804037DE0CD7B1B79E8D7731AFD8BEEEB7A7BB8E0FF00F02DA36F1465B595706D25D3CF4A78A4001B006432F9654CA66325CC2490CF9022957CF8FBCE1F499B2D49092CE4977E3A96D1F3D2CF0C93BC3F6810FA8E3183E0570C242415E1EC5CAD0B84804A4930731E951B3D6A9B41D2ED4356E9A6B5D626B048C3211BA120977DE663772C7ADAB4D22C4DB4DE3EF70B0B182ECF30D5C807DE7ED5E08E239CFBB2489988CA39D464CC395134B9C9DB5D072A7E62CB2264B003173CF875A575A4609BDC3FDA2B6F1A8C5F17B4D9AB57894A9CC11EBAB4C40A78A21C2A904C6424E4093AEB90B4C90CAE9DAB9B1A534787416822961951EFA7BD625365BD9C7F0D709BCDA0BBB8DA0BB510A55E62AB17373275295AC4CE7F28E8698E227CBB0FB70360DA5AAFA98732E720067D19D9FB0F76D699FB08DDE6138516D2CD9B4A2D8050EB8DA7C46CE521063204E59C6550F8898E5F4D73ED5341EEB12B271728252D7CC585697B3FBD62F746CC593A80A4ADDB77844AD82105E11925C3FDC00CBA807A45442D678BE4F6F51FBA1D0C3B5E3DE8908296FA8915D2963A69DE1FB762CDB302DD2CB4C944C2191C2DC927DE8EA7F32BA9EF4DF14AFF00230EB9207D6CCD9307C81EBC223D58E44B5EE83BC2EE6A4B9B7E05B5E292587418253C33966491FEF2E5FBD5691255B3E6FCE58700BBD09E5DF40FCE1413153599DCF1605F9B59BFAB4561DB8B45A96521FB55A7FA8D89516C9109244C244E797298CE9F61F6B1DA1351874214E54002DC6E3D96CE80422B94A2E09AE47DD072D0D59E386DFC4F76F36B37A5896CEFB2DEEDF137862FB4EEBF6F8E3985BCE78762CF1377091745A254D9532A504050FCDDB2AF6E7C06F076D09F3F0B8C4A52A09295044D7293CC58B33F2E05CC5E217B8E0A9DBEDAD1DF2A519E30C7B3C7F02DDCDECCBB61B4BBCFDA6DA8C79C7FC1BC7F0655DDBDD61E5E570BAE2576EEB67DC5384C89CC124E75EF79C572B00304B4A65CE284A775144D0370AF5376D229F8EDA0B913944294D56AD752D4E36CEEE5A3B3BBA7F635F65CD91C53086F03DD2ECA5B5C58F036D5E0C12CD172E848482A79C48F79440CF2CE67AC34F0FEC49F2F1E99EACD4EE4EB9171CB4B1AC53F6CEDB2A92A00AAC4104FE38971A67668ED0EEBF63F65F66F00B5B0D99D9DC1F03B4286FC3FE5D6A8B67084C157104E473F5835E88D9C52AC2225101F75A9996CFD4EB4B51F8A6D913311326CC0A356706C2AE19F8B8CF8465F72D564A0F88B2129FCA1592A00FCD3A904476FACB6130B2652B7CA06F5C1233D1C7B073886C295214525CB6649D2CDEFCA246C82C329E3E1933F97439EB9E7D7A5389C5256775F893C87BFBE9B4F52553094E801ED0F2928460A20828820A20828820A20828820A20828820A20828820A20828821056A7CCFD694979F4FBC3399975FB4548D4F97EA2915FF13D3D442C8FE43AFA1847861D7951AC69AE5D7F4A633BFDD425DB27A37EA16171971D22D9DB04716097794C20E5E87E3E54CA60FA59A8CAB0D787B787B21492A507AFD239D5E9E75CAFA472EB7B6BBE385ED5B587AC2568C3AFFC4CD420AAD9EE09033C8C46933A19AE35E35D94162762022A012EC3425FA51A3B078627844896934219A9EFC99AB1CC8F676DA96362771B8E63BB5364C62BC18BDE5A5F5B38DF8CE94DEE2EFDB347857D0382267B682BC51F11B6EE23662E7A5256129DE176D6B43D7A5C10F1D8B63E24290900B12DC496E1AD3D6CF0E778DB8CC1300C291BC4D86DA156C762375E15CDC5AE27749B1C3AE9774525A43086C4AF3720A4CFBC40D4D795F69788317B4F12A940AD414A20DCDDED56D795ED176978BDD4B29C8206EB64DABB172386958C6569ED8988EE871CC3776BBC9C3F16B5771542B87692C9A28B171B6DB0E871376EAB3494119E9D349A9BD8FF000E311E2097F35525DEBBA524294EF402C7CFEF11B8BC4826F40ED63CCB0D5E835E51B3FB31ED35BA5C4F0AB6759DE560092EF11F0B10C559178933987532633C93CB21DEB5C7FC1FC7E16614CB90A005BE9200A3E94E361A18464ED34246EEF3330A1153F67AD5BA5232059EF9362EFC8559EDAE07700E858C41B50D01E44E4476CFE134EDA3E01DAB8376953A8F6490E43816FEBBC48C8DA2852AA439156F215FDB9D1AB78611B4985E2EB439678CBF76E3874B57D2B615063DC00C9D33E53CCD50B696CDDB382DE644EFA49228A661CAE683AB718939535332C5ECC4D0FE7F65B38BC6E6CDE5301C7AE2E186C8FCEEAB875EA488FAE5F1AA4E2B696DB90B2DF3C373671A0ADF5A01D2AF658429802951B109A90E730DF6B68F0CEDDE436DA52DBFF8842491E2F105CE706543A69A11232AC61F6963A78FF5FE6151615243EAE3CF3F485BFC32A62D4C81E37F2CC919DA245BBAEE4E9CE09F5EB0465D674A9EC2A04D00AE845F79A94CC1737E40E9AB84E10243333D8E5F625FD4F794B5B900A3B4FC01FB8FAE469DCC952A5A77814BD2BA7B6B0A528D688EC561D92A2D4670DFBAF0F4BC5E36174084EBDFD7EFAE91D05444EDA8B904849342C188D3F54AE7567AD3F1D288DE167E67F75356191AD691775921B79285989333A671CBEFA73CEA5B073D7894256A241CCD8F3AF4BF9443952852C479FBD738BB6C996C464339EFDB3FAEBD39558F06A4A4D4D465626B4ABBE9F9CA22B153164DCB0A96E56ADCD7D22E4610D04241E181F18D403E67D0FA656BC1CE09DDBDBB3FE69CB8C424D52C28FF003FAADC3BDAFAFAD651A4B320C8111AE8341A8D3F69E756191884EE9750B52CEF9BB1B574E10C56A5870778B7FB8DEAC6F415B5DBBC392B4B44919B640D73072198ED9FF98A8FC56206FBBD0DD9AB4D7AD75A50445CD2A54C04B5097E595EAF5AFB30C2EACAD710052BE132208CBB46BF0133CFA014DD3880A7751072AF4D791BEBC21CC85949FAADC457DF4AD9D9E229DC26D6DDA36E8F0804CE47501464E5DC9903ECE4CF2186F31ADC9EBE599EF4898C3E24029290ABE55CF4FBF18B2F11D9DB77D4726733DA3BEB1ACFF9CE813C1A953E95D1F537D183DD844D49C45C8DECB831D73D2B9768861B3987B29085B6D29C4CCC0067B826397A10353A963397BEAF7DBA655A5A1F2318C0024B97AFB6A37EA1B39845B2092DB423B247307EF99CB28A6335EA2A79E97CAD5CB4AB34394625D4050BEB56E373DA1839837192EA5B0907310348EA0FEC7E951F312E906A497A135D0E55E5487D2F12919E54073E601CBDBC47396FE04C1397FDA728F5CC69CBD3234CD5289C800E5AEF77CC77870310F7722C5BCF33DA235D471B8489F41F03FBF79A48A04A49530E3A9F21D6374C833485901813C9C9662C1EBEEA4C51E17FF6EF97DC5203069DA0B1299CA8814142E6D636CF31CDDA464832C0A800543D2ADED87DAF83B7FF00BD5C3774BBBAC7B1CB87026FD4CA6D70EB30522EAFEEAEC9B767F0ADC85381A75C429C23348CF235D93C05F0A4E3B112270C3B82524326CC41AFBF3610DB178C4A105EE1D99FFA1F637223497D93F702E5AE258A6F877ACDAB13DE06DCBFF8CB87AE41791B34C30B51C3D36EA7878B686EED56DA5609FEA1194F3FA23F0C7C2C3C3F8792A52370212059AC2971426FEE951C76D015FA99DFB54D39C74556D2BF0EC052022324A522070A7241CCC6691396B3975AE9B8D299D8B0B4DB53A5AEFAEAF9DF3A76D09E263A81241A35C9C9DAFE77AB9CEECD8E6BFF00E6ECE468E0D27A8CB2E79FCC9CEAD3B2100292482F4AD0E9735D08E3D4C50F6AAC90A25D8851F7D2F4A9B523A5FB12230CB11C837A8CF90CBE1F1F4AE95B3EC19C30CE85EBE9AC51316B652C3D1ADAF21958916BC64958800F248F5FBFBF2B0A1B74019522292A1BCFA1A8E632852D7FE14FAFD6933736E96E9082FF0091E9E821C56235828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE863D52638CC0CE3CF2EB4CA6921EB666E0ED0B45B1B440DD61D7368810B75042547F28273127E1CE99CC202483983E4CF0E2424858551A94ABD639E5B7FB2EE5AE2D8E5AE22522CDF4F8772A689CD0F20A722A81A28820CF58D6A87E244A67E1E6CA672A0459FA51F3D2F5238F43D858AF96948DE619134CEDFB23CA3827ED7B816F1B703B67865DECC5AAF1ADCE63B89B3738A58D925DB8BA67C1B969D256DA21848F1D4A32AE93135E40F1F7C3CC46D9993B76593BE4D4268D5CF4EB7E21E3ABEC6C76E9402A3955CD6FC38BFEAD6D7B69FB55619B63B05B0581EEE302C7717C6DF5E181EC2F0BB64BE2D976CF5A150BA65A3C48E20954C89C89E55C9367FC12C4271816BC3D029C9DDAE76A5B2E758BCA71DF403BC59867C087F3F2A868DA1D97DC15EEFAB0CD99DE76F4367DA699B2B0B3186E0AF5A94AC45B32CBE9BD61E04428A791191322BD25E0DF87B87D9E895F3248FA4016AF1CB8B7F548DC563F75249512E0D9B8919BF71C5818C9B8B7B296E5F1B2BBB1B178260EFAD08416F09B0B761A4290908E3402990E28895AB9A89922BA54EF046C89E9DE992251240A1482C4B5DE9E561C43D7266D35A6690925B30D46B57DD39C623C6FD88B622ECACE1BB47B4F8324CC270DBB6984A7A00026321EBD339AA5ED7F865B271214061E4D41B203D7855DFDE913184DA0490E4D6FD18F43AF78C4989FB136F1709BB7AE7767BEADB5C3EED9016C338FED03AD614A58121280CA41827256999EE2B926DBF82DB3F129294E1651A963B81F3BD2A38D7C8BDB3058F620EF03931CDC67D2D50DD22DE6F799ED7FECF771C1BC7C393BC6D9DB7242AE7056AFB15716D27995BC420A881993D0F399E5FB4BFE9EF0F396B50C2A2D40101ADA6EBBD0B70B459B0D8A964B8201615058D879DFB50B5636DB735ED6FBBEDEB5BB0C3C95EC863A6517382E301BB1B86169240058E22A495C710CB30418AE29E27F8313365CD98518764A49A25059874ABBBF37E0D60C2CF46EA4156FB13FC8826B9BBBBFE9E3692C71766F57C2CF8859569723FE050D4292B920883D79FA8E11E22D9188D8AA9837149092C0976001ABD9F5AF9801DF2A64B525C0045C01573DBCB2A6B5996F14B761E0CF18700221C410A6D5397BA474D3B9D473AE74BDB334CEF92545AD7FB3DDF952D686388489B294424A5C588EBD2AFA54D327BE30ABD6DEE11C611A415981F1CB9EBCF2CF5A9FD9FB317B4589058FD5514399E2E48B53F351C7E15552524EACEE6F61C2FA3B6822F9B47168E101E41E8127AF31F2CC48F2E73E30A7027E530200C8D2B5D3F37D1A2AF3E490B2C9525EAC47BE1EC345D56778E048F789D34267F5D3B4C65E54F30F34EF3B86A3DA94E957074D2D11B3A4B92E90C5AEEDA65ADB43CDE25D1882A47BC124E441CA23D7591AF79ED53D87C504DCF177FDBF0639758879F214092C487C85B43C3F1E724DDEAD4212B132273F2CC73F3CA338A94958C02E68D9E8C0E9E54600C464C96A3BCC09CB80A6B4E1971B44AAF106CDAA5A85174482A0070FA199F3CF5E8669ACEC63AC8717CECDD48BEBC4F3860708B528A98805D8313D5C0F2FB4465BDCDC34E95A9529998075F4E5F2A47FCCD19C35496EDECB768593875020949A7FE26BCE9FD4387EF90E38A570E662720740074FAFCA8FF2CD5CD7A7A5CF06E7587D26514A47D2435836AEEF4E3C3B34352FB2AD5B9F41F3F8655918C04583E7FA76F46CA1D252B702A3913E4DE7C2211F682EE56BE121063DD034CB9448F43D474A513337C02146B93FB7F487282ACC1E7CB81FB6799BC2CDAAC513E234E11CE123303CC83F5D73E95BFD2D577CD9ADF9FEF846CA3382BE921F8BD2DCEED71F8641E530EF1065B2949D0A840F5EBAF98AD7E48517B067EA74BF11C98B6AF6419C024AC826B6726E496F2ED945A18A5A49E3F11B4E44813CCF58CC72E9D6B070C9AD3CF37D1B23AF0AE920998B7018876EBC98D47166BF216AB64ADE79A8E14B31C4F1C9A3C59A615CCFEB505B424CCAA520B0D38B66D9E9956D13D879A99720155D87D39E76F77EF1686DAEDBE05B01805EED1ED2DC270FC3ECDB538953EB4B46E826470DB9564B512008EA40A9FF0006EC79F8AC7C92A42F777C646B517FDF0E2219E231E84950DF7DD150F6719F6AE9A8CF99780BBB4BED81BF2B0DAF7AD9DB6DD2EC7DC3BFFE3F8462485A138AF8882DDCBB88319B0F165F6FC5B4524E47849AFA4DF09FC3587978590A99280FA126A90F4029E85B2F28AA63F6928957D74AD03FEC6BA1CDEF1D14B6C26D10B7B05C3385AC3184B097DFBD01372F78094942429320A1A52785B06084848CF5AEDFB4D48C048DD943758300037B033F5CA2AD89C5AA6A8BABB1E7D746E05E913CFB8D396AD3AC92B687B80EA4F8709398E597EC2B5D91BD8A4852C0E04DCD79B53F0E2A223D73094A9E8189B9F6FD9FAC5F3BBEC31FC4715B6798294A50B1C5C5209CC1E5AE433D4E626BA36CAC391BA7938E0F677E40DABC6299B594EA5358D40AD181E1EC115B08E92EC8D83ACE1966B52870844473919139FDF99ABDE0E584A4166E038801AEC6D4D2DC2287895A4A94337A12ECCF97AD59B8C5F0A525488FEE20CF4D7CFE952454539D2AE333A74D7D888D0A2093AE4D4F7EF575ADC10D007A9D3CEB20B807580972E7385AB318828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE862971D482519CFC3F63EB4C66FF00BA9A7DABEF585D201501AD7A0BC473F6A5E049E9CF33F7F4F432CE6074B9205C578C3A42802C680B5B87BBEB1AEBBD3D8543E9BEBF21C7137A905411986BC311247298D67F4AAB63702B9B38923E9341D8DE97E97A50B189AC0E33717BA19810D4E5A3BD4D7F348D16DA5D90C1F16B6BBD9FDA2C16C31CC31055EEDDDBA6E5C4024A8F0858E1064444E446424547AB64E15559A849A33103D68C7EDD0C74DD8D8B2A4A54E7A1E77007DAE6312ECE6E8F74183624F5CE1BBBAC35772957126F2E30B6086D59E6870094F0E83908D795339FB3B65C9FA932D00B6807F4E7C9B48BC4AC613280DE34B826C3977CB5B464271F7025586E1E52A62021BB56B3619198090819240CB4D48911A88F5AA44B27E5002E404B060D60DCB534AD5DC4663316A7FE4C2AC41B5E9CF216111CAC39FB64969F480E0FCC120C0E2322273D0E63581E555BC66D0C50584A0AC26AF520355BBD7CC4478529642AA756CEDF7CEBC6E5A21FB6F7A232CFD3E47D3A7C61B2319895FF0032B2FCEE6F4E27A7189492B54B00B9CEF7716EB51E9AC4270076E96CDD24861A23C328D64E66493D73F29E722B6F98A5B15A49702E0DA9CE822670B8FDCFF71F3670CC2D473EAF156321BBCB33875CD9E1D7387A870A85CA389CE1E73CBAE67D295DC94B4D51C983BBE5D470E71352B6CEE007798F0E81A97CAC5F9C68B6FBBD92361B6FD6BC4F64F13BFD92DAA92EB177B36F3763FD64C293F8F5A015F04800091913A646A8FE23F0DE13684B984CB495149674826D6B711C6F13185DBF91517CB30CD5D0F1B75AB4604C037DFBE5F664BE636237A9855F6D8ECB29618636970365FBE5DB320E4E62376EC368805324468ACA6BC7BF113E144CC67CF5489143BCCC9E6E5EB4AC59F05B5B7C004BBD5C105DEBDDF5E79D3A49B9FDE0EC4EF4B08B6BDC03686C3104B88E316F6F72DB974DA880A5B6E25130B42A52A1C8823B5793F6CFC2BC5E027AA6192432892774E5C481C75AB919C4F8C4054A71A33F6D3F7CB5CC76EFDBB37AA6D97DEF1983932FAB2544689D4E4397999CA9AE0D32B633226B0DDA1DE6D08FC30343965092F0C569214012450E8E28D90A0BBEB58B818DA3BB5DC00FA030B100B69052948190201D02B224EBDE69AE37152F1538AD0CC49B72F6FAD2948ACE236780ADD04AC027EA2C7D916AF570232560D8C21C424A97079927FD03D23CA3A53742B749AB3E7EFDBC4462B6791FC53958D5F4F36BF578B9D2EB6F283895E47BC67E59F6C892234D69EA66669533DEB7F38879B8577494D4065532E596773969126C148CC39E8159E9D20C680FFAA709C492C0A83F7EAEEF9F4B8B4464CC1A41FE1C5EC2FC73E34AE50AAEF434A28E398CCE7073EF041A426E21492594FF00D0A7BF468DD18305208043EA1FEDA367D228FE663A9FFF00D87ED487F94BD4F61F98DBFC2F7BBFA8ABF19C598224EA0AA08F9FC7215B7F9254010A19BBB7979F58CFF86902A97D4D07D87BBC1F8A13AE7A73FACE959FF2A9BA5EA6E0866F2039D5B9C63FC66760903437F207D4748709B849410A201391279687F5FF00753585585CBE2337F64E55D73C86BFE3A82AD4C9AA3ADCBE7C21A3972D0D60CF5F58D481F5E5D2A4A4A42981E6065D69AFAE90AA30EA51277496CDAE03707CDA20EF318650A5B08202D319E5CC48CB3CFF005D69F252281B8659F67F2A5290FA561CA40510CF4622D5CADA58D62D5BCBC6A49B8B94A1339852C800753F0EB9D394480B60A0CDFEE6615B548ABF67A43F461CD4B127219EBA7A03C1EB18C76DF791B21B1F85DE6338AE316D6CCE0CD974599B8421EC51C5025B6DA41203C50B0124488E2EF3574D89E085ED7095097BC090FF004B923B7DBCA19E2B1424A424BBFD5AB27CF2BD29EB1CFF0052F6E3DB476A8DFE32DDE6CC6EB706B8219B05872D177ED255C33E1AA597015B61407454F6AEFDE0EF849364AE54F121AC689FA4336A38393E6CF153C5E3021240512493BCA37CDB78FE7AC6F66CCECDECB6C16CF58601B1986B768D59365B2E25A4216B5180A52CA009E23267299AF54F86F672F644A952CA5B7404D29976E1DDC18AE4DC495AEAA2CF99ABB73FD680677731656D7366B75C3E0BCA12E1C84EA79E672D663F5AB6CFD9EBDA83751BCA243E6F9643C867935A044A2B2491AB7B66B0605EFC8C37B5B668B0DDA30A2B6D2A30A104925524C9EB9919FD26A5766ECB3834A65AD0410F96BA599EC2FE6D0C718D2DD35000A92EFF0070FC5B5A0631B29BA6D9C21E65C08C8A92743D729F203F6ABCECD96C94D2A72CC8143CFDD6B145DAAB7DE2E5FA7A5FCAFC6379F0867F0F87B0D10470A743DE0F3E5570C3A5887B1D2F62FC2F147C5CC725AEECF7D0FA5B2CB9C9D2B3087352DC72F3E5EE911BF32AC547B96F7AE435876CFE41E66B32CDEB4A379C2E92E906FC7AC2B4A46D0510414410510414410510414410510414410510414410510414410929064C6739D6E9504BBBD5BEF0D972D459859F5E1C22A4248249F2A4D41C11EEF0A24177666D61B2D8714E958238491A93947DE7F72D664A529D9FFAB37BFD2C181048B438E0CB5CFE5FBD22AC312962F93D3AE61BCE3255F56F0E8FDA2D3C76DEE31143F60865A29527878DD4CFE607F29194C76CA0674CE7210414EE90A66A8B355DFF00BABE4D0F30E374098A5115B3DF2B75B3DF48D29DE7EE81EC25F7313B2BDBC05C5296FB2870F8644CC25206801391CF3CEAA3B4B0F88FAF71442AC0825DAE486D1DB3B6B7BEEC9DA0896849B80CE3CA9FAE51AF97187B56F76B45BBD7EC37925C4BEAE149207BD09034267A73354DC4E0F686FD56A524E44927370030E2ED7ED17295B5D0B48029C2DBDA1E35E0DC6AF093682CBC1AC398694167FAAFF0FF0057A92950E799D40A4D3266A48DFD5944F503476E35BC626CF135254D52CEF6B86D5FBD7842F7987AC2D50A5A814A4F13C6564902412390CE04E4075A96C3E0B0CB4BAD0144DAC7B07FBE79D214958A44A001EF7B5455F9BE82916EDCD9A9274D394FFACB9E91D795666E1306827FD31FFD23ECF9D3DD1C231C951228C0F56767F23DDD806868E58DB78056DA26E553C5C63DC1D2329D2751F2A8D9D2A42086450568056CC2EFDFC9E1EA26850749619B96ECC6BCFCAB4B3EFF000643CA2A76E6E1067F2B4A1C1E5A1F8CEA08A62B54AC9200B3066B655A7439584384A966DDEAFE54F2D22199C2D9B275D5B4DA145407BEB48F117023DF235E824F59E95193247CD984DD2694B75F36CB430FB0F2E71008530D41208FB65E94D6CFDB0D93C236B70CB8C2717C2AC1FB6B84942C964294A4AA66788473F3C8F794311B0B098992A1364824E7BA33E80B3EA79E462D380C61925017500D49B65573FA191168D19DB3F664DBFDD29736E7D9B719698C5D6A5DCDF6CCE22FB89C2D0106786D2CED42540B89E22A0755281CF2AE29E32F86F83C7CB9BB92424A829B71201CFB777148B8E1F6E484240500695736CC5DBB6515EEC3DB771CB1C5D8D94DFCEC662FB2DB40DAC30EED13160BB2C0F891092EAAEAE55C45110AE2CCF9675E33F1B7C0ADB7899D357835AD287247F3720540A03A6B1292FC418520B8B86000147A1CECCFA3BDF4E87ECB6F036476B9B6DFD9CDA2B1DA16D684B89BBC3EE9174DBB29E2284AD33C4A6F342C7250E935C3319E12DABB0712AC0E2513173525B7D94451FD68DCDB81504F933C6FA0009360CDC0F2AF5CF9647C331B5292A952AD4A084FFF0022513248919E607603CF952A36362C23795296903FE40D7859FA13F686CB4058CB872396777E2F1778C6EF2D582B0A53EDA38214DF110BE331EEE70424913032F95436254BC2A94952542D71A6648E1D6D9444CDC1A4A8FD22AE48D3BB68F9B70222455B4D756C9694B0E2D4E09094495088D472F21D472AD64CD334B82C4317D35AB9B4305ECF0A2E052EF60EE7DDFBC4BDBED236FB4DADD65EF19C305B09F78198CC6713FE69962B1E64CD2820AAA6B46F7A9D78C339929129450A42891983FB1A8A5EF12C9BE44A78DB75949FEE713C20749E629346D12A3541166B55FA1B76E302512D401092736724F6730E1FBE6ED9A0E825E4A808F07DE27CCCFF00A83953C9334AD8258BDA9DEC5DE3099466160821B23CEC18D73FCC26CE32DBA9E2216D000E4E0E1518EC7F61F0A9093835CC75070EE4795EB5E59F3853FC298EC03926A2EC28ED5157340417F2886BBDA74A2E0B6DA1F7018014D00A403CE6397FB3AD49499A70E7E5EE289CC81D3BF377A55E1F4AD90552C15EE8A5CDFABE61F9579C20F63C86C02E3E1B075E3504F0889CE63A7CBD44D6096B9AB4B2147A6668E7FAA1CA30766194EE46EB3029A3D5BCEB9FDE31DED7EF0B67F6612710C4710694CB82438DBA928102082547AC0D27D6AF9B23C3789C79425093BCA6BF16CAFC0FE03422BDC94EF5E7FD30CEBEC6986F43DA1DAC5AF11846C65CBD7F7B70781A4D9AFC585188E2E054E848FBCBA76CCF851B4F18942805004A49B8A38B822A1E1B2B69C9942A0588BB3B38BE64F4BDF45F6437138D6F1D386637BDABEBC6ED2CD65FB0C2AD5C5254F052B8E31261E1EF24C24B607F6933CABD3DE01F86E76761651C4A0129097701E9AB8AD341776CC45076C6DB96310A4805AAC435DAEF903C637170BC1B07C22D6DACF0CB0670CB5B3425B6AD6C5B4B2C3C94A42429E424C29440E23A1E23AC57A2B65E070182C3A50A949DE48000DD1F8C9F26EB157C4635539F7598DFBF3E4FAC5C4EB4979A42AC98436B392894F0A0C18CA3393CCE93DA92C64844D98552C6E8B06B3741DBEC6B08494294A05F788B3126EEC39D756BC0F5BA516E52B0B0A508514446B999CFB919139CE862AC7B0F1387C26EFCF402F4767A5466D6FC67589CC3A928B9761504D6DC789CB8D5CD54D9FB12ABB6DA652B5238F20449CC826791F9F7CAAD8AC08DA2A4CF900250A62C030B72F75393C5736B632589AABD99BA72A37168DE9DD6E0AB432C2D480880932444E5241FDF3ED52985D9AB92A00D599F5176D03DCF1245EF147DA0B4A8296429839005CBD3D7CB2358D9069B21090001023A72FF00433A99972F728A72DA9AFA51F93DF58A5E2120BA83821C56BAF2A7B1A429C0AEC3EFB4D0B46F5B30C7DD623D72F7AD9DEBC5E1CB7926398D7F4F80115B253B800E17D7DFEF38712C86DD1FED1EFC88852B68520A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821A3EE34D92A2015467D48F989F81A6B324EF0248008CF5EDA5EB61942885FF00B4AA8198136BF6EBD22D6C5B0BB5C6D05B7DA42873E248394F2907A673FA9062713852A72433D2999B657F76A9895C262BE4021C90C0DECF90CDB80F28D76DE1EE5517CCDC5CE16D842CA491C020C81D00EBD0EB2222A0F13B394E0B2800EF43404D9F2B795227F09B5104805401C876A5EDCDB5AC6B35AECF5EECFDF2ED2F6DD6485405291F3CC8F3923E7509336792A50DD37BB54BE4697E7A44E236900032AFFED2E74ADAB9D9B5176892BFC33C5714B4A40040CA34C88F4F88CF5CE95460FE5A40666A3B1EA3856E087B16A557FF00304C6DD37CC963636AD9F969AC5AB79849930939EB9798CBAC4D369D215BA4B07197AB73EC61DC89C01363625EF4A9A9A38D74B59C413F61C1C49888EB9779EDDB3EF50F89C392E4675E56B7323C985E26E4CF70327B686EFF00AE15E56D5E589E239489CB43CF97AF3FD62A24C9625C647A6B968CCF7E31252A7848157D2A19C5387463E8D10AEE1DC4147864C667E323423EF2D49A66A5EE2C0341A350DA8783FDEB133879E0241DE07870B3533FC86CA21DFC3553A13E59FC2048CFFCE993B4AF7D208343D9F90F7A43D4625259E95701E8E3813A674842D2D9D6DF5B686020019BCB494A5723FEDA98CBAC75E9178DC399885101DC663EC6E3FA6178749C502A636C8022A5AAFEA22C5DB5DD5EC06D9A56CED7ECD5AE22873253CDD9B6EB99F3E258D4E93D7AE7547C76C654D52814BBB801A95A58FBEB50EC62B46073770C39E7C9B5D2358769BD8D5FC18DEED1EE5B6E719D92D176381BF889B2C2D970020A516D6E9C92E2C4AA224CE872AE7F8DF84382DAF89562A74894B98A2FF5A6A5854971D6834ADA2C982C7A53280DE6200706C5ED9F5357E04C60C637ABEDA5B98C69CC3F783B1B866D6EC55BF1A9CC6707B0BEBEBF36EDA54BF13C77086F88849CC889CF28AAEEDDF83982C3E194538745029BE9E1614AD39D2B7A449C9C626630B3B333E75FC3FDE919A775DFC477737B73776DB34E626E6038A61EA71AC52C318798B7B9B67944801D6B8A5292B04A246600033AF2A78F3E1A623040E213865224CC2AF953770842F74B16362D6247F6FE5044C53392736233B5FF0059E85B6C70DDFE6EE31265E36BB6DB3EAB87024DAA1EC41A0662600067211315C50F8731B266EE2028024D81D73A73CFCEB1228C0254086C9ACE03F215EF9D844B61BBD1C2AF8AD4D63D87B970DE65DB7B90A61433238153C80131A6A3A53F95E1433803350EB3A8E3FDD2EE6174F86D33C0594824D4E9E60FBB6717261BBCC43C1DF1F1266EDB6B3E169E0BC87627B453A1E0EA809964D724BB771EEB01F0DA10092814B960FED8449FFEE8E10E5AB6E1BB2C34A2A002969470C18248073CFBE94FA4783E72082892A615FE2FDAD715E26819A103B225A0BEE80012C5AEC73B8D323CA23717DEAECDD8E1EBB84E2C2E16904F84D3E9528F6893AE63B7ACD494BF0D62890912D49721C37767EF9706784FFC244B56FB208A31A6F646BE74AF58C4B79ED47B2B84D8285CA5EF1D5E22521213E285490264F32411D6262BA56C6F86EBC6E1D334C92544554525CB90F56EA78E60444E2F172A42C85123402A939D6AD4CF2B5B2C2D896FF76C31E7DC6B64306C43145BE48652F30B7904AA40808327CBE9575D9BF0B5689809901A87F8E8796A2B1098BDA89DD2029935B1F79BD9DF5156A309DC7EF7F7C0EA5FDE25F39B2981CF1A2DEDDC7ACDC08992149765209232EB273CCD764F0D7C3F32572CFC948008B2780D00C868DEB157C5ED10EE54C0BBD682E00CAF616A9E91B47BBADC2EEFF621808C3B0CFE6F7AC0138BDD32D3EB0B4C92B0FA6089339E672CC577ED87E14F952D2E9600682ACD4B5816FB457311B40289216F53C5891EDB96869995A64786385C0B0320419000C824764881A888F4AB72657F88D2AC2D4A12C3A31A55FF005159C54BF9EB52C3D3B8D6A59EDCA14F00F5F4E7F18229CA092A152473A5453843032FE5922BD7F1D7F1136D5E356B668429292A1324F39396BAEA0F202A4E4E154B1715A37AB5383119D3284FFCA1243B81773A5FCECFFDB1685CC4D7C2DB5C5240809D2644EBA9E43A72815252B66294A02C4B1A5AF5E43A8A645E3076ACBFF9E55AF36CAC3A3F08D8CDDB6EE55768B5BC799E10A2492A4F43DFF4CEBA1EC89224E1820DC5B4BD5C9D39E715CC6E3133662D64B019937BB8A3DCF1E91B8582E0B6D84DA2128400A4A7A69FAE675F96553491BA092CEDD3DDACFC0D62A98BC52A7ACA45100B30CF9F0F662E2617C6DF144493F414992E49D622E7A774A83BD8F7685AB10C141945BDD21540CBCCFDFEB446C8CFA7BF48AE88520A20828820A20828820A20828820A208FFD9, '1', '2021-10-06 01:13:41', '1', '2021-10-06 01:13:41', b'0', 0); -INSERT INTO `inf_file` VALUES ('7e7ed694-2242-46cf-9ac9-0709debcc22f', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F00010000060301010000000000000000000001020308090A040607050BFFC40045100001020404040403060503030401050101020300040511060712210813314109225161147181233291A1B1F00A1542C1D116E1F1175262243363723443538292A3D3FFC4001E0101000006030100000000000000000000000203040506080107090AFFC4004A1100010204040306040405030304000309010211000304210512314106516107132271819108A1B1F01432C1D1234252E1F1091516243362435372923482A23654636473B2C2D2E2FFDA000C03010002110311003F00DB823E07E37221084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210844495A905D25BFB690844CEFE6FF54210EFE6FF00542112497249D4DCC2108421084210842108421084210842113E5CA72E5EDA37F8E5FDF584409B0BEFF48A832DD291CEC0EBEFCDF5EBBF28640BB163C9FEF589085292544591EA6D6BF4B5FDCFAC56D3E0CA9E9CC27213C81D4F958F9F571A341E5CB3721C380059B673BDD8731CDE2A458E1084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084211508960904681AF7BF95B5F4B1E5084574B4598062DBF27FBFD6112AB569240240DD76363A07DE20FE115B2A91552AEEE525D4740399D2DCBF6688173132C6656D70DCF9F266FB31F22AD52A5C8539D9BA9D45BA4531A429C5CDD4679A9461B084A965C3CE7921494252547D85ADB98EC7E10EC7B8DF896A648A0A3A899296B4F892859195D9EC92E6D6203EBD40B1565707565CA14A172C3C5E659F91DEEEC39FD98E958C8210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108472091A184239CEAE7F21FB4210CEAE7F21FB42110EB08421088E5E5CC3300431B1BFCB78437F97CADFDC7E9134CB0A3E005BA581FBF7F46844FE403CC77F99B6FBED6FDF5ED15D4B4D2759E82C7F5D3CB99312D4B63A86EBCDD9BEDA2522C76B588B8B7FBDE2EABC0E9EA249A893574F2128194CA5A996A624B817377673A989130CF529265964EF672FECDF4FDC0A13BAFEE807DB7EDD3DE28A51A1A75777328E6D5312EA96090AF23981B36DFB444813ED995ABB9B586CFAFD3D1E38DCF4955924F5B76DFEBDC7CBB7CE2399F839A3F8586D424AB474A8B7CCE9BBDB57D22AD92078943477D80E6E186D6FA189984B85603EA521A58F23F76CA49F42D825EB74370DF4E9DE2AE9F06A994B428D24FA94AD8A51282944B9B067B1DB4167E514B595D4D210E148CC0789209043EE087048D8027778F8188F155030AD2E72B38A71261DC3148A7A14E3F57AA54E5E9926B6D00A9612AAC392E5E7DB4A6EE352A9715E64D93B8BF7AF0376478971B4D954D478355C85CDCA04C9925612E6C1C91A97B73E4631556373D738A10A704E50C3AE8ED71D4FAF4C39713FE377C39E4E551FC17936AA8E7D63D712B97629F83A9D35352289A1E5287D6E332CE3AC078A10A7257982E53A5442AE77BBB25F80DA8C3ABD18F7194EA5460DDDA54135933F0E896B70439577799446621292A2ACB605A23AD99895553A134A16A5B87094662C5DCB316F3B6DA8D719189A77C48FC465A54DE65E269BE1B328DF70392385A96890A4D626245C3A4214B956CE255AD72CA50B3CAE595101C36B93B99832FB1CEC9E49A5C369B0EC42A24200354ACC24A272032932A5CDCBDE202B79A82EC08B1262EF81F0AE29882906AD0B0951B86B94B81A8D3676208763CA36E98F9A48BC42108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084220ABD8DAF7F6EBD601F6F942223EE8BDF57E5FEE7FE7AC5DB0E97DECC424B124E8767D2FA683CDFE72E62F20F9F3E71F16AF5594A6A983393723241D9E6245A13B50919353CB783250B65132FB4A7802EE9D0C852D4A0404F48ED2C1781AB3184A7F0D254B2AE492439DBCAD168A8AC6258F5D85AE370C6FD1C87F38FACCB9CFD2194F32CAD0A285254026FB39706CA041B84A4951162010445B389BB38C7B08AF932BF0B51967202F284A9D9CE819B661F48952F19932C142AEA0EC437E96D45D9FD220EA994874CC3C9939669402A6A710B956FA9B9097C36B2D8FEA780E5207996B4A45E333E12E08C4AB952E427876BA6A94C9EF3B898AD6DAB1F3E5789533192A0720241D033160CEFE4FE66DAC5A3673F1C1C2D70FB2B393398F9C182A4E6A4C2AF49A657A9D5BAB3853736453E93313D361574E9D2590ABED6E91B25C33F0ADC67C52BA7551E11554F256B96164D2AB280E09CCA32C8486DC9B5EFCA8D58954CCB0CE33F84000B6BF3D6FA90DAB5A30DB9A5E3998DB332A33185B820E1F31563DA8B5AE5CE39C4F4F7A428A92B5684BD2F2D507241364D8AC1725C822DB7511BCBC1FF00073C17C272696AF8CF15C32494A10A992066AA9CA5243AC034E998841D001372DF5D0C5C11C3788D600A4CA9AA0A4821C9D4FF00F262413BFB88B53ACF0A5C6D718B5194C49C5F67CD4F0FE1C9D77E28E5960B9B5C9372D2AA21486DF320C8A682E216B6D6A6DDF883A41755F723B0AAF8EBB24ECAA9552B85B04A2995F2E5A909ACAD44A9EB4AC064AA5497325C1018AE5121FCDB28C2BB37AA9EA419C9233105920816D9DF30DF768BF0C8EE0BF20F8799368605C074772A9A5297B11D7E5FF9DE2075570A594CFD50CE3AC05AD216A32EB6D414949490018D6CE39F8A3C7F1C136827D49FC1296549968968952F30709509729284000288484A40625AD68ED9C13812550E55CC940A7280330727A9D49767BBBF9978BA179B43EE36E3A5C77960250DA96A406D23601B79B29984240E890E04F416D3B46B571071662FC43316B935535282E4E559763B6A412F6BDC876BC671498452D390532D296DC02038D7A9F5043EA2D196B8F39A359E10842108472C59D8B736B4211C42108E1C0D481EB08E424A8B00E758383A107D6111776BFE931CC221208B1041E4434211C421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210844FA64A1535216404B13736D3CC6CF68422EB488EEEB652DC89799249B652971FCCDA33D9C68363149521652A604EA18027CB47EAFD4C625BC5C723736F34723E9B8F3237165728998792932D6366E9347985A65F12B5499D1565C8CC36DA4F3C99664B6B6C282F962CAB01B7AB3F06F3F82D788AA931B46175B2314A29B874F4D57773275209F2D72D3574B98B267C852FBC43A54E5094B125A30AC5513D63324AE5996B4A859401662525C12411B0EBCA30FF971E355C7267261D96C0D923C35E1EC458FB0B48B185F16E209F76B084532B72290C3D3EEF2AB92D4F4321A532A53B32CA91F109790547416D3E8AE3FD8076514C8A7C671E453FE025C84CC975264CC5A97241514B8949695308BF8C0D4280CACF434D4D555F34264CB54D597040D417DAF717F4D1C398E3629CBDF168E294A3FEAFF001308CAFC3D308D350C3F8585065FE124661453CB96769B2AE551D23ED1A438265C46A410E950044758278E3B01E0D99512704E15A4C5AA24A9A5CD9D3545495CBD1D14F325F81447882939D9F48EC8C2B81714A8085CEA69D2D0C03E420176772A04380C5DEFBC7A4657F850E436199D93ABE6AD471667463169497E4EA789EBCFCDD2A6A6894AD7F1EC535C937DA6CB801B3EB6FCAA56E77B6198F7C54CC41A9918149A6C1E42D16A4A7A7932D29CB982405AD0A9C40D0BCD2ED7711D9185F673256941328A9682E4A9C9DB51A1E5616776D6322984F2FF000565F4A269383F0A50B0E372C005FF002FA7CB043A027484879A4A94AB04DBFF0070A8DEE4C6AD711FC41714E25327A27D5CD9C95AD6C01CB636E439FD3AB763D260326484215283CB64B650C7EF41B8BBEC63B8216B492541B0A2AB8E5EA29D2474F3A945245B74936171B474A62DC5F598B2D73271984A8A9F34C2F76D03F5DB5BF98CA6969A9E404E5969040B823CDC8DC17D0F2F5894BAF29C21441458FA1DEFB1EFEFFAFA88C726AD53D254A5BEAC1459B721CB3916BBF9022D1799425D4112C808BBB1D1B40C771EBD62205FB81F389B49884CA4494A40507E6003EFAFDDEF1CAE86503AA6E4DAD66B336A2FADFDEC632CF1A4B1A6708E589D013E9084710844495149D6DA11B31D7EC5E114352AF72771D08FF1FF003138CC9440694C7CCEDD0F3D75D5E2320100A41F262DEFF7D22AA557B5ED7F98DFF3FF001F8440552BFF006CEFB9F931F38965209B8BEFB7BFDBFD22722D6DC6FD81BFE5FDC7D7B47227207E49794F32EC47BEBED10A501249737B31D9BF7D6211C9A8984310961D0FEF11C220F14D50B5DAE76B6E790FBBC21101052483A88423884210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210881DC1B6C6108A69D8D8DC9D477DEDB03E9DCFBF51192D34AEFA95CD94948B96723A73DBD75E9C10E18EF1C09E93969C42E548626989B4028947920B73AABF2A6E9F300A86A4CC3295A2D704A5D0047737635C62384F1F913D73D484A26A4FF00DC22C08D7C4346BBBBC63D88CA5942B32772E4E87FA4860DA37507D23536E2E328EA5E183C7949E7E61C6A651C387129539695C6549916D69A7E0FAD545628F55176C28309698E4D49B2EDFED5E51B9B587BA7D9DF68749DB5765D3B8724D449FF0075C2E8E6990AEF1E655D2212A9AB92015052E7CB26628285F294218B5ED78056270DC6A48984649B352EE2C9512003C8025BD5DE32C9469A97AA5269F52909895A8CBD49845429D392CB438DBD2334C34EB485290A29296DA216371F68B73BDC0D02ED3785EAFB3DC4AA27CC1353DECC5AC851533936D49362082C6C760E6377B87E6C8ACC2E5652851EED2EC13FD20B160E0B333FEB1F40A9B6946E4B6E7F572FF4D81E87A743D7AC74C1AC388054FCC6EE3522E5DBE5CFA5B78989989A39A52964DD8369736BB30D85C72BEA623D62C539CA9D4DA93A726BDC9DB7B4579493E2045C3FCBD8BF3B42282697BF33FA1FB31104060EEFBE9FB4224C4FA74B2887760E3DC06DED08456465A234DE34BE11594E9CC85076F11DB98108828E917B5F7B4552684CE3605F4F08E6D7207203F71BC20B75252404807D77B7B837B6DFDEDBDA27A7079997BCC8A294DC862E5AE47DF58840626E4F20768E2B6F357F3B8DB9D7642C3205ADB12BE67E37EA378ACA31214BCA680962416D75DDC1F2160C3AC40BAA484B25402858E6208F326DBDADF28E40765C2482D2D02F70EFC730B491DEE0320DC74B5FF48BA4FA7A612DD386AB3358EEFB91E1161BFE9146AAC5851CCB9447FE285076D812A53F9DEDD6D12A17AD4742D2B6EDB1093A811616D7A8A4FAEC05FAFCACC8A34572E64B974A65292097B9075DD868FA8D34F3994F52272D412DA17DF4D0FCF660DCA2AC5AEB30F9B4AB21414403CAE3F7DED63E7BD6C220A340528BEAE1873637BFDBB421126A401396DD3E8DFA4211221084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084211C80E586F1C12C09E512936FF001D6FBF61EBEF7DFD3A45DA9EBD32A5E460469B8366BFB0F6E45C4722EDD79DA264A1B5202B40D41E4CC03DC3CD690DB80FAA4211B7DD36F3024989332AEA25CC13A4A88162081A39BE9766362F147572028124396B7273762795DF4BEC748B3EE3A3860A2F17FC38E60E5454E4E51EAE4C51EAB55C2F54994053F4DC452322A9AA10957016F4AA76A8C312EE137BA0D9206E637EFE0CFB61A9E15E21A5A6ACAA250AA900852D82D07205A0B9365A5D2A61B9F21865652AA4D4A6A00395252EC086209BBF4B68469CA3009E19D9C589A66878DF871CCD7669BCD3C8D9C5D326252A0A29A84FD05B9A9812DF64B09594B6865F20A517E529B2491631E8DFC4B703CBE34C06471060B244CA3AEA54D4489B2D04A338493325E6BF892A752AE2CA1A3DFBDFB39E374A932A8A64C7520996B054091A0B0DADBF327CE32B096103CF2EB53CA7505EB38012D1171CB02DEA075F5F5BC799C696661B513A8677826233272F54921DB727A359F431DED329FF00192913A5BA92482481CDB71D074D0ECD14FF007E91669EE165DF5DEF7DEE0795CDA2ED2E532120A4B8006FB795A114131DAFABDECDB188FBB1FD27E708931325A7293621C75E639C2113632D2B1A5370413E96DBF1BFB88D384256BBA50A239B758D2D4AB3683F57F28A682A735E84EB2D8D4E2527CE11DB968DCB8A363E5041E9BEF715B48898A5096949CCA25831726CEE1EDB35BFBF330F760155B35927519B928FF2EA39BED12BB32CCAB5CE7D4DB6DA81239CE064A103EF178A81E4B82D7436AB972CA008D378EE7E0EECF719C7A6CA44AA49A3BC20056451FCCD7D3AF97D0582B71C452139924B1E6D71A8EBCF5F4D231CBC50F8AC7063C27CD2E8B8F332256AD8D2CBD18270FAA5E72B6A52076652FAD691AB62A2C900EFA760237D7B32F817E23E32A597884C9B364D2CAEECCE3DC152121434592A4B3E52CFA81E71609DC6D2659CA24B920B0CCC6DAD9AF7B4611334FF008A23084AD4E764329F878AC56E5A5E6552AC54EB98A996913001584BC8926B0EA14A4D93A8A7E26E01EA7AC6E6F0E7FA75F0E144935D3A9E44C54A4AC04D389AB52AD69802D3DD12FBB8D7CCD895C6414559242AC4B1D12CFB162F76622C5CE81E3CBF0AFF0014762C72AC246BDC39526ACD36FAD335274AC4AA93A832C972C95042E933A5C7143709084D8EDDE332AEFF004E6E11452A946A6466C80A40A6042944071FF70650347F10205AF6347338C5811DCB925FF36E6FAB3BB746F28CA670E9E3F5C256714FD3E898FA9988724AAD3BCB495E2E986D74665C71C4B60B93EE485312DA14B58B38524588DAC45B5B7B4CF808FF006AA2993387A4A664E965456BA593DE3A4256A2494D982439E57B98ADC2B8D25A66ABBC9590286AB55F5661E762CFA9D088CDCE1BC5748C6147A7622C2F3B255FC395B61A9AA1E20A54E373B47AA4B3E90E34E313CC853575A085048D66FB5FBC799DDAA7633C41C233A6A6652CE5A25A94EB32D490C017B5C90C2DD3CA337A5E219152C026E58BBD86E0DACDA797D3B1A545574E85A5C6D650F21692808B7F521476753EE026DF2DE35C44A5D34D299A322C29563AEA41243588B5BF7117E95384D19980490E920E672CECC006F47BDA220DFD3A91B1B8D891D47EC748B7549067288B8B7D2277F6D6D11891084459490FF6DBFDFD94221842108421084210842108421084210842108421084210842108421084210842108421084211C80352E12F72DA08440DC7417B75EDFDBE71528954EA01E7804BDADA738020BDFEFAEE3D8BC4BACF4D26FE9FB1F388674B9281E09BDE13C886FA7ED1CB00097B8D86FAE9E81FD62A00A209234DBD4C5366161ABF2BC40A5650E0666B16DA21B800916045F7FDFEF6F58AA912E44C0AEF270411602DAFAEBC8F2F680513B36FAFF6F6E6D10B82091BDBF7F389ABA7A64FE5A90BF261F7F41CE228883700FA8BC51A800A20170343F7CB47DE10886108E41620F28E08704738811716FD88E23901801C834453E516EB7D8F6FDFE715D22AA5CB9650B979B563EAE03EBD3CA38580B7CD7E56D2CCFF00AEDB44A90D05A12FA8995E6954DA124256439A532802883D6606D706DD6C40B9CE7B3AC46752F12D2CEA72A90942D2B241B780E620DC3381E57B03A45A311A54CC90B940A42969396EC6D7530BE83DC0D63555F13BCB9A8F05FC7565171858692AA560ECE7AA230C660265D854BC8A669130CCA3CF3EEA565A587E42725D2942D092DB8971C2A5870253EF5FC3A71E5376A1D9AE29C3F52906AB09A7993A95130E72B08927F1465B870D2E5A5459C17EB18FF0E53CEC271697384E2B42960283B017748373A9376219A32734CA9355191A555D975B5C954D69AB4ABCCAB5A6764DB969579F690011A0252E03CCBAD24AFEE009223CFDED2307550714E27396932E5A674E4A506DFCC599B61CF56F68DD4E15C7D153432E52A51CC94B024B87CA003A0D5F9DAD1CC26E49F537FC7F0FD23A926D4BA8802C145B968DABBF4FDCC6582A125D927DEFF40CFB6BF2884532A666770CEDBF289A8585E9089711C2108CB24D3A86D2A2A5001B5A5B593BE97156D293B920AB526DEB7B5EF1AC7493A9414C9080E47874D09D7401DEDFE234991532D049D589BE9A5AFAD8730F770C23A0E3CCCAC1D957862B18CB306B9218630A61E61C9EAD5627A6512CECB32D214E284AA9CB25C7D484A8A504A4FDDDCDE364BB1BEC5EB38E712A6AC9348B5C83350804214A49398170183BB80C5F6E822C18D6372E428212A00643A96D6DCBCEECFF0048D287C517C77B32B36F13E23CA4E186AD3B82B2BDA5AA9950C4CC3CA35AC46C6B799717A99E52132AF3772B297147CC9DF68F78BE1FFE10B02C370EA2AFC630F973EA3BB44C452F761225901242A728A4B31FFD3CB71A2E3AAF16C5D73A6108532492EA7B9F27F2F97531AD6572BB5BAF4F38FD42B5529A54C3AB989B9D9A79C9E9A989859D44E9756149495137FB5B017D8F7F41F06E0AC1B094211365C9414CB44B4CB9684CB9694A410004BDB61BFD41C745490080E6CDAD9F7D9C3EFCFD8C64C7C2FF00C32737FC47F3819C1D8710FC8E5D61F769CF66AE36984AD12B457E78AD729234A7D29E5A9D9E665AA0B652B582532AA246D1912B06A1A2654B4A4380583311ABBF2B0F668B6CCAA5DD24DD8EA5AD6B336FB10469611FA207099E0C7C0AF0A78768F4BA264AE15C6F8A25D86DB9CC5F8C2892D51A9BB34020BB3A667524596EA0A994149D29510567A981A9EA3C0A0188003B68DEBCF47DAED78A29B52A21C96670A00DBABDBA5AD7D7CEF8B197063C3363CA42A8F8B72672EEBD4D6DB29665E670DC9B4C36396A67C8940D63430B712DAF59D2A29558DAD1455FC17836292BBBA992950591A01770437270090DE9CE29C622BA72E9043DDC9361CCB0B7EB189CCD2E0F717702B3F53CD7E0D8D6AB593F3532F4E664F0F9539C76A529274D0E17EB55BC245B69B14F4D325D0FD46525CCA3C34B4941753BAA34DBE24FE18B87F17E1FAEADA6A296A9A69D6A49125254C997E101BFA58061B87F2CAF05E21525694A97A91A1606E0EE4F91B7CB4BB9CB4CC7C379BF822838EF05D55550A35728A5CA712A4A8D2A6A554B979EA6D54A55F673D28FB0FCB4C3640521D42C5B68F9B5ED93B25AEE19E24AC948A65CA9299EB0C94948090ABE83567E77B98EE9C0B1513D092EEEC1405C90D62EFCF53C847A2304F29A0A012BD09D601B8D7A415A8136BA54A2549FFC4FB46B857D02A454AE5A81494923996D6EE05F5F96968CC01CC01777BBE9AFEDA457208EA2D16F992B2E8180B33FDDF7E4768E621122108421084210842108421084210842108421084210842108421084210842108421084211015804DB4DDDBF4845449959C82438D4BFDDF9F26D621EF433B5BCFF00B3C2F6DFD378AF142A9A932D232BB31DB9E9E8C4BB9DA057983331569763F7CE097D2A04A54921240277D89F5E9126660F3901F338BBB0D1B5D7EFAC4B34AB07F3A8137607D76F9444DCDEE3AEFF0043FDBB44CA7C34158135795208DB5F5058F5F5D221EEE60F0855FAFCC92FF43AC4AB0A08240569FEA3DADFBF6B6FEF179381D34F4BC9580503C4C41E7E5AB723689D27F332C872EC34274E5CB71D6FA344A9D66E6C6D6BDCF44F7BF7B0DFFB768A19D82A500E59C333B070E3DDC7E9CC44E3945B3026D6D1F5B0E677F28AC90B02E1371DCDBAEC3F7F58903029F32E9989200D5881D776BFE9AC40540753CBF7E51245AA74A54898B94BFCC82527AB59E2205C03CC3C225C21084210842114B58F886DB5A0A9B1CB5382D70E05B9A1BDEFB09758E728906C937B0EF97F0E4DFC1257581B3A7300C6F74FCC870E1F66D629AA4781F2924050059C0B5DCB86CCE0462C3C65724D19D3C0DE67CB3A944DD5F01CB3D8BF0E16D1AE624DCA234AA8CCBCD28F9D097D0C34D5D3FD4C9DCEC23D36FF004F9E3A9838A1587CE9AC99B3E63A0A892B42800A4905DD2A4B823A9058968C76988154DE27705FCCEBA16BF4B74044590F87B6613B995C2565156A69D5CD56E8B26F618AA4E3CBD69667245D409D0FA89BA54A957A502924DEC81DAD6EC8F8BCE19A7E1DC76AA6524B299752B339194312263A880CDB96E6D62F1B1FC1554D22592C090010DCB53A33F2EB7D418BCB3D4F4EA7A74FA7B7A468F041201259C3DC73F58ED244D3AE80805CEFD086B7BF3E5108777D7E5FDE2B654C09DC17DFA9E8F6D3D37E88E148CA1DF5E8DCFF0068AB4AC2B4E57F97EF0882228CABCE16DBFF00D73B32DC8B0861C616F4C2ACCC9A582B7A66A13248F2A1965C4AF5764B67CC3B751F643D9D5671A6334F462495A7BF77082A073252004B0D2CF73AB9D75D0AAF9A64B9CCE6F62430040D36EBD75F2D0FFC707C52710F10398F5CE1D7292BAE7FD1BC1B55758C413B4F9A534711D592A0C541F438D2B42E496DCB32C2028AACB43BB0EDF46DF08DF0E949C13C35455F5F448556CD22A2953364248944A53926AB33292A494920338B17731D57C4156A9B50A4A56486655C39E637B0E6E5892DD75CC0E294DA92A6FE1895950972BE6ACA36D2B71CB24DF75586937F58F4CB0BA69384D025084244C291994078896F5F5FD230D9CA52CB3800D85AC06970FB7DE9695282E292817256A0800752544016F7DE2D53A8AB2BA699A952B2A1454C1F4776B72DFEB13A54ACC924DB28E409FF001E47773BC7EA6FFC3FDC2C61CE1DBC39B256A32B20C3788B38B0C51334B115614CA5152985D769A99DA7D39F5DB5AC53933B34DA35AFC9CC20246A317112A655242092484949BE9B6B7E5BF5D358B74D925CAB53C8727D75E6436FADA339127284B2D2DC74AD6A4056E9B286C2C93B9B691B5FEB6BC4B4E16A924AC28050D6E46F716B9BD87DB514C96924D806E8DB96BFDDA3E838D5D011AF4EAB017EFB5ED6BF5B7CE26A8D42C77685293DDDC90ECC39DC587CA28A653898921EE3700797A8766FDA3AF54687233327372932CB532998977DB5CB3E84A99984BADA92A65D06E9E5BA096D7706E851041E865D7D18C7B0E9D87D534C4290A490A16636D0BF9D8BB599C08829C2A9E6A402480C4598F4B8361766FA6B1ADFE526246F86BF10FCF8E0ED15112B8533265A5738B2BA9732AD2891AFD525A9F51C534BA7B57D09A73530E56E6101AD23426E509DC8F1AFE377B12A2E1FA2ACC6D146801A62FBC44A17CC933029652FCEC4E9A79F7070C5794776E45D817360469D75B1F6DE32B1A349B9042AE42EE2C39A9252E948EC953816A47FE047BC7815C47290BC4AA9494B253354966FE82DA1BD88F23CDE3B9E8661994E8512E4871B3FB6DB73F9435EAF2FFDBEDD7EBEDFBBC6213D000D1ED63A9163FAE9156033F5DB61E508B54730842108421084210842108421084210842108421084210842108421084210842108422242731676FF00205BADFDA28272C8594B5B5F573D2117DA296094B00A1A03A03BBB31DF9BF5E465779D3E7FDA20A525092A528A529054A501A8A401724276D440DC0B8B9DA332C3B099B5F36548A74A95327282101092A24A8848B80589275D1E38554A6482B53654392E761ABDADA6BB34790668678E5464DD25755CD2C7587308D292D17C3F55A9B01F521214A24C89525C3B0FBBACFE368D91E03F869E28E2B5CB4A696A5417909FE12D4121577D183F561637D445B26F13D32092932C120A5C3055AD6BE9D6DC9C02D18FAC4BE365E1DF85A6DD929CCE2929F536E9639D214A6D52C4A7FA9A26747937201B0B9BED1B172BFD3DF8D2BA9C4CA6C3EA56A290ACA896DB6CEDE7CAF7D18D9AA78BA9E5803BD272BB15A9CBBBB390E481ABD847AB65478A670339C35993A5611CF5C38AAB4D8024E4EAE19A6A02DD2004A9F334E849510906E9EDE9B46118CFC0EF1CF0DCA9AA9D4159E2709CB256A2181D9398BDEFCF48974DC5F2EA4AC256924725358D8824DC686ECCFE76BF192AED32A94F6EB3489DA3D425E7480CCE532A08AA3136950D490C3CD2121BD5D6E76B6C235478FBB18E29E1A9B34CEA6AA09959BF32169208BB9B3B80EE0B737D1AF94D8BF7A52010F66BF26B31D5DF979B3C7D7438B99681374150DEE6DBEFD0EDFEFEB1D1B35389504C5217F884149218BBB827672C0B5CB73EB17D94B331399811D2EFA6C3CFD3AC5609D2026E55A45AE7A9B77FAC5B264C5CD5AA62C92A5172FAFAF5E71562C03F288C411CC21084210842291F2BE8737B04DBF32477BFE47F18BB505412052B3898A6D1EC4DF96D667F944339FB85B6CE4DFA06D8E8770DEB1E3BC43D065B15E48E6F50E698130DD572E317C886880A05D98A34DB4DAAC76D94B041B5C6FDAF1BB5F09956BE17ED270BCAA2913932D44681D6A20821FF005E83A61C89853582C7F3366EAF7DDC020BBEFBD846B2DE11D5C99392398B84C927FD2B99B5861A6093E444E38C35603A0FFF0017A7B778DF8F8C897F8FC428122FDF6134D5414392FBC1AF4CAEFB9B35ADDF1C17519A4CBD1DC020EFE5D5F43CF668CB4479E4A9241286163940276E96376DADE71DC32A6121373A0F22390F4D2DD6110F766E19C0E7A6FA3F9B721A5A2BA5AF301AEE41DF58449A84B240218A4E80D8DD9E2E14CA398A6CECC4F36DC422922B23E178D9F17935C2AF0818965F0AD4E624B32B3464A6B0BE1D98979A32CFB54D9D6BE0AAF5261E4283A8765A5A65443890157652014E916DDEFF004FBECE287159B49595F432E69CC95998B9799921293943A48CC6E120903335DDE3CD9C72B6727334C22E580243EA6FC9831BF9911F9C25467266A939393530753930B5A5D55C90E85BAECC28F4DD0A7E61E5D8F55AD67A9263E82387B0D451514B19085327C4ABAD59400092752C00E6C00168EB4AC9EB5CD27312391F7D01EA5FE778E1A1050A51161AEC16475568BE9076DF4DCD876B9F58C8CA94AB124DB4276F2DE284924B9F362E7EA7CFDF68E632E8967E56634EAE4BCD3A53FF00772DC42C8FADAC2262274C96190ACA34616F3D1BEC472662C2540288041702C0EBA8DE3F5C8F081CD2C3B9ADE1DBC2862DA14CA1128CE51E13A0D4E4C283C69F896528F248AAD397A2FC84C93E80D213B69D4404A7A454CB190029B12351D768B4AA6ADD5E32C4DC3D8B738C9FCB1525B4A1D480E2494AACABEB29362A27ADD46E6C45C5E261512083BFEEF1095920825C6CFA81B0D741CB6D2394E1BA536483E636EBE5D8D8FB1DEC7F5B4429480261DCA093D5AEC59B4D6FCA244D52865092C5C6DE7AF43F6FA470E614BD0BB69B86D5E43B6A2524E920F5076041DBAC51519589732623F302AF1004E5653A481B335BA81D627A91FC30A03C4DAB39E66E072258C6893E22DC4BD3E5BC7F32127B0756D2FA7071C3D80B10BAC39CB765CD7692D48CFD2F9A8513C83FCC9D65E6494A4A4AD2A4D898D69F89CC1A8B17ECDB1E56272454A95433D402C02954C492467CCE6CCE1DEE1ACD19370B4C9A6A129CCE01F26736B3D83FE84738DAC03A5EE9A8730735209B90DB9F68D26F73E54B6A4848EC9000B585BE4DFB56C29143C438AA6911DD4B1513825080C01EF09D9ACCC06DBC6C3E1CA50A79409D833ED67B68DD03EE2C2D11D3A763D7B9F5F7BF58E97A70B54C2959516D5CBB312ECFF4DC6D175413B926DF3FD37B44A2F7B7604837EB6B6DFAFF009EF795501215E1003BBD80BB9F7F3E7E7132268A7842108421084210842108421084210842108421084210842108421084210842108124036F436DBDBF7FDA2A6453CCA929972802A7B9DEE6DA5CF5897952661240717DB90D7F7DA292DCE5A52544DD6A0D25294DCEB7886DB51B90129694A0B593D12937BF7ED0E19E12ACC6572282992A3513141072824E626C2C2E58B7937A52D6AE5CB92A3605AECCFB0FAFB07D630B9C78788DE37C298EE83C25F071456F3138A9C7336DD2AF28E0345C16C3EFF21BAACF3AD3730A945CB235CCCCB818D61B45F736B7B05F08FF0009F22A25D1E37C5583CB9D4D29529495D4484CC99316485044A42C329B3254B24A4049719882074F71062D52852E5CB9EB009219C84D9FF31E476B5CED1E8FC3F780DE12C72993CD7F119C7D8A7890CD4AD25BAC4E526AD589D7B07E149878077F94CACAD41E7D13ACB0B245BE0D841BE92848DE3D8BE0DECC3867014A1386E0D4D440C944A5FE1E54B946621398B4D08480B3E220E627D8475CCDAEAA512553944B96BA8E537FCBEC2F6B6B17F156F042F0CEABE1F3499AE16B2F9B61682D2E72430ED1A995DD3A059C62A6CCA1782ECAF2AB5A4DF73EDDC48C170F93232269A58480080122DB36835636B3FCE286655D428879AA2483B9361AB07EB76D635CFF0013EFE196A4E12C27883383821AAD453354677E2EA1957594AE75C7295A1E79EFE52F075E6FE2590D14A161B68A750B1DE2D8BE1AC2E7A66AD54A0651FCBE1777D1872D47BEED558755AA5F7854B2F6377363FCBBF93927D235DFE12FC4FF008C2E04B158C2B278B6BB3384A97555CB55B2DB16CECEA69B28CCABA1A7E45EA7BC5F625665F4EA4B2032A2C7248DB546B4769DF0E5C1FC7D4F5B2D180C89752B4AC99F269E5AD73164165CC0420BBB9529C936B168BCD3633552E7272D428070C92A622FFCAC6EEFD00667777DE63808F124C92E3BB2F64EA981E6DDC3F99547916062DCB9ABBAC2E66993250034F353C5F52E7DA9CD330B963F0E8E6A1A5393225DC4B4DB9E15FC547C22E39D9F55D5575350934C5739525726593296259F180C12465702E901EE1EF1DBDC3F8D2A621089939401482A25442812465601F5DFC5D37719109399334842D29284A9295241595948236054A082AB0EAA2013D6DBD879BF5342AA3993A4CF9051325A8A541408292090400C7FB1E519FA2A25AE5856619983920024D9C8D407F38FAA84690751D5F3DEC07B9FCCC6315292262B224848D407B12778E33B90C6C5B6D5F96BFA7478A04DDC3626D73B76E9E90414849CC1D4D62FADAFFB83ABE913C0F0126E5DDF95D9A2788220842110006B0A201005AC7FC743FBE9175C2552D3500A920A8174A88D2DFBB1F488165C141FCA41717EA7C88B79C7C5C4F229A961DC432602344CD0EA4C2D0A48295A5C96712A4AD3B85055EC41DADB5A3643B1EC4AAD3C65844E97394858ABA6961492CC9135362D77B9E5AC6258A23BA9AE9606C5C58EA7705F560DB316D63524F0A843D2353E25E981C586E433567D4A6428F2D094CD3C52023A0D3BE9DB627DF7F5B3E26A8915381F0DD62E5833D5C39440CD6B96EF8DCF477B9B5DAF78EDCECF14A5E40A512925995B9E9AF4BF94663BAEFEBF48F34B12795316124BE6587D086FBF48EFE4212508B3002C3E9D1C7368459BBC5FF51E7AFDFB6917196125CB0D06C377844D98B52A5241BDF5E419FF005DF94562404FE5B6DA98453C45994773CB58D74FF89873BA7313711F95D935293EAFE4981B2F25E6A765D0E12A454AB55AAEA6610EB62C017251B9548513AB4E9DB611EE47FA7C70148A3E0D935EB97E2A89F2E524140007712E54E5282B7244D01B4D0F48F30B8867113160100A42947AE674BF2D9B5B1B6ED1AC53056865AE6274152494B5727949D6A4A51A8EEAD93AEE6C6EA23B47A8D3A522494CB400025212C2CCDCF4BDFF00BC6066667274606FE77789D4AD42D6B6F7EBFED126110510A001B8006F63BDB6BFE90810E08E61A36B4FE1E1F18AC39C25D55FE13B3E2BAE48651632A99AA612C513CF38E53F0954A69E48765E70ACFD8A2643E82A08D69499717E80C578D07908B71483A8DEFB7BEF1FA0EE12C7D84F18D1E5712612AD5371361FAB2133F2558A14FB351927E5E6ECEB4FA48712FA50B4282820B29D17D361DB9F46FBD638CBAB004B921C580FECD1DAA6EB52D28CA9D7961080DA9E0E00E14F293F7493A079964A4580B00A3BED1CB7F0E6916210A62CE1F7F97D625CD466CA00D54010031DCB8BFDDBA88C417895F8B1E49702593788ABF5CC4B213F9A73F4FA9C960EC094F9F969AABBF539995986693507D8967DC7A5E5197D4CCCBCB7101686C28F2CD8034D87247E126A9475CEE79DCE836E7EFE95C6514CA7B3117D7C9BD4307E863F39EE1AF31F317895F11ACBBCCBC635176BB8BF3033BA8B8B6649042993395965C769CD383CCE4B53244A9D6DD524297F0C905B48248D70F893C424C8ECD3880949294E1B5054B0CE8374A4B13FCEB64D8D8289170D17EE1796915492080730B36A4060E4793E81F9EB1FA7053D85CB25942D5AD6D4ACAB2AD5BF99A966907724DC8D36B9E9E91F29BDA75548A9C57129BE1635338D88DA6AC3316E5B01D3731B05463F832C0B30FE57BDBCC3E9FB5AD1CE70DD57B761F8EFFAC74225483357959DF6D72937D1F6E9E80697397A9D45B7F3DFE71407DE55B6E9DBE57FC7F3EBE916CAAFFBA5B460DCB53136278A6842108421084210842108421084210842108421084210842108421084210842108993A54AD0490AE52962C2F7D24DEFEC122F7F6B7A45CB099FF87AB44C37495841D6CE017D3CFDE244D59439B245AFCC373B6F6D74E66D1615E23DC5B49F075C2AE3FCD6626A5DBC4F3126E61FC172B30A08F8DACD50269C9750E00A71B5C999BF89416D0A512D0074DEE3D20F841ECC6A38DB8D30C5FE1953A9BF152664C640565928295CD5B16072A12B56AE74E4630BC771212A5AD94C729CA3472CC2CC2CEDE641F38C7F7F0CA70E4ACC9C2F9BBC7B66DCBAF10E6766B63FAFD1B0DD62B0CFC43F254095A748FC5B94F997F5BA96DD7662A124129D0121AD43CC6C3E9C383781306E1EE1FC2E9A4D3CB94A972501084A06601878CF86EB5125CDF4CB7023A6715AEEF262813E2510E59C5CED72036B6BB5D89D36E51470E34D32FAD33086957487D943AD6806E94A585DDB4A80000700BF4BF6B67E8912245929003B8B00A7F30FD3CA31E5E562029C10406705C6A1FD9F48FAA25006424E97AC494F38056956C2E8041081600694D8003A5A2298A0B0A01094B800336BD6DF3B9FAC52CC3A1F3D874DB48F873F467E698790660B4B7016398D80AD32CF022612126C2EA096C2556051BE9EA6244A94405CB2582C8DCDD9C33076D7D7CF5972CAD2E017059BAB3907D3AFD05BF372FE270E0AF0EF0F5C624866EE10A44BD270867A4A556BD59A636D2053958B6526251C9FA8CBB2072922ABFCC82CCA0436D491964F2357315A66CBA9A5C1A5F7EA405E662A0525F7B1046A092CEF1512D531335C9B6847EC6FE567D3578C0C70D3C48663F0A79A18533432D310D5E9556A3CFA5CA9309A84D2E4EB34D0B42BE0AACD15944DB2A4A2CA2F36E95AACB502A488E9CED13B3BC17B5DA2ADA1AAC3E9A689D22684AE64A4AA64B59493990A5A5C3DC162C4B1D4465F87629324196D30A7291BD95B31BB68CDEB60E1BF4A5E0238CDC0DC6A70F58433770CCC49B35B72972F2D8EA84CB9E7A262465A422A32F2A8202DC9144D22650D3CB432484B7F6635587CDB7C4FFC35D7701F18712F7744A95492EAE72E4A8206554952D6A429243A4023290E5D88700C76A6118D77E99633853B0D6C08DB9E85DDB5B45EECB3E5D970FDFECDE515360D82C364F90AD276495274A8004FB6DBC79E35F469A7A99B2169CAA4A8820F47BF3BB68DA18CF698F789045ADA6CE43BDBDAE2FAF58AA079B55F7DFF000E83FB7CE31FA8484CC2069EDA74FBF95EA492C0727F7789E2447108420ADDB206C6E77FA7EFDBD62AA842BF152C8D2CFEE7EFCDB918814EFD0254FD1C16F7FD23E7D4965BA3D4544836937CA947FED2D2811F203A8B7AF5DC1D8AEC61C7166119BFFDF69F7FFF008A1CFB35F95B68C4F15FFBC860C1DC3EACE34E572F668D487C2E2FFEBBE2CD03CECCC667CF00BE9A15F113009481B13BF7E84C7B2DF11CA95FF15E1B040FFF0067A8D86A481DE9773CEC0E9666BC76BF6761CA741767035D1FA79FF88CC3A93A075BD81ED6E9FBF48F2EB1663394DA15ADADD7972E9CA36165FE44F94489248B9F5FF11645000B0E5FBC57CBDFD3F589A2357FDB479FFF00E222B2112A11A86F8FA2A61EF116CD7F8A4287C3D3F0DCAB416A0A0CB7F0DAE5C36029574BAFB8E005174A557D453631F461F01E8454766B87CEA719A4CA9B366A94001734D4EFB87B252EDD23CB4E270B4CC9A4921C33E8D73AB585F5D4FEB852056E152C8D94ABA45C6C90026C37E9704FB5ED1B9F2ABA4D5CC9DDDAF3144C2820BB82ECDA6DE7BC60F48ACC955DCE67F4D3EC40A48DC88AC4CB5AEE90F157108196A4EA3DBEFE908A8A5A9296594A9B5CBAD84A9F66CA423E2125252B52C23587507514A9BD4012AF36E22789C860EF61CA38EE147407E4797DFB7AE453859F156E37B84593628F94B9E98B9BC3AC329699C338994C5768B26DA7492CC90A8AE7D68641012D37CA6D2DA0694A520DA1DF23AFCFF687E1D77B1E9616F9FDFCA2EDF31BF889FC4C330A82F501DCD795C3D24F4B99375541A0D1A4279D4A9050B509F95916266512412B4BB2CEA5E4B81200092A22A64A84C4CE4A43954B20381AB8DCE9AC4999216921405C313B3A6FAED63BEBEF186ECC2CCBC7D9AD89A7319665E2FAE63DC415175C7DFAEE21AD54EAB5F9571D24AE5E4AA35079D7DB92255CB54BA6650DFC39E572CA7CB16B33E5D052CD97395956A0B012937054AB5C7D91CAD1397365AA5F77FCC5218368C2EDA5BDB95E3315FC3FF9033F9C7C79615C58F49BCEE1FCAEA05671954A6CA52A949279B949FA5D34BA4AAC56E4EBF2A86DB692E3A0AD2EA921B05C4E8AFC61717D3E07D95E3A99F552E5FE2A44F904120AD484CB54D4A5201CC06748753072E1F6395F0B51CCFC44B594380336D72E3D1C0E6413D748FD0EA58ABEFA9455A8ABCD7D942FB6DF976B5AC7A6DF2C3C538DFF00B955D6AE4954C0AA9A8208D6F315CEFF00DFA391DE7492D4254BF0B0B72D585BD79FED1C85904EDE96FCCC6094C99A998553028073A91A72B16317048235163F5FBFBD629D8EABF6B9BFE000FCE21A90E429F98F3B9D3C837CCC4713452C2108421084210842108440903A9B4210041E97FC0FEB68316762DCF6844610888049B08E0902E610208EB0041D21108E610842108421084210842108440AD4D942D2D9513CE6B620795C975807A816D6A03CD6DF71B6E2FF004B228A68A144A98F55327212B961C162A606E189361AF40F1435CB08965FF294E63B1CC0B01EC1DF6F38D3C3F8A0F3927D998C94C91929C537212B2A8C5351924A9612F4F4FD46724980F1166CFC3A5B6267515142529BDEE081F473FE9C3C0387D3E094B8A55CA972EA57202BBC29752410A0438048EF12E92E7425CB061D41C4756095B1163A6BA69736D6E4BD86CF1B007F0D366050719786565452688B9555430756F1461BAFCBCA2521F91ADB7569BAB3827084A4EB7E9751905A57A94DADB75094A8A8148F5F2A27833E549A7F14B9210124386012FA300C19F9FD63AAAAA62953924E85403826C1F90BDF9799D4131B0C34FA145B0370B0AD2373AB47DE3D3600DC6FD77B036B45610B37CA03B3B9DC8DEDCCF96D6DA5AB29D1F9F4275DCFE91C852D035592A2ABDEC3E5EE40E9EFF58890145EE9037D4F3D989FDFE929692A660ED7D5B9347CC7275925C0B250A6D362DAD41255AAF7500090426C2E6F617173B8B4D989C892B749510E3A14870C4B6BC816717244474F2AE41B01A1E7A92CE03B5BA1EAD7D18FF8BBB1961D5D5786FC0CEADB7EB32CCE259D532563E2A5D970D092DBCB4121C2CA88202C02D9B1B288B18B752CA975B5193123DD49CDA90F606EE2FD18EFE6F15F2E5CB6770FA12D6035D1B5F73A794693201698E7B6EA14F3CAE5AE59492A536D9FEB2549D1B586C95157A6D1578CAB0FC16405E05304E9A43148046BAB93E77B9D40F3E16E2E0D9DBFBF97F8BDE33AFE045C6D4E70DDC51D172971254D3FF4D7399E56139E71F7969A66199E9971BA849559C973E65393B35229930B9665E712A9DBBA10DEB58D0BF8BAECB29F8AB822BF1AA697295898C3D73E7CB5A56A99316A081DDA08429399398B66284324DC1201CBB87B114226CA4155F380AB8649626E753A36E5D88B1263F429712C89979A61485A109974256DA8299529B68257CA522E85252A05374F955D52542C63E587B4BC1EBF01E2BAEA3A89264A935335013A394AD419AE188040E40477DE1539132421492E08076E5B0D869CB7B36B505C24156D6B0BFE9D3DAD1D775685A56952C315005BF5F5E5B45C0AAE07325FE67E67EF9453E6E9BFE5FAC524090358748473AC414404D8F53AADF808BCE132D3DE77930003F95D892DBB7420EACF66EB094952AC1CE520F47763F51BC7C1C4EFA65F0CD79C2A09535489E741BD800DCBB8A2A247A0DEC0827B46C376254D3311E36C26928D39E68AA9134A458E513439B1E874E42313C70192B0B5B0043004E97BBF262395F58D4B7C2957F113FC4D546C541FCD09E710E69235B6B9B994B6A04F40A536B1BEFE5DC0045FD71F89AAA12304E1DA252DA7CBE1DA24AD1C940CD7D35235B58FA34769F6673133CA3BA72CA0E0EDA077E4E35D6CC63316B3A80037363EDB903E91E6AE2293366A8A468B53FA98D8947E50FAFF0078A69040DFD7FC459A62160DD26C1B6D6F15C8DFD3EFE713417F9123706FEC3F68AD009D2112A39C8AE5F31FBC6B5BFC4959293D8578B9C0D9A4C53DD670FE62606A731519C505043B59A1D5AB2E3CA2A2AB95094764C7C82447BD9FE9C5C6D4B51D9DC8C297350152D4165C87509B2254B091AB5D0E7A5F58F3278BE95CACB06208D18D8A8D980F61FB46B57CEE5A83695EB4A755943B8E62BE43F1FD23D0B451A28A7CEC8434D98A592E2E4DDFCAC1BD6DA475A53CBC8953867516E7EEE77FF11CA26E807D6DFBFC445F29D7952E1BCDF99E9F7789F14E219AB37D1DFE675F6E5A73D842114D1CFE2903FA8741A7D6F0843F168E6BF6FEF1239D07CFFB18953A6AE5CB59964F785242403725C37CFEF588913133C94A7313637E4FE71C995A6CF4F3CCB124C97DF9871B6589746EB79E7561B69A4FA95AD4948EF73D7BC627553A6D252555762CB32A54B94B5669849484A743A9D0072C09DFCA3958795CD0A4A4963A1536AF63A077B6BD5A3F41CF012E08A7F864E1B99CC6C6545FE538E739C1AC4C2669A099C93A126589A7C8254429486A69A95969CD09504A8BBA88B931E0CFC7976F52B12C46AF86E96A52BA294A54840490C52A27328B7E6CC492333A8021240668ED7E1AA254B420E5736B5AD70C2F63943FA69B88CF280802C84942412024DEE3737EBBD89B91EC4478D756A93DF4C54850295A94B600B3A9449FAF93EF1D9D252532D20F9FD3E87D62316F9AAB126CFAB72FB689B08A098B0A7DF603975FF10844984210842108421084535024FDDBFBEAF4EFD47E1EF1588952B2A54A372013AB071F7FA4226009B5D23F1B9FD0FEB102BB80E01162C0B39FA5C75F9BC227D27FED3F844A3325B6A0F4FBB420411D411F3820CA53955883B39047A3B75D3A6F088454265D3AC7B86757D0DF4842E4F5378A79A84CB5654B33025B997FD1A108970842108421084210842108422520907D01246FE88BDFD8DFFE7AC5DF0341FF0075C396C1BF132EE6F70AFF00163E6D141884B0A92A24EC4F930219FADB6D4346887FC4CAFCEAF8AEC0ACAD0F3E0E07A5069B48251C81569CF8ED7E84CA73436AB850558820EF1F50FF00008B4FFC0E926BA33212942C921C20CB4E501CBB39BB753B3C748F1120898B4904D981D77E5D430058ED73AC73FF00877BC50F0FF0499C95BC98CE1AFBD49C96CE6A8D3A625EB69716E5170C632D4CD365E726DC1AD1292932CC9D2A56717A741E5BA5C17D4A3E97D1A02E6A948B8CAEE1DC11772FB696D35F4EBA9D2CE77BB82EDB10496F3DC1BFCAF1FA44E18C6341C634762B3862A74FA9D067A465A6E995B9175B7A5E7989C4F312A977104821614149D2075F58BA051D4BEBA13A91B9BF9368FE912F22B97CC7EF1D9DAA830F21B080A4AAC752549F30B6C4281DF7EBEB623D601B7246F6E63471BF9432AB97D22DD3886E21F2A7874CBEC519A19B18A6898530AE19A7CC4D4F4D55A65B61E9D421B71C3234F0ABA9C987F9605900281D3BEFBF1356E05D8DEDCF466DF6B368DEB13A58660D7724DFC98F46F9C7E54FE2ABC74563C4178B8C5B9CAE4C4E1C2F4F666F0F604919A52912B4DC274F9A3F04B6D92797F15556D4DA92BB29C713284956D78A39A3327762E0B6CEDABE8F7EB6E6D13D80B0167D99BCFEEF18D98B7AE4289203100D8E96F93F56F9168E79F97DEB1DB702E239CC278AB0EE2191506EA940AE48D4E5A6E59CD0F32A62690FB3A948526CA4B2850513E9B82230FE3AC1C62DC3B5D4EA405A0D3CC95312D981CD2D41208B970BCA459EDAC5561072553B16CCE1DEEC6DD3426F1FA9670479B433BB85CC94CC433089B7EB781E88A9E792A0B71CA8374E956E78BAA1725C3321C2A5124924F61B7CB97C597670AC1F8EB1298B9441975B54E5807095AC39B6B6B0DFD9F60700A90A9090EF9909239BEA396D6B72D62EC9E074FB0EBF88B468662E3255996E5921803B36B19425CA8747FBF7312B3D07C8FEB16B8897A0F3FD0C15D4FCCFEB08893A0F21F48A6BE83E7FBFDFB45DA816020A7FF26EBCFDAFF3B17885133F8D979DB7D4027C8EBF28F38CD99844965C63A9D53A5A12583710CD05DED65314F98706E3A5C8F7B7422F1B65F0B346A99DA9614B667EEBAFF391B06BFCF5D34C538AAE84BF2D1CF3BDC7A9E46FCE3564F08C6D7319759C5592D8D355CD5AC4B7340009129301D1BDAE47FEAEFEA3574F5F4DBE2CD229EBF0B4920146074A0BB6A0CD2DE77F33B4769763F2DF2962F98DDDCB59DF51D7E96B465F7A479C33D6A54E98C4B672D761AEB72DE87CA362C060072845BA6AD4545F4FD9C7BC57A3F2F9FF008FD21125C91724FADB7FBF78AD46A7CBF5108E226C7C1F19DE0B4F18BC29D79FC3B26A99CC0CA8969FC4185A4DA6C7C74EAE5A5933B51969274243F3C27A5D86E5D896438EA4BFCC096C294ABEE1FC0D76D5FF0012C5E870C9F53929E64C44B9C1D4A025AB2A145AE73252E52C1C1D2E43F9CDC4F499D2BD0EA43D8EBA1716723A0D06B1F9C756E9351A2562A547A94B38C4DD2661EE636F4B19679A75A714C3B2B30D290D943CDB8C28A9B52526CB0A293AAE7E8338771F18DD248A90B42C1968216852568525690A0A4A92485020D8E8085070416EA1AA94254D291D4EE2DB38B7A7468F9BAD164137E6BE0ACA7A048476D3DAFABD3AFC84675217E1D5BCF4D8EA7D3974114D118826ADCB69B39B020BB5CDAF77E50D611144A34A765003910EDD1DE293854748483E5209B5B7BFEBD7A7D7B4239FC29FEBF94576D066661A4061B702BC802DE2CA12A282038541C6C158EA946A3AD5646837D3168C571397858913E6A4A922602A00151290E48600DB726CC05CB457E1F4C04E2E41195EE05AE2FB7DED1B217826F852D57883C6949E2033A69150A6654E079E6E76834DABC9AE5063AA8CA4C85CA2D2C3ED365C939598487C2ACDB534D4B00A53C976CBD09F8C6F8A6C1386B876AF0AC26B244BAD4C832E68913524A49967C2A54B252E34201707C2A014E233AC2F0E4CCC85B706E350DABB3EDD5F7DA37B6A733234A97A653A932865A974F9344B4AB01BD12F2ADB4D169A6A598B06996DA42434DA1A4A52840094009000F99DED47B40A8E38C5EAEAE6CF54D98B9F3157249578CB00EEE436D6DA3B3F0CA04CB976172035C83622F6B8B73D343ABC72DB37403A8AAE546E7DD6A36DFD2F6FA475685AD28F182936B10C6C00B69A90EDD7945F48CB6E407D044F14D3261248D411BFCBD5BEBCA38844984210842108421084210844D4C89AABA65A8BF263FAC482AB9015BD839DEFA74FF0F103A7FA9447A5B56FF86DB7E31552F0CAC9BF92513CB5BF93031095582893AB0777B7CC40AD29BA82D4A237B1D76E9EE7FCEF157FF1DC448FFB0CFD2EDCF43B7AC449582A00A89726D7EBE8D1444E952F416C01EB6FC2FF00BEA773D224AF01AE95732D7A12E34F7D74E6044C0800B827CB6DFF00B7B47209BF603E5B451AE8EA2590152D449BFDD8446CDCFD4BFD62112549524B28107AC2110C210842108421084210842108A0F95843AA4B6A559971B4DBA5D6855D42DBDD3AB6575DAC3A45D30EA8EE6B284BB659F2D4DB125635B7D878A7AB4A4C85DC151492C5EC0386E4C777E76BC69B1FC509960ED371AE46E67C934EA64AA987BFD34FCDE93A04E07A7D7A1C73BA87392121449E9DA3E913E0031C54EE13FC30983FFC24B9A849672651CD30870EFDDA4826D61B474BF11A1A6662C0BA92E0B7E6240172DA9BB967363A46A4295292CA5B6DD1F60F1967E592E061B525243EA7004A9096DC1CC2B4BA08536AF3852542F1EB360159DF216730FF00B761ADDBAF37FEF1D753D0339F50390626C3561A12DE4F1980E0BFC7038EBE09E52570F609CC16730B064AF290CE0CC7D2D51C45252D2ACE94A25E5AA3CA7A6E59B4A404A3913C8E5DBCA5317DCE797F9FF3B3696BC53F76798E9F7B7CE32A158FE2DBE2DA7B0F3F4AA4E45E50D0F104D36A73FD4F21FEAE985D39E29D3732957AC4D49385253CCD2655C45CD88B6C78CEAE9ED1CF7679C60AB8BEF123E2C78DDABBF53CEECC7A857686E2E615298629B309A761A6CBE525E0F50E404B493E404B496D5372CEA9002B96A054BD52E62CB82C1DBEF7B7EBE91125395F7FBFBF68B0848242B5F976404A13B22CDEA0D809161A5B0B5040B79352B4D813112015B01FCCCFAB72EACCEC62284550A64B1B3900DEC03B1D3FC984519770B538D36CB652E38A75C538AD92B215B7FF0061BD937B800D858136B1932E761F8BCB9803242C39E63333685C73F23D62A685C4E770CFCBAB17B6ADE6F1FA2C7804623A9E20F0EEC0E8A8AD6E2A8789314484B2944A9425FF009ED40B6D82493CB69284A1A47DC6D090940005A3E75FE3EA5D1D0718574B960054C4A66B96752A6CACEA249BB924EB772EE63B77872A9D0904B949200B80CE40D98581DFDA336C5DE6300AB651036B5AFBFF00C9B5FDFAC78F58DCB51AC3340F0177D2CF73F63AEDAF66493992140100A47B80C47AEADB72788B3D07C8FEB16688D7A0F3FD0C15D4FCCFEB08893A0F21F488100F500FCE2A695653350068542DD4106FBE8229262F254A03B38B0EB71F53AF9DE2DC78BBAF35863863CF4ADB8B4B224B2C7182D2E93A0A15FC9274A4A542C52AB8D88208EA237BBE12E93BCED27095650A51128804ED98ECFC8FCF4DE31AE23567C8356171D4960EFADF7D9F5168D797C2429625385F9FAF21BF357331F13CFB64A767105BA579F71650BEE09B9BEFD0C6FF007C60854AC4E8C2CBB61D212E48B001561FFC4BB0BEBC8BC774763D2925034040BF9B06D762CCC341B464F96D940D4E5C4ADEE1409D7A8F6B83ABFCFE51E7F4CA0CE55307F3171AB17F3BD83F9F222D1DF4410483CFCADB6F04951173D2FE53B6E9EC76EA4F7277F58A199879672837D1F5E5CADCCBBEDB3456205B5BEEC5DBD34F567FA09A2827D1F732F3170A1ABE87C86DD7945721DF6D3E4E3D8C228226C656D72C971B5B4E279894AD2B94D684AC4994D890842925B98429775A913699842B5149051E58E9EECF38EF12E13C564E274C90264A525410EA09749CCE7C43981AB5AF1A1F5D86CBAEFCE5409724872E79B696E8DA078D5BFC5D7C0FDCCE198C499F1C29521893C67301754C5196B2A24E4E4AB0EB616F3D37410F250F9A8CE9D4876584CBADEA4325A9649592BF71FE167E35E92AB06A4C2B8AE64BA6026A2409A939D7265B240999495A94847894A968198870963AF5963DC348913C99254A195C0F2727A924EDA731BC69B79959499899495B9EC3D989846B784ABB26E29B76955BA45464A765032A521C4BAE3ECB4CBC1D5001A7194E83A092557047ACBC0BDA3708F14534B9B271591512D60144E92B4B292A1E152904954B2774CC0141AE2E63119D86CC960F8482350AB106FA73F47EBD3CD94A2969978B6B6D95FDE71652BF9E94A3CC3BECABC65B8AD5D32539B0F9F26706F0E69A87E8E1C5BA86D6E7959A626A50E421EE6CD701C5FE7FAC5343E975CD0DA54A07A1510DABD0F917659DC8D80FCE2D5438AD4075622AA7952C6AA0B48B737CC76BE9AC4E96BAB5003BA6B13A3EFD2FE5E7EB1EB796B9399A19AB5B630FE5E607C438C6A736FB12C893A2D16A53AEA153074A16EBB2EC38D4B361446A71FD2D907EF01BC63DC5BDA870870CD2AE7D562D4B4E10852D4B9F3A5A41081E2EED24854D2F6640262E12A4CE59F12147664A6F7BBBB3245AEFCB9C6D27E1C5FC3CF8A5AAE61CCDAE31E5D990A7D3DC62B74ACAA6A6A5549AA21452A63FD4EF4BADC9944AB4DB81D725A56664A67E2D2CA564B21E6D5E697C47FC71D151E0B3F0FE0D9D22AEA565520D4294A44C424B85CC9212A4292E4300B05412A215768CB700C113573C89E0A424666001DC1651BF319ACCE1D9AD1B75618C1786B085028F84306D26468986282869990A4D2A59A96939697611A589546848714DB36400E2D6A7DCD00BCEBAA52CABC38ED67B4CC738CABEAEAB10AEA851A852D4A4898A520151777255D45C926F1D8B478549A420A545446CD61AB5F5B0D198748EEC6E41049B137B580B77B0DBA6DDEF1AEB242535499A19665CC0A214FE23989F2D4B10DA7CAF92E7996059D830F2F705FEF7B40000580007A0E9BEE7F3DE2662154AA8A954CC89960B78123C36003B6DA3DB9C56CB59989CC753F7B5A2316F25EE6238421084210842108828D813FBEB08453D67D07E7FE610370473895D984B496DCD2A754EB886D1288F2CD285F438E8D434F2839BA55A6DA48B92482737E1DA2ABAD9F224A64A0A56A4A4A9419C1DC5C10DBB8726EFB45B27AA6A3358101D947460AB037D483AE8FE60463EF8B5F13AE153835A8AF0DE6A62C9D99C70C3466DEC1F44A3D526E78CABA9E6CA244F33293324CCC2D97192B43CAF315A9484845ADE84F62DF09D89768D488AD934ABEE1D295CE05089409DB3AFC36D0906C436B18AE23C41328D5972A09B96D4B790FD7CDF718A299FE270E1755509C9597C9FCCA6E9EDCCB8C4BCE3FA01525B274B8F5A4529425D2362528B056E7BC6D9A3FD3831A5D30994C844E51979D91514F30B11A242145CD81B5C69B30C7BFE71588999532527501D2751D490C1DEFCDB945E2F0E1E39FC1671158970F608957B16E0EC5F89A759A3D1A8D55A44F4E2AA15498712CB01AA84AD3448B52CA7149054F39E54855D63631D15DA5FC10716F06E1B5B8A4CA296BA3A09626542D351216A92145921684ACA8172032803BC5DE8B8C2AAA16997324A1256AF0B2560DB5B92D762DA8EAE1E333C8750B65B75B55C38D21C483D6CB485209037DC11D3DFE51E747196152B87AA66D3D4251992A524D8120E80009BB3B73E42FA677433D7529CCB0DB962086B3DF66F4BC4CDA8A9373D6FE96FED1D4B5D3A54E980CA0C2E5FCFD2DE515CB00161CBDF5BC4F14510C2108421084210842108421100A5A15AC28D82569D040D275A0A2E76B929D5A86FD40BDC6D173C364A674E419812132CA54145C174DC5C96B90367B96DE2867294B0A9792FFD43467B0D6F76B1F48C1F78F5F0EF3B9DFC06E28ADD225BE3ABF93B5293C692879497669FA722A52A6AADD929E616E5A41334F0E4849484DDC2537BFB3BF00BDAB228F1AC3B87A764FC3CDFFA2CC1694AD26A11DC8512A2C120AC28822E1F78C131FC1E5CC96B9854429F336E18B91A1366DB4F211F9DCBAC242E612A09979D9598026549492DB93330CB40B684B8569525B975B24A55AACFF302AE9F20F7DE9D72B0EA5A09D44BEFA5D4651395981091676236D4BF50C747EA1C425A244E0906D99CBED7F204B69BFED1B9E625CB90A08D04364B49575DCA5BD29BEE7A01197C9553CE9456898ACCC6C49D586BEADC9FD2F4E0CBBF8AFB6972C3CDDEDECD122920B61B0549B1F2AC13A80B92527512160DFF00AC28FBC5A26D55489FDCCB4B8248CDEAD7BBFAEFCE39083C99CFCF77E5BFB7510D3A55ADB3CB2400BD0000BB5EC4A6DA41DCDCA40BF7BC5C66CAA944B96BCA08502544DEC1BAF2EBF38854876771CA2A95950B102FFF00777F7DBA0FA0113A9E7A12DDE1CAC43BB59B4170DEEF10641CCC4915E2BA9588497B101D880E376D7D7EB0C82FAE85B4D768AB2D2F35373B66D242255B6420E9014E3AFA9012C8240BA8F994948DF42557B9DE302C4EB2761B4F88CC9A909935256524D9D25CBDCB3B746773A3C4FA04E79AC4DED61700F98040F2D79E91FA49F823E5954B2BFC3F32A29959977A5EA388BF9A62979B79010932B5B9F7EA54E7191A52A2DBB2738DAC296544820831F389FEA0F8C48ACE28AEACA69C954D44C327202480992F2D25401B2B2A466BB66D0691DB3C3F4BDDA50D7719893CF52C5F9D9AEDB978CB7BC84EA42526C13E9FD574926F7EFBFF009B9E9E541AB9955493953929CE836B3120B7CB571EB1D8D4F3660484148621DCEB6D0EDAE9EA2228251D3DC0BFA1B1FD62D315840218C0EE49F584722C00E501BAAD6DB6DFF5FDDBD62A29C01325AB56580DB17205F7DF6222DB5672CF42F7091F57F2D631DDE2B5881FC33C077105506356B5E0CAA4928A090AE5CE484DB2BB58EC3492493716EA0DE3D1AF833A3FC4769FC3632002754D1CB3624655CD0920F201F5F78C6F1D39D2A51B1082433D9873DBD75D9A30BBC26E63CB70EDE1A985B3326685375896A1D0F106329C969242DC79C2A69B5143896415F2B4C9750028951F30DADE9A76C9C0187768DC65418355D4AA52E7CB954D4E73A1092B2B284E752C654A493724861BDA3B3FB3BC5E6E154FDE225A4E59654429CD807B3107E7A39E8395C39F8B470DB9F330CE1AADCF1CBEC6ABE4BA9A3D7E61B91A24E33A948725E42B73896E9EED41E213C867E35C537A55CD695AD24F4F71B7C1DF1070F522AB30F9532B29C67C93259CEACB2C02573252495C9410A012A5848532B29394B64D23B52A85D59933A5CB969CF95C8617533667B91A101C8B68E2326D4D9D91AAC93753A54EB352A63EB52999B61412C960E92DE9796794E2403FFBC825A58DD048063543887B3FC730054C159453529964824CB2EE97D181049FB78EECE1FC670DC569D33573D285901C0367DDC392D71CC5F4E7CC2928365EAD4BF3B45B42DE60B7DCAA71B0A96E66E9B36161646A201D2AB75657896A4AE5AD25265AC2559ACA7215A03729196E4020167D445FD13654EA85CAA7216424A831770E3EC060E1DB94422D49A5A32F9D6A4F2BB39B5B61BDA296A17884A2ACB252520EFC9DBAF22D73FA1CB602803E9B9B1FD8FA46A6D64D452CB79440531218F4D2DCD83031A7250A7D07BE9D03F94533A4297B208294801C24DAC4EA2C1494943C41B15B85C6EDA6C8D8DF20E14E29ACC347E2115B364290B7C89594E801D0697DCF2BBDE282AF0E4D49CC407367B3867B925DC17D031FA45B2E737077C35F10D28FB39B394584714B9308D2B9FA9C9BA8AB85EFA5D13F497E43594151524381609FBC15B46D8702FC6063BC1A6549958A546594438EF96C72B657014C77D45BD62C955C3F2D600CA0A8001C0B3BE9CFFB0DF58C5E639FE1DFE00714CFFC7D2A4F30F09A9D5A9C72530ED7294892694A37B36D5628D545948EC0B86DEA7BED0E0FFEA498E224A51515899C84801495860C35BA0853F47663CDA2C53B85252941425B39008FA1BEADB802DBB473B017F0F9787EE089A95AACF61BC758EAA52EB4AF4629C414CF82514907ED19A452692B50240B84B80DAFB826E22C73FD4B2BEAA96653535404050621014496046A4957931E479454CAE1496E3F86E43ED6D8900581F36F48CA364FF0AB9059094D12994795183704BA9535CC99A6D3D7333F369B12E73A76A8F4FB892955ADCA2DF4BA6C363A8FDA1FC59F1071AAE6CA4E275094AF3040EF941290A3A32944070C76BEBB45C6470DCB46881A07B0D5EDA7AFF68B802D2FEDD209534FAD243456A3CB1637B2D454A091D02104277164EDB6AF625C4D8ACC9F32AEAABE6CF4CDCC42153338751241035D3A168BB52E168A45664245C312CCEC1B7E6DF3F6AEDA1B6980CB292D0B82AE8A277B904EDB1DFDF7EB7DE310AEC56755921CB1249725F4D413CCECDA5B945C04BD741E9AF589A2D928B2C1FAEFA3F2EA6F0C8798DDFA72F3F942139414B2445520327D6DF21FA4225C47084210842108421105024103F7BC2114B42BD3F31FE61083ACB730565C4A94E725B61050AD0E369BA1C5AD2A208079884F404907E5191617C4157854E91340CA996458A487095066D1DD3A9B802C766A59F2CA9252DE139945408B924F858F42EFA3DB78C50788D7856E54F1F5444D5A6E69583B37A954D759A256E4DC684B54912439524DD590A4296F3AF21B64175B7594A13E45242AE63D45F857F8B64F079A7A2A89C9974CA64CF91312F2D76CA490AFCA46A086F173DFAF71BA0330AD4525D2ECC2EDA9D3E9FB469FD8E7C0AF8F9C258F5FC2329978CD729F3B53989495C4D4F54C2A98242EB4B737373A669E91616E369490970A097141B480B526DEC2601F1DFD99D360495AAA64C89F2E9100CB992BBE54C9A000532CCB0960A21C12E52EE7478C1E561D52AAA00CBCC1C80C72867B6A7ABB0DF4DE3646F0AFF050C37C244DD1F3A73C5F5E31CDC4B0918770D38BA72F0EE169871252DD4DD522594F4CCCCB2DC53C1B44EA14548000B98F3ABE27FE37F0FE25A2ADA0C365CA954F39535FBBCE833DC14A7BD656553302D9585890EE6332C3F0E29521653704036040075037F5DB7E51B0BA5A7D26CE0474B59B1645EE41D092A25290774824D93606F1E2F717F14CFE2CC5275490C17354A4A459DDC8275007A8FD23B0A8101094A5CB300AE570496D76D6F7BC5740201BFAFF0088C4A7D3AE9CA44CD4876E9B7AEAFE91725104DB60DFAFEB13453C43084210842108421084210844149252481B7FBC5DCABB8A24292D9D60070EFB820FD7E7B44195198BBB9171E96FDCF9931D4B17E12A563AC2F88F05D769ED5528D8BA8D52C3352937101D4993AFCA3D4A98982D5895FC1B336B9A510086C37AD5B24DB607E1C78FAA784B8C28EA3BF989949A992ACD988CACA4D9DD9833F4B748B1E37202E4A99394906E45896DCEC1474B74D63F324F11FE103177075C4AE60E02A9D366938597589BA9E0F9F32CA2C55E8F3CF2A68CD4BBC8406DC4C9256ECB39A54794995B28274C7D47F621DA8E1DC75C21413855A274F14E844F42541A52C20250487CCD3192CA2594B2402EE0741E39473133D6A53B0248E44B9D0B5F6075B73DF1FE494B41F5A56860EC1E5A4A5B27D02CD9255EC0DFA6DB8BED0E01202E43953BBD891A37E9ABED7BC63D24ACA838043E8075F7F4D87A4127500AB11717B28107EA0EE3FC6F1C57CF9545519D5600B12A673E7EDA69660F17695977019C00FA91E56B866D1C4462E1271DA5A99252328290407617E9B33F43E711D56564B10E5C103A35C97DDFFB59E204D85C02AF6482547E406E62CB5089B5330094EC5F4EBA7D1F52DCAF14512ADC4A0849D4A511750424ACB63D5D09BF2C0E84AAD6317BC33009D33C539797437394902E6C4FCECDC85E1F7F6378BE2F0FAE183147167C4F658E55D229D3935439EABCBCCE2BA9B2D2BF97D268ACA933E2A53B3A50A979748430991650F2D3CDF8CBA3514DE3A13E297B44C1F81F826AE749ABA693574943313290B502BA8A82912CA72A5416C94A96A54C072A16129241501176C36816A9C8284AC85AC6637602E75D1EC3ADC98FD3DF2EF03D172D303E14C038740146C214692A053BECF9444A52D8664E593A6C9D484B2C2436E81A5D400E2494A847CA476E1DA2CDE32E22AFEFE7F7AF5339CA959B55AB5724BF33A3B1B5E3BAB04A40844BCE360FCB42FA33BEFAF21667EE2A5152C13D0DFB5B7DFF007D7E5B46B55584C9742000958771AE876EA7F5EAD97A5294A48000200039FBDB4601F95A2316E8E610844A080E01DC807E809BFE83E71532A5A8A52BD122624BE80870087FD22DB565A7241D0A43742E6E796C1F67E518E7F16AA62AA9C02710EC042D7A304556642504851F87A74E2EFB5CD811626DD2FF005F4F7E0895295DA0F0FCD74832E752AC28EA32CC05FA806E47B5DE2C38A4BCE93ABE52006D77F3DBC8C629F80EA3D1F327801CBEC2755690BA5E22C195BC355965E097528E66A42404281BA8A660957A022E3711BD3DB9712AF867B48C2F24D3965AA9D454090E0CD2A2C431B696B87B68F1D8BC1D4A55484B0BCAF3FE50E35D4B7AF9C599F864704BC31E786767125E1CFC4FE194D3F15D36AB338DF26F3370EBCE51B1CCA2EA4B9B96A8D3999E78CC5366A59AF83A53B4FD14D002CCC84A965474FA6BD9CF13E17C71C3F830553C9577D4C9919D490A2B992908CF9C29C2923BD162092FD63A2F8F311A9C22A67996149289854A0C6C924DFA3B10F66234DA2E5B357C377C4FFC37AA350C53C36632A871479234775D989AC215895157C40C52412A217214F32F516ECC35A50EA59436A372DA41168B0F695F0D9C318FD1CD51A3972D73659095C84A03ACDCAA6A4A54480ECD2F2EB6BC41C13DAC56534D4CA993D40121242892DD1DEDC9C9D5ADB470387FF151C99CC6AAAF04E6F49CE641665B73424A670963075548A6393E85969D4306B0D30FB331CDD9A69734ABA0B9E4569BA7CE8ED4FE0DD5414B515B83D2CCA9525456A549979B2CA2EEB58427C21C8776CA4DF68DA0E11ED5A9A4D4226D54E43A9012332AE49666D01203BB12D1946959C969F625E6A45D4CE49CDB297E52765487E4E6D95A42D2ECB4CB454CBED9410A0A6D4A0526F78D17E32EC531EC0F391226808249050A60068E1AFE7BEC63BF708E34C1F18400552D456029C1BF2D7770496F72D196F56A005C5813637EA2FEFF002B75E97F78F2FF00BF993484AD5981617B8B9E5D4DBF78D4488800D8A813D3A9B1FAF5FAFCE26FE0EA08FE1E86CEE75D1AD6279743711C15006FF7F7F7A44E48B580B6FF005FDFD7DA241A59E8254BDAC6F61EC7A72F9C4A52C906CFC9F5E8DA37CFCCC4B157227CA9285A095124105859CF2FA17D625162A00A5EC5891A736B7907B4352D3600FCEE3A0DB6FF001140996262980B9DDFE6747FB3157E511BDCF9AE6FD6DB7EFF007BC542A8E721214901B517B8DEE1DC5F43F28E09035DE224240D893F3FF88905537F2CC2583100927D6E7605A380A074E46DBEDE9102A27A988529E43EFD62288421084210842108421084210842108401620F22F08858837DAC45AFB8BEFF0081F9C5DE7D7D3CFA79728CA01684A428817B0E7E8393B728E087B1D220A783435590413A4828FB4EFB2564DD23AF4045C13EC6F5C3D5829495C998B96A076535F9DF62CFCB5EB14D32825D4A8E61B38F5B173AEB76FD045129426CB4B8A652E11A94A75A78EE7A8694DEB27B5C2869EB6DB7CB6571EE2341572CCCAA9CB9290429099854406203A6F616B91ABB6D16D9983D3A1D484AB324DD59084F26CDA0B6FBF48E616C294DB6D15B8950F34CCC6C117EA520040001B91DAC7F1C7788B8B24E34145656493FCCF9B9105246DD46910CBA54A41394EE410356B81A073EFCDB58908D248B836245C743636B8EBB18C2513128585CB05C5C3FD6DA5BD045D25BA40F0B307F7177EBE83D2D1088EA6A1550A0A50660DABBF58A849704B35FF4108A688A10842108421084210842108AA366EE6F7FE9F7215F5BDBAC459D73552E493E104240BFF35AFEF1689954B4D6196904861AF367F70FF62380B4AB5071B5AD971BD7F6C9170DB4B494CC03B0DDD675B6826D65A8102E008ECFA3A218261B2713933009F90AC31F1020B330F1176E9C9CB98AB9D2FBF940292E48FCBB96B821B4BECFB5B48C5FF8A07876E1CE3DF261747A77C251F3430C494F4CE01C5AE30D26EF3685CCB5419F5108E70A94E7325D37710A099B09483617F4BBE0BFE21EA306AC914788554B553852254FA69F34A04D94FE20925432CC00932D45C05105493A475DE3B8289889C424E662A0407BB72BDB63CC0239C7E773C4170E9999C3AE61D7F02666E15AAD0ABB419B5CA06A75975BA655D08511F1D241C69BBA1763A4A5C5825205C902FEF0F673DA4E1D8D5352CFA0C4A454C89E80A5C91302A6D292E04B9A42AF6D159520DEDBC7594DA0992CA82E5292468426CA0D7205B936A19A3C2086C121A56B6C7DD56C6FEBD36D8DC0B6D611DCF5144316969992D59B3872411F2D5AF700DB7E71679EB9921C242AC1CD8F32FAEFB9F4F388458EB7089D864C91E2244E511AF222E46C2FBEBA69789722A0CE2A05DD237DFA8FDB5815251E6585148DCE8FBDF4D8F7FCBD3AC6474F3A451D377F3572D3912E5C806C073D469A6CCDAC5531E47DA2E5F86BE14739F8A6C7D48C0394584676B188AA6F21137596D879EA5536556A4A54ECEF2D3A129495249529D6FEE9EB1D51C69DB4E19C274F3E754D7C8921085F75244C4A66CF0917297242522DE229507291C8C7294CC2B0132D6A63E2212484E9AB0D6FFDC47E82BE17DE1B181B80CCA992A6CECBCBD7339F1253E5959858950CB6A975CF3896E6DFA3D1D612B532CC93C85B49D2FBAAE5336263C06F8AAF8A5AFE3CE22E20C264D514D153CF9D4B4B284C272CA4A949054A7654D504833141294A9574A520B0EE7C07089628A9E6AD394A900ACA92CC54D662F606D72FF58CAACA25E537A9F5A14B5BAF14253FFE8CAF315F08CAF7BEB6A5CA1B513624A6E6C498F27B1FA95AF139D5014A2A5A8A9C97759FCC5F912F66701B522D9CC893DC2084A4F8776B1762E07CAEF7D2E62B9EA7D8F716FAFE7FAC5A14B54E4952B54806C6D72079EFAF95F6888542BBC09205F93B37CEFF007A4224C5642108A4BD9615E89B5BEA7BFE517E95252707993AC1489B6D5D985EDD4DCC59EB0955420000800BB6BA1F36DB945B1F19185D18F3862CF4C26E341D156CB3C5B2EDA0DD5F6AAA2CE2506D6EA952AE36B9ED78DD7F82EC7D5238FB0E42E677413918A8E50E09667F77162FEB141529485241205C063B13E6DBDBAC6BF7E129585CFF000C350C273CE10EE1BCC7C534596BDEED30F4BD21A964007A69710F10361B9B46FF007C53CA988E2DC36BD39CCAFC152CF3318E44925648CDA380906E37D2EC7B6B80A5CA994E5208538524656760030D4D8BB07FF1E3FC7B7FA8784FE27F873E3FF2E82E59DC2D8A6428F986994D4DB550C3689C9479972683646AE6FF00EBAEA5EA074F4EB1B55F08FDA952564B93844E9C094210BA74A882A13A58032203B933C14E66FF00DB1A18EAFED5F84FBE4CE9C99533553A80B105DB316360C598DFADA3786CAEC798573AB2D709668E1826B386F3070CD2711D01A6D697C34C54A5B9BADD61A482E22CA4825D2A6CEE0245C83E9A54572B18A394241CC952100AC1722DB9761724E839EC23557FDBA661F50B57E42144B17177D1B9DAFD4B726B33E2F3C26F84AE32E99333198F9754DA763454B39F0B8F30B4A4AD1B13484E68296C1718967251C6895171C4AE4FE216E36DE99845961568A8E0FA7AA90A156A4AB30BA4D8286FD141C5C69177A0C6AB04D080B5A128B2495101B40731E5BDF7D7531AD966FF00855F89B78794D4FE2CE157164D712591F2CFB9333197F58979C62B52122D953E52E48B9393752AABAD3295A12E538C83257650674A82474871DF6118363B267A974F2DE6053CC4CA493F9491E1486624016008B1360D1D9FC3FDA1D6616B423BF24A4A6C261360402D7B816E81DA36970B0E0BF51736B811F19270C548398A81662C1CDF63E91DAD348A44E6512A0C4F88B9B726B74D479444003A472B98B7001600306DFEFF00789126AC55DF500D9FA0E85B5D79FBC22DF316A50B926ED7DEC7DF58AC47E61D5C1F68A5A95AFA9FBDEBEF1262730E5D3D394558E4122E0907982D0844466CC362B57B984220D75842108421084210842108421084210842108421121413FD47ADEDE9F9C4CEECB02FAF4DF71AFDDE11384A48DEDB6DD3F41BD81EFF00217BED11266AE592125BFF008F87F7D6205120DB46E9ADFA444B681B8293ED6FD05FAFD077809AA9C72292A24B33BEA3A8F5DDB94490A529652AB824020682C35D351CFD22112949292410C444FC89E5F33FBC22296C1697EBF43114226545D6080DE116F530844884210842108421084210842108AD9011950A23C40920DF991E9F2880CB41254521CEA5AFA37D2115C6AA6A91DDAA6ACA013E17253A9DB4BC4712AD295A14DAD3ADB50214DDF485023717EC4F4BDAE3AC5C309C7AB303A9975745553A4194B4A8892A52335C5AC3789532521695664A4B8BB87FBDFD7CCC5947157C0B70E9C6261B98C339D18229F539E2D2DAA4D6E96CB5275CA629C49087199B53531CE71B590B49537D411BDE37D3B07F8B6C5783AB69E6CDC5AAA494E5412A9C4E64064A810A0DA58BEA395E31DC470B953A5A80932D9812C9D3AB83AF9EF68D7133C7F862B11CBD66766320F34DB768CF38E392B48C6549E5CDC9B0BB14B0FD49AA830D4C2D2755DC4C9B234148E5DEE4FAA9C19FEA19814BA4922A6A64A96A48CC944C4A19400723366673720EE491AC75E627C36A9A099681BECE0F506DD5AC40DEC62D5695FC357C5EBF5032F3F8EF02C8529974DE716E19E6DA0A22EAE5227258A0D920F99D5EAFFC74DCE59897FA84F074C4833F3CD50BA422B65200D95632176D34237E6D168A4E0AA89EB51019AF74B3B6BCB5E7BDEC4EB7F7C3B7F0CFE04A55529F50E21333EA38CE5E5E61A79CA260B658A6CA4E2104A972AF3D30BAB1085EC09B0D81D85E3A578DBFD43B095C89F230BA844A2B4A9328998264F4280B14AD265A7375C85AF6D232391C14A9490B9CC1203A89B002D7BE83A1E91B1C70F3C2FE4270C186E5B0BE47E5A5130651E4DB44BCC54694D34E57A7A61A4848555269C654A528D9657A10D0D46F616B0F353B5EF8B3C4F8B6B67CD18AD4CC5CE2B7577A5FC44DD810003C872D498C969B85E44801265A524070E3563AF9680E8CEF7BC5C6151528ACECA512B3616F32AF73F3DC827AC694E298DCFC56AAA2BA64D98A5542CCC2A52892EA24DC9B9D5B5668CC69E9D12252258481912000341603991B442317AB5672E4BBAAC7D0DBADCEBBC544228E21C8905D838D0C21114210882BA1F91FD22ED4931E47764B8CDF94E9721891BD87F78A09C926A90C01F0871FFDAE7CCEF1D76BF4D6EB545ACD21D46B6AA74D9D91712521414899616D2C106E370A3D7EBDE3613B1CAD386F13618A92B5495F7F21D48394B158B588F913A9BE8F8DF1385A120A14126CED622F7BEF6DEDEB1A9578653FFE93CD0E2E326DF0A61CC1D981375644B2C90B0AA83B361D2949B69D2DC9B4761717BF78F667E2150715EC9302C6972D0AA89B83D1AFBF09F190813014855F70097E7E463B03B259C42BBB5ACADA6B10A3700E523FCF4E8E3235C4C64DD233D724F1B65B55A579CDE25A04CBD2EC5925725354C61D32AB4950514EA54DAAC12124E9EA2D78D5BF878E3D9F87713D11A7A8549994D548292936252B48D2DAB1F7023B8F8D30F935186ACF72839A592CA482E00279037D2FAB8023D9BF86DB8A7ABE37C82C67C27E625650732786AC4FFC929F2332B299C730791352CCB2969D70BA532469ED24AB748E700529BEFF00429D976374F896092CA18CBA99089B212ABAD085A5D2E5F662E402778F3D78E69D54789CC514948EF08530213626EC2C1DCB72BF58D9B585256FB847475287594FA200B2EF6FFB4A9209B75247A46535F3A7CCA83292B5654B10D67CBD7AD8F90DA31B54D4D452A132D92A6399ACA72C468C49B9DC0F9888D4A5C4DB0A61690E36A4292B428056A0A4904588293704EC458DC003789B2A9973100AC92EC195A581B9BFBF5E9A71210A96CE49BB927F6B5C96E4FF004B076CA5E965CD4BAD0B96274A5E3E5E5286DA9C479AE0F5FBDB01D63E182AB05C5686B5722B644D4A50A527328283B1B10E069CB9DDE36997562B1211A12CE1F7D6C741BE9F2888BE94EA02FA479926E95FFE69D8581E96DFA137B1116EC464A64CD480CF943B33177E5F63AC4DA5A714E328DC9F4B3B6A403118B1AF4F5FD0C5727F3067DFAEDE4228FF005FFF00CBFBC4A89D15A108421084210842108421084210842108421084210842108A7A4A8DEE46E40DBA5891EBED78BB22585213C9817363A02D673BB7ED088A8816BDC5FB8D81F98BFF00BFBC7270F9934E6426CF7B173FBFC8F5BC4B5EA34D3D7FC72F58980E9B923DFF00E2FF008C4D93854C4AC2D40E5BD98B86E4C7C869F5890807BCBEC41F76B7D81118A7AD9195CB5C5EC3CEDF7D186D15708B60201BE977F50D0844C9AA0A50234CA3EA4C2112A10842108421084210842108422A25AC84001B7FA9EB084479CF21F3FDE1102010411707620C47292674C4CB2400A203DEC5C3177D8DF430D62555D7E5754A7D0149D2DBD65368FF00EA00045B6E87B8115F5186CCA701521613943854B2C4BEA1F427C99BCDA257732C6660C55A9058FA1895652A520A9A41084E90920DADB917DFB5FF006220918AE2F4AA025D54F484801B39CB6E5CB972710FC2CA55C84DF9B38DAC1ADCC0EB11BA9684A3514A5B24B606DA0ABA9474B5EC2F7BDED7EB15753C478BAE5841AC9C366CE4B0EB71F4B9F9F224C9A775A52919C312000E0680EC45CF2239C54712979296DF25F426D6E61BDADD2D603A7FB0DA2CB36BEBEA16262EA271580400144FA6AD7DF5B973B3419E521F225201FCD96C15AEBABEBEF133A43A517480DB62C86922CD8B5AC748FEADBADCFEB79F4B453660FE24CCA48BA8975907F95DAC2D7D5F6222904CEEF314A57997F9892EA517B5DAEDC80163E512C499B33B952A4A194941CA0BEA06966B1B070F170428A92090C5BEC8E86114AA515973E8360222844308421084220AFBAAF91FD227D3AD499A801D8A8023CCC5296FC64B27560DD75FA6BF28E3CB3A96DF4AD490A00F99245C595D491DC5BAFB5F78EDEE09C40D0F12613E260A9D2092E5FF00EE076B80DB38275F58B4713C90BA70A6B80F6DCB9E86FEDF38D49F0A497FD25F199E28B00147C349663B0711D31A02C8996DE666186F4D800521D65CB2424D9448BEE23DE9E2892AE25F878C0E694E6FC3D34CA22C5FC32E449988510DAA8CE501B16706F177ECD6709357F99C152576E65C33B87D074DBAC65E8A88494AD44A5F41679A36581B029D66FB2BA280EA0017006FE73702CA3C37C4AA9D3159128AA605F2E8B24687FCBBD8DE3676B29856503315669563A9663A3DB7D4E818B461D6978D67FC3C7C5DB2CF885651FCAB2A78800FE15CC4665D2A6E8ED4ED5AA14E7DE9E6DA050D4B38858D2C9714F14A5C705CDC98F74FE1ABB48A2C4308A4A254F49992928CA02813908014557BA524240166CDCCC69076B1C36B97553E6041B955C6FAE8E186F7B7CA37D7A4D4246A4D89BA73E89C959A4FC5CBCDB442995313365A1B6CA4904253A415056E2DB5AD1BBD324C99B265D582921400077530FCCEFA93ECF1D0D492264852D2B4948D1B4208D39BFD35E91F7D09558F537B74ED7FD3F3FAC0148486D5BC56B391D1CB5AFE9152B219873279F3D7AF90DB48D6E3C3AFC4630071CB960A9B137274ACDEA138C48634C02B2DCABD6434CA5E9F90610A5A9E6564BCB24B4D1414280D5A6E7E6A7E283E19E7F08D3D6E2B494F28D3FF001264A9B2D0405A43A8149CBAD803C99AE18C6C5E2926AF87B189945552A6A56898525494B243167DBCDC73F5393F9697286D494A91CA0B219B2CA872F4A4D81291D14542D6001BC791B8D19B22AE7A66CB20CA9AA9641703C25AC08F2EA1E2FF002E7898942C5810EC7D5C96D2C75E9A6D0D6359459408EE46DFAFF6DFE862DD2A997532D4B43008B973CBEB6FBE7572C85170E7562DB6E5F944A410A07D4DC5BE7D3E71488495A8247EEC2278F6F38AB109B1239421084440BF703E70BEC09F20F0881B0EA458753DBE7F211514F4CB9EACA011670E1A2052C25DDEDF7CE21A91B9D69B72D2E8373E64A9E0C009DB756B22E3B0DC9BED114EA49923F3149B9006E5839B7400EF76B3C495554B4AB297EA4683CECFADB4D623FD45241491FF0076DEFF00DC7E2220FC34EEE84E12D4A96A240290FA6BECD1CFE210CEC5BFBB7D6D03B5B706F6DC6E37E9FBF7110224CD985932D6EED74900799E510FE290ED9544DF41CA04D813E913C51ACA824A909511A13BF2D45E2722605B3021CB78ADFA449CC1D2C77F688A650CD9775293A39FB7313B2FFE49F788950001DF7892241568A1F61FD3D5A21172438B75B7DF9B44A1D4136DFF000FDFEC426485A081F99F93903FC6FCBDDA5CE9A8920152817D81BFDFF688958092AB1207602E7A81B01F389D228664F4E60A4201D029C12FA6ADA9E4FCE241AD940397F4F5E9D3E6368A80595A1652D2F4EA097080543D82756FF3B4433A8E6C9D4A577605377F2897F8F97FFB737CF28FD4FD22915200090A0B5AD47ECD3BAC77D4A49B59361B9BF4F73191E078362D89CF9326970DAB9C56400A449514B682E35D6F6168986B65306CC4B02CC1DBDF5DBA6F1E119B5C48E45E4A31F1D9A39A584304CAB4921C5D66AAD34A0B0AB72B94C879FE65C5824B605C7511B6DC0FF0ABDA1F16D322AA8E87BB42D29532E54C07C40102C921C1E676F41493F11080FDC4D533E89D87AB1E7E4368F95937C5CF0DD9F8B7E5F28B38B05E399B95514CCC9D1EA61536C116DD6C4C2185906E1434255B107A74BAF187C2CF681C2D46B557E1EA40487CC25CC6209704282198B6C7DB48A1918CCA9B51DD2A44E483FCC410970C5957E5D75F48B8F5A92D9097569694A1A9B4ACF99C49170501214540FAED1AB1C51C198B609DE7E3A59494BB92921C39DC81A7A6FE717C1532CF36E7AB35E27092A1704475A4A90B9D37BA436676009EB688FBD06C2FE45FF4BF908914A09363BED7DB71FDA2A2AE867D3292169FE517BEB7B69F3B47226021D88FBD6201609B6FBC5114A81620BF94460821C40A80BDFB5BF3F489C9A65A939B3253CC13711CC4358F7FCBFCC53C21AC7A1FCBFCC21110A04D85E390092C211340820B184238842272242A60CC086F9EA47E9D6108E554EB4872437AFE80C211241292082411B8D443CA1F97CA2726A67243672407D6FF006F1032F98FBF487CE38993E62C0BB11B8717F3D5BEFCF8567D3A1D016E8E7EA2263A7B037F4F7F5277FDFA77A719FF009883D7A72DBECEF10A12B2FDE17BF859DDBABFDFA4523AF7B7A9F4B91DADFBBC54A26E51762599C8BB1F771CF43134250CC43FB7ABBC4A4ACFAFD0111C2A7CC517CC53D136100948B0000DAC1FEF9C5517205FADB7F9C4225A941C317EBF58E47B7972DA110149496208FBD8E87D2111B6D7B8207F9B74EB1082E598BF97EA2DFDE382583FCB9C2DFF001BDCFE5688995FD27CDBECFCA20EF3FF001F9FF68844689531659293E6C5BDDBA471DE8E5FB7BB31F4BBC414A484906FA88D88E83F7BF6313E9A9672EAE549092159816BDDAFA8D00E85F668851295327A67380940662353AF42FCFF0048E1A11A1C41529210A7129794A3D1951B2EC08B12104D877E9B465F4555F80E22C30CCCC3BB9B20961C96D7F507CACC5F5A0C7DA7D389680EA0EC791BFB8E76D7DE356AF10BA2AF283C5BB85ECCD45A5E473129145C2F539B274A9E9A4D7A743E1C16092D0627D8F31709DC8281604FD09F6555F278CBB0DAAC3A914A33692928E7E55FE41FC35F78A05CDD41091A5D872022DFC31592F0AAB9289D98199359C3F3480E6DD79EA6326E410C32DB83ECC1E65C6CA3AF705293B1DAE7A8B7D63CD7E3B9F36831CAB934CE9992EA9697B06217776D87EF68DC5C08A6AA9255DF3CB04036B116F3DBE6F161DE22F91073A786DC58BA3B1CCC5F80D52D8D30ACD281438B9DA625E51A7879095BAD87B5A1C3A12B376126C4EE36D3E187B48A9E1EC6B0E9589D42FF000B50B97226F7633A84B5A92E5282A4025F29624003E7D39DAA707CEA8933A74B421C02A4BDB62581DB9728CDF78197174EF15DC0D601AA57A795318EF2DD8465F63561F20CF1A9509A6A4533F3092B5384CF2E5A61DD4E04A8E924DF7B7BC5C29553712E189155DEA664B04242C1241CA0DD3B104DC1D08DF63A3BC474FF00EDCB58525941459C31172E34D1F67D5ADAC6695B75B04A350D4908B806E77BDADFDE2E69AD4217DD29F33B7307D6DE44EDE6F18D216A98E54A0580243F366B74F7BEF1F94FE03CC8C61C15E7D619E27B29D0BA67C03D2EF633A54BA94997ADD0D97899F0EB6CA4A1C52D83328216855EDB98D27ED1384697B49E19A9E1CAE9699FF8996B1874C58FFF000F5931391092A374C99CA12D331B448258E91ED076EFD86D2E1B4F538ECAA7485B2A628E4FCC8FCC7A9209B3E86F1BEAF0D59FB84B896C9AC119C782679A9AA4E31A4CBCF3D2ED38852E9F52294A66E9EE21B5AF96E36B0165074AFED41D3BC7CFCFC53760B53C058AD577148509CD326AB2A48055995605838395DEF63A468A4996CB9E803289731480144EDAB8DFEDF68B8043885F4B127A2AFABA7517F5DC5C1E9F58D29A01325CB9D2C5B50A0C76E963BB1B45C25A598DAC1981F9B69EBABC5428242546DB137EE2DB5BAF7FD3DAD16DA63FC7525AE12AE9F5E56D7589D0890AD4F99FAC211C4220A3617F7DA2E1413E9E42D6AA849527296000249F523EDA39177B816DE2620817B5F6D87AEDD36F5E9F5F9C564BC4A5CC9E8972E5E54A9411C8DCB31B93BB5BD768A0AC504249BB9D003C8721AEB7B697F3B4AE2378BACA4E16060D5E6FE205E1F97C5D5C4D2E49D12E5C4308752E3ED38E2CADB096D2EA079890011EBB1DB6EC93E1D6BBB520A551531A9EEA48A89C10CF2E5384296C58901F4014A6DB961B5989F70AF12C872C0DD9DF9FA30D99BAB7BD65FE66605CD6A348D7B01E2EA6E2CA454184CD4A5464A6A59D71D6964DC3CCB4F3AE34A65614CD9CB1B36147B0893DA37C3C718703D55448A4C2E74CA1909052B4C95A836404FF0020BF3BEA7C8C5761D8CCA56444C55CAB52DB917B91D7D74731DE1C69D6D5A53BE9EA46E2C49DF6BEDF306DF4B4740CC55550CC5D1D6619512A68252A2649003B022FEE741D748CBA54CA75A33029BB9D6ECCDFA1F38982B6B037BEDD7724F6B8F9F4FC36DA31F9FC3B533E77E269CA6585282B2AC94906C6C18B1D01D2C6FCE28E7D4CB27B896A0998B60FA0176D411CECFF002D621A80EE0FB77DF6E9D6E3F6224CEC17137399724D9803339D99B21B73F5B4527FB7D5A9DA7A6F67CEAD07A379F99BDE2A2834517DEE36501BEF6EBED6FEFD768912787B1352ECB90CEFF9C93E43C3D753F588461D58EDDF274D7311EC59C6B7FEF1C05841559BB9BDF6EBB03D40173FB1F5BCC9C32AE8D065CF942A153834BEED256C5B42C1C3BF2720F50D39385AC826A2A07966398736243726E76B17B7235043616A5BED824E95CBDB9F71D43375A015DBFF0031B137368BFE07D97F16712D64A14587CF32D6BD04A510012CC400C59F7E45A389A8934A950494CC22CCEE011B12C5B6D8973D5E2D3F884E327874E18A9351C439AD98B43C39332CCAD68A14BCD4BCFE26A8948BE94B0D3C032E9B5C85BE2C7A98DC6ECDBE0AB89F88534CBACA498CB28395485B25CB9BE560EE4396D4F4894719952BC0A913161D92C8B172427C3A10924747BB0600EB2FC5578EEE7FE78D5E7B037065855DC0586029F9098CCDAEA8B3899C924A94D266E412C36F940986C075005410424807DFD53ECA3E12780B83282817C494F26656499328F712A5A14E72273A67CE56432D41CBF76263A983B391D95C1BD9C631C473E4D40A499F86A9505852905803E2052188539637239011884ADE55627CCAC46EE39CF0C7589332F12CF3EB9B9A98ABCECCBB79875456E3DADE987D4C25B59504B6DA5614005122F68D9552F86B862985070ED3C8A0A7CA10B1492A5CB9931219BBD9A8654D2D62542F6B6D1B7BC3FF000D726AE8E5CEABA50B564492148B68E4B1059DFCFDAFCEA765B620CAEC4725991C3F620A9E0FC754371138CCCCB4ECC06E6C349297DA71E4AD9712812BCC4A921A58584941165189D594DC2BC5F81AB06C5129AC33124269E729254826E4CB2A2AC8B05D4E90E6E1C3BC63BC7DF0EF4D86E0D5551434A13549BA4A10012EC18B0F201CF22CCF1B30786AF8CC612CDB99A5645F146FFF00A0B37A4D0DD2A8F8DAA0E215218B396036CB5A9D530B9771E09E56B701170157F4F393E227E128D6D155E23C3F4F2EAA89944F7414A9D4C4964CB9E908604120254852C2925254C49034D388784719C11444D91310A46A329018594A05B97CDEE446C2CC5498530DBF2B3099B959942572F34D2D2E32F36B00B6E21C41536A0A41B801446FD77BC7927C57D8E633C1F884E5D4D24C4225CC56A850B02CEE46C5CFA728C6282B952A61454E600116367FFE409B1B36FF00B7251720A892493737ED7B5877B7CBD63AAF17AE952EA9326620BA5012C0683335C1B816F58BFCCA89534A55254E32DC82E09DDF6D2F7EA6EE22AA3A83EBD0FBF5EBF2FD628D629A6CBCE900167039DB537EAD73EEC226217616EA7F61D6DF3115929D573ABD80EDFF003B75FCA31B9EB698A06E1C807A06D3AFDBF29F14741F51FBFA44308683EA3F3FF10844C94906E6DD3FC42113C21084211C85280B2881D090211314902E7FE3E7013546D98FADDFDFF5844B1304BCC82B7B8737E407BBDA108950842108421084210844CEEA6650B00B588236EBD3CE202B487D6DBD9BEB11B1B5EC6DEBDA2AE44F916133F3331D0DF980C796C1EFD6CCE391F97EF04EE76B1F5DAFF908AEA8552A69F3C800CEB101AE6E0060C587F7BEE5992AB73E7FD8C415A6C6C6FD41BEC2DDF71D3F0FC22D899956AFE43CEC8FD19BCD8D8C71DD21DD9B7B13FA923E510B8F51F888A84D456CA07C0592D7C9E9EBB6D6DE3932D279DAFEBCFCE29AF7371BD8589F4DFA13DBA8DA2B70DC465CBAF44FAB4FE549482DA723CDBE9CF945DE265A72EE5C87FAFBEA3DBA5332E99A28975A8203CB4A028EC12546C1449E8124DC9B802DB98B84CACA7ACC729274BD04C9602816FE7703EF43A6E62D9569050A2CEC0AAF7E6E7993FBFB6B8FE3F9861DA5D03860CFC914F2A7302E64BF2AECC36921C436F3D4232A85AD23CBE765E524288BDCE9BEF1EEBFC20E30AC47846BF0794A4915582D4CB20FF5CA91FC324877014A36F38C726A4CAAAA6984B34F956D0865073AE86D6076768BC5C3F566B1061AC395C6CA4B53D4E91714A053A4F325DA5059502459449B126C6C403B18D33ED870B9B87F11562CA487AA985C8D4859BB3FCDC3BDE3703846ADE9E952083FC2961B5D83F26D76F3E91CC9A944CDB3354A7825E66A1CD6D52EE00A69682DA91A5772414A90E2EF716B81BF48ADECF71D34588512CAC0089B28E6722CE1DBDBCEECFA45C78CE90D650AC241BA083BD883ABF9BB93B92072C69F862E70D47C3E7C5531EF0DD5698765724F8A244F62AC20C2D65A9394C40E4FB5314B69842CA590A549D4E7B99CB56A4A9B4800DE3DFCF879ED065E3DC1D4346A9A950A695229D41ED69644AB3DDD295393D35B18D08ED2387174EA9930A2CA9AB20B1DDDCE8CEFA39F68DE269CA4CB961C51F887DD9653856157BDDD6929055736584A8920EE4037EE6364914885B4D09DC14DB4704F3B7ADF58E95549EE1DF62C4B75D34BB333F3263F2EDAC52DAAD5367A97382F28FB0E52DA4900FD9CDA085A803FD377957F61ED68D2DE1BC72529424CE2953324BB6A0B5DC6F1F4FDDB26088C638766D226582A54A218873F96ED63A0FAB6D7C8F780AF1315ECADCE9CC6E0CB16CF095A362443989F2B1730E00D375B936DC138D344F45CF2534E690123CC5AB6D611AD1F18DD9AD07137085471152C92B992652E5D41284F814539A52C2EE7F88A252C34C849D418F1E78DF8557C378D54524D42529993264C65020142890B0465F168C361CF511B7E30A6B98B6991A5B421B7D361E5D4F8295A47522C5ABDAF6F30DEF1F3CF8B60A9C3F15AE921232A26CE0DCD8B331FDF7D368C28BA45FF0037E52A1A16D0866D8DACE2FA472E3ADE70126A561980CD6F307EFF00BD8D399A01B82C4B3F3DC7B9108A43724F3262AD3A0F21F484711CC408BDBBEFFD8FEFBC5D70B93473A64C4D5A825390E52EDE2B37C9FDBD9056EDA92A27494A82ACB295004106CB362936E8A16D37BDF688CD1D3CBA942E44CCC10B075BBBB87E7CFAFA5E86B102624A5B6E572E2DD0750FB758F08CF1E1DF277890C2F318233A70661CC5B48764D6CD3276B54E62A157A628A0843B4E9F7A59D71A79A3E669487DB2156B2876DB6EC7FB78C5FB385499B41553E9662100154898B94B29DD2A28209041F107218DC308C46B30BEF94ACC84ABA116E840BE9AB7AEF182FC5DE109C4870E15F9EC77E1F9C45E23C30C3536A9A465BE28C4B88A5A973835070C889364D429330C38B2436DCE29968365285694A6C3D1EE16F8BCECF78DF09A4C378EB0EA7A99B3902554D4535352CAAA2A032256579A599AA2027395AC3924DC9BD96AB02AAA69667C85948D424A890CF7DEDBE9A5C691D42BDE291E247C19CA3EAE31785699AFE1DA3A1A62631CE167E8F2D4F99612BD2B987052DE6DB5A94DF9FEDCA54A27CC01E99AD3FC3C761FDAA8975BC3F8AD1F7F5AA7452564B54AA842A616423F8099D2C92A21215DE6B736722DD478CD7226F71312A0C425D24105ED776370DA73EA63D632FBF88DF841C492927FEB0C2D99B822666396FADC670ED16A1268208D65732AAE2660B6920952D0CAD76048415581EBEE2AFF004FB4CC33D383090082528226A42731B0B10F974DB425D9C81D9541825756D37E2A505158014078BD08201723403736D1E2E8289E38FE1D15A9613151CE96686923516AA741AC4ACFA7627755324274820FA397BF43DCF554CFF4ECE3052880B907312C04C397CC1CB9599F70D111C378843E544C21FF00A0866F30E1EEFF003678F8189BC797C39F0DA1E14FCCFABE274A412DB547A3D6D4F4C100D8736A52F2015A8ED77160F5E8378AFA5FF4E5E3072553694004BBCF4BB6F60E5DB90D03DA1FEDBC427495301B90421434DC06F263D2FA88B37CCAFE23ECA490977464BE4A63DC5B3E9E6B32D3156448CA4AAB9800696843554992EA5C29D4BE736829012003A956ED5E0AF8009787CECFC4359878653A3BC339494310EE51214092C00671ADDAD110E0CE37C726253414D52B4CB2D30A10A624B00EC1F477773ADA31A79C3E2F5E235C44373B87F05352992185275B5A5BA8525C4C8E249069C50FB6A6D4A4D869F959A4A6ED975136D2B438B1AECA20EE1F047601D9C705D3CB33254AA9AA94C4897290990B290CC262CA668D3512DCD835E3BAB82BB05E28C5152D388D2AC216C162621449720E8537E834E5160EE64F56B19E217319675E35C4398F8AA6965E9899C475299ABA9C7566EA2B5CDCCCC1515289B951F58ECBA9C469F089229F04A4934B2539411224A12548486F1AD202961BFA8B7AC6DC70B7C24E195B2E54DAD900AC0492163A826C74BB5C0778F69A652A4A8F21F034AA749C8B6D80DA529421212DA3CA12121160024580E805EDD228F19C729F16A2954F48B4A2AD32C2668496505E8A162E2E2FFD9E36C3867B25C1386A96929D34F2C0A642500E44DF2B00E5B50DAFEA23E824A74B6805B2509B2CA0586A2ABDC8207A9F6B7D231FC3F0A44B42D5884D254EA21D4588D9829AD76366F3678ECB952E8A9E4FE1E4A136013648E46C5BA1F944B30B28B10875C2568404B1FF00B835D90542EA48B2028A942FBA41B5ED68B4CDA3A9C3B11978952ACF712C90405288624D8EBCFA5AC378B256F0DC9C4F3A2A25255256E4829052C5DB5D9AE45B53BC79D63ACB3A2E36489879A96A5D769494BD4EC5524909A9CAAD3F688FB44043BA90A3FD2B3DF7B476FE018A5062B48BA7AC29299C8CB352A62998CC405A0B05234705C1E578D75ED3BB17C3710A69D324D2A02B2A99901C1637058BFCFA18BE9E0D7C5EF3FB8339A91CBAE224D6337324D97D9966313CC2D7395DC272C421A6DD69C9C525750F876836EB74FF008A54886C212A712EA9E6DBD78ED9FE1C301ED0A8EA95824AA79388290A12E90A42533E63951EEE6B650E08CA165202814B8178F37BB46ECA2B306A99D3254921014A399208B681C30D35B6CC5DD846D9DC37F14D91DC4E61A91C5D9458F6958A64AAB28977F97313C86AB2C4C68D6EA26A9332B65C6CB495250A4286E50A08D4DE859F1F3B5CF83FE20E1DC5E729747325302A3E1510C14AFCAA01887043A491B0DC474E48A39F400CA9CE083A17058733F7CE2E72E1D4A14E3EC1532A520B68B4B38DEA2059D96484A1C3E8E0D7A4DF7EF1A85C4BC115BC373A6C99C829C9624853F85DDDC793DE2BE52D88B900BA8825C722126EC34B585CB0DA260957DE69608B1DC1276F96D7FF003181FE0913733EA9725D81B6FF005B1D75DE2B92B2C5AD76E7EC7F589E2D2A195447224470E06A40F58471071CC7B8888569DFE90C856424737F4FB311A08CCC082E36302F03B036F7DFFC6D1592689C87F5BDF42DCC8EADFE2665725C9239683EFDA29DBFF941FA9FEE445E2461AECC90469CC93EC2FEBA7388BD0FCBF788A5DD2746A0AF43D7A807E7B13DFDF6B08ABA8C049906604876BEC5B577F3E9FBC70DBB317BF3E5AFB69FA98AE55E5BFAEDFAFEFF00778C426C85499AA41D125C1E8FCA3800051E7B5B6D1ED6BFA1D6D78A515727FECCCF3FDA22845242108421084210842264A5B49D4A22EAB9DCFE3EA2FDB71D62EFDECA5D32100788000E81ED6B6B7727D378A05CC01445CB7C8FBDFF00BC454F25C525B6D4137493CC5ABECD3637D2A46FA89DFB1F9C4CC3B87AB71099924A02B3285C0755EE03B383E5D625158377568CDF6468035CB696D6386ECF312EBD2EB85942012E4C265A5D894B006E56EBAB6BDF7D26EAFADFB4B05EC7B88AB96855353CF9F30A4144B085CC7E76234677F3D5E384CCCAAB3149D4A945C101C3062036EC4167D5E3A6D433372E29AE2DA9EC6D85A45682A0E89EADCA4A149BD8956970EFF80FEFD9941D8171C2807C1AA48673FF004EA22F73AA5C5DD9B9BBBC4FFC500921C3B0660FD3702DF64DA2AD2B3032DEA8A70D2F1DE0FA93AD275866571049CD2946D700214E8FBDD877B822DD224E27D83F1CCA0A2306A9B7FF00CBA98D9F74DC36AF7F3310FE301003283B82AB0DFA1245998802EFCA3BB3132D3D2EDCCB6C25D9479254152AF4B2AEAB901D0965E3A85ADE7B5F6B102D1D6B8F7639C59434F32B2AA8A653CC47842664A524103A1019AD6D9FCCC514DA9FE384A54543F99CA9EFA312D6E81C3B748A4E7297A9BF2A995254A5AD5B38DA77D60936EA2F7DFA1B5AC0C6094FC3389534D4CF9F2CA44A98330482DE1625C300F7D9FCC931744CB0B959CB91A313725B47B91F3B9F6C43F8DBE004634F0FACD0A9B2C29CA8E0376858FD8094DC84D255517E695B0E896A5182A36D811BED1EB27C0BF15E6C6F0DC1973804D54E450AC1538289E44A5803A8D74E718D622324D0A507CB31240D4062E0924F51CC5B4BBC5B6706B8C1CC75C34656560BC1D150C35212335656AD1FCA1B05415DAE3E36C6D6237262E9F139C3A30DC5672C2322C4D529C3862546DEA1B47B680C6C87065566954C972FDDA45FFF0021EBFB39F211754F10E4D2F9674B610E31A8F4E59D3CBEFDECAB6DF2E91AA987D5AE8BB998925253312435EDB7A68E7E71DC73E9455D2310540A7771AE9BE9A8F94623BC5472BAB6DE13C03C4DE5D19893CC8E1F2BF45AD4B4E4B0703CDD1987019F4A14DF9B4BE5997655DB4B8AD5600C7A89F081DA54E4E292F0F9F356A9332480A979C801496099B95DB3A5D49075651BB1BEB076BFC3D2E4613DF6548577A729CA792ADE4790BD83C6DF9C00F14D8778C1E17F28B3C291C966671461CA23F8869ECA90554DC64AA4A5588696EA5BBA52891A819A61247955CB16001DBD8BE1EAF15D852673A41EE926EAE809D3572373F38D2AC6E47E1E64C04B9398860080970C93C8B339B92CF6DFF3CC74A1252E2C5CA08527FEDB83B12916048B0DEDD8479EF427B99B9D04A540BEA6DF5D5CBC7D4CF12A0D4226257E24B33301ADCBEDA5B4E51E4E9C7B3F905C46E4571154575C95730BE2FA7A2A6F3675FF00E96467652696971B59E596DD4BAB4BA9234BA9484B80816195E3D86FFCB382B18C12B65AAA115149395265A6C573654B2509009482A5288CA096BDD81BF9B7F1358052534E562B26584CF96929CCD6009274008F32C7CC98FD0BB01E2796C6186A838969EE21D90AF51A9B559771B092922725D2B5D943AA0904A517D2937D00152A3E6FFE247023C1FC5F59230E9464CA54F9B9810EC4AD4087DD9883CADBC690E17553EAC4FEFCB9429936DAF71B061C87D23BC46B8574894695352524CF5148274170492CF7D6EE3D348A797326CCABC8FE00A729E40117E9B80D7F7877F6DFFB5BFBC5862FE9D0790FA4211CC2F6FF00807F5833FF00923E9081B1EA010762080524770474208D8822C7BC4485AA5A8292482342E4FF007F9C4250953B8D7CE0424941286C86C5908E5A3969EDE545B4823D401FA4578C4EA8060A6B3756F3D7E712BF0E8FA6DCB6B98A48515AFCC014B7FD040E52C2AE4875AFB8E8DC81CC0AB0000B694DABA8B17AE93365CC973E62148650CAB29B8208D1AFD795B4B452E2694A2880097CE4BBDD85C326DE10D764B0CC49372631CDE2AB838636E05B3F68DCB25B6708542A886D9529A2CBD232CF4D36B972D14A98F3B292E06F485A014AEE98F4DFE0AB8EF16A8E2DC264D755AA6C8935D46AEED6B2A49089A85314A89494822E92188DB68B2D3E078714227AA59EF14E4973AF4BEBE7E9B3690F92942C2F88F2BF0CAAA743A54FBF2489F917E69F909671E53C89A79094B8EA9A2E28805362A55FA5FD63DB7E26AC9D874942E95926714AE602C5BBC425619DD8806CC036CDA47A13F0EBD9DF0D712E140D7D3F7A512D252FABB7555F9171F58EF6F64FE5BBEE735784E91CCFFBD126C21571DEE96C1BC6314B8FE26B490AA89A10FF00973AC0DB676B58FE8FA6CD1EC2F82D2A6386A4BED9525AEE4EAEC7EEE447258CACCBB9316670BD2D6E1B5FE225599817EBE50F216136F4481D368AA5E3D5524029587EA735DB997D86BEEDBD653F623C009244EC3413BFF2FAB020302FA16D04768A7E1CA3D21015234BA549A05AC18A7CA34A5586C41434920A77B11BEE7DE2D555C5D8ACD69614022ECC9161D4EBD403EF768C8A87B2BE1BC309FF008FE1F2D092419F9D01648D99C2B997DAFBEDF6EEE2DA52544A9A705ACE28A936241B106E34D8741D361BC5AD5515F5ABCCA59B93A1203901C5AC4F3371E5AC67987E11826152C2AA6553CB5001C14A12CDB9B0E7E6E22B0425D40D2DA5A2D8B731AB27A6DEA371D7D76EB72045C69E9B160190090A4B1252EC0F521C0D362D7EB136A78AB07A0B53CE9290CD6500C363AD8B0BF568E3B885AD449F3D8DB56B686A1B8BAAEBB927AEFB923DC916691C3B5F4B573AAE522609B3661985DC872492C925B7B16D36E74353C53267CB0A18853A7380E0A815005B76B3DBAFCC4412D2812406507A1054028903EF59AD436B6E546E4FB457555062D557989586203E5034DBAF227945AE9F1DA71349FC7D3B937FE2585F7B07B0F2B4456AD249E610AE9F601C2E74B10924246FB8209B1171731CA28B124485489A85992E02BC3770430059C681D881A748CCA8789284809A8ADA632D8582D37605D9802FC8D9C1BEF13210928166CB57DD4B79160BBF5D6370AF7D5788512E7D25E5A66208B8B9E6F70E7CFADE2A6B310C0ABA4AD099B28BA6C92A0766D013A8736FD8470AAB4E91ADB069F5494949CA7A9B5204BCC30D4D4BA42AF7D2CBC853480492AB0401A94A2003D6EB2789313A41E02F9430CE80A7E56502C458FEBCBA3B8BFB39C0F1E2B2B928999DCD80B8366B5F9FBB5F48F24C2983B32F21F169CC8E1BB32711E5F6276A604E2E952D529E97A3545E6D41602DB69E5213CD484B0A6B93CA08424742445D6A1780718616AA4E29A1A6A99880512A6A64CA97532E5BB8099A94A56A014490852B2392E2EA7D4DE3FF00873A75AE6D56174CB0A095164E629700EC1C68DB3C6693866FE203C5585D54EC0BC67E56D459999528904E6461995905234D92DA2727794FCABF320A815B80B2F3C46C94289B46A876A9F079C11C5F4D5557C3D26554D4CC4A94294A972AA41209621792458DC94CD5007C9A34878DBB3DE34C02AA6A64D3CC4494A8F884A246504B5C2496F41AD9E3620C88E32B86AE2128F2B52CA5CE3C15880969B5BF23395372915D4B8B483C9FE5355664A61C58274EA9769D4956C951DA3CB8ED27E0F78D302ACAA46198655D3C894B5E6065288397F3044C4852140001D964024462141575F489527114294A66D082FCD880435EFA1D3AC5D4B6F29C49702DA71C50BA6525D130E246D7F2CD1684B9D8EDADF03BF4BC6B0E29D927116153549AAC3AA54505963BA50B8F200FD9EAD72A3C464AF309E0A1C929529214C01B020BEBCF9831C31353A546F2732DD8EE952E45640F62D4C2C58F604EB1FD401DA287FE12B4CA515E195598027F21046B637DBCFE515A716C2D0C95642AFF00C5EE39B103C881A5B9C7256EBC96C38B69E209094A12658F9EC482E59D2A4A36372904DF600C5B28784AAEB2B26C895455128A104A0AD0C09716724EC766D3568A9955B44B0F29525DAE4939824EE0333F9D9B5DE2AB575B7775D946DD501F620CD234057F538ECC32DB7A503EF1438AEF6BED7BFE13D9471AE275B2A4D0E1959390A580B58924A5B3072181B5CB3B16D6E62CF8862A64664CB58704B28017F41B72040DA2C1B8B8F10DE1CB847A2CFCE634C614DAA62C9469C94A565BE199D15CC4588EA6A05B9708128B758A7B6B7085A91393724E048292DEA3A237E7B20F83CAEE24952558CD04C92E94AA74D9E9549952923F3CC98B2400948F110E4EA12924B1C697C455A92495800961BBF20C4172FA722768F09F0F1E2BF8B3E2AEB38F333334B29BFE9B6443CA43797F25392D28CE27B296C30CCCADA179E9B4BCA2B7D45F71C682147944B6124C3F111D8F7655D9960F2F0DC0EBD38A6392A91733119F21C524A9C4A8225CA5CC285AD61190A884146ACA26C6E1418BD7CF733192927C0E3C4A7DD5661D1EF71AC65E4582020283A9D2DAD0F0B0252B6D24A1D48B043C95156A45B606F7ED1E5A570CF5F3729397BC521B29B82A2414FF00E395AF6F1022F19552CD5CC0EAFE90E3705CB1D1D88D03B5DD9DE25F5F9FE1B0FF009FAC71393DCA425048CD753EFE11CF7B1FA08A95120A5B737F9422922284211037B8B74BEF11272B10412A2D95B63777B8FD6113DD02F706DFBF7FC3FCC44696A8242CCB504B12F95C16E4403FB7A453A7BD3308259235077EA352D7DC8895C42DA046A0B5A85D0803CC01E97B6DE9D7D62BE80D1CCCA89B294B59B060352586E1EDAF5DECF104EAFA6901E610920905CFE66676BBB79B6BD23A8621C5941C2B47A9D7717D6E9D85A874C47C44D566AF34CCA4AA5948D4B4239CA1A5691B153E8434BD24B0B73CB7D82ECF3B16ACE35AAA6974987D4E59CA4B2B22FC44B00C90E18BEC39078B657D7489D207FB79CF38A400004BE63A952B5B1D0077B93CE300DC6478FA651E50D72A980786BC28E679634483292F5261130DE1E909F410D170CD3E584BC12BD4A216DA987083C9538DE951F53FB16F80744C954D88639293494682954D9935330A859CCB084A55333382012909041721DA20E1FE14E35C62A9225C89932529418250D6240D580B0D595CCB4613333B8F4F127E25669C7316E6B4D65AD027895270FE0F5CBE1F5CA4A2C85B52C87A8ADCA09B5B634256B79D52884A964EA11BA3807629D937074E44B9783AA6D6C82512E7CE2522614B8CC519C801C022C1F70ED1B5FC31D82565751A2657D1CC33549495008218B5C936737DDECFCA2D7EBF96998B5E74BD8AB3E73527DD9A56B9A2E627ADCD6B5A8DD4415D455A413D00B0B5B6EA63B329E470B5304A65E1985B200033E1F46B36B788AA512A2DB97BDF611D9141F0C941387F128A71275BCC07AFF330F31FBC51A3E5963CA1BC66B09E7DE6761D9B4D8279D886B8CA1DE58013654BCEB8A015606E6C77E978E67D3F09D524A2A708C2A624F2C3E925A83FFE4896147A0760C06822756FC30D04A4954BA49E0B59D4B51B6AC3391E5BFB5AEC72AB8F6F108E1867242770F661CD66D61B90790EBD43C43308ACBF3ED36425D9044CD792B99964A9948502CB8DA12B74AD2AD6551D65C43D8CF66DC6B30D2D5E152E5AA6864CD401DDCB725F32259761D10A2DF96E008E98E32EC427E0F37FE969673A525403172C0E9B35B9EC7CE3609E073C6C724389E9C6B2FF0037A4939319A336B44A3F46AD3825E9534F25294BA86AA6971D4B4ECD15290C043881AC84829EB1A1BF11BF07ABC130DA8ACE0DC355329B2A97DF5382B0A1AE6C87F8C848DCAD09667360F1AF38E609C51854E5A132972E5A4964AD07406CE4A48BFF00E24DC4646F8C5C0CDE6D70AD9DF81995333CE632CA8AF48D2D128A13087DA9DA7CEB4D2E59D41521E52814941D45C49B900289BF407C38E078C766DC57455189CA99227C8AE92A945492005266022CA0016BEA1BA3458654F417189ABC62C46977F47D6C7F578D7EBC24B13BB5DE19061C7DD52E6F01E35C41409C2AB24CBC8389916E5D9527B2B5CABDF6A46BBDFCC488DBFF008C0C30149AD4A58D44897509527465A1C11CEEF63A5F9BC77676778822A3BA4E77CAC94E8580E7A9240D1BADF9E542725C30A2DDEE0A10A041EA945CA0DF637F31D47FAB6BDED1E78E032D3579D154490851DD8D8B7401835B57BC6C19A99D2E4812CBA5AEE1C37933EBB80F1D4B1DE1CA6E3AC178A309D765A5E6A9588E8B3949A834EB28D2A6A699536DAF64DD2A6E60B2E85A46B1A763B98EF8EC578CEB385F8DA422967897241406597719D162E08B8D459B71A18C1F8C706958E61332555CBCC120A835988046BABDDD83D86F16EFFC3B59E551C84CFBE203C39F30AAAEBB3183E66A989B2DA66716196EB126D56D997986A442B4AE61F986AA089AE72921D2DB2E0D7652C1FA0CEC7B8A24F1170DD3552BBA4AAA643AA5214E94CD48026109FE54A9449969B009D0001C79DFDA260F3A83129B264A5425A1647E50E41360E46A1AF7D6F7D63010E8494D94350B7E207FCFA7B46A3D3338B3B93AED6FDA3EA131A9399040E40F2DF7D35DFDC74F09E22A942A19515C7255239D4E4AE79214095361B46A529045F495684D8FAA77204766F0DCC9444992B3FF00AC951E81C66B5C976B82588D846907C48E062A302AB9D949694BD47306CDEE435EE7A36EFDE1738F9798BC0770F18B1F75D999C7703D3E9B5171C525C7153B201416A2A493B143C80012163492A16B13E15FC73F094BC338BF14CA8044AA898CA218975A94E6CEF7FA72BF993409EE265420021E62CF3BA5C01B9E6DA0DB78C81056A492011B13BD8FF7F4F68F38AB96F4E10FF954DE400B020F91BD8F58868521557354412A48370F7399886F3F7789C1B807D45E2C517B8421084210842108E287036A374A8951005BF01DFE7DBFC45752804DF64EBCAD14389826953BB28017BB9572F2368F15E22B07378FF24336308BCD87515DC0589E450C9495175F7E8F3ADCBA52122FBBAA4F4B1DEC37B46E47C28F10FF00B6F19D123BC293F8991BB1BA92799661F65A24A7F874B2D4C6C92EED6E8D6D7D9C8B1DBF3DDC85BD1D7989825F4AD28C378CAA52ACA15605B5FF003279A08B13A868280A5277D88DAE63E89B139A6BF0CA2A8242C4EA2A69E14096FF00B084B83B8F06FBEF78DFEF855C6325225015B04949209D49B02FAB8DB7B9B08B842AD2AD2411DB576FF36FA461A85642400CC6D7DC59EDEBCF40EF1E8561EA456119C0620172074BB5EDB5C0F4110710DA6CAE6581DCA82566D737B00137236FE906E76EA2262A4CC9C52C09CDA79E8C4681833E97D4DC4565650D2210A5AA64B41F3034D7CBE47503A70AB13D214F91339549D669F4F646A5CF4C2CA1A401651BB2019859B58F91A55BBDAF68AFC3F86EA2AD655DDAD85BF2FCEEC2D71AFE91D6FC43DA2E11C1326677D512734F4AB2A4AC12E06CFC9EEDA45AD63FE2DF06E1B77E070A73F12CCCB9500F30C96A4798905239899C4B0EA91F7BEEA54490362378EC7C0F82D6ACB9E50008B022E4BF20EC741761EB1A55DA77C4BA65CD988A2A8252EB6C8A0CC0D9C86E970FB08B4AC43C56E62D75E996E4A7114A61C52CB4C4AB2EB6EA413B0D6A64377E83659DC8ED1DAD85F034AC89CF28330CC598BB166D0F3F3F58D63AAF88FC66A26ACA674E20122CAD3AEB702CC06BCA3A02B3CF345360713D4AE46E04ECB0B1F4DDC0458ED620456AF81640516942C4B02069E46EFB69186D47C4971A99F311295546585B26CAB279D9FD2FA73D23992B9F39A88F3338B670006EA0E3F20E1B8ED65294AE9FF68B03EE6203C0D20FFE881C88047B38617F4B74823E22B8E124280ACE764286A3958728EC725C4B66ACAB8D97312A9D4A41F23B249285AAC426EF372DA6E5440075D89B24122385F004A9A8EEFB91C8300EFC8F97D22E523E26B8CE9D48FC42AAD32DF749B6BFCDF527AEC5A3BBD378BFCD094F254E5E953AC9FB88703697562C371E54F5B9B5EDB7A6F165ACECC920102597035CA37D1B53C8B3467D807C55E2895A44F9D358104B953DDB571A83CBD7AFAFE1AE34692F34A96AFE1C9E69E4E90E3924A91424036D452B79F426C2CA360AD561B0DA311ADECD569CCC87B924005EC3AFBF2F9C77B605F143267213DF4EBB004A9406A3CC5FA6DABC5C6613CE6CB5C5CD3029189528A94D00D2642A41C69F97709EA0BE84C8AD1E616710B55C8201200B61B8870157D35485CB42932C241206603ABEDA6874FAC76F603DBFE01894B126A66492A51BE628D4EBA9FD36DCC7A55428B42AE492A52B14B91AE32A41E6CD4D7C3BC1095742C2A5D4A652B1D504E9712ADD1624C5CE969E5E1A902A90429296CCECA1EA082C5AEE59B980F19BD4613C1FC6F48569148A5CE4900B21C9201B0B7F516FD23C1E77217F97D43FD419638D311E01AECBACAA566E8956AA5203642B50D53928F3334024D88D0E103D2FBC713712E1DA9229AAA453CF44C390A6A254A9E03900B77C159736F9407B3EC0F41716FC31D26253A64DA1928CAF9FF86185DC8BA40701AFEE06A0DD365871B7E253C3DCAB149C279E752CC0A0CBA92A3298994D57A7E6128160DAA7310CB3EE5940149D33009BF7B4605C6DD82765F8CA26547FB651C99B56D373D390C82A724E42ACA181B0096E4356E88E24F873C4F0F4A932A4AFC2EDE156C6D7624B73B836BBC5DCD17C7978EDC38D3E9C4991D83EAEE4AB52ED29F0DB6C4C4D17028257CAA7B8D498594A16B51165100EBDEC23AA47C1F767D5B97F09916A98095AA62129968B064B0014E6E2C0DF68EA1C57B12C6E925CC9EB92B4A520ECB7B6B76B681CB87F38F50CA1F1ACF102E22710D7304E4BF0D186313E24A52968A8B72532DB4696D25E0C1995BB509E9794490FADB404B8E5BCF7B5818C5F1BF83EECD387D02BB13AB9186CA01C4E01241524BE520824D81B80D6F28E92C5A86BB03A85CBB950514949517E5CEF6BFAB6A045CE4C64EF8E0714EDA6999818D70CF0E18426D2029C94AA619555C4A3A2CB434FE115546A087792A572D4E2D2B0E006E1636C3E67167615D932552E5A2562D53252596A120495286A52C5135C1E801DEC62810AACAA63303025D83A94DD366B86D7F58BA2E1A3C15322F2A31149665674D7AB39FB9AD2EF226DCAEE339D9EACD20CDA55A8BC69D54714C4D2C1174B93926E39AACBB858046B4F6C3F1A61786CFC2B8366270AA6CCA6451CB95256A252A19664D9404D988BDD2B5949DDC08AE97869CD9D4824B7F33D8F406C2F7B01A6D199AA7D2A9549625252914C93A3CAC9A10897629AD89797974B32FC865B62510132A9692129FB3E584A06CD8012911E6871AF6B78DF15CC9E712A9993A6CCCF98B9B872C9B3000DBD185ECD9251519094B8B387491AECEE390D1BA748E5A414048164950529F02C12E3EA75479C06C428B452952459208F28B111D554C65AD7DEA92E58F8945D4D7B33A80009241673B9D4C64B265F760B905D826C1C240162753773E4DBBC5403ADED7ED6EFF3F7DBF48A4AE5E69C024B8018EC06A74DCDF5F7D6DCA9473B316041B9D9B6BEE47F6845244E898A4817DADB7E708842812D77BFCA29856AB80924FADC6DEF6EE7DBA6DBFBC490A0A0A0E42487001BFAEDFABC4A99332CC422E01373CF4B37BFE912252A5072EA03CBE50A36DC7624D80E9D49F9464F33134D552CAA1A7965535404B0C87249605CB6A3FC447553532649502C403770FD3CCFBD85FADBF7127C4B654F0AF96B89B35336312CAD06994D90755489379D49A857E6C254A4CA5325FCCB2F2C20E92F25B6F71E71D236CBE1F3E19718ED0EB29264CA49A65CC992C84996B01944396093A072543401DD8DB045D1D763152A45385AF32AD95CB8277D1F6E67EB1A46715FC7B7119E2338D2A4D3759C41963904CBEE4BD170CB2FAA9F3F5DA136BD34D7EAE698A2CCE3EF4A250E388987DC690E2945A02C0C7BC3D9BF615C1DD92E0B425345435D8C53489495CE500B97296103BC0944CFCF3133129F1E5524B1214418D98ECB7B03C5F169B455357226A64CD285F8926F998B9B75E86FA08F30C138170F6069644A61FA4CA32CF2D0D4CCC4E4BB5393D36B4A4054C99F984BD361CBDF4279E10D83A50024003B465F6A66850BA214E90951214A125001528DD49CA9600BECD7BB47A7FD9BF60F8461541226D4524AEF132D1F990926C90FA8279B1B6BEFDEAFA6ED052DF964DD4C87EC879A5ABEF6971AF369DD400D7D2C0F78C7314ACA2C625AEB10B4A6A49CC10157B9B8606FA97DF6B1B4771FFC7308C39A5A244B01366084B5B4B003E4E6C4BBDA29A523FAB58B74D2F3CAB7FF00DD67FE778C58C99EDF99577DC8B3B6DA74700758BAD2C9C2E580F2A5863A6506CFE4F7366DEC62294A5BBE90A59249D4F28BC45C1E8970AD2074B0000DA0254FE6BD0EEA3A07E77B44CA99585CC040948B8762801FDC7D3A7945441085978A96EBC41400A4A1965A411F79B431A0176E4F9D49B90120A88168BA51624AC2489D349241D49B84EB772FFE1CEF187627C0585710AFBC54997E1052F952ECE5EE436A6FCAD1E5798595987B1B044FB3CCC3D8865D6DAA42B74A5B92532CCD257A9A9D7E6A554DCC9725DCB38820A8123CFE58EC6C1B8A308C7252A96A65C9529485CB5A66CB44C44C42865295CB582852540905D26CF1AEFDA8761D86AA8A7CD974C824214414A0588720BB3D8EFCEC1CC665FC2AFC52F12A2B14CE0A78A3AA99533ADAA9597D9A15971A2E3CC280966E4A7675E2661ED4AE5F2D242C7995722FBF41768BD8161D886232318C0E9E5CA49A997326CA96923BA566CCE3F94A14FE101D4194140067F27FB5AE07C4706AF9C99125484216A2E80C960A3AECE06AC1CBF5BF4CF0CC9B4E08CEDE3532550A5372D4ACC0959FA3CAEB4DDC944CC56D4FCEB090A3F62FA56C94A810494EE00B475F7C4F70AA95C2F8695054C5CAC365D3AD4A0A242E424BA0950CC549CC3310E18863CA6F64F5733F1224920A92B620FE67703FF8EC6E2FEB78CCBB8E2DE4214B275140B057DE40DB4A15FF00926D6245C7707B4793735030AAD9F2C9CAEB5063ADC97B0B58EF61BBC6E24896154E92AB9CAEE06CDCDAEF72F7F91891482A69C4041755A524363A2CA549D940F54804A88FFC45B788B0EC597418B53D64B24293312E46ACE2E79E9F51ADA2555CA973A9D72AC4A9243303B6DF472E7A68230CFC7326B5C27F169C38F1EF800BD2030D63790C298F154B4ADB6E6A8D3AD3B27353152242187582863984BCA279BCB576247B45F089DA9A6BA8E4E1132A539FBB44C9685286799312529EED2F7FC8A5AC8B2591CDA3503B56E110F36A932588529CE5D2CE0E83911B104E8EE4E3C9C20A7637363E87B7B77F9464B4E3C5761E271F41ADC0F6D9E3E8371212D48CC1419B5777D43D8ED7FAD8C797E6EA3565B62F4A6C14BA1D4398576094A112EB29DD5B0372AF73D3D6D92603513D78B2244A42A624655A9280A2C01B9B07E7A6BAECD1AB7DBE53495F09562BC2491300F3CA34776E4C7CC5E36D2F0299C72A1E1C9938B5AC96D8AC629A7F989B16E4A5A80B60A49B5D054FBA1253749B2AC4DA3CA8FF00504453A38A31594A5244F5CE52BBB2597F97FA75F96DE71E422D915D572D2E0254B214C59CA94000742435C0B8717D23314E0425A3A4A6FB0DAC7A03B7FCFEB1E47D7CA32D0A4CC4A90EA240208E5B9D7D35FA718581DE4D2EE49D5B6720FCDB76D209FBA3F7DE2C11733A9034BFC8DA26842108421084211414D8D48F4D5D7D3F771EB1574B62B3A3A0805AC4DF7D39450D72553652512C673DE02000ECD73A740D731338D30EF31A7501E69681CD6F4EB4AD03771040BDD2B4DD36EFD3DA3BC3B0AAD9D86719D0CF9CA32A4FE2A493356E940016904B9606C0B9F5B452D613268529596514A86570EE5ADAF5DB73A388FCF2B3BF2F26F21F8FFE26B29E642D99238D26AB94C4389E525E96A9C8CAD55B725F504971A4BD30E36168D48D6DAD37D48508FA61E06C464F127675C375D453D35AB4617F859F325284C79B255326292ACA480B12E62014D884907420C6E17C2C57C9955D2E966CE4CA33662322545B56167D5CF983A58BC76A0E25F1A0900D8DD4748001EE49B7B7E178A04CB9899C5131241CCC0301ABBF2DAFF663D2EAAC630DC12994B99592652908D54B0901D2EC6FBF9318F10CD6CF5C2B95AC1949A9A6E7B1025B53723232AA1349D400B7C5219E614A82880438526DB91BC763F0E70DD5D700B452AE625B3254104DB90700374E86DAB6A776AFDBFD26088A8452627254B405B251303D9D9803AF2EA7DF1A398B9C98E332AA2E0A94F4E352BADC12D4FA74D225DB6D2EA87D9B92E95A4BCB5D93A1252A234A86C5568EF6E13E0F404CC13A53109BE64B1CDC85BEB71BBC79DBDA176DF8E71956CB934F327CC44852C128528BE62395FF0097968FCAD709C37F0139F3C46AA5A76998666F0CE1C69E417310E26939BA6CA2985DC739A4B8961FA80360409343EB370AB69D463B129F87A453B6596905C1609BEE753A00D6D3E66313C3300C6388D693512E7AC2F52A0A6BDCBF9EFA6B199ECA7F066C96C3F2F273D9A75FC538D6A8A4A0BF49A7CC49D3A85AEC35203CCB327544B60EC0AA642ADD49317D914A89432A52C036A007F205CD887FB11DAB83F62FDEA52B9B24826E428286ACEDCFF47BEF17668F0D2E0DE5E5DB97193D4C5686D0D0E6566BCEB8342401CC70D5D456BDBCEB2A5151B924EE638553B92420B126ED673736D3D3A467345D92612854B97369505401CC480059C392E01E5A75EB1F2E6BC2D78339F4153B95B2B2CA37015275DAE36B4DEFBE9356FBC36DCA7BF4BC71DC16CB90B7908C8D3D94E00101E9E4861CC6BA3B0E77B3B6A2C18479F55FC21383E9F43A24E8F8BA94FAC82DB92588669C6DA37049089F9D7A5943A821C6D440DD365011C042A4B14CB512F6B3EAFD1BAB5BE516AADEC7305AF49A64C9952CAF45D8007567760CDBB9DB78F01C69E08B94B502A770666B627A24FA8DD96AA6C53A7986C760A70539F6F6DAF757B7B0856B5AC5E41EA72F46D00F96F6BEE7AE71BEC2A55085AA9594521BC04923AD89776F41CF58B32CCBF06DCFDC332CECC60EAED0330649AE6A954C2EC9D2669686CA885075D553CA96B4A41294AFA9D29481B4502E94ADC9907723C3BB3E8CFD0B6FF2EB1AAE05C630D98B4C99352A009CB942890D70EE2CE77EB7B698CCCC3C9CCDFC9CABAA471DE0AC5584E6651C28957D74CA84BD33E192AB216D56C32649D1CD0E6FF18B36B1E8413455382A27C9528D382A20B0CAE599998DC5F90373B45BC2F1EC1E7A4FFD44B5D94124281B68EEC3C87EAC0F66CB4E2331BE067FE0A767175AA529D46B94997C3E6D7B25499852C92E27728643A54B36484AA3A7789783E7CF337BB9331249533A54524B59367676BAAC39C772F0476DB8A70FCF932AAEA264A40287EF14C19D8FE7B10DB5EFE91928CB7CE3C1B99D2ECB1213EC8A9A5B1F1143985A24A602AC2FA5B74B0F2D37B8BA49F99237EADACECF27A533679514AA5A4AC02E0E64DF6E6D601FF58DFF00ECD3B6EC231B954D2A75753AD533225454B41605B57B8FD39EB1EA09429E2B4869C25B27981B59496FA8BA885274DAC77558758EA6A8AFC5A9EA552EA67AE54A9530A1E63846549D8AAD71E91B335585E13C432E54CA29726A814254A32C256012C751AB83701CFD23AEE26AAA28744AA5414E252DD2E51CAC3A87969742912EDA98014E12A0752A69361AFCBA76B6F1D8B8157D64EA1CF433BF10C2EA96CB6722E40B59DEC34D43474CF6ADC3D82E0B80D62EA132244E1296425602540E55598DEFE568CEEFF0E5E4C2A4727B367887AC34A1399998B0D3A90FB92CC95990957E7DD9A32C669A3CC964BCD4B8756C6AD2E1681502A00E857C7776A58B70FE072F07C2B1614B574EB909A81DEA4295304A589AE012CEBB91B1B168F16F8AA7AF14E2EAD909967F0C85CD29580027F3B000F95CEBA0631B28AC9B04852260FF00DCDA10D293BF7E72529DBFF0B937D85EC078918EF68F8EE2555306235951521DCAF32C82B7D3C3CEFA5B6D35B850E172D0332C2410400540A8162C1B2927D3C9EDA4028136B11E97FDEDEDEB187D6628BAF9658AE5ACBBE75A89BDDEE4ECDE9EF174551CA67006FB973EEC469AC4D165974E0A9E6AC6BBA85EFA92E75EBE4F09729282592401F3BFB11E43DDE2900A2A1D45CF522DB7D6E361F3FC6209EA32D652953A406195EF6D8D81E8396A22A89194017E67D496E7AF97CE2A902E45EE36FD07A7BC49432828ACB1670E6E4BEEF7761C8BF2668A59A14569CA0B39CC46E001EFFDAE358404B5ABF2A4ABC81FD408A88A848D16BEF61B77ED1C042C9CB94E6E5BF4F7E5FB44AD167D4F2DBFB811C7407374A6C0ACA50906D75ACDF4A137EA5563602E4F6117BA2A450A6A8336594929F095037716F37B30F360E628EB0A84C94B03C28512B3D010E4B359B998F24CE9CD8C2B91196D8BB36B302A3274EC2782E9EFCFD4D7393ACC921F75A6DC5B34F6DD79C6C2A7664A4966552AE7B896DD2DA0842C8D99F86EEC5311ED0789A8C7FB65454D389D2C664CA5A900155CD937B073AEFE716AC52AD754052D203366AADDDCBFCEFA3B00F6D0EBADEEE63447E2BF8A0CCAF120CE5AA663632A9D4E87925862AF312383303A1130CD3AA6D25E52589C12E127E2872591776EB4FDA7DEB2A3E893B30ECDB02EC9B86E96548A6A64E24BA694B9B352077B2BF8779284BB254491DE2C8CC0A404900A9F68BE1EBB29C471CAA913F12C2E7A6515A559A6C92124020B9253A17B03625CB6E38F232125232AD536565DA9495966D0CB2997683494B4D00940012058040000B6DB7A4438862757595B3D6A5A84A5AD65291A24124E56602DCFCC728F5DF87381706C0F09A212A5494CC95252E909402E129D99B51ADDDFDF9FE40021054423CB75022FDEFB817EDBEE3E5145328E96A85C34C21B36971ABDF7D747BF998C90623364B499682258B066667173A7D058DB66450A30A5522CCF44E0509D519EE43EC1C9BF5DACDA472AA7156EB54C097D89E5EF7E9EBCA1159F8B2FF94B7917FF00FB629CD025258AD2DD08B9F66FBE508E3F16A7FCA5BCBFFF009FD3D638142925B3A4827A3E96DB6FA69AB422867A7F1B384A59C8950D4F8400347D2FD791E8C4264EA09C9972939D0A05CA466B93D1C69D039D440A0B88711E5D0A6D61DD4403C9D2799A3704B9A6FA129BA8AB648262BA46132F0B29A8A7AA429563952BB9B9E449275BC48C6A4FFB9514C9532513990A0CA4DBC42F66BEBA6FCA3C6F38701BD89284FD5F0E2DC90C5D86529C4B842B92CA53151977E4C29C326148B39CC5AE5DB2869492B55F61BC76870DF119504CBAA49521442559C020A5EE6E3F35EDB837B6B1A51DA9F6492315A7C46A3F0256B12272832092EC4836DC723A9B35A3DB7C2433BB11E29E31F185471838E0C4B8EB0AD569F3C1D05B53935465CB204D388504DD4AF8E2398A1BF63D63AE7E22F0BFC770AAE74A42574F213326E6431093529B249D8A7BA720B9BE9A13E6EF05E1D3301E24AC93894A3421357312813C6474A5458F89AC5CF2008F28DA854A2B529450A4124EA0A4A9373D3500AFE93D88D8F68F0B78E259463753DC8252998B0549BFF35DC00D650F4B46D9CB9B2E6D0A2648509882900290414D803B166D7DDEF13CBB8A6DF6D482906E41B916B14906F7DBA9118FD0E498334C504A8390542E48F6D6CDE7168975673E558290A39731B82492EC58D8D85ADADC18F00E287282899DD91198196D549444DCACFD0A61726AD05C996EB72E9130C4C4B5AEE151710B48522E4EBB026F63B5BF0E3C7B3B87B8AB0FCD5429822A258495AC049739487D829248E80FAC629C7F831ADC1E7CC44A2B2A4288616279B8F773BC6BA31E9D800681BCAD1EC44C91FF00464907401EE4585F4BF31CBD84792678CFA2999638B661C017CEA4CD4B21B3DD4E32E276B6F72542DD2334E026918E2A7A9208553A920A998A8BD9CEE5FCBE66351BE216BD349C3B5925445D332CE6CE9D9CEBA9B6B1B82782C61898C29E1D19032B30D299357A6CF6206D0A494DD350448B7700F507E17A81D6F1E2EFC7EE289AFED57144CB5E74A56A49F1020F88D9816F5FA5A3CA1967F115152B0011DE2D4E43D892EC762DA1E57DE32BC36474FF00B761F231E697134C1327CB4A5AC038075CBB9676B37AB9F2978620A274D17BBEBB37D9D39738E427A0F90FD23128B9C46108421084210845258B91F21FA9B456CC4997229D406555CEBAEA7DCB7BB44129250B528BB7EADB3DB604B31E7BBF0661C719E6724FDA5D84F426E92E8E674EC13ABADADED736CFF8671C12574A33E556648052C08B84B82CFC88E7B9B03160C7164E4CA49637B697258F2FAF5B5F4E5F1DECA87B2BF8CFCA2CF89060314ACD192A661FAECFB80265DAA926A53326E17DD3A509D12AFCB295AD42C83726C447D10FC09E3A317E06FF006498BEF589AA92952B31EF274A44B9AC4920782520816172EF1D9DD96F17CBE1EC5F0FAB5CDEEC4A5CB330E6CAC12B0A0F71E8E3D0C613B3BF897A661C969DC35835499EA93C971B9BA8344B89975105254CB893A094EE76BF4F7BC6ED55767AA9D5826E42139AE02497166660CE5CB38201BEE23BF7B41EDDA5E214CB952EA9C2A594B2661727281B17B33F9EFA08B10C278571CE77E3C91A0D025EB38CF11D65F4896A2CACBBEE3DCE797A7F983F38D34392C24900A16EA1002493B5E3BD7847034E1F4A842A4A50128B3A41623405C13763E47A346A462ABA9E2DAC9995732685A8FF003A943C5C8BB6D7EA0F48D8FF00836F0A0C2D964AA5E37CF26E5F1A6345A6566D187925B552E8E1214B5313C862C875C529490398E1559A50DB7BE634F2932D730A400E6F66D5F6B75BB74D1A328E19ECC27D22CCD99289EF082E52ECF7704DB77B78AE7A36686429F4BA34B0A7D269F4FA65365DA0894A5D31A4B52B2413609B252A55C84F97751DBB455C6C570B6009C3E5A54A94900009FC818BB390E19AC18ECC7998ADCE1EDF818476326A5126584A5297018D8338DF4D39F3B79C4A5A2AF30EFBF6EFBEDD2D6F78AE487487BB80403B79756D75DFCE382A0BF1B839AF60DAFA34020A363D4FEFDE3961C87B08E2260402094858EE93D0FE9D3AFD20C390F611CA4949046D13F31BDBFF004E8FCBEBFD5F85EF6830E43D847135A6865006CD700FD45FD629FC858761E9EDF48651C87B08B54EC165CF2559125F7291F2B6FE7F48E9B8DF01E0FC7D449AA3E33C2F47C494C7DA5B45AA8D3D1373002C14AD32AE29256858041484EE146F6DE28EA27F74A0819763700EF66007D6E446238A767527149E26AA5A49660C1AF7D2D6F6D6FE5838E2C7C20256AD2F55C6FC38BF372134969D9EA8E05A9B6D3466DB405B930AA6179965D43CDA3FFC74B4E951510129518B7554B15082084E8760E4373B7F88E89ED07B2B9D225AE6C896A0CE5D014347D0A6DADB4D630253F4EC759478A1E939FA55730BE26A1CC2982ECE33312AB94536E589982F213F1282A49D37D62C0DBDF03C5307EF73A4A432810C007B91B6E3A36A4F3B75D70CE318970955A10A5CF025AD3AA9603037BB8B59FCA322390DC4253B1F3030F6259A149C4520121D7B572935255826C0AFCABBA813E53FD5B4744F1C766C9ACA69825A594A51629706EE5AC7A06BF998F473B12F886A5A4912A5D45427326584A84C98F719458294480DD06D61B77BCF29AAA4FD128D81A94102B78F6B323469096974EB9A7A49F7343A8084EA5282CAD876C13BE8BDFADB09C030FF00F8461758BA8392549A79D3A62964654CB407CC4AF62ACA39B961165F880ED569B89A9A7269AA1CAD246542F5716663A5C5C3E91BDEF01591F25C3AF09F93994922D3685E1EC17457EB5E4D0F8C4537212CBAC29CD81BBD3A5D5AEE012A17EDBFCFFF00C66F685378BB8E31239C844CA99F34A10A3DDA4AA66664BA8B84DC3B9B3C79F8A923F1932733B95788B392E2EFBBB5FF004DAEEE5D5CD5A937DD249F6D8F4FD3F3DFBC68B4C524B82012E0BB8BB5C3FAEE4EA22B51A06245EEDCFF00C369BC72748BDFBC51AD7CB5D2C2C1BEDBE5AB4554462917F98FDED08443087484224045CF626C6C4F7B9BFE3B7BC5C697C0852B98EBB6CCF6EBA7E908A9636BF6BDBEB14E89E4542576FCC2C40259D83EBE5CBEB121572AF33CF57F7D629ACCAA4176694B436C254F9712A290D06C02A789B5B53771A6FD8AB63BDBB4B87B0B9FC478A61985C996A5FE2262107225CF88A6E7280F627A1BBBEB16FA9A8C88327C39A73A58B9373CDEC093E679BEBA6778DA71935EE26F3E91C1F656565F94CBFCB99875799D334E7F5D3311E2075E6D971130EA35B4EA29E996994B21B50004E39F7AFB7D047C24764323B38E0DA6E20AFA74FE2ABC20512548095CA12D20CCA898E0121D6912F44ABC565338ECDECA3B3BA9C631BA7A8EE14B97DE254A514E677513941219AC5EC768B0FA451E9944A53147A4B09669F4A9666564194EC1C742425D7937EA3C89248DBCD73B18D96E28AF4CE6A94ABC201243DAFB30B103DF9878F60FB32E194E0D85D3A0C844B5265201025A42AC058B241DBD01F37FA4949425282A2A29012544DCA881626FDEFD630B9733BE4899665DC375BFEB1DB19945C1240BB072CDD06DE513446E468488E21073A3DB941CE8F6E508E18721ED08418721EC2108A69A82EEC6EFA79DB4BBF3FDA2A242920B167770ED7E63CE207FB8FD444996179D8AB30D85C903DF76D3EAD15134A5495048B80790DBED8E9A8E713B96D02FFF00691F881195E1D332041258020B39058EADEDF58C2F1BA74CEA7AA494A4854A58BA5ECA4B3D83962368F21E174AF2A7C4332AA6F4A69F46C5B306940A7CA959AA4DCB09AF9ECDB5A80DF707D0C5E3B4447FB876638A84273A9292A700139532D6EE7903FA8DA3C8DEDD785E652713AE6A11DDE69E48284E424A967FA5AF6F96D1B8207D2B1A52A2A09011A95D490077DAFD47D0F7EB1E0FF17C8553E25896701FBF9ECE1ED9B6E619F4319B70B4BEEB87658513648D6E7F28D497D87AFAC12DEE55D0107D3AF7EFB7F68EB2739105CD94D6E56DB97EADEB45312B989003F86606661B9D180FB0F0B15794004AB600F424EC01F63D0FB476070ECC34757435E145065CC96B24129200BBBEEED737370CD17DC5D299B82CC944329528B0604BE536F1737F23CA3558DB9BA7FA74DEDF4F5FF78F6EA3D51C5670A6A13A0F0F36D05EE7993E71E01C43BCA9EC2F43C2120853957C5D8858A54AA1B1A9C710552E85A023CC08587C0E9717B8B11197607365D0D2D462534E59349227D44D568909929CE5C8167BEF7DAE63CE4F8A1E2029A1A992951F1A5490DA02410EDD19FCB6E7BFAF09596FFF0049786DC94CBC5321B4E14CBDA153D0D22E94B2EB8D38F4C24024A8956B413AC9370371BC7CFCFC4EF10CCE21ED1B159CB9BDEAD5327A8ACDDDA62D8F8586846DA7520C79E782AFBE4D42C6866285AEEFADDCE8C0F41D22E554004F96D627E63FE2F1A5D3CAAA7139A955DA5A8005F549D58EFD34B45753CBEEEA66302C413A36E6D1507416F48B12832943400903C9ED1510886108421084210FD221A4137F4B6FBEDDC03F3FEF15336685CB932C5D49DADEDF3F939D624D44DEEA59274B96EBF5E46C768A4BE436A4ADC4254A51290557BA428596E26CA02EDA2EBDC11B6E22E32E44FA697267074DC29C07D0BD987CFD48778B70A5358952F6059CEE4E9D1C9200D7908C16F8FE70F5FF0058B826C498D68D21373B5AC9EAA0C5ED2D085DC61F9144ACED6A78B8CA50EA25DB9494779AE21C4F2D2D29695A092A8F68BFD3D3B4D4D2E2585E12A58986A952E8D28528D9738F7692CE0BA49D1F958DA30BC6E7D46164896548502E0076617F7FD3CC46899905C3E66371199852380F2F69B393EE226597AAD599F65D5495224DE5D966AB3366D0DA025B5960A9D68909515297DBE85786174989CA96B5842959520B0058B3173AB92E0E9E71C6054B8BE3F39092A9AA0A206E581DC83672F6B0763D5F6D2E13782ACABE1730D372349A3A2AB981392ACA6B589E725C2E69539A0F396CBDCB09650547CA997D0916040B98CB272654821080371BEA3A3EFCC1F902636BFB3DECFA6538953AA25160CA254921DB5D5F7DDFD8C5E6B6DF2584C828A55C824AD68528ADC5396075B9ACAD76D161756D7D80B9110AA5E54A56C40568E3D75B7DB98D87385D14893292132D052003F945DBAFDBEF154129472C5823A580173F355B51FA9882385264212532F282030D353E807DB449A53E9F9910FBFBF68A1988528009F6F6EBFA1FDA7B9F53F8C5722E94EF6F99BC554B494A1293A800442E4F53788A238100EC6108974A7ADBF0247F784251FCA4F57F98FB313422ED226CA00020397F220071A68DEC6CD03BE8FF00C15AD3BF456DBFBF41D6E22D555256B9E0A4961A803404972E41BEDCB42ED1495D5C6956854A032E52F671A9B5F7F6FAC48E210E294E38B792544296F36B5F31B03FAD22E4109BDCA4A4A08FBC920455A299920ADEFD011B5B4D6DB6A7918A2EE6971E94B933509515BB381E5E640B7ED78B01E363814C11C5261676A9254C97A0E6B53D0E1C3D5691684BBB5AF26A0279A40128E9E604FDE6524EB3BEF169AB928217A39B0D2E5CD8837046F7DEF1D29C75D9953225D44E932929594A88200DBEF78D4DB1CE06C7591F98754C2B89A4A7F0F62BC2337CA4AA71A32EA9F966DD52553F2FAD080F0D4D26E4071BB2C6D620460588489C679973A5B245EE36E65EDC8D87EADA9F2A7631C2F533CA664E4A5135762E2C2E05B6671EA4B8DB353E10F9538978D7E34F2F6A95F924CEE0DC97A17FABAB95275B52E4173722ED3E5292D3CAD9A1315413333325BBF9952A421B4A52A11A6BF14DC6145C1BC198A284E122A2B50BA4968B34CA7095AAA54A3FCAA4CC4C801C87049019E2BC71855E2B35289F356B0F7CC492953DAE4E8C4BDAD1BFAD3A5D6C2A642921B2A2DF312940424AD492A5202400901A23400903E51F33BDAF631271AC66AABD3342F34F5827303BAB4E8C2DF2D62F400EEC16B9482FA9D8F9FBECDEBF45084364A9090926E49F5BF5EB78E8B9931EEF6FDDEC2FA5F488D3A0F2882D5D87D7F7FBFF0034E56E2D63A7D93F5D7DAF531327EE8FDF788211342108E53F993E63EB0892E35107ADC11F80B7F78B816EE5597928684177F778454241D449D086D049D879D5636DC8BFE16BDA29A8E42A74F4200CCA52D2C43B80FA00FA17F78A758214482FAB0B33F5F26DC83AF368C7F788D7144CF0A5C27666667CCCE891ADB720F533093414D87E7AB9372D3024E5986DC0AE6AD453F74215727A5AC47A55F065D8C4CE39E29A3A954B1DD51555395AE625E5CB75392A51601232104B8DAFCEDC29575588D02002477A3304B93AA59EDA5B96C3D747DC96A454E6A9751CC6C505D9EC519933B315FAA552714E393EB72657CE5CABCB2404961531BD908579EC7B5BDECAB461B4780CAC2F0E328228248A695DD1053DDCA4848CA1C92E43BB9BEBA5FD4EF87AE06A69786D254CD9290B2896B25490E0900FA970DF3F3F7148092D148B16505B6FBE942AD71BDEF7B0DD5757A1EB1D47895515CA994CA3E32E058DD8EF7EA2FF00E23766448972650952801943727EB6D44000901205801603DBEB10D2A4A644B4AB54A403E8037CA22D2231510842108421084226894172DF773E763A8D9DBA7BE91019813310922EAB8F4FF1103FDC7EA3F48B6CC010B012E3437F9BF42C475DA2E2856619B9F46D3689946EB427FA4A46DF33FE3E5174A69B910492C12F61ADB7DEFCB99B0EB66AD9266255AB3106DB3962DFDB61A3C7806369D99A0F107C386280B2C1A6633257349B0D2C998A616D249053A5252E5B55C9D4A24DB68CE028623D9C6352D5E27A7AA0010E73196962399B7A1667DFCEBF896C32448C550B6621614E181D4EFF00B39671A3BEE312AEF3909787DC74A1C6EDB0D0B420A6DEA23C32ED729BF078C62094A425E7CC66DD9675D083773A5DAD1D7782D4A060A84A7461E171C8BEE4F41BBD8E91F517E51E5DBA0FCB7FCFEBEF1D312E44C9B4C5694B842CB90341CC9E56D39B9DAD5B454C2749CC41233662DCDF4EBB368CF726290495102FA751B0574B5F6BDFDBAFB45DE8710264A2981F1A40209B1B036BEBE9B72789D3099E9553B38008EB6B5FA5FA7AEB1AAC32971E76E96C8503A4A09DC236BB9D3A0DF6F63BC7BE270F74A0A266752D0951401E2049D23D25E3AC5BFDBF0F99372156541D0B06DC8B1EA3576BF26ED9C0CE4C3FC5A7885E52E119168CF60CCAB9F94C5B8DDD5CAAE6651A664E792F196734A92DB2B9D4493ADA1D70A820A35142ED162ED478864F02F6678C55D48266D5A5726427433109964CE04EC0A5696D8DC0D2DE48FC4471DA315C5D785892A4AB2975E63B921258805C10799DCB46FAF2EC34DD3E9F2D2C90DB32ED6845AD608421B690CD9205B9296C1BDB7D605869DFE737B43E2395C41C5B89D72432553270CB9B9A9446A6C1FF00C46B5E08F4889885DFBC538243102F7B9DC73E562C5A390A074848B9FEF6FDF4FC3B4746AE77E17119B34A3BC042D838DCF36F724078BEA027BC52DC5DC3359FA9F5D5A271B003D22D130E65A8E8EA3F5842208421084210842237DAD6F9D8F5F4F51F94729B292A3B1076B5EFB38D3EED143588EF90C9246DE6EFF7FA4525B6B5EC8290B295A2EA49500971250AB0B8B129245FAF7F411971C4E4D5514BA64CA095A036721F51626EEC5FEDA26522D1225842F31CAA4AC652C4941CC97770403B3F3D8C740CD1CBEA6663E01C6D9775D6C4FD2B1CE16A9E0F9B95710172C6995A9398919E69D6C82A754F3532E0052A494DC5AE378D8FF869ED066703F1AE089505AA5AEBA4070B2023F88972E9D2C6CC4336BA08B0637868C4E6A67785194B90198B13721C5C8670C34768D347C3D6952DC3FE7A712BC2756E872B258CF09E2B7F10D16A330C8667B1150279C996C48294E0E6258A5B521AD2104EB1384796DA8FD5C7623C592F88F02A2C66410A45452CB5CC96924844E42121484804A9B2E455C972A277B76476672A8A8EAE54B9929335495A43EEC0F90B93661B30B4660E59D134D36FADC7D6DADAB001694AEF722E545B24DAD61EC07B18D84A4A638A2D534AC4A28BE53B82FA0B172DF60346EF615F83386A66499212AC83C235072EA6D7F60081D04546D21B6D2DF5D254759DD4AD447DE3DED6DB61D4C1338CF9D3699B28A72539B5CDD760DA7AED16454D993E7CC4A9C25077079ED766DC7C9B489A27F702FE2DED6D05EDAFDB472259DD6FFF00E503F58443DC17D587D7CAF6F5D3AC4F95910E54028B59C6FBB6BCACFA73844F4A42430828E6512030274844510C21084210841CF38453AEA132A600A482E0DD9F721CF4689CA948A8A55A161D409651D406D05C7BEAE7D4445AE2E14A171709205C7706E0EC7D2D15A9526621D2351AF43A7B1D0DBF58B45109B864ECE0660492120E9C88B11F460CF72F112A32C87C34B71C53D6E5A94417A58FFF000A824048371D527A01D22CF3E532F338B282B29B3826E357BB16B375B455E2B33FDD505053DD852487203380410FE7BF26F2386BF177C85CBEC4395A8CE49C9B92A4662E1B9C96A2529D12C958C48E4E25C52E9AE25B5B4A5BED1956CAE60A8A525C00B63588B57132A91183CFC61494CA14F295E0258928049676B6960E7918D51ED7702A4C350B32CA0A94092430209F223F73A18CCBF8117098BE1EB84F94C6B5DA6B5298AB3A5DA6E289A57C1AE5A718C34DCBBEF5165398EA9C5143A8A895AAC9093C949091B11F3C5F1D5DB92389311C4787281264FE1A64D97DFA26E742CA0A905486B04ADB30E82E7431D19C3B822EA0AA7998122E48208200D2C7524F2EA3A4678F65A52EA762A2B2E83D54EB842D4BED61706C37B0223C55C4EAEA4544EA79D30CD698A5E7279936D0F3E7B79465C0A913D74A2E5091E21A102DA5EF7E6FAFA22D0A566E822AD12C801C81E9E7AE9102904DCFA5A2189D11E908421081DC11EB112139D694870E407173025813C83C4A40D9449DB6FC37DF68A9130A14A94A199992FD6FAE8352036DBDA384AB307D2FF7E514DC0B582424AD2CADA3A41B6BE6150D20D8D8A74DC937EBD22EFC332BBDC6692982331A89C25EA7C374804B6A0BD874778A2AAA8124124155980BF524160FBDB4B5EF1A8FFF00110672BF8DF38720F85AA34FDE469B3CEE3BC54969D0B614E3AEC8B149919993410ABCB1959E2B5ADCD2E07800846824FD0EFC0BF03A384B82F887179ECB562926969E4132D94833D13F3290AD42A5B249DC66171BE5BD9AE1A78931EA6949053DCCE49510C4594080DC8F37BB6F78C65C832DC9C84853194A52CB689C9C6DB426C2588F864ADBB5FEEB87484EC9D3A08DC9DB6B254A9D453AA1532699B294A2528D59DFCF9DF5672FB47B3DD9570B9C2B8729A61502D25076D426DA752FA6BB6F1CA8C4EBE466AD35215E0752B233EA438E6C3E5611D954539536A4CA50600817D1B671CB5E7B75308A804100A6C0871EB15D3D1926AD2E0B28DC75BC23989508421084210844D4CF12D3948724BFA1DFFB037894B9256A4CC76CAC1BD5F9F51F3F288117FC41FC0DE29168EF0E70A6706CDA5CB0EB7D4FB454A67776026CD726C49FAB6DF7AC44EEB0BF4036F523F41F8C4EEE8A65AC380C82DE7D58DF6FD3468A49B3C4C761ADB930F6D62D67890989A9398CB5AB34B095C8E2391082904281332C1242B5796F6B74BEDE9D33CE0F989A8E13C4B0D98970B454F8F98C8CCEFB75FF003E7EFC55C95CBAE42D25FF00210C2E439B6A2FA6C402DA6B1B9360D9933F8570E4F120999A3C83C6DD8AE5D048BDFCC41EFD0FA0B5A3C59EDF28453F1157C94973DFCD503ADB39716FA6D1D21C3C4AF0C4254480E05EC74D03E9D2E6FF003EDAB3700FCBF21B6DF2FD3DEF1D038656A64266D32E5E74CD4A803A10A37EACCE7FB3467F86D32655266CD99C396D1CB0F5DD859EF6B44AB56B01247416F2F537F4F43D6DEE6286995F86AA42D57CAABEFA38D06BD7C85F9DBC5319150A9AA5829727297D09E96623A38DDE3510CD4C7A9C0587A7279C2815C7241F97A7B28365AE69C42C3480804A94B256DEC900EE9B1DC47D14601864C5A054CF7082B0949525C212E0E625C0CA01751E578D90EDBBB56A0C2E8EA24AA72065429BC61983DC0B7A46D09E093C1156B872C9B9FCDFC774F5C8E69E752A5EA3501509632F3D49C3C194BB212CEB6EFDAB6A7BE3669D054405256921201B9F353E363B6FA71495582D05524C9A797329CA10A1942925495120382490CFAB011E5A719E372B89F18995F28E748252E03D8924DDF500FA3D8C673396038B5A084B4B71C521BB58A01081B8B9EA4122DEFE82FE2A4BC4E6D4D7D4CE512A1354B984E61AA89720DBA6DC858463F4F28A05F99670C0FD4BDBC85EC4454B6E0FCC7E9FED168CFDFD52C936F11B7276F99F3FD62E487CA3E5E5F7F28451AB53E67EB114238842108421084210F3892A4DCB24B797DDA222E08B758AE91318A46A9B007A0F6EA7CC9884A1C3652C3A18A6E38A6C17EE12E320B8D85DB4EB48BA6FED7B77EBD2E778C9F01C6D7846274B5F2CF8E9A6A569209242828283105DCF41122A907B898424B849D0176D36DF97ED1A9878C9657CCF09FC66E4771B387DB729F8131BD54610CC45368E572A7256624DE70CEBA9B25B4CECBD542190E24EB2CB96240207D30FFA79F6B52789F8729F0FAB9EA5CC4C8945282B0425811354410E424049D587B43867153495D2C394B2C06B3862C36E6E35DF9DE2F5E8F5393ABD164AB72251FCBA6E42527DB710A0A6912F36D95B2B2B1B695E95E93DF4ABD23D4E5624292A92990AF04C50622E4ED76E5AB5ECFA068DDCE0AC6115987CB04E6F0071625DACE0FB9D5EDD23E99BA56A42B65A2DA927A8BDED71EF68C9534B925A2A4243D407246FB8FAF58BFCE94997314B01B33663EA59FCFF00B42388970842108421084210842108422827A5E68EA3F527E86D1CA67041C84FE60F60FD19F6B3C4C9246B55AE10852D67B250917528FA048DC9ED1552D795236663BE8799B0B3070D6EAF15669730700105CF202CE3C88DBCE283E5B6D21C0B0A0A5349D8DFCCF6AE50BF62BD0BD3EA126DD22D7555012B3999B5049D03B1B1F968DA1D5C58F11A99547267289014942882580F0DCB3F30FA6CDA5E31278D30A57BC41BC4032DF863C2E5E98CA0C9D9E6EBB98D55944AA669CF4C3D392A99E727261043082E1910994E66BBA4CC017DEDAB3F123DABD2F06707D723F129939E54E972867C8A5CCC873100BE64CB1942D9AEA4871BE96F693C44AC527CD94951584AC8201CCC0120025FAF237D2373EA1D029587A934FC3B45A7A69745A24A334BA44925096912B4F92406A5594A4252025B6D21205ADDEC9B6DF2C1DBCF1EAF1CE29C42A5330AD1326CE20E6FEA516B8B7CBDDC4621C373552A5906C140B06B97DF5B79B5BD447DE536842414A813B020107B1DCD8FB0F6FC493AB55134CE9EB986F9AFCD89BB3E8D72C390BC5FD2826A5537FA92475D8FB3066FED1244A8AA84210842108422649B4D437F50810E08E61A236F2DFDEDF97A44E969CD5A124FF3EED72EDD3FCB69BC219367D39FBEBA79791EAD514AB21006C1016FB84F72D849426FDB51B81D7A7A88EE3ECCF87535DC5986787313532F51AF893CB771A7BB5A2DD549330A85DD49661B59AFA3EBF7A0D0178CCC66BCE4F124CF9C5734F7C5C860899461FA6BC17CC976D72B313AA6996D77290B5952AC91B929BDA3E943B21C24F0EF661C394C94A659AA136A96C194A42A5538944976B10B6B6E6363BE19B877F1F8D575414B8926581E1704BADF4E6C1EEDB738F8081A753C9DCAF96D04F5296DC0B2E9B0EC0A51ABB0B88CBAAA715055F6201D7A5F97405F6EB1EC9707524B95824A90C3FED2037A680E9B39B6C3D2A463D509CC5CB59FC8B74FF3FAC433650A3A852D80014D676D776D5C6BBF43A9440341E42271567257FD57F784731C42108421084211297A8F2FD4C463F22BCFF684469FCA3D7EA629D7A8F2FD4C22B121F3067F09B7B45245AF7148162818450DA0971389A9810026EA3CD7D1CBB773AF96AD236DC11DA3B038469D12B08A82A0C324F5124B0CB903EACC367E8DAB468A7C57292BA99697B84A188D3771F3B746DDC1DC5F2E99533807062177E62B0D525D5A542CA0A5CAA09B8EA3A478AFF1013E5CCE2DAF45AD366BB1B0F196176B5FD341D35FF0305386A19C7892400D6605EFCB6B6C3CE3B99047516BC6B52D3DD4F2A018105B737D48D07E82D68CDB0EAA269F2A9D57B6D61BF2E9F7686FDBAF6F9C48D66B820B904EECFEDC989EBD6229ABCF99CF436D80F26FDCED1808F0AAF0FF00C55C6067052389ECF1A04ED3B24F2F2A7295BC19846A2CACFF00AB8D31D44E48B6FA1E4843B2F31516DD6E60A5B72EC102D78F693E243B75C3BB30E1A9FC3B8654A1788D4D22915B528983F86A99DE217224105CA4CB090B5784E6252DE073A9FDAD71C625C498BD4C81397DDF7AA09439D1DC1234B29FD9FCB751A5C94BD36974EA6CA30CCB49C84A372B26CB2004372AD957251600005B49E5F4D82001B08F01FB5EE32C4389EA2A27D44E5CC44E9EA5F89449295289DC9D1CF9F2D0C60982514DA7A7509E5E62A6155DC9661637BBEE39302F1CF26E49F58EA8C1E84AE92A27B0052950049D6CE5BEC6ACD17A12C06BE97666DDFAC4CAFBA9EFEFF4E9FBF48C7652FBB9AA503A15021EE799BF5BDC7AC44A5652CCF67D7FB4491C12E49E65E22842108421084210894A6F7B123EBB44C4A4100DFF004D7CA1104ABB1EBD8DFEBD7F4B402B2D8EC751E7088A9C2871B5E9E614292A083BEB2157D3DFADBBEDEB1365679F311293AAC8487BDC9034B3F417BFAC70B47792E625C070CFC9DFEDB7F91C7F789AF0B948E2BF843CC8CAF97944D4711B346A8E27C3932E361D9866BF48957661A44A020A83B32B32ED8D27512D0EB1E9AFC0EF6A957C1FC5B87613DF94A0D4C84141514A48CE014A838F09DC369678C22A54AA3AC490420858CA5CDC38D6CEEEFA90DD63017E1BB9C3378DF247FD0B889D73FD5F9433731836BD273AA2671D96A71D326F4C2576585051984DD40D80B031F4DFC3759FEF583E1F5E14266794898562E0F8505C5FA9D431F48DA3ECC71952A44A4297A849673CB467371F2772FB6431297D3A79E4294A69B5158E856756B4FCD1E51F5F717EDF97342E8A9A58FE4431BE9A6CD6D39DFA1B46C0AA689A84286E1FF60D7B5ED789E25C4B841C6E7CBAC2108421084210842108422927A5D614FA59BCC738A5593F8848D4302C35D7F6DB7D220AD2015292A58482A0DA05CB8A4EE1B23B85DAC477110AD4132F523C21DB5008FBB383190CD5F754C565DBBB3A5F627F563EC1CC5A671B3C43C8F0F19295DAD34B44E62EC4F2EAA1E0CA530A1F13313F526D4DF39B4EEA2BA7AC327CA094FC40E9717C271CACFC3D354CE52F2F752662CB9032E51F4E5A5FCA35E78E7890D3A6A519F2E64AC0F16F71F4DBEA22F9FC1338327787DC80566BE60C9B9399C19EEE9C49896A5506FF00F5D44912D97E5A454B7017521C5CF3BF78A2E5AD85C08F9E9FF501EDDAB958B546114552A4C890B5489684A880C0A8198B0090662C0198821D83C6AC842ABA7D4CC582A2A98545F525C161CD9EFB8B98CD9A15A9A64A9252E7291CE04DC87ADF69D86DABA6D1E42621366E2F4D32B66A8AC95924B9B9625FEAFCFE952995F842325B448036F32DEFFA5A268C31ACFD5BF7FD22ED4CB52CA546FA8274D8B5B6F9EEF7847115D0842108421087489B203CE962F750D3586B004690013604FE837FEDF8DB68A8929CB5E010CCB4FA31737FBF23A44A9C7282E40607E42DA6FAF5D7778E0D59458A7CF4CA1CD21320EA7D2CF0438A17F53BA4EE36F5BC6D276252E5CCE2DC252A00BD4C92188BF8D04EC7F6DA24C8489A5208198A8BBEC39F9F98FA88FCE5B0D569CC479DDC446259D3CD9BABE624FAD6A26E796D4D4DA5BDEF73D556EDE9EB1F4774129345C0FC252C32569C2E4A54058384825FCC11FAB5A374FE1629E5CB9B8B4D2920E6490FFF00E673AE875243EDE9EC65C7145166EC92773BED7DCF6FC77F6116A54C7B383B81B7CB7FB31E9BF0857E7948927602DF4F7663D793C548A399737BBBF41FE5F56E9A45FF001D941092B4B30662D72ECC7AEF7F43088348B64824C996497748BF384226C2108421084211297A8F2FD4C46E04B5396BFA6DBBC2234FE51F7BC53AEE43721F5308AD46A7CBF5114330E542CF204DFA45B7E774A3F8AB15E4EE0C934972A98971A25C6A545CABE1255FA7096361BE9BBEF5BBDEFEF19AD0552A8B85F14A963964D2543EC33A903207E658EB6B7988F3B3E27311EFB134CB2B21D4904022E013B74275B7B878DC870FCA894A6D324D07ECE56424D86876421B65294A3BD80B1DB63D7B4785BDB9622B9DC675E12A71DE4C26F727BC3AE9F521E3ADB8765A66612826E4B5F46B06BF93DBFB47DB73B7D7FB474E544C4CC4CB601DB5DDBF4EA09F48C964CBEE29CAF51A3DC5DF9FAB86E514E24CA0EBFBF3FD2212B706DA8E7CFD2325781706E1CCBDC3F46C2783A912587A8187E511214AA653586E565A4A5D0D86CA1A69A09424A8005CD22CA56A3D0C639DB0F6BD8A717625513313C4D75A55314D9D6A55CA891AA94C1DDDFE7B68ECE94BAAA9335473AD4B2EB2EEE7FB9B39BDF6D3BD21094202136000205BA00493B7B5C93F324F78D6AC4B129B5CBBAC9960061D43EFBBD9FA003577BBC84AD08CAB249B6AFF00AC4FD22965D6D44A96654B985282194012C793DF5F3F389F0F6EDE91486E49DC973D4C70C0EA01F4842398421084210842108472091A130880481B811C4220B52920AD3BAD035209DECA1B823AF422F7ED159875AAE49019960DAD1C1B850E6086E6E343D0C715D9495130D9754E34DB8C292DA59074B4B55C95213701249209F5EE768EEEECDB1D9F81F17D155C89E64AD35129614924310A4BDC37986FD62C988534B989CEA402522CA3724B6B7F3B9DB511A72E78E049DE067C57AB54B0CB749C9EE2B15F174C4348F85A3D2EB9539B71993FB01F6085B4A75D5CC292A04731074F98C7D497C237698788F8430DA4C42AC54CEA7912E58CEABA92B48C818A8F892412A2362036B190F02635328B129728CF5265674F85DDAF76BB071A1BDDB9B464F12E05A5294DC36948E56F70B695BA1E57ABAE804BA77BD931BD48CE9F102A0850F0F21A6876707CF5BDA37530AAC978861F2152085282015A8751EAC6C1B73D0E9344CCCA2CEA25B99FB7F58E664B9D98F8940B8D5FE9987DD8738433A9FF003126C2E74E5AE9E67AC56D2D8B2CE81AE5EFCBA9FD7D1D15892E073163D4B5FD3E711AC82A24583BB337A11F77844510C2108421084227F2A51AD7B2756907BDEDDBD7E5F3BF68A5AFAD91229172B20EFD45C2B522C2FF002DAFCA38FC14E9AA13C12109074B7BED6B6C74F6E24FCFA28928F55A69D6A569B4F6953B3B3CF381A4CB4AB092E3CE95A8F4420151E9FE2D58555A65226D456B2E5A412CA701989DF4605B4F90618FF117114AA2A499294B01484900067B0B8D6F7EAFAF58C5870B795359F13DE3ACE2EAEC8CCBBC2D70FF003AB7E48CC053F47AB622726C2D99032CB0259CF8A4D36D3977095252C6A49B46897C5676E143C1F846232A82BC5356D4C99A8972D2B0932A46523BD5328399C49082D6EED5ABC69BF1BE2F515D5EA4CA9A4CBCECACBB927477361B8DC7946E2D44956E9F288A749A12C4936CB4C265DA1A19E530928693A00B04A53B253616FCE3E69BB56E309FC598A621598AD5AAB661A99CA44C9AA73F98B0B956DA3683517734D229A4A5083DD8CD95DC8B8767F7611DA6EA3BA892A26EA27A93EA635B2A2AA62153244998A448CDF901203DECDA35FDC9F49A644A2CE816D180B422DF11265A505D21BD9BD035A1088E10842108421089F4ADF8894E1C670E34E708748A99A526BC14DC7789D39BD9BE512A6876E773E65ACFEF1F22B6426993E4B61C6D328F2D4D1170B7396BF314DAC49000FA7B08D9BEC1D4A1C6384E73635528E52DB2D2CFB38E4CF77722F13289290B0E900B827C81D1ACCE3DACE1C47E711976D191CD2CFF00A3CC20375092CC19D49D40071083393C426FE801DAC3E5E83E9196B13B82384A64A0DDE504A5E9B14A3A93B6BEFAC6F7FC294BA69871B0B969CC3BB60A6DB3E9A3EA6E35F28F7E52CF90051D3A74903A155875F736EBBF78C6EE94DEE79F2FDCBFD79078F40B87A9A64B98952414A2C459835D98F2D3AF48453CC98A50092A2E3DB910D68CC6BD426490959248E7B103463EBB7D211126C963AE9E57FDADE516B94C25A43378436CD77B7DEF08E623842108421084221EE56A0A98F64D9B61E7EFFE4C43303CB3D0A8FC87DFCA264A50A365A8A4589B8EB71D07BDFA44B9753290A12D4D98170FBEEDF767DE2A70B97DEAFF008802824BDCDADB6FD77B9F489F415DC200B01D48B5CFE67F3F5ED19261D48AAC9D2B2273256B4A4DB5048D6C6DE7C9DF48B6F1654D2D150D4A90D2D48913141ACCC937E7D49372EFB4752E13F06CD67C71F78224512E66E9595D4F355AAB83ED25645C919A694B4366DA50A7801ABA151685FEE889BDB26274DC19C115C3BD4D32AB0494CB95A674CA44D338962C582E5F4BE8C03F933DA763231FC6EA52B589CB953E6049D48F17840F624B1D985E36D169B665F4A65C290D048E528F5522D64AB6BDC11D06E01FAC783FDA46209C5F892AAAA511312B5CC04A6EFE2B3FB9B45470952CE974C1131CA2C4077000E846A4124ECC20493D493F38C49669D144996B4033C29DEC0E971E96D75F568C927CE42A61903401C87DCEAE3AF3E761108B7A662125C24FCBF40225E54F21ED195F4B0194F9544DAC06A24AAC361756E49E97277BDCF78D40A933EA27296B249517724971D2D7EBD59DA34B68E50482A5067B6F7B33BBBBD8388AE8FBBF58A59B2C4B2066CCFF00DBF7F94561001B1789A254710842108421084210842108421084210DBB8B8EE3D47A44FA698254E42D5A24BF4B11F7F281D0ED6D794012140EA06C7CA08BDBE5BFCAFF00DA328A1AE5C9AD97572CFE5585120960CD705B6D472DA29EA650992169087394B293D41DBFC6BE7182CF1DFE1BA733638617B3B707D352EE3BC84A88C5527312C926A535245B4BF3F2A852105C976E5853D8534E365C254F39E54E9055ED07C0BF6C424E3384E115557DD49A85CAA65AD4B3FC2CE40EF402D9B28D03877D4461D4D3A6D0D726600A395692002CE017617771E76EB68B5EE1633969F9D59138171F22650F4E54645A90AA34DACBAECAD6A4D96454A5A6490952032A71A0DA943CF75929469DFE85703C4E562783D0CE42B32FBA057CC1CA9D6E5DFF005DDA371BB28C7054D1CF44E5B8CA9CAF76E4039B33DFADF668B8C01614E2169014937480490A6B7FB4B902DFD3B0046E7CD1746E7E9D3FBFDF9F702A64B9E1810C1807372FCAF7D39FBEC8453A93DDE8E4E97EB7F6FBB6908AC941903ADFF61E8D1182E01E61E11321084210842108896D6E84357437AC3CEB2E4CACB5284CB212E4C071D407168286F42B669448FBB73B463D5B23BEAE4052990C1C1660C777FBBB795CCE234D4784CE131694AC956A766DDC5BD3F58C5A71E79B18CF30B10E13E0E720C4DD7334735DF91A7D6514A79C43141A2D466554F53130F4B85AC3CF813066D2A6D0897974CBB816E29D525BEAFED638E309E0CC02B26CFAB44844992B5AD49290B510939509B8754C6200FCA08B90D1A71DA37144C5554E972A61233166516D4B13E5EB7F71B2F702FC20607E0E787CC2994186996D7504B0D56B1BD610D36CBF5DC5936C3226261C436562CD96B4241715A49276D463E69FE2DBB72ACE2BC72BD326BD739014A952C09855965A54A09426E5807366677E91D4F4895D72BBC98147C40B92FA8724B976766717B8E422F219934B26E14543AD8A401FA98F37710C5A7D42D7994ACCA249B960FD7578C8C0603C9A39A4DCF4B6D61162BDDC924926FD60030FAF53CE211CB866DDDFD1BFBC7308E2108421084210813604FA0BC47295966215C943E767F477812C09E5135C045CF404FE62DE9D444F90AEF2B90543550373A653FDAFEFB440F99C37AB3B6BD7969D5F68A2EB48986B4BAA6D2C2DA7DB98D44DD0909BA5562083AF5286E401A7AEE63613B25C565D0715E16A2A0922A653DC6CB4DF5B6E3CC126E625A96A9398005D2C42AC013BA497B00C1CDD9C6BA47E7B79D181E632A38F0E26B08D41025CD5316B957A33253CB33326E3D39A5CD3601215736292A1707DEFF48DC058A48E20ECEF8566CA751914269E692036794994A2DCC34CD0B1E40C6DA7C30F12A68312C4644C98009CA94C093A12B1A1B91AD8EBECFF0057ECC2580959517105C7469B729D16B35B1370756EA363B0B88E3104892ACBBDF4274BF51A6C5CBDC748F57786172EA30E97516FFB60E9A0B6ACFF00ABDDDB589E2D929A61629D03B6B7F4DF58A99930CD9C65BE6D773ABB173F7ED08A8D22023296E56F6B421084210842108440F436F48AB97325A299695119944B02402CC7EBFB6B11E42A412CE1F4D8EDABEDFB36B14CAC124B89B348BADC55F70840BA881B6E05F62403D2E3AC634AA69F36A9D092C556376D7FBBFCA394D40A294B5964B026E40B00FB5EFBB74DB4F38CD6C7F2F80F09CC55CA4AAA01A7D9929242C844E549B405A2552E8BB810F07590D3A1B5152CBA9D00201576F70AC812C4B33328292082A19420002E4B5920DC9B30B9208BEB076B7DA2C9C3E9EB64F7E12552A6A00CDB949660FA9E8C766DA32E5E117C303D94D94F58CE0C6D4E98463ECDB71B9853F329297E9F2812E38A95438ABB8E36FF00C5A752D41B23942C937DB49BE313B4B4621493B0FC32A8CC954C1725012ACB701944A42884A94D7D49000E51E7660A9A8C5B17AA9D312A226542D6E5CB82A7DEEDD47B46608795B61BB11C9650CEEA2AFB808D89EDBEDFDFAC795D4733BEA89F327A89CD99409F76EBD7AF3B4776D2A25D0D2A5360A09B82C58B338E7C9F7E42CD1B0B5EFBDFA7F78B7559CD3D65F761E4098B5A65AD55467310823AB3BF5F23ED108A68AD8CB446A04DA82A709B0E9ADB6FEEE5FA469A29D23C2186EDF2FF003E5787D6FF008FF70229CA94ABA89F53FB130412439D5FA7E908E223842108421084210842108421084210874EBD3BC22098F94E5D7F4895685DC2C03A46FD7DF6FF001D37FA08BEE1B324A69E609AA00876245F4D46BA5F97D23994B4776CA201637201F6DBD2D1D4B1760EA4E37C358A309D6E525EA14DC594A7E95352CFA02E5C4B969E439CF6D6929597BE200FBAAD91BDB6BED17C3671B49C178C2833D4AA5A13532B7292C16346D7AB9EB18D55D2854F0B480466D53BF5F2FBE91A6CF0BF2B53E0F78CCCFBE09B190E4D26A9587B1860371F0A0CFC1BB373AD3CED3FCAA484BFCC94BA11A5C1CB4EB40B08FAAFF87CE33A3E27E0FA2A8935499F964094A577816BEF25206652C139815661E7721D8C770767989A6915369D331944A583B1B92C3605B70010CC232D4D21D265D6A515699275A716374A96DAD91A491717373626C15625254018D874CC428120D87DDA36530B33E6484CD5B94B03989B333EBD1F7B93B0BC4F1CE649DFE47F68BD2549AA5044A7528580B33BEF7B69AC22E32D0AC89B6C371FBC44A4141C8AD5363E908856B08B11A6BD3D9E388136EB12CD4203B916D6FF00DA382424392C39F9C46C6C0F631C0A9964B0209F33FB40282AE92E39889524293A93BA6FA49B1001F7BDADEC4EC6E2C77113173512D1DE28B27AEB6DDBEFD238529290E48116ADC5FF0012742E1AF29AAB8A670B351C4D32448612C34E1E63B56ACCDD98972CCB2438A765D9794CAAA20367992C5286D2FA816C61BC4588FE0A966E2692934F292A4A979C27C4C6C4A88000704924243B92D78E9EED0389FF00013BF0D2E690954A0A64BD9C1B9018936D399D768F77F05BE0731261192C47C6A67F48BF3F9E399EB7AA785E8B536D2F3F8530FADB4B92936DADD2B6587EB2A79D9795432BD6D7F2ED4EF242904F873F1C5F11F49514F5D826098A899512FBE96A44A98B75AC3A4BA8B16B3253A02090D98BEAE63552AAEAC5AD799492336627C24927C29BBB8675386F10626E6360E6E518974A3E19B75284A532ED36E2829C6DC04AD538E1D4429254BB0B2D4BB20F9378F0B313C5B12C4B119F57892D644C3317996B511E251CA082E0285EC2C5C39378AFC384B44ACA03314957E51993BCB497724F3206A09B3373631559904924A497D4E5FD58C57C229A6F77A219DCBB0FB1EC6108930842108421084210881E87E46394EA3CC7D638502410358893F6647537BF43B8B6FF005F6F5899295DDD4A56A0C124BFB9DADCE21969297CD7F26BDCF5B7BDA25E59710B4292D212B43683AF51D7A54B2A26C93D01036EBF3BC661C33894CA7C7E86A65A94254A9C852D4EC0242817B31275EB6893529510AC84AB3289E89748013FA82CEF6D2F1A6B78F4E4F5432678AECAAE2464248B387F33A48E1DA9CDB08024E5EAD479965D5B530536D2EBC8AAA4A4A93A5C083655D26DF463F06BC694BC6BC095584D1554BA89983A69E6CC964B2A5AA6CB5266972D66948B03E4EED19FF64D89CEC1F8864F7AA3284E988487536665161E5767B1B69162ACBACBAD735AD2E2668B732CAD04292595A54A2B045C58DC5B7055B9403636EF1C752D5464A1CAD24860E030B1198116F76DC73F69FB37C4454F0D485A5798AE44B3A83FCBBDEE3AFEE62AC5253D1CD949EF6686494B0653BFB1DDADF5074CA2814A35AA330784921C860CEEF7F21FDDA110ACA41241B5B5F61FA3F58AEA85CB4CD580A0CE75F3308862505A54582813C84204B6B13532D4BFCA1FE5F7F7C8C2210A49B3FD626FE1677F4FCC42228817266203A936DEE0B79C06EA427BAC94A7DC8173BF4D81BEE445B278AA5D54B972925482DCB9BDB7B06F5EB12D388514950A69B31A7AEE9433F84B3B97B6FC8C70EA33B4E94A7BD3B3936DCAC9212EF3E69E0B4B0D36C80A7D4B5D88D2DA3CC40B950D9214768CF705C3A5CF5A25AD2F394058A7F5235F3F326F6C038FF8BB09E19C36754621569908085104EAD94B69EAED6717678E1F07390D39C6FF0010CD57EACE25192194F3B25509EA729414D56A724DF71F94A7A5A04F3DC714CB85D52829A2DBED02E120A5359C678A2383B87F145CE4F753E7D1CE9689A09265A0A09CA948DE6BB1558A02410F1E5776B1DA0C8E29C58CAC12B7F148138E6092012A2AD4936F0D980B12E368DACA4A5A56954DA752A4E55A94A7CBC9A65A9B4E603653225B4A5082A435A90D92128B5CA774EFDE3C52E30E22ACC6B13C54E26668926AA70415A54A74951219FA3EB6BBEB17CE11A1934B265CD9B91331684A95A13988E7A83B5AFA6FAF2D9E6165AE60B2D09E5AC92012B46CA3D771B8DF707B131D23882108A82287C4093F96C6E77FCBAF95B9C5F3129B30CE0658796E1CA4E9772587CF7D468F135FCC5237B024900D86E075B5BBFAF689D4F854F54B33E6CB16198EE48DF98D4F4BE9D6E5F8DC3D34494F789EFDC166255A1B3EA4B6E6C1BD627D0AB6AB1B7AFF00B753D228D53A91337BB09BBB5922C4EDA8E607BF28932A626636453967DC1FBF27D632CD1A451A75084210842108421084210842108421084210842D7DBD76FC606C09E51C2BF29F2310D5BF2EF7F63EBE87F5F43BF78BB61D2D33654E05883D5B401B5DDFF4EB14CB43A416005EED66BBD86BA6FD622B6961B65B6C9F8879C992D01F7B4212D6C091BEEAE97B13EA378CA383ABD38263922A9F2844D45C69E151209F3DF901D628262194AB5C0B3960E5F7D187B7D6358DF1DDC86AE60BC4F93BC79E57D3172D5DCB4AB9A463E725501B54DD26A8E4ACC21D9D527675A964D32600E6936E71B0DCC7D097C01F6CB22BF0EC470A5D4A14EAA70119866CE91312026F6D4B80C15BDC089F86E2BFED788531272E755C8274047DFB69631EA396998341CD3C038771DE169B6D549C4F234CAB34C0375B4C392CB5A257A1D2B96E7044C0077529172A22E3D9AE1D992B12A04D424A559C036B9BB1F95DC9E76B46E7706E292B12C36520AC2894246CE430049D2F6D1B7F28EF315E6481332021B301A5BD3A731BEDB465F2650A39D99AC4920FECDD08DEDF545CC4C094A5214C121B293AFAECDA86B741098BEF16A5732FF7F584524CF1153117BF4DA20881FEE3F5114736966CE494CA4F8CB161B804126D7FDFDE25CD495232B3B90EFD086B6F7D3A889D5FFB60FA6AFEFEC7D3FD8C5D6824D0CA1DD541489C468AD41FF222BA969E58944AAD6246FE977BB373E7B474ACC1C7B8672DB0657317E2DAA3146A4D0255CACCEB8FA8A135497936B9A65A5AC0DD6AE496AC020951B5FBC635C5153FEDB295349690DCCF89CD983172458003CA3AD38C78965E12898D312E87736BA6D6661ADF5DC13B98B1AE04385AC6FE24DC4F4BF1539EF439A94E1AB2C2B68395586670E993C46FCA3A8984CF4C4A2545A9861D99E520A9FD4086D4922C2D1E687C58FC51E19C1986CFE17C3ABBFEA2AE9E62AA929210253A549125ECA135D24CC6190A549F11B81ABDC47C49FEF95A6785B840284DDC177625ACCFA1D45CB6B1B74D3A4E5694D49D2A9F2ED53E4241932129292ACA199532928847C3B4D25B4A5004BEB51B048FBF78F9CDED538E67F14F1055D58529626CD5A9DC9FCCA537305B99FA308C6C4AEF941C056C76F23E97BB5F478FAA5606DDFE5FF1DBA474C6293E729294A828279836EAF7D9F95B66B98BBC8A6EED1CCEAFFA00DA0E4D7BEE584D16289F0842108421084210842108423905883C883ED08409724DEE77B98452712E9E9D2C6DBF61D00F7FF6B45EB05599738298366BF26DDED77D8B9EBA3873F9FB0FD1A31DDE267C204A7197C2A63CCB6128DAF1652649EC53822A6520CCC8E21A5CBBA65589776C56D09D53890E041D2B2CA35821223D16F83CEDDC7657C512E8A69CD498C54D3A6AA4953266CA4A94952482406F19B10CD160C4F12AFC2EBE86A6973012D4E4A1C310525C91E5ABB3DE34A4CA5AB54E9ADD7F2BF1AC94C51B1D60C9D4536A3233A0A6652DD08BD2C89720951E621530BF880482496F5151008F77E4D0E17C43C37FEFB864D975027C81554D312E153254D4674299412AB81A1D8691EA07C3376CB4D88D1D1E175F5094CCC92A5A90B5B97218EA4805D9CECEEE58C7B0C74D61F5F892B1799455695A64216A4877D012036D60F7200F3DF7CB119085D2A2B70F2159D216E82082F7DB5F2D356636846473901331413A662C072E9D3A6D1229A42A6CA4296019840CEE40BFDEBD6112B2AB91F689A640478B2A411A31FBE9AF9EA211C290588367B3FF00831455556B91297DD139810183BD9B421EEFAF4B1BC225143071B3EB7B0D35773CDE20A2AAAF9E74985C0737D2DCCB6FE606A39225952DED7F33FA388AF9A8AA2851567B6CFEA4B02DCEFE770D1337AD2E21D6DB0B0D2AEE29EF2CB21B558294A51F28504EABFA0B45E30854B4CF96A9D2C1255F9887013B925886D5F76E767B6621270FA1C32A71AAB98844D9095105643B24022E5F57B5F5E8C63CE72FF2831FF1D39F546E1AF2A915046156EA32CFE3AAEC9179AA6C8539B750ED450A9B97F373D72C1619654034EB83438AD37233CE34E3AE11ECFF00860E3558BA7A7A9EE262A982D28CF31494F854125C99614F99475B84B9063CB5F88EEDA2462CBABC1A9A7A660495CA2016D1C063CEE188D2DE719B2CC1F054CF6E13E992B98BC0867A54DCABD229ADD42AB97F8955332D2D5DA84A239CEB68937587B0FCEA0A8680671E0A21442AC0DA34C387FE2AF8278FF18A9C0B8A853CDA31366265CFCED36582A09F0824226060084AC9483A6A634164E2988D056AEAA485A42965434CA6FA16248FAB36B1E5B817C4A330B2C310BD96FC6B64E57B2B71207112F318C29B8704961FA8104B456D4D4B34CB213A81714B6DB03CC08247495C5FD8AF0771B61D3712E08AAC3F134CF54D50A692B952F1090C017994EA282A01F59066070DC9FB4F03ED3EAC2E5C9A8CC8203397297B3B2AEC5F57637DA32BB80F31703E6361C97C4382715E1DC5524FCAB4E308909C6E6265964A6E96E605814CC3608E6A49D4091F38D22E30F87AE2AC126CDA9934D53DDA4956421492C1C8053F9800016B01ECD1DEB81F14C8AE952CCD9A9399237075D5FADFAEDADA3B8E9496D971A7C6879056B95BF992B007986DB04824582BBDF7EB1D4758713C03FE9EBE926A43E425692DA9704E86ED7D1F4D233DA09785D52DD2B9654012580D0B1B7936EDA5A25D5A4137500373A0E95586E6C6E2C76D8DC58D8DC4712F87518B844DA1428CF9846542527F317374E8FCC9B1BEBBD5D65561D874951CF2EDA170DBF3772790B0763D32D11E7D469B42108421084210842108421084210842108421111B11F3889092B5040D54587D986B14EDA9C161736DF6DEFBF53EDFAFCA2B25D42A90A917D9D835F6B5BE4F7DC98100A43E9703A01B8E4D7FB789DE5594829242DBBE9503E64DC0074AAFA85EC01B5AF6DFA4402A26AD59905414F60EDBEF71CBD229168046815E7707CF359C5B5B8F68F15CF7C9AC2F9F99319939518C65513944C6186E7E9E65D4D21C519F71A58935B214094BE85A8E871165A01558D8AAFB9FF099DADD5702713A29D550B962AEA656519D4904A56C5218B87CC46BA167B458713A25CC99267A411DC92480D616F16C1836B7E9D351BE01B10E21C84CCFCD4E05B359D5338A32DAB1547F08A674ABE2A7E41A9D5CB4EA25661D1AD72EEA8492E55B42B969690BE5A529B88FAB0EC2B8E2571270BD2E212EC9AA912E78961B2CA529214A96350C876B38362F1DBFD9A7189A59B268E64C7282941753BB167673D4DEDA3EF1961654EB92AB99290801DE5B92CA1F68122E09077576EB7DEF1DC526B1332B169170547C2198DCE8DD0F4B6DCF6B65D50ADA54CC43789292082E74727FB5F52C778AA34FF45F41DD3A892AD27EEEA277BDAD7F78B81980AC8666B11B803A8616B5A2343E50E19801E6D63ADFDE11390339617B121ACFEACCFCF7E71142C4824148D0953B655ACAE502E1458EC4B813A123D488BBE1D369A8E78A8A864CB0820E6B80A2922DADEFCDB4E71C804E9FAF9ED1F231055E9B46A33F5CAB4DB7214490617539FA8BCF2586E99C8056A4CD28A9376FECEFA141492955883731D5DC49555E9C5975D499C5225454E9242425CBBE836D9F48C5F1EE2497854A58EF02084ABC4766041F97CCEF18B8C3383B333C5B788890CAFC0CB9AA470BB96B5043F8CB14239B232F88912132A999F9365F486D736CBC1B534191A90B4ACA4A6C483AA5F129F11D85F0670BD4C9FC4A25E26890B12A5E609989535A6AAF99241F14B7F166014C12413AA9C6FC4F331754D972E6382A21C10C45F7DDDFC8731B6DFF0094796984327F2F30A65AE04A54A5270B613A4CB52A9B2D2928C49A1F44BA945734F34CB6D85BCEBEA7097560ACD937276B7CC9F6E5DAE62BC77C5759593AAE74D42A62C24A96540BAD4CC4923D4475C61B493C662A0A2EB203DDC1E84D9B6F2EB1E8AE2825494800841514816B20A800AD23FA4AAC35586F6009368D779B56942CAE6A8951399CBEB7D83EDE6C3934657229932D24E8AB392EC7A3EA40E8E1C9DE298428EFD8EF7BEE6FFBEF11AAAA92AA5A86AACAA60C07D6FE4DD5E2A0CD4203393C9FE436B7B6ECF15A3175B675368E5A21D6110C210842108421084210842108405C81CE108BAD29EE806706C5FD5EE3A107EC423813626F5244B381B4AC10E056E959360949491624EF6041EB19FF000A62429B12A6AF3332AE926052482C5DC1E6FB6B607CE23CB48B953135284A8A8320A99C58BB1377D34E578D63BC627C31F1139885DE32B869A73BFEAAA448CE54732708D325137AE35AD97E6DC97A536D166727E61414A5BBCA53EE04799674C7B87F09DF131475D87D3708E395485534C97264489F3540AA9969192512ABACC86242903300729086048B5F0BF1262DC1FC4126BA8E6CD448973731C8A21050140F301F5BEFB98C0F607CC6A36336A62594B99A4622A2ABE16B7876A61123544CEA0A92EB6D4ABDCB73CAE2169B2136BDAFEB1BED8A609435325188512259993E5F7C89924A5489885004292B4B820821C3BA5D9401D7D69EC5BE23F09C570CA6A3C4AAA599A94210A13141CA998820D817605F959C88F4E96507937425ED42C552F38DFC32D83FFED17084070A142DA82DCBDAF7B461AA92B428A569F10B1701FE778D8DA4E2AA6AF9C6753293DD4C53CBCAD97293A803417B10D106D4495837BA480410748FFEAA3F787D4DBEB10F767FA47CA329155DF49CD620877166FA5F5D3DC69139BDBCA424EDBAAD61BEF7B823A5FB758953D39259565166D81672DFDF711434F3651AA409E5D0A512ACC036E40E4EEDA74DE2575D4B68BB8359EE5AB8F97DDB5AFDF7B9BFCA25534BEF94D7655B41F57B7F862F1929C5707A196A566941924DD80040E418BE83A920BB470A72AB212095393938DB326DB45D5CFCE699269A013A8B639819E6949F2DC255A88B826F739252E0267E564FC897DC0E57F5F3DE3A878C7B5FC0B0644C06A24208736205873D1DC8DEFD045BAD4734B13E7262FA46446445127B1462CC715495C30E26410E02E22A7329923352D3492D89212497D534A9C438C9294E92EA928091949A0C1787703ABC5F189F2A90522264D42A6A414AD72D0552E584A92ACD9D40219B28CC0A992498D1BED9FE26933A8E7E118554B89E85214996B6B97049B82000CCD760400748DD9BC357C3E30CF03D935272210CCF66D6299392AC663629504BB30F4CCC8D12B4692985DDD6154C2D2D536A6395CF130038B740007899F16BDBDD4713F11D4617478977741207E1A4D3C89AD2A4CA0B5BA42416F11529449049CCC0B0481E6CD54CC4B1DC6A6D6D4CC99313327A96A2B5120E625CB682C583DB76DE326012E1692D3C0BCD04900384B880166CAB25774A42AC350005FE40479F5C458CD4E12A955984E253A5CF52D2A599530A48048243A487B92C1EDB81A467A30EA25C84CB54B4B80C54CE4960FF004F3D79BC793E7470F793FC43E199CC2D9B397B44C794F98656CB626E9F206AF21AD0525D66A4F25B9B469B829D135D53D6F1DF3D9CFC49E3BC193E8E7CCC4EA7BC421014B4D44D973012438CC95A54412015006EC1C6D16C9B8653D382A42120E64F8941D2A377CADA1B3F898FA4600B3BBC14F34F25EAEFE6470179C952C36A95599D772CF12D627CD2E62613A9D7A5241A992FD2C38E14A1B3FCCDD6E5D5A501A590176F47BB35F8C1E0FE3E91230DE31A5A6A82A9790564A4CA97579D59528EF49EEC4C4206624AB329C837BC432715ABA153534C52427C3949B16B950D5896E9D62DCB097889E6A644E27195BC72E49E24C01895B59A749E3B94A4293409808710D99898769BCCA6ADB78243BF172885B080082EA75A35773711F639D9D7695839A9E1CAEC36BA75A71952CC9975603789A42F24C9A428A434A4AC9D52088CBB05E3DAFA29A5750A5CB0A494BBA8A4DC0D744D811723E71E9DC447891601C3349A0E0EE1C1B98CEACE1CC36912D87B0F617945D5D2DAE65B0944CAC21050D8975B8D38EA4A810014949B9116BECE3E1584AC6A52A6CA54AA4973419AA9D2D40A4024E528292B054D94272D8DC86062D7C4BDA455CC9330226A8B83940535DF5770EE1EE09B3878DAA23E6E1484E89F9BEBC8BC731017DEFD6FDA25104163088C710842108421084210842108421084210844C9530CA98958BE53F2DE112A53A541409D85AC7DFF007F3F784E98672D4A2E33379DB4F28E49CCC0EDF3F3E7052428DCFE5F33F3F58E25ACCB50500EDB1DDB73F7E712F20D1CEFF36FDA205486C1B3A5B71B22652A090A500CECAE50292953C4AD2109505248D5E526D6CA3863139F458DD16212990AA39A898002C090A06EECECDB3EBE514D56724A3674A8292A21DEECCECC000DE77B59CC6B2DE395C2B624C038B301F884E4D51A698C4F81A765DBCCF93A43579C9BA2B8024CED465D905F536148597D61213AD482A209023E8A3E087E23EA714A4C3F8671034D4F2D5225C9913D6B48489C027289854A64A14949BD86609B80631CC2A72A831144F94A3FF7038E8E2E367BEBCADD4768C8ECD4A0E73E57618CC4C3F38D4F313B45A7B936F30E25C976EA0EB2C999979A48515B6EB6B2E0208490A49076B88F60F0412EBE9515F4EA2A9931209965C113080482351BB8B5FC9E375381388057524995348094A12905C5EDD3AF3EA76B7AD1569559640055E429E8A1D7DC5C8F4DBD22F32697169B30A8C9484B9BE64BEB62412145DB4E477DBB1512973147BB054924B6CE398BF5F573AB08996140A0213AF56FA6E12A5DBFA504903513D01ED7BC5F2452544A0153D21200670DBEAEC4DDAE186E0E978E67C89F210EA45C5DECC433DAF72DB7EB68A13CFCAD3A5A6AA1529E92A7C949B0E4D3C671CE5AA5D0CA0B85532E85061A4129D3AD6A4B690A0A5909BC50E312E555512E9BBF325765128241F0905DC0043B5FCE319C471FFF006E933261CB992198E999BE5BEF768C4566062ACD7F11DCF36F84FE180542432E642A12B2D9AB98F24879AA74C4AEB6D557956679E1F00844B4BEB6D16485CD94044A9756E35AB56BB68EDE70AECC785EB24CE34B327F773254A33168EF4B258CC2EA04A0974929B950235B46AF768BC715752A989932D0524104A4EE49B58866D58EB6F5DAE3855E1832D7848CA3A1653E5D509994453D9955566B886908A95667D0D3499D7669E404A5C6DF9842D4010094AAC7AC7CD4FC4FF6FF008D71DE3D5C69EA1465CC9CB00266950604EAEA3E10001CC0B08E9EC22B2A6BAADEA12C92AD1890972FE8EFE9A45D532A2E82B5DD2000128B0484A401B0005C026E4F7249373B468B56D7D52E795CE49CEBF13390FD5AEE7F68CE952912BBB4A2F6D459DF41B8B6BB3EE22991A9640B8DCEE7723F76FD22D7366AA6A8A893E44DBDA26BF8401E65EED7B6BCF7FEE5EB93D3A0B0B44B4A9482E9241F3E7B7F8D2242E5E720BE9D59CF5617FBDA211C44C01801C801ED08473084210842108421084210842390588235041F6842270A858E5E8E3F58441448091CB4AECE21CF36A162D9240F291D751B8FC22ED874D98B44E23C2A005C12E4B1205C917BDBCA2DD59878AC9929667AE577649CA824050B72E440D7A0E6FC09B9454E2669332A438CCDB856E36F32D3CC68B2D0A614C2D0B43AD2D2B21416955EE3A758ECEECFBB49C5B84315933A4A8FF0E6209254468417370012CDD3DA1574E8553894C1C25B396CD6003BEA79B102CFB8023029C7FF00820E57F1035B9ECE4C849A95C9FCD7B3B32BA55367572946AFCEB87985F999671D70216A746AD2D29A4F9D564EDB7AFBD88FC66CE9586D2E1D8D193514A132A5A93314833102C93DCA964997BD810924070A64C5061188E23C3D522751D5CD19561565902C5F40C08D1DC1E91AE6E6CE4A71B7C2D56A66899DF91D8A714E1FA638F4A318C70DD2A6EAD499B62557CB4CFAA7E841F61844C213CD4A67DC4BC02ACE2750508DF4C0F8B381F8B24C9C46871DA742AB25A2A154B55365CA54ACF9546589A4A24AD482ACA72A8BB12924398DB5E0DF8ADA8C2A968A82AE4CB5AE9D0896A985D4A2520024DDF63736F3B378B35C49E0A07955893AFE1F7D1B2A5EA544A904376D941A75B93FB54A48095A8AD6A0ADAF78CF918160D3E489B4F5D2A79525DA4544A9B725C3896A514B8B8701C36C6362303F8B4A09F29299DF874822EF6E6FCAC08D069E61E2A3DC4AE592104313551AA3842425993A6541BD6A51B04F31E954A13A4EE75293709291E62045A6A787095293FF00A16254A9B2D0A0967B254A04B5DEC6DA39BC5EEB3E25F079B4E55227C8134870124B72D73374671B5CC73A878D7363346A4D50F26723B3171A54262C1A7E4309D7E7A9E8BF42E3F2726522C06FA5CEA7A98A79BFF11C0291559896314B2912DBC09ACA75CE7701BB996B52DC394974B0BE9AC74D7177C4DD5CA93365D3290A2A49CA7311E999C0D1EF61B6BAF77E223813E2372B7271ACD6E2EB1527010C44A44965FE4F61B7E4AA58CABD529D713F07CE92A47C7BEC48C934F3731506664333E52C4CC9B67E3D21A191601C59C31884854CC0EAD152A41004C9E04B403943952A72532D09771996C9DC1168D34E3BEDA788B88A64C659961454004A8B92E5B424F2D3CB6B6C07E085E17ABC83C1349E2373568725FF0053316CAB8FD1A8D555CA3F3384687372A934A7ECD2CCD4AD61E6DD35408995F39B6E625D0EA1252511E6E7C67FC41E2986E2133843089F2C50AA410BA8A79A41993485778B202F28292320CA908294029725CF50D18AFC5271ACAF9F37BC0A3E052890403A02FADF35C963CAF1B23B6DB5A1B482A5A92A2B71E24799452902E364D9253B103512772768F11F8C2A6A2BB11A8AC9D5D3A6CC9D35531CAD4540AAE475FA6EE2ED9F502C212121203A024160483772EDB8D6E430B738AAB4A0D936B7B8B6D7B77DEFB74B763D7D311A7130A8CC9B3573521C842D448DF63A7B45C3BA5175198B06E4016BFD4B9F96F78A4A6D2A02FA82D26FCC6D6B6966DD012DA9208F9DFBC51A55397309CCAB962E90A480E5AC458750410378A79C0CD4E42490189B9670EFCEDCBCA24710E2C04A74DB6D576DB5F33AD8381695051049B2882AF31DEF19970ED6D5E153513A9EAA74952492C85948049F37B1E5E5A452268D21947C4FCF9B8D89725BA5BE63C7B3532172973A28B3987B3570061EC7149A88532F335BA7B53536C8536E36932B533A6A526DA02CFD94A4D30D15045D04A53A767BB39EDEF8DF84711915785D655552A504832D73D4C94B87219693B024BED7E711CFA644D97DDB64E643BEFABBBBBEFE7CA35EFCE5F02EC7993598F219FDE1FB996DE0AC6B86E7A66A345C335D144AA536443854EFF2E935D6A5672652D9B2186B9B306C2C56AD898F563B10F8F3A15264527194AA4953A6E44CC9E0A3BECC01B925452544EAA5824DEEED18662F8610850495298E84580BDB4F20361BC6CEC06DD49BFA98F9D14AD4ECEE0D8BEBAF3D63B273A79FC8FED118E6665CC32970DAFA98E4106E2112E3984210842108421084210842108421084210842108471E650A710C8427ED19996A6526E06AE4858E5A8122E85F32EAED740BF68BB61B3049EF265B310C92A7B0D490C6C6D677F4895365098CE4B00A1976254CC7D08D1D8BF48EB18E30450B3270C624C258C64E5EAF47C514C9CA1D665A6DB0F4B5469F506CEA5160A4A5A5CA38DB6A428042ACA5104D8C6D6760BDAE54F09E3945FF0050A96897365E8583670C5FA337AB6B18EAE9552A6B84304F5D1AE1D9C9B3EFF511A6A664609C7DE10DC4D55703D75BAA55B84ACD9A938AC275B71976A14BA24FCE4D26652DA1F934132C196D6F2421F55AC9B5B6B47D30FC3176F787716E094A9A8AB9736AE5D34B3365A94332D094A52169B8056EA1DE26EA24E60004931D91C33C4EBC2C4B41514249005F42E1D2AFA0BD886D5A32A542C4987315D1E46B187EAD2D55A3CD4ACB4C4A54A5DC4AE596CBAD256CF31D49D0D3EA6CA75B0E292EA17A90A40525406D950710E31595B30D3C84AE91730992B1E20524821989B00CE743B46C970E71E512A549EF569CD9124BA83070C75B7316EB156B15CA451E913D55AE4E374FA4D3DA5B93550997D1252B26D3682EAA6953AFA9B612025212105775055D208208CAF10C657494A5758132C250495125274724BAB636B807ABDA2FB8FF001C61A8A39850B438960FE600D8727BFBF3DEF189AC518EB3CBC49F3493C35709626A9196B4EA922999979B8DB4B6E9D354B92704CD45A66AB37FFA3743CDB46500925975ED450C1E6AD263583B57EDAF08E08C1ABB119F552A5AD1256512D53521473248428A5C29214E169CCD9810402088D4BE33ED09550A9F4F4F30B296CE97D943CDF5637E6D711B4D7059C17E59F05594D8632F32D68B26ED7DB6173B8D71B4EA10E54F15555EE63CE22696AD2FA1A69C2DB722590CA501A64CD17D21DE67CE1FC5CFC4CE23C698E5451D1621344898A988CD2D6B530CCACA02525432BDC802E5EEE63AE25CC9B891CEBCCB7006439728F15D6490E4E5240BB30B0DE2F1DD6DC74EB0B09528EA5A6D6B2AE491702C4024F403A6DEFA188A9AA9922657D7CC5CC24A9414BB953DB7BE8C18B1F9C5C138722907788D478ADA1D35E9A69EEDA5768143642D40A9573B0EDD00D875EBEDFDF19ADABFC5CDCD942427C23A8D47C88FD86F5B4B315345DCE55105CE9707C8EBA8F68A61275DEDB5CFA77BC51C574548421084210842108421084210842108421084210888BF617B7CF6F7FF0098ADA4AB14C160B32C8D4F27BB6EDFAC7043FDEDB8F5E9136B581E4294280D94A4EA483EA53DC7A8DFD62B92153BF892CDF5B33B1DEF6BB7202DAF3A79A82A0A04383A3DB7B5C68E3D46D6B450F86635175B69B5BCAFFDC33214E15F75724A540366E76B8D811E9B4EA7E21C670C5B4AABA8920365285B04906C483F987449B45B66D29538CA2EE016D41E4E6E7E5D39F5BAC52A9D57957A4AAD4D95ABC9BCE2D2F536A72F253ED2DA24FD9A5136CBD2A5B009D9D6D6E5AC4A89BDFB9B867B70ED0B0A453CAA6C527AA9E58012BEF9603002D94A811B3101A2D69E0ECF34D477EB41984AB2A54C120DDAD77DB7B00F16F188B82DE13B1ABEFCC625C84CB89A75F374392F4454B3EAD7E673E2B92FB729CC52EFA4CAB4CB6537BA09E9B01807C52F685492108562B549530702AA6A5F401F2CC0EC0B0D80B33697793814DA74909A99A02400095020EB76D75D7CC3F38F874AF0F9E0CE86EB5354EC84C01285B710B0EBF4E43FA55A81DD332F3AD104F96EB4102F7002AC466749F13DC71894DFC3CEC6ABD2952144135D3AC425D9CCDDF97563637A79B2EBE4A95DDD52946EC92A0C6E5AD636D40D437A4778C653D913C2AE5E631CC97E838372FB0BE0EA62A6E69325274AC38E4C25B42396C49CECC36D7C54ECD6A4265256596E3F34E38D36C36E2D6906E1D92F1EF693DA4F6812703AF15F3F0A5D5A91DEA7BE999A5A4A8E677585064824DECEA360F188E273F1251266CE5A9249D4E8072DB561E7EB1804E1532DF1EF8ADF16B53E2E33C68AEC9F0E194B5B7D193B84AA867E9F295DA953DE54BC8555D54C3CD30B6D87D4DD49728F8D53932D38D290ECBBC9615BD9DB9F68D85F621C013B07E1DABCFC4788D34B15F37349989A79250850A79672B89E56099B3104E54AFBB74CC4A9A8E8294CF9A89935CA125C02EE54E4124368CECF6B66B8D767490A43122DB4CCBA39328C21B6A5A450DB4CA659865B436DB4A5348421FD9014DB975E864B6CDC06C253E20F687DA5E3BC4B8B4EACC627AD7356A52A592BCCC87569989D4BB005AFB80D19AD3D2242032580B66B5C37EBA1B8368FB3A5211E4F2116011D6FEA493E9F38E99ACC466D52C925C6EFB972E472D98F48B9C99252058BB8DDADB35EFF003893ED3F768E69CB0502F724BBF3B1B746F9BDCC5C10E05FAB3BDBEFDA2A44E099697673D3F416B0F2FDA259412E19C79B7EB1305102C00FCFFCC3F14502CA0E2E05C1F47864568C18797DF972E9112B24822C2C6FB8D57D88B7B75FCBAC5CB0FE28A8C3A62E64B485A94928BECFB8B8059B9DE19093716D0E9A7CFCE387CA086A60B2843732E2B63756DE624AC5CE90A02C537DB6DC18A5FF0077C62AAB454A2A6A650CC54D2A619601D406B59EC482E6EC629EA28913CB1B0E76E5A335FE623936B6DE9B7E116020A5446E0B7B189998FF004A9FCBF5FED088A686500429272870A0C4173E51365A83310DE7FDFE5FBC225C4D84210842108421084210842108421084210842108448BBDB6B7D7B1EC46E3F589F215E308760A2DC989FED68446E556425412A23EF1B5874BDCD80B11717E9BED6BDE32292A9B86AA5D54A98525042832803B11EB7D2FD7489536521692543AB8373B5B9EB76D3CE3C1F881E1CF2E7899CB9AFE5AE68E17A6620A0D52594CD3DC9C693F13419A524A533D459A16704D22EAD162E8DCF93D3707B0DF897C67832A69908AE992448992DBF8852084AC12F70E0E5BA48D39DA2D73C194AF0E636BB073616CD6F091ABD8EFA9BEB558C3C1CB8FCE1C2BB3E8E0CF3A64717E017E7665F6B016399A92627A992AB796B9770BF3D312AAB308525255CA08DEF609B01EDAF66BFEA3DC128C170EA2C4E7CA15C990844E9EC184D281994B400EA75386490CEF76112D38D575125265CC5E500B3925C3116218379BF5BC56C29E0F1E221C4255A495C5B67B51F0C65DB4FB4E55B0860CAF50678D669A85875F9579CA53AF3B2CE25C1F0FCA76EEA9009BDAF141DAA7C7E70F4FC26A666155122A27AA4ABBA59590896A0C52B4A12B492A0C1B39286B292444A9BC4F89578EE15326A41B13E2B8DC13CBA8B03E71B1970CFC2F64CF0B397F47C0394D84A9B86E8F272ED3535352EC876A75A9C424F3E6EA936E6A78A9D7829E162DDD5A469B794F8BFDB6FC58713F1C4FC428135D36626A27282D7DE2806CCD60141200D02521800E368A74E08BAA9A26CC2A66CCDCEC092E41277DDDEEEF172FCA50792B07C840B0B1B7D3DFF001DBB5ED1A755D366D6CCFC656CC33567C5E239B52E5F7B824F9B0117BA5A4974A82946CEEFAB9041F4760FA9772758811A4950DCDC8EBE877DF6E9FDBE716CABC495552D34684B2010033A5EECC5C9B59BF78AD2D312DA8D34BDF6EBAFCCB40282F71FBF975DBD3F2DA2DD3A9A6D314A66800A838B8258F36FBE710CB92248291B9727993A91E7FA0B3888C488990842108421084210842108421084210842108421089828A6F6B6FEB0C857A025B937DED10A9452CCD77D7D225B12401FDB7FC7FE7AC55D3D5AA9BAB16662772EEC762037D60E950B91A7B1DFDBEED1026DB6E4F703B5FBF4B5F6E8627CCAD953537961CEB6FA173E9CB68E320E67D58FE913F250AB13626DD48DF7DCDC8EA3F6045322B6A81099648009602C2CF60799F3FED466A2B53372A12E8059CB80D7E805B9BFB448436CA4DC0B1BDC8EA0F7F5EA7D80F5DBA64D83D1E3B5D31024B84A8D8AD441236DC339B31DBADE2298AAB5A5DC07E45AE46BADEDC85CDDF58E8198798582F2CF08D7B1D634AFD3F0E61BC3124BA9D62AB5479B6A52564DA5252B1A9C5B6954D3EA5265A45AD44BD3CEB0DA50E29610761FB3FEC6B8DF8CB14A2C3F0F9530CC9F3104CC40504848214A054EDA2487D376722316C4675461C17573561694120A52ACC6F6D01F5B79DD9E357FC695FCE7F1ACE2065F0765E9A8E12E0CF2A71507EB555756FB4D633939098B4F054C28B489B9F9F529C4B52884A8D3C2D0A53204B18F61F85B0BE0DF871E01973B1E9743278B461899A145283534B3662000B55C9CF35044C4850BA1692C5DE30D9DC4F2ABD650259C854012124051DF57E4DD407711B3C657E5A60DCA1C0587B2F70650A4E8D85B0D48C8CB52E8F2CDA5B654E48CBB2D227E7DD480B75F794D098754A5242D6A248F35A3C83EDCBB6AA8E37E25AF12EAA7544B35534A02D44A194B25C9D1893A25801A002330C0A4A6ACA484A92E960C9BF422DB0D1DC93CC47A134E25D53AEEA529C75616E8B7D9256129404B1FFC410947F52BCDAB7EA06ADE34AA99D5095D410094BA424B86BF5373716B466829BBA4E53F94593719998139C6A144BD88059B9C56E91681254E1D9BA1D3CEDF4F78E42002F72DCDBF40211C99850A641D0DDEFF0030DEADE4F052882000FF005D624F3027CA373DB6BFE6638EFE61373AEA05BF788E205449B276F9FF007F9443989362CF7BDDCEFABB6E7FCC2264A74DF7BFD3F7EB1514EB95216F3466074B726F5B6BF77E0902E62622FF0050444732AD4A59120650E58871EC1FCB5F268E33A79FC8C525BA1D2082494800956CA24775000589B5C8B017B8B5B68BE0E1E9F4A8993EA82913A54C53CB506F10BB317245D872D758B7D2D52159430B68E5C74D39BEE3F78A8D8BA53FFDB4F6E9B6F6FAEFF43DE2C15F5B36B6705CC96841420212109CA1924B66726F7BDC08A998BCCA0CC3E9D1F523C873D7488C51C4C43BEBE7D628A42AE08E97DFF7F2F68E4027627CBFC44D8AD1C6908421084210842108421084210842108421080241716221089866CC5062B510CDAED088DCFA984B9B325282A5AD4953BBA490621284A9DD20BEBD621CC52D646FA8A74157F52923A02AB0245BDEDB0BC64F4F8D564A423BBAA9B2C8672998C7AEE7DBDA203224905D093D0A411E637F4EB6E9C654903F746906F700800DFD8587F7BEFD62A66710E2335395788542D25C10A985AFE8621122402E252411FF0081FDBEBFB41B94E5282B6B0BEC4FA8B6C3EBF80F94592B27A66214B242A613656AA73A5DBECFCE782D64B81D0103E968E4DCFAFECF58B499B30820AD441D43984220D348422252D6B6CCA2A60C1F6108443084210842108421084210842108421084210842108422346705D009E7671F77896B4A94D96DAF2E9CE11592909981A62402747B6D73E7D0FB44210A60E2FBDC42277FB785DD0480C4B5806E9AFEDC9A2624102E6E4BFDFDF947157392CC2CA1735CA037097125C0B776F2A402836BED6BFCCDFAC745864CAC9C6521255350404B6A482000C01B9DF9B7568A69D572E5A4BA5266074E60E0A53CC8721EF73D46D1E419D99FD96B905806B998F99D8AA8586A854D975FC43530E264EA552F21537254E44CCCA82A69F521210A4B2E5B71CB51371B77D86F623C5BC6B8AD253CEA09B2A88CC4242D32D614B482E0A544313670CE59F9462D5F58B7294CD98400493998E846C19F95AC1EC358D6C2AB5CE233C6CF353FD3F4592AD650F04F802B613579F6DA9A62AB8C69D2531A65855671CE54B4E4BCFD404B1684BCA31A0ADA5EA58410AF58A911C19F0D3C26AAB59A2C4B89C513675AA5CD461226000A9591B355B2B2292A5012CA94152C94BC628535188D4090B5AFB951202560BCD5072C39A433DB96AD1B25E44E4765E70F196B43CB1CAFC2F2F86B0ED0E565E9E1E94436B99A84D14244CD567DD43485294F3AB71D5158EFF7AC2F1E51FC40FC40D6F1C62B529915F31699AB5A94933592A049536BD58274660031022F74B804B925CC84306B6516D2E395F5D753CA3D99C68A53A0AF99A4692BE9AEDB6AB5FA2F622DEDD846AE77A9ACA75CF5A477A412546CA763A68E6FC9B93465D4320D325252026D6CA000DD6EFD3D2FAD8C0D2142D6F37A7B0E9EA3E5B7E7187CE528AC82A516275512753BFB45DB395804973A6BD7E515E251528862A24722491ED08471084210B0BDEC2FEBDE10842108423199C01788D655F189845AA63EE8C1B9C78793F098D32F2B0F225EAB2F36C2432F3F2D2EEA5B986E454F36F25130B6960A90E26C4B7757AAFF0011DF0B588F0FE26BC47069099F84D6AD5369AAE97F894D3D2A39CA513100254BC8A4E64804A49CA79C758E1F8ABAC0CD71AA6E080E5FC3721EE3E978C95A5D0871D966D95CCCC855B9216197595292950E73652E11B28280B8B8F35FCDB68971676733707A94CA32569564CCA7053E224E81AFB682FD358CCE967F7D29330286505CD9C948D46BF3313A1C0496CAC29E6EE1E4A4795B26C52926FD7AF6E96F58EA7AEC3A6522C8292C3576B731FDAC5B68BA4B2E5D98338BEBAECDEBFADA273701207A81F48A7956B74F320FD98A94805DF6493EB134532B53E67EB10C238842108421084210842108421084210842108421084216B7EB073CCC210836BD75842108421084210842108421084210842108421084210842108421084210881B9D877BEF6BFA7E7BFE5D2321C1A9D13D1382DBC2035D9DDFCFEFD184800924001B52DABDFD396EED688DB4A929B02544582961B4926DB6B215A7A1B581F90B88933E8664C9C25C8CDF9AF9415313A68C6C1EE1DF9BC534EA8421248371B0D6CF6D472FA18A6B71286CA89B39AAC5873ECDF401B15B6D9D466120DBA68BDC6E2E2334C0380F88311C9DCD34C58514FF002A8B0537B937243ECD16F9B88A424F47653BFB9E8DADC6F668C6C71B7E24990DC18532625AAD567314668541B725F08E0BC31CA9EADCE579DF2219A853505D7E5DB438487516529B2424A8DAF1E837609F0915BC4955438B56484C9A5909454D7D4D5112A969E524256A5CE9AB494A40D81D4900177118756627FC55E656AA20252495172400C0172F6B75318B6C9DE0DF8B6F135C6F4BE2178DCA954F0264E4BCCFC7E10CA54B8F482AB14D98744E4A2EA0C4C0B065284B687580C15ACAC6975001076FB8EFB6BECC3B18C02770C709CFA3A8C7A4CA34E31497265A0A66CB4196BFC2A92B5158510A026B90A9649C833068A4CA9952139D395240010E4926C407DC0D40D4100398D8E32EB2FB0B657E12A260DC1540A661FC3B429514F92A3D3659B9690618658530DCCA5A48E6AE69C1A56E38E3CE24B8B5A8206D6F2A3B50ED8F8838BA757C9AAAA98B9559356B04CC51042D454F72C2E5DB42CF17DC2F0BC9532E6AD395282081A10400E2EF63B8E4EC4477566ECA4A5B0528524A1C03AB8140EAE61DC1363DADB7CAF1ABB594535530AE6AF3072B0A55D40820D8BEAFD0A58C654B932945C806E160386045BC3BDDB99DF47115927524036B74F90D80F71B0BDBBEC7B889132B152A51952BF99EE090EFF7A732FA0BF0500F4F26688E909D81BF7EB7FDF48B5BBB9622FB868241018F3FDA11CC450842108421084210842304DC77785854ABF8951C52F06D597F2C3894A23BFCE1F92A4ACD3E4B17BF20AE7312FCA95D0B54C3A1B0C2A6541DD49281C8F212AF727B07F88EC2F8830095C25C7EA4E2B854D012A95302664DA45A8009A8A45AC9C93259016031CC521C8D4750D4E0D572672A7232A569DC12C43E8AD9BDBA3E87E9F049E295298D71149F0EBC5D5393947C40D25C4D1CCE54AF252588E6DBD2C30ECABF3296545530F25615AB502A55C28EAB0A6EDABE1E66714A57C57C0D3A9711C01526CB9601A894B56650973A5273649A9053E10A20862F7B5CF0FC7E9E807E12AD2B4CE26C19D376B876705EC1839E8C233712D312F32961722A6DF6020F3E6658A5D65E2B092DBDCF0402909B924022C6F722C63CB4ED1783B15C06B6748AAC3E7CAEED4A056652822C58EBE435B7AC669435F4F5233A54CED941D9C7E57EBAB163A3C72C1D64E904A1241E6EDCA57A84AFBDBBEC23A5A70FC3AC80524B90425CF99B0F2FF117513000E3F981B6EDEFE5EF13C521B927993114238842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842234CB5292540800733AF940D813CA11044B33072F7B7EF08E402A2024124E800731019E90D6372DEBED08AE9787CE5A5CA908B3B2CB1FD2F118980EA08F9EDF62CF7894AAD7B855877B6D688E561553366776907FF009149CBEA5FCE26800E8A4FA98A8D3ADD96B52AC940054AEC8BDEDA88E9DED6B8B83BED19451F0A62E854B4D3CC9530CFFE594B248361E26E9B6FD22DD88D4A69528CDFCC4B7566B8DB7BBFD63CD734734700653E16A9634CC4C5948C2986A9726ECECDD4EAB30DB4D372CC805C5B6D2D6DA9D50D413A42937241BF68D99ECB3E1FF8B7896AE966FE0CCD96B5218774A2F988D2DA800B0D3C8C61D578D480E0B80FAF32DBFAE8C1DFDE35FF00CF5F141CF9E2B7174CE44F86B60BAB57BF99BAE52B15E6C54A4DE44A50A58AF92BA85326A5B98969B0A25C428BB7D2949DCF4F513813B12E0CECE70A9589F68732970F299299F2280A659ABAC32C0250A4AF2F72862332FC641397217262CEAC45554A52648510EC56E72807CBF3173A37AF2BA0E0CFC23707654575BCF0E25AB7339F3C45CEA113CEE26ADBC154DA54FCDD9F9D6A5D8994CF2A64A1E3A5133CC972B09D5CA4EAD23A37B71F8B0C368696B384F8100C2F07A5993109A1A4697214B1993DE2D4829EF16C5402FC36528B5C34DA5C26715F7C7C6B533AD57241BB0E439F974BE65E464C49CA3728D36CCB30D1429A61A482DB41008084582004A76B5922C36B1B47979C55C6231EC426D7D655542EAD7316B482A25249249B1D05EE1CF521C4667875114175A45EEFAFB6C4F33BB691CC1BBCA7144A94A1A6E760902D6D237EC2DD46C7DB7C46B7109B369573497989004B62CC2D7E6EC357E9D632232D9032F808E8E0BF3D1B7F5F48AA6C6FB0DC58FBED68C567564F9C085A8B1E4EE6EFABFDE9BC4BF181B2BEFEF99EB055881A45AC2DBF436F503D7A1FDDE950188CE6D9812D761BEBF4FAC471017EE00FDF7F78AAAA3209477249F0F8BCFF0043D3FB422314B084210842108421084211C47913328968CB8750C4B952E4DD49BCF493AA3A96E050EAD9579800B174DFE9DA3C11DA0D6E055B2809C432C7892A2DA0DEC5C6F60D16399462A01CE904104104302EF666E5A863AEF68C74F1AFE1D1929C68619997F125265305E64B0CAD34FCCFA1C9B3FCE5B54BEA7641DAC041967A6651A9871E5A00992A6545E5252B2BB47A0FD8C7C5654F0E63347475B524E1AB484CE97399729626F86605CB52824BA40177B3EF161C4B8724AC77CA4174A6C45988F7D1DC3EE47531891CBBE3038C9F0B6C592592DC65E17A967170FA2643184336E9AF4E4CBF4FA5B6E06A510ECCCC4AAD7372E96815BC87DD9412D61A39FCD568DDBE38E06ECC3E20B84E7CDE14187C8C7A6D399A285E4A1539450A33552143F2972908964312497043C62DFEE5370C9C2592A0805B37F4F225AECFBFCA3634CA1CE6CBFCF2C1745CCACB5ACAEB783EBD2CDBB4E79080DB726E388438587901C5EA5A0287436163F4F1C7B4AEC1AA7B3DC531295892532FB99939D0BFCC9524B04ABCB4DEC488EC0C26B8D64B42C28310EEE6E96D2FCDF6E4D68F5B8D5E9A90898B48B84A881E86323844B84210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084226194B0813329C877F523DAD12D44E6CAF62C3DFFCC41448B585C9207F9FCBE5F38E64AD2850CC1C1B5B67B13F7A6B1CE44F33EE3F6890389248BF4EA6FB8DBB81198D2A29914E6A654B0B992D39C24072543460C5EE2F7E9B3C4464240CC4E96F736B91ABF3F789B526E13A93A8F417173F217BC500A2ACC6A7664C99895384A529490080761CC9B3EFB691473A6A653B906CFCB4D40D5EDE51F0310E22C338529D355AC4F5B6A814D946DD7A6A6DE98659A6252848257522FBAC1B917D4108780401B9E83BF3B3BEC838BF8AA6CAA0A7C3E777538A1026192A03C459CA802598817DB578B054631DD29C076248516B36E356D1DAC35D58BE13F89DF19FCBAC2D517B2AF848C1B3FC42E774DCC4C48CAD3288DDB0C51DD41434CCC19D6DB9B0E19A75C56A0A9768012DB2957DBD19EC7FE0770FC0A9E6E3FC755D2682966290A4CC9CA493298152B2CB9990AD6014B27C20BEA0C58AB7165D60CA1D653B6AE058126ED7D4B13A88B74CB9F0E9E2E38EFC4F279ADE20F9975AA1E03538DCFD2F263093F34E229E95A83A6467D97DF919671AD1A5A713CADC249DFBF62F1276FF00D9976234DFEC3C2B8709F3E9A59953718AA1295553968F0A574D4E14A146CC4828A89A4BDC0CAC6D29C3EA6A56A54C6D4E49693E1CBD567F306E639467BF23F21B29B876C1B2B80F29705E1AC2986A5586DA5A24251A945549D69012998989C665C3AE4F2815296853453A96AFB5D813A13DB17C47D776933679A4AD548EF0ACA8AA6A92F9897B827561E768C8E8F0A12825410A50703C2916EACFA37577DA3DA5A012DA004AD20252025CB7300B6C17627CC3FAB73BDFBC69FE2B8CCC9885266CD3366DF32CAB3662355137776DF5E717F9549959830DB60FB8D2CFB0F9F3A96DAF6DBA7B7CA3AF27D419B34A89D0923ADF5FDA2EB25052DB65166B7ADB73AF40DCE292479BA6F6DC1E82D6DC75FEDF388BF12B328CB7D6DA91ECDEEC5BE422A8AACC4DC9D39EE7A003D6FCA2AC52C4308421084210842108421084210842113BAAF2DAF7163DC9E9B7E1FE2F096F2A692FF914CEDEEDD40D2258225F88EA2E06BA72E87AB72BC71904367981C2176D211BF41720EDDC93D37E9F867D47552154C85AE6995392A0CACCC59837F306B92EDA1B011CCC9A898854BC9A85329C6AAB337462FE7A18F3BCCDCB3C1B9B584EB583F3070A53F15E19ABCB2D9A852EA4DB4E30E0295243E10E36EA4BAD85AB46D7F39E9DFBBB803B6CE20E0908387574F3DC9065A9139799053F94A483622EC6C7CAD1855770EF7F37BCCA9F11D3505CB369B5EEDB5C8168E0E4F650E09C94C0D47C059714090C2F8469EB53B4F94906DB6D2CAB4A124292DA1B09F281F87A6F189F6AFDB5F11F1F54CE99884C9B366CE5297366CD2A54D9CA57E652945F328BEA4BB8DCC5750D28C3C22581A30CACC03E8396BA5981676B47AC47401254493A92E7D63294E83C87D211C47308421084210842108421084210842108421084210842108421084210842108421084210842108421084210842110B8BDBBFF009FF91F8C5D04F942844A206700EBBD987BF57E8DB7052DE3BE86E5DBEED112AB581D49480ABB884EB2DDC1015A091A86FD36EDB88A9C1387EAF1BAA97229D0A65A901403926E2EC059FCD9E28E7D4894012013A804FCBD48F47D5A3CCF1FE6765D658D15EAD63FC618770C5259D7333153A95499A63A89666EB79C7651056E4CA5B4A56A5326FCD00A3FAA3723B3FF00875C67189748A4514C9C1443A1085294B16364E52F62D7FDDECD558D265CB5BCC60907C2AF107D035EC473B16DE30ADC4178CEE0497A94E606E10303D7B3F731DE7CD3A9F352529312986D99E715CA65D66B0CB73B3CE10B5255C87298D4B90024BE94A894EEF702FC20F0EE1A6462DC6664E0F4A8089CB338CBEFCCB06EA449CC1CD8F856A473D098C6D58E0A9514A3C6A0481B07E4F71BD8DC73DDBC1287C0EF88D78804D358A78DDCD2AA650E5BCC38DCCB194B427E610FBD4A78EA32F3F2528ECBC8A57CB1A6C1C7414A8155945494F65F13F6D3D8F761F44AC338528E46255F4F2823FDDA726529299E9CDE2914EEB194029216548538578583980514FAD2EA394125902E6ED62417DD9B9728CD1F0CDC0D70CFC26D0A4E9B93D9798765EA09659FE618D2A146957AB15B99612AD0669DE4B8F20CAAD4E2D3A9E5DCCCAED6B6FA17DB37C62F1771904A70BC4268968CE14D354159491940CA4B000358FE9171A4C10CB273900280094E9CDC8767F2D8F5BC5E24AB8DAE5820F9DF43C56B5309F8765091FF00C408053E82DB5B6EF1A4D8D71CE358FD42A6E293264D52D454E56A51503AEC58B91EAF7378C92930D4A00CF97460DBAB66234B3DFA33C7201B8BC62758B9AAFE2254A4277492C4921C1FAF41CE2E0A969942E0300C6C068DE978815806D7B7B83D0FF9BFCFB45377AA54B4A4924D9DF7FBF2E7D227A65029045DC0B1B7B5FED9BCE00A8DEC41FC41FDFD6298A083A6E7D3CDDBEB111494D99BEFA44403705477B5ADE9F5FF0068823889A108421084210842108421084210842108137163D3A7A7E906B93B9B9884A52751D3EF6880007402FEA4027F1209FA472A5294C14A510340E40F605A20EE92F986BCF53FA441490A26F7B1EA9BF94FB11D08EC47423AC56D26213A8AF24DFF00F2621BC883CA273D9986843B5EFD75FBF26821B4212B4A4592BFE9FE94FF00F44F44FD04735788CFAC20CD090435D203BEE4DB778A7994E89A41512E342F7F27D5BEDE278A089E2C00E50842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842200006F607DFBFA6DE9B77FCA2AE6514E453A2A5BF86A2C0EEFAEDB73BE8FE90AF33166D37E7F6C79C757C6D2B88E7F0B57E430AD45BA3D76728B5597A555DC473134FA9AE45F4D31E2D04AF5A4CE9642C6955937241170765BB05C5383A8EB654CE219456A428720ECAEAA008218B3F2B3C58AB65CD9815CEC2C3A680B7CC06D4F9EBFD46F070CD7E21F14D4F1AF1C3C42626C74C22BB34A93CB4C3755AA2692FD294FDE51E9B982F48A29EDF2882F312CDB9F6683642CAC83E96CDF8B4ECE3817064D1703E134743894AA608A6ACA89722A2ABBF324256AEF179CCBFE2662928538043170D18B4EC30CECE26A94A049747E54E5D2E3551D2C407E66331BC3CF099C3CF0CB4B92A664FE5AE1CC2D51926132EED7D1489399ADCC2123492AAC3ACFC6A96413670BDAAF63EE34F7B45F8A4E32E2CEF8D6E223F899EF297914C49203A5ACC4331E6F6788A9706952C8CA9372E06D7E7CDBAC5CF25600250B75CD4490F4C2D4ECCD8F54F39C25C08BDEC80426C7A46A1F11718D562EB986AAA664C2B2A72A98A51199D83391D59C6A3CA32AA1A308661A6AE2CA67B5DECCC2FD7CE217290436A5320FDE4B0A2D2576BFDF4A2C14773B917DFAC60536A44A2A3209FE2865025C59F673CFE97B45D932501B3252ACA4949233104B3DC8B683488292951048008EE3627A7DE3D4F4EF14D2EAE64B5660947FF00502FB7389E92521869B3B96F2736D9DB560F0000161FBFF3F38E27D54DA86EF08B17B5874B696DBCE25CC40981947CFAE9C88E510D293BDBDFB8FD2DF9C494ACA746F6BFDFDED13124A4000E9110903A088BBE5331093E63FBB4092753118964B973BC7108E2108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084535056A041200B7A5AC76FEF7F7E9D378BBAABF3D0CBA562C93A90399E8FA9B1FA4460A72DC686DD6DEFFA69105A14BD212AD04282839A52B520A4829D285DD0BB94F982FA03B0BC5FF85D545226154F9E25E623F9CA496018B8206B6376E46242D0142CC0F222C75D77EAE2F1054BB6E73358534A7B77DD93519571E5A40085B8582DEB02C9D4DA896D56B1052488C97169585CE42AAA556A4CD4254520CD2A72A052E03900DED94383705F5A4994485019521C105C9E5CDF9E9BB6DA5C19012940756023A2804EB3FF00D8F7BFCFF531834D9B51500A4CC245C02492080EC7AF993A9B1111CBA508BB26DB1BFE8C474E7F3989205AE4DB62483F874B74EF707D2289787CC5172497BDDFC8FD3668AB094822CC398D40D3A96B691147426DD7F7F87FBC524FA73200248249D8FCBE87CB7888B6DF57FD05F57F489E29638842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210843584223EED7FD26110B8F51F8C4041058D888381A9685C7A8FC639092AB00E79405F4BF95FE90B8F51F8888BBB5FF00498E58F23EC6171EA3F110EED7FD260C791F63118776BFE931C421DDAFFA4C211C142C072920084221842108418B3B16E7B470E06A40F584221EF11FD4211104288700B444083A1784431CC21084210842108422248CC425C804B18A65CC5A56C2E2EFD03D986FC9FD2220DBB03F317899369CA40226036764A9881D7CB7FF0011185A8D803EA2F112AEBE548FA6F13514730CA54E33D29C833652B2EA6BD99C1EA1ED13337FE2AF68962648AD5A080A621C5FF52EFF0064C705476497EA211553B133972A05F9BB81CB76F367E512CAD61DAE46B61FDBE4FCACF11DBB580DFE9EDF4FDFB5B26CF5CE3E3DB937D46BCB5FD23994B52CA9DDB676E9D4E9BE83944224C4E84210842108421070352D0841C1D08308421707A1BC21084210842108421084210842108421084210842108421084210842108421084210D2E3686B13E83EA9FC7FDA22FC42F62A7FFE29FDA0E06A5A2422C41251D6E09B7E7B83B5BAF4F94121738B252A528D980BFA75BBEF12D492BD3463FDF47035DD8FA44C12DAC12B525241EC7ADFEBD3D37B6E6DEA669A5AA96CA0850246FA8D7CBD5EFE76694EBA624E55282BA0B72DB7F206D7816D9B1D2B04F617EBF9C3BBABDD25B7FB31CFE2D674429FC81FD229E84FA7E67FCC45DDD4FF004AFE50FC54CFFDB57FF588DC0DAE36DBAC70D502D9556B7E51FB4540CCA00B1B8736DCC2E3D47E221FF51FD2AFFEA3F68E58F23EC6171EA3F18E1427904292A6DFC23F40F06235047A44625645FF004ABFFA9FDA3884322FFA55FF00D4FED088DB6BDF7BF4F68E1D693958806E2C7576D1BFB6B12165615F95F6040B3FCDF51F3BC44E816B2AE6D73DBA5FD6DFDFEB1C3CC55CA6C4BBF3D9ECE0B336DE71284959B9045EF720FB6FEBEB12EC3706F7B13F3FEFD07B44C4CD9A9041B0FCB70EE3DB7F7B4542539370CCC1EDE9F2F3844B89908421084210842108470C390F6842396034004239CCA6672DC9CB7B4211C42108E18721ED08472C06800842108421084210842205E83CFF004308E5AE1ECE1DF5B449412C0B97BDDF5BC4AA4DFA75DBBEC47BDBE7172934489D97C612ECF7D398B9DFEDA27A4A7C24B16E658E8C7AC100806FEBFD8453D6530A699902B303BFE9B1FBD6232413E1D36FBF389A29238842108421084210842108421084210842108421084210842108421084210882BA1F91FD2264A4E79884FF00516E5AF5DBCF68E46A1F988E3B6B595805571F4EC3E87A6FFDAFB8B97E0E4A54332C0F50C766BF96FD4C4150024A5BC232BF57B39BBFA73E51D2F30CD72568B313587DE4B13AD214B48490B71764937D0E1580761D1207B0119B70F61F87CC9D2FBD4A549CC3307B9D34FB23A9313A813DEACA5F5209B682EC1D98FCCEA7CACE9ECE9C7F4E7552CF4F95CCB6B50986D6DCB24A2C404923969209B2AFB58DBE71DA88E13C2AA80525196528032C84BBEE7507A137EA778EC0C27875388A0952012860599C72F4B6BBDB9C73D8E20316B607316C2963A29694E927D48414AADEC2251E08A004325C3DFC21C8E574B0E6EC79345EBFE13288632BDDFF0042639E8E223168B0E553DDF936FDFF00277FCFE10FF85503969674E482C5ACE320FA7CE38FF83C8FFDA1FF00EA8E627889AF1DDCA74993FD44158DFB91774DAFBD81E9DFA448570252E62404B13A143B7470CE7CAD120F052038EE880346517FAE9C9C9DA2A0E22AAD6DE42541F659DFFF00F431C7FC1246C847FF00450FDE38FF008523742FFF00B3FED1599E22AA41C4F3241829DEE10A5157D005DCFBFE30FF0081D390C5097246892033877245B778826705A424912D479B927E435DA3E99E240B4805CA5DCD8136E60B7E040F7B778E7FE03487FF004D3ECDF48A43C18F709581C8001AF7D4751F2D62238932403FC993D3FEE73FFF00A888BFE0549FFB52FF00FAFF007887FE17FF00F57FFD1FFF00AC4E9E24D0010AA484A8F4B1748B7AFDF3BF5F95C7BC51CDECF24CC9998494948B064FEEFCC1D6DB3344A5706AC28069BCF2B0D35170966F26F9C54638919353C84CC534A50B296F512BB24AB607EF5B63EE2D6EE3A97C012E5A484C84120153006FCDAEEEDF3BEB12EA3850C896544CC0078B41D5C7E50599BD5EF68F69C038D67717373534ED37E12525EC65DC56B027011B58A9442AC00FB85277F9475DE3F81D2D01CA152D6ACA4A909FFD3531F09D5CEE6305C4902996A4070C7A3060D677F9F3BDC47A5475DA9B3298300486F23100B81E42110C7308421084210842108421084210842108421084210842108421157452D136A1085B6520BDDB6D5F9F9D9E21507077E508A8ACA60951EEBC403B005CB7521DD80E9E8F14EA396E4E8F6240E4E2FD43FCA267026CAD21C0509D487824AA51D5752DA976B85249293658B11D46D6E6870CC4A7A8193266292A2D649CC9E4416CAE7935B523734AA9E527503762C4B73F26DF4D75DE06C52855D254A4DD6947DC42AE4593724D8A4026EA26E7D223C430EADA29894564B989528050CE18B17BE809B86E51554B34CD4924D815002DB11BFABF918845BFBB1FD27E7155087763FA4FCE108910842108421084210842108421084210842108421084210842108422045C103B8222396485A48D5EDE66DFE6391620F2222921AD26E55723F4DBEB7DA2A26098BDEEEF63A740FA036D39441500CDFCAE1C3176FBBFC9B483EC34FDCB8D2564A74D9449163EC763F845CF0BC427D04C0B5A8AC0FE51EFCFCB6D5E14D9A4060A29721F736BFB5F93EE3945A7672E5586F5E27A63284B639AAA925B4294B2494A99B252ADB60EDC80476ED63DD3C25C4E2B91329CE6409646472C94E6706E43DD835F68EC8E1FE2F95403BA992332940242C162AF7B5983DB7D22D45D65A404120A54EACA1011F7C1EBB83A823616BA9247A08ECBA7CD34FF00DC16B904DBD7426EDA476A6178B4AC492081DDB80439DC8DF987B5B7222A27992E2E97DE4D86E0F2557B0DF7E5DAE3D07D2F13E64A50BD9CE803936DF5F367F2B08BE2A58480A05C38B1DC7B6FF6F1497A1775595A95B95123727A920003DFA7D00885339831290536B9EBE7B6FB08A895534EA013DC051000243DD981E7777DDA29A5094DC6906E6FBDCDBF388BF1096B94D9C0BFDB8F5E6C62A15329C24114E492EC329F9B3DA26BDB74A520F6363FE7F7D6099CE43104EAC35FD6E366F38A7554485FF0C53B120DD988E841BEB6BB74D6F15A94E0B288B6DDBA81EBEF7BC4D336633B11B5C0FD2204CB945DE501E96FA7588210857F52C01DC116DBD361FE3DE39CE0302468EE406F73A7AF9445DDD3339091EDFA0814A41002B5A55B022CA5155FEEE9EBB5C1077049DBAC45F8C44A494E54A88199DD80E6E4301A73B5F62628EAE6D1D302B64121DDD81602F67D75DAE3CA3DC72EF27EA1891E96A9551BE4D212A0B5A16DA838EE92952528374DAFD0900DAF18763BC532644B5A5082149046641D1C31D8FB9F56263AD38878B68E509B2134C92B214CE7CD8916240D480C5CF38BDEA451E4E9920CC84B369665E59094CB06C6952481625761E706C2DD3B93D76D7EE21C515553A629198249B826F73CF5773C8474C620B35F31531242492EA6701DDD92092CDD5F6F28FB31886B016007202108E6108421084210842108421084210842108421084210842108422A2950A9934252ACA482DD6DF284401BAB49DBA6FF0087E978BAD32849AD952668EF5C82A3EA4FB3E859ED7768A69D604B681C7A97BFADBCBA45897890F1278C784EE15F1BE7360612B315DC3EBA1B32F293AD972415FCEAB92746428B616DB9AD954C97964BB6581A40178F41BE18BB20C1FB4DC628686B262A9A9D6B69CB42506714243A84BCE952412CC145045C13B88C7EB2A4CB4ACA402A00B3BB13737662C46A07CA3D5B838CD6C419E7C33E4DE6BE286E5D188F1EE15556EA6894416E544C26AD5291FB24A96E14A4B7248362B5106FBF68EA4F8A4ECFE9B8538D5585E1AE645299B25248016B44A9935292A648198801C8003DC0022AF0FAB5092E50E4B1243B3903CCEB6009DF6D4DCC8075142BCAA1DB620FD446A5544A994E48520D8B69FB6E3F43A45C056390326BADF4EADC8FEE35113F2FDFF2FF0078A235045F2BFA1F5FBE5E713D33D2A0F6EA1EE3D37FD629FCE24C4CCE7FA4FDFA42E3625491BFA8BDBD6DE91C3EA18E8FD3C9E22049D9BEBECD113A7B2813E900FB86F507E43488988D411E9108E6388FFFD9, '1', '2021-10-06 01:19:11', '1', '2021-10-06 01:19:11', b'0', 0); -INSERT INTO `inf_file` VALUES ('8448cada8c714e4ab61f521c8da21990', 'jpg', 0xFFD8FFE10DFA4578696600004D4D002A000000080007011200030000000100010000011A00050000000100000062011B0005000000010000006A012800030000000100020000013100020000001F000000720132000200000014000000918769000400000001000000A8000000D4000AFC8000002710000AFC800000271041646F62652050686F746F73686F702032312E30202857696E646F77732900323032303A30343A30322031373A32343A3135000000000003A001000300000001FFFF0000A00200040000000100000320A003000400000001000001C20000000000000006010300030000000100060000011A00050000000100000122011B0005000000010000012A012800030000000100020000020100040000000100000132020200040000000100000CC00000000000000048000000010000004800000001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD9FFED160050686F746F73686F7020332E30003842494D0425000000000010000000000000000000000000000000003842494D043A0000000000D7000000100000000100000000000B7072696E744F7574707574000000050000000050737453626F6F6C0100000000496E7465656E756D00000000496E746500000000496D67200000000F7072696E745369787465656E426974626F6F6C000000000B7072696E7465724E616D65544558540000000100000000000F7072696E7450726F6F6653657475704F626A6300000005682168378BBE7F6E00000000000A70726F6F6653657475700000000100000000426C746E656E756D0000000C6275696C74696E50726F6F660000000970726F6F66434D594B003842494D043B00000000022D00000010000000010000000000127072696E744F75747075744F7074696F6E7300000017000000004370746E626F6F6C0000000000436C6272626F6F6C00000000005267734D626F6F6C000000000043726E43626F6F6C0000000000436E7443626F6F6C00000000004C626C73626F6F6C00000000004E677476626F6F6C0000000000456D6C44626F6F6C0000000000496E7472626F6F6C000000000042636B674F626A630000000100000000000052474243000000030000000052642020646F7562406FE000000000000000000047726E20646F7562406FE0000000000000000000426C2020646F7562406FE000000000000000000042726454556E744623526C74000000000000000000000000426C6420556E744623526C7400000000000000000000000052736C74556E74462350786C40520000000000000000000A766563746F7244617461626F6F6C010000000050675073656E756D00000000506750730000000050675043000000004C656674556E744623526C74000000000000000000000000546F7020556E744623526C7400000000000000000000000053636C20556E74462350726340590000000000000000001063726F705768656E5072696E74696E67626F6F6C000000000E63726F7052656374426F74746F6D6C6F6E67000000000000000C63726F70526563744C6566746C6F6E67000000000000000D63726F705265637452696768746C6F6E67000000000000000B63726F7052656374546F706C6F6E6700000000003842494D03ED000000000010004800000001000200480000000100023842494D042600000000000E000000000000000000003F8000003842494D040D0000000000040000005A3842494D04190000000000040000001E3842494D03F3000000000009000000000000000001003842494D271000000000000A000100000000000000023842494D03F5000000000048002F66660001006C66660006000000000001002F6666000100A1999A0006000000000001003200000001005A00000006000000000001003500000001002D000000060000000000013842494D03F80000000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D040000000000000200093842494D040200000000001400000000000000000000000000000000000000003842494D043000000000000A010101010101010101013842494D042D00000000000600010000000A3842494D0408000000000010000000010000024000000240000000003842494D041E000000000004000000003842494D041A00000000033F000000060000000000000000000001C20000032000000005672A68079898002D0034000000010000000000000000000000000000000000000001000000000000000000000320000001C200000000000000000000000000000000010000000000000000000000000000000000000010000000010000000000006E756C6C0000000200000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E670000032000000006736C69636573566C4C73000000014F626A6300000001000000000005736C6963650000001200000007736C69636549446C6F6E67000000000000000767726F757049446C6F6E6700000000000000066F726967696E656E756D0000000C45536C6963654F726967696E0000000D6175746F47656E6572617465640000000054797065656E756D0000000A45536C6963655479706500000000496D672000000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E67000003200000000375726C54455854000000010000000000006E756C6C54455854000000010000000000004D7367655445585400000001000000000006616C74546167544558540000000100000000000E63656C6C54657874497348544D4C626F6F6C010000000863656C6C546578745445585400000001000000000009686F727A416C69676E656E756D0000000F45536C696365486F727A416C69676E0000000764656661756C740000000976657274416C69676E656E756D0000000F45536C69636556657274416C69676E0000000764656661756C740000000B6267436F6C6F7254797065656E756D0000001145536C6963654247436F6C6F7254797065000000004E6F6E6500000009746F704F75747365746C6F6E67000000000000000A6C6566744F75747365746C6F6E67000000000000000C626F74746F6D4F75747365746C6F6E67000000000000000B72696768744F75747365746C6F6E6700000000003842494D042800000000000C000000023FF00000000000003842494D041100000000000101003842494D04140000000000040000000A3842494D040C000000000CDC00000001000000A00000005A000001E00000A8C000000CC000180001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD93842494D042100000000005700000001010000000F00410064006F00620065002000500068006F0074006F00730068006F00700000001400410064006F00620065002000500068006F0074006F00730068006F00700020003200300032003000000001003842494D04060000000000070006000000010100FFE10DD2687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F003C3F787061636B657420626567696E3D22EFBBBF222069643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E203C783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D6574612F2220783A786D70746B3D2241646F626520584D5020436F726520352E362D633134382037392E3136343033362C20323031392F30382F31332D30313A30363A35372020202020202020223E203C7264663A52444620786D6C6E733A7264663D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D7264662D73796E7461782D6E7323223E203C7264663A4465736372697074696F6E207264663A61626F75743D222220786D6C6E733A786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F2220786D6C6E733A786D704D4D3D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F2220786D6C6E733A73744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F73547970652F5265736F757263654576656E74232220786D6C6E733A64633D22687474703A2F2F7075726C2E6F72672F64632F656C656D656E74732F312E312F2220786D6C6E733A70686F746F73686F703D22687474703A2F2F6E732E61646F62652E636F6D2F70686F746F73686F702F312E302F2220786D703A43726561746F72546F6F6C3D2241646F62652050686F746F73686F702032312E30202857696E646F7773292220786D703A437265617465446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D65746164617461446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D6F64696679446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D704D4D3A496E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D3232623834663439646366312220786D704D4D3A446F63756D656E7449443D2261646F62653A646F6369643A70686F746F73686F703A64633333616566382D343164372D343134372D626566652D3133623366363839326632642220786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D702E6469643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222064633A666F726D61743D22696D6167652F6A706567222070686F746F73686F703A436F6C6F724D6F64653D2233223E203C786D704D4D3A486973746F72793E203C7264663A5365713E203C7264663A6C692073744576743A616374696F6E3D2263726561746564222073744576743A696E7374616E636549443D22786D702E6969643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222F3E203C7264663A6C692073744576743A616374696F6E3D227361766564222073744576743A696E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D323262383466343964636631222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222073744576743A6368616E6765643D222F222F3E203C2F7264663A5365713E203C2F786D704D4D3A486973746F72793E203C2F7264663A4465736372697074696F6E3E203C2F7264663A5244463E203C2F783A786D706D6574613E2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020203C3F787061636B657420656E643D2277223F3EFFEE000E41646F626500644000000001FFDB0084000202020202020202020203020202030403020203040504040404040506050505050505060607070807070609090A0A09090C0C0C0C0C0C0C0C0C0C0C0C0C0C0C01030303050405090606090D0A090A0D0F0E0E0E0E0F0F0C0C0C0C0C0F0F0C0C0C0C0C0C0F0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC000110801C2032003011100021101031101FFDD00040064FFC401A20000000701010101010000000000000000040503020601000708090A0B0100020203010101010100000000000000010002030405060708090A0B1000020103030204020607030402060273010203110400052112314151061361227181143291A10715B14223C152D1E1331662F0247282F12543345392A2B26373C235442793A3B33617546474C3D2E2082683090A181984944546A4B456D355281AF2E3F3C4D4E4F465758595A5B5C5D5E5F566768696A6B6C6D6E6F637475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F82939495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFA110002020102030505040506040803036D0100021103042112314105511361220671819132A1B1F014C1D1E1234215526272F1332434438216925325A263B2C20773D235E2448317549308090A18192636451A2764745537F2A3B3C32829D3E3F38494A4B4C4D4E4F465758595A5B5C5D5E5F5465666768696A6B6C6D6E6F6475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F839495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFAFFDA000C03010002110311003F00FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8E35D5BCC737C2D3C9BFBFF666A389DAABAAEB92D09964A9F7C78D5CFA56B736CD2C94EF538F1AA82F96F534916762EE10D78F8E112B54DEDED35BD3EEA09B45B992D25620CA14D3265239BD8EDBCD5E6BB286DA2B8BE79A375FDFA924D4D3205B0232DB5BD4EF199998E5459C58F6A9ABEA16F71CB9114EF9125B120B8F3A5CDA026573418AA583F34D616346AB5298A09A424FF98F2DD0F80D2BE18691C4925DEBD7DAB05B61522434CAF2C51C6FBA7FE7122F60D17CBBA84175B333D4D7E6329E172714DF5E6AFE7ED22CE1043865814FAAB5F118F0B9A26F8C7F30BF306DEE7549AE2C8889391A95FA71E1499BC4758F3D5037A77ACDEA0AB47CBAE4E30713366E12F35D43F302DA14901531CE7ECCA7C72C11718E7796EAFE6ED57516663AA12A0515431E99608B8F2D430D9A677E524F3FAA4F5A9AE5822D0750978B98B8D140D8E4C63B63F9843BDC13F64532431B1F1AD0C5DB916EE72D8E362656ACB7457BE4BC3606368A13F2553F7E5321BB5F0EEDD0B6F916C0141ADD0558F5385BE2690CC5536E98B682985A4527312ABF1A6F5C9F44527A6F5255114979C48EC4E424136EE70A2D2593E54CA2516432D265A76A6F6B5FAACACBE041E995F0B319DE9DE5BFCCBF37E8C54E9FE619A075E8A1C8FE18699F88FA4FC9FF00F395FE6ED08C0BACAB6A71A302D2BFC5B0F98C890D8323EA6F247FCE5769BE63B8449ECD62F50F5D875AE564360C8FA2EC3CC5A46B32DADF898514F2F4EBD72B21BF14F74FF4D7626F1F53F8A192BF5207B785320439FC4115A4693711DBDF5F5F12CE8C0D913D857B640865CD910BAFAE46A41FEE46F95909115A6CE4BB46B98FAC20D7214C643662170CF7323C858AFA27E2FA314452DD56DE2D4F4C9F94A6B1827AF862DF163FA65C8FD1C2C11EADCA80D716F09EC33DE42A6D1472A2824F861069AB502C331D3BCB3E55F3C412795FCE9A746D05DC6CB0CEEBBD4A9A6FF3399784BA4D445F8C9FF3931F9253FE507E61EA96B145E9F97B57919B426A6C402C4D3AF866C605D3E41BBE5BAFA5230FC32DB583B90724F865D8B930CC5BCB5A16375C55AC5578E98AB78AA8BFDA38AAA2F7C55A3D7156B155EADD315560D8ABFADEFF009C6EFF00D677FC84FF00CD73E56FFBA45AE5A39349E6F68C28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF917B754FE45FBB34FC2ED532A855A803C71E1551370C0E3C2AADF5A26361ED863155D0DC52840DFC72C2A39A6893B3D0124F8D7205B423E172F227A6C401D86D9516714AB5F0D52FD80A139193607916A21A49641526A722125825DE9F335C1F4C75ED96C434929D699A6C96C434DD0F639708B519B2F86D62F8446DC7EB1F0971B52990CB0D9871BE87FCB0F341D3236D0D5B8C6E3E2981A1FBF28E17231CD35F3479E9A06B8D356666080FC7CAA4D6BDF0F0B9919BE7FD5BCC7246F2B3BB10C4EC4E3C2994DE7979AD87666AFDAE9921171331B2C0F56D4F996EFF003CB045C5931D8EF2A483F765822E3C93012875EBB1C988B4108794A034D865910C68BA38D5CFDACB0048895EF171AE4C36479A0A470A7A6580362A4738A2F877CC49C775A4724E0D32149016B354935AD71A4A1DD6BD77C7853689173C4000D282981B835EBA75A0AF8D30316FEB00F53CBE780C5810510B7617A1A7CB21C2C68DA6FA7EA011872EBE39021BC16463520EBC791A11BF8640867128FB5D46EECDD26B2B9642A6A021A6408660BEA2FCB2FCFDD73CBED676DA8D64D3C301752BEE42FCCE56437639517E927903F33746F37E9D6F35B5CC6CC69C5188FE272B21CE195EF305FA4D63FBD6531AAF4047864086E8E4B486CAF94DD3C40F0427627A64086D8CD96A5DDCDA59B81C5A07EAC065720CA52B09035922C373792515250683B641116276C6D6D61BBE6F53302029E9BE2DF179F4113DAEA124A8F54249515DB16F0CA34926E2FE49AEE5291C6018F7A54F860465161EA22FDB4CB9B1BE11ABC42946201CC9C45D46A60F8AFF00E73E6C935ED07CAFE6151B69FEA733E1CB966C6127479A3BBF21B5802DEF21BB07F772A9A2F6CB896A8B7129F492423FBC15197E12C7338F7CBDA14FB8C555475C55CDD7156B156A98AB78AA8B1353BE2AB6A7C7155E3156EA7C7157F5CBFF0038D9FF00ACEBF907FF009AE3CABFF748B5CB472693CDED5850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91688D3E8CD770BB55732D29BED5C3C2AA125C2826831E155317408208D8E02155E1B85AF4C8951CD358A7AEC0640B684DB436F56492BD16B9596615B5884496D2F7DF6CAE41B2245BC82F22E370C08A6F82213221279612262C82A46E7E599100E3CCAE5B8127C2F41C732621C6949524D42354F4A234917A1AE47306A2535D3BCDEBA4425797FA536DCC1FEDCC76FC4509A9F9B4384B899EB24952C6B5FE38D39824C1F50F30477E480698D24CAD8EDC5C8D85474E95C9C766360A4574C1CF635E9EF930D6404B3D13EA5541F0229BD72C01A26023D4B200A41E5D969BFDD9688B498A9C8A643CC30A7422BD32241B4C601C9CD0D0D4622D78559E6DA85BE9CB031A4148391EBD7EFC95A3758ABD0572A31B6611B1823A838384A95415A9D8EDDA98F09415600537EFDB070962DFD589EDEE477CA8B782D7D5877207CCE16629B36E3C4570F267C214BD23C80EE4F4C2427802690DB9461BF5CA484009D470F214276A6FE232B21980A5CBD19290CC580EB4DE83DF2B660332D27535212DEE8FFA3C9B487DB20591D9EA7E53F3E7983CB371CF47BA75B588D42722361ED5CACD22322FADFF002DBFE729E486FECA3F324A5B4F43C6EB7AD6B403F6B2B2DF0917D9AFF997E53F30E976D75A2CF1C72CA0114615DFE9C8172A322F48F2E1BBD5F477844BCCF02EA6BE032B937028CD596783CBD6EAE486690291DF2A6C890F3BF35C434FB6B478C9AC8A0B530D37C4879A9BFB99670B1D41AED5EFF2C0DE0B228A4BA8602D3935603D3A78FD1912CE554CFF004DBBBDD461B5B6949F4D3BB6DFAF32313ABD48BE4F08FF009CBD8E0D47F29B5582DF79B4BF4C311B9F889E99B081D9D0E789B7E39EB9664FE87818D4B86E5F7E5A1C5029425A239806C20F8732B0726190DA1CF7CC86A531D462AAABD7157375C55AC55D8ABB15506FB47156B155E3A0C55BC55FD72FFCE367FEB3AFE417FE6B8F2AFF00DD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91745DBAE6B5DAA0270038DFBF4C557A007DF1B569937DBBE025217C042073DC654C931B4B9E50CA83AF638153ED2A660AE69F7614A367BA58ED6466DC57BE210497946B3748D33508EB930030322C65AED519B7A6D930C0A4B25EA976A1A6581AD2C9AE872FB4704D38D012DCEFD72B6D40CD37A94DCD07BE2CACA024DF7F0C56CA8140C8FF00BB32CBD8569F0F7CAB27369C922D18005B7B89916CE2B561340E5BAB2F4EB92C64B5D943DB5FDB89F5295B5385DAF559A094950D1CE7B04AEF99B8C2D95595FCC31E95FA5A2F2DEAB79369A4C971E6692CA54B64886DBBF1E1B7BE654698F1747A07953F25FF00357CD5E47B8FCC3F2CF921F5AF26DAC924BAB6B8AEDF686F20A01B713919D1482F2ED2EE9AFF0053F4EEAE9567B5774B4D35A8AB291B1591BF678F6AF5C85320537786D4C727D62D7D2746ACB0024AAB57E1A37BE16C1BA0A592333C1F5AB6956F6452D6B040A646283AFC2B8B2D91111FAC46DF5AD0357B7907FBCF3A594ADC97BBF4ED8D30F103505E5DC61A19341D524914F1B6B916725593FDF9C698D3094C2BC17577C9A69749D5DD17E004584A7930F1DB6C698198519259239ED629ECE48EE637F5EE6CEF94DAB7A0DF64D1E87010C6D165EFA492CFF437FCEC1AD7982636B06996E39B2843F0A8095272AE0B6424C9F59F2D79A3CADA9E9BA7F9E7C8D3686FAFA7FA33DD1786BC056A3985C85331262333C3A54F76F7BC648AB4B360D5AF80195D16C12513E60D2CD80917D45D661916331703F0A31DDBE818981642749BC3AE6906375955CC900F87512A429FE19594FE60222D35781D3EB68CAD1034926660015F9572B3129FCC840C7E65D1D24BEB4B581E196ED089EE402E021EE32070CAAD7F3211EFE61B4168AB6D299934E50F75301F184E8085EF90F02523417F34193E95ABBEB4AB7361A9FA4427EFD88A72403A53C6980E92498EA8047DBF9C7CB567070FAFC915C4CE561708580643F1127B54E0FCA49C886AA2CCF4DFCE48343113DBF98273C2842D0D36FA71FCA172A3AB8BE9FF00CBBFF9CDB4D1FD0B6D435C905A2AD18F0A9FF896425A434CA7AC14FAC348FF009CD2FC9CD42C53F4D798CACC46EA631D7FE0B043465C6FCE29EAFF00F393FF00939ABD91B3B0F33299266A44F22AA8527BD4B659F932D90D6EEC1B4AFF009C92FC948F548E1D6BCDBEB7D5488E20B10E0B20DAA581E9954B4843B0C5AC0FA4F4CF3168FABC116ADA4C424D0EE943D9DEF51231DCD3B653E018736EC9A8E21B326B4D5ED26FDD28E20EDB6D8D535DDBC63FE7231043F97F76F6EA5FD68D8B83BD681BAE646271B34453F1A350B93EBFD65BAC723023C3E239B1C54E8B53B294BF1309FB5C0E4332C38504337F1C2CD662AAABFC3155F8ABB15587AE2AD62AEE15DEB8ABB80F1C55DD36F0C55D8ABFAE5FF9C6CFFD675FC82FFCD71E55FF00BA45AE5A39349E6F6AC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90949CD3DF35AED52FB89CF2AF7C55B86E091D7E78AA21AE147461F7E02A39A924D50F534F0CA99A334E620B96D86F4AE054F2D6EFD2473D3C3154A750D59DAD254AF1F88648734179BDEDD33C8C49D8E4C302C72E27356DE9930C6492F362E77DB26D6A44FC66A69B7538CD38D42523B1FA72B6E435483D7156B155F63A7CDACEBBE57F2EC774BA6C5E65D66CF4A9755A8E708BA9021600F600D6B93C70123BB466354FD9DB4FF9F49FE51E9B35B5DF9C7FE725E596D2C19259EC276B48A07400311EA48EBB7C865808ADA838F7BBEA8D27FE704FFE70B7F2CBC93ADFE62EB5E4ED2FCFDA1F97AD1F53B8D68CE66458A1AB332885B893F4E5D007DEA4EFDC5F217E7E7FCFC07FE716353FC95F327E49FE4E7952E35AD3FCD1A73D92DB5DE9DF548AD1A421898DE956229B1CBE2A0D9B7BB7FCFBAED6DAEFFE7DEDABC11C097125CEA9E608E58A641C5CAD0F02C474D8EF91931E27CE5FF386BF901FF38ADFF3939F947F9A5E46D4AC20D13F3DE4D4AFA3D5B502693D8AA5C31B692CB911EA29FDBA74FA3229E2A7E6C7E75FE48FE62FE43F9FB55FCAFF003FD93DAC31B9934FF32509B7B8B752CD0949A9C492805403D7037465694FE5779EB49FCAEFCC9F267E62EBFA147E6CF2EE9F1490DDE9774291BF26A6F8B2E2EAFDABFC97FF009CC4FCA9FCF4F37697E48F21FF00CE3B5ADDCD7052DF51BD5B3AD9D9DB103D4066084034DC570B1E305EEDFF00393BF9B5F917FF0038B736896771F9223CD9E6AD663E3A258D869FF588BEAA48520BA275A9D862C38DF24AFF00CFC07F285102BFFCE28EA5A6B472F2BE54D1A4243F7A829818193E5CF2EEB1F945FF0039A1FF0039BFA5493F92469FE42D5B4CB5D2E7D04C660314D0D43332281435070B0326BF337F28BCA9F919FF003F16F267E5FF00E5ED82683A169F269B7D6F08FDE822E95988A3D41D80C89E4CE25EFF00FF003F7E5B6B6D7BF216FAED56EE1B8866F5D446B172F848FD803B9CAEB9B3069F945A4FF8720F3D7902F7CCBA4407CA305FC0757B66735684CAA5B90FF572BE8DAFDCAB4F397FCFACEEF5A9560F2669B26AD218AD25536AE12579540001F528C7B5460970F716278AB9BE8CF3FF00E497FCE0E7E5E7E5C69FE7AF387E5468DA6F90EF8441677470419BEC02858124FCF23C239D7E3E4E29B7CC49E6EFF9F50CE925A2F93B4A8B4E1113C84120527C38FAB5AFD3938C224F543E93FC95FC95FF009C13FCF1F2BEA3E60FCB0FCA9D1F52D0EC646D3EEEE9E378D870A93D5DBC32D18815DDE0B79E65FF009F5A683AA6B3A4DE792B4AB0D6B4B9A7D36FE25B7763CE0AAB0E5EA53AFB75C9C71041BA7E10595CE9716ADE686D3E258B449B5DD4A4D123AD185A191BD15A7871A65BC23AB5926F67DC5FF3827AD7FCE27E9FA779F3FE865346B2D425D52E61FF000CC570865F4A341FBDA85652A49A1EB8384364645FA0ADE64FF9F54F0E2FE56D1154776B7907FCCEC7843689C97DBEBFFF003EAD240B6F2B684EC4D14185C024F6AFAD80C026539232EB55FF009F5B229F5BCA9A1AB20ABA7A7202A3DFF7DB618E30D5C459F7E5FF0090FF00E7DF7F9C370BA2790BF2B6D35DE5F66FADEDE6FAB236FD67595941DBBE1300CE32931BFF009CC4FF009C6AFF009C4DFC9FFF009C73FCD3D534FF0021E85E59F375CE85247E5495A765BA92F792F130866DD857B0CA66221CAC5399237D9E1DFF0038E06E1FF24BC8D6FA85CDC48EB67037D52742BC18C62AC09DCD7357A900BB9C123D5F4B695A658ED26C48DC819824539F1281FCC5F2E5A79A3C9FAA5A7107EAF03F15EE7E16E99386CD59793F083CE5A73699AFEB5A5BC6D088677081C52B466E999F8CBA3D4C5283B5B59A9054AA1A5733226C38110866FE39364B315545FE18AAFC55BC554CF5C55D8AB5CE9B53157733E18AB7B9DE9D715750F862AFEB97FE71B3FF0059D7F20FFF0035C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EE4B96A57F0CD6BB54BEE6E4F2FD78AAE86E01502BB62AB1E41CC1F7C05211724A0FA7E1953247B5D0458CD771D302AC9756E0B4AE2AC5EFF0053332B28F1E9921CD058C5DDC9A1C98605209A72C684F7DB2618C96890713936B5093F7854786F8CD38DBF476F6CADB96AC542DF462ABFD318AAA691E55F3379E7CD9A1793FC99650DD799AF254BAD31DD8AC8AF1B7C3C69EF976201C4CE5F60F993FE70D3FE739BCCF6ED6FE636BAD4D0A7A0BA64974C55430141414FC72EA01A2CBF643F2F3F273CFDA2FF00CE0F79D3F27751D3560F3D6A7E56BAD3AD2D236678CCF22154058926A49DF7C9C764136FC52D1FFE701FFE72CB48B23A6C3E43D327E0C6E11A590B4CA587B532C0520D3F6A7FE70B3F25FF00307F2DBFE70CB52FCA9F37592691E78BBBFD6E6B3B02DD56EF8984D76EA01C892C0C9F94DF94FF00F389FF00F3995F93FF0099EDF98DE46F2ADA43ACF97B58B9B9BFF5A5741716D34DCA84568C0AD6981417AE7FCE7FAFFCE51FE6E79534AF35F9F3F2AB43D1FF002EBCAD1B32EA1612BCB7E1CA1F51AE118D5072AD074C590953F38FFE71DF41F23F993F327C9F61F9CBA9DDE9DF96FAE3B23DCB201688E1C22891CF40316CE27EE04FFF003953FF0038D3FF0038DF77A57E43FF00CE2AF97F45D77F31FCC37D67656F7518A6957724DF097B9BD427E3626800C58195B18FF9CAAFF9CCDFCF4FC80D7BCAFA67E687FCE3DF94F59BED56CC3691AFD83497715B5C16A2A4323861EA03B85271636FABFF002FFF0038507E40CFF9F1F9F7E46D13C8B05BDA9B9D3F4E4445935042AC10CEACBB48C69B0C5812FC5DFF009C15D5A2D67FE7381F58D3AD6DADAD7CCBAE5CEAD690D688B677723CB1C6941D830DB16264F56FF9CB6980FF009FA17962F26790A01A3C56CD08AFC512BA95FA2BBE25B81671FF003F8D92E6E35DFC86B458964B3FAB48F6A53790B537046408641F93B24769776F1C5A8D8BDC5E5005AA9AD32A21B8153B8D1ACADF59F24FD5E27B49CEB5640015A8FDE83B570034CB9BF793FE7E412ABFFCE01F962299A79644D5F458DA471425D6A77F6DF2C8C6A9818EE5F822DA1697A868B63A7E97A1869E3B413DF5D92F5F5075EF84367007EF97FCFA0C347FF38C9E7F8608E44B9FF10DDC61C0FDA11353EECB049AB806DF17E12F9AB47B1BAFCC0FCCEB8BA8DA7BDFF156A70A3396A02262C6BBF8938253D9B3806EB5E3B64FAAB416104933FC0DC4D7EC8CC7F14B1F0829A683A75C3FD616C230D727F7CA091B8F91C7C52918C27967E5AF2D4C04779A2A4DE22AFF00D71F14A784226DB4BF2FEA7AAD9F93BCA1F97771E62F34DF4C9FA3B4FB38E4964E75A091954D4283D4E4A323252007E937E427FCFA63CE7E6BD624F38FFCE42EA16DE50D126845CC1A268937AB24A08A94B9E6D5414EA2B970B69343DEFAFBF303FE72AFFE716BFE708FCA571F975F92DA2D9EB9E72107A561A1E8CA67B496FC01F15E4C0B1526A6B4C8CA7B338C093BF27E59F9CF5FFCCAFF009C81D6EDBF31FF003BB537D6EE21B8F5743FCBD8E42FA6D9467EC96E276A53BE60E6CF5C9D8E0C3B6E1F657E5BFE6369D731586871B246D63122D22A1B745A50468C07ECE61711939F5C2FA534DBE8E15925460EAE054D72328B7C24CC22D5AC61D12EA696CBEB7CA290B102BC7E13918AE4E4FC43FCFDBED3F5AF3EEAA2CE0F41D256DA94A6ED997093A7CE1E1FEA48CAB1C8FCFD01C57D8667623B3AF229D96A1D8ABB155CBDF15546ED8AAC1D3156F15770077AE2AEE03C7156B9D36A74DB157733E18ABFAE6FF9C6CDFF00E71D7F208F8FE5C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D34BC51D4D0F8E6BA9DAA5D757887900C2A71A55B6D7229BB0AE34A897909F881D877C041506914D7085128E2A32AA2CB88285DDE7100A372E23B634578825125F3B6DE3DB0526D0734E0296AD08C9008291DD5D541EF920C0A4C65777FB27E7930C485FCC81BFD3930585174720E677DA9824530148B0F5141BE41B2D48B91D8FCF15B6BD4C56D917917CEFE6DFCBCF3E68FE74F25D8DA4FADE8686E21BDBD1FBA4E07970AF89F0CC8C3C9C5CFCDF7349FF3F5EFF9CA09EC6E2F7F40F96EDEE2C9C5CDC4A63A3948C50D169EDE39750B71DFAE1E46FF009C8DF3C7997FE70D7CC7F9F77D6D65079CF43D126F318B287FDE7668D4B05229D0853DB26021F945E58FF9FADFFCE5A79B35516DE55F22681E62D56E938AD859DA9967DABFB0057B78614BF5BFFE7113F3E7F303F3EFFE71A6FF00F34BCD7656107E6269DAB6B5A78B38978242DA7FD8475A7C2DB1A8C04354DF9BBF941FF3F0CFF9CA9FCDFF00CFA87F28345D1BCB916A1ABEA975A7BCB321458A3B4765E4CD4EDC70522934FF009CF1FCF6FF009CA8FCBB54FC9DF3CC3E4CD4B45FCDAB77FABC1A0167BE8560F85BD6561F0D6B51F2C5987E547903C85E7FFCE1F31E95F90DA75CE97A4DCC5234B6925EBFA51B3F2E410B7892705864FD16F257FCFA23F3F26D7B44BFF33F987CB7E4EB2D2CACD0DEF97A57FAFA5C210D14B5634E4AC01AD70A0BF577CE1E75FC81FCA3FCB5D0BCB7F9F7E7DD07F32353F23411CEF26B7325C6AD737D0F499537AB531624BF32FF00E7323CE1F9DBFF00392DF975379D3CA7E4D9FCB9FF0038CFE50893559ED75188C37B3C51FDA96341406234F84E1A60FCCAFC9CF2BF9BFCFDF9CDE47F2C7E5B79864F2479AFCE0F1D9F917558E43088E40A5C7AAC3703883D31E140897EB27E5E7FCFB5BFE727B4DFCF1F24FE6C7E63FE61689E709343BC49F53B89E691E765414DAB4AD6B5C69B86CC2FFE7EF9AD68DFE37FC9DF2EE8BA9A4BE67F2DDBDCBEAF6D237C36EB22928CDE0180DB2259805F3C7FCE28FF00CE04F9B3FE7277C8B379FED3CEF2E942398C3C1E42073EA05011EF913BF26775CDF5A68BFF003E80F35DB6ADA36B1ABFE62B5E3E957F6F77F57E65AA20903D055BA9A5300891D14CC17E927FCE507FCE31CDFF003909F913A5FE4E5B6A8FA49B39ECEFCDFF00EC97B4D954EFDF2C0C0CC9DDF9B23FE7CF5E6CB5D3445A7FE68CD0DDBB5651EA3052BDD766A644829F10BF463FE710FF00E717AF3FE717FF002A75DF235E6BF36A771A95F4DA9497719F84348A568373BEF954C90A245F9F1E67FF009F44F98B5AF37F9975FB0FCC06B6B3D7B50B8D4C42F211F1DCC86460C037515C4094BA289D17C03FF393DFF38B1AC7FCE29F9FBC85A4EA5AE9D56D3CC32395915890415F72727E1D06CF11E5115ADBC0BC0ACCAD3B3189E9B75DE990E109E22AF02A25CA98A4775EE7B60A0C6CBEB5FF009F6E24C3FE73B742F456393FE752D5CC824EC9C7E265F714DB2E8061225F657FCFCFFF003C3F35FC97E6DFCBAFC96F2179A27F2BE93E74D264D47CC3E6289FD3B9611CDE998B9D3BA8E9965048912FC9FF002E796B4CF2F6A1746D8A5FCB75704DF6B7A99ADCBC86A4C8A6BD77CAB200DF025ECD06A30454B7B39648D29FBFB81D251E0C7C335D962E7E29109E69570F65730DF69E56CA20DF15B45B4751D5BE6731E31A72B8ADF587E5979ECDFABDB5F5C28E2005E47AFE18261BE05F56793754B6B9B7BDD2DD11E3BD8D979B741B532B00B39BF217FE726FCA5FE19FCC1D4EE238EAB732332D3A1A96E999100EAF5043E588DA30F351BE22DF1A9EA0E67E2D83AD9157A1F0CB98BB7F0C3452D12075C08B5CA46FBE2AA8C46DBE2AB01DB156EA3C715773A6D4C16134EE67C31B5A6F883BD7AE3687701E3855FD72FF00CE367FEB3AFE417FE6B8F2AFFDD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87A96FEF941ACBF8E623B3B0963DF5F16DA5AE34B611515DDF541F571A5D9318B53BD42A1E4AA7ED2E0931927706A3CC0E9BE52D61166E7638B38A5E6EBE33D4E2D8103717049C52833FBC23155616C42F21DF15434B1D3B62A868D7E36F0F0C5894746A3DBE8C582BB461BE43155168462AC93F2FBF2CFCE1F9BDE7FD1FF2EBC9776965A8EAF19905C4E6900A1A7C7976271B31DDFA2BA47FCF9FFF003D7597F43CC9F997E58B4B688049A0B3123CA57AD18AEDF7E640F268B7EC4F907F217CA1F937FF0038F179F955E75D6E26F23C1A335AF9A359B87280447FBCAB9AD12872616DF1CEABFF003963FF00381FFF0038BD6BA743F96BE5BD23CF9A8D847C5755F29411C972838D2B3CEC2B5DC8241C905B5BFF003EB4FCC58FCF1F979F9AFA45BDB470DBEA3E63D675CB68140E5026A2EC544B4EFF00150E4BA2F0DB17FF009F7DFF00CE324FF963E63FCDAFCFEFCCDB44B09FF4B6ACDE5AB8B8F84DBC31CECCF23927F6C74DB010CB81F96DF9DDF9D7FF002BE3FE7253CE9F98D6F74D045A7CCD65A2E9970D50A9033C3CA01414E4054E56436C616CDFFE712FF28FF257F327CF9E6FF31FE72FE7149F963AB796353B69BCBCB6F75F56B8942307356F0AE459786FD51F38F93BFE71CFCE8D7B3AFF00CE71F98B48B4344BB5D3B5DE01005028483E032A32A3CDA4E2277A79DF977FE7DABFF388BF9C724FA9681F9DFE67FCC6BB8EA6F35A1A8ADDB0A750CEC07864F8C745E0A7D95F97BE4CFC8BFC81F25FFD0B3F99FF0036D7CCFA7F9B4496BA47977CC577EBDF4905C8A0B58A951C00FB2B931913C07B9F1A79AFFE7DDDFF003895F947E615F32F9A7F3CF59FCB2D465BD7B8F29DF0D405ACB64ECC4AADAB863C4A5683DB26269AA1C932B9FC9FFF009C6DD4E4B4D31BFE73E3CEE249C520787CC4435C9EA55985795326770C385F15FF00CE607FCE3DFF00CE35793FC93A9FE677927FE722AEFF0035BF320CB15BDBE9DABEA02FAEAE854A30AD6A780ED95C837C075A7C55E4DF31FE71792B429EDFCA5F991ADF923465E12CD616174D00776151B2E634B6673887D0DFF38F9E6FFF009C92F3EFE7CFE58F92FF00E576F99F50875F9E3D66F2CA5BF77A5BD9C80C9148A76A3807614C8F38DD72712517E82FFCFD9BF3BBCF5E43D53F2BFC95E46F376ABE50D47CC9A7CBA8CF75A64ED0168E297830629BF6F1CB9B7146F67E4949F9B1FF0039096D688A9F9E7E6F8AD66FDFCB72DA8CA013ECD5AFE382DCA9C283F6FBFE7D73E78F3479EFFE71CBCEFAC79EBCD5AC79AEFB4CF30DDC2BA85EDC34F27A0B192A159EA695A9EB8251704737E2FF009DFF003E7FE720AFBF30FF003022B5FCE7F34697A7DAEBF7D69A7410DF3A2450C729F4D68294016836C31A05CD8E332890C035DD5BCF3E67D574EF30FE64F9EEFF00CECFA07C7647509CCECBCF614AE4E73586911714D00BE54BA9663752A97D3E2AFEEC022A6A3E5989293951D3D2B5AB7A48ED5FDAFE3862584B1BEBEFF9F69C9EA7FCE75684C3FEA4ED647FC933991170F2C69EDFFF003F6FDFF3EFF26475FF0070139A7FD1C60916A897C11A8C06541DF8C9CA998F22E5C0A7769767EA8B08FD9ED9448B971679A34DCA08E393ECD77C85B75DB34B4D4A5D2EE2196CBA0209A64245CAC6FA93F2F7F32121B8B35B9702BC565AFBD3DB220B64F93C6BFE7316D6CB516B1D6AC183B3AD5A9F4E64C0BAAD445F9DD35A43EA99631F13EF2FCF2FE275A614A6E782D075CBE05690E243D3DF2EE882BC0E79596B937C78ED819479378B2762AEC55ACC79736D1C9BC4312578CB43592EEB920C097F5CDFF38D9FFACE9F905FF9AE3CABFF00748B5CB87260F6AC2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF864BB048AACD51DB311CEB4BC2B147612EE01C56D17621DC0AC98ADA65E8307525EA2BB8C124129D5B45D38F4CA501306040229D716C8A58E28E49D862D88571C9F6DC629548E36A8DB154D235AAD08E9DB1541DC42687E1FA7154A1D5D0F43BE282A91C8E0F4C58F0A3519A9BEC3B62BC2B8891BA2938AF0B21F2279EFCFF00F94DE7DD13F323F2F2682DBCC7A3AFA3682ED3D5818B1AFC51F7CBB1CA9C4D40DDEF1F99FF00F39CFF00F3963F99305EDCF983CE163A19D22DDC48BE5D88D8BAB28AD1F89353F4E5DC40971E9FAFDF975AC7983CE1FF003EDFFCC2D67CC3ADCBADEAFAC793AF6692F6F5CCACAEC87A96F0C9476B5A7F387A7BE85A5F97E686F0C4B71A859A08A7863264776DF812A09AEFDF240AD3F707FE7D29F951F9A9E58D67F327CEFAF794AFFCB3F979E6FD06D2D74586F289F5A962209786B4A13D6A72D06C289D3D0FFE7EADF9D7E75FCBCFCB8F2D7E4FF95F4E9747D37F3126922D63CDB6EA5623146D510C6CA2AAC4FDADF7C494F1EEF91AF7FE70E3C83AA7FCE05F92BF3AEF2F5BC95F997E5B8A7B89B5A998AC37BEA48591645EA49A0A13EF9592D8323E2BFF009C7CFC90FCC1FF009C9CF3F6A1E5DF285F695A3F99A0478754D4EFA15781907C3CD50EF5A6F91B6632ECFD44F20FFCFAB7F26BF2AB40D53CD9FF003943F98B1EAF1E9122DD31D16E0D85B451A7C6C6757AB301DE83A60113F0419DBEF0F30F9D3F2CFF00297FE7157CDDF985FF0038E51E8F77A2E99A34D3E87AB584002CA507C25DB882FDF7A647C2A533B3BBF9ABD5FCC1E62BDBFD3BF38B52F3E1D5FF00332009E6CB79656692289588A59C486BC597C06110A62723F717F317CA1E4DFF009F8A7FCE1B683E61F29DEAA79DFC9B6E93C371250BAEACB12ADCC53746E24D763921162676F3AFF9C76FF9C4AFCACFF9C2AF256A3F9DDFF392BAF68DAC6BB25AC8348D2EEE1F56DE1050845489C37C66B4AE4B8D1C4FC98F3C683E4FF3F7E6A7987CE9A0F95AFF00CB7F97BAD5E493E91A34D227AD21690B17B72BF654D4103C32B3367E3523BCC3368DE5ED38437CCF631C29EAC4D72DCC48631544A0AD49A532A3BA7C6B7EAA7FCFAF3F21AF74CB6F31FF00CE577E62D9AE9F1EAD6D2BF93BD61C560D302B7AF32F2A5140527135F00C38ADF0C7FCE507E6BC1F9E5FF3923E60F3559336B1E4BF277ADA2792A590F34B9B5726B3475EC1AB91F136761A7C24EEF13D4A2B98216F556DEFED9374B08928CA3C0D76C7C47272E2D9FB2FFF003E9130C7FF0038CDF98534B0936D279BAFFD6B75D8AA08A9C7E8CB89DBE4EAB83D4FC42B8373FF002B0FF346E6C618E5B6B7F36EA8E7D75E4157D634041F0C864950761A68F34C66823B9FAC35E7A572978ABF0C0BC42537E99852CCEC052AAA97948E11B154E30923E3000EC721E2309CC24B3CE90432F3902146A3D4F427A65F09383972D3EC4FF9F65C7327FCE717971E44204FE4DD65E13D792F03BED9990E41D74F2713DD7FE7ED2449F9FF00F92E10F22FE5F9CA7B833E5732B10F862E5828B84A5655AD5331E45CBC6126D3AF59262937EEF7D81CC79172E2F55D2984B0523352AB5DB204B918E36C8F4C9E559024919604D2A72B949CA80A679663EAD494CBE9348414FA32024DB241F9EDEF35FB18ED9C35C431A101FA819938E4E0E585BE39D634AB9D26FEEA39A268D2662D096EE3DB2EE370E5898E354B6FF7E6463938D38D34D18D88FA73281D9C5915363C7A76C8940709053734381B03B9A78E2AB81077071575478E2ADD3C329237656EA1F0C900C495DD865803592DE4A9812FEB9BFE71B3FF0059D7F20BFF0035C7957FEE916B96057B562AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF86BB8802C67311CBE240DB460B32F63B1C57899159D94483A7CB15E25595139003AE465C97891F6DF00CA9215659878E2D914A669013D6A7B62D81411BE21E18A519137BE2A8C57A6F8AB52BD57DF154A6615A629014E35DFF008629A469140B8AD2262C5682DBA92EE182EA4897D5B636D227A6366F588F8581F6C944B46585BF40FF00E70A3FE70BFF0024FF00E723FF0029B5BF3279AFCCB2E85E6CD3F54FD1B7D1CF7CB1F2A8279716604E5FC449B718C2BA3F4B7F3B2EFF00283FE71B3FE7103CF7F9456BE72B18EF350F2ECFA4796A059D267BDB87144850231219B975392053E1DEEF8D7FE707F47FF9C0DF27FE58699F9D5E7A920D17CE3645F4EF33E9FE629BEBB0472C5F6A58ED983503B74A0C9DA38084AFFE7217FE7E75E7BF365C5E7907FE719F438FCB7A1D9BB245E63302FA77D68A6A9F554D84551B9A76C78E9A678492FBA3F267F36BF20BFE73B3F246D3F2E3CE2F6ADE69D3EDE14F3568B7AC8B7B693DB95E53432C86A3D4707ECFBE0333C988C469F327FCFCB3F353CABE53FCBAF26FFCE267E5CDFDA3C1E60317E9B4B77594D8C5624344ACC8763215A1191E3A663097E57797752F3AFE5FF9C6C7CCDF943A9C9A0F9CF47B37B69ADC3304BA5917E290814069EF94F8AD834F27D89FF38B3F927AAFFCE6FDA7E64798BF3E7F37350B297C93A92E973E8C3516B68AE39C65D8B46CE015A8A5732465003038E4FD4FB9B5FF009C5EFCACFC8DB6FC88F3D7E61E976FF96F73A61B09B4D8665F5F8B1DCB4D11635DFAD301CF148C322F85A05FF9F51FE534B65AAF9524BCF3E5F69779EB5A587D6E6BA592E54502399556AA41E94A644E701B069645F0D7E4CFE707E71FE4DFE6779E7F353F27ACA7B7F2BDEEB5777FAA7901F91B67D325959D04716C81E8C454657F9A8B68D148F47EAA587FCE5D7FCE207FCE64F97A0F277E7DD8CFE44D68148A2F29EA333219A56D898E455E2373B03F7E40E51F51E5E4C65A390DBABF3FBFE735BFE7193F2E7FE71D6EBCA4BF931E6B9F599BF306493F44F97BEB7F5C7B6892AE2854B05A8A0C81CA48B3C9A8E9A47A24BFF3851F919E41FCF8FCE08BCB7F9D5E708F47BEF273A5EE8BF97374C527BFF4784AEC676A2B2AF75EE36C1C6472EBD57F2E62FB7BFE738BFE730D64B5BBFF009C5CFF009C7DB8B4B9D4AE02D96BFAD6931886D349B68C7096D02A1E279A93BAED8F89E9B972FBDC8C7A49134FCD7F2F791E1F2BD8A68176E65963AD2F474AB6E687E67304EA2CBD060D36C9D5FF00962CDEC2E4C7290D6F197694577A7CB271CD6DB9F4FB3F537FE7D471DBC1FF0038CDF9836D79756F682FFCD9A8A47EB4F1C6DC425391566046FE39B033B1B793CF4F170CC03DE7EF7E383E88DABF9ABF332F6D2329158F9BF538A57471C64549295DBED5731F3CEA2ECB1E2B0B64B2FAB6DC295ED9A83959F8450935A7AA80863180EB571D695CB2191AE78497A47FCE3F7E527E5A7E66FF00CE4DE8BF97BF9B2B736BE4AF3858DC5D45789762D544B6F1928399200E4453E9CDB69C931BBE4EB73E120D53F757F207FE70C7FE718BFE71AFCE927E65F912FE4935C165716D61ACDEEB114F0C16970A04CA23671527C4666125C2188F73F2B3FE7E3BF9A5E4EFCDFF00F9C87FCBEB2FCB3F30C1E6A87C89E5FB8B0F31FD554D22B812972BEA74AD08CA67CADBF1E3DDF31DAC4D05A3A188C69337A8439E4E1BFD6CC69173A18924F4C0BA048EF98E4B950C4F51D01855631D5C01954E4E4C31D3D46DF46944493053B8AE63CA4DA229835ADEBC6A5222C22EBB64449245AB5B5C4A54C33C541EF9938E4C4C2DE59F9A3E5C4BCB14D4ADE3DED50AB53DF2D949A32627CC778E915B014A4B5A1CC8C527559E348462CA23AF565AE6C22EB25CDCA390DFB64CB3839A315C836114B7D35C50EA53618ABB155C1C014F0C8916825AF572403025BF532603025DEAE5822D64BFAEAFF9C6B35FF9C74FC823E3F971E55FFBA45AE0661ED78A5D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF881BC880420F5CC3E20E424B0A857A1EA4ED8F12B24B50B4218D31E20AA8F08670CBB9ED809B0A39AA03C41076395F0B604BE5662C6870F0B30504E1C9AD31E165C6D29E277FA7070B21205171354FC382928CF8A83E78D2B8D698D2A12406B8A625A8D0D7A6D8B2B45B23300145698AD85F1EDB1EB8ADAA4A225884FC4CD3AB045B6AD0153D5BE8C429A2868F47BB86133689E66D47465BDBA56BFD32CEE6585789FB529E0402465832531E005338FCBB6FA84CE751D4B53D461B17E766D79772CEAF20E8C15C9030F8BDE98E11D11F0795F499EFEDAF6F2C266B595F85D69026222007FBB997ECB57C30F8C19F83BDB33B782934292BC7E8C4ECB672C2823F4231B2D78815DB6CA67985B64710EA91EA7E5A437115F68D25EF97EEA32FFA4F52D3EE5EDCDE06FB3511914E390F1E9B3C081768DE5FD3ED8FD72E26BBD7F5E0DB6AB793BCAF427B1724ED909E7B671C1001E86B6EF2DC590922A49044CAFABA1E2483FB240DF7CA8E50DBE0C52883F2E6D4EB125EC771AA59E917959750B0B1BE96DBEB128E858C64549F7CAFF3738F271A7A404BD4B4AFCA0F20CF6D75A85CD86A90996129159DE6A12DD0527BD5C9CA726AF24F9B762D180ED0FC95E5FD05E19F4BD0603769271769155C18BC68475F7CC796693B0C7A50F52D3ED674B48A28163B4912E1A66754142ADFB0C0751EC72BF1A4E6474B163FABFE5BF943CCB3DC5D6B1A12EA3716A39D98B522DA49246EB491402299911D4D7544B4B1287F227E4F59E81AD5C7992EAE2F3EB112D346B2D46E1EF7EAA0FDA0A64AD36F0C9CB59C5CCB8FF901D143CF1F94BA579AAE96F74992E3CADE648DAA3CDF6933C721435E6948E8DF1034EB9286B047CC2FF2782ED17F2EB4DF2AD9BD969566F737F74419BCC533F3993F9B9330E4C5B213D582092E54745188D833187CB62EAD134DB88792A75D40F53FC73046716D98F152B4FE598AD6DD2D6CC85957EC5CB0A807C48EF96C753109CB8F886CF269BFE71FC4B7D793E99E62D5B4A17B5B899AC6F26B783EB2E7E26F4A3206F99B1ED1A157B3A89682E5C54CA34AFCA7D23CB5A63D9C76B2DDDC475996F4C86AD3B7DA771FB44FBE5597571946ADCAC7A7203CF75FD0E64998087A1F8B35E32370D384AE0D338C0E49F4DD47C2C45687B6646292CB00609E67F2EBEAF0D8DC5DC93DB6B36CFC6DEFEDA5689E28C9F8802BBEE336DA7CDC2E0E7D2C65CD8A6A3A0EA36B2B45A7F9B35FBC8C7C715BFE91B85141D57ED77CCD3A814EBB369611E5F794CB42B39B42944DA3DD8824D64F3D75661EACAA4ECCBEA1DCE512CE1A2189EBB1D84090ACF0C6C2D8AF0F58B16E4DF2CA279A2E6431A0534EF527AA2D77CA2598391114CF346D3E7867B762945E42B944B286FC71E3E4FA7F44D352F2C21089CCF115DBDB293305B0E0932587CBA3D27458E8CC3714FECC00B0F0A439B17D4FCA324619C2D3AF41FD99930986420C0753D0A76B1BCB59D39C12EE58F63965F1726196161F1E79A3CB8D63A8CFCA32B6FC8956CCBC669D26AB1960ECBCB91614543C53E599F09874D381054A46F4E95D81E872EE265034A4F2F1343D698096C26DAF52B8A1557703155C411D462A8377F888AE203592B79FBE48062EE7EF93B6041772F7C9713120BFAF7FF9C68FFD671FF9C7FF00FCD6FE54FF00BA45AE066393DB714BB15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8779E6690D0E6BDC86E0B62C55A9D0D6B8AA7B1454C555F8814C473508693A9CB59A5E480C49E98AB4CE9E18AA1A465236C05945742699536F1047092A078E2B61716DBF8E15B08391B7AD701482A9130DB026D16ADB1FD78ADADE4395715B5CC6A062A9859FD93912D914FACBEC37FAD95C9BA09CC1906F8A6B0A0645AF8E565124EE5B5E56640EE320531482C21F4EE0AFF29DF2B9330CEACE0F56829B9C8368E4CDAC6C8B24629D3205B22F49B3B43FA35969534C81722095DBD8BF3A50F5CA8B97065B6766FC7EC91909392190E9DA51E60F1A6F539510D822C94E9842EE2B4182922294BE9CBBFC3DF1A6D10413E9C95E9808D9918A3AD6C100A53AE505ABC3569B4C47A10BB8C57C3455AE9E00E9D714786EB9D2B9A3F14DE9B62830A0F10F35689708F3388C77C945800C0A1B0924B69D5D00DF7CCCC658CA2C43CC9A64B085600D3332127032879C5F44D1D651B3014CBB8DD6E68EC9569E93493D373BE4096BC707D0DE5ED224BCD3238D81217E2194CE4EC2186C27B0F95E4120223E9ED98F22CCE9CB2BB2D12485E12E869514DB2B3272F498082FA3BC976F1FA31C6CBD80C00B9B2C4F5CB6D22065A85FB5D72C12689E35F75E5C826423D304E4C16838DE5DE70F28FA16FCA18FE12A4B003FB332B0C9A270A0F913CE5E598A54B82F0FC42BDB33232B755A885BE51D7EC24D3EE1A3E344EA332A05D2E68531CB9903428D5E99931710841897950E5A98F25656C595ABAC805315B5479401F3C56D2F91FE33BE4C354B9ACE7EF8B1773F7C55DCFDF157F5FF00FF0038CFFF00ACE1FF0038FDFF009ADBCA9FF747B5C9ABDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88316FCCD45335EE42630C7C17891F11D862AAE55A3FB5F862AA7CC9751DB08E6A164BD4E58CD00D192493F67C71552654F1E98AA832AF6EB91290B797134C832564620D6BDB1557E551B1EBDB1542C8AC687016512BE3246C4E0656881228DBC715B5E11CEE294C56C2AD0D003D7B629B4CACC1A53B9C896D8B20B34655607B9A8CAE4DD04EA089F20DF14C63AA7153E3BE56512656AC0D9EFE1902CA2C7A01FE94CD4D89DB2B9320F44D1A22C54D36A641B43D174E882B0E4366E9902D917A259DB936C4506FD32B2E44175B598E7F677AEF95972E0CB2D2D502EE3225C90C86CA10A46DB6574E481B270E8A474ED8D360012CFAA73AF15EA71A6C0109258B03BAD3011B3202D523B609F6B314B2E04D22B3590034AD714702362B38D4D08A62BC08D92CE26864A0DC8D8E2C670D9E75E64D0627B39A4352789ED928B8A214F04F4608659A2058B96A71236EB97424C65040F9A34E89EC95C28AF1CC98CDC1CB17806B5108838E3DE800CB3C475D9216A7E5FD3A7B8B80238C31276180CD9E1C4FACFC9BA25D0B4F4DA1019539357C331E591DBE1C2F4FD1740FAEC9C12352E3AD76CC796473469D93DC796E24291B4604886A6991E2B6EC7800667E5DD3440E9F0D0786112672C6F5FB14B68E3024AD587C3B65824D13C69CA476CD41BFB6D9609B41C4A77FA1C17F6B22320208EF97E39B899A0F913F337CA4B6E2E0DBC436AD4D3E59970C8EB33E2B0F827CFDA605F55B851D76FD599B8E56E935189E113865050F8E66C0BAAC91A520A4003B66406B05554D3AFD38A6D706A1AF6C56C36D20A7738ADA14B124EF930D6D54E28754E2AEA9C55FD837FCE337FEB37FFCE3EFFE6B5F2A7FDD1ED726AF6EC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88EB5527A8EF9AF72138584000F862AB580622B8AAAAC0BC4B6D5188E6A1033851F3CB59A058A952062A876E3FD715506A74EF912BC90EDF6B2B5E254AD00A615E25367618AF129FAA5B6F0C0520ABC75207BE0648911B1236E98A11A88C314DB60126A7E8C59C135B35DC644B745925BAED95C9BE09EC0BF08C837C559C5181CACA24CA6DC7A9694F6C814C52DB7B73EBF4EF95C9987A5E876C788DBB641B4727A3E9B685DA314E832B2CE2F46B2B6263094C8172609D5AE983903E395972E0C8E1B001694C8C9C909A5A5A8AF4E9869B849363682831A6626BA2B44A7D9C69B04D42E2D12A76C8C86CCC4B74B4DA1AF4FA3304B7DA6F69684F1D8605B4CC590AD298ADA30598F4DB6ED8944B7093EA9610CB613A9515E27F5620B488BE60D5F4C486FA62ABD1F7FBF260B19063FE62F4CDA08EA2BC72624E0E58BC2354B0E572DC96A9434F9E4FC470B82CB37FCB4D05AEB534E70FC3CBA91F3C066E5E2C54FB7B4ED02D6DED144680394A1CA2537678A349BE91A6AD9CA5F852BDF2894DC8B013A36A269D98AEDDB0464D9020B26D2ECD232A4AF4CB049259A5BAC2FC435053A659C4D134E3D3B7420F2C989341451B988008879061BE4E33A71F246D83F9B7CB36BA8E997521505CA93FAB32F1C9C2CB8DF97BF9BDA0BD95D5CC623A0DC8FC336584BA6D563A7C937D66DEA91D2873658CBCEEA0520658FD26E077D81CC98F27094F0AB44818ADA8B362B6B7AE4C2BB15762AEC55FD837FCE337FEB377FCE3EFFE6B5F2A7FDD1ED726AF6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A0B7896BB6D9AEB72116C388EA3DF1B553E05BEC918DAAA51C2F1E43082A94DDF21DF25C4CAD2AA495D8E3C4B68696564D88C78D6D62B926A41380C946EAA2367351B0F7C8DB2F0D50055346618DAF86B1E30C2AA7AE36BE1A82A146F886C7A6048852696F172DE98A784A64B1AAF5EA7A62BC255982D0D06F8AF0950E209D87CF10120F0A696686A36C0436C66192DBA1DBA6552722124FEDE2240E9ED951939312AB340C29B8391E69E1B647A78ADBF1EF4C8908BA46DB5848CE1C5284E57209137A2E836CCC428A5477CACB744BD434BB378594BD083E1954A5BB7443D074EB477A11403DF21C4E5420591431716F8874DB225CA8C29378D4505075C8916DDC48BB65A374DB0ADA6C232C36A615E3A44288D054A934C5B233B509551C6C0D7232E4DC0A10C04B0D866010DE3284DED6DD956B4191B65E222429077180C93C48F8684712363913365CD21D4D084954746072226BC34F9E7CCF02C124EED4249DA9F3C98935C9E37AF34B2B829F647519306DC3C91B49ECB467D52EE2855284EE49C375CDA31E2B2FA6BC83E4C86CA38E568D79F723227239F0C74F6EB4B13EA0DA8A17A1CA897240A4E96C569F0819598B2E1255C5B46801A6E3AE08C59C2242716691BF414A78E4D914D2283E3156D97240B4C85A36508CB452464F8DA4C54EDA89255892064E32B6990A446A33A3DABC22B475A0CC9C73A699C6C3E1FFCF3F2C7A51C978C8ACA63AFC3D7B66D304DD46AB1ECFCEAF30DB98DE4923015549DBBE6DB16EF2FAB86EC2259FD56E46B502999575B3AEE02A7CC7BE4830229631A9F6C242A91563DF224D32112570141BF6C226B54B4B81E3878969776AD7256B4B4B01D8E2B4FEC23FE71977FF9C6EFF9C7C3E3F96BE53FFBA3DAE4D0F6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A889788DF6CD7539086B99B8D6871A5538666618D2A20C8C0548E98D2A0E6FDE0A8FBB1A54BC2D1E871A540DC805F7F1C6954F9704AD37E98D3387344464BAEC298D37F120A6B794B7C24E34BC48A855900E5DBC71A5E257DA62140DD37271A5E24C625E031A5E256049231A5E2452AF2071A5E25F1435AEDF4E4834CF74CAD63A1F6C816706456895207BE51272E0CAADE1A2034E994C9CA8F25EE9C8D298C4ECD80A75A5C7521299125AA4CB9221146AB4F880DF2A2562CC7CAEB59D790DAB9025CB845EC16F10E4B45DBC731E5CDC880671A58A28DB22E6E309C2A0E75A77C5CB099451A918B021116F1FC74F1C5253A48A806D8B54954A2D3F8E2D9050E0B5A78E097272A28848158F4E9984425191A0414CAC8641A6A02476CAC86C0BD245515F0C810CC1A63DADCE1629187864405E37CFDE636699A6205687A64C313BB03B7D224BFB9E012A2B97458F876F5CF2D792A38E786478A8DC7C32333B2638A8BDE749D320B481005008194B7009FC50C75D862D8023046A0785316C010F20500E29A57B324134C2A426292B066C0D642A3CAD4A62D6421C5C145624EF5DB2C816B942D0525F173C589A65F02C0E379AFE66E996FAAE8570B40CE10D3F0CD9603BBACD5637E4D7E6158C9A7DFDCC0148018FF000CDE603B3CA6B31EEF25039027DF326F7757214D85F965D171A4E2BF2C99601BE3D3A65127231A9323576E9910C64A0C8D920C56A96AD0E58155D0035AE495FD83FF00CE337FEB37FF00CE3EFF00E6B6F2A7FDD1ED72618BDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A8F54702DC7305BD2695FD57E9424E2A898542F520E2A887914A15F11D71542A9AD452A7C7154BA7942494A6F8AA5D31323020D2B8AA22180135770569B8C5944EE8E411D28B8B6A1979198A114DBAE2AAF28F4D775E55F0C556DA71E4E7895A8C551EEEA829D7C062ABA08DA46240A0C55341198D6A472F962ADC13A92CBE99153D7161229DC101A06AFD19596704DECFED57C0F4CA24E5C198DB30740A053DF2993971E4ABE8947A7DAF7195B34F74A819650FD457A64496B3CD99C712CF2569C41A6C72B25B718671A0D9849148A139025CD84767AD58C01D5052847539496E8C7765768521A2952D4F0C0E66308812564340684EC3172404CE1734AF86282138B70052A7AEF4C5849368D948F0F6C5AA4B1C507DADB16D8286E7BF4380B9314744D4ED98A42551989208046F9590C8284C5BEEC810D810AEEDC0F6C8109972633AD4B5B765A9269D7234E3C4BCC24D39EE5DAA6B53D31AA72602D3FF2DE80AB74ACEA0EF5A530F139508BD86DECA389A3E294A0C04B394682747E08C7C3906B015ADA60E7885208DEB8B301184D462CC0404A18EDCA9E18B346D8802B5607160423FD440C7DB162434F32018B59096CD729E1B6374988492EAED549A0CB2326528B1CD465FADA3C4DF65D78D0E6CB049D5EAA2FCECFCE9D1E2B4D6AE233462E49047BD3377824F2BAB86EF96678C452C89D402733E06DD0E6145439004ED991170A4B8508AD29932C03741E19449C8C6DF25029C77C8863258789FD9C218A1D901AD053BE5A154591BB1A6495FD84FF00CE32FF00EB377FCE3E57AFFCAB5F29FF00DD1ED72618BDBF15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF89F0E3D33BE6370B90957306400773B63C2A893C9057A531A5414B39AF107738D2A6360038353D31E154BB508584E08FB23BE34A81F41BAF8634ADD1B74AFBE3C2A0A32D41F9E0E14F1353B32CAA4277A63C2BC49B7C0D082CBBE3C2BC484A537514C785789A1148F22D477C78578995C16E91C4848DC8EB8F0AF122B8464531E15E2524B74120A0EB919041DD3B55548C6525BA2BAD1AAF41E3BE5127320CD6CD78C60D329939514DA35E681B8D77CA645927FA70008DBE79592C3AB2FB280C8E1E9B1E99025CAC4377A3E8500E6A4FD39592EC71C5EA7A75B5694E990655453A11716DB172F105648A86A7BE2E5008C8F614C58108849CD7AF4C5A64994539D8E2D5269AE0B122BF2C5B20A911248AF42712E5453D8A9435CA2412BCD011E195C83243CCCBE34AE564360404C418A403C36C8D32E618B5E219BE06DFC31A6B1043DBE9C88EAC57E795C9BE019569D6D142438503DF2A2E4C4D0653115722831059C8D84C245063E98B00142301771D7BE2CC05766DB16C010ACA64AD0D08C595226D548A8AE2C486D890C77C5AC8519588077C2C084B26734EB954CA46C92DC826BBED8C249914B48F8C0FA7365824EAB54762F867F3DA0FF738E69DBFA66EF049E5B56777C797AA05CCBB53739B5C6E833F34BD97AE65479B8325C3651932C02ECA24E441AA0C88632688184315608BC47CB2D0AA4C8BE1D724AFEBEFFE719F6FF9C70FF9C7E1E1F96DE54FFBA3DAE4C317B6E2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88C69196127AED9570B9096DAC8649D09D80618F0AB26963050B571E15484A8697C287070AA610308CD41AF88C3C2ADCF2ACBFB1F11C78556B47C63E5C7B74C78552891B91200E27C7052A6FA64609DCD70213292D95E4A70A537AE0295CF6C586DB64789544DBB12AA13EC9DCF8E08CAD53386D49A129C6992B545CC68AA03538F6F1C6D54EDCB4A695C6D5368AD893CB9F4ED913BA2DB9A42B48C0DBC72A945BA324C34BB33248007EA6A4D328945CB8167013EAEA13EDD7BE5243951927DA622C90056D8D4E52609326436500120402BEF95CA34DB0C76F41D3AD38471ED94C8539B8F15335D2217F500029EF95172E269EA9A7A88E38EA2A69BE066237BA6E6207E2AEDE18B91134E238D3BF862DE26AF1C7CE9BF1C549B5AABF11F638B4C8A3D361F2C585371C7CBE2AD37C52364CED5796DE180B7C7226491D3F6EBF4640B3E25B27C3DEB4CAC864248095B96F5A65526D0508CFB78E479320503E887979D694ED9599B6844B5B86150DC699519338A6F6E802019592D802776D1D5280EFE3823CD289766E3403A65BC2B6A28581A15A0F1C7859892282961B1DCE3C2DA0A998985487EBD4E3C2C81B5D1A322B1E75A63C2B24BE49DCB9DBA63C2D6A4CEEFDE871E16B2859A1928183D699465145318DA477AF242A0D0B1390894CA0878F9B3A9A54115AE6C7049D4EAE3B3E30FCFBB7923D45AE78F2AEDC7EECDCE1C941E53571DDF1B6A16ACB3C8EC69CB7E3F3CDBE09ECE8B34774918D0D3C333625C1986E95EF97736B6CAD3BE5320DD02B9412064445245AF1193DF080BC2B0AB02464C15E1586363DF1B5E17F5F3FF38D029FF38E3FF38FE3C3F2DBCA9FF747B5CB03597B6E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D98A8B7639072125B39544C3E78AB27797F75F462A948156A62A88A30C554E163F584E5F67154E27E0D0D075A62AC7648CA82701546E95381285F7C8143339230D1864153DF2252A0A08201195211D0C695078D7C718F34A39A48047C76072C548AEC8E69C0D41EB8AA63A7C144E647CF154CE175AB8F7C082B1A1F524141D4E466CE2CA34AB6F488246F98F37331B2066569157282E4C59269F6CC5D4A8F848D865726639B34D32D97EB09C865322E6620F41855508551B28DB289976100C974992928A8DF2825917A04120E2A7C70B743927B6EDEA003B62D88958F93118B64516917100E2CC287A7F113E2716B3156040F9628E144C4B45DF7C578530B55EB812228A1CA83205B5425E546C8499452E7E54CA4B70429EA3C32259072FDA39410CC146A005699021B01B4CD015400E4086C0532B7978AD46301452792351CB76CBD00A2163E54DB61BE2CC145A41B74A571660AC922A0DB6C5B6254516BC875C5050BF54E4EE695C581287961E1DBA62D64A02694468478E63E50CE058FEA24BAA9032B8865296CA5C9A28E33C7AED99D846EEAB57C9F257FCE4246D0C493B2ECDDE9F2CDCE11B3CAEAB9BE25D56759642C050140299B6C01D0E61BB139012C69F4667E37026BD010287AE5E1A951BF865726C8AE465005722DA15D5D7EEC2AA9453BD3AE2AEE2BE18ABFAEAFF009C6BFF00D674FC82FF00CD71E55FFBA45AE5A39349E6F6BC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EBA9D962318514F1CA2DBD2086568E74237E4DBE36ACCE37F5223DB1B543A8E2F5EB4C6D51AC57D3E58DAA5F50581AD0D76C6D5305E4C8057E9C6D5053A108C08DBC71B5405BAFA73F20DBD712ACF6C6E8AA54A06DA943912944170E6BC403E195A15D2E022BD5474DB0412C76F2F19A4214D07B658AA96FCD8835E7E3ED8AB258A65861DE9B8E98AA5E977C653C68C09A9C5053DB39C33A92A0E426CE2CC6DD8351BA517A663CDCCC689854B5CA6F9417262F56D06C8488A37F63944CB7445A791C0F0DE2A28A8AF5CA497371067F6567249C7634A7DACC79173E316496561E8C80F224E524B221964638A281BED930D914DECE765A7C35C2CD3B81F93569D4E2D91473B6DD3166146353254D29BE285850F2229B62AAE8EE9B7018AA6768F4EA3AE2551ECCA83C72B2C908F286AED909328A11C8A74CA4B7041484006942476C052A51824824532B21368F8EB5DF61E390219829824818053B656436028F80A82141AD71884996C9BC4AAA011BE588053355AA29A52A77C5B01560CAA37C5982879248DC30AF4C59C4A0165547206F5C524A3519284FF375C5AC940DDAA052791C5812C62F1BE02C054A9E994E4512A414BC1EDD5C8A1F0C8C53C4E6712A20540420AE66E1165D76A4ECF9B3FE724B4F79FCBB1DD2C615947D91ED4CDCE10F35AA7E736A49E9BD1CD0F1155CDA61E4E833F349C0A0E43E23E199D8DD7CDD52DF115A13DB2F0D4D9A93D32B93645408F888AD37C8B6856403BB6154482B403962AA8154FED9C55FD75FFCE35FFEB3A7E417FE6B8F2AFF00DD22D72D1C9A4F37B5E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF876BBE87315C8485CF160DE06B8AB2DD364F561FA31555941018E2A88452D01F962A955584943E3B0C5538B771C77FBB156AE1D1D4A8EA70C552A02928F9E48A197589AAD3DB22528D63C72A4202EA7288287AE304B1A7959E5A7BE58A9D5BCAD12123BD3156E5D4491C4B6F8AA8C37039160D5A9C50591E9B745A5515EF909B38BD1ED5FECFB8CC79B998D3AB14E57287DF282E4C5ED7E598D43A46DE198D939B918D92DD411A5DA35075DB289173F10675A5BC7E94629BD331E45CF804DE8CCD551B786524B221388549550763DF2D8F2484DA24E00649926D6DDB16C8A3DFA62CC23ADE35E35F6C59D34235E67DF15A44FD5C374C569AF4590EDB602B4BDB91C8162A251B7ED909328A83A353AE525B8210A357A6053C9B58DC6FC71402AA0B1143B7BE408660AF5661DF2B219828BB695BD51BF6C88E6C89D936FAE84E35392620B23B5BB8E48802462D81AB89929B362D80A5227ABB0E58B3057AA826BE38A928D8CA804571604A1AEDD781DF16B258E3CF17C5191CB91A8CAE41ACC964482E3946A9B0ED8C42789A82CE732B2AA1E20666E1145C4D472795FE7CE96F2792E591A3FB009CDC610F39A97E4E6BCE5EF64A6C17E1A7CB3658DD06A39A5F08063DF3371BAF9B7407A65E393535C4572B9364541E262C48E9916D0B789185555436D8AABAAB53157F5DFF00F38D5FFACE7F903FF9AE3CABFF00748B5CB472693CDED7850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87BBB5531935DF31E9C863A543921B61ED8D2A6FA4DD324A200070AD2A7AE1A54E75173071F4C0656FB44E0A54C34F904B0716006DB61A54B2E222B72A00AA93D7052A342468952C41231A543955506452491B50F4C2020A1A83D415385871325D3E4F8B8F6E38299DA6373444E4BD7DF0708674C7EE1E4956941B1C1C20208A4BE38BF780B57E8C076502D386904501E00134E87236C8458C4B2C92CA6A00DFB640C99885A3AC80F4E466635076C788B194190E94DFBE06BDF2066CE117A759CCC4AF4D865129B9708B35F2E446F2ED44BB007F67283272A317B669F69F5495668EA76037E998F236E4420C87D2378E1CECC3F972B21CA86CCC749B3A471835AF7CA65172A136530C25187C35CAF80368926D1C2397235A9ED92029B446D328E20C37AFB6165C29A4302A01427E9C590D915C1586F5C520A362015401DF167C4E650096A9AE2BC48A85CED418AF1225959874FA3015E25AB6EFD5853293265C2E3180694EBB642526622AA2C95C7C24D72A25B4042B69D3A49CB882A0EF91E25217B5A3FECA60E363C28792D66542C62F8475A6478923642B46C3A46D8136B6349C3AF08CF23DCF4C40DD0648EB9B19446B21A863D874C953113455A7AB1A0E47638D33135D7771E9AFDADFDF1A6CE341C127AA58D7A0C04536C668E499D76FC7032E26A5BBE20107AE2C52A9EFA490F1DA98A0C6DD691722CF4E4D5D864A301269C9B328D32131373F4D4D7AD4648630A192470DBC70BCC8A0DC336E87A53333144071353C982FE6C68306B9E45BF515F552363C53C7369843CDEAA443F147CC3A4CB6DAC5F5B5C03188A4603E55CD96301D2651658DB22C5550DF2CCB8389382C415515CB9A0C5771CA6452154283414C900D814E445180AA9C6C4B71A6C3224A53058C507BE438D5FD727FCE36EDFF0038EBF9063C3F2E7CADFF00748B5CCA8F20D079BDA70A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8749E4AC447B652DE9347F131A77DB1557B6AC3386E9BE2AC8AE5C5C427F9A9B62AABA7B98D4027154C4C625607BF6C550579CA31C7BE2ABA08CC916E31415268087C5AD34B4E51B03F462D8134B97E51FD18B68415AA076901F0C05126A5B602A5464648097CC484653D32B6C4A963A927C7BE565B62B91FD30E3C4E218493CD1A4E532FCF2126507A969FBBA8F1198E5CB83D5FC9B6D5BAE9DF292E541ED92A18ADD683282E54026BA2C2EC39B0D8644B7443D0F4C8D782E5527222190C71AF31B641BC04C52104834EBD316F8A67142076F9E2C9305B72698AAB0B638AA323B7341B62C9CF6C7154C2DAD136DF154E560840F703014851692255F88019410DA95CF7766A08E601F1C810C9049AA5BC469EA8DBDF2B21B0228EAD1488C88E3938F872045325B15C4951591720C11C2E55455DD597B8C55DF5AB56EC98AAEF5ED88FD95F7184319206EAF2071C3D41926210735CC7140A43D77ED8B20C62FB52E4E141F6C5B137D2C92189E8C36C05B2298CAC1109C8B3B486F2EC28DCECB8ADB1A7D7218A5E25FA75C56D33B7F355A5BD393800E5B02C08B4DD3CFDA7A2D0381F4E49908D2D5F3FDB199B8C808E1B0AF7CBB1C9C6CF0B4A0F9D67BAB6BFB49B7826560A0FBE6CB14DD0EA30597E74FE7368325B6B97B7B04748A51C811E273638A7B3A2D462E12F9DA60F1BA07EE73371C9D76514887015A83C065D6E21E6B7204A40554FE1841D99A9C9D701296E28F7AF8E564AA37A0CAED5FD707FCE36FFEB3AFE41FFE6B9F2B7FDD22D733A1F48683CDED39243B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8739D15050D6994B7A56838C8A53A72DEB8AAACCDFBCF87C7154E2DE86024FDA036C551B6EBB6E37C551F1CA237523B763EF8AADBF40F1FA83ED1DF156ACE5E30D0D3962828D58E3937A5716B5748B7A1FB23A62D817CA6A287718B68528488CB15EF80A24AE5CB0C8C9012BBB4F877CADB12C8C1DC0CACB6C50EC84B1E58B0927DA3C6038206F5C849941EA7A38F526507AD36CC72E5C1EDFE4F83D39B95329939507AE9ACD1A2D3E119417371F2659A55BFA70F151DB225BE219469B190429D88CAA4E44427D6EAED3053F6720DE032686D01A6C698B604D52D1788A038A5328ED8F15DB6C5518966081B7CF1555312203418B2433E2ABE3623BD3155579F82925BA024E2AC5AFF5A8F81A380720437304BEBDB89598A49F09CAC8641266B8946E646FBF2B21B436BAB4F1FC21CFCF2B904AE3ADDCAF499BEF394B05875FBCA504E7E938AAD5F30DE29DE7A62A887F32DC471971354F4A610C648287CCB712CB4692B9260190C1AB4D31285AB45A818B30EB6E7753FC7B8AF6C5B1E81A7C451197A055DB0499DD35773908DB8DB22BC4F3ED56EE5A482BB0AE2BC4F2DBFBB732B166A11E18AF124536A2EE4297240E94CB20CE25080DECB25217600F8EF8934D9619058E9FA9F2462599BB1DE9928CF76899B67B67A56AB7118528294EC3336191C2C98ADE51F9ABE4D9A5D3EF649E127D0879A353BD333F164D9D06B70D17E7FDFAC4CD70B30FDF40E4474D86C7BE67E2C8F3DA914972492301EA50B77CCC8C9D613BABAEF4AE025B61BAB2004D3240ECCCB6F12D2A7224AAC0FC7E8CAC9558F3B76A7CB236AFEBAFFE71A8D7FE71CFF2049EA7F2E3CAA4FF00DC22D73610FA47B9A0F37B5E490EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87FBA8BD4048194B7B1D95BD16A1EB8AAAC3FBC353F3C553112FA6A476C553AB12255A8EF8AAF9E321AA3B74C5549AE015F4D8EF8AAC4AD76E871414E6D7B138B5A6C801E9E18B6042DC6DF3C5B52DF50A927C701449176CFEA353B646480985DD972841A74195B63152BC1C8EC0E565B62A4D4635F0C430927FA42FEF07EBC849941EA7A0445AE51BB0EB98F272E0F7DF2E22D40194C9CA83D12CB99611F5DF6CA0B9F886CCEB4D0C38AD3E8C89E4E44597E9F0FF00A415237DB2A939116530DA8F5850641BC06490460103C31649B2C6B4C551491B6D41B62A8D446A0F871569EDCD09A6E7164817B73BED8AA1243C176ED8AA4379764065AD6A08C55874D652DCEC95381B9520D0AE08355241C890C9171F961E43464A8F97F66565B0233FC191B293C7E2ED954F932E88197C9A00E998CC12CB8F2B8B78DA5E05F8761DF156297F6621AD206DBBD31563176EC6328B0B29AF5C218C90964D289B743D724C0335D3999E52A548F8716619DE89680B863D716C6573968D2918DFF6A980A4A4924C4F20FB7BE4516C475754653C37AD6B8ADBCDEE74C92791A83A9C56D42CFCB5732CDC1622E09EB4CB22764893D3347F216E924D1F1EFB8FECC848A99BD2EC7CA9630AA82AAC7AE40163C4CA6DF4AB5800E2829F2CCA84940619F99FE5A1A8F937549EDE1065F4986C3C01CCFC52D9D36BA1BBF1A35FD2CD96A5A84338E327ACDC54FF00AC7363864F27AD0C6648CC52943D466C205D213BAF4C9B978BBD156E393D0E36CA489BB4E2A3B57204A1219A52B5C892A8749F91A57A6564A1FD7F7FCE346FFF0038E3FF0038FE7C7F2DBCA9FF00747B5CD9E3FA47B9A4F37B6E4D0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88FE09E89206F986265C86217D18790FE1928CAD5640FE91DF2684C42ACA093B8C2A9DE95F01A1FB3E18AA6578547D8D81EB91B4A41229E7CB2064847C0EA29CB718612B2829FC7E888EAA37F1CBA835A26DDD016277DB225B0284E19CD17A65664DA103242114B30EBD30192D5AAE9FFDE644C9908B241CE489D4EE00E982D980C4F50B52AC59453DF06CD8024EBC91B89EF9125B238C1E6C93493FBD51DB2B914F000F5FD094ACC9C45052A731E45B601EE3E5621A401B7AE504B9B08BD5ECA14AAB22D189EB98B3951765860299FE9502D15996AD90E22DE22199E9F6D1FA9EA71F8CD2A7236DB10C9E1894B82474EF8B626B144ACE7E793114A611464B713D3C325C2153A8E3000DBA0D8E0E10AAAC0A8DBEFC7842AAB0F86BED8F085B40BF5C7842DA577708E2DC0531E15B62F3E9EF2B13C490712026D1765A5246DFDDED9512BC4C892DE355A7015A656496C125C88A29F08CAC96F8C95C01D29D72B2CEDC638DBED2D722634B4A0F676EC0D23049ED9548522987EABA7C6C5FF74BF2A0CA49626DE75A8E99C8B462314AF4A61848DEE903BD278F4708F511EF5CBEC32E109FDA69C435553E223AE3B278598E9903C34EC3BE1B09A4E652163241F88F5C8C9B211058B5DFED6FD6B9149800C6258DA4675AD47718B510A967A6C4CFF147518B512CE74AD3ECADD59961018904138AC4B2B49232B420500F9603BA69689A388D176AEFD71A452256FA9FB59206992716CF16A9A65E69B3012452C6FCA33DFE1399FA736EA759B97E31FE70E94BA6FE656B564578DAA3B3431781A939B9D3879AD6403C655A49EB34E794A5882DD36068336511B3A1C9000AA00074DB2B9158121176E55483DFBE52665CB8C6C29DF5C301B361E22A62C6E6766AF235C9B02104B38434069878583FB10FF9C653CBFE71BBFE71F1BC7F2D7CA67FEE4F6B9B087D23DCD079BDBF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8DAB09F719801BD8DDC8A4849EC77CB2294B5C736AA9CB1531B69285636FDADB0A19143FBB5AD7A60554F53D45627B602942BA77F0CA8A143D4DC01E38C0D154FE02C621E19719288A362069F3CACC9B045308E2046FF007E5664D822A7731064000E991253C2A7A7DB7EF3A64789908B2BB5B6AF30456B8F1331143EA7A627A65A831E26C1160A6CF94D41DB6C04B6C62CA746D3099936AF8E5722A43DA746D302F134DC65132CE01E9BE5C88ADC5076398F22E7630F63D1A20F22A1F1CC69F376388507A3D9C3C19401F4641B87366D610D29B6F8B6C53A4401C7862CD31B789CB123A65A392A610C3273C2AC8228C71507AD3155EF18A53BE2AD32EDFC715413AEF8AA19A307AFD38AB696D19EC36C0555BD140360065549010B22D180F7C810C8158401F3CAC86624B3991B9391E16C8C9DEB0C4C5B4168DC8405ABD3299452C72F6F1199878E6398A6AD875ECAA5C90054E400A4F0D2053E371B77C3C48643656C6B5A6D4DB1E254E12260BB63C4AB5A195C30F0C902DB89239AD253CBF56499C9237B57491B6A16C5A24995AC0C083DF16892730C8D1EC72405A225182E881D70F0B2B51376A49E477C7856D512ED36DFDB1E15B649A15D1127C3FEEC0CB4FA0E6660D9D6EAB72FCAFF00F9C90B196DBF342F66238A4AC493F7E6E74E5E73561F394A156460BF66B9B2076745946EA7FC72A996B886BD42A72AE6E643925D7331634C980892493DCFDA51DB6C980C4A56CE49D8E4C06A7F645FF38C1FFACD3FF38F1FF9ACFCA5FF00746B4CCD8F20D079BDCF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D880E040E87B66006F492FA2F88803AE5914A1C5B7186BC7E2F1CB108781585C46CDBAA9C2ACB15E3684803738154955A35663F6476C05285594BC9C6B55AF4CA8A157D052E2837C8F567109CDB3AA808D8993688A6B0C44B0A7D93DB2064D8229EFA01635A2D09CACC9B0456081581F86A720649E15D6F6AC1C7A6BC71E26422C9AC6D242D535A63C4CC4532BFD3CBC068B534C789988B036D34C731F82849C789B04597E8765C654257204B121EB9648B18400509198F32CE019C688A82652A286BB9CA497371F27B068CA81D582D0F8E5122E7E3E4CF6CCF29D2BD3C322DA39B36B4AF3F84D17B62DB14D56A5B03364368E811011BD284E5D1E4A9B200402A389F1C2A8F49102AEDBD3738AAE3221EA31543927715DBB62A82949036C550F473FB471556457A801A82BB9F6C555E458A31549BD4F639021925B35DB80CA2DD189E8DE190216D45EFA38AD889621EA53EDF7C810C4C92A4BB8DA29A46958B28F8129D72206EB19A0D2EA607D53C9D3F9299618B68CADB5ECB7069E87A71D3E2343944E0DB1C9691DD7EF83F01C58577198F28B609B1B78A560C492483F6B299C68365DA2ACEDDCC82BBE55C28675676A0AA80BF1531E154D52C588E98F0AAE5B1707A75D8E4A21B71A12EF4F2A84AAD0F8E58CE4C4E6B26939A96E2F5F84E2D1256787D2B16319E52C42AD20F018B449E6F79F9A5E52B099ACF51BD4B6B984F16151BE5916B2692D93F387C822A1B5B2BF223254BC4BED3F363F2FAE24A0D6D9B7DEB4C697899345E73F28DE11F53D5D2A7A02C31A5E2665E5DD574C9264F4F555256A428208DF2FC45C2D46EF833FE7278423F31E36DA482653507A13439B7D39741AB8BE3F6565BCB84635556345EC01CD903B3A2CA374422214625457B65536B8849677605E86832500E4C521B8B97527E3CB00625262EEECC791DCD7260312B94E4C06A7F64DFF0038C1FF00ACD3FF0038F1FF009ACFCA5FF746B4CCA8F2683CDEE7850EC55D8ABB155AE683E9C554F97B62AEE5ED8ABB97B62AEE5ED8ABB97B62AEE5ED8ABB97B62ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88BB53C866006F5971082E0D3BE5914A16E00488FCB2C42550D19E83AD76C2A98DBC844BC3DFA6054E2E29F56603BD3014A4515564CA8F3423C5C0420F7A65726DC7CD745704B8232B25C9AB6490DEA22A6E2B5CAC96C8C593433ACB1AEF9025B04535B4B70E188A1DB20649E14FAC6C55985464789970B281A7848C328C3C4D9108EB6D3DA78DAA2BB63C4CC063B71A3137205325129AA4EACB4A68DD6829824C4866305B32B2023B663C8B38B35D1A03EAA6D9492E6630F56B106109951E6E6C59D69DF100D81B073673A6FC4AA69D7BE2DB14E917E3C59A7D6B6C48461D0EF96C792A751A711BE155C57DF157703E38AB5F4E2A849BA62A82798462BBD71541B6A616B5AE2AC7F51F31D9C1192CC63A77C910D8C02F7F30F4BB763CB520A57AA93FD99590C0B179FF003C3CB167270BABC593DABFD99590D04A47A97FCE48793ED2A91852C47C27DFEEC111BB59953CAB56FF009CAA82DEE78DAC21A3AD1401FD99710C2390DA5F27FCE4A6BFA821FA8D89E0C09E407F665120DF1C858D45FF00391BAEDAFAED776C556BDC7F6663C839519BE91FC9EF3EBFE61426231805D4B961ED954837C256FA2AC7437AA9E3F4655C0DCC9EDB4C78CD48C3C0A9DC160481515C1C2AACFA79A834EF8914DD8D0379A79E1F7E06526177962A03963C585787BE2D1248D61963B1D453ABCB1B08FE74DB16893F32BF313F293CFDA8F9AB50BE8209A5B79A4668F8F402A7DF32314801C9A64C462FCACF385B6D73A4CF2D3BF13FD725B215D7F2EBCDF34CB1D9E893C751BB713D7EFC7657A0F977F243F30A7991E4967B343BD09A7F1C695F5FFE597E526B1A5DBC6DA96A0F34CAF5662D5D89E9D7251E6D1946CF1DFF009CCDF253680DA3EB11356474EBDFA1CDAE9CBA0D587E7F593C9373965D9DBAD73640ECE8B28DD16A7E07F1ED954DAE218BDCDC0124895E8694CBB1F26F88D9239EAE4E5A031921F8D065803595226876EB9301ADFD94FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A0F37BA6143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8294F845330037B52D4B29AF7CB2294AAF6BB8CB152D8D5830A547CB0B13C930854870DBD7C72122C2253953585ABBE54496C4A1BFBC6F9E441552641238567283AD7F86322299E306D98F967CADABF98AEE2B5B3B62C8C69EA01DB31CC9D8E385BEDAF227FCE2EC17515B5D6B32155900A293FB5BFBE5129B9F8F102F43D57FE716EDA2B988E9CF5403EC76FF89663CA65BBC10F25F35FE476B9E5FB932C687D193E1555ED4FA72066C7C10F3E5D0750B0B8F4E5571C4D0D7009A462A6616D632491014AF11BE59C4CFC20BCD9DC4428B551ED931309F0D012DB49CD59C50F8E094BB94C02636B1134F1C8711699C53368A452A791E9B60B6BA65DA0C94750C706CE442DEA763229E15DF289F3765879334D35C55476F0C8B7B3EB023E103618AA7D18AB0DB02DB27B16F8554F6197479330980DDC006A3C30A551862AAB18046E31545718986C82B4C585A57716ACD5E228322B691CDA75D716F8493BD32B2516F3FD674BD4DCBA4523A73040A1E99124A5E3BAE7E4DF9C35F467835BBB8977AAABD3F8E4F88A402F1CD4BFE71BFCE6F3D06AD732B576ABF5F9EF82D9D16357DFF38C5E757A97919DFF0098FF00B78B218D8A5C7FCE3179D43F22BCCAF4AFFB78F2639310E1427FD0B379CC48ACF6EBB1EE3FB720723891C459FF00973F203CD715C436F39F4A0604391B536F9E4253722185E97A27FCE37581BC59757B812AF2ABC2C6A0EFE15CA8CDCA8627D4BE51F22F97BCA10C49A3D9C5048ABC4B462808EFDF2A9CB67271E3A2F52B68AA828287C72102DE629D5BD9B4AA07877CB835909BC569E9815CAE4C0AAB428C0D08F837CA81B402424B733060D18415E95C2DC0B0ED474F6A973B835A0F0C5B0C424F1C216A196B4C5A6710105736314EDCC205E1B103BE0B21C59C2F9249756B69103CE352464F88B5F865298A6B78A5A450278D699602BE19661653F35154070DAF8659369F7D0DA144745FF4821547BE46CDACA1B6EC37FE7263C99179DFF2D64586D926BCB088C826A55C0E2C7AD7365A693A4D5C03F119A136BA9CF6922F131C8D191EEA48FE19B8C727439318B5194888DD21D890787B6DDB26402B080616EB44AB6EE6BC98F5C9844A21047ED1CB034C821DBBFD3930D12438DC9AE58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4F37B9E143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B535CC00DEAF28EF9645528BA1C8E58AA10C60B8AE2A5181789C045B590982FF7669E191314829431FDE36532D9BE22D52D2C9F52BE82D233467351F466365C941CCC18ACBF49BF21FC950E9D6105EDCDB2BD003C88F9E611CAEDB1617D71FE2ED0B4B8E21385E286813C0E512C8EC71E057B7FCCAD0EF6EE386270A76037CA2591BCE165F7369A4EAD6CF2CC527122FC209AD32BF111E03C475DFCB0B2D424966B78946E69B63E22F80F329BF2DEE609654856A17ED532D195071525571E49BB86BCD0ED93191071A437BE567442CEB4206DB6113B6AC90628BA7345395F7E98789C5945329ADB8462BD69D71B6BE156D224E33818F137462F48B49887515EC32B917618850679A4C84B2FBE06D7A3E9CDBAD76C5594DB8E4C3154E6D5C89197C32D1C9984DE13571852886FE38AAAC7D3154C228BBF638A6959A21DC74C82D21999882380CAD692C9ECFD53BA0A9DABE1919288EEE8ADE6B65F4924EA29838DC8F0D092DACA8793C8013D1BC31E36631A5773F003CAF01FA4E3C4D831B1E96F2047DEE86DEE72139ECCBC2B496EF568492A9722A7E798A7228D3282B5C489EAC373561D1413959C8DD1D3A274EB7964B80D2C859ABB2E40E46E1829E8D6914CC1226B6E117FBF48C8F1DB2963A65B6D6E11176AED96C0B5109D4238A82075CBAD810ACFCB8E5732D6425CED22568763D72B896043A38A39012454F8E49B6297DC5AF21257A0FB38B7249FA3958B6DF4E2D3916C1A423ACBCBB1DB22538B1F131ED53CBE8FCA87AE20B6F82C364D0258A60231C93A93938C97C047C505C5BAF43B6596BE026B6B0C976D645BED452127E583AB899B1D3D3AD2DC6ABA76B1A6CC39ACF6C63507DD48FE399D84D3A3D5C2DF87DF9F7E50FF0003F9EB50B20BC6970CF4A7F3B31CDB6296CE872E3A2F1CD4855D641FB4BBE650DDC7E4C4AE362C3C32C6322969FB67241A64876EFF004E581C7921C753963497F655FF0038BFFF00ACD1FF0038EFFF009ACBCA5FF746B4CBC72692F73C28762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B360BD730037A3E4A1E9DB2C8A529BB42C76CB10A50AF165A8A625211B55C622D8494E52786C77A8C998ECD60EE83BCF8AE9388A506F4CC2CFB39F845BD1FF2CB493A96BD68047CB8CAA6B4ED5CD5E59DBB7D3E3DDFA93A3D8B69DA6DABA0F4D1211555D8663176D8A2F2BD72D751D7353962B3321084B1504D32893B1C71D952DBCBBABE9EA26657046F5EF98F26FE009EE8DE78D5B41BD1CCC9344D45911892001DE99595107B868DE79D1B5B31AC92FA5310014069BE36930658D6A8E1DD40E128F81BC72C69945299F4A421AAA0D7C46581A0B0DD574359012117A1ED9312A6A9C5E51A9E83C2524201BF618789C69C58F5D69DC410476C789AB85274B5E126DF0D0F518F137C22CBB4752028356DFA9C376E5C0507A4E974053B7F98C2C9E83A6CA15803DA98AB288E7008A62A9AC2E480C3BF5CB63C998E49A42E69D4E14A395BA62AACADEFB62A9BDA5D536206D8B35F7373CA945A5720B4840ACDD09CACAD221232BD6BF3C84CA62375D2AF53D0E637139A12B9622FF0D49E5B6F8789B404A2EB492CA69DB071338B1A9BCBCCEE47106BED919CB66D88DD47FC2E3FDF43EECC4B6F115787CB8D1C8A40200ED902590A661A6E841543155A8F6CA8A788271E97A478D6A3C3082899B08E801D854E5F02E3109AA82A0153990C4869A471EF954CB590A2D2B32B0200C840DB54C25A4B89050903C32D6714C963F5A3DCD0A8DB16E4B64B295492010B5C5A72289825D8455A7ED655334DDA734BBEA32CA28687E782DC9E2583494460B201C9B71F2CB014F10448D060906EA3EEC9028E25F1796914F258FE9196C5C4CC2D36B6B45B53B2B03DC8EF97E39EEE9F518DF9A7FF0039C1E5223518FCCD15B8F4EE295217F9797539B2C32743A8C6FCE1BE9B8832EE55968066CF13AB9ECC50124B549CB4B594249D4E48354940F4CB038F2511D4E58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88089A86B9801BD338CD40F1CB22969E30C32C420D8713B6291CD6D4E4A00B1C8B58D46E69979AA681CD40FC7331F019ABD4BB4D353E9EFF009C74D21751D692A952B535A78669C9DDDDE101FA397F6CB6DA3D360563A01DF2120ECB0B7F96FE5B8F503777862ABD08AB0EDBF88CA661D96309BF99F4A3043246918E9D8663C8373C0752D0F50796436F096321A37C35DBEECAE99458DCB65AAF96E48EF4A4B50C0D02B78FCB101127D05E48F375D6BB6612E418CDA850BCB626B4F1CB0071E6CFEE66658C7BE594E34C149A525D1AA3AE46450030AD4EC83B31A6F91DDAA51613A958D0F4A6DD71DDA845864B6A56423EFC6CB7C629EE92854283D6B9747937067DA79A32E4959BE9FBB8FA31564A83718153C85A8A9F2DB2D076660A6B136DBE1B4A354EC3F1C2AAEA4D3154742E148AF862DC119556C8324C6DE256A74DB2B28559630B95CF92421D979661B900A87A7BF4C0CE25B30F2ED8B60696C4160481B74C05B224DAAFD487F2D7E8CACC5B812EFA90F0032042D9575FDD0E23E9CAC861C454DE124FA9D7DB214CA3225673F4CF4CB62C885C353111AB6E3A65CD65506A91C9DB2120C0B6F771D36DABD7238F9B44D0E675AD69972628BB797D571C7609D716F64B58A587871DE98B4CC162B7F21D31F8769872194E45C7612F87519A46A274F6C886EE229B44E646066D9874F96482F116416C22E23A64D788A756F2AAC4151030AF5CC989D98917BAA344D37488610E0E78BE6AFF009C9CFCBF4F347E5EEA73BC5FBCD3E2661B54FD963E199D824E83541F83FAA5A1856F216D9ADA5650A7AECC7B66EB09D9D0E6D8B0FEA58E5E5AC1D9072F7DF2516B9287ECF5ED96071E4A2A773963490FECABFE717FFF0059A3FE71DFFF00359794BFEE8D69978E4D279BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EB35F7CC572138A74DB2415A634196054B67900E44E487355B1CE38D2B96EC8282B9AB74F1CA665880A912F22CBDE99ABCE5CCC5B3EEAFF9C4EB113DD988815E25AB4DF6CD69767A626DF647999435D5A5BAB1D880403FC32B93BDD3F37B97962CD6D34832280ACD0EF414CA245DC621B30AD5A77B849A302A6A77CA2459494B4AD209812478C115DC951FD32316A1CD3AD5F49D15B4D91DCC3EAAA134655EB4F964993E64BFF300D235631DB30085C8F82806C7DB1453D5F45D7E4D52D54D6A683F56147084DE0BB3C9C4B4DB619645A728A49EE7799DFB1E992A68A627A944199EBD4EF8D2D30A9AD944BF3C6928AB440B28A61566BA79A30C559A58BFC43E8AE2A9F46FF10C55388EE00551E191BDD04A3A3BAA8EB8414A363B91B6FF003CB1B02312E47CE993661328DEB43E3DB16E099C4E38FF000C82A2606A656528D2A5C0A75C84D5BF4CE6310DA1A2877C890DB169537E99590E405754DC572239B656C98C511A74AE4E419C10D7111A1F7CA64E4001085780DFE9CC793090097CD7263A953F17860873681CD26B8D4E58EB5A6F97AC92A7BD9A405877E9938B4C9AB7BC9D09CB29A095433DDC8E4AD7010D68F82EEE0515D6BEF819C5368272159E9C69DF16F82223F307A4425457A62DD1016DF39D5F871FB4A28299092C804A6386EB4B928C84A9EE722C53D86EA3640CFF0068E2A98DBCF0D462A9EC13D221C3ECD76CCBC5C94A6B67744115CB1C2CE16F9AB4B1E63F2E6A1A4900FD7A090014FF00248CC9C45D06AE0FE76FF3A3CA4FE54FCC6D7347652AA9348C05283AB1F6CD96293CFE68EEF03BA6FDE483A10732E25A2B648E7152773BE5C1C69F35315000AE6445A96E5A036C407F661FF38BBFFACCFF00F38EDFF9AC7CA3FF00746B4CB43833FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B31D2B98AE426E47C3920A8694EDB6F9605482ED982BD01AF864952E86670D435F961B414D50730396D909A0370370B8907B7539AECCE5637DD7FF388F76A359642E05617A0AF7CD74C53B4D3737DAD359B5DEB30730410C280E63C9DEE9F9BD5EE3513A558B2745F4F8E5327718B9304B6D4629D679188EA69BE63C99496DDF9DEDB46B231B952D355547707C72316A1CDE15E63F38EA77F2C896933047A8A2939364C22DF48D42E6669E7E72173553D7157A56853DCE9A1622080682A715672D70DE9A3AB862FB900D72D838F991729E56E186EC7A81D726D2905FC25CA9FF277C558B5CDA9049A6D8AA95AA71931565567B32EF8AB2BB37A11BEDDCE2A9E46FF0010A9C55358CD40DF21D58946C792641191E58D811B1D6993661368998003C316F4D6273415E990423918D4532B294EED8065DF6F0C849513C465242789A2828720437464B553C7AE4087263255A002B4E9910376CB454520E3D69ED864DD0536219C0EA3C7289736F082BB1C50D3AF8E63C98C986DE4AC3950EE0E087368EAC3758BA99281493F2CBD125897130B346FDA66A11938B4C9111C92B15A6FEC32C0E396596B6D298D0AA924F51896B45C92C36A959402E3AAF7C8B6458E5FF99A0A18E21E9F0AF3AED8B7C5875C7984090BF30057662716F8A79A379A8C328726A95EBDB2052433C9FCC16DA94694515EE46458F0B514913505413E0315E14EED0C408E5F0FCF6C53C29D2CD1A2715229D46F97E33B302AD6F78A1BA81F4E4F89AA70B09B5AEA9CAE91030658C153FECB327149D36AF13F22FF00E7387C9B168FE686F3446800BE6259C0DAA6BDF3618E4F37A8C745F9A7786B7136D4F8B3638DD7C85256E09ED9787167CD408A66445A9665A1BA2FECC3FE7177FF00599FFE71DBFF00358F947FEE8D6996B813FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B33D37AE62B909B337C24788C2150E57E1396854A665FDE0C4AA4F29A4D5F7C802828E0F545DFC36C24A02E97EDB53C33132072B13EABFF009C5AD5E3B7F345BC6ED40411BF8D735F986CED34BCDFA88F12B6A36578375E20D730A4EF74FCD11E719DCE8F2CD16E6BC49CA64EE317278326AB710C14E5BF2E998F26526317AF79AA5F3210480A29918F36A1CD97683E45BBB86599E33C4D0D48C9B27A641E5FB0D360637340C47C18AB1BBFB6B494B7A43A74C550FA4A869DA222841A0CB60E3E6667058D09A8EBBE4DA503358061257F9B154A27D257D36FE98AA4034E546229DFAE2A9D5B5B22815C5536854290A3A0A62A9E47D302A2524A151E191EAC4A670CC7EFC90649847374CB1B022D26AE4D984E6396A06FB5316F098C6D5A64109A44C2A32B294D216A50D76AE4648298FAAA76C890805BE55CAC86D896F9656439112E26A322DD12A65C0EFF003C8C9C9C6D7D657A65126F086BA9818CF8E63C98C983EA32F10EC3C7A6087368EAC1AF2F19A4A7865E8936B7C562A1DF261A648ED37518849CA4DA996071E48ED7BF31F4AF2D69F25D4AEA0A834AFB62583E6AD6FF00E7226C2732CF030660C40A1FECC8B38A3BCB7E7A8FCCF6F73717527A224A7A5BD2B8B7C53237D1CC5E2AF348F7AE2DF1627A87E63C76529B0869198F6A0EF902D8032DF2B79D6FEEDC0E478B7BE4534F6FD0F5096499096DCE2B4F4225E5E1F175C5691261936A4DC76E95C9034D13E6EF425FF968FC71E26C10B08CB698D9D02B739240791AE64E29381AAC3B3E3CFF009CDAD163D5FF002CA3BF02B25A30634EBB54E6C71CDE57578F77E2BCF2195DE43FB44FE1B66DB0F27479051428EA3E79921C39A1E41B9F9E6445A90A577CB83745FD98FF00CE2EFF00EB337FCE3B7FE6B1F28FFDD1AD32C7027F51F7BDD7162EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87DB371502A2B98B4DF69C13D01C90554E3B7D19312094A275F8FF005609482B1EB8DA6F964225055E3625900049F0C9A014D110167327C238EC4FCB31F240B938E41EA3F935A8FE8AF31DB4AB2846332802BD413D7303340D3B3D2C85BF5FF4FBEFAC6876376AC1C7A43E319AF90A77DA722D34B906FF00CB573DDC3120663C8BB9C4367CFB35ACCF70B0202CDCF751D466392999A7A8E81E5AB7F53D69286408A48F0C62D319025EA16D3456B0085221D280E499DA4B7BA7C9A99268691EF418DA5E5DE60BA83439191E550D5FB24EF82D52DD0754FAE6A30B28E20FE396C0868CA1EC8564540C632011B31193B684ADC1624914DF738ADA94F1A985A8C09A614816C6CDB92C4D3BE282295046CBD01C55150EC77FC7154F22208EB8AAB2005AB9162533840A75C21923E351B64DB0146C69B64EC3208A89CF2A5698DB784EA17D86F90B54D616AD28722529AC6F414272242AA2CC01153898B0E0368F4DC546FF002C818B6C415F46F7CACC4B9116B953A9A7CF20634D91284B89000486195483978C84A4DC7C62AD4F7CA241C805B966AA1DFB65120C64C33569F843235413D86463CDA3917973DEF2BA615AEFD32FB6264159AF9A12ECC85815D864E2D5229249E6048924DC230AD01EB9686821F337E6C6A3ADEBF6F1D8D8A4A07A8DCD97B838086145E59E5AFCABD62E21ADDBBAF26E546FA0F8E459C43E91F2CF96E2D234B68AE18C92C207A2ABB9F7C69BA3B2AEA725EDB594AF65138918100537C5B8178FE9DE5BD66FF547BABE57ABBD547B64241B4483E92F2CE8A6CE18A886A06E70527883D934189F9AB73E86871A5E20F4069278F8904D3C7052F105C6ED89AB392DED80DB44B9B5F5BFF29B23BB91090554BE113C4C5AAA55AB5EDF3CC9C4D3A88D8D9E47F9E9A41F30FE5579801AC92C51B32C23AD02935A66C71BCAEB31905F8377711867B8848A18A46047FB239BAC3F4BCCE7152418076DBBE65C5C19858EBB9DB2F8B4A1580CB04806E8BFB2CFF9C5EFFD667FF9C76FFCD63E51FF00BA35A65A393813FA8FBDEE9858BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF874B265328CA593246507853C72259C513C07139596D0935D28562721D5279311BC929375CBA1C9A24BE0B90268E872F8F26013B9650F1EE72126FC68DD12FDAC351B5B98DB8B472015F6CC2CE36761A73BBF5CBF267CCA9AFF966D6D24903148C0A66AB287A1D2C9EF3A5AA3C9FA30AF10FBD735D91E8714B6615AEF96C695E6084C43E0998548F7CA29A739B7B3E89E598CC6B3247EA19D0034DE996403878B9B2EFF095959C5F5ABB70AA054A9C910E482F39F3AF9B340D26C192C028B85560E57B900D32B21982F8EB53D425F345F4CD2A91463C09F9E565B014C740B2D46CEEC39AF18D870F964E0C66FA4B4DB8379651ACB27C400D8E5B17166956A21E262886AA456B9634F54B2332383B6581C8835E9301B8DF0144D690475C0C694FF6CE2B48F85C01F2C569188D520D698AD2650B50628A4D633D314D23636DBE58A8B6D1C73A62E60E49A44FD37EF8A53BB6906D8AA64241B6298F36CB0241CB9C9149B5ACC1471AD2BB656BB2600823AE40ADA1A7038B37865534DA493C828731CB740A4B3C94AD3AE51272E054DAE1BD322BDB2892C8B17BEFDE73E7D32B71E658826968D7264A7535C21A2D327D2BD40401D475CC88AA42FE528A69099146F99015747E43B157E7243EA03D0787E38C92194DAF9574C8900FAA8DBDB20C9CFE5AD3CCA812D40F1DB154F57C91A75C45536C3953C3FB714A4375F9736C2559628F804EBFE75C8948445AF97520223A74C0A9FDBE962CF7036AD4E2A9DA32BC746C550727A49B03912CFA2025B845DAA3DB20D40EE827B9574702868466463E4E55EC93F9C6E3D6F27F986253F11B4947FC21CD962745AE2377E0879810C7ADEAA87AACEFFF001239B6C3C9E3B55F594A17F8E67637026B24077FD796171D02EBBE5526E0FECABFE717BFF599FF00E71DBFF358F947FEE8D6999D0FA47B9D7E4FA8FBDEE99260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF861D3DE432034DBC72964CB565278537DF2259C51C6600152C2BE19516D093DDB13CBDF23D5279308D403ACA3623C32E8726892193D65742548F039911E4C03258F9B415E276CAE4DF8D49039755A94A1AD7E5989945873B0BEE7FF9C71F39AD95CC3652DE0EC3893F3CD7658BBAD34E8BF49F4D9C4C12F512944AAC9E39AEC90779872A6B75045AA442EA420CF17D95EFB653C2CF24AD9FF94B596B3B6953D1FAC49C6853BA8F1C9014D111458679F7CD173E94886630F20691FDF890DC0BE62BB6B9D42E984E8E6366F858F7A9C810CC1645A779360216644E04EF9510CC1640DA298978C49CDA9BD30C42C98F1D46F6C2F56DDB946A4F4CB22E3CDE84B492C83BB0666DF2D69EA81876276DB261C88372321620900D3A602C8A0E414DFB604521F73B8FBF15A5652C3A0C5691F1F2A2FEBC56933849A5295C569348C9D85715A46AB506FF004E290162960DD3E9C5BC724C627A002B4F1C529DDB38DA8698AA6AA4F615C5239ABA1EE72E6DB541280CA396F5DB2056D324B903E127E2CAD6D7CF23189FC29D72A9A82C7AE255E81B7F0CC72DF0293DC39505A9D3289B95028069DE9D0D3C7289A494AAE999D08A6F5DF2B699157B5B55600D37C21A93AB6B3ABD38D76DF3222AAB3D8AEC547CF3202A360B3429B10580F881C64C8223EAE9F6792FCB20C913069A240EC08057ECE2AEE735BBF02E062A8EE64C4C18862DD32254242E8166AB0A6F812A978C161AFE38AA412DD98E062AD52062AC4DB54B862C0D46E72126CE88492FE43B16A6443472288B5B8E714A7957A664636F32F4A035894C9A16BEA4D57EAD257FE04E6CB13A0D74DF86DE6D503CCFAE85DC0B96A7DE736D8793C9EA0DC98F053E199D8DC19B9CAD3AEF96171D06E2A76CAA4DC1FD92FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD333A1F48F73AFC9F51F7BDCF24C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85DD35C96DF2964CB6023E1F9E44B20BA47FDE1DFBE5526E081BC7A2935E8323D527930FD45CB4887BE5D0E4D1253673CE1073223C9806516854C237CAE4DF8D12618E343336FDB31E4E66366BE45D767D175482E623455606BF7E61E58BB1C137EB17E5579EA1D734AB485E60D23280457E7EF9ADC917738723DF2D678ECAE638E75062946C7B6F94F0B9B1DD1535D496978CF6BF0C53281B63C283B21750D223D6007B800D7C7224282803E4ED387A4428AAE4086C05192E8F15BC5C621B814C810CC1632F697AB3858A22EA7A90322366576C7353F2BDE5CDCA4E632287241A26C820B0921B658DF7232D691CD4A5B431C6C476C9872209210DC8961BE02D94A72313B605E15200814C5695D6BBE2B48D4278A8F6C578531B76E9B62BC29B420938AD261E9B1FA714D2F119FA462D815D63DE98A53680D0818AA6F149414EB8AAE6980D89CB99F12D5605948EC6B5CACAF12A7D6292EE77C815E245CD755888F11954D416352CE7D43ED98E5BA086B89B92F1F1CA66E5C4A5D24C146E731E4A4A57713165F8776AE56D5229B69DCDA95C218B2AB5421AA4F514CC88AA37EAE5F71D33202A8C917A2373C6BB63264103FBB06A64A78E4192610DD451A37192BE3BE2A96DC319E4E4B21A0C551714AF1B202D514C894847CBE93A87D8918158F6AB72681074A74C55894D73C636538AB16B9999559972326D1F4A4C2EE477A1AD322E393BA716F70638580EAC4664636523B286BB2341E5FD79D8F10D6B21DFFD439B1C4F39AF93F11BCC8E24F30EB0E0D435C3107E939B5C3C9E6729B293667637126A2CB5AE5A5C7502BBE5526E0FEC8BFE7183FF0059A7FE71E3FF00359794BFEE8D6999D0FA47B9D7E4FA8FBDEE79260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85EB109D5771E394B24EE19497451D3950E44B208D724C840F1CAA4DC1037B50A4378647AA4F263B7B18AC6C72E872689206EC51A2653D32F8F26B08F82E48A440FEF295E39093918D3FB23F595759AA225EA7FCAED94172E299412FD5A2223FB75F8328C9172B1CA9F48FE507E663685756D0DE5D985C90B1A13B577F7CD7648D3B4C3983F4F342F325A6BDA35B5C3DC235D7006300824FE398C767698B202C860D46692358E54A18B704E0B05BA62D35B6BD77DBA0C890C63128A79D8107964086D102AC932B00246DBB9C898ADD2296EE2B643E8C425E5BB31ED95914CE3BA167D4A2991B946108F6C431940B13BCBC049111AD32624D3E19B4ABEB13382AC2993130DD114974E3892186F8DDB6092041DCD46D8AF12E6EA4D36F1C57897091456A715E2565993615C578C2656CEA69EF8AF104EEDA4407738A6C27B132151BE295540189A62CD1023351B7D38AA24232D0914C55148DD29D31559373AEC32DB544DB9A0F8BE9C812869C7C7C874F1CAC94B6F229000395CCDA84AA68DB996A6DDCE63B7C36414CE95A577CA66E540A45792D09DEA331E6C88B41C2FCE4006E7C32B6B9448DD9259C81283A64C45AF8939FAD3715E0475DF2E0BC4135B7BD2A9566CBC49788295C6A1137DA3CA9D4612CE26D8F5F6A9044A5AAAB4DF761FD723C2CE982EA5E7AB3B105566524D796E36FC71E15A63C9F9AB6B1D47A8A5BE63FAE34B4A4DF9AE92238128592BFBB507AFE39190544695F99324B308EE25A027615FEDC8D26DE956DA8C1A8C0662D56E831A5B63BA93FC7C23A927B531A543456723C3FBD4A313F86464D8262A90ADA70462426F91693024ECB5ADCAA0929448D8733E19763906194F0879FFE736BA343F26EA571EA7A69776AE96EDFCCC54803EFCD86298797D76404BF1AE617524D2CB74BC6791D9A415AFED1CDBE290AD9D1CE24EEA7C18F419990C81C498A5AE8C06E2872EE305C7A52E058ECB5CACEEDC1FD8DFF00CE308A7FCE35FF00CE3C8F0FCB3F290FFB935AE67C3E91EE75D93EA3EF7B964983B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BD3BEC652C938B6FEF53FD6C89641399500ABE5526E090DF3B32B11D40C8F549E4C7AFDE4E31FE397439344905217668C78E644793584C2C406BA27F9475CAE4E4637A6796B49FAFD95DBA0E455AB94D5B951E4C7EF266B5BC6B775A50D304A2CC4D7C26EBD7496194C7E97C48D5EF985931B918B23EA0FCA5FCDFD5B48BEB6B6D4EF19AD9481F131A537F139833C4EDB06601FA51E59F3FF9775DB2B764950C8CA3910457F5E53C1C2EC6192DE8D0C7672422789AA08AED91B72E050F34C84A88C74FB59025BC6ED2C8DF3F0C899354A289496A8CBD2BDB21236CF0C50922D011E390A6E314BA4B22416A634D44255246633BF638D3021033905B7F0E996C5ACA0682B5C92AC734247E18AA8337BFCF1572B74FD78B594CEDA6A0A62D914EADE652462CC325B6605462D89B4282A3BD71668EE031558ED8AB68DD3C3155772A77C9AD2989950100E56534A46707A9C84969A1254D474CA8A40DD648F5539516D8A4B350354E5126F821258048390DC0CA26DF14B638945C71E5C4D3AE463CD728B8A6358E05E4641B75DF2C70F850ADAC5B16E0660BC4D6B5C9C53C0D4FE71D2ACA2224B95A8F7FEDCB578581EB3F9B1A3DAC4FC640C4D42D3C7EFC945B2029F38F9ABF379DE597D19DD63A9E95FEB926C7906A1F99CD71EA52E9AABD4127FAE2AC557F301DE46ADD356BE3FDB8AA656BE75BD915E4B79CB2A1A36FDFEFC8C9059D7947CED24B7F18BB6661C803D7FAE455F61F973CE960B68891EE0EED5F1C559347E6182E6752B106A9C55939B95940658F8823A64486A3CD0CEF5AFC19590E4C64A2FE9B2FA4C2866EDF2C9C22E0EAA5B3E40FF9CA7F308B7D046911BFC71A9F86BF3CCEC71793D61DDF9A864E681D8FC4D527375861E975929521B91AEDE399020E26492E33A13C5B7236CB40A68B4D2CE28A4EAB9600DA0BFB03FF009C6A017FE71CBF2000E83F2DFCAA07FDC22D73363C83AFC9F51F7BDB324C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85CD3C715A1EB94B24E228DC303B75A8C896514F44323C058D3EFCA8B70499EDCB24B5A647AA4F2492F638CAAFF91F6B2E87268925A5E07F8D2B48F63F4E6447935854B3E4B73327ED15247DD95C9C8C6FA0BF26AC66D5D2F6D22512486A287A6541C8E8C6FCFDA1A586A5710950B75093EA0ED936B32A79F192E1220A4D2A39291954A1698CD562D4A485158BB2C8A762329389CFC59DEF9E40FCD2BDD0960334F2B46E42F52694FA7313538A83B3D36A1F767917F3C6C350B782092EC06A00431A78660183B5C595F44693E60D3F558D7D39939103BF8E53214E7C260B295B66E21832303D286B94CB666775DE8488EA781A1F6C31DD944D35246EC6A23603B922992A64648A11A98B8820B569418D06B24062FABC2D683D4996887A531A6B25884B751B92C84D0F8E16050F57FB5514C285BEA57BEF8AA9B9F7F962AEE42837C5ACA2612716C8A3A17756152298B30CB2CE71C455B16C64115C28A55A9418B3470B943D0E2AE3206E877C55B57A0F7C5548CFC07C677C9B6D20649CB37C26801CACAAAC659B71D32125562DC76AEE72A2AB7983515DF2A2CA2955F3D15941F88D29944B937C1A8A4021F8CEF4CA26DF1631A9DD7A3C9D1A86B4C8C39B29724A9EEE49E3203354E58D54C4758B3D4562F5226DCB5363BE4E2B4C2A5D0754BE722494F1EF56396AD05A7C8B6654FD61CBB1EC7A64A2B4935E7E5C79767564907C4C3C324AC0F51FC93D2262CF6E7883526BB62A935B7E45D8FA9B9A927AE2ACCB4AFC83B510CCFEA705E42A323241677A0FE53E83A5C81A62A597C722AF51B0F2BE90CEA96BB1514A2F4C55153583E99708A895DF638AB2386FDFD3459051FC3034CB9A2D6E19876C8F0AF1D34D342CF1CA4F1FAA2B35D7CBAED9918A3BB81AAC9B3F327FE7257CD967AF79AEF2D74D9DA48E0E4AEAFB6E2BD33638F1BCDEA4D97C82C5D763D3B66E30C7D2EA66511000C4572DE4E24CA356D6126BFB44EF86D880C92C2CE20061E26F8C5FD757FCE3780BFF0038EFF90AA3A2FE5D79580FA349B5CCE87D21D764FA8FBDED19260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BB6F848AE52C9904352B5F0C896514D3D7E36C77CA8B704AE3943AC9BEF91EA93C921BBFB2FF004E5D0E4D124854D2198FF94BFAF2F8F2601358471B966F18FF0086424DF8DF5BFF00CE24D8A6A7E63B9B6715564634F7198F234E544585BF9F9E5A934FD775396342055B7FBB1136B9C1F3100C614E4370B96036D06C20E54F8078D72756DB09334D247FA1C629B9EF9467C761CCC597853D827BFD3254B8B6BE642A6A141CC09E27698350F58F2A7E73EBFA4DC470CF3B988951CABE14CC49E276F872BECDF23FE7858DD476EB3DD8694815527E5ED9893839A26FA16D3F306DEFE28A55911380A28AF5FC32318A99D2723CCC6F10233A229FDAC970A0E54AEEB5C834C9030BD578C8E4C6BDF1E16A395E4DE74FCD485A64B586753DB63FD98F0B039103A66BAD7D124BCEBCBC30726C89B4F45EB1A2F2DCE2CD1092357AE2A88F888EB8AA834850D3C31605562B923BE2CE2895B86AD6BD716613AB4BB7000AF5C5B03238AF8FC3BEF4C59A651DD934DFAE2A9925C57BE2A89593E1FA314C79A065763BD726DF4A22BD7E9CACAF0AAACC13BE424BC2E6B8AFC43B6545045209AFB8BF5CA8AC50571741DAA4F5CA64DF04BE7D43802AA731E6DF148E59BD77A3FD9AD4E461CD390D04F6CCD998C291BD32C71B8D4EE6D2240640BCD5B6E3FC72617898FB58A732E4045EF962F1A51A8CB688AA88FF001D77C9C59C656C3A7748E4E6D27C35AE49938EB9A728547DC8C55522D734F520C7154FCB154C63F30B49F0C44411FED29DAB91920A5375AAF2B9553217A9ED9157A77945B99568C1E05A8D5F1C559B798AC80B713AA0E406F8ABCDE3D44F221CD181A53080E3CCA6D1EA238F5C20346495060DF999E7087CAFE5C17AB2859EED1C15AEFD08CCCC31757A89D87E54F99EE6EB5CF30EA3A93312B2B311F4939B5C50D9D266365881B52546D999195075F38DABDB5A9EC3194DA2504F60B08D8AF8F7CACE4651C4CBAC3490C071E9E190395CA8627F58BFF38EE9E9FF00CE3F7E45C7FEFBFCBDF2C2FDDA55B0CDCE23708FB83A3CC2B24BDE5EC59635BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85884F361C76CAF8536C96DC111904D6A301816424D4A58C5C075A65462CC6441C41E1560CA5C9E80654765394525D76A423B31095ECD96E336D12CA18F05E69242AC0B484107B6C733230348134E0FC0EA6849910814F964278C86F84DF60FF00CE1AFA8BE6C997890CB5427B6F98594539D8657B3DBBFE720B44F56E352AA8320526BF40CC7E2A679214FCFAD422F413895A713C4E591CAE14F6485D8351286B5CCA84C14464F40D0A20D0C709A127BE3964006F88E264377A544A16AC797E19892C81CEC008418B78D5951D6BE04662642EDF164A099E9E2EED2E565B29CA1435A1398920E58D500F50B0FCCBD6A0F4E192770F0ECBC4ED4F7DB2996CCBF3024CDED7F37358E01259E4E245363FD991B41CAA7A97E61EA7771FA705CCD461B963FD98DB0F1187DA6A375A8DFA09E4919F97DAED8DB1337D27E58965B5B3854B971D70F0DB958A7419A457ACD2AB576F0C781B78D90C37CB51F153E79122990926B15CABAECE3E9C090B6491493DCF8E282143D555F1F962C86C8859EB4A57DB1640A696D24840DF167C4C82094556B5C53E204EA09169DF14F1A3A19949FB58A414DE27523ED8F962C816DD4788A0C9B68CA165630A41EB4D8E40848CA12C9E4E3FB5F3C810CB8D086E9551AB5395485053249E694B3F2076F0CA0C911507B8526B5E998F2986E8EC954D3879295CA8FA999CA229B69D6F1CF22ABF422A708853564D4090A6616FA65804AFC5CA985C7F1107776E2353E99A8EC3240AF88C3AFC4EA181A508E8327C6BE2306BCB3672F20635EA41CB319B6DC79186DFC7292CA49A65DC2DBE284858411732558B1E95C7857C5097FE9178643C5453DF1E14F8A11BF5DFAF71E6CD13A0A2F1E87E795CC5309660CAF42B41EAA34BFBDDF6AE52649196DEDBA3AC91C6A21554A374C1E2065C69DEB17D722C9A3908269D7263763E2878E3CB28B89030DEB52C3A53261C7C99022CDF47042D34AFC238FED13964604B87972BE3AFCEAF345C799357B8D2F4F98FD4ECA80723B1AD6B4CD861C6EAB3650F99E6B7BA8AF3882BE99D9877CD9E3141D5E49A0EE2DC076006C3265C594952DA2A76CAE450236CA34DB28E591405353D7316526F8637AF68BA242630596BB6527239718BFA78FC884117E47FE4D443611F91BCBAA07B0D32DC674FA7FEEE3EE1F73CBEA3FBD97BCFDEF56CB9A5D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF858B4FB432AE36EF0D94C1F6457A77C789061488210F4C89DD81539220637E0C15E9F0B7865660C244524D756F13A52693D47F019761C6E31905B67E5ABED43F756D68EAAFB89E9B0A66C61065198B425DE8B7BA7DD4114CFD036D95640E66220BEC4FF9C378DD7CE37019830E62A335D99D8E10017D63F9B7A7A6A3AB6A7005E47D36DBE8198526DCA6DF997E77B23A6EAD25AB0E2A0D7200D38138B07922A10C33271C9AC459B79526E573E9B7602992CC6C3958B67A75E5A7308CA3A8CC493B0C692359B89375DF28C8E6C792BD9C6E26238E63C925131C00CEC5C5083B644C6D946549998D5694C1C0CB8D1B1395E31815AEF8F02F1BD5FCABE5F49D16764F8BAE3C0BC4F5AD3A16810474D94ED86A9CAC4764E919B983F7E25B814DE201A8CCD4272A93644A690F1029C8E41B0146FAD40003B0C5928B4FEF8A559273F0D4F862A9A5B5DD286B8109DC57CA08DF0B105358F50403ED7CF16C051297B08228F8B3051E9A8A01B3F4E98B3B6CEAC4FED64896622B7F4913DF205988A067BD249F8B204B608A0FEB47725B6CAA6526282B8BC201A1CC599445269AF5FB5731E4DBD17DAFA93480F63928868996716303222B74DB2E1071AF74EA3770295230F84B6A53B32AF23BD71F097898EDED5C1F871F096D8D4F0121885EBD72CC71A6C81B63B77A6990310BB9AE5CDAC12FF4AB80CDC50D0F4C558EC9A3DE3BEC877F6C551B65A2DE8956B1B52BB653910636F54D134C962319910E6290D9183D46C42C7C05295DE980067253D7A655B76DFB665422E34CBC8AE2ED959C0FB3FCD968838939879279F7CD7E8594D630B9591C1008F7AE5F8E0E1E49BE6986D2E66B998CE4C8EC49673EF99D8F675D96492EA9A6709AA13BE65C4B8336373E9D234AD45EF84968E04759E8D2B015427299C9B61167BA2E84EAF1931F5CC6939110F67D1F4BE318F87B65326F8BFA35FC955E1F937F94A9FCBE4CD047DDA7419D5E9BFBA87B87DCF29A9FEF67EF3F7BD372E69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF855B670AC2A330CB984B2785D5A23C4EE46C300938D3C8037146EC0D640A57B1EA73271C6DC59E7013FD17CBB7FAEB98A106353D588EB9991D3B85A8D50112F59D1BF2CACE1557BF01993724E5F8F03A39768B3EB2B0D26C08B45317A454D401F16C3C732BC3D971F68BE7EFCC1D3E117D1DCDBB5631C8041D7BE60E78D3B9D2EB789F437FCE1B5928F37DC48C4A6FCAADEDDB35595DFE973F117D6DE76B8853CCBA848F19742AC38FDD98530EC4EEFCF4FCE7D0AE26D50DF5BC263889E5D3AF4DB292D5283C3230655657431B275AF7CB612A6A31A651E578C9BE1C5A94A65933619E30F7148792460EFB653273F1AF4B1ABB029C89E87C3289B9B16EDB4CFF004A3F0F5F6CC7924A3C6845A6E741D7A530C5814DA3F2DB4D4A2D3DE99246E9B59F955DAE230141A7B62BBBD7748D35ACA255DABE00615B2C9238C83C9969ED95973709D912B1FC4081F31912E48298C7C788D8E552660A2D08A743EF90660AA7A95D80E9D31656EE05BF6A98A6D772A7C35E9B62B6898A4E3D4D7145A244DDF9D315B442DD11D1B1640A3E1B84A8AB6F8B65A6D1DC42109A9E98B3077524BA534DFE5809724144FAE0A9A1A6DB6449660A02595BFDF832A25B0150FAD71DB9572B994CCEC8692E958D28731A4D112BE38BD42083D7B656D97B325D36D5415240F965D8E2D332CC15408C00287C732E107189B2B7E207ED5465BC010A95E638B0AE3C0150B2DB07E8B8F00543A699CF9D453C32328D3762431D138B54D18785320DE8693CBF0CE45502D3C7156E2F295B83560A47CB154CE0F2E598707D351C4F865536704CA6D16085032D001945365A47724C33A90A7805EA3C7271834E4C94C63CC5A8C0B6EDC9E840DF3371E375B9333C3755D61A4574B67F1ABE640C4E064CFBBC875ED367D4A61297F881DC9C988538F3C96A56DA488630CD1737237232D8871A52B492FF00449A798BAC3B78658254D2425FFE1E666DE2A1F9644CD90C6C86C3CBDC40AC5DBC321C4D831B38D3F468D387EEF7A6F9592D822CEAD2C5234038819596603F7D7F27871FCA4FCAD5F0F286883FE9C21CEAB4FF00DD47DC3EE792D4FF007B3F79FBDE8D9734BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF84F5A9238F5CAA50699EA135805C2D19413C7A0F1CA841D7E5D4BD77C9FE4C9F5955BAB9531A36FB8A7F0CDAE9B15BABCBABA7B25BC363E568B8428AD2D3E13B75CDC474FE975F9B54642929D43CD1733551578D7C3251C4EA660B1C79EEA4E530908600D30CE1B231715A437D65F5A82269F76DFAE6A75317A5D04097D2BFF38A5603FC513C69B50F519A5C8F59A4818BDF3F32C8B6D7EE550D4EF503E8CC4C8EDA06DE35E6CD274ED634C8E1745F5C2F2DC6FDB31645BC45F0F79C3499F4CD4E482088842DD40C6326A9C55BCB703DBDDC25B66722B97036C22FA334EB45963889EE06093998D91DB69F1FA87E1AE5191CD8F245DB5845F5ADD46512E6929EC1A746D253877F0C8DD2631B66365A3C2101283071B2E0641A7E9B6AB2F22A0536C7897813496D944AA517E11D71E35E0463C28C415E94186DB63B2E580602DA0AA88B88F6F0CAA4DA0B74A641902A65A84D3164D09A9D7155F50686BD77C55DCC0DB90C554DA6A54F2C516A26EE9D1B16C06D552F883F6B0330518BA937F37E3859834AE97F4FDACAC96C1345AEA15523976C812CC4D4DAF474E5BE544B671A88B82CD4E5D72124CA7B2AAB0E42A7BE504B18B23B331FC3B8C039B6B27B39A35A6F9978A2D190A73F5D8F8D2BBF6CCBAA71495CB728DB636BC4ACB301B8F9636BC498DB3ABF518DAF126255154103AE4265C8C25AA467ED0CADC97048491B0C5556910EE31550692256A823DF2B9ADD216EEF23E34AE5643194D846AFA82420B33058E952C72EC637703365781F99FCDF662678397A8A4D0919B2C7074D9B3BCEE7D5EC0C9584D10EFF004E6588389E2DAFB7F4AF4811906B80C11C68897479C39A3D01E8BE19514A9FE8B71F69B204A695974DA007803EF4CA8C9CA84764C6DED78EDC0636CF85905B45180BF08069BE368213650028A0FA3157EEEFE50FFE4A6FCAFF00FC04B44FFA80873A8D3FF771F70FB9E4753FDECFFAC7EF7A265CD0EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85F8ECA6827585979C84FD919084FC474B9674F6CF29F906F35036D773218A18D833A95FB437DB719B1C3A1E274FA8D43DA2E0C763686D6D2216DC06CE3BE6D30E8F81D5CF2F11610F34D76CEB212EC8767CCC3300535006ED2AB986E56455F4CB03FB54CC7F1699CB7539675B32AB335030DEBB532B9E76EC1877633ABEBD05BC4817E3095DEBE39AFCDEA7A8D0E301F49FFCE3379B34BD275C3753CAABF58466DC81C4F875CD5E6C342DE931914F72F3ADEC17BACC9A94171F5A4B9DFD21FB35CD7CE36E44254F2DD5E40F74AC253188D3E28FDB31A78CB951C8F3BD4BCA69E67B826C23334CBD471FEC395F0D322049E6DA8F93752D03518E4BC89E28D5BEC95207DF4C2254C6389EA9A33F3B58E48979851B8C4CDC884699569EEACE6BD5FF000CA652722324EBD158255940E61BB6545927D6AB1D43EDBEE47865728DB644D32A8A7884600F0C1C0CC4ADAFAC952283BE3C0DD18DB27B39964B73CA3DE9F6B1E06C186DD1A90A6A77A9C9C62D528515707AED84848D950380A2A37CAA41902A4CC7B0FA3214CC490EC549353438190921A42AB53CB14F1297390814AD3B62B6A2C66F7EB8ADA8BCAE2B5E98AD201E46AFDBA62C97FAE07FBB2A7BE2CB89DF5C03ABD0F8E02CB8DB5BFE34F8ABF4E506569051B1DF7203E2C896C89561755FDBC8D3305556E7810FCAB4ED8382D24A252ECBB57A7D39138523252716B7C626525B901DB11869978CC9ACEFD64A7C5C72F87A5AE53B4DE394935E5B53AE5BC77B35108B8EE82903957DF229114CEDEE62E5566E43C3DF1663127705DC0A2B8B3181305D460208A74F7C05B618F854A4BF87C46001B2D06DA8C6BBF2FA3088ADA1A4D622029CFF001C9702DA17F4AC4C681BE23D05729CB1A5AB405CDD731BBF0F01918C2DC7C9B3C4BF35FCCF268FA60B6B78DEE2F27158E34AF434DEA332F1E3751A8C8AFF00959F947A8F9D3433AAEA90B5BFAA2A3983B75F119B1C717499A565BD67FE71E6F9B549EC74CD4B9F04E6005EE7B74CCC842C38E254C2A7FCA7F39795E57730C9731C7D5829FE991941B23240C3785A76B4BD06DEE22DA507B6634E0E4455269E35902A2FAA9DE40731CC5B8056F5410027D9FD939518B9319505E8CE36AE222C84938B13CC8A8E9D708091BA7885760570A781FBABF947FF0092A3F2C7FF00013D17FEA061CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8797343B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D2F23F91A57BA4BFD6D6BC0D68D99B874D4F199B556F6FBFF00315959471D8E9F1AA0A7024019B9C18F85D466CD6C59E49EF25615E4332A52A0D50DCB2DF2D6856B70C52551CE43DF31324DCEC38B88D3D353C81A7CB0F32AB551E03FA663193B0FCA3E7DFCCDF2B2E9FEABC7B2C7E1F4E53293938B4F4F9C6F56297D485DF7198E64EDB4F0E146E83AFDC797196E2DE46AA9A00091D7E9CC6CDB876719D3DDBCB3F9BD24F2C31DE0DA94AB1FEA7308C1B0667B4D94D69ACB0BD12208D97E3151D3289636F8657A07911B4F7D723B3D2E146909A39DB7CC738DBE395EB1F997F96F6BAE687305B355D42DA332D55454D47B0C8F03938A76F86AD6E6EFCB17173A65F42C9F1955E429DF0183920B2BB7BC4616F2C5B16DDC65660CC165F14EB3463B9032071B30532B566E2C3B83B65538D1499526D019BBD6990E16719A6917C5DBA63C2DF19A6D6F7CB1008C7E8C785BE395344BA420107AE061396E881329C892A0DAD663C8D0ED9592CC054571DF2BB6C017F2B7FDA1BF7C2A8599ADE876DBBE2A82372A361D3A0C5541AE7155295D4AD477C52934EC6BB6D8AA0C87F138AA8307DB7380A43AAD502BB7865062DA0A3E1269D7A60A6C0510A5BF98E34D80ABA3316515F98C69369846687AE16B4C2075322A96D8F7C55328A7F498156AD31564767AA23108EDDB08544B5EC55DA4FC724C81444378A5A9EA7BF5C2CC14C92F401F6F6F9E06C1277E9458EB593AEC37C84CB6715A849AC27412F4F7C8829421D6A25AF292BE1BE580AA026D6226DC3FE39602A841AA52B2C64B329A0032AC82DC5CF9B81E8FA0797EFF00CC36DF582AC8AA3AD30C62E064D45B23D2FF002E746D666FABEB1682EAEE27FDDB915A27874CCCC61C0CB2B7BEC5E5C8B43F2FBD969AA96E889B050053F01997034E0CE16C3BC93A446D35E6A37975CAECB32853E03A665C25B38C63BA6F3C3CEDB526BEB5496201B83151EFED82526710F942FF00F2B62F34EABAAEA1631FA2F393450294A57DB31E45C8807897983488FC97713E9FA8CA1A624844277CA0B7C52BB760F0C4E05030A819590C81A45AF5C14CC14D74F6F888F0C7859829D237C58D3305FBB9F945FF0092A3F2C3FF00012D17FEA021CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8796B43B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF911B5D4CA4450905BBAE74F1C603E6D3B48AE67FACCEA900FDE16A6D9682038A626D9EF97B49957795D99CFEC9195CE6E660C6F47B1B58EC87AAF540BB961D4661CE4EE74B87D4191C5AFAAC65616692836E5B65066EFC600F1FF3E4D71AB45708F1045607E21F4E5329B64703E3BD62C6EECB539792FEE8B1F88FCF31CCDB04292D9AE9C158E18C484915AE57C56C8DA31A49596358E416F21EA54E44840059C68FE69D574B44824D51BD24151F16E7D8E63C837C6DEEDF96BF9A30697AC437F733A5B98C8A9E5D7E798F272216FBDBC9DF9E9E4FD7AF7EAF7B7111F56309212474C003978362F14FCFAD33C9F3EA31DFE8572B34929E46314A54D7C301736DE23636377C39471820F5F6C8101B0499559B2DBA8F59E847619590CC14FAC751B37996105CB374DB6CA671B613932D59618940988453D0F7C8F0A04D136CD6F2352390BA9FDA1BEFE18385B064A593E9D74D30689498C9DD8E3C2CC66461E76A80354A81BB65538EE9F15B87528DDB846416F0272B316C8E54DE3BC454025A06EF4CACC5C98E45296FE05DD4B37B5321C0DE24BA2BC570095007BF5C8B0326E59EDE9BB004E28B4B5E48F7A1A8C56D41A44DF7C56D45A4DB167C482797AEC315E24135C76A62BC4A06E0D7A75C4A89287AB43D72921B414545734A53E9C785B01B45ADC8F1C785982AE2E42D0D7A74C14C89D95D2EEA2B5DF035DAAADD92C17953DF15B4CE0BB006EDCBDF15B44BCE78F247A3FB6109050E2EEE01FB44FD392664A69697B329A93DB147123FF4A3014240FA71533A434FA846D148EF394310AA81DF018DB28654A6E3518B9DBAC324B2198D1CD3A60106CF142A299A4BC92D622F2040086237DF2622BE28651A77947CC5A9C4F35BD83945E8C4102996082F881EB3E4EFCA9BD9D44FA8388EA7918FE5898BAAD7E4DDF4559E9967A26872A40024C828A0EC09C9083AFE3280F24DBDEACF7535F5BA2C8EC5A075DFE1DE997C4522ED966AD33DA5A4934D2963312A213D299785E152D23CBF696D62D3ABB191FF007A2BDCB76CB449A670DD4BCD4C2CF402DC4249715529F3DAB80C944698D7953405B5B06BB9A61140D1C923CDFB5D2BD32B25980FCBFF003D4B379FFF003D6EF4486FCC7A769D39ACAA7ED509EB9021982FA1F54FC9D96DF4DB7BFD27525BB9258C39B52C28BB0D85322907778AEA52AE8F70D677C443780D046761F7E2C814CEC599516534A30AEDD30365A6515E425FE26A7B61676FDE9FCA021BF297F2B997756F28E8841F63610E74783FBB8FB87DCF21A9FEF67FD63F7BD172D68762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EF578F9B5C06FDDBF4CE9B8DE267A6651E54D1967BAFADC9BA72AAE552C8E29C1BBD62DE25826E4AB45AE56656E6E0C28FB8B9068427241F697C72B9F276F871F0EE94C97B4256184257314C9D96395B10D522BB9CC8D23058687965129399116F07F30E857BACDF35B58446572D4F8728949651A4E34BFC8DF335FC6918B3912693756A76FBF2B126118D966FA67FCE2079E3569D2425E28DBA7F9F2C4C9C918596BFF00CE13F9AA29D1E5BD255853896E9FF0D944A4DD0C4CC2CBFE706B5A9E359DB5858C2EECBCFF00E6ECA2526F8E265563FF0038CDA7E8171691DF7994594A8F4F50494E4476EB91126D11E17A95A7E487956EAE62177E6E597881D6407F8E032660A7179F957E4CD35D2DE1F32C444A28C798DA995993602A69F929E539E932F9A6293BF0120C812D82491F987F2C348D2EDBEB1A7EAA048836F886E7EFC46ED3964C33FE55FF009A2FECCDDDAAFD7517A01BFF001C970B57131F6D13CF3A6481DB4B6B5B68FED02A454F8E3C28F11136DE77BCB598417D6E4229A31A634BE2338B4D6B48D6A25442179EC6BE380C2D81CD45BBAF28385F5EC65A93B8A1C81C6DF0CC92CBA4EB91A13E9B3D3BE40E37331E54BCCDA9DAB7EF6D0923DB2BF0DCA8CD53F48A85E722346C7ED2F8661CC516CBB516D4ED5BED311F3C82AFFAEC741C5B63D3E58AA8B5E27F362AA2FA82F4AEC3BE2D96817BF5AF5DBBE29B59F5A88FED62B6DFAF19EF8A82A2648EBF6BAE45B42BC6CB4FB5BE1640AB2B8DB7C0D815B92D3AD70164AD1B0A75CA9AD7F2DC50EF8551D0135A5715477A8513956BBD310CA3CD6FD61BAD324CCA9BDF49F663EB8B548A3ED2C750BFA705635F0C5ACC99E795BF2D359D7F538AD591845506507C0FD396E38DB0964A7D476DF933A0D959033C4867812AEC7B6DF3CBBC363E2A47A4F937C9BA5DEDDEABA95DC29145BF027AF1FF006B2C18D7C5629E7CFF009C98F23796F4ABBD13CB56714B76A0A0950577029E1ED93F0D7C57937E5BFE746B779ACC375AC4AD0E9CC4B70EDC6BF2C84E14E3E63C6FAAB53FCD9F25F9AEDA0D1F43981BDA8590AF5AF7ED80069E07B5E83A3AD8E9B6019FD4927456E47B03DB260278588F9D0BDE6AB67A65BF660580C902ACD043E8C3A7C1D2A02B8F96264C4861FF00987FE997DA7E996FD178F35191E2470A335A8DA0F265F5869B66D3EA4B6CCA0815DD908C921F9C3F96FE439FCB3E7ED77CC1E77D224852EE6768DCA6F424FB9C3487D831793349D5EC21D5BCBBADB441E3E6D64ED4E1ED4C348B7E587FCE45F9ADF47F3B0D3667A346FC5A64F6A60E1660A1FCA5F98F1DD086D6693F771A84563DC78E34D80D3DA2CEEF4FBD50F1CC391F7C69982FE81FF26E83F287F2A829A81E4FD0E87DBF47C19D061FEEE3EE0F25A9FEF67EF3F7BD232C69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8BED12FA6D457F46FA12ADBC7F626A7C47E6736E72BCD5193DAFCA1772C114D67796EF4894FD51E31D5BB72F6C899A63A6B6609AB5DA32C37B6E2DD587C2E452BF2C78DCDC5A4012093CFBA5D95C5C4123AA9B7157693A7EAC13C9B39630D30CD5FF003318397B28A39E2ECD18AFF0CC4326D863A62B73E79D575085C4517A61F6F886DFAB29949CC807D51FF38D7F96B36BF24BE60D7A33C62F8E30BF64F43BEF98F29378C40BEE7D22C74E69E9269D0C76D07C10CB1AD18BF45AFB655C4CBC1E1DD9E8BFB58ED1ED0C421BF857933462881478E266DF8E16F93FCD9F9B3A89F3543E5DD06E92E5E7904370EC6BC2BD48DB2894DCD86114C9FCEFA4EB5E4DF2D0D6EE7CD33CD77749CA3B3864DAA7B5331A536C38E9E45E5CFCBEF30F9C746D43CE7E64D66E20B0B2532DB425E858FB0C89C94C463B64BF967F973179E359223BABDB6D26DEBEBDD31A6CBE06A32072527C17977E75585B796FCC53E81E54B9BBD4A68BE15773C8F2DC640E56DC7A7B286FCAFF002B79ECCC351D62C6F9A0421B801F0F1EB959CAEC31767F13E9997F303F2DADECC68BE67D3A6B4BB20707028DB6C4E1198863A8ECDA28BB3F307935EDBD0F2EEBB25AA1FB2B2BD313A92D3FC9A82D7B509BF41DC2C9AADB5F475256456ABFCB251CE4B4E4ECFE17805ADC68374F7306A7693F224F0940D8E644276EB3361314A5FCB71DB96BED36F0C31F22521734232F0C2386C59661A17994D9010DE5D212BB75C90882931A7AE681AF68FAB442DD6E22172B5E418ED919419C7210C953CBDA4EA2A566A7ADFB253ECE63CB6726398B18D47F2CE695A4789223131AA377A7DF98192365CC86434C1755FCB7B8B552CB1866F0EDFAF2A316CE379BDEE87A8DB170B6D29E269D36FA3234C81481A3BD462258245A7B645210F34BE98F8C1030B7525C6F2035058838B3115212F03591CFB53148802A6DA8C6845198E2C8E20022A1BB59A95241F6C5AC48A3967229C6B4F138B30510B73D37E98B74510B703ECD7AE03BA65B045070AB50D91E171BC42AA92EC64AEEB9131489A36DAEC3380DB0F118084892266BD759111006889DEBD71886C81DD1F0992E18C50C4657A7C210572CE16D243D3BC97F957AF798E482792310C524A1645E8426FBF5EB8F0B8D393EB1D1FF002374CD2AD24B8FACC8B2409CBF7A76247D38F0B8D29A0B4DF33689E5E3793CF730C571A7D79F134A8197618B10789E11F993FF003955A5E97697F6FA0A9BABC98323B49BA8EA36F87325AE669F188F3B7E6079FAF9ADAD2F561B59FD46B94534201A9006C3C70DB8E7290C5B4AD3E1D275392DB592F717334A03C8FBF53DB27C69194BEACF2AF93E2D6E1161A2A492974A3B36FC411DB2B99B6C8CDED5F941F9172796BCC4FA84AD2CE8CFCA6F537E277E9BE56CF8EDF74C691C2A8109E1025501F6C3652082F3BB1AEA1E6A7BCA739223C78FECED8DA683D06F1115A198578A312DEC72F8C0485A90180C006AFE6C9243F14708DA982500189A66B1C4F1488518AA4B5E5F25CAA52A6069E4DE67B48BCC7E67B6D2DADD25B585C7AEC07C54077CABC621AF64279ABF2B6EF4DD2B5AD5741BE6B484216823534A0A0EBBE4865B6C1005F879F9B02E6E7CD9A80D61E3BA9E1958073B9DB26269E00F3089B568627BAD3D12358E4A1E636E3ED960368D83D2B43F3C4F63259C11C9CE5968272DF641EF4DB274178807F551F9093B5D7E45FE4BDD350B5CF913CB92B11D2AFA65BB7F1CDEE1FA23EE0F2DA8DF2CBDE7EF7ACE58D2EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90FF00CB7F20CFABEB70F9784FE9BBB0569CD76FA727E3B8A3474FD1DD03F23BF2F3C93A589BCC5E60B79AEDE3E4119F707EFF007C7C76C8E969F1C7FCE4679DBCA97925BE9BE5331C6DA651649E3E8DC698F8EDF1C34F985743D435AB73A95C5AB244568B514F57DBDF01CEC8E34D74AFCB3F36EB344B1B65B6B63FB4C074FBF29395022CB74FFC91D5CEA169646F0CB792B82B02D6868457299657271C5FAB7F90DF96FA8695E588AC2E2331968C027E81941CAE6460F7693CA361A1E8F705C896E5DC145EFCBB1CA8E46E10BD9F397E76FE60587923CA7269D6404DE66D67F72186EC81E9BE0395C8861A60BF911F93BA0E956D75E74F38EA0B3DC5CC06ED8B36E8C6BB75CC79657371E36216F637DF9B9F9A52D868F792CBE5AD35E9287354A2FDDE198F2CACE589ED7E70F2C5C6B0963E42F2E5C1B68B4F939DEBC6688E0F63959CAD4715259E7AF3EE89F933F97B37956C5565F325C2141243F6F930237A57227236E3C5C4F19FC99FC9EF3579E357B2F3B7982E85BDACF299409BAB2F20DEDE390395DBE97476FA57F323F30348FCBD8C68F62F6D3B88F837115DC0A7BF8656723D0E9B40F813CDFACB79A75A6BE9E0145242328E80E0F11CC9F65F131F9AC2248F925F4B6EDE08D4C81CAC4F6481D1434AB8BFB2BB8A73AACD71A746F59A177AD4F7C9C32BAFD4F66D07D412F9D7C87AC79623B2D3ECA38F5644A34B415E599B8F23CE6A7414F0F3A6EAF7777248B3B95AD16253B53E599D8E6E8F2E1E03499E9BE5C56BD53AB192DE2247276DB2F127127165D7FA0E8F0317F2EEA85EF1002C8ADB93E18CA4D6229B7953F33A6D26F5346D6AD65424F1FACB0FA3AD330E72722117D2D63AAD9DEDB42F6B79CD5D4155AE634B9B971E48AF5AD89E372BCD7C72B219A1DACF4FB9E4A6C57813B371EA3C72B21B2293DE792B49BB25BD08D49F6FEDC810CC3CE75CFCAFB296390C4A2B534A7FB78B787916A1F965240EFC54D05698B6061D7DE50D42353FBB240E9F462CC31B974CB8B7E4B25B9AF8D31672E4848D2584EE87171AB74D61B9A8E25295D89C5B150951DF1640B4B28A80A773DB14CCEC9AC658A0DF22E2A3ED62326C7A1AE34B68D58A15824653F18E831E15B645E43F296A9E67D5E1B75899A194D2B966385948C9C2FB83CAFF0092FA779295353D5A2170654E410EF4AFD3991E1A0E77A4E82DA4699F5ED6AE255B3D3ADE3630C55A55C7418F86D32CCF3DD5BF33AE7CE574749D20496F6ECDE9B4E36047CE98F84E34B23CEBCF1A3792FCA7A1EA926BBAA97BEBD80FA4BCF7E743D725185328647E5DEBFA8C32EA57C2CE212DA991B8B91534AE4A98E4928F9735ABDD1EF0DD69B251CAB7A918F9634E29927A350BBF32B5ACB1DBB3DFB5C207A0DFED634CA2FD64FC8CF29C1E5EF2B0D66F63A5CC9081F17662A3010D8F77F23D85DCB6FA9DE5CC815667261AF8646922D3CD6EEC69D62189A168F8D7DF1A6C8DA43E4EB4FAB9B9D4661B4D5E24FBE34CF74E755BCFABE8B3C8C68ECEDC7E9E9878E934520F29DB1B2824D4E71BDC92149F7CAE5918905956A139B4B19A73B7D514927FD615CA253B6B312C23C8F6AD35FDFEB972B54B824424FBE5129313128BFCC0FD23079435716F2B969636A460F4DB2D8DD391189E17E06F9FFCB7AE0F34EA9A85FD94CD01998F220D2996C4B0902C7749D26F7CCD7834686136494AA9229C865824E348909B47E4F86CB506D288E57711A09325C6E399C83FAA2FF9C7E80DB7E437E495B375B7F20F96E33F34D2ED87F0CE9307F771F70FB9D2E5DE67DE5EBB96B0762AEC55D8AAC7DC7D38AA9D0E2AEA1C55D438ABA8715750E2AEA1C55D438AAFC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF233CB9FF0038C3E4DF2ADCBEB13B133D0B1911C0CC3B2E7ECFCE5FF9C95D5A6B1F346A1A7E95AB4E6C625612C5CC96E229B03DB1B29A0F89DEDDEF00926B97974FF5394909AFAA47BB63653C2FA87CC9AF797F56F2279774DD25D34B4D3A86707FBD6A0A751BE365061B337FC8DF2C5E79C752B7D26D6F2E0CAEEA11B937122A32B258460FD2CD3FF27FCBDE569F47B4B9B432EAF28065BC6DF8F427299172618DF40456B6BA6D9C16FA4C4102A51E4661D69EE72891A732106272C4F737978F79C94DADBC970B272AA1F4C578D077395D972B1E3DDF9E76B6317E6E7E6FDCDAEA08F69636B318F8CA7ED509FB35F96425272B829F42FE69F927CBDF977E4FBCB5B1FAE896F63315A4924C4A7A8694A0F0DF28916D8079F7E5DDB5EF907C986636E96B7BAC9ACD7DC6878B03D0E512939118A6307E6459E97A6DCD968086FF00CD3316F4EE07C67936DBD2A72B2594B0DBCCBCB9F94BE65F327999FCDDE78B1B8BA4327A932C95E0141AEC08DB2264E4E9F4FBBD4FCFBF9ABE57F2AE8F0E81E52E7677F0A18E242F550D420EC32B26DE8F498007C75AEDF5D6B378B7DADDCB4D7B292CBBEDD7C32B327A0C31012DFADC21FEAF343EABAED118C5283DF07139825174B3C0842B583B13D2B91254CE285BAB580C5EAADAB41714FB1FB253C699289759AA31AD93BF21FE5BF997CF5AA25B7942D9E390B52E6465257DE9B6676393CB6AA9FA0BF97DFF0038C4BE5FB186E7CD3299AF1497996BFC33618E5B3CA6B620CB646F9AFF0025F45F3497D3AC6330A8F843A6C7C3AE64893AE9C5E7FE59FF009C4B6F2E6BEFA88BA9E78B90608EE5878F4C12935883D1FCE5F91FA16B366919822B5BC450A27550A6B4CC49CB7722317CD97FE5DF30FE5DDECA90C72EAB696CD44F4EA683000D8F40F2E79AEC35E884733AD9DD746B7907C55FA7010CD983EA0F1AFA3C1404F85180EB9590D812B7FADCADCBD6F84F4036C810C834F248AB406BDB7CADBD21BA53293CD41C5B42552E936F221AA038B20C2B54F2BC3217A44BB83DB16C3BBCCF54F2A4B17F751803E58B5F0B13B9D1E5B706AB4FA314243346F1FDA53BF4C50A5146DC838041076C0589927F096E03236C0A6F6C582FC3D7FCEB931BB548A3A0D2A6BABC820B40CC2660251D7AE5A22D7C4FD0BFC98F24E95A1E9D6B7A2D985F08F90673515A7865F8A3BB4CF23D4FCD9E6780AC36D247CE78E3ACC3F6683AED99341C7F11F21DDF9E17CF3E61BCF275ADF243A7D94865BB8D0856A0EA2B5F6C691E25BD5935BFCBEF2569062B7A34F0A7266EADCBFD6C683025F9C1F9BBF987A879ABCC37C25AAE903E1B5727627C0602144A9E07E85AB1755670AC4D77C1C2C2791D64B67A6DC898BB2CBB8849355DFAD463C2D5C56FA7FF00203CAB16AFAF433BBC73C664570817DC1C785BE127EA25D4634ED0934E0BC04DC5828DBA0ED9121CDC401E6CF7CB6D0268F089CBAB2814A1A7DF829BC4425FE6C65BF8AD6D636E3561C877E38D331009F689666F74B92DE195614B215766F6C69B0462C1FCF9AFE876D2C3A341AA4308545370ECC0EE7AF7CC79C776C1008D7F39FE5FDA687656D77E64B5630D0944700D7DF7CACC14C22C4BCD5F9C5E4792D27B1D3F5980FD6C2ADC55813F08A0A6FB640E32D6718653E49F37F93EEB4286C1756817D221A3F8C035EBBEF90F08B0F0C273AE79A34C3A7CF099619CCBB2B5410C3DB7CC8863A0E44202980CDF92FE44F3BE963EBBA72FD6AF3ED3A902B5C3C0C258C3E78F3E7FCE23685A523EB9E5EBAFAB6A963FBB823076A2F4040EB83869C69E10F9423FC92F3C4BE66FAC49A6CB33C8D46B8553C4FE18971CE9EDFD0E7E5058CFA67E52FE5769B72A52E74EF28E896D7087A8786C21461F78CE9F4FFDD47DC3EE797D40AC921E67EF7A2E5CD4EC55D8ABB1568FBE2AD547862AEA8F0C55D51E18ABAA3C3157547862AEA8F0C55D51E18AADC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF30EE7FE3932FFBDDF60FF7998EE4BF25BF357FE537D53FE39BFB5FEF6F5EDD716D0F1497FDDBFF001C5EA7FB9E98B745253FDFDAFF00BC7FDE0FEFBFB9EBDF23264793F4DFFE7143FE3BBA67FC707A2FFBC7FDE74194B18BF42B56FF0094853EC7D8FF0077F5E9FB194CDCA83C8BCEFF0061BFE521FB5FF1E7F63A9E9ED98F272E09DF927FDE49BEDFFBCB27FBDFFDEFFB2FE3953938DF1A59FF00E4EBB4FB1FEF50FF00783FBAEA7EDE464DF27D01FF00395FFF001CEF2EFDAFEF63FF008C1DBAFBE53258F3625F985FF92AB47EBFDCAFFBCDF6BA663C9CDC6F00FF009C69FF0094FA7FEE7ED0FF008EAFCFB65679B9717EA37997FE51BD43FDE3FF00799BFDE4E9F64F4C94F936E93EB7E3179D7FE531BAEBFEF43FF7DFEB9E998E5E9B4FC921BDFF008EDDB74E9FEEEFB1959E4EC23C936D3BFE3A375FEF1FDB1D3E5DB029F8ABEB3FDF27D8FF009E790973627E2AB17FBD717F75FDC8FF007A7EC7D39383AFD47C5FA1DFF389BD2EBFE385D0FF00BC3FDF77EB99F89E675DC8F37D49AFFF007D71FDF743F6FECE6645D066E6C5344FF7A24FEE3AFECFDBEB99117124CCAD3FBE7FB5FECFA60C9C9AC3CD3CF1F69BEDF5FF0075FD398736F8BCA74FFF00A587FBC7DFFE3A19747E9497CB7AEFFCA552FF00BCDF6FFE95B80A43D7A1FF00792DFF00BCFEEC7F7DD722DB1504FB67EDFD1959641565E9DF2A2DE12997ED606D0843F4E2C825571D5BED7D38B6B12BFF00DAFB3FECB14179F6ADF6BFDD78B51611A8F5FF00757D18B192017FBB3F67A603C9804543FDD8C805926D69DF2E8B44F9BD2FC89FF1D6B7FEEBED8FEF7E797C5A25CDFA15E5BFF8E6DA75EA9FDD7D1F865F071F27262BE69FF8EB6A5F6BFDE47EBFC32E71DF97FE4FFF00C995E66FF7BFFDEC93FBBFB7F4FF00938ABEC7BDFF00943F52FF008E77F70DFEF47F7FF47BE2AFCCCD7FFDEDBBFF007A3FBF7FB7F63FD8E1632E4C6A3FB4DF6FE8C0D3245C3FDD5C74EDFDEF5FF638583EDFFF009C50FF008E9C5FDCFDA5FB5D7A8C0E4C1FA41E6DFEFB48FB3FDCF7FB3909399064D63FF1CF8BFBBE9FB3D320DC3E2C67CC5FF1D0B0FB7F647F77FC71671F8A62DFF28CEB5FEF67F74DFEF07F7BF4E167F37E67FE65FF00C746F7FE526E9FEEDFB5903CDBA3F178737D97FF008EDFFCF6EB8127E2952FF7FF00F4B5EBDFAE2D72F8BD3FCA9F6D7FE526E9FF001EFF006708607E2FA3EDBFDE1D1FFE523E8BFDFF004FF65930DD1E5D5F5BF977FDE0D27FDEFF00B2BFDD7DAFA72054A7FE6EFF007960FF007B3A8EBF47DAC816324FB4DFF8E7D97FC733A0FB5FDEF4EF902C1F62796FFE51ED07ECFF00C73AD7ECFD9FEE57A7B674DA7FEEE3EE1F73C7EABFBD9FF58FDE9D65AD0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD9, '1', '2021-03-13 12:29:10', '1', '2021-03-13 12:29:10', b'0', 0); -INSERT INTO `inf_file` VALUES ('9a2317ba-fa4c-4f77-84b4-7cc537d382df', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010402030101000000000000000000000405060702030108090A0BFFC400511000010302040305040804040404040309010203110421000506311241510713226171088191A1091432B1C1D1E1F015234252162462F1335392D20A4372A2253482E218356317192655648393A3B2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004A1100010204040306050303030302030607010211000321310405415112617106138191A1F00722B1C1D11432E10842F115235233629272A20924E21617344382C2D225354463B2F2FFDA000C03010002110311003F00FCFF00F041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C10418208FD87B813D3E67F3C7788F3FC6E69363C22D6FDDF0411BB815D3E63F3C104286410153D460823760820C10418208E4027618208E7815D3E63F3C1041C0AE9F31F9E0820E0574F98FCF04119A10A936E5D479608525EBE1F78DBC0AE9F31F9E08520E0574F98FCF0410702BA7CC7E78208DADA0999B6DE7F8E08236F77E7F2FD70410777E7F2FD70410777E7F2FD704118A93C317999C10CF13AFBFF008C638219C72013B608232E03D47CFF002C1046694F0CCF38FDFCF094D4158006875877214CC4D4FD59E32C6132985EBAD1DBC7E9189A1DBE576B559DD9FA7DE0C2D0D1724AAA4545ABF8AC18553348A7AD1FC695F7ADF44E1946C9F53F76F5BC6C473F76174E33BB4F03024EB57AF9368DA3830E51803308511C2536ABBB6EC6FE9D1A366135E0FBF1DE92CDF335347DDEE075873FAB3873DD005AC29CB7F4D6B780E5F4D5A851A8FB2D5C6FCFDE363F973C309B988C092848E23661A353F0E1FEF1B1CBBF5AEA52806AD7954F9B1B391E70DFF567A9D7C397282190654A510010227ED1F523D3E3A0CBA7F68FE44CB50E2F95D8D8BEBB6EFE908AB3AC2766471AE623E4A8721E9CB4B73D7AC467586B5D2BA4A851555F54D2B3108594242AE1691B7849036DA2498EB6BC763FE0E62FBF335285B02145D07567AB3373E839C707F8B3F13F099FCB1290B41E0052E143F8D47E2EF1E7E769BDBC67DABAADECBA8415508529008E12384980678418B58EC46F7DFD51D8BEC1E2B2C54A331040053420A6D4D5DB4616EB78F1AF6AB1E8C5266709A17DA8E49ADFDF98A15D4F1A96E288FAC39726D6264FDE7974E5B63D138341C3C89686F942403B1259FA01BF3146BF11C561D4AC41535D46ACE2E3416D980B78C33F7B56CB87BCF13677208B0B58013EFE77E5BE1D4FC4E164A0103E602A5EA0F46E9EB5B45932826536F4DD9C352D4F3D2FB3D52AD755FC9CB69D6AA85405AE080831637111067A72BE2B38BCC82D570DD5DBF34FB545E26B329A26A101DC0DBCB6D7DF296D2692FAB2135D9FD5200FB41B252088822E08322C6FCFA5F112BC5898E259248B9B01B6DC8F3B5AF09DD10CA04B0BDBDDFCB5768E2B75F6579237F56CBC0EEC82952B8ACBE1B022790F58E57DB0B48C089EB97C60A9BF6D051CF2BDFD0738CF0B7ED2DBEBF58A8B526BFF00AE05C41924CCDE6E6F620C5C7A82011CBA064F952259494A49B3DC57AFD1875DE32C5EF4D9B4FE7E914E669A892E9971405D51B73DE4FF00B8169E78BD48CAC2C070C031353E0C4FBBD214960D6BEFA7D2AFD5CC57B9BE76C282A48264F31F388F2C5830A8561C0094150029CEB5B3D2FEE90B02458C5659CE748414107884AB8960CF0743CC103623167CBE79596EE94016DFA3DBC474D602A56FABFBB539443ABB50B652A4B55A16A0090D94F09932624F43E9E98B127284E3903893DDCB7625C9A1A3B5F7FB466F57751D1B9EF688457E7D9A212B536D0A74916295A5C2F728099244741BF4387185ECAE5929655FAC4F10A974B355CDDB63E2E7687F845F7038881A74156ADBD80C46AD1966479EEB3AE4D1D165F58FBCEAB852A34AFA112AB495A91C113E7F3C67138DCAB26429B1929D22A0A92096E4FAB69CD8690FD58B29038998F420ED607C5F4D23B15A53D8935667C935FA8EB5191D227816D347B97D758857DB061C0A68A45A08BCD8CC6397E79F18303226AB0982FF00E6785D2B354849D2A4172F5A13B46E9C6CB482490966E120BB1B9B1EB77F28EC2699F669EC9F45774E57D00ACCC1AB9A90F3A8950DD5C21445FEE0440C72CCEFE2063F16B2A9092949774049513D0B75BF4143185E669593C441239EA1F73A0A103520EF16DB35D9169D60B392A825A5A424B72A3C2102D75493EF323D310723033BB529EF714852384BB11551275D400DA3B93D22B79BC93982870034D75F00FD4921BF2C198EB9692092B4DE67C43A5C6D6B5B162C2F651583471CA4958005003E16BD3F310F2B2598925C103426F5F2B5B5BED15FE6DDA286F83B92823C5C478922236DCFC45EF893C360F1085702B09316C59FE617A060C77E40F51599C365533880AB01424569E5D6C4E8763F43BDDF9FCBF5C7C6A8FB131B1B6F7BF4E5EBE78208D9DD93B19F77EB8208CC20A6666FD44608239C1041820830410A1948215239E082377027A7CCFE782083813D3E67F3C1041C00EC27E38208D884004CA62DE7E5CFF0C10A4BD7C3EF1B3813D3E67F3C10A41C09E9F33F9E0820E04F4F99FCF0411B5B481303A608236E0820C10418208D0FEC98DA4CFEFD7E6704369C2A7937D0084D82108DEC6EAF4C10429C1046B7397BFF007FBEB85E454A81B375D768D54A2080CEFEDBE91AF1B2C0248D296E821DCA415F086277E956F0E9061B2BE57D5B6F7E71209C10500785CF3A0F37F1A6FAC7307A1F81C3757CA1EE7503D2B6E7CA36FD3357840DEBA79FE233458906C4EC0D89DF61CF1B494158E32A219CF0B78EFF0096D371A99A9927846B43A93CB95EBEAD1B0DAE6C3CEDF7E135E3E725624CB4A94FF28A3EDCB9F3DA31330B24CA33662920B7155B7D4927E9CB584B599BD1E4CC2EAAB9C42184A655C6A090A001DA489F389DBD316AC87B198ACF6721465AFE6503504B545C0B373357E4D1CCFB55DBEC2767E4CD4A26A78D20FF00700C40237D3EA6E0D23AA9DA97B41D332DBD41A6DC42570A471A162EA883736EBCFDF8F507633E14272F952E66270E1870A99419EAFAD5DC0D2F78F2376E3E2FCCCC8CD932672812541252A3F2935B0BEFA0E978E906A3D759BE6D50BFE3B50F2FBF512C00A5917BAAE9240B0E6664917DF1E89C8F23C248C3818591292500098FC2CA61435D983B0A9BED1E7CC7F6971666A973E72D426124024D35B39BBBD3C621A3307585FF002524A567ED106D3E666F7B01F118B1AE461928799C0929B0000E7561E7A97DAB0C5199FEACB1750258B9F017E6684EBCA14AA96B1F5B45995B951FDBE2E020C0E289E1BF5237EA31058BCD254B79682DC2E2EEEDD2B5D4EFE0DAAF0495BA8861A335EA46F41A915AE8226D94E87AE6529ABCCD680C7DA2952900F08BFD9E2927CCFEB8AD4FC7AB1130CBF9893D75ADFDB1A690DB80E1EA0B373BD036B4035BD3C21C333D4F91E46D0672361B554905350E18F09488175023D23F2930B96E2312B515F114D38433B5DDB5E437F28CCBC419CE92F6605DDC543DAFEDDA29BD41AE1350B50CCAA949249E16D1C5C23A094102DCF7F28C5830B904E5280E025C8AB352FCDFC7CEA215E015F6C3DEBE91546799EADC2D990191C45B5055C8E7304116DAF8BBE53D9A595259160E5C10CFEBE9E2D521962CF5DC5BDFD3C04573996A24B4140AED3D63EF31D07E62D8E9596E401013F2ECC1897A56BE356BFA1D420EA5BDF5F7F4AEF3AD4C1DE0E05C70F14DEDBF95BE1E78B561B23E2203300D417AB7974ABD342F0A2106AD5F2F7B8BC5719A67CE9E2217293B4131CF97E38B0E1F26C34A40330A53C357207DCEDE20C6C4117D62249CE6BAAD6696929AA2B5D7D5C284B2D2DD0924C429494A8226D1C513CAD384B1D8DCAB2F149D2828034701D86B5F76BC64214A4A940512CE5F7B7BE9168692F674ED1B5938DD5D4E5AACBB2E708597D6EB654942B9941215B6FCE76C737CE7E25CBCB5E5E194E5CB70D8B01A5B52CDE71AB6BB74BF4BEFEDE3B33A5FD98B4069B525ED515BFC7AB7C0A61A525D61348A4C158F0A8A1C0B3D640E9D39DE3FE2666999CD2995355864A5DC825D6F4AD886FB36D19FF74A552D2EA0BB8D49EB4AEBA336BADF946F643A6A8D34993D150D22109E14A8D3B0A58E1020F196F8A6013BDF7E78A86638BC7E6734CD54E9F3261FEE0A98906C2C0B1D80A51AE6012E7B01F3569BB72BD76AF4110FCDF581A4595F12AA03F370EF7496639A532019E805ADD4E12C0E439962A60E34288243B80E4022E59EC7DDA35EE26B5016AB0DF7E5EEB158675AE6951C6B7B312DEE4B6A4A9503A711BDFF00327963A7E4DD90594A0CCC389967240A1D74AD58C024CCAB8507D2B5E75F75EA22A8CF3B4FA36520533E85405719EF00EBB898103974B7AF47CAFB21C20BCB4CB048E1000DE9B5D80B1F4895C0C86204CBBD5F9BB0A8A50783F952FA8BB5C5242F81EE217809503693D2763EF1B5B95D309D9BC0E1C0FD44C9680003F3149D8D8989944992194DC99AF5D79BDF9161B0A9332ED3B38CC1C4B7468AC599321961D7449DB88A52A03CA6FE7189299FFD9DCBC12B992262AFFDA1DBA56A75F5893952E4FEEE14B269A0BF2A75D8C7D9F702BA7CC7E78FCE947D488CD00899E7820856D7F4FBFF001C1046C7397BFF000C1046BC10472013B0C10473C0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208CD00899C1042D47DA1EFF00B8E082327397BFF0C10A4BD7C3EF1AF04291B1BE7EEFC70411B304118A93C51788C10463DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1046C4366F0472DEDD7D7046AA4F13559A33E03D47CFF2C11AF77CFD3F98E0A4A6262F820EEF9FA7F318E083BBE7E9FCC6494F14DE2309AE7095AD4DC0F4D21ACC404AB702C767F7AFD9E32EEFCFE5F1E78C27121542AB50F46E9E17AD59E25B0880407143F624F87500F231AD41485A63633263D63979F581BDF0A0636ABFE7F36F48972BEED2598003A7ADE9785E97611E000AA2C009933E847E5EA6CA0C3950709AF536F63DB457B1D980960B1B3EBBF386F5A1F2E7795280D2904965C2425206EB27607C89983B637460B12B9A897250541440A026B4B5FCCE962D103333EC1C94AE64F9A947007F995AEFE837E758ACFB40ED7B49691A171BCCEA9BA8AF4A141A085414AD22D3DD9BEC3A73DAF8ECBD90F86188CD97266AE5514439526D57B37516FE787F6DFE2F4ACB53364C99C0B710042BCA8EFE1D0DA3A0BAE3B6DD45ABAB3EACEBAE3792A4B818E05F0C2153CD30A3CAEA9F863D51D9AEC160B2097C62524CC64F1929D980615D49D2BE71E43ED576FB17DA099302672D94A2ECA25DDF9DEF67D0E800A32B5C72AAB0A299C5960A8A9C5A964913E2B9513CE79F2F71E852E6CA54B1282412DC219852C2D7A6F60E3568E61370B880B3396A528383577AF89E7C8E9631ADEAC697C34AC8EF9C62CB4F0F1294544110482607979F3C44E331ABCA5887F9AE1D83D7F353E71159809B882020171471F6E648FE1A90F794E98CD7365871491474A2EB2E04DD063FBA08B4D801E5D442CFCF7138C3F2950068384925CEED785B01297214935040AB8B9D6F5D2BCF689839FC0F48B45197AD0F5554A4FD6D44F180A6C0E1E10A2A09BCDD3E569384F0F87C4E26612B4A88A312E5FD0BF8FF009B14BC406093C9CB83D2BD7A00FE759EA5D6AEB895A50E2D2992084A8C46DB0F4E9EEE58B9E5D9271315203D2AD5FE437D5C447E2809BC4003A7B715A5EBE42F151D76A72E71F78A22E4824C13D46F3E71B62FF95648944B0A080E68430E6DCCFADDB946B8190CA20861A1AD7C3EFD4968AF739D40D10A2B50B4F43BDA79F5F527618B8607260E9FF6C1377200BF20DB7F889054A0EA6340CDEF5D76F48ACB3ACF95C214D3A4F0C9E0130A9DAFB88FBF6C5AF078144A07BC481D40A6CDE9FCD635EEF9F5F7D22AFCC750D45495A16CFD58DE17DE7113CAC89E76DA7D4C624E4E270F852429495736614E47CF7D768C940A72F50F5AF9FF0010DF94E5B9FEA5A85D0657435598D4A9494B290D3ADA254620BBC3C2396E4623F31EDC65D93389810A55C7CC01A07D3ABB3788A4615F29A51DDC69E1E71D89D1BEC9FA82B8B199EBDCF13A5E8950BFA806915E5D418F09534AE24CED3CA76C732CF7E2B4EC68523289267AD2E95242FBB67E65810078F2302502BC5F28350757A93E7B1FB476974DF673A0BB3EA7713A6B25A6E3AA091579A3C43EAAE5343C2A4B2F051A7E13C93C24C99C73AC463738CD27CC9B889D312EDC3872A5349767F9C11C4F7A337AC60D0326BC5767AB1D9E9515A316F25D5DA83EAC9296F81A481012D8091FF4881B4DA3D061C48C9674FF009A6ACAAF42E6B5D5C9B5691A457D9CEADA068076B1CE052788A1C924A6638A403723A6E3EE7533B2B389419128A8387603FCF9D0E97896CB90851F98F2B0D3EB5DAA75BC5459FF0069542942D34E7EBCB4880B528D3F099B58C4FCE0FCAF5D9EEC84C982599C8E12083548275F3A00C452912E2549092431B0E74DDDEC35B750D14966FDA5D6BAB5F7CA53886C92D36DAA4B53361C175CEC378F22631D7705D95C24940527BB42884F12C81F330E76620B9153EB194CA9003900DEBBD1CD6ED53B3B18AF2A738D47AB5E34795B55656E12800D33C94C9B7FC45242779B93077E589350CAB2F9759D282807532D0F4D83DED6DF9C60C99360D7200602E4120BD9A950D123C9FD9B35B66E876AF50E6E720A65F0AD912DD49A94AAEA94A17C4D948EA39FC6859BF6DE5CB5AA5E58B338CB2CBE1052CF600B17F0AE81AD08CFE0C30534BE252838214CDD40FC01436689851760DD9DE429073DCCD39B3C800AC28AD90A2093221640B08F39BDB1589B9B67999A80968C4278AAE0A983F26B7DBC223CE2A7AA8A24241B52A0D59FEBE1A38896D1661A0345B6B190645423BD003CE3AE36F13C164901E4A888E7004DE7961493D96CEF1E52A9B889E90AB92165B4AFF86E4E408C9C54D724120D2C6FE1FCEF4DFEA0B813D3E67F3C7C448FAE1182C01103AFE18208DAD7F4FBFF001C1046C7397BFF000C1046BC10428640215239E082377027A7CCFE782083813D3E67F3C1041C09E9F33F9E082315262201E73B9E98208DC8FB43DFF71C10464E72F7FE1821497AF87DE35E08523637CFDDF8E08236608236B6099813B7E38208DBC0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208D8DA0C99B5BC8FE3851129730128492DB03F88D4A929604B3C6EEEFCFE5FAE345A552DF8C14B5DC41C69DFC9CC25A84414C49B1E584BBD976E34BECF1B42683D0FC0E144FCEDC3F33D9A08554E82AE29062D68F774F31EBB74223333973D2C532D5CA86EDEBC879C68B0E40F60381E3F6850503991EFF00F7BF2E9D79623E4CD5A3F7862DF6D6EFAFD62530A81F2922ADA1DDCE87DDB48E52D852D28304AE403C86D79B6D7FCB161C02D33F85D8BB3695ABEBE239F284F30C64B9328954C4861A9D9E8CFA74DF94346A0AFA5D334CBADA8A86509402AE15BCDA4D8490125533F38B5B173C164F8AC424193214BD5922AE76A55EC06DE11C833FED56030CA5F162D0821E8A50B8EA59AECE63A7DDAA7B49A94CA32BCA4A53671B79D6D4991FDA640133E47CFCB1DFFE1A7C3A39924E231D87E0EED890A4DDFA8ADBC9AFA793FE2AFC5299972C4ACBA7F7DC45415DDAF98A509A57968DCBA35A8B3BABCEEB5CACABAB72A8B8A2AE052D5099E504991E57E533338EFF0085CBE4F673865CA94084B00C1B7B9FCB6E1A91C067E718CED0054CC44C5A42854124924EDB30ADC784343D5A5B6437629779003C3C3BDC093BFEF9CBC9C7FEB4F0A93C06C4BF938A0B50EA79561A0C18C19EF0AF8F5F5DB7F0B7431BB2E4399B1197E5ADBA9754614E702F8403170A2909023CFD30E4C993844F7EB9A193F31147DC51DCD7D0E85842C31699E44BE10D40FE62A49A0DEDE57B0E934E64BA5984D4E62B43998B838D282AE2248BC5A529B5A481327AE2BF982E6672BE1C3C95144B35531170C0B1E96D7A42F2B2EC3A4778B5A49502458B36F5EB7FA9AC3B52768350EB6AA44C5234994A3BB29320587D88378EBE7732712195F67A6383310470B1729DCFD69F5EB0C7152E4CBE208502DA8F1D411BFDC08A6B36D4F5544438FB8A750F71142F8A763264090396F13B73C745CB324C31212402B4B3B80F514A11B8DF588552D6E785CBEDD357BF4D6A6915F663AC12EF1092679C9F988B753691E918B2272A5CB712A5B8A51987D4FAC48E152B985969246BD01A7566AF9440338D4895C70AC08E2913173F03CCED2475C59F27C2290969D2CA53A72BBF27F06A5A251587080080D6E54B5BA69BB12358AD735CFD6A514A572A13B193F0DC9BEE2E4CF2C584CE918541AA52DA9A9D3D2FD5BC635280D40C7993E30DF9465DAC351542A9F22CA6A2A9C5A9295BEA429286428D882B4049045EC63E2315ECC33F91282809E974BEA97D4DABA680758D084E8AB339DC9D3A5347BF28ECD683F65862AFBACEFB42CDC30530E0A20DF15EC4A4A9A544C45C8B1BF2C72CCEFB6B880A29C0A3F505D414CAE1E1AD0824D79B7F319FF6FF00B884DD892F6D4B6FE3CA3B2D97A748E8DA6396699CA695A0A486DCAA5212A5BBC0212415A0A916BDBE3CB154387C7E7E1588C56257420A52C7E4D48A5FD9B184D402E882585E80BEDD05B6E7AC36D7E7294A56BA806F24153A4848BFF4931EE03D7AE24F07947E9871A0998A0C48E121D9AA6E796E1ACE29A2A5AD3423F1AD36DCD7EF15E57EA96E902FFCC15A144C24130D81E7263E3CB98179895350A5241C39045096626C0559A8DF4D69191C61C90EF67A5BD9D2FE71516A3ED0D0C970072499E704C728EBCADBC8907170CB24C89A9038784B8D59AAD5F3EA06D4318214A366F114F7E315557EA3CE73E525ACB32FAAADAA04F70C06DC4B6E1302EE9414245C1249B832671699589C065724F7A25ACAAA1D497A6C2F60458D61591395248649A967AEFB1A59FEF1BF2FEC875667EE7D735BAD3A532F242843ADD515A39C869414391B89BDFCD15F6F24C99331380C195CC450000A5EAD761CDFCE1CCCC54C0A294925243B87E47E94E74BC4E99D15D94E97434B08467EF23ED54ADD718EED49DFF96A242A6368F80C404EED57687325A532C4DC1A4B8E04A78DC1D8B53AD2E23518D50354F15033ED7F1DEB47109732ED674CE4CC9A4CADBA3A100708E1A7694A03942CA267DF208DE775A56498FCCD5DE4D9D384C2039254012756240E54E8F185636610DC2A67E9A860ECFEF9C53D9FF6C152D9E2A3CD9FFE7717136D32B7A609800241088BDA00DAD8B764DD98C065EF33319885BD7E7604355DC972FF0047E6CFB0AB188A4C3C2D4F9B5AF33EC88AFDACDF5CEB3ABFABE51936659938B5405A9A7E992A2A3FDCB404C5F798138B0CCCFF00B3D948225A641290593C4870DD1CE9A3DC0D61E1C3C915E201BC6E2EFA0E55040701E27B45ECDDDB3E7C84395D90AB2AA65805152ACCD9594A5512A2D1701300EC47E00D6F17F19329C29549C3E152560904014D6AECCDE7472212386921CF186D6D576BD5CEE2DA120C7D69E3E0F47D6C80807700FAE0820C10460B49511161CCFE9EE8C1046D423E1F7FEFF41E4410A020FF00E91E9F8608232EEFCFE5FAE08237349E124CCED8D16680737F2FF3030370F1BB0946186C3C840403B807D719722C488180B0020C62061B0F28C929E29BC4608CC65DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1042AA64F09573C1042AC104182304034306081850B5ADEFDB4189CCAB32C3E102C4E0090000E1FC8B7D9B9C6ABC14CC5074288E1B73D3EC7C6FCCC218F9F2F18E25D097B36B61B59F5E95B335C89987352FC2EE0DDAA0F27B6F4F28E201DC03EEC5715964FE22A0A535C162037E0FD358C271A38B8483521EAEFE0C2DF6D9A081D07C06257053460C8EF403C2A04BD2BA8AFDEFEB137879667B0142C2C3A8B5396DADB44EFBD50C42984CA3FF32C3DDC89B1BDBD0DB12788CD70F8C09969949530201A6F714F0BEBB46D8CC30C2A4AD6A6D6BAF83F3AFB7E02D971B554D43818424712CA884EDB8F1116B1BFAF2C2723B353735534A96A1C4400C1E87A0ABEBB522A599F6B30B964A513312E906EA03C6FE26FA333C541DA0F6D7A674BD306289E6DECC21C4852553C2A168316E9626FD48231D2FB31F09B3099325CD54B99C2483549EA2FE3F5611C1FB61F14E4290B44A9E051428B048F5F31E0F531E78F68FDAB679ACEB5E1555CEA69829412843A4002F000491E86DF3C7A7FB21D809597A658C4C80B147E2480777A820E94FE44791FB63DA2CCB369B37F4F8B98905DB8546E6A2C5BFC6E0353ED39F5BEF50E71252DC0EF56A51E2264CDC99F75F1D824A30B95202644B4CB7150960ED7B0D3CF9C735C160B1656A56653173C9248E304D39151D5C3728D0D507D62A52CD3B6BA92A500549E2013B740A1B99E7CFAE23F1D8F95381709D6A6A75A134AD1AF577D8C4BA42650F91013C3FDB667D1FF001A88B432BD0D49414EACC3397D219090B0C2889E662C67CCD8F96F8AE9C61133BB9293C4AA822C9BD7C5DE9D21B6214A52439A0D1C543F3F4FE6AC79CEB3628D2BA4D28869829052A584A7888F252D3C5C8DEF688C4AE1302AC510AC5A9534E8092914E42F4A795223A62969712FE471A6A75D68DECC55199EA1A9796A5D538B150A278C95920ABFD227840B1FB3BF9E2F794E12522584942526C01001A35CEB4A353684D336711C2165B9DA8F4A07D5EF468AFB36CE5B85294E78AFCCC73EA6D6DCF962DD84C12569E14A472200A5431D3CFC7946122613572FA93720DEFA3914E422B1CEF3F70777DDD484B7E20E34471F780EC02BFA63A889D8733896C3E4F3259E304EE4B353C1CEBCE8FA448C8420BF100C3EC06FF715D62B1CD756B6959629E9781D5482B0E05993009E1F9E2C3231185C394F7E525290DC2435854BDB6F06A8B44B495CB9690C90EEEFA6BC8F2F58D794E88D73AE1E0C64740FBA0901EA93FCB45325C363E20028104CC6F1104E18675DB3C0602504E1D32C5083F30736F122D63CB91DE74F49D406B6B4F2DFD3A34766344FB30E4FA74379BEBFCED35B54385C145DD9042B7E096D445AD7237B75C726CDFB7B89C428A70B2C94A9C779C4C13CC03CFA7943454C4B925437602FE1717BEADCC98BF69DEA1A1A3728B4BE594F454CD25282F169A2B7922C93C4B4858889306E0ED338A82B133F19342E74F54C5BBA6A5210ECEE01634D08A784325CC592529A03D2B7F2D7EDCD9BF88D6D1F7AE57B854923ECF140883CA63FF6FC394E60F2B13C0E22492000C08776D75A7F8864B953947F716B9DDD8B337ABC40F35D4F4AA538A6DA085A64874AF842226E12A0019F5F518B5E132B97804242A604A1603A08A9AD43E9734F2890CBD1C0FC4E4D402742F5DF76F74A8339D7CC07974AE55BB5EE9202596DB5C09361C4806D31CEF1BE2CB839397280485A11C41CBA85FA13E5B3BECF28426EA0EDCDBD61137936AFD4AA6DBCBDB5E5197BD77EADCE17613C8842E15617107CB6C2B8B19561105969993B4484D49D03D58D817D34A46532788B80C3572C3D6BEBA7521DA97B3AD1F912BBED539BA351D427C61B334812B17E1250A20DEC6D163EB8ADCEC563D5296AC3619724A8FF00B6A0EA7008AF0B6BEBBC6552D095014551EFF7F5D59E8766FCE3B60A3D2FFE4720A0A4CB29D00A1A6B818A85D504F475482B411D4193898ECEF67CE7EBEF33698A42E5D415CC32C3171FB78922C36D9EA63454C42414801376D58F53CCF872678A633BED3B51EAAA834D4B479834F38A29406987DD696546DE24365B4836332201F762D98BCAF26C9C30C44998A483AA43EE1DEBB35FA930DCCC4A9D400246BB8B73B7873BC3B651D8F76C1A8D21CA8C8D54744F416EB975CD71F02B752A9F8829300FD95004F316B56E776E72FC14E54A46150B5208621373D598BB7A8DA324CB090428125C10D6F4B45A593FB2665A809ACD59AB0D42800A732F148B49EA51DF2147E37E4646D86B33E2662F8BBBC2E583855699C403529429B83A75148C254805D469A5363416B1D06FE962651D96F64BA5160D268D6EB2AA53354ED738A0B52765774E7104ED31104F2DB15BCCB36ED0668A4CC9B982D085391282384240AB3A59F6DEDE08E2B1219A586291A7D37A6F5F48B21AD48E65F4FF0057CBF2ACBF2BA303847053D22D684C58F106F8C9F7C8F9E20D7964CC44DEF67CD9AB59673C6A00B07FDBC5F4E9710C3F578866EF0B1DEBF588F3B9BAEBD6E29AAF5BCB0417525469D289D8004A527A1816F7E2464E5F2C30984166009009EA4FE5F78D3F513BFE6AF323E847E23DECC7C878FB35060820C104668483337DA3DF82085A845801CB73CBF7C86082378481B608239C104184E669E3F6820C27041820830410A69D20F1126361820855C23FBC7CBF3C10473C00ECA9F77EB82083BBF3F97EB8208C8009993BFBBAF9E0823991D47C46082091D47C46082091D47C46082091D47C4621F3113411DD922EED57D4F93B1D59E257018A972814AD9C8A39A16E5E2FB738CA0F43F0C38CBB106510269AD1C973776A73FC6B1A62A4271615DD01E06FE3CBDE91C7BBDFD316B463642D2CC38D8598EDA7DBFCC404DCA57294555046B5372FBF5B0E8638E24FF70F88C4762B013B141465A4925D9ABE81B4E9CA91B0CE64659F2CC58043072469BDDEDF7860CF3525269EA735D52F30186D2A53895BADA490279150240E606DCE3161EC8762B1D986251C52E61054E070A886B9FED6E9BD6AF143EDAFC44C24890C99C80A092C428072CE351D2BA79C7457B62F68A73375BF95E9474B4471216A6CDBA13361E97F4C7ABFB11F0F4618CA3889628C4BA7EFE75B08F2176EBE22CD9C26093394CCA145EEED626FBEBAD1E3A69996779ED6BEAFAC3EED43EF9256788A8B7B9BDCC4836F98C7A432BCAB2EC248484CB40EEC072120396AE9A757D3568F32667DA6C762B107FDC591C45AA58392E0BEACDD3D21BDA7F2FA154E64EA9550B8E1404A892A2622124F5DA06E3918C298DC44B961E5A512D20162C34B52F5229C9DF789EC8B13DF9499EA249209E2BF874ADABA6C048B2DD2F9FEA073EB4D27EAB9332429D5B812DF78DAAE3842A167C3BC4C03E726978FCC53326A65713A96EC12EAAA7FE4D673BB06B4587384C94CB49941367A36DECF5058D584E4E69A774A52F7394B68AAAD4A48754A9B2E3C5754F3FED36E62C30D6565F89C428F1A1610A6F95DDC3BBD2941E9D62AEB584D8F12AA09EBE60536FBC5699F6B673325254E3CA6FBAE2E2A70484906C048201B7FB5F169C0F67E61E17430A3121CDDB930AEA5C4205D4E4D46BC87BFCC54B9BE785D5A8B07EAEA932A9DFCC93113D245A7173C0F67C84A68C056C1D8F205B91F1A3C375CB7341A50FD8F5FBF5884E699FD5AD0DA1C8847142D2A04AA44CF86E23CF9F5C4A4DCA972787802985E9D35FF00378564C906F53A8A55AA3969BEFAD4D659C678E1529216A2ABF824924DF95C99F4F332379DCBA6A70AC66D367274B97366AF9738597213AB31140DB7F25FF10D195E9FD4BABDF5D365740FBAB94A0BAA4A9086B8F9A4A841041E46DE5CA4719DA5C1E1E51056805B7AF956A29467A79EAC6C68123414E5B54DBC394762344FB346459625BCDF5D66A0D4D9C6E93BA2AF172492DA88DE05E773D231CA33DED5E23133169C04854E9609E29817C3C2E59D8D09D4FD890C999852FC4A22EC2A6DF96FA0D62F7A3CCDBD2ED2F2DC9B2F62832F74043354036B5D4A50224829E3470EC66F27E15F91819B9B28CEC4297C52AA904A83137700D40E6E28C1A1133D75483C40B798DBCFEAD0C55F56D289A9A86D554E93214A754900998F0CC45EDC8C46155640FF003214E454802C006BD3ED194951503A9B87DBA52C1E83A8311C5EA4038C38FF007684CF7680809088E448DFCC9E7F0C208CB664999549D1F7A727F7D21E4A4BA8248626C5BCDBD9FCD51A8F54E7755589A5CB10E3E952A09424A80E57201DBA74F2C59F018D561E850CCC03FAD4DDFAB3D2241186E3B5199EFF009630A5DD179B6694F49519C560A1A532A711092A701024182088DB6C6732C562B31E197870A2514570DAAC45474EB5368274AEE1228C2C74D9B5356731B54AECFF0046B25CA6A0A7CCAB523894F2AA01525606E1B5151372791B817DC8C60B2AC62B87BD9CB96C352479D5F416DF9C240BFA1FC7F9EB102CFBB58CD7345A32AD314350F553C4A1BA56A95C4366E213DFF77C207424C74C58F0F829186509B3B16898A4B9659156DAA4D033DFC2360A2011E5CAAFEB1865BD8BF6A5AD9095EA0617A5D959E21506A5BA92A49933C09585260728BF2DCE1EA7B6B96E01250252710B45199813B71330E77E718D9CD0D5EFE3EEBCA27D967601D9E64C108D639B1D4158C90695052ED3C2EC5CBA150676932003D23142ED776CF34CD8A1394E19783624284924B8A307481CCD183F388FC6CC52280EC47E3C770FE348B8B2BA8D3DA5E9114BA7A86872EA74240495D3B358E2D226DC6E214B13EB23AD862B3864E6D8F081994C9F420875AC1AB12E1D8EF0C0629490C1C13D48600D395EFE50D953AA1AA8716AA665D65D905D79BE3E07093E129680E04C5AC1201993CA2E385461658509D350B0C004A800400198A8B957992D7D635FD612096AEAE5FD1B5ADBC5F44C9ACCEF30584B4A79D4AA3C3DCA933B40E22981EFDFE58D978FCB70C4944B4A9B6200240F07AF2FA467F52B7DFADB56E5D474D6B0A7FC2B9FD514ACE524857DA75750968A3A10851133CEDEFDCE23E767F2E6B2508091A1150DE1D18EEDABC67BC330D284D087BDBD34BF2EAE6D7672E389E3ACCDD3978DD48E10F01CB70A8F94EF86ABCDE6A52552D0A98480750F566D9C0DBC63520BDED42297F7EF7D4F68BD23430735CF3F882893DDA50CAE9F808FB576D438F8AD726D1206114E79892549549286622AFE83C7762488D8D855C540B0FBBFE0347B95C0AE9F31F9E3E55C7D9E8DADA0999B7CFF007FA608236F77E7F2FD70411B5A401337DB718208DF8208304106082324A78A6F1184E669E3F68232EEFCFE5FAE138236B68179BFCBF7FBE98208DBC09E9F33F9E0820E04F4F99FCF04107027A7CCFE78208514E002A8168C1042AC10425A80094C8B4608213F027A7CCFE782083813D3E67F3C1041C09E9F33F9E082324D10A93C72AFE544004DE76B741F8E1DC8C3A2783C407537A3B01BF37F37B44E3953D2B4997C4CE6D6DF4FA6BAEF0E0DB8FA07748488800C807CBA44F337DCF28388DC6E0D6853490E09A84835666A8EB7F1312F97E3C480F38B505C80E3CED4FBED1A5F7174692BA9521B61CE2EF14A2910123DDB091B73C3DCA329C5E226A3E4590486A12CE45A9CC72DF410CB3EED66070D87983BC9614124FEE48D0D3AF2AEB1D79ED47B63D37A5E9DE672DA943B570A078566CAE7CC8933CB6F863D15D8EEC1CCC70477D289A24D52FB568C18EBE2D5AC794BB6FF00113B954D32A707054C12A1CE9473F8B3D5CF40F5FF006A59CEAD71A43952F21849761A4BAA48712ADA4248DB9C83E5CC63D43D90EC4607289056A909E32126A914A54543F3B9A3758F2DF6A3B7D8CC7CD5253354415100859347B383E914C54BB534C4AD973BA0ABAB888515493375C1BDFCFDF8B96225C8C24AE3949482DA5096D8E8CDF6778A32F173F1A499855F31AB9A52BEFABD617646D56E64EB8D6574CB0FACA454542C1291FDAA01620082660F493D2A58CCFE6A55C090404D1C3D2E6A35FCDE3072897FBEE4B3E9FE2BD356DA2C8634C69DC890330D50E22A6B40E36C724AA398448F2BF2DCE231798633174758E226B52C05F4DB4FA464BE098A0971564914277F53E8F0C59FEB9398A1BA7A750632FA4E24D321B86CA81B10AE182AE51C409BF217C5A3B3B94A5466CF5CA2A9931B88A9D56B33D07A56F183984DC480164B25E8F67ABEF563D68DB1AA735CE91255C769EBF39264FDE791B63A160F2C007EC0E7968CE0FD3A728DD0AA9737667F7FE62BACE738010568584AC025299BABCA79C5FF002B62D183C081F2292C926AA6019B5E74F585C70A5882F77BD7F0DCEF155E67AA9F5AD6DBAB0CA45B912AE5B8BCDF95F9C6D13D25183C3B1510784B5D859DDBFC7842C9009259C8BDDCD051FCA18E91CD439E3E32FC832EA875D78F0AEA8A565082A220C389200BC83378DF0962F1F824216A98B425206A5209A56848B51D88D2F028F7601259DC74D7D6DEDE2FCD11ECFAE53A919CEBCA80F03C2EA59B022D37EECFA4D8F4C730CDFB49266AD72F2F52A628062405009BDBADBD7A616B143B8717AFA534A55BCE2FC6ABB4F644C228B4FD3329425212B525B485022C2545215E867EEC50B158DC5CF980ACA96A7F94D58576B12DCAF7686EFCEFE2FEF7861CCF3543AA2E3CBB7424C08E8240B7E96B9C4E65B2573B87BC04715E8C0ED41BF87E74324AEA5C9DDAF6D010F119AACEA9DE6D4A4284B1C50A5287849E8933EB6D8E2C404BC0002628049BA451C6CF7FE29BC09C3D406A93434661CF42DE3D4DE0EFE7199660FA9965E5D409212DA5B2916FF58106C2E6479CD8617958EC19708940391FDCEFCFD61C264A87EEAFDEFAE9E75BF5C93A7731AE5A6A334CC5BCAE8A98F12E957C0A35C954784AF88291C3039DE71B4E5CB5292997244C2B70482DC1B1E6CEFCEE6B0FA4C804B936A8D3952BEE94DDBF34ED0720D3ABFE17A572952F3357F2CBCDA1CAB0B7088064B6B489DCF8A3AC61EE1BB3FDE052F198A4774AAA65964B001C7CC0825835361489044C9690C181F37E5B5ED6DEC68DAAD2DDB06B30CD4552065F973D252FA9DA76E1B277EE8A924100DEC3D37C6ABCE72AC8A62E4E19231539D94C951029AA8022AFCAC39435C62CA920B7D093BFA379D21FF2DEC4BB3EC9168ADD539DBD9A6683C4AA64A2A0202FA12DA94D913D3CC6D1883C7F693178D98512B07DCA1569BC605D8FED6069615F2AC4705A48E251A8FEDF6DBBFA74B0A92BF2CC98219C972E672E60C065D1469AB71F8B4951694B6A37B91336E711189C0AE7A92A56348A12471D89157655486FBF4D04D2096B1B0A7E35F4E70F02B7516663FCBA1755C768314DE83C5C200E5B5B0D8C99787078E626601A8AD87224B7BE507784D002454F3DFF003BF28C17A1AB73458733C6DBCAD283FC950A843EA7A7ED4F0A8F0F0C73DEFE987D82ED0C8C220A25484CD5D944A4023A15276FA0A6B0CB1838882B0C3A8377D06FEE90E4D68BD2796A439559877CA489293C66E04DA146DE5E76F2D3119C62B1CAE14E15287A382353CBEBA4302DA17FF34F4BC64ACCB4750A0F754A97DC16061420898DD379E968DEDB61AFFA4637145C2D487B3F3BD29D5C884F84EA3886E28DB0D2FA0B08677B5CE60CA94DE5342DA132027F968317371C49E912461D48ECC82927118863A82E3D5F71EED19083606BA52D4EA012DBFDE1BEB351EA0CC0215983A5A0890D25B084833733C040F59F779CBE0F24C14A1FEDAC4C7A17D1BA9B97BBC38972D44BD9B9FE3DB8863A8CCEBCC8352E0106D0AE9E768BCFBFCB121FE8D216DF28045ED47FF1FC428401AB9E43DFB6D21ADD715557AA754BE01E13711CCEC47C67AE355E4320B1041BD185BEF6B51E8CD180CC5CF41CE3E827813D3E67F3C7C7F8FB3F1B5B481303A608236E0820C104182083041060821553278B88CC6C36C27334F18215777E7F2FD709C119A1004CA80F5FF7FDDB0411B3847F78F97E782083847F78F97E782083847F78F97E78208CD20098333FBEBE78208CB04118A93C51788C64249720381730463DDF9FCBF5C6AE096D76F7D63608529983BDBFC5E0EEFCFE5FAE1512A61B24F913F40605A4CBAAC30DFF003B41DDF9FCBF5C2334F73599F28DCD3C77AFE37AA299A859E14972341527C89B7B78534C9525445E1504988100733FBB4DF082317316B12F0A0CD0A2C420D9DB40E75AE96A562630F2F2E97256BC7CF97228E9EF080E79390FE1C9B788CEB0D5F41A5A8DCA875E6429092A20BA806403C8999DB91E5B418E89D9DECF63332988E3C32CB91562589E4CD476BB53998E3BDB7ED465D97226FE93192D7C214DC2A1663B135DEC6F56AC744BB53F698A9CC94D65794ACA427BE6DD5A0C8BC817FBAF8F48F64FE1AF109532661D8FCAAA81D59CED4D0D5F58F1AF6D3E27634CD992E54E5A9CA83824867A7D7C868D1D42CEF3E5D73CED4D7D4ADE75C5710495120711FF00EA039FE938F42E47D9A9397CB4012C7CA120BA59B9D458372B470CCC3B498DCCE61E352C827576AEEEDEDF788655B952E3EC968294F2CFF9742415711D8F144C0DBED45FE387B9D66E9CA6584259D42A686DE9BDB9C37C265E9C5152E62C39AD7C4EA77BE8D13BC974066F99A5198EA17052D23403810A521329F301493CB68B4CC75AB4CCE958B484A428A967E54D58BDDEE282F5E5D1E9C2A247ED62CDE8DCFF0005DF61128CC7566579553232BD38C349718053595090388923C264893CEE955BEF7182C82762662A6E25C216C509290C96B8A0A9DDC437562D95C201A5E8E7E87E8DA3EF54671A8D0B5A8D73E5F52893E2511C27DE6F1D7A7CEE380ECC4B29042028581671CF47D0F23D2009FD439340AB3F8374A6BB5B940B31CD5A4C2997070AE7C01511E9E5EE1B7A62DB97E59FA67404301C3A0F32E1FC7A50886B3F08B92C5150A3A07F56B6CCFAC40335CD9C4F100BF326401E46F1E9EA316294844A0EA4B3022A2D6FB7D6D1ACB1301AA4802D47AEBA6AE7ECD15DE69995556D4D35252A1E7AB5F2A4B01A6DC713C52012B294A929DC594403060E1862F389387491DE253BD406141B8A8D39DA1E4B06A542B4BFE2C0DADE9170E89EC0F36CD4359BEB157D5E96CE21B252494EF10D906E2D713F7628D8EED580B992A44C2B58B241372E3F75A8EFE778792F800F98F08AB9D69EFDBC76068FF80E9160506459730E180976A6101482810140AD24C9BCC751B462A1986698EC54D96662662D21D9292A003E8598173BDBCE23F30C414B7764177AD2FBD34FAC26A9CF5B7C2D352F29D4A859B014902DD45AC23F1B4E2532F94BC40654AEEF89AF5D28E5A97FB8BBC45A264D591C454403CF9EFCFEED588CB953474A8A87DA4C950920927840BFA83B7BB6DE313B23279666A42D21DEAED762E5C359ADF4899C3A09038B6A6FB721AEDE01A206E664FE6D59F56678F854A8309200927E7D24DBC8624274AC3E15C24A681C00DD69B695F21BCACA93C4C4DB6D9BA69FE3687E7B45505232D57E6F9A8A765292B5309256B77994F0A145423CC7A6F3881C662138C981082FC27E773C2C0D475B579B43A4E1A5862A2036FA9F37A368DBEF0C6BCCF35AD7865BD9FE9E5BC80425CAF765B027FAC77E913CF63CBD063051230C92A54E48091F33548A5A85FF008B18D4A253965060ECCE4539BFD4D1D8C3E9ECB9FAE432FEB5D48595BD25596328E22B3B9471D3AFC3130277D84E1A2FB45DD14FE9C7788018AE8967A588721F97F0D2694A49F99B60E45AF725DABB7D227FA6B4BE41A711DCE95C9425FB7F99A86CD471AAFE206A10AE199EB691888C6F69A64D2518A52E6CA49F965A54A9652F70E92FCC68F4869FA9E0A8FDC054DC17BDDFD37D61FABB4AE7B5EB69DCFB8282957C45A79B7D0070FF0051EE5A5262DFD247BA766927B6B2706152E4600AC1038B89D45BFF005281347F5EB0DE6624CD62A2F7602D7E839B7918E5BCB343E46DC9CE0668F0FB4C2E9D6140F3016AE2927A8E7EB25A623B513F18B213853281B10FAEE3847913A7584DD2F715E7AD21BC6ADC9E914E0C972B69852A05429C21D0E47D8E10EA484D85F86DBF4C2F84918AC6AC199314800B8BD1FA5E9BB585E91B8243B6B786AACD4EF541934AA120CF7083EEFF00869171CE2F8BA60B2247085CC9E8593A294000D615569FE37813C27FBB6D3DF99D8B88630F66398929A3A6AC2763C61F0049B01C6047BA67D7066392E1528044D948D7852A492B6E8AD07F26129F2EC01E2B3062C0BDEC3C284F58DECE8AD61527BD6E914B46F0E3C94C4DAFC4479741F2C44CACC70B97100AB8DA8C0120FE29CC4371289B1DBDFE37E50E88ECD757558E34D332D773757154D39E29E775CD874E91B61E1ED8E1A538EE540A87CB425F42580A78D77D633DD172C41B569FC736BD4B73854741EA36C774A0CB6A00ECE30AEBD0C0F7DFDE30D2767A8C602CA992C1D4254E1EAD40F5DFA467B956FE405FCFDEF18D3F673AA9EE33C54EFF0040AA8A747044EC14ABCF2E9F2C311DA03972BE554C98146DC0A16EA0EA5DDAD6DE3432D40396E61C13CADE31ADEECC756C1229E98EE20D5D34DBCB8E3A6DD646D7792FB6CE2A8586A97496AEE18743E71A80F6FA81F5863ACECF33DA28557B494850F0065C43C6DBCF764C6DCC5F962630DDB01378B8525811C44B8EB7B5EDE87508502035DF51A728F7531F24E3ECFC6C6F9FBBF1C1046CC1046494F14DE2304119777E7F2FD70411B5B40BCDFE5FBFDF4C1046DE04F4F99FCF0410A69C01C51E5F39FCB04288D7C214E085235B9CBDFF008608C100DC03D635E08186C3C8472013B0C1030D87908E7815D3E63F3C1030D87908D8DA157B74E63CF040C058011B3815D3E63F3C10307076B78C668044C8FDFEFF0076C6C2614B2407E2A01D2BEEDB3C359FC5C40006A6F4D05DBC2F5BB346785D385A778A21EF7E9A13A7D99A24E44B44897DE2CF152C6F4366A90DE16AC1C2AE12A4C42374F320D847A794EC6D8D6667327040A182D5616D5DC59CE9EA219CD98BC61328A4A454055A9AF8FA3D1AE212BAB65B6D550B712D21B054A2B206DBEF122DB7218CA32FC57699918696A495020F00DDDADF8262B79AAF0DD9D44CC5CDC5051038F8491FDB56A9B5361E4E2284ED37B7CCA34C5322872F79B72B569752A29503E24881C88E7D7A5F1DAFE1A7C1CC561CF7F8C42A677842871A0B5CEF414F3178F297C56F8BB88CD8FE972F9C70DDC128265AC8E236FED22ED53D4F21E74EBFED6732D575AEA33079F4B4E2D413C2EAC24024C084900F291BEF8F567677B1785C0703E193403FB6D4D4355F937DE3CEF8CED26678B2A13B17326715C9528D198EBEF6D62A879229525C2BE2454DD3C4789422E7724CDFD79C6F8EA38746130E84A1084CB54B152183BDBEBAF9B522BB89526629D63BC7724AAAE75F07EB42F7B99664398E67529552214585195A9426C62FE2DA2F61CBCED8431D9BA2524A1243B338D7C00BD9CD8BF488C561D0E78500381E0C5E963EA4DA2DCA4CA74F69BA32FD429B5E6CE241610BBF8C0B813206FEE33EFE7B99CCC466B8860925292DC4347EBD3F11A80A940949290A34BD750EEDE8FB8AB18AFF0039D4F9AD71719CD5459A3121AE05048206D6410761F9626F26CB1485238D1C5C2DA37D07DD8B6D7D54B529DCBBFF0098AD6A3306D0A78D2BDC2DA2EA59333EB26E3DF7E5E7D37098796108050EEC0066AF27B0FBEF184A52028ECCE2BE15F637DC57F9967F975538B69F05D7A4C2C15244DEE427A799F5107162C2C9320278260969B94B03CDF88DB9D7F11BF100CC1D85DDBAE95DE20D9AE6C9A3E04345556F5448A6691C454D907621326E0F38F888C482F1B85920AA64C4A5491F35871B3B16D0D05BEF0EA414AA93038A54BB0A6C74F3076898689EC7F5BEB379198662E9CBF29242D69742012DF41C5C2A88E979337E543CEBB628904C994388A9C24A6AFB59FD5857A8859425004200E26673D76FA3116F18EC9E53A6744E8869C672A6587B30E148AE79C4F7AA2B47D828EF02B809BC94113EB8A5946619C4C98B98552D0B6E1AD3CC1F4FE59152411F2B12474AECE35E7EC21CCB54B8E9534D921A1221321201E8040F2DAFD2F187527B30A92F38CD2B53394B17D2BBBC47AA5CD24A9C9074B54F4A5BA6E6230E6614892A52DE879C32DB241FE6904C82B261113CFCF98C4B610253FECAA504B515314038E6C4574FE630241511C639EF7DEBE875E5766AACD2ABBC08711F524A8C02DA7EB5C5B6E5B0787DE47BB94903849201252B53514070D7C286B6E8FCCA889291FDAC5C31A13AF5F752F1B5BA3754D97EADF729694C71250C29F5D6CEC0A100AD920F2816E5D62F1799F00A2824070EFE55EB4AD4F8C3A4100304D5B7BFB7261D6974C67999B61DC932D4E9BCBC5D79DAD48A979C4F350A273F9A9BC8E1099FC2B589CD0AE67019C78D40F0B3905AB734AB0D6B7D62465CE64BB0005FC6CFA9DE9D00892E4FA1320749152E556A7CDC91DD553A8A8A1692B06F2D2C06A395C006E7D21A662679F9C4C082788F0F10268FA82F56AB55F90A35C5CD247CA4B52A2D714B7B689F2321ACC9A9C9CE730A6CA68801C148C32C3EE2D16F0778C8E3498804933798C3246266E20A97294B98A059414E90347A96363E50C8CC58001554BF51E2E6EDD3C6191FCC743658A2FAF2071E7D5766B5558F2FBE527ED1EE1455C107900266061412316B981427F0CBB997C03415F17A6BE75867366926A493B1A37D6BE5D06ADAE76859DD52CD2E474EE32C1F0A51F538001DA5C53408B79F9CE1C7E8A42D7C5318AE80FCC2E07FC41EB7DED0D56B58D68795AD478C469BD61A865EA97954284DCB86A12B94A8CCF76560A607288EBC861F4A380C229A64A0A245B878812D6259BEFB5A149014A075B6B56D287EBF57785AD681A3A24F7B996A843AB172C7D5D33E63882C9E5D27A635FD58529A5E5E9087A2DC55F56E17047DC690B306BD7663F58D4F37A3E9212FE567315A6036EA5F71A8237242779E876BF5BE674DC4BBC8986504B12909041A6ED46B0F3E990A2976D7F98DADEA6CA6800FE1F9421881E12A577845EFF6C198C20BC562D48E05AE62C30B122BEAD56661F88C0252EC5ADB69E11B5DED033152404229DB4806006184904ED278413EFDADCF19C26055885BB4D26E5E62C8A6C0F8EF734A46C662CB39B72F7688C663ABF50D5CF7550100FF006F0276EB045C0E87160C3652400E8A0DEA7CEFCADAD76844A1C92F53CBD2F11A39FE76C294AABA97561CFB1C2E28011B93C26FE73EEC4B48CA9142A969F14026FD2C7E96178C701B7153DB307AC267351D6F279E33BAB8D667DE5437F8FBB133232E9691492936B20680727209F08CF07FDC7FC5B5EBE7E6DD51A96BC1003EFA45FECBAE0DEF78541D8753E98CE232993359E4A054D4A053500B03BD396D0DE70502DC47A837B6A0BFAEDA426FF1357EDF58A983FF00EB391FFF00DE18AB2295A4A4D1EC903EC5E1100837BB6F7D353E821C6875A673421C55357A9A0A8E34BC03DC7D000E93C31B1E1DFDD76537B3C95824CBE1356091C3BECC096F5F187D2DC3B726A3FBFAD63DF2C7C938FB371B1B04CC09DBF1C1046D83D0FC0E08214D3A24AA645872C1042AEEFCFE5FAE08233420099501EBFEFF00BB608236708FEF1F2FCF04119A4013041DBF1F3C10A4BD7C3EF19608523058262013BFE18208D707A1F81C1046E6904CCDB6DC608236F77E7F2FD70411B9A6F7B13B6C0FE1FBBE0823670A7A7CCFE782063B462B4C0040317F4E5CF12783C3226254A590E03B1D99CF4FBEF1B15A1287203D6A5B7E77E5E20F2D720EC715ACD7309D2667732C1370C1EA3766353CADBECC82D7C454B244B7724D9AE69AB72F1A3430E7B9CB792532B3075F69BA7610A53C95BA8471003601441277DA7A461FF66BB298EED06253C4898CA5025D24DC87D85B67B58C577B53DB7CAB20C24C509F2FBCE134E201884F22EDCEEDE31D13ED87DA357982DFCA74D3DC05054DAD4DAE4133133B6F3CCF3DB6C7B47E1C7C2C465E9933A7CB0AA24974D281ECDD5B6F28F10F6FBE2F62F37C54CC34998A12F8949052A2C41A587837956E7A559EEA3ACAF792F56BCE3B56A52D49F1120124F99178DBEF818F5065B94C8C3CB0992896942000484A68E3C398AFD8C70DCD312A528CF99338D4BA91B390F7353CB7F186A6AAA9EA15C35C897366C4493681B0FD70AE33BBC2A7E42900BD38478DF9FBDA253882A62E41A3EADCDC8736DFF1129C934557672B5D5BEB0CE5F49C2A6C3D08E34AA09E1E382A8E71276C52F1D9BA04D1292BF9A61200487A8A55AC5FA5BA43D94492EC40D79FDA9A743D224798EA7CB74ED31A1CB5082F2014A9420C9D89BFCAF78E57C272F018AC5BAC9514962915A0EAEEC40D7587899695330E44F9F9D5F97845319CEA4556540AA75D5F7CC9596D209892798109DA3E4479DBF22ECED38E6A6FA9FE7CBAF9C32C64A0804B8A55F7045075DFAF3222199A6A4AECCC776FA825B48804285E0C72BFEFAE2DB2B289723F6A40DEC29EC57C623A2135D9A06F853DF453890F80A92676100C9B9E585D4A124306A74FBF88A6D56104194E99CE75555213A6A996BA752A1E75C050009BDD71B78B9D8FA623F179BCBC3A0AA6CC609D4338D2C1DFEF4BC0C5DB972F4F0EAFA6AFD83D3DD96699D28DA731CE386B33480B534A0A506D62E76E24804FEED8E6FDA1CEF1989983F4A261924B05071C41C034D81E84D2052CCAB1A9049E5F987FCE353D45731F51CBD69CBD840E1086C253316004705F6DFAF5DE4B26C14B992C623128E298402AE22FA9D0F3E8EC291A4B9CB5900A80E47ADDEFABBF5D6B1057DAAD4142DD54C932E158973E26F1D3D39E2E127F4E10AEE40240B04D88FCF94498410905B47B83F48E5450F2785082A7369402A9923A0373F0BFBF090C5094B69DF225E8E740357341BDBA438952C077B6A3917B03F7685997E83CCB3B2B742D6865882E305B23BD0AD8070C14111CB103DA1CDB0D2912CC85A4294E15C2DE16D0DFA878526619203A6E0BD7C373FCDA2C3C9B485365E90DA1B144BB0571A7EB7C645CDD5C404F381CF7B038A87FACAA624852DC0DEFE8DCF4A8686531205856E096F13A0B023A72894B191A288AAA29D4CE5F605ECC9D4B6E848022452AFC37E612075386989C699E82953AC2AC904A49634750723EF6A3420B5F097E26167BB72A36BB7ABBC20ADCF322A074394F5DFC57334EF56DB2A65A4A87FF00D327F967680784C917C212D6A5A12E8EED350A415711FF00C9891E6618AF1252A3F3120D8F3E81F5BBD8D7AB4BFA8B5B67A453E4C94D2251E1A851A569B35A954F004A948496F807349133279E159587C3021641F92A3E6248772410E7D6DE91B4AC42E6FCA4BBD09B7986B071E7CE1C29346D406CD5EA6CC4E5CB2389414B35416664C2428813BC45B688C2E7109207E8E477CB7A86EED88717342D537F285CA080E4814EACE396AE6A368E10CE8FA55ADC34E3367198EEEA0A96D06CC5CF74652A98DA396FB61E0C3E2A709678BF4C43F12182C2B6E41BD2EE690CA6AAB51C6FB16B015BFBD21054F6888649A4A26996DAFB01B14CDF108E5DE16C1B0E7EFC38465120A84C582B9A2A5414A0FCDB88016FCDC43798B2C00A0AD3F9F1FBDDC98FD7E7AEB890B4B8AA253A09E14ACB9F58E920186E04F4EBCED33232E4CCE10A008A5581296A8EA793F28CC87AB12051F9EE39535F2D621B54F55AD7DE2E8DC75333DF7D6942DC8844CFBA3711CF1228CAF0FC410141E8FF002B5090FE7CE1CC694661510A4D354164A7EDA548E38E6002ADBA6F187A32492082A4A549558BD4EFF7ABDC068C804D8437D4E635C8E22B7839E7C294CFC36FDF538712F21C22D8AC01BFCA0D43B506DEAD625A33C2ADBD47E79C34AEB1FA8214E2CB6048179E299F75FA1F5DF1212B27C361FF00E90E27B800A6A7ADEA6FE42321075207AC6835A968FF00F33B5A26D7F203F7BE1F232F4B8694F4FE6FAE8EF4D2F19EEF9FA7F31A9CCE5B48852FBCE9CF879EF73FB89C3B46014689484B3D680927AB7BDF4C141D0BF266FBC373B9E20589BF9188F4117F3C3A4E015A3807C7E8FF00568D82030715D6BF83086A73C64F0F2DF73F98E71F2F3C64E14CA7E21C43A1F03A73F386F3D0281BA1FA7DE879C26FE36D7EFF00DB1B230E85D801BD0D3D457942299628D53F4E7B7D7CE1155E6297D4DAC37C696E4ABC653131161138728C14BAA480E450B061A6E77DF485D2909622E35FE0BED1F4AFDDF9FCBF5C7C3D8FB350A69D20154C1B6E47CB0410AA0741F018208E426761EB10304119702BA7CC7E78208D2EA488991EFF00C8FAE0823540F3F89FCF0411B5A493C51276DCFAF53821497AF87DE37702BA7CC7E78214850C8202A45E7F7F760823760823058262394E08230E0574F98FCF0410AE99E2C25C4981C7B6C76F7E08238642DC778B913E7F18FDDB98112100D0C10E75CE328A64B40A42DC163D001279FE9F3185A54C9C169972D2A5719E12DA3F423476F6D198E988920CE5CC094A0124380030D5EFB6B5DAD14F6ADED0324D134350BCC6A9B2FF000ACA47109E20091201F302637F763A9F657E1A4ECFE6CB9864F105104BA4D053537AF90DA388F6EFE2F60F29C34DC348988E209525D2AA82DF5372C36778F37FB52EDA730D5D990CBDB7DD4654A5BA16A43CA40E124DCF0907D24DBEFF0052765BE1AE1F2244B5AA4A1C00E38439FABD5BF378F11F69FB779B67D8A9AD3A6196A52BFB8904134A3B3331D5ECEF1D73AD71BA7AC2CD02D4B43A654A528A8C912492A9BDF69F21D71D6B0988952909932E58433024306601BAD3EFB456D05253C53140CCE65C83A53EF5EAD182692AEA1F6E9D8A75ADF74F85E825283CC9E569E640B61DE2330FD22490BBD4D852BA02C75F7687C526629557297B6EE6FF005DE2CBC9B4AE5F92B69AFD46B4BEEA405A1361C24DC02127D224408E4315AC5E613F1A0A6529552012D41E7B8EBADE13485020B11EF5DBDEB0DFAC7560AF6A8E9A99D0D52520743286886C90409E32D9055B082A07CBCF6CB3294AA719AA492B9853DE12E6DCAAD7D186FBC3C97354E012C2BA7E3715F6D14B66B9A13C5078B7B9373E649FDF3C752CB72D421090120160E48B5B97D34D9A1F4BC400003403526AF567FB115F5881E659C2DB5A5B0986AA09E35822101331F7CF9F438B1A244A928E3550A050333E9CBDF3108E366A6600010790343671A9FB38A188DF05754D4A58CB1876B3BD304A38A1324749EBD45BCEF88FC663A5A41248480EE5DBF0FF009ABBD21845CBA5BB17A6AA6C66BA81EE1202568A55133782A100824F3BA76F953331CE809C9952419855C4E412C9E6EF5EAFF48D92970E4B6DEF6FE768B6E9DDA5C9694D164686E97812132128055C22665404FC639ED0045AF0E714A0BC4BAB54A41347E94DB9BC0542A1346A3EBA1FC73F1778A5566B98A56EA89E22A27BC2A215DE003FA649023CA36DCE25F0D82C2A929EF509734402053E971CC5793426651984FAF878F2FCC46DF759AA5296E2BB87A6787C44ABDC0817BC5AE2679E159981E075CA514A459AA29BD75236D2309C32829CDC10C351E2FCF67B33C6DCBB21D4BA96A053E5D42EAE92988151532521295DD2785513D6C77107081CEF0D97527A93C6A1F28A39005B97E4F9484B2A0068C0737A1B036BEDD18068BDF4FF0066F4D94B287AB2A43EF708516D4DFD9205E4FBBE1EFC513B41DAC18A131121010CE1252A724D6CD6D2947E7787489812CF524073B7DBF1CA251515D4B9636942DF699660CD3252826A026D0A5A6EDC4089B99E56C51309371B8A5CC54D52C8D0173AD3F716F768C4EC40018AC33073E0EEC1EA3F976888661ACBBC7052E4B953944FA8F087D3C5549715D7EC94A77F75F78C49CB90B47EF5D4E85874B9F2A93EB0C66E252A040A91A35B7FA56BE4EF0997A775167686DDCFF34148C0054C84F04BC93B8521B50298062E01331C8E1DC941E258BA92DC418B07B56C4977FE61929455521817A7B25D8C6E4651A5F20477C809ABAB45C28A8F89436B1240F4B6DEEC3B4380AE24B59CDC1F2BEAEFB97B3C335CB2493663CCDECCFB7DEB0CB5FDA03ABE063BB4502192A0D77684A8B808DC94266D1B9263961C61A5212A2AE1AAD892A2FC4CE6C6829D1FC61690952487B569E0FF007F3A4476AB3CCC3300422A1E7A6E3C0A2083E57B795A399E92885A1218048E6004BFA0F6E6B0E88704421629B397B8BB969E215B80D2A075984FC663A6D8593894A58A949049A02A0391D9EF5DA1A2C5880799F76A7BD96A348EA7ADF137401C0AFEF521A37BFF005011F1E9B6379998C8921D4B0280923E61E2078D89F48414973415EB7E5D7C9F4736507B35D66E82AFA8B4C81713594EAE29F22AF0FA19F99C309BDA495288EE54B26AEE950D6A2A069EE90ACA414F13EE05F6FC74DE13AFB32D6A1265A6B9C4D5306DCFFACFC3D631B48ED6A9FE67045CF09FB06DFF008061686DA9ECCB5E0134CC30491E33F58A69B6DBA89E5BCF5E789893DB293F2F7814787604B1A5E9F53CDE320136D39C42B37D05DA432543F8621F1D5350C73DAC93CFD7A62730BDADC3AFF6A08D6C4539B80EFAF93504655C563FE6F5880E69956B1C9C4E71953F4C854F741A9A82E017325A49E083D627979CF60FB4322791C4532CBDCA833317E47CB58524A544579B167EBB72FAF38ADB33D5154DB8A61541534E663BD5B6EA408E67893005A7A40C4F49CC654C03854950701C11A16D0DE90B777CFD3DFDE3450EA4ABA54BCAE36EB52EC120B886D54D133209255363FBB4ACA5A2714926DA3DFAF21A8F1A46021E8EC45FECDD6BE4CD0DF53AA5A2E052B304A164925908E28B1B4881899932524710A00185CBEFFCEAF19EEF9FA7BF6758E06A34BD1C46020595F678A7CA6DF87C2313F00A981D20A8867715F0D3A8FC468A92E0907E63EFDB8F0DF7379EB53056224733CEDCE2DB73C248CB6705070BA5C70B7DEDD5B4F04BBB0356D5ED5DFF00970DCE36399D34AE14858F71BF5BDFA75DFD2D87C9C14C4B7C849E63D2DFC7D6125A824B5CF2000F478FAA9EEFCFE5FAE3E0C89885332856DA7D63ECDF02B6F51F98C80099922FD6DB7BFCF1BC60822E232C6C124D40F51188DCD0078A481B6FBF3C1C0A360FE519009B08DBC03FB87EFDF80A14039040E719E056DEA3F3182DB248893EEFD7CB1AC60822E230EE8F9FFD27F3C1188CD08899313D446DEA7CF046E8203BEB1B3801D953EEFD704280836AC66941131267CB1A95A45D43CE36E151D0FD3EB19411B823DD8C7788FF00908D84B59B249E958CDB4154F84988D813F763066CB01CAC010195305D0A1D4465C09E9F7FE784FF005521DBBC0EEDEF9467B998CFC26CF63F86F568DCCD1FD60D85926E7D6379F38C2C852564041E27DBDFBB5DA135BA012A0C05CB8A7BA7B11CD77065ECA96A504800995111600EE4C7EA4FBE42565B8C9DFF004E4A95AD219AF1F8496FC7392967B91A7F98EB476B7DB153E92A0094D436AAA7D2E86381D4A8A0A78B7292637B131F9F67F873F0FE766EAEF71521480820FCC9A1AF303AEBBD75F377C6BF8943B392D387C24CE3EFB8904A14CD60F404DD8F851A3CD6D53DA1675ADEBEA55985538A602D5C03BCB419E40C72B4F9EF79F54F66F274E46512D12010800060D6D682BEF48F1AE6ABC4F6856AC54CC4948592B292490C4BB5FD05EF15AF7DC4AA8654B01282384A884CC9E52798F2F8F3EA32387152871A780B3049D5FE9A73BC56A64D97820650471173F37A3D8D76D1C561E726D3AFE78529A00A2A4AA54E14F840DCF88C8137BCED26D338AF669265E05E677A01A9617BD07F97F1686D2A5CC9F30289294B82CFA03BD2EFA8AD4B88B5159964FA6281140F34DBB5E5252B7400A2D91CC403FBB7962030866E6B88A4D644BB23877B5F7D5BCE2566995C094801C0152CFF004D856DB6F150EA1CF2BDE5AD4DBCA758519093E1E117D81DBE5CEC062E383C9815255C3517A7959BF3EB0C968490F46FAECDFC6915D3F52B6CAD6A7788AFFA788908F7DFCFA4F4C5AF0F9726500B4A78599C357D456BD4D4EB0C660208AD9EBE5B7BBC44731AE5A8A9216093602428C911D66E64587CF12273097857723E5624BB6B66D7EFD61A4C9F32A00B8A372BD6FE2F4872D2DA2B36D60BA8525B5B34148506A9C790503856411C05613C5707EC123699C43E65DA790E995DE00A502129152E342D41E3D442B875A9555BB356BEDF4E757768BD727674AE85A72CE5F4E8AEADE185A8A54A8541132A0A1FBE5B629F9862B158E70A52A54B770805F883BBD08EAD57B43C0A480183B863EEB42FEDA1AAB353FD72A3BFEF14C3927829E0A5279401013B6E7CF09CA4CC4942425C02439AFAD75FC35DF5AA8EE4FAFE3DF266CADAC76B104BCA2CA87D9E19326D13C302F6F8F4BE2C384402DC4013D767DE9716AF8B46C25AD4EC934FE3F30C14ECE735CFA29DB438E2CAA28CB692BE393E2E220787CB8FA88E785F1624A071F7C9414876240A6947AB723E0454BCC2CB493FEE029E166D8F503F3CF78BD7487640F5425ACCF57114ED8E15A10A2078409B8491D472F238A4E69DB43210BC3E0BFDD98974958B0D19CB8F5B3F8AF31284915001A33EBB7E75AD79DB5519CE41A529914997A986587070385084AD4F706D300A9245BF7BF3DC5CFC4E6B34CD993162612E0D404BF205B5FA88426AD09E24A0B00C431BB53C3A52FD1ABCAECF755672EA98D33951553384872AD4EA510956EA09700279EC76E6409C187CA4E1D499D3E695A49FDBD2DA9F01CAA223D731492CEFCA94FA78B8077D192A34C657918359AA33A554D4D6F89597776B2029024A038824279C9116E9B62C38752E6BCB918701219A7050A3EA451F66B5219E226A8872A2FF00F115FCEFF4D2353DABFEA08EE34BE5CD503401497DC08A852845C80EA54A13C883387C32844DFF00F1534CF208524A7E4E12EE47CACFB3F2A43718850601241D5C3BF990D406B4B7288EAEBAB6B5C52FBAA87AB1E3FCC7077894715F8785221099F281D79E1DAA4CA4242414A5800EE1CB6875A59FAD21DCB3C572DD747DFC79D39011CB1A3B51D72C3B54E7D5E9946656E249E1DF6E20498FF6DF0D57325214521D6694009F221F7143B3C394CA04124D34A375D625D43A6345E5A92739A94D7D42C0E0400A4F7253F6AE92649FF6C349C9C62D40CB965080CCA05DC11701891EEF48DD4254A624B93BFDAB6DDC79C66EE6DA53290A19765887B876F11B40B5940FC79EC71B0958C23F7AAB764F9DBEDAD79424A992C9141C989FC81A359B4DA1B9CED26B18F065CC3396255FF10961A7FBE036FB48053C3E5136C61596F7E52A9C998BE1FDACA2867DD8B79DA1B4C9C12A74A80045880D66D8F95A962D467A9D6F9B56821CAA0B077E06D2D5FA0E100EFD0751B0C4861F06245449240B12EAA6E5DDFC4FAD61B4C9BC4CE5B71CB414AB36F0C1539C562883F597999076716BE23D202A047291D6713123264E3D24AD212CDFD8C6B6FF0088F7717856428105B96B777A8F7F58685E6F5C3C23317C0BF35106E660150F2DBCB0F13D96929D52C030A0D7D9EB587108DDCE733490A4662FA60D812BF17FEE3F327F2772BB3126951FF88DA87E95A1DE08554FAB7356665E5BC446E77BDE64FEBBF2C3E4767F0C3FB80074E11E9E3AD057782143BDA066EC94F030CF0ABFE221D69977BC03A7789570C738009E588DCCB23932F80A10B9A03F094A9496A87B1A8F7BC3DC37100588ADC10EC2A3DB11AF8A0ABD47A5F3F6CB1A934D53BC14005B88525926F04CB4DC8F71F7E12C261B31944A70F3978643060A495DABA97676FA43A4A52E4A92EE46BC87DC37214A88AC353F62DD9DEAC4A5CD1B50AD3158D859AA696E3D509AD5ACF8002E2C25AE0DA475BF95832FCCF35CB26138E7C64B531130327BA019CF0A7F7120BB35348DF825ABFED3B56BF41AF5D39C75EB56F60BDA26960E5751D02B35A16E562A1A79B512912A2AE04952AE22DBFDE7A0655DA9CAB14B4484E27866D1D2B4292DCB89403973F50EC29A2A42C00A6A6A5C1E761AB5F4B5A28B7F5156B6EB94954C3F49514AAE1710F36B6C12491652C242A083B480778C752C85781C4820CE96554003A6A497FC579EB68C77547D2BA8F02D7B5E95B8B18D88D44A3E12E0E5042C48DAD63F95F9C62D072C94A0E809376602BE156EA2908AE592E521DAE68F6F03B721E50E14F9EB8BE2FE6131037FBE26E6F724EDE78417964A480C815059CBB74DFF00311D365AAEC4B3BEF5ADAA63EC831F9C095839AE5C94B333823C0398FB38AC4CB510CCF5F1F21D6343DBA6F11CEFCE7CFCBD7CF1212A470DDCEC1F53D2E3EFA4604CE21FB5C0BBF875DE3142547727DE6607E7FBEB87F2C0003D8D4B6DA0FE3AB460254A2A60FC8066E9F9FBDD634024102794F9FEFA7973BE10C4E255254E84710E9CABE95D3988DD0A4CB07BC152D5351E819AF5F02446DC3318C5AE851D5F6D49A563071491F2A405528C697DDCB78C641D71BFB09E2264F5836827FD8FA1C2A898482E1F4D00FA7A69082E7CCAB21C1079D79DB71B5F48DC871F7265C089882426D7F4F891F3C2A99214FC47A06D2EE7DFDA1A2B158B144C9596772029F968C0F58CDC436803EB2A352493C3C1E1088899E106645EE46C71198FC4CDC2377492B7BB75E9CFA74710BE19626907123B903FE619EFAD350DE3AC6D645393C2867879F89447DF1B7C4619CA9D8CC45449587E4EF7BBB7430F26627052407C42001B2853F9FCC294B9C0084A1A8E654E206DCE144193CEE3E7897C2E498FC5B34B5D6C58B87FAB577E750D0CE676932CC3FEEC44B2D562A039EFECD0D210D566F9753A66AEA2999817979B047FEEE53EEF38C5870DD89C74D01C2C9BBF09200AF27B74F5864AEDE64F2B8BFF009892C3750BD3737F43B558B4AB5C69ACB829F39E5236C27FE38E26D731F641F11208EA089838964FC32CC316C89689C566C02155BBD746DABAF48AF66BF15F2BC17FD39929628E42D34F00F7E5CB9C305476AFD9F38E2AA17A96910DA264909827CC71016B8B7E786B3FE10E6F2CA4AA5CE06A482953EFD6A3C7AC42FF00F7D39714F0F1A050D5C1D1FD3760ED788F7FF882D0D48E3C8A0AD6F306CD9C711C490D948812448215D2D389AC97E1C63A4CD48992D65881F32496B55989EBBF368AA673F19B0BC0AE05205C82140BE87974AF2DA3ADFDB07B4AB6F52BD4990BA12A712A49295410152362266F8F41F63FE1FC996B44CC4CAEF08E160A4B01CACCC3C79C70BED1FC68524CC12A6F0B3D44C2D63A3F414DABCBCFFCEF3FCD7397AA2B739AE71D6DC512DB4A595589364C28913E5BF28BE3D1990F67F098342448C3A50081600585EC037D9F78E19DA2ED8AFB5530AA6CCEF382D5048E757A121FA446DB63EAE3EB617DCB0B3E14195151260EE64413CA712F88561B08E1494B8B9A0B7E39379C57933A620325440E4FF9891E53A1EB33CA962B2B12B6B2C2AE25386521494FFD244907E26F8879D9F4A48299412E91400F09D79FF24E8F08A997FBAAFAFBF38B0F31CF69B49D28CB321E05B65252E2C70C8B4925464CFBE397AC28C2E23362672F8B8DFE506A05480D56B35852F405A3604A1D293F2D35F3A0714B6A08D6292CD754B85F7B825750EAAE5478BAF5902DD395C8E96DECEF6695862A993430353A3E9FE29C8B184A612E9726A4DC935BF9DEB110ADCEDD434B35EB0804184FAFA5CFBEDE5B1C5C026560EB4E11577DBEDE0D5D85352A2431F7AFB6886D353E77A82BBEAFA769DDA94A963BF6FC412B04D8F78A10809DCF5DB0D713DA0C3006A904023D8170DAE8046840343EFF00117C699ECC74FE4C84669AC1D0FD7405A3282A50E1501201750608363703F3A263B158BCCE7AA5E1507BA3FF00F7014CDD13AB9A5EAE0BDE0EE65A43962A06DBBEAED421B6D5EF589466BAAA99A63EA8CA114F428494D3D13294A14DA62FC4EA1216E4DC8E2923118325C661A72A6F0AE6AA690EAA96B58924797D291A9412C123A803D77373BF9C578BCD09A82AA263BB0A2495384A84F33E3F3F772EA7167CBF07C491DFB020390696DF61B579428896430218DCBFA0FE34FAF0FB88AE537F5B6D55552927B84B28E1851201E22D0215CB7B731E52AB460E4310B42529152549714AD1DEEE000C6E3943A97C23E635E16A351F4DFC9A2CCD23D946A4D45C35956A19665A98510E841251B11E320FC2F7C52B38ED4E1702BEEE5AF8D6E78528048A740CFCDC561F4B5A58D0067AD3DD7DEA62D166AB44F674DBC8A453559982C27EB0BE12EA82D03C3C09855CFF00A76E722D8A74FCD7139CCD69AB5CA969B24122EEE0B16AEBE70D3173C24012C877AB6E0D3968FCFE91F7B38ED0FB415919165AA4652930BA871C45284B60DC8438104C01CBE7CD354CCBB0491DE7F796763314EF42400E2FAEDD623BBC98B3FBAB7BB7ADF7B56B4B8829F24C8F272EA733AE39AE6C882BA5571A514CB1BA439250B0A33245875BC61696EB5132E5F04A1C244CA7CCFCB46D7534B426EE4B9BD4B9277AB79C32661AD2B985FD4A887F0A4A894A03480F95721240913205E636C3E3292A6E3F99BCBA37DC3460DCEBCF78D74BA7758E7A7BF790A7583E245538529E049BCF02BE7F773C615899520F095849D921CF90B426B524508735A5A9AD6D1236B22D3F91242F3CCCD1595200229D0D91067ECCB648DCC5F975C2B2E6E266B8949212A3498E4335D81A9A381BDE13EF24A48AFCF5F958DC73B56953C9A0A8D5F4F449EEF2ECB9B6985C84AC84ACAC0D89E24120C7291CF0F519799BF3622615ABFB5BE5D2AE030F5AE86D185620243A52CF76D2AE3D75E8394305767B51988216A5B73C924A449F48E47A5CFC04DE1B052E526890ECD50EFE27C06BE702B16433DCF36BFBEA74148634D3A5B2A529C528B907C4A2A889E64902797AF4BE1EA6420B02905BC00F0B7A13F66988C4296C1D9AD57EB7D3ABFD63538844C48EB78FD9F761512258B2436C403FE39D3486DDEAFF00E47D863E7FE1A113E1B000253CE0C739F3FF006E5CB0E65C941A8961B9900D76A59C6BD631DE2DCB93B54BBEFD3FC6D0DEB2DC1F10E8449FDFAE1C8C3A4DE5B1AE83F0DA535AB41C6ADFD0437D43EDB407881E2917E51B6FC8003CFD30F644874B24330D8B1A9D87D07D1A1F609D8EDA7ADF43BEF414840AAE6047119236836FC7CA77FC30E53875357C6A47A53D6EC224211BD5CD9E102204FEC4CFCFCF0B4B9452E2DB6BEF5D6086F5D6A0837F75BF7E779F4C29C0DFDCD6B0FE75B4109975295F0C19DC99B812622DD630EA54A4A920A98DC5439F571D4DE1594A29762D6FBC2571D4926C24F97972E60FAC5F0B1932DAA81AD424026BEA7CCC2BC6ADFD07E211FF0011629DE6E9DC42BFCC980B42949E0E1BC9281CC91F9E18CC934B50BB16707CE81AB4EA233C6AA9E2AF415F187D4EAED47A78368CBD62AB2E77FE221D0878047310EF11DA7CFF00185C56592F10A4AA623E641252504A087D8A4A49F41F58D84D98971C47C61AB54E97ECC7B4EA7A56338A5628338752E019836853629DD588054868210BE251FEA369EB87582999D65E5588C32A64D91218A6471F0950D7E62788F09FC757D84026FEE5313AFAB01D7F160F1D27ED53D9D759766CF2F36A243B9CE975A8B89CD18BF76DEE3F92D95AAD2522676338EB1D8EF8872B19325E127AB827A084AE52D4C52FCD4CEE7F1AC3A9984E1142E0DB571A9FB5E28C7739532D06E83892572971C7014294A4DA0A1705252AF8F3E98EF3844E17152FF51316821829297147B9A1ABF36AF230DD58628F95497357D497059BD2AC07578FB7CC7E6CC4E4005806DE9E2D43E61ED1F5CE5E196E2E583391BB3D89F01EB189415DC49E1DE01547AC6D84578800B685FC391A3FA6FA343D44934228055B7F13B356362131629B799223F3FC30DCE2175E10E2A3416F0AF41E70F654B48AA9403914E7A3FADF468DE4445EE7974FDDFE18DE562012CB6E840F1041FAFF00889191946171B59D8844A61476AED7352DE4238F3E5D712386C32710C10872A346035F27EBEA4D21A63301966041271B2CF0D7F7245B9397B338D8E91C8AC66990B5B8F32DA40995B8DA66378E2509F77CF6C58A47661738A7E457CC47ED4151F161E1E02D57A8637B5B93E59C5C58892AE1B82A4876D9EDE1BE9101CFFB54D1790717F13AFA747083C5C2F24ED7BF02AF37FC2716AC17C33C7E2D295CB9334BEBC2A1434F6C7CB4A9E33E3664181E249321D3AF120BB5F715B6AF14EE7FED67A03254A5392BADD638B2A0F82B578236FB522FD131B62F9D9DF8178CCC4A8E264A900311C697E2D2C5A9CEE5EBA472FED77C6FC1E62C9CB9694B38265A83DF97DFD228FD4FED9B50AE2FE18C84CCC70A84011623C3CB6BF3E78E9584FE9F644A62A4A69FF60150068FCBED531C8B31F8AF8E524A53316EA06CA3A740E39741B98A473AF6B2D7B9BAD28A2A97691B4157111C278E6C394DADB7588316B4E0BE0C61B0801EED0786E784333BB1D0F98BF8473ACD7E25E6CBE2E19B32AECCA50B31F37AEE29D22BECD3B5DD679E89ABD4552C71CCF0855A6DFD2A1E405B6F3C4E23E1FE1B0A18C943501748E5C9E8056FF68E73987C45CFB895C3327D4B8F995D75A0FA72885D6EA6D4C1B729D8CFAA6BDBACBBFC4B71B0D04191BAAFC57DA448B8C5D7B3BD9BCAF0C952E7C89448A25D209D41D1DBD3D1F4CABB519CE68A3DFCD9A18B3A8ABA01567FAB6950CD543459FEA47539551D6562005CBAE77CEF0113C46545511CB78E90621E67392647264AA74C44A4B876E104D4D0301ABD9BF02D12F178E58613D6FBB9A9A69E7ADFC1EE845651E87C9D1943657519854208AA70BAA708524784924A80927918B6E314BC176770D8C9CB9F2E4A65C804143A402A72C6E90430A9603D6AD71A718A4979AA73D69ADDD9BADBA45479857ADFAA5AEA1D212B55815710B93CE6DBFB8822778B8E03249320829480C050003425A8C683D691CFF34CB71B3CA8A96A2E6A2A5A9422F46DC68613AB2B26A29AAD4FA9E4492DB224F1156D10542248E5CB61CE4A7636560E5AA5B04101B4D68EE7F36342C28865597CEC1A9466125CB80797234F5BF568B0B29D2CAA85B59AEA43F56CA5B1C4DB3CCC0B4A130BFB4049239913BCD1F34C67EA94A9723894B07F68762F5FDD7B7E0C5859EB615E6DEC96F3DA156A2D76A4538C9F2C4258CB784A68DD109242478CDC0572DC993CAF7C43E1B27C54D9FC650A01452E6AC7566B060F517D235AB004BB453798E7EF309729D0B53AF2EE5464D899373236B833E57DF1D4320CB5324244C484877A803C6BEDBC6088356E6FFCD652DB6B5D4051EF42413727C26D3F7C7AED8B6AE7C8C2A56164310024380CC2BE06CF616A54C68BE11C240735706DEF5D45625394F66D9D6B071AAFA9596689052B50721129064C85149881EFF7E2979E66B2427BB0B20A8909094953D6CE079D830D2130926C29BFDA2EAA2CC720D194472AC9E95B4D6B8808ADCC4242CD3140012784A55C7C664784CFBC629333078A9F3828A95C176F9AA0D6F46D3D01B4093C229E66FAD7AD621398E64E54BAA71D756F8513FF00C4AF6E63F9009B0FB3616126D8B5E592C4800ADA8C48A0714F76829B7F17E7F7D21A1B0D3ABEF944BE1933DE10525EE2D806CC404999B79DF13B331B879728A54B44B49FECA2B81BAD5CD2DD3ABFC3A41A90E5C317E97A9BFE0BDA24F9668DD41ABDF6D748C8A4A0491DEAD4128F04DFED7018201BEE663151CE339C2489265CB98CA51674B9E2B5481CC55FAC6F31254556029B507A036BF48B9F2F6BB3AD0AC34CB884E639FAC40470B8B097936B1852609B4EC27CCC731C6CFCC674C5913D6845D2789F8C747A30E571E30CE62F841653BDE8CDE1EDF9B346BAEA9D79AB941B654727C98447086D00B676B0E056D1D7CC1DB0D30B2972D45531E6951ABFCD5D4B976B9A5295864BC5292E09DD80F0B73AFDE358C8B4D643DC3950D7F15CD5525352B795C34EB024A968E25257C53B1B401D7124A0B2B4909EE9201E2481FBDEDA79F2686C310A5062E0AAF514AFD4F23A8F04399EB6CF549FE1EAAB0BA758E0698A669B67844C0054CA4131379DE2F33824616521456996EA56AA3C43C8B815D79C1C44EA7E9F48479668CCFF0032EF6ADE7BEAB42F14A9DA975490A693CC84AD416E7A2648F961E2E722594CBBAD60F0A52924121CB5289A8D5AFD6000973E25CFE624ADD1E90D38D9552AD3A9F3148BA57C54FDDAC5F759E130768B58FBB32A5E618A0AE296707C27E5B2FBC1F6A3539E91BFCA9B1E23E829A6FB7DE19EBF5A675512CB6AFE174A652AA642438427902B48936E7CF7BC62530F952070CC5278A6007E725C3B5684B0D98FA5223F15356976376DBEC75D2911879D0BE2719A4358F2AEA79C78A003BF17028FA98FD99697842861C2C1EA001F8B1F1B56EF0C7BE531AD740DEFEDE3686D7F316E80CD5BA1D53A3C2CC4060A6C405010AF5F899DA4A4E116A50253A9AEFB528370D077C40A54EC5BEBAEDE7686D7B3C61CE20D909E704C586C2E39FC4FBB12F270A6CC6D5A1EBF5DB954C6BDF2D550695029D43F5E74FB43554E7BDDF04B89E1331E20408FDC733EB787F2B02A2E58B8B8009A7D453E958511C531C9E55347F01FE3A4352F5118BAC4F5E2E43CFE64488C394E5EA70E9BDEC006F1A783F9D6151289B1F4FE61B2B752287042C73BF103F8E1DCBC0106897A75DB73F43E1780CA22E6F6B7E7F10D4BD48A9238C473F1263F48C38460554F9091B55ABD1FEFBF28C777CFD3F9844E678AA823F98070CFF5723D0DBA4F2B03D061E49C1949FDA45C9A337AEEDF6A54BEC2A7868EEF5DB7FC5FC2C61BDCCD557858B03FD42DBDB7F4BFCF0E061AA686843DD9BC7DF287D1C3599A94092B163FDC3F138C9C2BD8795BA51ABEDE08D6BCC094AAE08DB7079DBF0E5F0C63F4AE1A85C8D09E7BF9B7DA08C98AC0BE2E2500444091B5FF00630A264A903840A5F60078D61497AF87DE335D40EA09E5E216C1DC294A26E1FA7ABF41F4DE148D6DD5B6D05171016372AB029DE62449DBF59C0708667CACCFA5EA2D572DEF9C118A3306AA41432E48120A4836B9B5E0FBC6D37B63656042032920061517661CE96621B4EB1935EA6FEFDECC183E28140AE345424C120F024A9256A1B10A0653C27CF63B6C70C3172A648E032C128550B6828366D75894C0021DC6FD36B8E7F5893E59ACEBF2D6159457329CE74FBE3BB5E5AF849EED06D679C0A54DF885E6D88DC6E5183987F592268C2E392CA44F413FB83DD23E52F6A8DDE25E5CC09F9549E24D68CD53CFFCC513DAFF00B39E47AAE81CD53D9D14525536DBAFE679536254CA9409406F8882E711927BB4AA22F02D8B0F67FB7799E0F112B2ECC662D9C264E28D133C0607880608614009ADEB1B89095974D7705CB0A6FF006E76158FAAB14EF3A0A90E82D93F6004F101D36FC7CEDBE3E20C8913A610385441A00EC29F4E56ADDE91F59F118E9125DD490DAE86FF006B73715684CA72BE9969450321B4B9FF00CC2D7C30A236238C5A04ED3B1C4F617259D3880124BB12361D5B5F3615E55BC6769B0F21C7789003B90459BF3D5A346659A64F9630AAACD6B594388054A05C48D874040B11FBDCD8B0FD92C4CF1F24B596607E53AD99C0A3B781F2AC623E206130E5415350E9E62AECDA86BEC6295D51ED01A1F23B1A969E750141084AD5E28DC120981B419117DEF8B7E49F08F1B9C1E24CB5A58D5924BBDB9BD29CDFC389FC45F8DF8BC9001815A960BBF02C96B33B37AD772CC23AC3ACFDB12B96B769321A314A83294540712E0F230527D63CCDB6C746CAFE0AE2706B42D6851622852696E83DF28E1F8CF8F19E63C1733920B82CB51E5EFF002F1D76D4BDB8EBCCE8A5751A89F7D2A2BE065A6FBBEE42B70A53647174BDF9F3BF55C93B11272F20CD9292433F12013460E1EDE94D22A38FEDD6719985033E7278BFEE56BF9E81CD2B68A8EB739CEF3A714AAE456D5F19932F3C99044EC09DE76F49BE3AA65D272EC2CB4A3B99492033F08A11C9BDD6F150C4A332C7289563660E225DD458EDFDD61D7C43426469E72A882C650FB6AFFCC52AA1C571CF4E2F2E60F98F27389ED0C8CB292C2268D025012C756615E60B786ADA42E764C5466CF334A8BBA95FC91AB6AD48548D25999108A4EEFF00F538099F45183CE07C0DF0F307DAB4628006530AD1CFE3ADC3BD0087E8CFE5CD0C58BD49241F520B06FAF36852D692CC385C76A0329EEF8424171A4C9263FB8191F1BFAE24BFD6F0CA21012A49554B851E66C3D39439978BC34EFDC94101E85BA7D768CB30D179DB9429AAA32CC0FB49EFD904806F04A81EB6DF7EB8653F38C1AD6649242CEA50A6259EE4352D4859385C0CD1C4532EA4172C585AAFADEBE2690F5A734057E64D30AA94A5AA51C4730702D2AB054A6E93E1E60F0D8F989C406639D7E854132144A9764F86DAD6CF5D21B626661301592122CECD4622F46AD6BF7A43FE7799651A5DB396641C2B70A7856EA0788280BF8A09DC9D8EF6B622E463E76366056252A59249E024B002C0D9CF514AF323546768482134E747A57933D7C1DB56A8EAF37CC8D438AA90A71970F8D2A32A50E5C24CA844990244018B1C89F44B27800601A8D6F036D6B67DE1519DCB200501E2CC5EB6228CDEE91B586691C5216F952D959114E38B8812481712AFB5F95B7C490CC0CB04710068C68767D41B6946B0BB46A71F254A07840511BBD2F5F0D398B345A5A7B4E52E5684E6D99AE19580ACB185927BB800B9379B9FEEDE3D6299DA2CC2662E60952145453FBF841ABDABAFF815863889A998414A425EB4F1DB9FDD9A10E7DA95556FA90B3FC9448480610001174A77B81FB3891C872F993129529152410E2A3CC5295637F366CE6A37BF845339AD7F7F52F9AE7434DB5FFCA5E37FB51C246F6FC76C74C9197C844B96A44B4A94C4AC1A11B5E97F2DDED9E1E1153C3B58BEA7F930C748F56E6358DD1D1503952952827BF01400E222E4C5F97CFD31179A6351824B23852402D50FF8B35AD188BCF23D03956414DFC5B3BA865C7DF095B2C2928968A4788113CED756C67C8E2818BCE711899BC082A213422B6D6D4A0D7784E669E3F68E730D45F5D49A4CB406DA48290A6BC00804DE131BC7E00E25F299299A7BC9E1C83FDD5D3636E7AF22E634249A3D36FA7979727AC4442D4C970BAE2540901C4900A957EBBF53FB8C59952E4147CA8482D7A5B96963B0D2EF1903E663CDFC9E1C28281FCCD696F2CA25F093E271415C3732480A1C36DFA1E98A8E6D8C1872A12D40B39A1ADB6A9A07BFE4C6B164657A4725CA50BCC73A790EBE8095374A91F6940494F0A099320EE3CB738A54DCD264D532D642483F315370D767AD74ADDC42D2A6A50E09620382F5A93E57EA2F0B135FAA3533E9A1D3944ACAF2E42B816F1010148062656944D81BCF48C5731B8E9C14AE07984E9FBADEFD758DD7890A003EE6ECFB83A6AD489454645A5F4C334F5598BC8CC739502A5124ABBA7073201503276DAF7C34C3E231B3A6F0AA42F84D2C751CC396D6CD7B4305A8A892FD36F2F65A19731D675B99B2BA64B6453A13C2DA5A1C32361050013E7E7D77C742C9F2CC3293C4B484294CE144DAE4B28D2BA72B690D264B54C2017A390296E6435BC341B430E41936699EBF56A710ED253D2A9257DE9528B895CDD25571B5E397BB0E33DC26070E990254D4AA64C7F9501C820589492CD5A529CC424652921418B26E5C83E1FC52FE32DFABE9BC97C41BEF2BC5C2D456A057B4C1246F7F5F8E2224E0A628B5810E4004D08A3D6E45BD2350417176BD4B8E5B7A1F4864CDF3FCCF38EE997DC2CD352F10A7436AEEC10AB10AEEF878B6047145E4811898C26532A592B4CBAADB894AF9AD66E276F2B3D636330292E406D0DB7D2E756F015A4459C71B6892577EA5444D8F9DF6E7D7DC276560410DC3660EDBB696D81D4D810635AEA7AFBAC37B99BB4CFDA583C5CCF4079DEFEEB6E67A49C9CB8948012FB966D0335FD6F0DE7A0A8063E1D2D5FB75AC30D6EA1607142C2605A1511F0FF7B79E2464654A2DC487AB501A574BB8EB4AC35EE14C75B785DEC69A5493C8443731D44D150E250E70499F7DB90F3307CB13527292C192D4AD3EA7C3F98C890A1FB8172FEC445EAF50B4A9870081D773BF336D8DFAFA5E425654A7608A167A6C18354BEE3703CF412964870D5DF476D1FDBE95860A8D42D7FCDD89FEAFBA76E7B6C6D896C3E50A2E782BD356E5CB95BA3079213C3C4E18500ABEEF4AFBEB0D2FEA36D323BDEB7E2549BED161D7E76B6245193F100F2F95A8FADC1FCF5870DCBDFB3EB0D2EEA141301C9FFEA3637E5C5F2E5EFC381939000EEC9ADDB4DED7FC6B04225E7EDC1FE61F39511CFC893F324F3C3A464FC207FB6FE14B73A7BA410DEFE7CD9E11DE1E67ED91F71FDF9F25464C546881E1414B682B530E246B4A7E34F7E9AA6FE3ADFF00CC57FF00E457E78DBFD157FF001FFDC7F30E23919E36777543FF00EE1FFB8631FE8CA76E1ADEE6DD5E08528CF51B1709B5A547EEE21F2F7E30AC98D886B356C2D4A182370CE9300A5C2379851EB6B138426654514E177F06F16F75F1511AF87BF585EC6728FF009849E9C5D49F3B587BAF384C601418701A9156B3D39EEEC7561A39521C539B2146EAB73BF96DBFDF8D7F46520B259AD6F6FC818215B15EDF1020A44F21CED3D7F51842661D4456D63F6D7D5F94652A29FBC2DFADA5704116BC0249F4F2B0E76F761BAF0E0A5495241705BAB52A5F958DDFC5E49C404A48258BD0687C7F8FABC6F6EA87507FBAF7B100585EC3CBDC714BC664D8CEFB8DD5DD951219E82FE03DD2A21F4BC4A0D8B6FB1B31AF8D8DADAC3FE539A54D02955B40E115D4E4162482D142A03A1683FCB5CA0C0E206390E78595270F3A48C34F40285065814571519943E60C58B067E7123271001704380C09E6075AFF0036BC7BF3AC7B66D1FA494E135ACADD6F8BF969741937E84CF29B1906048C7CAECA7B258D5A920E196F7FDAA0FE83C4F531EF1CEBB7580085706312431FEE1F9DABB1B4757B5DFB5DBF5C86A9F4FA02035DE25C5226564D9264A790E9D37B63B1767BB0AEA4AE7492C4070DFB480696FB0D2C63887693B7EC17DDCF0407019635E43AEC7C2D1D5FD45DAAEBDD64FA9A554D4B2D3AA2375253076E968F3DC6E37C763CA3B1D9722524CC4A12C3E674876E76B695BB33C70ACF3E206378C844D5A81268146A1C9F7F48853F9054370F6719829D2FC90AEFB8CB7175484ACDC83CC7E38B7E06760B23491839299A411C4C86236D3D436BCA2A0BED5CCC7A9B1897FF00885973A58973F52E29C92BB4FA36851C7519B87D699259EE9627AA78879DA6D6E9CA6E5E6F89C6D25E0B80287EF6700F88DCDFC2AF1B8CCF0F313F2E1D24E8CC2B6D35B68D76D21A1CD6BA4E81696D8CAD2667C6A755FCC0911212A16117813F09C292F2CC66255FEECDE02BA049400D5A07363E760FCD2999868892C75BEDD2BBBB6F4168459876AF96D1B455474CC36A1BC14AF6B8DC6F613313E71189C93D869F8801E729955A24B7938ABE9ECB338CC52D8CB4A9AE4077DB4AFB1CE2BDAEEDFABDB52D287596D2926490D2605A2640F88EA22F3890C37C2C389502A9856D5FDA4B750E6BE7D1E1D61B28C5672E161496620170FCEF5B6ADAF843731F685A900977326DA039A4208DB62523CBDDD799B5603E142920140528D4905045056CDE3604D77874AEC74E92FF00EE1009A51886EB42E7AB8A369100CDBB7EFACB8C0FAFAAA5B1C657C2E16529B5AE08076DC0B0F22709E61D959395A4A66A9285D8829009E8EF4E5CEF1A8ECE62921452A5280AB0734EBCFEE41BC4F3B2DD59A9FB4BCE11419526A0E56D2D3DE3A9714A6B845CCAC9E1DC1FEADE6D7C736CF0230A0A829013BB25CB1664B3B9B7DC434998799875042A694AB4049A1A316704EDFC476FABB3CFF0F50AB4FE584A2A8B694D7B9DE71C92014F0A892266C4249DEF7DAB581C1CBCCF10578850013FF4C287EDA005EEEE2DA588A40AC14C989056A25DEF527CF5A1ABECD1515467148DBCAA62A2ED72D478944AB72646E623DF318B6C8C830F2C02569E1BBF981AFD2DD2B0DCE5938170694AB1A8D2A2DA3741D23706DCAF7A8A9A991DED792AEEDB4DC2A6E66011617B8D88F3C63112F05212409C800025DC1B03ABBE9AD74E9AFE82671001449E8C697D7AD0B7A87B7F28D3993E4544732CDD4DAF36E12A452954C2AF7B4A4181B102F8A5E3F138898B230C82A92927E70E3A535EAFD378789C1AD20294B246DA8A01A5EEDE0CE22BACEB573CF1ACFADA9490084D1308F106D3B1FB13B8BDF7F8C4CF65F2D56625467A3F6915533EBA9BB336EDAB340A32A4D0CC0496A3B9BF3AFA1881566A25B74A43A92A75C308812A99816BFAC799C5C96309971212B438FED76F20CF72DCBC28A04952428541D7E9E75FADAB0F9A7BB38ADD4494E699C2D4CE5E921684AFC1C693720494A8F2E477F3931B89ED194132A5B296A042529A8B6A459F991EA2123365A4B15007626F7FC74E7168A6A72ED374668F4CD232FBA94F0B8EA8A0293D482EDCDE763E5CE0577103118F5257892A72E529721AA2EC454EA2BF58732D132601DD825F502876D0B5EFAF237AD734A8ADABA89A9AA5ADC7092E3409086AE6C9E1F09B1B91E5BE25B2AC9A432A6CD02805E8ECEE0EE079BC253A52D052160A5ECE3F9DC74BD617656DA8A85252216A71C84850429504DA660F53CFE42C9E2F1185C1F1095312549B80A17D0BBD6D6D3EA8CC065D5747ABEF6E9E9F58B032DECDFEA4A39AEA1A8029DD85B2D12018173C412411331045E0E2A38BED5AA52952788D1C392D7722E2A0FE63596D33F655B6D3C36D983562734F9837DC8A1D3F40142380BE940213CA78949BEFD794623518A4E378A6AE6710350E77E4E6DB39A6B1998B4A4F091C2545AAD5A3B6C2A3434A3DE36D1E9AA3CBCBB9B67B541E7D10B6698A8DCF310959102C208BFC31178BCB06371084E1A61E00FC6A14096A8D6AF57A7833B33C515A0029716A8D7E9F5B0A8611AEBB58E6D9B32AA1CAE91BCB291A051DF24B60A9239FD94933C3313BEF899C064986C214CC9FFEE2B73AEF434AFDED0D133575150CCE29E429D2B70FE706A4C9B32CD2B1D6689D5D63C149FAD2DC909493241415CA4DB7E13EB737B14CC56598792FDC21C0D05475000724599FD21CA160B82A1BDFEA7CAFD22CBA0A1A0D254E1DCE50876A0890810BBDCC4A245AC36E700E2AD9863664E495E102920B874B87D03A41715FC720E5065A4FCC43806C41D8F4D79BD9CDA23F9CEB87AA5484D2D3A68E9FC4105011FCD02D0A80088E5C5EE1318C64985C5E2262953C2D4090DC4E48E94A5F47F178618C9B2C2992B751A000B123A7B6F07887D5E7A5C3C6F360CDCA94B13BEF1CF6E5F8DAE585C192689D589FA0B1BD6B5F0061B9933420AB84807521FF0087F17FA447EB73E652905A792557949504F0CF2127C899B49C5870997AD4C384814D2A4935FE6EEFA330D5089C43B384D8B1A3BBD1ABA9B52B101CDF5496F8A1C0627FA80B6FC8FA6E7EEB58246553385F80B51BE5D29E36BD34A42467252A62B0145831F16E5BFB3104A9D56A755FF140E136F10BEF1B917E53EEDEC6C183CB0949796F673F6A73D1FCAF0F25CB2B62490E1DD9DC54F833D2CEFB445EBB51B92A3DF0B72E31CFD081F9E2625654A2CD2AA6D4361BBDACCCEDCAD0B19029F35AEFA74888665A91C2A402EDAE6CB11F7824F3E7EFC4BE1F2B98C0196CC2B4D99F7F4F38D44820B3B0F7CDC9F088BD5EA35AB77A081FDE09336D81FDF5BDA465656A0C44B735D1A966B72F7AE5586AF102CF62DC98DCB69AE85E23D53A85DE4E026E7ED475E84CFEEF7C4DE172DBBCAA1D83FF00FB7F9AEB511B09640147275D76D74A35294B986A7F50BC2DDE4DCCF8891CED73E6791E5D70FD3966BC1E9BEEC0F3E7B178CF028E9EC7A7B1B874275039C4AF1CEDCC7CEFCF0E519726A0A1DB71F753728381434FA7E634AF3E7099EF08DCEF73E5BF2DB0E13972187C9C8D016F27F483815B7A884AACF56A375931CC2B693CFDFD3DF8C2F02948FDBC2D761A0A0A836F621442141C949D3EF1C7F1B56DC67AEF68EB311843F4D2FF00E5EBFCC1C497670FB4033C5F270DED3C604FE3F2F96373824B71105AF51F9A42810A21C0710A919DAEC7BC2473F10178E7CB9FE58D5385973094A594D46BB574D746A0FAC618BB6BE10A5ACED6A27F983FEA120499BCFEE309CECBF87E6200480C5C33BEEE2CEFB3C6E3E43F3538980F53EFAC3AB19D2A44B824EDE2DFE7E7F7CC6E19AF06548744BE2A35001EEE1F91703585C4B5A83A524F4F7EDE1F28F3852F8897072E7F2DCCDFDDF2C436324F700712784A8D396F435F2DEB1AA814FEE0DD61F98CCD500F18F5E21E5E639EC797CB117FA79AB2549415234228FD2952F52CF0977892581726C07376D46DBC3E51E653214A06C902E0FDA1E5BC193C845BD1A9C2198A0B52486771B1D76F7CE349A569524B108A574E7EC08764D428414AC137240222E041B7974EB718D664A49490A48200356B68FBBFF9E70B49C428D2DA6EED52DFCF833B43AD354ADCE249516E9AC5F7044A4FF48091E2326D6DB9CEE2B98ACA2522677A164A892A096D056F6A1E8FD686564CC55DE8343B86B54FB6DEBDD07F2A7EB966BB51E68B78995AD25D5113B9B0599BCEDB472E7E6F464597E1788CAC3A54117FF6DADD534E7FC3C6ABCDF3458FF7315354FA712ABB0725F4EB5DA1A2B750E92CA94D37474C2B1E1C414AE35A4A08D8DECA2623A8B47338778693C7300972C4B492001C352D46259EFB986ABC5E22692264C511FF00A8D5C5E95A7AC46F39ED12A92C292D25AA66384880947104C750028DFCFD2716FC176566E2D940A9054DA16ADF61B16FBC32323BD72A0E75700FD4D77B52298CD7B44A36D6A51CE9548A24F1A1495381DF20552940126E3FDAC69EC4E270252BEED5890B63FB2CC694A8FCF3786D332B54F520CB1C201B8DBA1E6CD5D62AFD41DAD65B468529354DBAB0492B2E804F9F093607CF963A3767BB2A7112D972532980705007D40AD35A08B5E579384201980A8D3A790D9DFC2B14E673DB930E3ECADB5B95350CA5D4B0594AD5DD29C0526528078A7948E56C48E65D93C1226C84F7D2E59E2A80D70A17636A72AEE6A5DE27052D2582343A01663EB5ABFDA2AD7BB48D5CB52BEAABAEA976A164A58348F2001C5207196E0083126398E78E9995765B2E19795AA6C952932C70A8CC4248201AF0F103FE1ECD19C1CB44B5FCD2D240342C0F3367B3E9D4421AB63B57CF9756E8C8D4D53381B97175CCB5208B1E12A4949EA2079F5C46644BC164B8D9DFAB216852FE43C25693C2589F95D88BF9178BB607F4C8427BB090A57EE0CCDA8AB7956ECEFAB4BBA27B48AAA734EE5336D33B92ACC1827726092E037B8DFD31D025768FB349E29AA2A134821291216C4B14D592C295F3F04F345A5212124352CA0DB55893ED891689B766DECFDDA4F6919DD26554CD2A8A868D73985621E6DF4069638941442884CA0280BE3CC1F17338929C4F7B257C1296A2C0382A721B84382CFB0B448E5C70EAC24E2A092A09BD284397D6C6F67A8AC7A7DA732DC97B11D3597E8CD2450BA9792539954777C4E3AA0429D8717C4A4DCB9B28C0F28C732C0652ACDD2AC5E632CF73874954849510FC42A48043EF5D758E17DA5CC38735484CD1598CA00528A037E571EAD0B17574798B952FF7AA6DA2106882B88A90E11FE638D47C4A0573F6CDA60784E18E132F3FA99812582154140E03D035D9BC46A6F12D9866024E1B0E65A5C902DD2A7AF3A6A6F11F6B2319957A5145C55554A5C2D494A884A64026448FB26E7CB7C587198708C1A953A67720268A26F7602BBE839C62566A66CB09EE6AD550D49AEDEB6D748BBE82874FE81A46B32013559F54B6A4788A8FD50A93DDDC2894F882B9C4103D31CA55226E231AB95326A9520AC10AE2FDCC5EC0D3437ADAD48C2E7CDE207BB2923400D1FC3A78F898ACB39CD5D6C56875E50AE9E342F8E5203B2B03864A620C6DD77C752C065B2A64AC3B04AA5AD2C4F0B31096AEB53F4BEE86231844B50E0341CEFB6D5FAC4332646679EACD1D0D2386A9A59FACD4AC12921C24A080B1C161CD24FADF1B2BB9CA933921494853948000239DDC97F6CD151527158AC424A4AC242EBE63A73FC345B796690D3D90B09AFD50A45555C05B68BC0526F109907E1D3DFCFB1737118BC4998952D48E3372AA5580772FBBBF95A2F5875265E184B27E7296A80F47D34EA35F44B9F6B2A8AE0C50D2B41BA06F8D14CB6CF006D077E2E10999B7DAB75DB13D95CBC261B8A7CC03BC980099C5524A4101817029A8BE9568AD4FC1E2A6CFE21C5C014E1BC4D34F77A9784B8E3C1F0DB6B72A9D70C70B7C52924F3299D846F3D622E5FCEC5485281484B519A81AD7F3A5045EB275CAC34B4A2704B902EC7424FE3E9BC58F90E81AF75BFE259BBA9A3CB602DE715C2A7109DE128FF88B9D8C030664E21339ED0A30F2D586904F785268976700EA0303AFF22233B438B44C9F27B9E1090A62D5A53C6F5DAEF6898399DE9FCA194D1E94A0EFDE309566DC2A52F8A409FABAD2A32488B72BE39F65AB9B8C9F34CE9C4A492482AB55C7CC4D3D3C19A1C66186C24EC24A2A9C996AE0A92D570FBD74AB0E5A339655A673BCD07D6F52D7C65EF0E26B8949417920DC774950537C361B49911B1C37CEF0CBC54F1230C851EEC8E352412002037CC28AB5DCF50042DD9CCAB2CE19AB9B8D965C5124A5F5A371120F2EA7585359A8E9B4F28E55903086A980E15D42871957532E5F73C8EDE78B4E51D9996AC27793D4AE34A5D280EEE41D9B9162348AF768A4C9938B47E9A7A540289201150FB8366A5F95223158F1CD1C52A9C3B53528238D0952F856A5ED00022D3CB7F29C3695227E0674C13414A41F9490051B525B98D2369C50B912C149058B3D74E61AA36B73A3C8B25D159916C667AA6A92C65691C69A2942145226CA285070C98DC6C79E1BCFCC4AE67712945531F404A438FF0090A1A6C74DE23BBA0012452C2F5AB3D6DEED78DF5FA8F26A40963226C36CB414145208593112A52BC44C89B9C38C3C99EB09131454A2CEE1C1F3F00F71F56137E42A2091B1777636F7D6D4101CDF55B8B90B5156FF0068CFDFB79EC36C5AF2FCB52B002E502555228CE395BF35B4305AA6EB3157BF9B0BD2FE3E1100AED4C9511C64240E28D87C36F9F4E98B7E0F2B4253C294840236AE8C6C37D0FDA23D52B1137198758528252A0540BB2AA3C3ABC42B35D4CD99977C239050006FB41FC39EE312B96646A52D4E93C2F4241E7607E9B3523A6E3F1386958194C8485F08726EEC1EFA9F0E9726BACD751B6784A5D2278A7C647A7300EC63D2D7C5CB099294948E0F9410E0A76B7BDCEF11996CF958B97380482A4A5836E41F33D0D6E62BECC73D016497491267C66E26799803A7511EFB449C0012EA803421BD34BEAF6715B452733C24E46352A4F184859A6843F56DDFAD2B10CAFCFD2A20A5E3CC471458ED3CCEF6368E932313380CB93F334B00534A8F4B8BEB16F12C0C34B2470AB87CFF00C9D1FCCB3C72AB3C041FE7122F038CFE727F1BD8DCE2764E5E0542075007833D3A8D28CD68D00510351B5BDBE86AD11DADCE92A2901C2626E556B8DB97DF389291800E494826971D3D4E9A52D0B212096D05C75B577E4F0C2FE6E9B8EF0C8907C47EFB8BD80FC30F9182096F901A12C45697723A3FD68C21CA659507B253B877360DD3D986E566817B393BF3B01BDED249F2E7F3752F08003F280C6D46E9BD3FCEA61544B4921C13BDF6E51A1CCC904005C1CC8827F318553866D007E87DFA9BC2DDD207F68FC7B6D6B081DCC900CF1C5C8E511F1BFEFDCB0C3A3500F4FF00023532050D4036603DFD3531ABF89A3FE67DDFF763612258B068D7B81FF23E5182F366D304AF6E7E667CE22206FBE37FD089E93F2920820330E7B6FAFDC08732D80EEF878B8A8E0506CFB0D2E3D04708CDDB5184ACDFA9B0F53F95C93388F3D9E0999DEA945DDD9B47D6A7C2EECD08E2BB3C427BF132AAF9C241AB01D76E6232733147085779F3B9F77CA6FCB71872BCB4CE0100708662406BD09D0FD39B5619E1A64C4FFB2A964B1E106951636DC55F42F66781ACDD04C0548039288BC5BF1EB6EB8424640308B334AD4A51735A00FA5F6B7D7589BFF4542657EA0CC0EDC412CE6AE483D3F9856C57000A8BA46DB133D7D48F5B8C6715844E29065A2E2F4B3353404BFAEB48ABE3A64D9B31294A58254D66074D28FE62B5B557B79924812B320F3511F1826E2C6E6FEF386D86C0F7482820716A2AE0396D2A3F1168C9CA12825601F946BAEE5FED7E6D0F9439A24260ACC7FEA3D6D6F758CDFD6062A1DADC02D430E65820F128A881CF561D7EAC62333A50AF754D4B56AD43F4F6D0FECE6D0532E1B40B289036FC87CC72C39C0604A7088F943B397DF4B83E15D75884CB92A5CC2555622E79EA2E7F160CCD25A4CD53F694E9D8589DBCEC418DE399EBBE19CDC2B4D989090D4F3AFABF96D58B062A48084828D9F57736FA1A75DE25F9766A92412EC8B58C1F84FE5F9E22F158321D9246DE7BEFEC0AB06A895F351343CF93EEFEEA369652D7B6A0003CC4DF7B8F744131BC7CB1018AC3109502284353DD8EC2BA8A43F961980B0B8B6EDCBA6DEA7B219EEAB6E95A5FD62B0F0806C571EBCEDF87AC1C72BC364431A383B8097A12C1ABB9603936E213329C38A0BFF817E7B34509AABB4FC8B2921C6EB5282AE3E200970A88D801E254CF48FBB13384EC54B94A0B52425AA03020D5CFA7D1ED1852284804DADA55AAFBFBD5A98CCBB5ACFF00523A6834D52D5D53CB3C083DCBA841262095291C31026E408DF7BDA70E8C0E5AC26A524A06AC2DB780E605232A94A007C8DC562EED67A7F35D233A0EC93B5CD48976AF515635A7A8442D9529DA6796F21775F842C2D25201DFDD87A3B7B9660D6654AC08C42D343721F467497A11AD76891C3144A523BC20F17200FA8FB574A3337E61D99766590A8AF54EAA566D5693E3A5E07D94A9437485A16537DA45B99B4E2532FED1E6F9DA972B2FCACC94AE9DEA48F945DD8A6BB7D22E9829B2152E8D50DC3EEE3E9F46AFF13F649A51B7579369168D414CA2A9CAE5BC5C52365869DE28F3040BE37C4762F3DC462A54EC4E2662F88BB04B04837143CEEE6C4C31CC70A99C7FDB04390CCF770EE6FD0559F68ADB3CF683CC909AC5E5E28E99B69486E998FA95328A78CF008516E7722E76BF58C5F51D91CB30180188C7198E99654B3DFCC40E24A5C538DAFCBAB5838CAB26C4CF530043B3029A9028EF5EB6FE7BE5D867B04FB587B54F665936BFD1144AABCBF35EFD65D69DA461BE14BA529E1515A4288023C33067AC63C6FF0012FF00A98EC8FC38CDE7652BC5A0622528A4CB215319AB555454784770EC87C1FCC7B4B2FBC9485814F980671E8D51FC459751F429FB6CD45452B4F65D54D31DEA4BE456529051C60AB67B98B48EBEFC5070BFD73F64BB95A573D05C3026517773AF07BA458B35FE9CF374AD053C6F6142D701D9F5ABFADE3D1DECBFE8BAEDDBB30D1D4995E4795AC6639B3406A2AB5BCC2DC694CDDA8EF16A32A25425044F4338E2BDB5FEAC7B399EE6527101626092B265B9525290A6770C0286DB1DAD133967F4E59AA3018842B8D948621AA684DDDE8F60F6D68F49EBBF649ED5F48769DA6742E7D95139CEB535634C294E324BAAA26B8EAE405148DEDC660D809938B8647FD47E418ACB674EE20512509EF439B90426C059BABBC79E7B4FFD3AE689CE25A5D65E691FB08FEE6707E9A3D445AB4BF46CFB42D49425ECA96D0A920BA0394E4348DD3052ABCA6F6F43B628B3BFA9BC9938B5CC1352895C44035B24B7ED6E46F78E8723FA6ACCD78592172D7314100D53472295FA9BB7888B7B25FA3E7B5BD1D4119564FF005DCD5D480B2B5B03855104F8C916079100C5F0AE69FD4A767333C2A513310489696484F125C9A87600383BD2D4D636C2FF004F58FC3CE32D724872CDC20B8D03D7DF9C573AB7E8FAF68259733472856DD3298A9AACDA5C615DCA699B53AD0482A9B84C7839D8CF3A8E5DF1E32C9D984A0AC50095CC4A5142CE4802CF476BB5EBAB4BE3BE044FC2E11734C83F2A492E8B53EBAF2B39B4744F2EECD7501A8CCAAB523BDDD0D3551A7714A292AFF2EF29920A428AF7411CFD71EBBECEF6E138BC04AE01C4B9B2819600DD2FC4ED4F2D3908F3F768BB1C8C04F54B5B009514970D50762E7CC7D627398E63419027EA790D334964A10972A470852884813E283636DF9623B1B8FC5E2672153D478CACFCA280026D60F436BE94D6B53728918596B52784FCAEEC36BBDCEFE1B56203579AA5F59FAD2D55255B24491799802474D8751B5B173C065F2D7850B253C5C37200D9CBF56DCEFAC51B138952311C01C241621C806A1ABF7AB6BBC2FC9B4A6739FA9C396B4A6B2F4149AD5BA9EEC2127EC96FBD00AC58CF0131BF4C54B37C48C24E1282C3AC901296502C6AE4394D09201009D00B45C30064AE4B9090403767B0E5F48B532B4767BA3592D102BB3822E9521D514B906627893BF4076F53886188C66266097DEF75243712A84A86A286E6A09B51E915DCE731FD33940248240009607951BA73E6D1853516A1D615AA7D2E2B2FCBA9552DAD5C21086D7BFF002CF0F78142C2C626D18639B63158541938792672A6063303922E2AC091D7AEF15CC3663331934959258B81A07D68D600D0FA3B89AF0698D2D4E56C5334FE6FC278F3499471C183F5720A01E5B743BC1C4365D819C95F7D3B8932D45D726A14AD5B881A35ED53A6CEF33C262B3195DDE1E72D2A01833967ADC569ADEFB88ACF33CE2B3317D6E5456283DC47EA8A49E04BE09F100DA4A528E110088E5318B4CACFE46101C3CACBC84964925D4A0DAB94B91AD7C394060FB2F9CC8529671B3B84D59D41C07A5FC8D3D5A0A5C83526A501971AEE196E097C70994820CC88B408DE60C1F39FC267B83C220CE501C4A0590FA9B86D0BEE2FA343B3956324CD42E6CE5AD94092A2FAD6E59B975E5135A77B2BD254EDB3488455E6CD24F79C5B2957224AA5361F740E78AFE27319B9CCE99C492251344F0B1AE8EDCAE0DFAD2CE71495C9972825949001377207F1B7E62079FEADACCD5E2ED5552997D3B5189088B08E2042222E3A89C39C1654785294228F43725DCDEEE1FEB5308124B925CF3E7B69CE20799EA4A5612820043EA90FA7886FC8CDC13CB9F9EF8B7E03252A524A935A55BC0D5C3FF30D4827881AD68F773FCF8DEF15FE6DAB1A1C44293BC0F101B9F2B8FC63D062F797E48470B259AF4FAD74F65A1232DC07152FD1BAB50DFCAF48AD33DD521CEEC36EA418513E21279D8137B6F63E6631273302A9588C3A384B2D55A74BB35C1D3A8112D9765C898854D203A6ACDB68F6F0B6A62B2CD753B8B2A0974285C1215BC7483CBE5E7B63A461B2F9186972D53120384DC35C36ACF43CBAD0C46666B9B3C2D087570529CAD61BF3FBC40EB351BA54415CC722BDA3AF3FDFA9167C365F2972C2D0010402384392FD1F573F8A46BD9533533D52D692C540317B3DAB7BB50DF42C222798EA074951EF02A761C516DF91DF636E9B6109582519CB41140450587B6FF348B567995210A93338402AAD03EDA003DDD8C44DFCF5D244AF7079DA7EE9371FB8C5AB0780EE9344B95004783BBD0BEF7109AE4714B4252C03063C837D3D5A186B33C74AACA2520112153EE1D27D2F7E5B4ACBC1AADC229C8F4D05858EF51D124E1406E2A91AF95181E5E3CA19979BB8A90A5445C5FC8F9C74E62DD36C3C460CA4B101EF4FAB51A95DFAD4C3A97877341437A7F3EB0DF519BAA6CB85007FAB7B7AC7422FD075C3B4614901869F96D7DEFAC3A12000346BDF573BF88AFD2A959CD5C5154ACC0E40FE33E44EE4018752F0459CD01F60D6BE1D616461F4097D6B46E752F4FBD0462E664AFEE5DA62F1F8DFDDBE161826B26D46625C697FA53D046E70E59CA03757F1BD3C5A123B9829444A95F133CF19FD116A20F93FD49BFA368F5C770FFD8EDE2DEB1A85728FF52EDB9981F3FCF18FD1285D247FFA47DC08C19005E581D7FCC62AAA539CC9888337F7F23B7C2FCE709CCC44BC1944A586E270E457F1AB75A68D0BCB4265A492900914047A83A50EE2F7BC02ACA08014491B9076E77106F1D63EFC48A1099C90A0C41A8E6799A6E2FAE9681299D354000A52491462CDD756F61E35BB982D447888BC448BF49DB9F90DF0D1139026141961206B7048FA0D776F387F3B2E912A57794E221D98120F9BD6DB73856C3EA4A544ABC46F79F8F9EF617116E9853152D465ABBB62520B10D40472F7AC442FBC532524948705B67EB407939FB70ACD5482471F0DC820AA0D89E46E3DFF007401179361A64C9738CD4170A277B13E54FCB40BCB810998104F139701F913B52CE2D0EACE66B21104C9DA3981B91E97F3B79E1A6608561710084FEE34DCB03777D3C29A3C3544B5E1C28005B7D00DBC2961E20830EAD666E20825563E640B4F537F873BCE1BE232F4E3D09F95DAACCF5FAE9CFD68C710833ECE6C4DCBF81A79EDD19EA97355909E254CF98DE663CFD26DF18D3F41DC4B292914140DBD35D687CFC94C1604A5567259CF2AB1A8B575A8DDA2434D9A2B652FED6C26F6EB11163B5BE2710EBC110B52B86A76A86B0B1B736DC6B594C4C970070B90CD5FBB816160695A0897E599A2E5202FA589DFE307F1C4662B04A20921CB5473D77E85F9814868249492FF002BB102FEB6F7B3458393E64A58582AB2787FAC1FBFDF7E5CE3158C661BFEC2F5F99ADE15D7A575AC2A896439BD9852AC4BEB1AA95BED3BB4FABEEA8D87E8E8DC5417950070C6F0A026C3CEF3BE2898C9F86CAD049280946819C54B52EFF61E6A892AA0B3EDA791A7E62C7A0EC034D64094661DA0E6C9AD7C80E53305C20A08BAC10DAC83E844748B6206676B26E2499584415D6ABAA7836A1BBDAFD79EE24F0A5492C4534AD399AD1ADFE21C337D75A5B4C512E8B48B5474CA690529714CB6A5981B853A8E29F7CDC1C3CC364F8DCDC714E0B592494B3A58DAC3E9D7A46BC0EE52E0747B5ABA30D472B475AF51F6C59AA96F2330A9714B54FD58A1E5251CC2A1283C207AF96F8BFE43D84537793A4F11A28F121CD37D69D4EDD59CFC3CF5AD250E438AFA5B93781A36FD6DD55AFABAB5E73EB4D2DF4A8F857DE1B0246F17239C4F43EBDA7B23904AC2A4A512932CBFEE2069C8B52F5163CAD6DCA708B0904A8956A2BA695A3F5A54ED15C6639A3CD394D58BCD3B84A43850C4779F68006402608F39BF96D7D3819331425094028302A34E27346068D7A5A2DB86C38580172DC9E16511FB18EC68417F30D488857EA6CB154F507EB1F58AC514F842549248513204401CE7D7A62A7DBDECC77F92E289C40C30EE54CAE2BFCA6A5886F16F48EB9D92C9F0D3D72C280D2AC391A5F60DA72B47E80DF413E62DE61F47FF0064E92D04BED8CEBBD709971415992C2428993610624F4B5B1F9B9FEA872F9B967C4CCF659C519E81353C0B27E5A26C1C90EFE7A47B93E15E5F87C160125084A8D2C91CF46DB773473B47B3A0212121490BDE2C3CBCA4F203D27738F33489C661583352E08A3B372BFB6DE3A6E63DD95A099009E497722CF46DADBEF53AEB94534C5688111E1005EF1BF972B73C45E284C9988969188FEE70CDB8D8DFCAB611218432C4951320370A87084835E122AC3CDED48F25BDAB2B6BBFFC5E7B3204B24203FA9803C3B4D322796F020FC71DE3B31842BC927A913C02657CC2F50926B6E82D51CABC1FB50A9433843E0C319AE0B3595436D77FABC7AB54E7868284A129054C3455E1927C099E53F198F2DF1C2F379B8C958F98254C51489847083407888D7DDC476BC8F0D859D97CA54C9284932D2C0A43DB524736AEBBC2E14EC8325092B804D85CC5BC85B903EE8C4A499D3D5201571061B9A96F0D796BA188E9D81C01C67089681534606CE76DCFE221FAF1B791A6B3BA86929E16B26CD14E3600F19144F70DE0C41BC5C6263229AF8AC3A66A8F12B1128A0D411FEE0241B1F173F730DDB6C1E1B0F934F9D2A5241125668904512696DDFC0C7C74EAAD78F54E7BA8E85D2AA7E0CE730484892920573C36063D3A5B9463EB17C2DC189F9560F8940FFB32D9D8FF006063BFDC9A88F8FF00F15FB55FA4CE3112C0349CB000A37CDEEDE1486BA4CA737D595F4F4F44DB8780F0F72A96D3565C8BF784009E1113E2C745CE30586C1CA56257313FED8E23C243F9024B1D5A9CC473BC1E74BCD148929155B301FF00736BF6E717552765234BD3B75F9DE4B505D653C6DB050EAD92A5899FAD2525B3C8DCF5F7F3F5FC43C221472F958D4495717013C40A85588E17DAACC0EB68B3CFEC362E64838B3216470F1F10496B3D4FD47942456619FE7B52D653434DF51A7A7E24B25A42528602A64ADC484A5E9E8A51E1B6D189B09C0FE8E6637BD0B9B39214B593C5C647ED29492787C39C73A9D8D9F84C5FE94B8659480EC4176F176B7D3495E4DA0E93295A733CE72F7350D7892EA69D2E28B4A3211C4194AC1DC6F698B6397E6FDAC95809CA9499E996A0AB93A38DF96B70E6F17DC0F62B159EE1FBD44952F892FF00B5EFD0381C9FC18D63BAA6BB33A52F36285DCB929FF84C10A6D6DA0C9F1029413E188E2FBB1D0BB199A65F9C4BE35AE59596FDC52A0A7A30AD35A6B15ECCFB233F20528CF94521C9A829147D2FF626FAC41D9CE93528465C285FCC2BEB894B496CB8A51524F2080A1CC4DFE76C5833C9596E5E8562A6E224C99680E949524F16BFF2046F60748D3229189C4CDE091215398B3004DF981A0EB4A0DA27F94F6579952B4C669AB296A68D2EA92ACA2816CB8555414A1DE0052906DE1DC1EBB639D27B7B93E2272F092FB92CE933810784876241BBB72D758B566395E6D864248CBA77090C7E45077F0BD28D485FAF2B339D26C50D3D2D3D569CA5AA491DFB94AE3A1C4881214E204483D441331CF1BE1E6E0313350B463E54CE253F0256950AE84051DDAA2DA4404ECBB16A92B33B08B96C29C40D05DEA01B7F9ABC52BA87508CB5483F5AFAD3AF24A9CA82384AD452083C3B02276E73B6D8EB192659271B2E5F772D20331501C54F01CBDD445352489D312F54A99A8FE1AF3F08A773CD646566403C8CF999D8833CAFE7B62F597F66CF106451C3A9835F636DD85DE1624E9E5BFBF22D5D08ABB36D53F598E2708E19BF15CF3BDC7588C5F703D9E4CB0974D5AA1AB50CFD4302F4D61CA5254453AB69D3D748AF735D4083C52E1EB1C4479723BDBA7E0459F0B94A5000096AD9AAF46A9F51E5A0859325C907A3EAFC86BA7BBC12B73F68B88594778A01690F178A031C40832926153CB7239DB1B4CCA0CCC5E1D610084A9DAE28DB126BF8D5A27F0004AC1CF0402AE1B9069422C76A5BC225DD957613DAE76E4C6A66BB23D3CEEA9AFD32AA75D586AA50CF748AC2A578B8C904700306F611BE28DF1A7E20657D8691949C7CF460A6630284A429871776520B10D5F017D5A935F0FF00B213BB4D371E65CA54D12880CC4E86DE5A7A5E2A0ED234A6A9ECCF5256E92D6B96AB28D4D96142731A353E1D5214E242D01412400384F2DCC1BC63A07C21ED3E1BB5F942F15879A99C829470A8317770C0FA59C6ADAE734ECA2F20CC528992CCB06654314D9B5F3E5A456157992493E2DC5AFF0018F5F2F3DA71D6F0D94A44D9930A5C1219EB6B7AD6A5B5BBC63B440A9186421AC28FC853DD7EEC6EE6095ECA262473B4F5E5D45883C84626E5609291448716E54DDFCBFC4472243CA4921E8ED5E5D1DF52417D4B59ADEAC02615D64933F21F77A83E4E9184A82534B966FB9AF56E70A230E285827A56DBD6FB3F5867A8AB4920F175D89B8163791E9704FB8CE1E4BC182430706E763CAE6E21D4BC33800077D68D47AB1B7BAC372EAC6FC4608224EDD391803D7E18708C154B80E19DCFF3434E7A43A1863F2B33694F47AB1A7836CD1ADBAC4A64F11B98DF90F79E7875FA5E160DE94A575377D7F98728C2392784BB6DCEBAD2BA6958E175A08038E7717206FBC926FEE8C6C9C3D4FCBEFC2BF6854E149B20BEAFB741BB743091CCC1488EEC933B9E5E5CCFE07CB0A8C3B8A8D742DF5F41A78C6461535E2A7D69E3CCEB78D5FC51FEB1EE18CFE993AA5FA91F983F4A8AB971D2B4B5493E8D0E1495DC6CBAF39501A5330024A67BC0B3004F2F5F7629FDA0C1A5536532C4B636B95390481A3F87DA18E230C7BD972D128CC4CC77502C11C350E357BB3E94A9A6972ADB5FD692D3A9A3701680A92A0E719598F0B64C6C48D8F2E58C62E72725C21C4E226F04A4A38895960400F724742DB30D00E83D9CC8862F0DC265712D88059F90637B30229BEC0595A6FB32D55A9F2ECCAB729CAB32ACA3C99943D5D99268AA4310E24AD04ABBBE048B45947DF0239D4AF8A7D9AC6E3D3814E3F0DDFA97C28477A80B2A70FC20A9CB78DCC2799F6233390B33132D66597247012002F5D74E86915A8CD2B5C72A51564D1AE956A69B70A78CACA1452A1C02F3298163E831D6A41972B069C54C295485238CA8AC335DC9A7F2D6D4B5C1F644CCF9420AD6A241604104E9677E4DB44F74B767FA9F57E5B579B655A7B33CD90C20BB595C9A5AA699A64B61452A24B45A5029178200FBB94E7BF18BB39946612B2EC2E370C674D982594098877E262C389DDDFC9EC4C4F0EC2E324CA066CB522500AE005069A9A8A914D6D5862A2AA4512E9DDA9571B8D2AA1B5B1B290A6CA9041024CA488BEF1E78E8786E1CEF069C62450A02D2A1FB4821CB69C874A450F39C957852A48B28906837FE6A07D840D6726ACAE4F025B24A5237B93631723DD699DF1A6580778B92AFDC0B01D1DE86956BB5DCDA2BE32C095213FB9CEDB11D79B72F0872A7AE91E9E67EEDF6B74E73D5FE2B0CE8259F930EB4F643E90F4E0061C0570D5AA6E3C5EC6E7D22434398250492A2640B93B46FBDF975FC0E20CE1DC9252C4934059BDFE68290C8A4CC253A0D2953B8AFDF9F496D06669041E2BDA21476F8EDF7EFE586389C30AD03D6AD4BFB6A168D152002771A558F377FBFDDA6995E6A94A95E3224833C47CB6BFE43CF6C55F1984624A8380E053EB4D39E90D94185410A0F4AD7A731EEB48EEFEA4D77479252AF2ED2EC314A96D250A791DD83000BF88024983B6C7CED8F2FE5F2B159ACEE2C5256A5ACFF00738034B160586A767021D9E15324103503DF58EAE6AED6A97D6971FCC5EACAD1C64B3C4B09428EF1E2298B721237E738EBBD9EEC22310D366A42258296200A825BC5A8C45EB58D84924EB7DABEFEBA0A18EBB6A8D522BD4B4BEE2E98A49809528CF99E1D86D73C84D8C476BC9BB2F84C0CB4A932D130001D4A6480DB0259DF97A429FA550A31074E7BF4D5B72F78A8736CCEB9D5B4C37DE55074A934EB6817140CC1909E2373D7CF718B94B5E53859478E74894784BA0A904D05831D0D1EBCDA2CF91E5986C413FA852659A37151DF968F4D236E4FD96F6B9A9DE42729A15AA85D23C6F06D9E14AA2E7BE00C409EA7A6D8A3665DB8C264EB599684CE0825B816C684B38483ADA8CD56117C9794E0A4CB79650A0055A8F461F5A569D69169D1FB2556B259CC3576AA6B2A091C4E5325B6EABBC9890436E1E189FEDBC8E98A663FE3263D73E5093819894F1101B88155280FCB6E76035BC45CCC74B9426489412A3C4385419C005C80CE4BFAD75A0794763DD87E9FCC5A7334A819C901417097D89213127849893B1DAE7A5A37B5BDB0CEB3DC8B1457266E18092A62144B82935A00CCCED4E82B16DECE674AC22E58528A7898026868DFC0A53CA3EE03E86DA1D2543EC5FA019D1F972B2EA39CD4477AE3A14057AE08EF0DAFD2C2DCB1F017FA8F38D9FDB8CD25E2F11DE244CFF6A802925892E412A3CB88B801C56B1EF1F837987EA700389355004A8B905C13FE45FABC7ACA84A9284C99266474B8EB279CC4FCF1E5D9397CF13261134A413B9AED7FAF5A476AC5CF4861C1C4776B0E8DAB7DEF0933104A50A0762094A60D8103AFDC0F4E738DA4E0569C54B0B98684B924D6ECD5DF61A7587B839D2CA1654001C35A5A87F9DDAEF48F33BDA9ABF2F4FB577B32B6E368EFBBDD4BC20800ABFCB372424DCC0E9CB7E98EF9D90C2CC392E604ACB2658E100D4D0DAAE7ADE388F6AB17874E71292A97FF00E630346FDC2A36F623D30A31C6CD3AA3C219660721FCA4C5B9CDBF1C7259B2509C6E256A524A8CC3C2EDFF00222DBFDFC23AEE5B342F2D9440E11DDF9B871F9F17E71B908714F49802E77E97F81DFE6061CAD52C4A60CE41A02CE1BFC7973AD6E5C9C4AB1C5452A090B2C482C2A77FF3D4888E6B2E3774AEA26511DF2F26CD12D091E22285F88E5BFC46F8DF2B9DC18FC299859A721A97216920817F5AD3AC3FED6611589C871A07EF4E1D756FFB0E9E6E7E8098F90FA6ECDA9EA7516A6CD357A90C3633BCC56D78924280AEA8200283D2279DCF4C7D2EF869DA6C5CACB30DC1296DDD203D69F2800DAAC757BC7C4BF8C792255DA1C50E2048C42C5F751D743F4D9EB0E8EE76D51D7B74FA66943CCE5EE35C4C349F155265370E04F123840B998DE77C755FF534E272EC7E2312A2B9E994BEEF8C90124A486E13436614A748AD64395230D9865E388042A6238CDC5D37D1A95D478D7DD6EC934769FED6FD96E82B337C929575AEE5B5AB7A987766A5B5529594F13E91DE8928B49079729C7CDDED676B731CABB6D394A339027E300487504B05B0205850B9661E71F47724EC46599C762A64DC22A5CF9C8C239084A5441E07A90E0171CCF311E2EEA7CFC653599E69EC969052A72EAAA969D4148EF29D21D73861C52429C2A026C48000EB18F76763710ACC7B392B309DC6168C2F15492144CB35634A31E6795447CD3EDD65389CB7B5E70AA92A42558C290188FF00F319B9F869ADE3D58FA3C3B28CA33AECE6BF5BEA2A76733467A406175C84A52834CF2DA50497A5224DADCE37B63C55F157B6389C3E73324E1714501135695B176F9A9A1F1711F48FE057C3CC366191CAC462B0E95F14A41495258074814D76AFD691D5CFA403B28CDF24ED3720A9D3540D51E4DA8BEB7F5B094B6DB4D2699A4849E22129209322201F3C760F81F9FCFCC30AA973318A54C40485A8124BA8D280DC78D7CA391FF531D8D9191F02F0B2C251F31570A40A029ABF4AD746B8887FB20F66D91D476B9A4F2FCC6859CD65756AA84A825C4A0A5A2B4F1C71A45C5A472816C4EFC699F9865D951C4A7319A014FCA975077206A473A8D2F1CD3E036024E6B9870CBC1A715C0B4F79404258D5FE53A0AD7AB5045D1EDE1DA9E96ECEBB5CEC972CA3A0A5A5CA74EBB5EAD48865B42B81B710D2E9F8D9420A956981C2666D8E19D83C266F9B23133CE266290B4A9D64A884B850DCDDDEF4A9348F58F6C256478491264FFA6C94AD80092948515001EE01BFE2D48EB97B607B5EF62DDA7685CBB28D06C37519BD2D3210E3832E76894D38037C652A718471EC762769E77EF3F073E1B6759A6638B9AAC74C9B2913905BBC2B48471925FE62D4E8ED68F3F7C431809981693804619625AC06481C6480DFDA34634DDAB68F22739D68BAB6D0E0A97EADC1DE175A4D33884B026C0391C2B1020F0CC45F79C7BFFB3D84C9F2597FA5C462E4255292848599882A5961C4384AFE562750E4C78F8767F375E3311311859AB965648012A00004EA017E474F28AAF35D4B59561468E96AAA409934EC3AF8B1DBF94857A72DA0F41D07099B767247089B99E1D0542814A46875756FD7CE26B0FD94CFA785775974F98CD6428EF7F969E3E1159E61A8AA0294D3A87699E132DBE95B2B3E5C0E2524C499F4BD862F395E2328C6B1C262E4CE701B8549376D028DDA8FE71BCFC8733C00FF00E6F0B370E752A490EDC940575D85DACF09CDF3DA8209E3299B03313E9B4CF31E91899C5FE932F94666216994801F894C186A5DC7D5B5D042984CBF1189253265296AA330249F2D0D869E31147EB2B5E6BBC3956695C82470FD5A96ADC41837975A6CA52204DD5D205A04049ED7764D13C22666D8497312AE101531018920070577EB4899576673DEED43F433D12D49AABBA5916A5386DCFF0088FA24FF00C3F34FFC4F38F69DEF288501A4A6D32426A521C5A78A9DE3F65E128248E8279EC4E3E6C7F5FBDA5C0E3335EC649C163538D4C95E278D522604865AA5900842AADB97F3B7AD7FA5DECB9948CD5799A4A030215365F0E8AA7CC0077F2EAE23C90FA4F9F799F6D1ED756B1C2555196A65238504229624204045A2605EE4E3D39FD1162A7627213278569C3A254A290B51506A93F329F9EAD63AC56BE39E5584959AA7F4265CC5198A7086705E96BD741EA1A3CFB62A6AAA96B14ECBF544D9229D972A15249E4D25667CA3F1C7BB3199FE43810462730C348EEDF8B8E621268F4AA9361E6F1C1734C9F3198A93C7849C525B80842D4EE06C08D75DA123D499CD2F78E55E5799D2B523C5534354C220EC789D6D222F3BFBCCDE1307F11BB1588C51C3CBCF708B9A5410940992C9772187CFE6DE10F53D97CDD3290AFD0CF08E176521428C1B4766360073B4332EA9D75410D256B52E7850D852D4A22660264FC26224C62ED3331CBF0D253899B88968C3A805A6628865248705C9666E7E17847FD1F1B2D410AC3AD2A51FDBC25DDF52DE97F186EAA5D43062A1B758528F843C85B73D63BC026046D244EF8532ACF327CD57DDE5F8C953D4925C2169241ABBB13F4B36D0FD792E370C90A9D8698806A92524537A86DAAFBD748481C71E3C0CA5C79667C2DA14B51F720127A9306D7EB896C663307974B13719391211565AC8F17A8F74D61F61320CCF1C954CC361664D4A3F7292951677BB258D053ED78D2E9A964F0B8CBAD2B925D6D4857C160131CEC7E186D97E7D93666B28C163E4CF502C52852491D589FA427FE9D8996A32D72D499828A0526EE69B0F7CE13A5558F71772D3EEF0DD61A69C584FFEAE049299E40C4F2C3AC666795E585031B8A9520ACB242D690F6B3900D4EC5EB5348772F25C74D415A30D316848752824F08BD7F6BB53F98D68A9712EF74A4385E5FD96D2DAD4E123786E0A8FB87CB0D319DA3C87052933B139848932D41C294B400433EFEDE12939662F1333BA91216A5A4F094A52A517766A5AADD7CA1CCD2E6E96FBE5E519AA59DFBD396D586E3AF7859E1F3DF11586EDD76471733BAC3E75849B3096094CD412EEDA178959FD8FCFF0D2FBD9D97CF972D9F8952D6CCCEF61A08D2DD653394D52D5532424800B8A25B2D284C4A6CAB9226622DB8B61CE6B81C3E3A4A71D22705F7693351C350A08054E5A961476DB788FC160CAB12996B4578825448B0763D3A781E7ED87D1C5F46D7651ED01A2D1DAD76D5AE32BCAF4AD3B89A84D1D656314EA7514EF10524FD65A7374581078B90BC1F9A5FD527F5419DE4017D9AC9B289F8A9C53364A972F8C04708677082F67BBD3C63D37F0FBB2194A9289D331929165709625CB96297D6DD23E8A352763BECDDA0BD8D7B435762D94652FE4C9C86A1A7B3A453B6F2AA1746D3EDA16DBCF214A212E20DDB70C8E626FF363B07DBCED3E63F12726CC733C5E310538A9B351853366A59D5C452A4F1071703886CC184764CCBB37835E5AB972F08853240337841715AD459B5F5BC7CE37D1D3EC0BD9C7B4E506AAED5FB5CED2B2BC9F4A6439EE60E1A2AE14F4A5D6D19A54A3BB014FB4E2802D40213B444E3E907C52FEABFB4DD9AECAE5D91E4DD9EC4E3F159AE0E64B13E5A9694CBEE258E251504101C56A43E95B50324EC4E469C619B89C6C99650B1FEDAB841249B00F4AF237D9E3E9B321F67CF66FD2BEC9FAAEAFB23C9F24CE3237B4D66ED8CE986987455B941495282B4B8A42D40A5D41921773D6063E6164DF157B5DDA0F899819B9862317215FEA282252D7308495CE4F121A80B3B07A8F37E87DA3ECCE00E4CB99859289A132DF8D207CAD7AB5776DF5A47E7EB99553CAD5DA81FA670AD946A3CF5A4B53E14A5BCCAA5B09126200004011D06C31FA51F85AB389EC06553B17F2CC9D8294A73534969F534A3B11D23C5FDB3C261E54F9C94949505101340CC5BCB4D3ADDD61A9E179C360A20152428409120743783F3DF0D64CE50CDA62250E24998C4836A9B36F5F50D578E6D2240E30E011FDA4EB537A68DF4BC2EA5AD22C5422473E91B19FDF3DF17B9D870653B7F66CE6CFCABE5BBDE15CC30EA4C8701C0069D28F4FCDAD687715CA44428136BCC6DB72B72B73B46D18ABC896A993660092C341AFDC59ACC1BC62B3224BAD4EF7DBDFB2D787EA0CC9700C9E5CF6E5204D8F4F913CCC46195574B06EB7AB81AF8E9CC18DD72D9C1A8FA3F5BDEE225B419A2E6EBFEDD95B79DBDE3DFD6715AC7619469C06AE280F4FF01C5BAB329A9B38FF00D5CEB4B794762B54E6C071A83A41333E237F58DBA5EF7DE71C7A565D225E253C12921883448152281C6D51B4339649559857C6F7DAAD7D6281CFF365B6EB4FB0A9711DE44999E4678A6C7AF58C769ECFE110BC1842C3215C2EC360E2CDE21CED13786AF8375E9EBD1B5178A7EBB33ABCC332397B6477F5B534F4EA240801D712824721014762248DF125DA5E2C2E54461D4A4044B515106AC2B73CAA7D889895278A6254A4FC86C79B0E5A901AC3AD63BE792F641A23B2BCAB2CA9CD69855E76ED326AB89D4AD694ADD6D2E8B282907EDCF3DA48031E5F38ECCB35C73E1B1737F4FDEA90085AABF310AA39208E7F888CCD676264CE0B0B29516A804381414040EA79B934AC573AED1B387EA1C6A90B34797A014A034869A21116FB294AB94FAEF8EB196F667032A44B99350A9B3D41255C4B591C4C0BB17162697DAD161C063316BC1CC2A9A543828EEE457C6CEFCBA5285CF359E62BAEA86E81D76A5E724A94BA8500929499E14AD445FC85E3DD8B22B29CBD6A92956165A96183809716636ADA9EDA23275CD5E3546628A92A5901DCB876677E74F3A98AD6B350D7BB46E2EAEA453BEEBED0727857094BC018BF4990236DB1359E76764CCECFE365230E90A561A6540AA7E451156AD3DE9178C405CBC5E0FBB0CEA4B80F40E9A96F36F311F6FF00F44CFB487627A07D8CBB31C8339D5749499930D6646A43A8292A5AEB0AC0054A093626627CF1F9D6FEA4BB1B9D49F8859DCF5C92705371044859500ECE08FF0095F4E4C358F7CFC27CD64E5B92E1C14FFB9DD8E335776A58789FE5A3D3C67DAE7B07A893FE35A0513B789223FF00783D368C79E667657311C24E1C8059994039DE86DC8C75D91DAA91312B2A092C39967F06F7CDA305FB55F624AA86186B5AD125D7C90DA000E070CC09F19E1DC7BB6DB0CF19D97C6257294B42A5A9C355DF97F9BBDAB0CD1DAE90913425600D6F5607D456DBBBB831D07F690ED5FB27CD3DA6FB08D495F9AB0EFF0085179EAFBE43842426B29D00294942B8556BDC1B74138EDDD8FECCE3E6F67B1C6493DFF749E04B0D01E2BB5EB7B4705ED876C24FFAEE140AA0CE72412EFC405B9791FAF7968BDAE3B1147749FF001C51381D6DB4A29F8384B2A420050278A4C9EB1B5A0638D637B25982F1B3D2B796B4CC5380417254FEA5FA73AC77197DBBC2E0B2FC12952C282E527889A30090C0536D47DA256DFB4AF63B52D17D3AB290242642B626D22DC40CEFBFA7A88ECCE612CA122515B9B920077D9CF21B35ED12D84EDCE027CA331284B84972D504F36372E5C0A39BC42754FB4E7636E64F9B32CEADA572BD596662C52B009056E3D4AEA001E21CD437F8EC70FD190E2B0D9860538895DDF14D965831765A6ED43B78D4456B3BEDA8C46539A32C1692B09029FDAA05CD3DDA823E726BB4D6A1D439C662AAA74D2E46E667983E97C29278D976A9E701001076563E90760D587C2E43841DC85CC3212C1AAAF94063E8FE11F1E3E27E67FA8ED1E2C951FF00F10B377BA8F3DEE1F76D1D5A15A4F42B81592559CCF34752A43E56C2D2195A92522EE05257C526FC8EFE53B2E4E2B3454D95DCAA44A7AA41278C39B6C035999AB668AC23303225CA5057FB80122B66622BE9EAD1EA67D1C3DA356E6B4DAD74267D5014D965A4E5ECACA600A843AB73BB40B0B284C0DA77E5E47FEA07B392F2DCC32FC7C99211DDCCE359081F310A4DC9036AB9FCC7D02FE947B5666659986131F33BE4CD95C284CC53B5160F08579EBA691E6DFB57D02F43FB446ADD2F48CA826B336CAD9A6436D1850AE711DE59293301D2609B795E3D03F0CBB5D82C6F60569529089D2706B4A8135044B291B3500F0E748E49F1ABB1E319DB5C26270F2190BC5B92948ABAC56800F46D9DDE3D63D679EB5ECDDECA7A4B4FD3D70A0AFA85E55514DC09EE9C70565753543E0410612975415CA3717B785F3FC9A7769F3FCCE76154A9A11885BB025BE657E29A1AF87B5BB159B49EC8F6772F913C0940E1D00020020F025DF7B86F1140219FDB652DEBAF673CB7B42A1A84D65465397D0AA9DF6520281A92C21F3C683E466F3F3C74CF833982BB31DA219762014AA7CC9685A9668CED650DCEDA5ACFC77E3BC8576AB239936534E2A9534A384026B4D37B80C28D778A1FE8BBD38ACC751F6A7AE3362A552E434B4151953EE712D3E0A675555C04CC41410A8FBA23A6FF005398DF9BB3D83C3AF8D3981095049A2788CB0280B7F73D5E28DFD1B7674E447B478BCCE571197F34B334587FB960A0478383D2F1D00EDF3B4DCB3B5FF6D6CC1CAD6C57698AECE692810DF787BAFF002FC34CE0481B12B490A81EA2F8BA7647E1F4EECC760A7E2952D4A5E2704660590470BCB2A0C5BFEEA6BE04449FC40ED2C8CE7B5D2F0B8629E04E2420A50A0430500D4F3A6D631D85FA4C7B09ECFBB23ECBF446A9D0990B397BF5B42DBB59DDA882F71A29E49E202D0B5796E76C3CFE9073EC42737ED665B8C9866210660725C83FEF70B29CF0B10051ACC6AC218FC68C99183C26453652693929E2012CF496EECE68EEFD6DADC5EC3BEC93D82F6D9ECCF95EAED55A69877387A87303535EA75C49A782E214E10980B800AAE6D1CB1CA7E2E7C43ED4766FB6F3F0F85C6CF121589504A12B57FB80AE8007A338D2FB88E87D81EC064D9BE469C5CDC1CA0A449054B29490E52EE695766F13E1D77CB7B55FA307D95F5337D966A5ADA5CE7575066CE50E74A5D0E6150D2DDCCAACA695B0EF03AD00D77A124A55102F187F2FFF00BD4ED5E0F119A617178CC26151251370C4052C21900AEC6BC446BBC5C3B2C9EC56598D56031587C199A66776C5281A90033737E8417878FA4D3D843B14CDBB0EA1F692EC3F29672E6F2DA36F31AB5D138E38DE60D661DDF7278388251DCA16491C2798306062D1F007E3B76A724ED88ECFF6AB319B3947132E5494CD74F02428853D4D081AB0B1B8880F8E1F0DB28CC72F46332AC24A948EECA94A9612D514B0B3EDCE3C95FA3EFD8CAB7DAFFB5072873D529AD09A51F4AB3B7B825B525C0A52525692950F1B651E156F36C7B53FAA0F8D583ECA76572F5659344DC6E61872112E5CDF996B2945B87626B7B4713F853F0CF0F88C7CC33D2172E52D24852416626EEE28CCD7F331ED076B5DA3FD17FEC44ED37657AB32FCAEA3324B69A5D4714B53982DA70B63B9529C6DB78B654553E150BEE4C63E7164B86F8B7DBDC662B32C1CFCCF0F216A13249489AA4A03BB3BB105FF00168F54CEC1F63B2E912F0B3F0B8452929E151504024D8D1BF8AEF1DBDF602D2BECA39865BDA876B9ECBD5AC3B9676954F42FE7397B02A1B5529CB5A712C0522A085A78C95010948E5046DC7FE30663DAFCB73DC932DED38C44D9A89FDD89B394A257F3201531729091A3F3ABD1DE5792E513F038E393AA5C80B40F96530268A37074F1A7311F2D9EDD9A0F5876C5F48CEABECE34B65EED466DAC334A1A4A4A169216B534C53A1352E955FBBEEDA25C85471011D4E3EBE7F4EFDAEC8FE1E7C239B9DE3B1B2A4ABFD3CCCEF145293C5C059342093C54E57358F3EE33E1D4DCC3B4015899AA9A9EF8B25609A055C13AB55A3DB2D21EC57EC31F474F627956BBF6A534555A86AA958AB7EB6A8543AF5454B8A42C34DD134A70ABBA5B81B3C283B49006DE1EED3FC50F89FF001AFB4999E1BB0F331872FC36226A672F0F314A010A52C24802B5636F08EDEBEC6F65F26C1E1978F93875AD284901410E4802E48247E5CD843AE8CED37E8AFF006F2AD1D8C694A4CA58D699834E31434BF52AACB54C843656DAD0FA9A612F153402880A244C1BEFCFE7E59F15FE1E6608CFF1F3F349F2B053113664B519C12A2140A81724338E90DE68ECAE3C8C2E1B0987750605212785A9B397B5DED68F1D7DACBD88321F60BF6BAEC9B33D4CDFF17EC2359674ED3525229B506128796C539429E1DE3A65EA800159F43C3B7B8BB2DFD48E3BE26FC3CC660A5625597E719560D689A9E22B521610A0826DC5C5C1D45758A2E73F0FF0D2F32C34D4E113DCAE62492122A388122DABBB73AB3476CBE995F611EC7B40F609A23B68EC4B4CA74F30DE5B435D9C2A9DC79F4D50CC51485A512BB2203AA22DD7D71CE3FA55FEA0FB519476C336C176971F331C9FD6777253314DC23BC58701C9A863A8F38DBE28F65B2EC365584560F06842D329D44243BB26EC0BEB61F58EB77D0CBEC69A0BDA2B5EEAECF3B48C9115DA5F4A379686DFA9714DD3B8BAE6149578EC9052E8B4F31B49C7A03FAD0FEA531B90766B2CC264188386C66310A226CB554B942943875A1ABD5E25BFA7ECBB2BC6E0B35958DC14B9CAEEF853C4134A2C3D41AFD77148CFE9C5F64DD15ECCDAABB21CCFB27D389CB322D4633E5E7556C294EB01146DA0B01448291C4498BFCB101FD0C7C4BCC3B6D8BCE26E7799ACAB02252D6664C241E30A51A1506B6C45F68E55F113B372324CE3113A5C905136728CA4705140ACD1EA035F9DDACFD87FA2DFD917D9F35B7B1EEBFF00682ED6B49359BFD7B23CC6A324CC2A5E7996D353963756DA8A00849979B48E524629DFD62FF501DA7C27C41C9F24EC7E70B9185C04E50C6CB90D30CC1F229292C5C380776D8BD7A9FC3CC8F2AC66478B18FC1CB13264A696A5330252AAFEDAFBA433FD16FF0047C7633ED01946B2F6A3ED7329198689CB736CF1CD319170BC80D51E519856D354789985B83829D2BF1209E84E3867C56FEA47B5D9965594653879D88C2E2B13284A5CFEF540A0808054524A5F8AA7C1F9C2BD81F875976133AC563674B973A4A269584148660A510CEE282EECE03C76133EF6D8FA209F5EAEEC8F37CAB2FC8AA72466B32CA247F07CC5C73EBADB6FB2905F14C140FD612920A951B99E78A9F6313F19666639763324CDF31C62A6E2242A68016A4AE5AA624CCA9240F95EDCAACC23B1F6C71BD9E9992CCC20CAA42572E4A92662529BF0900B04D5A80D5CF947CB7F6DD98682A9ED2754D0690A448D286B5E772AAC69C7385FA7756E38D1088E26F852A40009E77BC63EF5FC2D19AE27B2182979895FEAE6609099895D4998A9490B725EA0B9602C0DE3E7D66984C361F1F8E992F86B3144240FD9F329AD43EEA5DA204E7699DA05168C4E8ACBB50E6F43A64D7D10EE28B31A9A50106B10B221879060991D0DE6C4638DF6FBE086071B85CDB35C76024CF294CC9A17325A4AAA16A35209A0E679984BB3798E2E5E6F874CBC64CE033405490EC9AB0ABB1E63611F719ECCB4196577D12940C55079D6DCD299BA9CAA7DC75C71C5F0BCA256E2CF1AFC7B1528C998C7C5CCCB0B87C17C7E46130C844AC2231E89699290004D92599AE6E1BD23E876569953FB10B98B960CE18572BA12FC14D3CBEF1F1263B45D6195D26A5D1596EA0CCB2FD38ACFB37416286B9FA34A93FC52A5442FEAEF2146E49BDCDED8FB5123E10651987C3D938FC560244E9BFE9C572CAA524A83C804949524A83BD5887E758F9EFDA2C6E6327B52A12F1B350062FF00E902B0923BC6625C69C888FB62FA37436DFD10F45C0FD454A91A67582955352FBD50EB8A5AEB4925D794B70DC9FEA81E58F87FDB0C1E1B24F8E786C34A9489586959AA1299694A5213FEEA1DE81DCEEE7C9A3DDDD9793FAAEC4A97894F78B5610152C977F91C13B6E1B6E71F0D41E4FF0019D517B1D4F9FDE7AE6F567CB97A48DB6C7E8E7B00A188F879911C3B07CBA58615A8949B3035F060DAD63E7B76F113067F8C96147804E5F0DD802A3FC39F106F07D6386A5E954FD98127A6D791711D3117D9EC22E566589993417E371C557D4DFD3FCC56E4E19425CB2454025F5AF2BEBBF4D442B65F4A549F1117D8133B9DBF111118E9C7826CA5310DC2CD7D0FBB51F70D0EE6CB070EB0A0F42DCEF4F5ADDEA21DCD581C104806C04932237EA6F6F33E51882C348EEE6CCF9581347D1AE08A8FA3F28AAA241EF4B503D5875A537EBE46EED495890078A368BED3D3E23F29BE179A8490C589624F869F6DFCDA313648276D542BF9E477DED125A1AE4C99267C30677DAFB99FC09DE4E21B13265F1D520835622C4EC74F388C9F29945C5363CF5A1AFA9F38BB35566EB3C70BEBFD43CE36900188FC0922390232E2A9C9530A9AB077DFEC7D98889490A55ACD5AD7EBAEDA738A4F33AB7EA52E21A5C3A2E825406D1363E5CB68BCE3AAE4321387929EF43A05F50E5DB4B124B7B1161C248B52A0723BB1DBE9BC55D5D555F97D6B398A163BFA5ACA575C3292785A7D0B31FF00D2920C5AF8CF69B0C313835CB961C290B4816A28105EDBB1B78C5A70187965491387FB6012F5A16A73D06DA7231EC2D0E6343DB5F64794EA9C890DD4667945070670DA16953A8521096592A6EEA121063C33F7E3C9887ECA769A7E0318A29C3626705604A87CAE3E69B7A0209D6F0CB37C009C25CC4A6A824289A382ED4DF7DDF58F3FF55D53A8A8ACA6756ED33ACB8A429B295A4D94531C8F974DCDB1DD70D99499F230FC052470804820B8206BEBAC38C2614A306BA31092CFBB6C3D19BEC6A1CE2A1B6E94D552D6298A961412A012A529C0E2A0DA64409E7127A0C5AF0384EFE64A524D8855BF8A03AF2E710793A267EB485A010A98782AC181A8A16F0FA51E155F574F58EBB978796F3ED86D6E28A54890A0144126DB74F77417FCC241959262E7CC4A512BF4B31C382C532C87BEB52CEFD63A16225A9388C0CD029C69AB87A902B7D3AFD63ED77E88CF630EC27B6BF627ECBB55EB6D3F559D57BA33712D66B5F441A28AF536ABB0E212E714011702DEA7F365FD5776CF189F8939D6065CC12F0786C47FB44049E2E2249AD598BFD2CE23DE1F0CB234E3B22913520F11949E2150CE06A59F5FA3B523D456BE8DBF65AA623FFE03AE03911A9336303CA1FF0021D463CC333B578E584BE2980141C29D7EC2C1FA474DC3F64C244D704F10B329CDDF97AD18C3831F47AFB34D0BED3B4FA1EB42D0AE20E2B50666AEECA60A6389D26FE5CF0C31DDAB9E152C4F9C95936F9406F001E9EE86AC91D9204CE025100DEF5A3FB60199F58E8D7B457B34F63B90FB4CF611A5D9D2D50FB1AC1CCF9A52179BD60211434C9FEA53849B120472B0C769EC576BE6A3B3F8FE09E1333BA1C33784167E270DD287626D568E0BDB0EC71FF5FC277608499C1856EE1CF8F883AD8C776E9BE8F0F65F3DCD4AB485635565B6DCA8FF00E399990494050801E001E4607AE3924FED5E28E37124CD1326198A2E400D521C001B6A0B58EF1DE25FC3DFD5E5B81EF16C44A4B062744EA0E8DEBA6B2647B107B36D3B229C698AC526200FE31997DFDECDED68F3C03B439AAD49299818170191C9B41AF3A1B81489BC2FC3993230EB48554A7FEEE7CFF817D4B4373EF61DF66CCBA92B734674A568CC6932FCC2AA8E737CCD490B6695C7495254EF0C4A07DA91CE3A3E959C63B178EC1AF10B0A289F252FF2820296806D5B00ECF50FD28D9D7638E132ACD5810F26656BA254CF50FB7947831A8B5585D456D065B50728A0A5CC6BE999640FAC1E062ADC6805289E2D900DE37DE44E3EA4760F2892AC83033D127BE52F0F2CB92DC24A126D50F577AB97A5488F8E5F14303364F6931891C494A3113372FF00316D0FD39EB157E6DA919CBE1798BCDD436A5781D84A0C922E40F14926D72676BC0C746CBB234CB13172FE4580EA05360493737A1D08F431465F7E664841258D0726605EFBEAFBC7643D8BFB54CD727F689D274B96075594666E3E8AF5281699504D390D7138B0126E6DE2BEC271E5CFEA1B24978ACBA74D080A5484AD5C406C1E80835A3787311EA5F835DA09FD9DC760E54B9851FA85A1376FDC4021AAF43AD9EF1E95FB45F61995EA4F69BEC673E6F2B15CAD6AF57D4E6CA292A43472CA765CA72B51494DC8944C49B0DF1E36EC176EE6E5F2339C12A62A5CA96932C20A8BFCC169FDBC8B75BED1EEFCDBB132B3A9D94E63DD85AA6844D2784528824DBAEBD23AD7F4A7F69CC52E7FA1B413084A19D334CF273069A7C6FDC32BA7EF1B4AA525251299026245B7EFBFD3C761D3DA34E6F98CC1DE89EA2B0E976F9A61D47D7978729FEA2BB4733B289C9B0B2D7DDB0082104876E00CC36DABD358BFFD99EAA97B78F624ADC89D712FD65265798F7895381C752A654FAD80A049298E04F082013CAE71CD7E2CE0E7761BB62AC5A5E54BEF9250C0200E020166BEDA50C59BE17E151DB7C97867FF00BA7BB4B05391F303BF5AF86911CF672AC47B3A7B09EB3ED133C0296BDD6F51D1D4B8F8EE5C5835F5D474A49500612952786D7E538D519DCDF89DDADECBE0A6CC52E5CB9A8E034570F01965B672CD5B6D175C5F66657C3DECE677899284CA54C92A24A592F45D68DCD9BA574F9C3EC1F5EBDA8BB72D195B5B52A5B95FAC2BDE2932B5BA87736E26EC24C00A107EF8C7D53ED664186CA3E162B8E5A50519594824004B61C8A3B17A73158F017C3FCD67F68FE214E4AC952518FA3925819A7EC03E9A0BC7BC7F4D6D6FF09EC47B2F57D6453B4F652CA9692910A866948B58DBD31E0EFE93F15C19F76C8B904E215F35DBE79C2D7343E5E2DED0F8E39209B97767D93FB25A6800BB4B7F13AF808B4FE8FACFD549F477D567542FADA751A6B51A9350941242D2DD604A936894A8026098DE7149F8A586979A7C5BC1E1A604AE5CEC74B40492000EB4824D9A8790A1E7171EC14B184EC6631228A4E14F096B325479F3D0347C5C675A8733D4FAAB3FCF33FCC3F8B664F6AECCB82B9D400E2CB19DBC96B88993FC9094000AB940B1C7D81EC77C2AC9B29F86BDEC9912710B9D960592109F915DC71000B106A48A3171CDA3E7F67FDA7CEA4F6F92893366F7631E9494B90083380E8D5E5E31F657D9FBAF6A0FA23A8EA350D51CC1674DE661E5B80AD4E16DC70530264901AE1481702009C7C62CEB02B97F1C71B8192938799FEA00219C703289A33338A8A6FA47D19CCF2FC6633B0183C54C4A9415820B59209249402E6E472DF68A37E836D3D97D07B32F6959EB85B39ED70D46E553EDC38E452556666907123888284252902463A27F51133192734EC5E1E74D5CE9689B2C1E25BA4A4992FF00292798DA39F7C1CCB958939C1E13C487090C410471F206ED4FF11F2EFED8FA8F52EA1EDDFB4CAAAD79DA976B73A79AAA1564B8A4A296A1D431C21E24B7084A638627CC63EC27F4CF90F64717D89C395E030857FA1905733BB944BAE587513C3423E66249203D5DDF907C4D999B617365204D9B2E5F7AA0CE4502B7A7B2F4B1F7A3FF000DE663AA9DA2F69CA1CCAB9FAACA72CA6D37FC1A89C052CB21D69F35019512507888957081B7A63E5D7FF101ECDE4B9676EF245E562428CCC4CCE3EEC207012A433B683CE3ABFC229B889D8498A9B89513C0010493C4E0DDCB79D7ABD5E7B03CBF24D4DF4D0F68D575CD30CE6D9355D21CA92FF03A0177285F7E5A6DC94A89008514A4C4C9223152ED6CCC661FE0B49948C44D38695879616842D690BEF1496A820D09B30F1022F08C2E1FFD53884F471F192D4DBAEDCB77B88EB6FF00E230D59AD55DAE764D903A9A87749D28CE52CD0F7C5AA5AC52D868F1AAE107B8761694A8192200B63D3DFF00C34F22CA670ED22F30548EFE7770654C9B2D2B291F395278540BB8A170FA93148F8AF3A6C992832A72827849E04A8D580377A7361D291E2CFB2666FA9325EDFBB38CE748E72F2F57E539ED1B74CDD3346996EB15B52C35508213C29792DD3A949921462488C7B6BFA81EC7F65476273EC4FE93088C423093945932DC321452A0C9B967A5059C5E3987C369D8AC6E745D4BEE4CC40092A2A0083F31725EA6AC6D1F57DF4EE657923FEC8BD9F6ABCD99646A8D3949A7333CA1F79612F37501FCB6A6B0A4AA0C9524C83F2D87C73FE96F23C5768FB5BDACCB30EB52B0F3A7CF429491F2CB4A0CEA10ED50001401A8C418F5EF6865E0B0781C14D9851C72D095558392013737ABF56630F196E6C7DB87E89E6AB2BEA1ACCF3F3A7DBA6532036A768FF84389658909B9E2453A6091F2C42E6B879DF0CBE2F4FC3941978638827BCB267900A8D2A070977B3DCDE2A99F60F0FDA4C995DD11314896470A43905801B16D872B3563A8FD8A6643D877E8BDCF7B415D40CAF58EA9CE5867EB253DD55775976A834D716591DCC0936817B6273E21CDCC3E3576830D8096959C3E4921656A014A48EFA53A4B86A120B579D59E203E19E5E7B32719DE3A3F50B02B4601441E573BC5A9EDED95A7DAFF00E8B1D29DB250BE8CE35150399652D3543284BEF819967749435012A471281EED478C4DEF24628FF0CFB77987C09CEF3BCBD6B992A5CF284AE695143F0850173BABCA85C45C7B4FD94C1F69049528A14A7252C94921C826CC4D40BD5C3888E7B42D72BD89BE877D2FD9464B982323D579CE541540853694D43C330AE69FAC480B214B05150A077001DA76E91F09F21C57C6FF008BB8BCF66838BC1A274A33E6295DE252148F97E524EA3D0C547B5394CFEC764A9186E2E12820000B903722B6FA5447523E874FA4FBB34EC3F4D669ECE3DBA54B590E5B58B71AD3D993A953CCD5273971D7F350E36D2421BEF3EB0471BAAB4C836C76AFEA6BFA64CCCFFA6669D98C3AE64DC2A0AE6C99287131410909AA4109621D9AA4EF7A87C34EDF19B3F1387C4A08257C20A9554804824BEF5F5D6DDE1F694FA20BD9A7DA6B2BCE7B5BF657D4395E4F9BE694B559BE6147401399AB3AA82D395094ADC53AA142A2E1544849515584838E71F07BFA83CE3E0866986ECE76F7B389981731121189C4F04B32471048290A96EB0C45886AC7A0D59060BB4592E3F112260E3EE4A82407E27492D7DFDEA7E40BB5DD09AABB12ED0354766FAE3277329CFB22AE55355D33AEF7CE04F78A0C3BC424C3CD04B800FB33048DF1F6F7E1276EB2CED864F97E6D8032C61B19290B9694149487487629A50D3ECD48F9F3DA8CAB1180CE71D875850509AB090411FB496A9B50F5E948AED154DADD6D0EBB14C2AE8545266E3BF6CC72E639EC3963A6F6F932A5764B3498B4A7FF00C24EAB80DFED2EB434A79F9BC7767B0CD98E1D64007BC0E7982057DD5AD78FBEAF662AFA773E880CB14869229BFC279D8EF645E3EB039827DDBF524DB1F9A1CDF855FD47AE7713FF00FCDD2424D984D1AB81A5E84599CC7BDF23C6A7FF00B26B95C54FD310472E02E763B7324B5A3E04330A827526A39794298EA1CDC8DFFF00E6753EFF008FC36C7E8DF26C560D5F09F08BE14850CA4A4D451E4000EB73CEF7B4789FB418642FB4AA25001562814ADFFF00F23F9D3EBB53EF17E8DD7C39F43DD125091C08D2FAB036A172AF1D6CF29989FD6C4FE6E3E364B549F8F1317254ED9BCA5708714EF52687A104FA55C1F727663853D8DE07001C29DADC157B0153CB7BC7C2A3EFAD39C6A42018FF0013EA08FF005019BD64C7327AFA5F991FA25F8098838CF87D9226657830328126A6B292DEFEA2DE09EDCE042F3EC41480C672DE9CCF5DD9CFD5A3172A549A9709901411C2677B5E27E605E3974BA63F049C14C9B36581525541AD7DB6BADA22315970932A5F086A3B806D4A0A69E1A6AECA115465266E0F23C87DE7D63718322C51C52E625CB75B1AF93D01F5D221D587E397303513A1F16EAFB6FABC38AEB4422157326D73E9633F3208F291890C534951090C4D9BCEBE1B79BC41230CCA5921874DC9BB37BB42DA5AB55A5506DFD5E963EF3F872C45AE6BD5FC5ADBDEEFE95DE119B2039A3020B86DB9EDF5F52FD4D5EA491E2E917E91EF13F0DB0CE6A8AFE660143C7EA3D988D9F86AA986CFEE9EF5D22ECD40F90557B78B993D4DA3E47FDB15AC1E5E95B16A534B3B78FF00377AC5670C82E3776B3DCFE4D8DDADB54D9ABE12410A20C988B4753337E5636FBF172C149125212C006A8BF4D34B9DAF16BC149E2670E77AFA86E5E0E4BC56D9CBF2570A3799BF39B5A4733D49336318DB1B244E42924536D2C34E7BF268B6E1B0E0814D7CEB563D43D69D2B1D8BF644EDD6AFB31D768C86AEA4A74EEA7710DE69DF2B89942584F80042E42788A88F0804DB7DB1E5BF8C3932D58BC3CC972495A78CCB524170A2285FCBFC5DF62300674A2AA0E023E56078838366269B36FE3DF7EDCFB25C8F5C255AF34025A348DD38A8ABA36133F5A2A6813C3CC4104F8419918A6F65B3DC7E5C24603385A84F0A3C0A51A293C4E1C82C960C189A9E704CC20460A6AD2070941AD058359F4A9FBE91E5F6ABA775AAE7D54B4EBA179B70A1CA2752429B521453243804F111C42C37168838F4C765F3CC24F5490262492120A5DC681F57BE9A6BA8A165ABE1C4995310584C265CC7BFCC49D34B171D62B87DFAD69FAA7AB82509013E201209B47282771698B5A717AEDC62049EC8662BC3034C2CC345137428F366735DB58BCCCFF73138201F88AD0C1C9145245AD6E576ADDBF421FA081E6DFF00A3B3B225A2C952B3DF173319ABA0C1F224F5122DCB1F971FEA4D53719F10B3D52C9E3562893BD14A16D396B4AD23E8D7C2099DCE47210A179483E40793687A78FB2AA6CAA07148163F2F3B7FBDA31E7E998351E021668C08F2AB7A4760958896A0B205007A5BD3C357B469ABE15367FD31045B9ED68B7EE310F9AE5B3166594CC371AB00DC3CE96F6E211978D9604C5300100BB867B8B5796ECFE5E4C7B5B1AA57B657B27D400AEEE95FD58091B0E3A56C5CEE0F4BFBE6D8EDDD83C0CC464D8B2B55049AD2DF2A99C6FA0361D2384F6BF3195FEB7840502B3C696F9921FA5391FB7AAC8610A436F95C7794F4E08BC59A02F11EFDB718E62AC0A978EC4CC0A202A6ACB7451A75D5F6F08EED2B3A95232FC17124377496AE9C290CE7F834E8601429510B0AD89277B0F5E717B7AC61E04AA5293C35B8A9DD85A96FBC3D939E499929443304D7A0B576EAC79C326AC729DAD3B9F07109FF00F25CD477840F07F917E4F513E58525E24C8CC72F05C257390493AF0AD275A1B0677FCD373ECCE5E2729CD014848EE576BD9557DEDEB678F8E1D4F9E32D6A0D474542DAAB1F5E7799A51C00F8146BDF1B00A8B9927CADB463EAC7C2DED370E418342905411225B56CC8079DC0D46978F8CBF15A44A9DDA3C629D81C4CCADDC7191BFBF48D794F66398E69568AFD5EF16329716DB8DB6B570C2525248F0A82809EBE40E3ABC9ED34C9B87C42654BE29841E1029BD5D9A9A3ECD72639BE27092654DC312404B83D76AF93459D996B0A7D019AE42EE8D2D3797D2D7D025EAA6C252B4A45432167BC23886CA04F15C18338E4BDAEC9F17DA2C973097390553CCB99F2B3E8AE10DC9C5FCA3A764989461734CAA6CB53211325970E416282F73AD58FDEBF499A435D685D45A334A6BCCCB39CA9FAACA32353D48A5D4D377CCBA28501EE195F182A5A609B4F3136C7CE35F62736CAB3DCC72F460E7AD789C4A124A652F8529332AC5883451B6EF1F4DFB3BDB3C12F22C04E9F8894572A424104A5252C90DCDA805BED1F2C5ED9BDAD37DA37B40F69BA9D7998550D53F4AC51C39DE3605334A60F7601294C9489E10279E3EA77F4CFD805E41924E070CA2664996A09292EEA492AA915624D0DFCDFC45FD50F6A65F68733CB8489A0895318F097A0296D756D6B1DD9FA1DFB66CA5BCE3B40ECF33FCE986F2FCCBEA21A159528A7692840716E06C3CE2130A04F170EFCE71E78FEADBE1E4FC595E3E4E1967B8528F0CB4173C6A6FED0F7FA0B08ED5FD3776B70F96E1B0F879F31290B4CB492A22C000E1D85377E7179FD33BDAF694D0DECA2F765BD9F5565CFBBAC5C4AA918CBABE9C70FD533043D530197140F1852CA85A7A1338E73FD28FC32CC734ED4A71188C34E4A72A9D2D40CC94B0E165E8480D6B579DEBD7FFA81ED86053D9A9D2B0F350158890A4D140BFC9B3DCE9B79B7CD77B2766A32EEDEFB3072AE9196D0BCCDB577CED5B61A6141C68B8A5052826E649E23F9E3EA97C69CAB118EEC0CDC26124949C3E5F302B80151534922C072FE77F017C0B92995DADC4E3262811FA90B750666593ADC6ADCA8ED5F79BE9D9D6196E73D877654CE4F99E5F9A5553E5A84BAC52D7532948E24520095069D2AB0041045A27CF1F3E7FA49EC8E367E73DB554CC34E92133C8495A1697F9A6B91C4002D705ED48F717C4EED06171F82CAA585A0996800B10744DAAC35D3CAAD78FB04EB9CA32BFA322972CA8CCB2BA4CC9BD33A992ED23B5D489794A79157C03856E05137B5A6F618E61F14FB219E9F8C32E5E1A4625CE3A41429329652405209F9827845AA01ABDCE88E51DAEC265DD9DC44954C9602A5147015024B8237AD4BFB68F8D0FE20A6B3ACCF2DFE18DFD61ED599B283E2A91C1C2E674FAD2AB9E002140CCDC791C7DC6F8739663F07F0B70CAC5952972F2A53CA5A492B6C3D2A41208DACFE31E4BCC065F3FB6386C72928E0FD5A56A371598087F324EEDBC7D8F76739E65591FD132CE50EEA5CAD19A2F4F578550AABA914EA438E2C941417B8A549510044DE7A63E2DE2B2AC6F683FA929A065D364CB9F992A5999C0A0901CA1DF85855F56D3578FA378CEDA64EBF87F230B24C92B4E0D2821D2E0F00167A35EA0757631E6A7D081EDA3A43B2BCFF005CF619DA03AC65B926ABCCAB98C86B2B2B521A612BA9AC5D61256A4821D2EDB8D4041F0F2C7A13FABDFE9E33ACAB2BECD67D96CC993E64A93FA832132C924F0CB5247102598D5ABAD63897C24EDBE5B95E6799CBC419694CF9A52975003F72858B543EC2978EC3FB64FD0D190FB42769B98F69FD9176C990698D3DAA5F6EBB34A76CE5D5296DB442D6A05CAB04132A5129005E3AE285F08BFAACED47C30C966F67F1992E3D589EEBF4EE654E676294B132882E1ADA758B476F7B2B96F6BD68C5E1E74A4852B89D251576367B0B55ED6611E837D1D3D8EFB387B29E95D73D9668FED4723D49AEF2AA2A56F5F66685D3D297DF71A71745655429B5F772A4FF002C9B092463CE1F18F37EDE7C4AED2E5F9EE3F27C7A30D331266A25944D99C492B4963F238D0E8E29710E7B1FD8D9393E1712138E4105150E915093AB862ECECFB6F1F33DDB8FB4F663ECD1F4C46A1ED372CCD5BCC34FE4B9C50375B554EB40A5758CC28934CB529C6CADB5F76971517544198C7BA7B13F07715F11BE14FE8B1597CEC3A4E0E92A6216145728129FDC12A1F307F3022A824A64E76427304BA67317208AAAA2AAA96A5C37D7E813DAF7D9B3B11FA59BB1ED21AA346F68F91649AB74ED122A28EA7EB14AE3E8A8AE4B2AA805A72A5B5288525408502236F2F337617B67DBEFE98BB4B9A6066E4B8E9D2319394995365CB9BC0844A2BE1AA65905D245F7EB16DED7F6270B9D60A4CD46310A5997549E162E03D4AA800FCC7527D943E861D25ECD1DAA50F6E7DB776CD926A3CB3479555E59973AD515021A0868A544ADAAA01E3E04AA540C102379C5CBB6BFD55F6E3E20E538BECEE0F2BC623179924CA0A2998C94AA8B042900170A34E434022A1D98EC9E0BB278A13D7390A757168EE1CE84F202BCC563CF9FA747E900D37ED2FAAF48F62BD926629A8D1FD9B0ABA2D52E53387B9CFF00BE6DAFA88412477628D6D7FE52941405C441C7A5FF00A01F80398E588ED467F9E15C939A2113128992AA85A9331F849A9752812D67AEB087C4DEDA77B2F0F2F0EA2C804712554228D4D080EF7FB9EDDFFE1ECEDF34C6A4D2FDA67B3F6BAA9A5FE1540D658D51A730AF45335C351DF3CE06D0F389063651493245C1C79FBFAD5F8659CF677B468CD7012A6CD97227CD5F14B9449214A0CFC214751BB5A8224BE14F6865E2E4CE958A57CAB486E2340C0BD0DCE8FCEB5BB37D3F5DA4E8BD03A1FB2AF67DECD1CA0A9CA73A733E5E6AD50660CB8CD3943E8AB68AD2D2D6992B24A4820CDE4E247FA39EC5E6FDB0C6E7B3730C24C4CBC6A30C897DE4AF993C09525552028B9706CD6899ED6E7185CB1483865A400A51E20407ABBB3DB414B02EC0D6F2FA0EFB42D17DB1FB2AEADF66DD739965CCE55A0AA327AA0335AF6025C5D4E647304708A97533C2B6D2004930400231CD7FADBF81D8BEC8E6B968C2C99C3FD51538CC99264CC3C265F090FC009ABD1FA0687BD91ED29C74A99356B0132785454542805682DA1F0AF28E96FF00E221F684C973ED77D94762FA3FEAB5D93F67F4999B59A2B2ECC1B5538EF6959728F8D34EB2DAFC4D88DE3CAE07A6FF00F875FC20FF004DC873AED2E3662C4C9F252B9726721495BC94AD2C38AAE586973C8423DB1EDE6599C4B565AF2D7DDA4A388917218BF3A6D7E51487B197D12992FB6E7B2EE8CED8727ED3F2DD13AFB33399A33AA652E99CAB4269AB174B47C295D534B47F25008E048277B9BE257E2DFF005739D7C30ED563B23C4F646766982953C4B933940A92A4053121E52DA9CEC361150EC9F6224625189C6E16600A53A884B50FCC6CFCAAF4F08F793E8ECF653CCBE8CDD13DA8D576BFDBE516B1D33995031534197E67534ECAA8450B4FB8B6DA53D5AEB87EB0A2010902D682231E11F8FF00DA8C5FF513DA8ECE4FC83239D95AE54EFF007C4A90B481DE197FB9425201E1FF00D4760D1D0BB35DA49BD97938B918C2552D614900AAECE0D34636B5C3968F907FA447B67D33ED09ED73DADF6A7A792C3391E695F46C65686214CFFF000F42A91E712520254165B2AB822FB99BFD73FE9B324CC3B0BD8AECD649889F3711330F2815CC585024CC29531724D1DB661E5E67F89599E1F33CD66E230C94A553564A929E1726ACC40F4E82F1D247948AD71B69A3C6EBB574490B1002385F6C12784DC01733F7463DB1DB544EC6F617310924A95825B0B9FF00A65869AB59F7BB98AAE538632E7C998CCC41219C82FCF4FE35B7DDBFB336A1D3793FD1114D91661A9B2B7EAA9F4B66FC544BAEA565F42DC2F2908E00F070CAA364C9DF1F9D5C776733199FD434B9630338056684F7E25CC2857CFC553C2C963401EEF736F5164F99A11D9F989EF83995C25259C3EC77607E952F1F0AF98B15CFD56A6AFF00A9341273DCDFBA685437E20732A80DA80998363E933338FBBF869388C2FC36C361895059CBD824920FFD216075B53D77F336793258CFD2B04F0F7C4F78C4DD428C2F6F1E8F1F709F468EA4A2C9BE879C99BCD33DCB28F323A7758A2AB2A76B690D4203AED6A590A429D0E7892411E1988B63E137C46C8B198EFEA09787999662168566329489E25CD32CB14A89E2E129A1A5CB178F5A6419AA47645C4D48E1C3906A1CFCAC19CB8EA3A5EFF1079D56A9DD479CD0B47EA85AD47A8D65EB2D2B0EE6956B491C8820C8B9B75B8C7DEAF8272BFD27B2F95E166829030D253C268DFEDA685EF6B0E81AB1E46CEA60C566F3E61629338B1707FBC8AD6951E62102EA1F436DB6FD4FD6384A8254121300A8EE2D3F0F48E7D23B4B365994549775A48A6C03DDA9B787268C6712929C2A1807E116704061E2E6A3EF1922AA23C441F5F9441DA3DF883EC8A0F14F51258177DAF4B57EDB45630D85EF44C0D41A5FC5B6BF4DA17B3540F3E7613EFB1B0FD8DED1218FC4254B2904120D791D1FAFF88613F0641248D5B6BBF4D7EEDBC39B15299BDCFADE00F3BF31FBBE23FBDA0A38EB4F0F188E9987242810054736D4B915F1F5AC3E51D5004CAA768E7CEF73B794DB96136F5FF10C26E16F4E7EFCFAEE445EF9FBCA495C99916BEDE5E63E7317C37CB7BB3C3F3247450F3F06F5B450309C248A8D4B1D694F37766F4200A9B337AF24C133CF7822DCE08F95F6C5816B961988B5C355B5F0B922EFCA2E99690C12EC59AB4FE2B7A45739CBA47149067CED07A12768E7E98CA172C9F988FBEA6DCF98B45CB0286006B4B80C1AF77AFA6F102A9AAA8688729DC534B6DC43BDEA55C2B49696958008330A88B13D3683880ED276670B9ECB4A804AF8056D4B6A3A6BE4F13D265204D42D49E24B1052752A70E79EB6E5AC7B09EC69DBAD16A3C859CB7357D0E56E4ED064513AE052AA82C14990A3C809BA4FE5E61F899D9E565A0FE9A590563E65A41E24F0331A5473AD87384330C0CD93869E94A14B0524A5816AA5C5F50E0121CFAC4E3DA13D9FA83B45A1ACED1744308A4CC5092EE7B97B0907838070B0520402560711EED26F20CEC28DD8CED5E272BCC70D81C629687584CA98A27FDC018977A066662C4EED1C7B0699E8C7AC4D744B42CB248019D4E59D89FC1A691E516A5C933664E654556DADA76994A4292E24B6B3C2483E15709361331B796FECA9D9AE5F99F64B152578A97DE4CC22AEA492FC0A162AABB8FF00069D070D353331B8128F9F8549B312038BDDBEB406B1F7FF00F40754328FA39FB1E678871B6ACFC2E08327F8A3BB7C7AC74DF1F9ABFEA9B013301F14BB412E5874FEA125019A85C92799BF851C47D21F84F8633F219135350258141B74A6F6B5CD047B573C37170AEBCA3D3CCFCA31E7054C50E1FF006EA6F5B3791DFD6E0C752958644A4AD2A50254F7D3933DDEB5A53484756DFF0029464057862FB99E40C72BFB879E22F1F899A0CA4A65120104B5AF6B3C30384470CD26684EB56B56BA3DB4DB9C7997ED4C8A65FB4C7B3BBAA092ED2BD9F84A8C594B6100F39F90C769EC5E38232AC64B5A7878E5A68D664976D79B6FAD9F85F6B7088999F61BBB980844D1516FDC0E84801C7F916F48A8549FA95229C215C4C35179FF00CB06C07E679FBF9ACE5CFF00D6E238657CA16A6A8DCE9E57E7BD3B9E1729958CC0615256DC32D249A97A07EB60FD042D4BD07812D9E13304DA39449E9E71CE2708CC54D0A41E0B9AD411F57DABA9A56F0F5394C8C3C99893307EDE4052BB8FA9FBC43B5AF0AB4EE774EA8E0A8C9F354B8B240E0FF24FED7E60F97BF0E25619789CCB2DF91E5A27202C805EAB481CBAF4E91CF73DFD3C8CAB3596710973297C2E039649E7F47FB47C9CFF0087F4FE94CDB52E62C96AB6A579C664B21C50250AFAF3E47DB2779DA01FBB1F53FE18646064797CBE220CD92876154FCA08A354D5A9F48F8F1F144E2FFF00B438D54B96B52062165C02D45162FA8F1D6BBC55DAEB5E546669750ED48629297C3DD214059560070C1E42605A2F6DFB5C8ECE1C0C852E5A4A8CC0E0849B8D7CEB7F38E479AE2B1AA5E1C194B0C468695076E5E3A87B50F9EEB658CB5CCB43D14CF1E24BA560A92A6D457224CCF1446DF0DE7FB23D98563D73D18A90485FCB504382FA16AF879B45D329CC2711216A7E29401B331706FEFED1006BB78ED1F2C6574547AF330A6CA2950B67EA816EA92A4BA14DF081DE6C27A72F7E2771DF05B2D44F9589978290A54D515294654B7D2E4A5DEA48E62D48E98BF88D98E1B06A9285CD010801202D4D404559BCB4D0475D352EA97DD5BA0E60E5754BCE975E754A502B2B595192499DC9373EA39F77EC7F6364E4B82EEE5C84A4290DFB40B03A369CF5AEA1B926699EE63DA1C5099890B3C0B3C04B9D5F4B5BEC08D23B4DDA8E75A5EB5CACD3B995569FCD69D1097A95E741A80B4C2B88B6B483C0098924FA1DE9FDA8F85F27B4B8BEE276192B97316428AA58500E402E0A483726FF0066BE7663B5B98E46B9264159092976590CC41D19C035F28856A2ED63567696ED2D0EB3D4B98666CE9F53C72FFACBEFAD3FE6BC6F405B847BC9DE23A62FDD8EF82992F6170FDF60B0B25733149056A42128293A12007353AD9A8D171EDEF6EF34CEF05874954C502901438891A0E7737D2FA562BCA9D40FE459A65998E4B5AEB2F30E38B62A10E2C2DA5248B8F103722C7A581B62E0AEC761F1384C56131081313884291C2A0084F102050D3534A0D2D669D809F332E13B1330702D4CA36492589E553FCD8D1F75576A9ABBB412A6B5A6ADCC337A4A06826969EA6A1F5A112DC0094A9C2081C291EEF2C503B27F0872FEC763B19330F879481984C75704A4A48724D4015FDCF5D9F58B2E69DB1C7E2E6A10A2B28413C2EA2CD57AB9E60DB4D2B0DBA7FB70ED3322D34AD3997EB0CCA8B4E5225F65BCBDA7DD0D38D3E56140A43804428D883BE2C78DF81D90E3B33C3E3A661244DC4718985664A38A9C2AAAAA46C6B5A42A736C5E2E5A13DF2D0966238942A7714A5ED7E45E29276B87091C6E77AEBEB74D4F12B88B8E3A5C2B3B1278953EFDE71DA26E5B2B2CCA1196CA940C8549324200040053C26C0EEF42F6B34426264CD97884CD1338940951AB12407605FEEDBF3B353DAF76A54BA75CD08D6B3CD1DD38FB62687EB6F25969B47F34A0254F0042CC8B00224918F3F49FE9D322476865F69132E4CB9C7102795F7238828A8170581A1B6BA691D4FB239EE2F31C0CEC2E227AD12D29290952CB0670CEFD0FA91AC55D97E635EE553D9A503D5394D530E05A2B29EA9D69D6561478969536B428971424C2A6E649C768EDDFC3FC0F6970795E5D8C28C4A70C9084A972D2414B2284104580F3DE29598CDC564B9909D869CB525530FC892415392FF303A383E1B34596D7B5EF6FDA7285DC928BB50CF5BA1E014ED527D62A57DE34B942C77A5E253C2826FCEFEEE57DA2FE9DFB213A660572B29C112E0AD430F29C905372106B4D4E84C751C176C33395839404C5AFE573F39245050172FD473888E53DBA7695A1AAB37CD74AEBECEB2CCE75496959C569ABAAAA55616E40E24ADF3C3C016A48BCEDE98B2627E09F63F0323087FD1B09356809242A44B64D059D3BF4AF844BE13B7D987E8F1038E602A490071177A8FAE9A6A6B117D41A9EAB52D43F9CEAB7DCCFAAAAF8559966AF3CA4D4D5A80F0124953814D936214622C462E384C8F2DC9300A9383C049932B807CA89684866A8094A40028C4806BEBCCC769B34399098274D333BDE2EEBE6660A7AA8D2D5AF41A448342FB40769FD9636F27B25D5B9DE421B5346980CC6B1E69238A5CFE53CFF00040BC023CAD8A64FF86BD95ED9A7128C7E45835CC50204C99265A8B977214A43F3A9BD6BAF4CC4FC40C68C3C896B9EB432085312402C1A81C1D9EDF7996BAF6BEF6A7ED1A84651AC7B64CDEA74F3C80D869B0B614C881C485165D4B8E0717E12A3B5ED6C73EC37F4A1D99C2667FAC9383C2B77817C2244B00317350351E075BC452BB7388C4A529257C697A959215B720DA0D49A5E3AE55D4AFB4A7731ABAB71DA9E24ADBAA71D53EE38A599597256B52CAF97193C3336838F487677B3780EC9E5DFA6CBB0C894020256109E00AE1D580F17A8AD1ED10B8ACCE6664E272B881A1048B68C6A030E5666ABC4B3477693AB3B3DAF567DA1752D6696CF5F6C8AF4D1ADD6FBEE0414B454A42DB49F092773B9F29A4769BE1764BF12153139A61249AB1EF65A5770C28A05F97D350FB25CEA764AA3DCAC94A8FCA453AFD5BD2D0CFA9BB4AD6DDA356B59AF68F9F57EA4CC925EFE1AE555438A2C820A5CE02A717C05405CDA6DE470C3B29F0B724F845881FE998594B18958E2084252031352C1A8ED4E82D0BE79DA4C56629497514268B3C4494BB0B7D5BC636E94ED33B4DECE686BDBECFF0055E63A4559CB8D2B325D13EE95560A75CB417DDB8829E00624F5B7385BE27FC25CA3E24A7073F192A415243A44C968594BB1A150A3F215F5898ECFF693FD3B018A40593DE2181763622CFBF9DA36679A9F3ED6F9A576A0D5B9C556A5CD4B6C8CC6A6B2A1C2B57F2C210525C7167ECD884CF520EF8DBB15F09B03D85C3AB09829E89689C9632E5CB084B005D82193635A728A5CA5E2F1B33118C33152C05A9481C4FC45CB6B46A3D35B6D38ECDBDA27B6CEC7D8699ECA35DE67A5B2A60AD4DD0B0FBAED3A5C512AB32A7782EE19FB20199E6629DDB7F813D98ED8AD788C5E59869D393C44CC5CA4151513772924D75BD2B6ADFBB11F11B1B904D9B82C4A55312BF941366B5D8BB8A7A5ECE7AE7DACBB7CED8A94E51DADF69B9D6A1FE2922A285A7EA32E4308A732DA4AE95E42561D4813D3AC99315D88FE99FB33839A56BCB70C9EE8828224202878B39F7766893ED0F6867E67C5364932CADC800D01FF0026E47211D79A9CCF2D06BA99346E51B34FC011C6F2EA14E71FDA59714789449F11BA8DE099938F42E1BE1865F95E1E5CC91C3DDCA1F227858D00A017A352C34B4727C7E0B187172A6AA615AE693C40D804B6B6FB0D8986AA253ED24D45112A6DC50214A3050526410150A9E7D248F73AC4ABBFCBB1197CC4912D52D52FA8208B1D34F037AC4FC932A470778A4A66242788022B6D8E9D5ECC77B799EDC7B60469F6F43653AE7356B260DAD2BCA9350F374FDD9F1B8982F25B3226C419F2DB1E6FC2FC0CC8979F9CE152B0FDF77E66059948E3078B8BF71F9BE96B35AED83CEA52705350270AA18004D4D59C3DBD8058456B4E8A377EB05552B156B5713882B594A9C995AA4909F12A547D63963B2E7787949C261B2B92014A502529A80064A45052C00D3A544727CCF118B56350B12C2A49987E7A1FEED989A9B5ACFCA2DCCA3B77ED9748E937F4A69BED0732CB34CB882CA7256DC7154E50E921C484F7A1290A2A26C800CFC38FE7FF000772AFF51C366430B865CF52F8CCDEE659980B823E729E22D472F5B728EB595670A95932E5A9652F29B85C80696634F1F48A997589A4A751CCFF00CC562D4E3CB741BADC7945C52894F52B24FBCC0DF1D672D9672AC36170E80C1090030D801BEDD1E968E42A44CC4663326C90425535CA49B7CC6C4DDDA837A5A120AF55434C9EE032DA4ABBB571F115C9BCF3116B9E7BF9CB6653D73A5A454FCA34DC375F3E9511379980BC3CB48A900B80795F402D460C4794642A215008B7E5BEC3DE01EBB8C3DECDA3B9918A333E5252E09D686C2C746B5ED588CC04B4852828555AD2BCACC5B9F95995B5504CC72E5B7E1F84F9EE3103DE4C5E2A6853F0F116F07E41FECFD0C6B98E1857853C54E54F2F7CAD0EAC54A85E6E39C8B18F78F4FD92E3D6212661D4011C377E5FC74D1DC5EB0EAC55A81B2A662DCA39FA4DF7F8E1C4454D90B0E18815F467BD7CBD63B31A83FF0030F9729F3FDF5C5772ACAB109E1FF714DD5EC0023C58BB56F1C87064FCBCF5237BD9FDF8454B9AEFFF00501BFE1FBF23B62EF2329594FEF248BF27D37D7F2748BBE560F9DFC3C0D9B56AD9A2B8CE261572771BF33B7A4795B9DA30DB13964C40A2D887A8D46947F7CF5BC6096A6000B063CECDA06EB5F1115F660B2961D00F8942537BC03B73FC7737387196CA54942C2D7C65ACE76B6B4BDEE1E2D3804898A4BA4900B7A87B3378FD1C44F3B1CD74E7669AB726CED2F2D2AAEA80D5537C6A094A0A92D789174FD9513F64091B49C72EEDC61246213338A5853F1338043814A1D4B57A88BAAA4495E0D49525259140D770E5F7B8B92F5762447BBBD9F6BC0E06B32CAEB52BCA6AE9D872A11C21E6EA389A056DC2B885D4549909244CEE31E5DCEF2C4712FE4E15851E152404941770411B30B50EF78F3E76CA58C3E216A909EED890C000FC8351CFE34AC535ED49D82A35A6529ED5740E4E9A7AB6997D59BE9DA75A54A76525A0F155B7014F42516DBA623B2ACF335C3ABFD3B178F9AA2974A165D299A935E16FDA3803246F7DE1976471844EFF0076BF3A0A5CD5241AF9FDEB5871F656FA6A3B60F628EC4B24EC374A766CF6754BA42A2B02AA5CCC9144A52AB6B5750B4F74EB6543854A5241BC81320638FF006E3FA61CB3E296738DCFCCBE2C6E2780A94093FB53C3B905C72A0F38F72F60BE2CCBECC65430D310172C20339B33B3537F6E4C770B49FF00E240F69CD7DA86974E649D911454BAF52A12DA73AA5592952925C20A99E4992795AFE7C5F34FE89A46094B64148960924836A126FE941B6F0DF3FF008FABC3A138B4A949134AC896096649203902869B56A23D6CCB7E946EDBB32C8727CCF30D00AA3AB553A5754C8CCD874B8A7109264049038493CAF18E793FFA5BCBA54E992C4E49282C42914046C7463A87A5F78E6B9B7F54D8891296944A293C24385549B6DADC0E61A299ED17DB175FEB9D65A375E55E96FF0039A3D756B651F5E689FF003894A1710009001BC19E587184FE9EB0F830A40C425282188018116FF9023E9CE38ECEFEA5313331C27AE5296EB772A22C6E28CC5B4DA2E36BE93BED716BA5A2CB745B8E14252DA17F5C6E13090904CB7113CE4EFE7784CDBE03E4B800A5290272E6D4B121D89ADEB4F623B1645FD5CCC95874CB9A42025200E2581A731FE0B062D13CFF00F78C76CB45979ACCD74D251E00A4B66B2941822C2C276B0B6D1B6C6051F02B01895BE1F0EA4826CEA557A380F5F3B3E8669FD59AA705844D0285C85E8D4B6BF93BD693CFFE94CED32B5EAACB2A749A99A3A9A6ABA45BBF5D6D40F7ECB8D6E102078B91F23D7177C87FA70913264B5AE5174A90B49E134620EAEF51B8D2D58E4B9E7F5278EC6098133490A0A0C0D3E67BD18B83B1AED1E5CE7FAD2B97FC56A2B1A5533B9AD53F54A417F8E3BC79C7AD06DF6EFF00083B63DA3D83EC09CAA4C994A5525A5090E9A06006A4BF3D8EB68E099DFC44958F9CB9B3308959592492D5737A03D6DBC5199DEB069D0950A8E2E2E20B4F111B5AE49826DCF9FC477AC16449290854B414A406FDB5B3863E477BC404ACD70D9B14BE1C21ACFA7FEDD2CF435F18A7B506A469C04A5C22247085189322C41E66D63E51B62D797E4D230DF34B9684ACB5001E069B0FA18939494380848036B742FA3015D5AF58A8F33CE0155DC8E22A27C5B983B8B4FA1E67CA716C912A67CA9324CCE166A3F326C69E874261F224226065241069BD01E777B58E910BCC3356C93E3937BF15ED6E93D39CFB8E27646267A180C228B5D81B55A8DE7CE159396C90414CA1D5A8DCE84EBD1BC221B9A66685442828F8A4CC98F599300733D05AF13382C50278A7617BB240624786C0914DE9A4484AC24B42920A1D542CCDCF46A90DCF4AD6227515C8415149009DC8B4EFE9CC7BFE18B1C8C52267082C4358DACFAB8B9DBC6257825CD480B47101448B81666A7A8E9BC30D4D625704A8929B013D77E7E5D2FF002C4B4AC1A26BA811F3352D517634FAB57C21F485A657CA80C9147FDA080395EA1BC690C4FD741549227A137378DBF641F5C3A392CA9DC2ABA81B9F114F7AEF1212D32D4C4A58D093AF23F7F5D6120A90A0AB9BC5A48B74236F3103F1C18D9A8CA25A4A93C6E0806AFA3E9AE8FB43D4CA3352D2DC70D9BAD4D7670046A55401D2D7F4F5B1B8F761B4BCF70D3C1E342411404B1AD742F4EBFCC2FF00A25CCA4C25540CC0D35AF263E35D4437D655B29E1529E5A0DEE0124817E578063CB68E85EA71689A03106DC2011EF53EB6687B8595330A0894B28B384D1DFF003E957B086F73336F84B6CD42D40FF470290099EB11BF3369EBB61BCCC4E2CA9908330A59A9E9507969B0787ABC389ACA9ACB2352C589A8343420DBEE61B8D0BB592EAA95252824951793C4679804D8EFCBD712381C4255FF00F50099007ED330815DEBF9D4522470D3E5C84B2C150B003A369CBFC5C9C0AE812420D32BBC1027894B00C5E3700C748BFAE36C766794CB0D3319294002C389346E60E85BF9B4384E3E5A50A12D290821D55677AEAD7A873A36E63356599AD78032ECA6AF306D32169650F2BBBE232094212ADFCC72DF618A466BDAACAA43B4F94B4A6FF324003667D8DBEACF11E3159782B5AD6896AD0B713F27D08A0D2ADE12BD3BD9B6BDCF9E4D3657A5F365B8B20049A1A94A2FB4AD6C817E4662FBF2C52E6FC4CC9302A509788912D44D077881BFFDCF47A8A6CCF0CE766523898AF89239368F5F3B5B5EB7F647EC4FED1BA9592EE5FD9E2EB1901254A7F33A7A5EEC2EE0F0BAA4933D22C79E29B9EFF51585C866265CB2311DE71550AE266009A876D9F5BF3868ACD70284ACCCC426514D5296B96347A7D757B18B5322FA373B79CD78467196B7908541505D6D255F08F4EF8EDE5EEC5626FF0054D85980032542EE0A54DE3F2F56B5E1827B4985492EA0A4BE8A29FCB03FE22CCA6FA2AF523A38F3DD7AD50A94077484D132E1FF00571290E72F3E57E830D07F536B72AC1E14CC209E26251C3CEA9AE85EC393B05876B30E1242425059A8429DB91D5EDA58D61DE9FE8AE0820ABB4B440DBFF86A26FBC78EDB9BC09C34C57F5238FC494AA6E5A66105C1E3A83E29E42B082FB53289FDE189DFF173AB46EAAFA2DA9C371FFED6114EA13C08394A55DE1F52E7863AF5E76C43E3BFA94CD019694E0A64B4D4169855C351A70F2AF4DCD7795DA9C3A1DD6140DC7133F5B575AFA6B5FE75F45E6BC4073FC3FAADACE42BEC90D314A1C8DA429C1E42F204DB78C2F23FA93C50E156225AC002EE49F06497F4F4787D23B5387B258053BFCD4F0F3B33EDCE9ED4BF4777B43E996C2E9B224D734EF19EF1BAEA425B0904C96D2B24F15E39C99F2C5CF25FEA37018C5894A05C517C4952589E7C3A837DA8EC224A467B85042C043F25025F5737DF5703778EAA6B6EC6FB44D0150B6F55E4398875054389AA479C4A00B9FE6B2DA926D17E288E918EA7967C70CB25A4292B94870EAF9C135B386241DEB534262770DDA3953662509295710600A9AA2B525BC45FC1E2AA5BE5B5C3CDAC380C354EEB65B24C90788AC03311B89DC62DD84F8AB96E6B294A18847180591C4002FA00E2B436E578773D5331E4F0A824A59CA485B3EC5DFC34D8E9A066C95BA9A761BE3A8BCD37D8481B9872C36BC49F5C472BB55FEA738CA968E1492DC4CDADDC063BDCBFAC269C9E7A921E62B84F11EF1C93CA8FAD9CF8467515AD28B694B85156DF107D909527B90A8E1874001CE213B1F0EC45AEE8E4F3023BE91892B2594521A85BD59FCA1C232AC4489615C4BE136507636A91D2F4D6D5847DF892413277B9927CCC74EBD7094B54E0A6C42485248F995AB6CFD3CF5A5779721082954C4F1105C3D811C9A8FE7E158E7EB12209558D81262DCFF2FC3125326A26A50090B2072F201B4FAF487188C41527810A5252CCC090C3D3CBF980BE15F68957A927EF18D5D2400500B6E7F888D12824B82C6B6045FC63732F4C80600B6FB03BC08B72DB029408AA016B57FC5BDB465482AA1538B5BAE9D7DD21636F264C44DA4733F2B72F5B7963744E280C9A0B30342D4AB01E3184CAE0FDA5B5760EF1BFBF09E1BEF78FD8936EB1F2B37514051213525F66A79746D21708E200AABB121DFC1E961F6852DD4A6D06D17DE4738FBBCE7973C63BCE41C73F6D4FAC379B2900314860FB33574BEB6878CBEA412B24DAD37F75B616E971CF960331F4F5FE222E749410484802A6C36FADEAD7F08EDB6A0040701045BF3C31CB7304BA7FDB2FA579BFA3F378F3BE0813C15616661576D74F22D78A97340544F0DE27693D3A6DF2C5AA5E6A5293C2082756FF001A37BAC5E72C07C68E3A83CC7DE2B8CE5278556379E477822FEFF909279989C7672B03F6B9666DFA9D41BEDE16B9E0DE83D1EE29AE971E7B08AC734596EA29D441E0495950E5E11B73DF973F7C028E5D98AA695F10201DFC81D18EF4A79C5D3286A92C188B8DEFCADA9E95B98655D7AD550FD7107BA2A40A640994A93092A02D1E200ED1067152ED203384CB9A1E571B51E2EC84F1C9E009A81F317A105F6E434B691EA87B17F6AD539AE96AED10F362B73FA1EE0D0075F08516D6B538EAC15595DD340280327C3000918E059E610A662D4B5129413C619DCA8B245011AD0ED1C7FB6F9605A953254BFF006A603C079A5B8DC1A8A83B69B47A5DA2B519C9DD65D72BCE6B475414D66C1D6781B6A41406FB95CA48BA91294C18E2DAE68F98658713254152FBB5A6B2A60357049D1B50E4127504B472CC0A97976238D880F50E5AFE43C3C63A43EDADECD20297DAAF674B41A0AF4AAA33BC9A9A9D24502909096C95004AC3CAE25C25238660ED8E87F0A73F4489F3F29CD4044F96129C34F5B0FD55092364F7618126A6E23AEE4D9C4A9D2901DDD8104FEDDDC1F3371E05A3ABFEC4344731EDD326555708144E540A9429B0A054195252786265244D872F5C4C7C40C6CA380C47E9CA44DA061C24873A91B8A3BF8C3BED14AC3FE88CE511C2A4121D80703CEB4B5483A08FA26A3AE6695960B550AA86D68285A12DA95C240E14400098D87B8EDB63CB39B058E352A50410494A9C55EA4FD7634AEB1E54CFB339471CB94140A7BC29E170D73B694F26DC9892643A5DDAAA866BAB6A0B742B2E29E6DC470020FD910A20F316F973C73CC51C4AD6A329454F4F94BB7BAD4EDA5A3599230DFA633BE57E1A3B6DAEDD75AECF120CCF55E95D2A834B42DB4ED50078DDE107855CB84949111CC1E9230861F23CC33450E2428F0961720FF8F2D4F3A34F993B153552E44D52425458A7C7A7954DF48A0F57F6A4CD5171BA8AD524F8821B4A484EFB5845AC49881BF91E89D9FEC7CD94A4999873421DC3BDA963BF8C38919762D5533D570EE4DA806B715A39AE9143E79ACEA56C3ECAEB514A1EF152AFBB42CAF80F12BA14C6D7371EB8EC99476792908030BC4A02AC198598EFA6BD280C4FE172013402B9D5531A834AB5A87DD0C75E750EBACD16FD7BF515EAA86698B68427842678FC2600D87BA062EB23245CA4251264103CD893ADA874E4EE3533527B2D216C14B0A70EE69B1621EBE3D62AACFB53BA1C4968948209510A241E200FBB7F2F7462DD90F673118824CE2A961E9C5B6B41AD830E6FC9599934BCBD8CA214FB537A0BE962DB83CABECC351BAE182BEA6EAF5226E2C0F95E2D8BE60FB3699443CCE2F02C7C2DBFF0D573250490C1B42CE6EFD6C4D76A5E910DADCDD6E470B920C830AE978DEC7E43C862DB84CBE54A041097A0A8BDB7BFE7C62730F24380C5A95B3EE3DF5D5E2235F98BE6DC6522F2662C3CB909F3E76224E26E461E426A780780E5B0D89AFD627E4CB40482000534059DABB6E74F1DC4465DCC9C3FD44949224107E22FBCED8713B2CC3E350C3853B148A55B40D6B757EB1208C009A54501ADA6CCD5FC4335557B841324037BEDF3888E9CE7E1ACAECDA10070CD34B86ADFABF95442A32E54B7E21A8615DAB6229B5872AD5B055ADC2B009514C4917DE46F7BDCF5C494ACBE6618057116A358380CE19E8D4E96A5A164604B3F091ADAA6BB5ADE81EB085FA9B9922FBCD88E563BC8B79FBB0E06231086F914AF3A6BB73FC3DE1C0C3B1143535F0A0E7A1A68C79B205D5A927C2241BDCC7E22F63373870AC2E1B31923F56B4208144AD41243BEAA21E9A535DDE24B0613294788B6940ECDAF20CDF6D0C6C69398559029E92A1F9B70B2D38EA8F580DA56A3E71F28C44623B3F93212B51C74892054ABBE4D80D7E70283916D5E1D4CC5C8428A52A4BB56C35A5F517FB1898E9FECEF59EA4714C659A77347AA8A929612ED154B485294760B71909BDAE2C23CED48CE3B4390E43C6A939B61A7AA557804D43BEA080B27CD9EACE2194ECCA4CB524AD6025479114205081F9D83DE3B1FA33D823DA6B5829AA8A8D24DE5F93B852A354E56D105A5B55C9EED4B42E40E5636E471C7B35FEA7728C8B10A9070DFA8992CB06248537309203B1673E7584F159E6065CB4893344C24328BB70B36F42FD37D03C76AB4B7D18342E37DE6AAED03F83D43010A7E8D1446A038A31C480B69C8B796F6EA46396F6CBFA9CC776904B9595E58A9281C41644E32D9EA09701EDC9BC62B38EED62A505044C03621890297BBEBF715A76234B7B0C7B3A69A6D0D66D4BFE2CAB4402B57D6A8F8C88BD94A001E7726FF001E653FE26F697304F0A27CDC0F15E6199DE316BB13FE69688299DAB985FBC99C6F70297E8D5D5A8DCDE2F1D37D897635A24B8E696ECC6932E53DC25C79DAD35A1E0DC701087D2BE1E1E805EF388239FF006967A97FA9CF66E212A6F9423848FF00C4DCE9CB486533B461638904855C7CDE7AE8DD7D4C58ADE6EBCB1B0C65596E5542DA4404A72AA25280116E3EE38BD6FD245F1018ACAE7E366F7B3313882B26FDF4C0097B9653005C0B5F5BB207B4734D02CD5C1D7E9D46A2352B35CCEA7C4FAD3FE90C3696072990D848239C11E58565E117824A93889A663B7EF256D5A312FB8B7E62BF9AE753D750B21C9700967028F5D2A77F368D2A7EA957E37D20C41EF17CB7E7EB6EBBE1C24E1D54E140F2FC52FE3E110A3339E47EF556ACE58BFB0EF189A779D952DE748039B8B813D25437F9ED6C3D96990406425B56001E868EF7E9A5A31FEA9882ED315E2F4F33F6869A969D6C9875C302DFCC549173D7D3E7E787C89120904048D9C0DABB7BF53FD4E79A7117143534E8FC9FD3AC3154BC040A975D41FE8BAC91783B137E5EB1698385D381C2CCAA9085686836E4FBFD615959A620280E3350C2A59F5D77E5A5EB0D8E54BE3FF97CC9F644DBFE27431CFEE9C67FD270CA344A48D030B9F3FE6FC83E4669884D96A0372496BF3FF3053E619E33C6E0CE9C5017871B2B00F48595020F39C2BFE888A04A824AA80A5203D2EE08E5F6112387CE31003898ADB5BDADEBD6DAC6AADD4A9CDA9D596EA2C872ECFE81D05B794ED1D2B2BE056F0BEE4AE483BA4838513D9854A2A5C9C64C96B50A1E252803D38A97B35EB1252F3EC48293DE2C503976A35598B8F27A523AFBDA07B24FB3376A34AE53D16408D199ED5059773D6DDA9A914AEAEE1429414B6A9262DB74DB1B6165F68F245CCC4A272F1C5052A912BBCEEC283BA83BD29A11BD8C5FFB2DDAD9786501899C4059657117E837EB56D63CC6EDAFD81FB44EC9456661A5595768FA71216EA33AA608A27A9DB00A84D224A9E547D93693C338EE1D90F89E8C5A256071F2460F14964AC2D4286CE16400697A86A08EC9957697018A530527829C21C11CDDBCDBA523CF9AA7336A5AEAACBF36A3768DDA359406DE694D380DC292AE24851E1B8F10EB78C77CC9BB43230C12B13C6202C0243BD1AD42DE3E517644FC3622524A4A4F10B023A585CF854D79469EFD179880379B7A13C8FF00B6F8B81C761339960238252D983303B3E84B9EB4BC4163B0E2BC15B503F5BB36BE1A93A6C53E821245C1D8F5B5C5BA1DE074DB9C4FE8E76114F31F8093C24B904540D0B7E5F788C1294160A9F57A31A386234D1A30EF93FB9FCB193300A91EBFC42BC0373E9F88DCD3DF6B87CB9FE630779CBD7F883806E7D3F10B1B789F23B1FC2D1F3FD70779CBD7F883BB1B98C9EA854A60FC083F1B5FF1E671A2E630AD01E62BD76FE6374C9777A0D1DDFEA3DEFA728A93C8DBEEF740DFAC1BE11131C5C3D039B5EC694D07DED09CD906AC016A74DF7776E7B0877A0AA502A8369111E51BDB73BF2F2C678EA694A372DF4AC45CD90E750350C0D3EA7C34BC77CF51E5EB71C5051932AF0404F3200046F7FDED8432B12183292C19EA090F570FD3D63CC9817E2041A0D2F4B963420877F2A4545A859772E085200A5EF42A54921F2E70FA4F0C6D1F9E2DF839586C43844C042400414B33DAE35B6DE517DCB9822C1880C7AF2F2ADEF152672FD528A8877BD1CFC011689E83CB7F5DB18C5E512149078D2C7567B9DDF5736FF371C194B25CF2DC8A91F7E6CF6B456F9A07090A75239806C67AEDB7A7A4DB7849B21182A022AEC436AF7B74FA1BC5C32F21201497E4C777E57AED5884D70001B08DE3901FEF73CA715FC7244E428F0D4824017A1B791F0A6D175C11331043162C1B660FE15F758977649AF33CECFF005EE459FE56FA99629EA52DD692B012A6DF5A5BF182608095288F7F4C735CE32B528F1000A49571029D85C93B35CF8436CD728958AC0E213351C5340FF60B1F95CFCD4A03AD76018C7BED91EAAA6CDB2ECB731A65A2A29336A661C438D11C3DE25B4174786D3DE133D31CEF1D8732C2A581F32497B549B7A5ECE2F1C073FCA15855AC80C1CB162373E9CDDDB58B9F24AFA4A9A07B25CDD947F0ACE98729EA9D7877A965250A42086D5C533C53E1162271CEB3ECDC6553A44E49289D20A8A568F96F7729BBF32D70221F2699311315FEE94A4104F83DABA1D1C6D1D4EEC5FD9A33FECFBDAC296AB4A65CEE69A1F3172B2A1CAD282C329EF2956BDD60D92E2C8104440DA6D50CE7E2262716854B2E02B84125454DC2AF3AFAED61161CFB389588CB061D5891DECA4A8218D55C40BDB6A7531EBE64793653A529EA5FACAA6DDAC078D146B4825854CC49242A77988B4EDB55B179C62335526570144920052AE5541E219ABAF8011E67CCB2B2BC72A709DC40ADEAE3FB9C6AE06A01BD05E23F9F6B5ACCE10F34BE1629590784A385B1C2245B8426F6F5117D8E25328CA6520FCB24952AA5C955FF00F559DFA56D589718713B0DDCF7CC4A48DB403536DF4E44B375A7546B1656FA99A373BC5D39525DF119BED249BF2F2B7588EB1D9EC9A58964AE5A52E450A406F120120FF8E6CB2CC84C99B316495125C5BA915A7BD6F1486A0D50A056A2A04DFA488E62DE9E98E8784C0E1E4814492350D635A90187E6AFBCCAF00A4B324834AB1F2E75714BB549D6A1CEF527D65B2B5BE5A53615C12779F2E5B01F0C5A72F12D3312132854B6E5AFD0EFBF898504AC4A0060AA52943F47AD87561147E6DAA1E53EB6CFF310A2249D94394DAF07998EBD063A265987C34D4874A5058559EBB917AE95A3738591331628EA013A69FE0DB6ADDA2279C67C9643243E58EF02B89253C7C7CA24ED1C84CE2CD84CB82D4B200570B70914636D285C1D4D1D856B12983953B140F1254403525C9E6C0D9F666D5E21D579AD1B92A7495F9DD03DC200F5F85A31312F2E5AC072CC5A877E96A6B5DF78969381525884B39A505EDCB4AF97278D556654C920D22E5641E23C53C3D01067AFDD322D8772B2F41238E604116255FCB8E571B077893958650E1E305AE094B38B0667FBD9C07BB1D43F5AB9716F828BCA2104C45C5AF7F41720F39C2BFA1C3BB1C5A470FF00DC001B33A8EDA8A57568934F0A40484B1FF95459C825E95BEA46E2195758B0A8A5A4A82B9873BB65D7E49D884A52A22FD3A6DCB0B7EBF23CA10AFD66632934FEF58727C4D39FF989EC0A4A05D04914248F3A9D43FF00910FB94697D5BAA1D45365390E6B5EEB842508FE1B54CA5449B7F30B010073927E57C41E3BE21766B02852A5E658770FF2F7A8A9E4EA716F52D0EE6E265CA6134A43E80A4DBA758BAF4EFB1DFB456A250FE13A25CA3A77F83BD79EAA6124A55B1097824A60192239DF96396E7DF1FB26CB57C266226F0F170942F8830AFF00692396B7B3C68730C1A038989516622CDCAA3AFE2B1DA1D19F45CEBECD908ADD65AA5BD3E084A9D6BB962A7867ED0FE5BA0DAE3913CA39F3BC6FF565270C95FE9307FA8526C97297BD1CA5B415BDBC5BCCCD7082C108AB12EEEF6A55B7B45FDA73E8DFEC8723528EA8D53FE27523861A148FD206787EDA7890BF1F19040998F8E395F68BFA9CCF7B41C49C3E5F3B0411FB4A2612EE4D7E516E6C0F48AC66FDA456087FF293434CBD02883E20FA5FC5A3B0DA47D9DFD9F340703990E8C65EAE6C828A879C79E0549FEA28792B499B7236C73B9BF127B639B288566B899725414152FE6143A3B83EC86357A64FED1CE9B314B5A895A8D482C36D282DB8BB98B869AA58A64A5A6724CB1B61B1C34E96F2EA442909800CA92C711311751B462117271D8854C9EAC7E20AA6D55C53A6904F205675A9A798863373EC4AC01C67CDEAE343EC55E1CD2FD4D4A78471B083601B529A17E894948827947DD66B338E516989EFC821CA839FFC8824FD81D4C47AF339EA720A8F16B51BB8DB9D3F98D468452294A538A25DDF8D5C5B7BEF37DBCF1A771FADA22477406A05075A026DEED0C311899F32E49376726DABD7C347784AA4324C828F23001E5D0CEFB637FF004DC423F602A6152E453CFED5D79B41326AA951E20BF58E50A4A66556E84CFC24DBF19F2C06662B0F4EE896E4F50C7C793EBD68ACA335C072491AEE082E599BC6B4DE352D6CDE4A63F7E53BFECE105E718B92DFFCBA88AB104F3DB978C39E09859A85AAC01E5A9D2DF88C5A75A4856C7C847E53E9FB8798654ECDD1C53126504EE2EE48B167F1F08CFE9153182FE63573D6B6EBBD9F68D6AA865332073E6246FE40DBE1F761FCBCA59BE634B6E7ECC7CE3539730D0B1D6FD286A7C18BBBDA105454B728BCEFB1E7EEBFC236E987B2F2D20B124333B936AF3D34D7CA31FE9ED7040D75F1753F46F65B9CA84110543C849FDC7CF0F51810CDC64B5F95DB5AF3DF58DBFD39C58685EDE05DFEA7470CF0D954A6D7C3E14922FF003E5B9005FF0008C3D9187E1242AA92E1C6C00BDEFF00687787CB9249A07D8536D7A8F2AD21B1E423FB42444FA5FA81B7E1BE1F22525CB38E8FE546F53F7872701C24961D0D7C3A569F567742B284F100A067748833CF9C7FBFCB798274B0148048AD0D08EB736D9B5E90230C906CCDEF7E9AF386CA85260CC08312204FC23CF7EB783862BCC71F2AA994A34B3134DEC76E9CEF0A09006AFC9BEEF7DA9E570DAF02D34F5624A5229C0E2480257C5B7BF6DA4C9F84BE5988C4E34844F4AA5F17ED7AD06F4A74FA968AEE7388C4E1969FD3F130AB87172294E67EB0647A9730CB4B9581487B2F78143CC54A50F36A6D52850E07828010790B1E9C94CDF03879C8017F22E59E274ABBB248A872962588F1B8BC4F7677B4F8EC3AD1C4B50346049DABD3C5AD1D6FEDE3D913B30EDD32BCC73ED0E8A7CA35EA9A5BCA2DB6509A87402A212DABBB641E104481E7CF09E4DDBACCB24C477338CC9B2414212A249090282DC44B6B5D23BF767BB5EA9C2524ACF0967756D70CCFA53C447833DA4765FAA3B34D4359A5B55D15465CED23EB4BAFB8857054A428A9252A808BA40FB24EE3D71EA2EC56732332972F153316996DC2A282B1F33B16151D08AD6B526BD6B059849C5042E5965AA9C1722D5AB3EF70D4E8212E555138D34C50345A6980A06655C449B9955CC993B9FBB1D4F1B9EC9C721126524112D207159DF9B68D6D77A51DE230E95A8AC91C440E2200A1B587859B972D1C6AEBF21F96233BD2400D416AFF0010DFB8FF00BFFF006FFF0054668708993F2FD318EF08B06F183B8FFBFF00F6FF00319F7C46CA23DDFA6326613704F53FC41DC7FDFF00FB7FFAA39EFF00A92A1F77EFD0E1099340D58ECEED7D1BCF997D614461C382EED7D1DDFAC6F6DEDA0CFA5BCFCC79C1C23DEDFE6F4E9CBD3C79C6B3648014F534F7D7C07850876A2A88E3BEF69FD8B6F06FD6D80CEAB1557A7BB36DAF945CF94CEC1A95F4377DEF4D758F7DB59FB27D26A443B5DA635EB4942C2968CBCD121244EC8EF56B493FDBFA63CBF947C4ECDA44D48C4E1A64A941899A492E05E806EDE7E11E55C0844BE22B0F41C20D385B67BF51D6F1D57D4FEC9BDAC65EA29A3C9139937E28A94D653A83813B28202D453D62FE9B01D3F2DF8BB8698024CD5255F2820829ABEE40BD6C7E916DCB6721012153122F471A8B73DB7A6978EB4EB7EC3FB48C982FEBDA7EAD8E1E204B2D29F802D6EE90A99E9F0E98B02FE26CA29ACE43B3B1983ABDC1FF000E368B860F1B87494954C0C0D9C397AFDC98EB8E75A4751D2A887B29CD94429524E5D569098EA7BA88EB3B615C2F6EB038E5813F152D1A00482DA9B97E9A79C5B7058CC3A923BB5252DFF70735A6AFA68CF4A59EB6CD686B698AC3F4952D116875871B20DADE2408DF9F9CED8B049CE32EC427E4C44B503A710D7C7D9F38BDE498A925B8949B860E0877EBEC79986BC1D70A9A69EEE8929936B292414C90445F698E5CC5A2B369D84282D310EC5CB86E46F4FA3F9C5ED69C2AF0EEA29720FCAC0D1B4A56D7E7AD48F5BBD897B40CC75664343D9C966A2B333D36427EB010B7439F5A73BC400A09527C298FEAEB2236E319EE3F012664D267A0281759E260C1D99CB5A9A39DEB1C4BB7B83C3C997DE808952E6F1F761C1248FDCE2E2A4DC748F63B4776415EFB8C661AB9C34F42D842A9A9140053F61C40F010A4418FB42083E58E19DA8CCB09984F54BC1ABBF525C4C20370F9D08D3D46B1C1262E5CA4620A2684A8711005C8D350DD69AD758EC054578CBE9A8B23D3342C656FD1021CAE86DF754DA882485A815094822CA3BDE6F8A0A32B5A97326CC26622614F025B878384D41A56B7E948E5D98E678C998832D2B581C443B96356B68D5D76DA2B5D4B5685E66A78B8BE3504F7AE952825E21104845922FD2D04C729B4E599710B4B49766B0766E751E773D69B4DC22D720CC2A3C5C2E473DE9A170DCBC22A8D619D56B4C2DAA5580D1042B848063A7AFAF39922F8E9F926024F1A4AE50E2A3063E2EDA534B73310984462BF50996A52B84A83925B5FA1BBD0C75A33DCE99CB96A595CBAF93DECA88BA45AE491E91D6F16C5B71B2C20CA12889628080DBDF7726CFEB58BDCC989CBA52149F9CA920921EB4D48DA8D14CEA4D5C885F0EFE216923A5F96FEBBEF7C5E7B3B9461315C2676252E786854075A936E9E109CACDD2B3F3CBF4AEC28D4D2D41E315257EA1A7AB2454B6F786780212E2A49B5C207BC75F863A748C83072C20CB5C8530A9336586B6EADBD626F0B889136E024D1DDB6AB747D08E7CE34BA2CD337738327CAEBDD5AA424A28EA0DE3707BB20FCC5B91061CCF46558297C5331D2249009ACD411E6547C6C37E526818472192E1BFE3ABF87F9AC3ED0F60DDB16A984E59A6AAEA9498E02F27EABC1C7B7FC54A42E6D244C75938A7665F1532AECC71204E938E4BFF6CD4929035F94A987D5EBA44B613F472C1F9D32FC8B33D81607D88B334FFB047B43EA2527F88E548CBA8D712A35348A294D8981C4156116B138A4637FA95CAB0AB5265C932C870C3896D70F6200E861FAA7E0D80EF25922A15C4915BD9F77BEF17264FF00462E6301CCFF005CA72050E12E205222AFBFE6A00A1CF0F0DC08DF79B629999FF519889EEBC061D734172BF9CA0827F6B710F5AD199E90D66E6928278664C42B87FE991C3F2B9E4EFCBFCC5E5A4FE8FEEC5721EED5A93509D44EA2EB47D5AA69C2C8DC781440980091B75077A2661F1E7B43382C4A91370EA2E1333BE2BE1E60354F2AF5111ABCD81042A7858D8003D6AFF6DC98BFF21F673F678D2602F24ECFD8AB7EDC750ED4BAB00A2784F76EA488277023998DF146CC3B5DDACED3F12B139DCF4A0542424A59E8CE0B9D2A5C44163F3C561DBB952ABA851F1B1DCFF116AE5E9A1C95A14FA7322CA72E69B84A5272EA275691C80716CF17BE7CE462BD88CBB34C414AB119A6216D60264C079D38ABA73110ABED16281A2967672487F115E9AC6E7EBF50BDE27D6CB68FE8EE5965B007A36123A7481B63323033258527F50B98E0385F128EBAA892DAB0FA0AB39DDA0C58F99D55BDDC78339161EEAD8A756E2CF7F993A49DDB8584CF9C1F2DC6D63118789CB4104AA5850ABD03DBF9F462F4664BED062839F9C93677FF003E7FE5400C34900B21C0B175973681209124F2F5E584E6A8E0182240505120808725B5766A79EE7409CAC7CEC7179814CD406BAEE696B59ACF4846E54D2B5E215694C4FF002FBA1FF4F144F51B448E5B61CCAC589A901182295D3E600D6B701836FF00430B842D475009342C6A3504D6B7BBD9C98E59D4540D85875B48200E05752378006C236F96D892460B133EA1250EF46DC3B37BD28CEEEA561C29B8AFE94A917DB97AC3755EA8609FE49092072DB6371CF7F31E98929393A830981FA8DFE81BD29A43D978246ACC4588E953A7A0F188F556A171EE1529E8093065439F493BEC2D6EBCF0B4EC327049F96495BDD8174B741FC36B4108E2B0E89600410A05C11F4A9FCED7A437AF3C8559D4C1DA143F1EB6F31CFCF59730AC809C32EC78810AF070C1EE7EED0CD329CF090E6E77615A57E9FC423775129023BC0799F15C419117F873DAD8949382135819079BA49BBF27F5E51212F0C9201E163D4DBCD872A747844BD50A124AD244990543CB789BF3E57EB87E32394B002A5027FF00450BECCDEA21FCBC1A76FE1F4ABEA39F852139D565327BC03D543AF9903CB95FE1855191CB402112B843D404F2E87AF4F386B8C906511C20D5F9F9381F8DE342F562C890E0F14FF5A7DFBFBA3CBDD8DCE5069C29A0E458DF952BCB4F38E75A07CE3EC6BCAA7F10997AA564FF00C498B18526DCFD0EF8426E533459246C5B6F277A73BD1E3624F0B849AD8ECDCAAEFCBCE12B9A95524F1DCFFA87C7F7F3C31565D8A07F693CB86F7A0A13B59DF94612166BA6B46F3A16FE232A5D46A5F79C6A1023723DDCFDD387584CBB12A727880D4116A9D1BCBADE1D61D6438343BB86D7D3EFE718D467920CA811BC7145E27E516E9D231248C04C961CA4977DF6F06B373A73858CD27FCFE07F88C292BD355DECAD29E1893C5BF900489F5BE362860077640DAA5EDB8FAC26A9AA49AA29CCFB6A59C470FAD2A0A097048DEE0907DC64DF7B5FCF18135083594E2CC53AF3A6BE1AC6AA9E4D58FD7A685CB5FA436BCF30DB0EAAA1D2536F009F1F4FB33B72B4F2C2F2A782A4944BE0BB909F2D3CDFC01895CB72C939A85F7C4258382A67A3B8140C69A42043F963ECCADC2DA018EEC0599336F2F7EC3CF096372D9D8E6505148AF11B167D6A36DBC75847199248C32D4652D2003466A51BC5EFBF8D23625C6A9174CFD2BA685F492BA2524921E832B4A84C7900B917F8B34E130F854AE5CC94261218A88B3B8A52FCE15CB7133B07352CA20021AA6D5D3F3E24D44417B70EC334B7B50690A9A5CC2829F2ED7795D3B8BA0AA6DB4F15529292AF1A9B084494A07DB260911E2DA3E4E3B1BD9F9885C89D31380E225402947B872080C0BA828DB6B5ADDAFB359F70A90A54C09581A970C4070C4800E869B697F9D5ED2F416A2ECD35766BA475150BD4B59963EA6C294DC36EA3895DDA9B5A5210B1C204F0931378B63D07D83EDACBCDC1913480A40002890EA70EF50E3CCF2ABC75BC1E324E2A54B988980F183C4970599C56A5AA79024F9D7DC6A98813D20CFC2671D6C294A4F184929677D199F6DA1FA51C5FB520F808C16E2936B03CC117F81FDFE0D978E9083C2A5805D807D75E7E958C29007EE4B7A75B461DF2FCBE18593392B0E9623707F88C25295164873B545FAC721E5733EFB7DD184E62CAC809E8C2BB6BF56E861712BBB0EB0C0DAA6EDD6BE0F0A5B7AE20F3369DFDE479EDCEDD708A8197520872F7A93CAB0DA601707D2FCFFCE90B98A92926F04C11703CFF000E9EFC69DE23FE43667E7B7AEFE71173504A8EDCDEB4E7E14F03611EEB687EDA28B56E4B4B5F415A52AE04F1D1A5E217C560411C4166E3A7DF38E6399F626461D6102527814FC2B0078B860C29A8ADE3CD998767A74BE2480525248A0B9AEA39EB56D5EB178E49AE334453F7F4CFA815892D38BEF0A78605FBCBDFC85CEE76C51332ECD2A51504A4109B70A5B5DC5C575761B55AAD3B0B8CC3AC8429418B0BD0EB7A1058D37DE1F59ED3F380A087E9289F44C12ED2D2B93E678DB50DAFCFD0F2A8E27239D5265CE26E005AF437007260CDD6C61C49C46310A1C530BD1BFC3FDC0BD4439AF5CE555D4CBA5CD34F64F5497C4718A2A26C343FAA5419FEA9EBBD84E18AF21C793DE495CE90031502A5176EA6940FF589019B62A5283CE551810ED723622BCFCF522B5CDFB3AF67DD66EAF2FCEFB396332AFAC2502A292A1C6C256BB02453A20415036FF66188CEB38C8D4923325CB9693F32141F880E64D2F423AD6AF7CC8BB5BDC00264D2486A9558EB63B8E756E515767DF44BE94D4D5943A8B24CC93A634DBEB53D9865EB4AAA14EB44828405B8E25C4102D298266F84317F16D6B0642E712A0024FCE471102DF9DDF5BC5D95F1144891FEDCE1C481FEDA8A8324EB427E606DCAFA477C7D9F7D9C7B1BF67AA34A342D0D3D5679C094D4D6B85456E38911C443E55B5C0124016C53B1B9B6233E0A016B9724BFCC16544BF315BF372F1C73B5BDB4C4666B9AB99882B5ADC10080070B8700161A3B00FD62F7ADA8AFCDEA1E79E7128503FF00080084A06C0003853B03748F9E236528E440AE72FBD44DB155C80DA924F5276E42397CACC66CC5CCF9C92EE43DEFABFF001D2C18EA1BA868C90EAD5B7F2DB52A40B72067D66230EE5769702A2C6580FF00F73B3F40C352CC35F14CAD255C4B40E2B82456A6FAB730C2B10ECEF2DCD336EE9BA1CADFAB7D1C501495D3DD5612A5800CF9EDEEC4CE03B5584C3AD5C012C59EAF41767E5CBC21533CB049FDA6800AFD056FFCC41ABFB1BED433849527206E8A9553FCE56614EB21276250A58579C73C5830FF001272BC3AC209698080592ABEB5667DB9962F184B03C4940079102D52C34F0D1A22CE7B251CFDC0E6A4D7BFE1F553994308CB855F7FC5F693C6D984949B1379C2B9976FF173C4B396E0063925F8D426897DDD9A8C1DF6687285A6682274DE103F682C767D3F1B58564D967B21F65D4252333CE7FC431F689A77A9B8E05F63691CBFDB11E9EDC768387E4C1AF0AA028A13DF84F47FA862CCCD192890141960B37F6B7D77A0F1B356279967B3CF6099382468C4BCEA88870D53EAE229333C278A2FE93E7B618E23B5FDAF517FF599D2907FB5DEFA163A57CB7AC6FDEA01749D2EE5B67FADFADDE27796697D21A7CA7FC35A6A8A9383ECF1B0D3A44411FF0015B331FBB620330ED06758E97C189CC31334310E16B49AEC42BAD346A88DD38B9A97216435AA4937FF0015E512919B57BC022B6928D086ACC062969D98B00412D213C5B5A648F2C43E0654C26628AE74C2B238B8E6AD5FFF00B288D74617BC4763731C59002669D59A877D4F3ABF23B4267EAAA9D1C2DA96849D82145239DBC307E189232491F384B06350090FFE79C468C6E3CFFF009AB67BBBFBAFF986E4D23EEF117DC70C1044B8A264CF99318CA70A14C18005F4034B53D4185C6231441798A7A52A75D9EAFE8D7D2368A669BFB4A048DA483B6F2663F59C6DFA142A9C219EE40E8297D2947A987099939BF7AAD73CC31D7E8083AE91B05752D28225002F918E533B9EBE62E37185E4E02683FED2481AD2DA6D62C0DF43768590954C204C2549A9AD3A5074D61A6AF39A61242D23EEF94FE53CBA494BCBF1258976D86DE36A5AFE26B0A77097A02C3D3C798A5B41D6182AF5353D3000BA0C93CFA6D173E5D6D6DF129272A5A8025245AADF7EBF4D69019090C421C7476D39EAE59BC223957ABA94FF00E6206F7B731F0E5BCF3DF9E2564E50B15009A6C69E8E29F7B464E1A5A88F9051E8CFF5B7DE9ADE3D57AD92D001B766667C5C899037807DF07D7793939089A1D480A6FF00B45DEA6CFF00CF9C2B2E44A03E54B3D28E35F23E1F5AC46EAF5D1332E024F981703EF9FDDF1292BB3A84B34B48662070F2E9F4F387224814E1B5BC798F1FF26AC4FEB8248F1C8BDA76EB3064CDA67DE30FD1912524809BEC9D69F9F43194A149B06ABDC7E61ADED6E20F8EFCFC5CFDDCC7C2C230F5191BB30B96B379BD6AFE1195778BABD0FDB772D7B6BE02AC559AD9C514F0AC889FEA22F3B7EE63ADF0FE4E412CF1712126C47187FAFBA1D2329413FBEBBD6FB6F0D8E6B47044B86C6F0A3CE23F73D7D0BD4E4328544B40D43247E2AFA53F30B2252410421B9D2BB52F5D77844EEB4709003863AF11D86DB9F8F9DFD554E4B2D364D79240FB31F77D1DA2593FDB4F23EE9AC37AF59AC190B3D278A40F7491BEDBFBF7C2C32996DFB6ECE784D5B4B034A6DD2B0E901496615AD684DB66F7531A15AB7BDB29DDB621506FEA47EF95F1B272C4A5DD001E97F21E479C273A5098C0A5C8D4E9C98B7D630FF13A3FE72BFEB1F9E37FF4E47FC47FE3FC421FA51FF11E9FFF0014649D581BFB2E154EF2A063E78D55964B3FD96D923EE3DFD33FA61B0B35403B6E746A465FE3157F7FCC634FF4A957EEEBBF0A7F119FD3E8C1B664FE63735AA43C4953844742448F71F9FBB1B0CAD228897E694DB5D3A437992BBB366E8CC3DF5610B11A89B3092E18F27279CF33F0F3C68BCB4D7FDB05A96B1E8072D0C26505AD4F03E90A46A244801C2044471013D363CBC81DEFBE1BAF2A0C78A58DEC34BB346BC25DDAF7706B4FA78690BD8D428FF9A4C46EA3B73B49F2F293E986D332A4176403425B8454F887376D3EF0265077E1A1E8FCEF57A5DE168CF1A72C482636DC1F98D8FE7E8DCE5A949FD95BD874B1A7807D79C6C999364D251297BB38A3FF0027FC085CC668C9220A2368205BCF632447ECEC9AB06A0EC2FB69B3D7ED5D1A144AE6ADF896FE0F777A9A9AEF7FA2A7ABA99D085B8A03BBFB306DE2E824903AED88CC5617852410EE0D5BE85B96AF6B6B0EE5CA4B8243AA846AED434D9ECF53E149365999E694291539324A82E0385253C410601B9BC44FAF5EB4DCC6429414921D2F620B7277D798B51A25254D9929B814436D4F67AC7567DB77B00A5ED4BB305EB6D394AD3BABF4BB2E5454B4C3294BCF0755FCC2E148057C2DA55048558408B636ECD664BCB3324238FBA4A96912D4E594010E341C83FE5BAB762731981610B52969510169528B125D88B90C6B71E0F1F3DEDF7C9CD169A9416EA90E3AD34D2814F0AA9CA90F02081B7091E21D0EF8F67E419B4BC5E5492A292A54A0D624D00249A55C53CAC63BCE1132C278480A5000AAA0B712411A36BCF4A4697EA454D5BF503C285C252208129B1811D762371BEC3140CD6562958CE296A57095D6A433B5AB6B0D00E909E290002430B0FBFBF5A911C71A7AFC8E2D7830B97853C6493C22BAD479577357A437C2F0AA635C3816DCD79D6B5D7AC1C49EBFBFDFC79616CAF1697982656B47D2FEB41B810F33340084100301BF2DBAD86BAEF0718DC18F49B7FB7AFC70E715884ADF84B372BD6CF67A723CE2118867DB6BF383BCB8857A933CB6DF104A2B33388289ADF66E4F50631C2083405AE453F98BEF4CEBFCDF43E794F9965D50E9485A78A88295DDF0D81BCF01B5F613E9389CCCA4CD4A54264B2DCDE9A333756AF955AB79A64B214E90122E5D87873771AB063A47A3FD9AF6B949AC680D577E18AC69B6BEB6C71EC4A61302449317E104C11D714FC523052810B2902A5891426A5C92FAB5FA54C72ACE32B420AFE502EC58E976D2A03FF88B92975032FF000B3DF1EF098060CA89DAD33F0B9C432E6E5C16489B24DE84A74A015D7F8AD6B41C609525441205D9B715BD06DADCD9EF6EE83ECAB5B768350EB793E5B50FE54D29BFE2754B96830DAC8285202C02E710E48E5638E73DBAED8651934B95204C947133828042784BF0817297E17D373D5A2BB8D5A964996E529BDEFCB566D0135AB011DD2D15D90E98ECEDB64D251AB34CE4F0F1B6F36E0097089238DD053B93B1B45BCBCFD9BE69333C33A825243F090A492A0C492CF4E76356880C4E65370CC10B50A907ABEA4034FCEB511720D1FA973CA74BB9850A68287861084D6B6070931F612B498883613BE3974EC1E18E294938898A585314894B22EFFBAD4E6CEDE4C27768319C247129B60AA6D6F13E8C740859ECF74CE5CE17559BFD55D0656D80B724F31C5C5CAF7DB7C59F058F9F94200448336591FB94B09B5CD7DF48623113712A75AD4E6ACE6BB8B6FCEBBC3A21DD1F9780DAB2B39D2C1FF8A2A1CA5EEE01B9008E3E2F88F4C6313FABED08025E23BA425DD213C44BE875A31E5E4D0E01EE482C41362E4F56A1F62140D434ACC8CAF276E8F7E12B58A883E7C6923E0394E3597D9D9B29242E6289D4915BB3D01F7A1BC67BF528D15E0DCF701FCA13BFA8733AEF0D656B14FC00865A6E89A05C9B1054840222DB98F538DD1912A5926592CAFDC5CB6F625FC9A3638936770391FB8A35A181F4E60F2A4D33CA6C99EF9352A02277EEC1F7F4F33857FD3141642940A8EBC21D853C8F5DA35EFD4C3E7A3D8D6DD6ADA7F9AEC66899701EF2A94542E5050A3C3D07113B5AE7975C4A6193370547252451AD4B9676A1D7913A43895378C92E5F4FA1DA9A7DAA615A72DA350BBC1405B927DD333F9728C3BFD54D5DB88B9A72A59890799858924B98E54DD2D00965C4A4B932080EC91B1B931FEF8D485CF0CA4A8105810E2EDA5AB5AF2B883894050B35BDDFD61AEA734A76E4ADD4C83C92904F98E1FBA2270A0C02D5429241D473B56CFADBC633C4ADFE90CEE6754A248524C03BAA260F9FA8DEDD2C2F2585CB5612921041D0B3D4F2A57F31812C4CA6A2D6D8D1CE90CF55AB69A9F9A401207881E66768998B7A5BAE256564EB99520925BFB4DFEBCBEB1B230FC26A1F6A8007853CEBBED11BABD74DABFE1B89404CCC280BF2267EFF00C0E2464E44416E124DC534D74BF91D21D4BC3D89A1602C5C9F7B6F4D622398F682B6C2A1D49DFF00AC1BF9F8BE44FC70F9390AD80EECBF215BF4AFD0E94687430C4A696D5F9D59BEA2B10DCC3B45714524BC00122EA03F1BEDD207BF161CB7B3A560BCB714041B8D057EBF6A8877230E5AC69A569EF96BB0BC56B3B4274CFF003C1B5C718B8E5CC1D8FBF13F2FB3290C020B3EC69C85EBE7BD9A1D7E9940174D2847A3B1BDFCF61AC6730D74EBDC20BC07093B2D27AD890445C72B5AC31212BB38D5087DC375D5B5BF846BFA6511FB5B4A9B79D2CFE0F117ABD66F4121E1EE5811B473EBF2F762491D9DA0FF006DCEB415BB3D3DED5739FD312E025FA9BBB8E9D3A8A9BC323FADD4D59C701076F18E80CEFE5BF2B7962570BD9F24370330B30F64756E75610A230AA0FF00280D7D19ED5F77861ABD7727C2E5AF238A47CFA7CBA8C49272229BA7A52956AF8B74610A8C3916FB7E7F9E70D0AD7624CAEFE6A03E127FDB9E1C232276250EDA37E038AD7EF19EE0A86A474B5C6FD6F081ED729BC3969DB8A62FCEE7F2DBD70F139250108236A7F07EB1A8C31146D5EAD7D45C53EBB504379D6E924852F6E7C5E7D247C7D30EA5E48E920A59D8BB6CDEBE5AB88DFB824BB12CECCDAF8EC368D0AD689932A9F5503F8FE1F0C384E4D5B59DD9F4BE83EBE70E65618809171B31153CCF975E621139AD1004057583C561F3F7EDD05A7191947201D9C37A5479D7C61CA70E77E800000DFEDAEB7842E6B34816548DCC1FD7CB01CA3E604A75676F1760FB9A9A51E9ABC9720A52294D69E22AEFCE91A0EAB2F9F02E387FD43F3B45EF323A8C64E535A203176A7D69AB56FB18D2761EE5B85EF47D2F7F1F516783FC48EFFCCFFF00DBFF00DF8C7FA47FD89F2FE21B771FF7FF00EDFF00EA8DECEAA2D1571B9BC478F8BE65780E51FF006A4780FBA4C67F4E7424F8375DF979F9EFFF001827FE60F889F778BEF23DF8C7FA3F21FF008A7D7E5FA03E107E9D85490741BFA46D6F54A9E0781C1E189850E768B98FDEF8C8CA7874A3DC8481E845FCFEC9AB0E4E8EDCF7E9E1710B1BD46E5817418F303EE36F79DB91C6ABCB05004B3BBB5AAFBDEE1CEA4D18C2470E496143AEDE2FBC2D6B50B8AB9581111E2927E6267DDCF0D26654521F87992C3EAC2DCDEF194E18B12407D28C79BB17FAC3A53E7EB1B391CCDC193D37F38B461A9CA8104B709DCA5F9D01AB6B5D89D2038751B06F33E9EFF0FD459E2D6482E4111CC5847AF4F8729B623F17960FEDB1D5ADBF43EADB420BC3312141C9361F663AEBD4C3EB19CAC443827D45EF1BCD8DFDF798C33565E59CA496A0A5FEBB3D7D4C604B22C9DB63B0F2B44932BCC52FAF8AA163BA6E244EF3B6D24C6E0EFB79E2171D97F08F950E482CCFE24BD36D3CEF0B252DB82E1CED5E741E9BD22CFC8335A8A358718521748A0016E526124729BEE79F3988C5231F8104A93C3BDC5413A1F1FADE1CB52F6DEE7A7DE2DCD26ACB975754BCC1097B2ACD695FA6AEA75A789BFE732B65B24104594B9102058CE39BF6851330CB42652CCA58585058151C2A04B6B5142CD422F16FECC6293879C1CB391AEBD1EBCFCAF48F9CEF6DCEC453D8FF006BB9B53E5AD1672ECD2A955793A82785B525D1F58A80826CAB2C8DE4131CA31E81F87DDA6188C261E5A965CA02189B94809FA82DA72B3FA03B3D8BEF25D54486A9357A5013A0157D7C0C74D2ABBB052EB3096DCE5FEA480164CDEEA9FC31DA6465C8C4A5331828DC1AD1EBE66C7A686B162C47CE9048A1BD7A75F01F50212F193CC7CBF76C2799A46164100B508352C4D19EEF6FB5A1BE192CB1460487B59EB7B35FC290059E4418F43E938AB60712A4AD556726AFF4EBE3614A43DC6A3890973A58E9CBCFEC39C1C6AEBF218915CD2A04855DA94FC6DA188CEE81BD4E94F6F1A9D5AAC449F203FDFE7F942492AE249507BDADB7F93A36CD1B265814BFA790DDF6FCC7A3BA43D897DA2F5C86BEA1D9DBACD2B9C3158FD630D2824C1E3EEDE0950B72DEF1CF109DACF8C391484CC42E6A105415C251F3B535E10DEEBABF38C7769704B92172B12998B1747ED3714E22DAD4D6B66B4771FB2EFA323B56CA2A9399EA1D78747210A6D6AA3144CD726A4020A9254DAE121039911D31E74CF7E22FEBE6CC565B8A54C492A74F094D9C8A96176F66B4ACEBB4B97CCC32E5CDC083359A54D137F6124B9617A373DCC7A1DA23D973B3BC89348F6A0CF3FC499951F0127EAEED2071698B424C47879881C81C732C7F6AB39985412A9A82EAA85135362C08D34F0D8C714CD7321C4A505F0D4B03B6D4D816F2B477032AD5941A7B2EA6CA74F640CE554F4E8E053A82859AA000092AF00360247112761E58A2E2E566799E2A6623173A64D248E10AE2F92F6AF47635110F85C72269520AC5ADBBD1BC3D2B4763086BF546655AA2A4B08926CA0DA02B9DE4241B75B5E7CC99BCBF0F2E401DF715AAEAB378FF0098658C099AA50490E2E68C3A6CCC7576A924C372179A66055F5879E42531C0038B00850B82124585BACFBC1C4DA27E0A50FF006D12B88B392949B5AAA07DEA62115825153BBD4B1A7A6C6DA7D6323953847896A51B9924998247351FD7717C41E6D2D58B1FED6D460D76DB5D6C2BD0C4AE1308997C2A533E808E76A6AFBC6D6B23EF02C13B478BD7900227F0C23914B9B9671778E78F7D2A4B6B776F3AE85C6324215C212CEC4B0E5CFF000DF58548C992D7DA337DCCCFEE3F199C58558EE2B067E8C3ABB3F85B48622411CB7D7EA60759669C02549E7731F2263AC1D87C30267297706BCD81FB7E203294081777DBF3FC6F081DCC1A6C11C4205809B5A7CE3A5BF495912B8FFB59DF57D7AFE2F18187481F352DA93D69E7E9CD9ADFCF295B1E25A0127910368F537BF3BE1E4AC04C9A3E54BA74E4EF57E5B887985C3BD402DA1AD6FCED5FA54C45331D494C0C77C241BC28DF9DB90FDDC9DA4E464AB5172953D1836BCF7A57E9A43A1865392E4826819BEE0EBB9FB443AB75AB742210F7171CCCAC9022D6931E640E9EB89CC3F678AC0FF6D8EED7DF4B8F2DAD1B0C22B899ED5B73D75B369BF2787E65DA1A47178C738B83CBF5E7CE713B85ECD129629A1E5BB9ABF41F5AD2344E14872493A746D9CF336A6C0C40733ED0B6876082AD97122D0441E5F3E66F89AC07674A685048E8F6DC6DD2876A43BC361CB9E77A5697F434A75BC436BBB41324F79BFF00ACDCFBC4C723FB8B0E1FB3A354576E1EA3969F4EACF93874BD4D4B39AE834AF95222959AE43F056F149127ED913B8037F5BFBF13123B3547EEE81B427E809B914B386B343A4618306147AD1CD6C6BE0DE43788CD5EB068C8EF8DFAAE6DCA6F6E7BDBE589797D9B4A98F7551CBD5ACFFE7A3A4E1EB56E5B9B6B5E7AC43B3AD58DAFBBEEDF20DEE167EE9E5E66D36C4FE5DD9FEE81FF006AA2AFC3F5035AEFD61E49C307B1D19C1D2EDEF4B86788B3BA9D2265E3046DC6ABCEE7AFC671369C981AF776D4A5CFBEBD44385E19EF47D83BD3607CBF8A36BBA8D0A36748893F6D573FF508FDDBAAE8C9D229DD9ADA9FC72D6BE71A7E9056A6AEC18DC7D5B7E669B35BFA844477AA02F3E3E7E4388EE3D371CF0E1395049AA6BA387E9B37DF5A46C30E052B7A50FF001573EA219AA73D42A25D3B1DD5CA36267F73877272C4A480C0A8DC331157DDBCCB42A891566BEB5A5DF586B5E78DFF00CC83CA144DBA993CFA6DF0C3D4E5A1D9491E403EBA9D3FC6F0B7E9B97BFF00CA10D4E7483C24382F3324C7DFF8CFBA30BA32D4D999ABA13E2CF18186219EA77615EB5D36B5F786B733947F79224CF888FCE3E1BFBB0E9397A00140DB307ADDB9529BBF8C67F4C1852BC8D3EB60DB8BF846AFE309360BDA6FC479FC3E736E470A0C1A122890185C00F7E46329C355A95DDBEA490FF583F8B0BFF337FF0054C0EB73BFEE6241D7F4C904B2789DDE81EBEFA7285D3866360DE05BA0AFDFC213D466893C1FCC169B4813F33EE3B0DA231A8C3006A900B9B81AF9FBD03C3A120B8AB0D680136D39EF6E468C98E66836E3DF9123EF07F0F86F8C0C280A761D7DFE2B0E8480C38BC472D371EF5B473FC5120D9C8DB65728F51CFC87BED07E94034008E601FC74A8FA97D6761C10E030D8D7EBEDDB678E7F8B27FE67CCFF00DF83F4C3FE29FF00C53F986DFA73B0F21F98066C9FF99F3FCD6707E987FC53FF008A7F30770761E43F31BD19BA37E31E627EFF0017DD1F2C1FA61FF14FFE29FCC67B826EDE207E617339B213C5E33B8D951F8FE76B4EF8467614355218DC507466277E909F72C482068C43535B3BD5F4E421623371FF003150623C64FAF3133F39E9BB7386410FC201EB50D62E4B1EA5CFD8EE52DABEFF00C3FE617359C246EE131FEA8F4B4C7EF6EAD2661527FF004BF5BF466F00DE91A1C3A740FCEC7CADEF943A339CA0442C836985DBCB63EBCC01E47082F0A91D342C7C6FCEFEB78CA64243D1BC4926FB1FE6D7879A6CE923FF0030F23F68F4E7F9FC45CE194EC185E8F76205B9B3F98B6D0DE6C904BA412750697A59FF00C33BC49A873A4C0FE64F985493F80F39F29C355E5CC91476D19B6BEECED61630D55254E5A9B8D9AFBDF661E1131CB73D6D2140B84484DC93FB267ACF3B5B10F8BCB8A83F0D3E6E6E7714A536D61352787C7935A2C1D399FA03E805C24150B719EA3913D6D7EBCE6714BCC72E67213BF42EEDA7F986C0BBF36B16A0FB7D1B678ECEE8ECC935D4EF3282081DD13D4410641991307EF3B938E37DB1CB140899C25C3F85BCFDED0E30D8BFD3E225B1A715DCDF57DC97AB52F7B8E9CFD269D90AB53F64592F68F48D71BBA51BA82FB884CAC8A9752D278D43C4AB279F981CA63FB199D4CC2E3BB92AE14A16800380F4D282C2FCE3BE763F302B44B4B965D0DB7F16F2FA57E759550EBA029C04252A5049DBEC98363CC4796DEB8F6BF65F3046272F96A7015C1524BE9F7FBDDE3AC292424275A1EA0D7EE235973CA790BFAFCBEEC466758B4CC5292142B46BEC7714F5EB1ACAA2D3617FA1FAC6C43A6FBF2E7B7EA7D047DF5D912560B83424F838D74A335372D0EE727BD606840A86F2F7EB1B0B806E23D4E2465A295DEB7F2F2B9FA86847B8AD154E8E7EDF7FC62AAF7996D4CB090A2F885180600E932458F2BE375A8A0505073DCFA6BBBC6532120D4B87A7E49AFD0D23EE58D7D7B87F90F334A23FF2295968091784A12916E623D31F37578BC5A49054B501AACA97471FF27AFBE51F3CA5769715303AA6101EA6B5FE43ED5118703AA5A7EBD9D2CA567C08EE54A9F78988DA670B48C74C2A0F6342C03823C295B785A3188CDE74D4105448152E6ADF515F10FBC0E648A52C3D4AEF7A94C12A29E19D8EDF3369DEF89FC362659FFA92DC8D697A7DF5262A7986266CC25B88062E01D5DAA4330DAEDD21C9344BAA4210D27854CD9CB44CF4DB6F89B5BAECAC44A94B981494B2998961D0DBD2D5A44223193A4AD8053137A83D2DABDFA750BDACB5F6CDC098B4904DAF17E9B11E82F88E9DC331F8080EEE069D1F43EBCA27F098A54D62A0DB56FE9B3824C6F51553C7188045A0031B7404EC3783BF4D9A270D338832B6607D75F21CAEF1348E129D1C742EFF009FA51E95D2BAB49025503DD3D3CA3979DEC77C4B49904252407FBF99DFAF3D8319F8954BF9520921D9A8E487A300D7606D5D286123F9C374401EF078A6F206D1D7A5AE7E785958454D0C0356E2BAE9A68CDFC467033666214789241AFEE24BDC5F41D7CED114CC358776094B891C878927A81E5FBEB87587C996B3AB86A36A58F3BFA44909243D0BA7C5DDF9EDCA21B5BAD14EFF00E6A470837E310679DCEE3E78B061FB3EB2CE14E74626F66BBF9BF278DFF4E5DF57DFF9BB546819B6880E6FAD9D6F8887B69D9423AF22479FE63160C376616A1FB554D83D6DB7B1CDE35EE00AB7A1F5AFD6F15B66BDA0BE88870DE40F1F48E73CB9C1FBB16FC9FB30025416973472CEDE5A7869A562470522A6C69A0DFAD36143CEA220D98F685502DC7133FD53B6F10636F8FCB16CC3F6725A588439E9F5A55F95F6DA48E1C1B25AF63FCBFD36882669DA3383878DCDE784957BBD2D7FDC625A4644840712BA8B0D0FDF5BED77C7E98EC697DB96BB11107CCBB458E2FE77C553F79B7EE71268C9D9889543AB6DE1AF2A6F48C7E90E80B68000DF5310FA9ED0A7ED390449BAAC7A9131BF947C313383C8D731C22512433B06F56DCFD2978DD187E0366A790F7B539C45EB7B40041873CECAE77F506F61B7289C4EC9C8668209924071A52F7A57C0727DCBA9529D541C46CF6F01EFEAD11B7F5BAEA15097002264F1011D0EFF000F76DCE7B0D9404FEE4682E3A7D747EB630F112663064B02D522FABDB956CF6863ACD5CFC121D83FFAB6E53CEFCBF6226246552001C400A6DE27D9A6D7A391216CE433D4BEB40CF6036A18607F54BEB8974D898BF2EB24EDF893E78929796C9154241702A18EFA7E5FEF0F24A1449F9438B7A787AF367AC34BDA99C5132B248B595BCF94C7AEF85060D2094A6583762DFC35B975DA1C194B37413D4084ECEA0717C72E447FAC5FE26E6DF75BA6A708D6433BB8E1767DEDE756615A083BA57FC3D04277B3F59305C1CEFC5BF3F21B0EBE9B6105618B91C0430D8ED4ADFC1BD088C2A5A9AA8F4FB8722DF686D733D75572E584DA473262D3E5BFCF69DD18750154B73E61AD6E553585A5485100A505F723C47DBDD92AF3C5DBF99E9D4EDCBF630B265115B9DA94F7D75858E1A610CC5FD3F9F2109159D3A77583D25447E9E97C2F2E492C40A92761ABBFA54F846061542A5FC74E77E637E509579CB9BF797F5FD679F2FD70E44903FB69B381F7FABC6DDCA989AB3EDE9CE386B365A8A871DF7BA8FE07CF9DFF001467A120064B72B8D3D3A529CA364E1946A01AEC0F81B10357B46EFE28BFEF3EE3F9ABF0C35602C1A1C2308B001677DEFD1C68E2135466AB1C32B3B923C407A49323E1F9E08769C32C81C496E9AF3B8F6E7AA6FE2CBDF8CDBFD53F120C0BF909D873C10BCBC3B100A4DF5177F1A3539E83683F8B2CECB3F1302DCCCF3371CE647492359D86528D05A9AD3F3E3D2907F165FF0078FF00ABFF00BB0423FA49BEC472335593F6C7FD5FA9FBB0460E1660D3D3F98528CDDCFEF1E6388FC7D2FE57C118386982A416E9FCBF942E673654125520C589DB698E636DFDD717C379E3F69F0FAF2FBF5168495865F11A1AB3163CFF0093C86CF0B119B2AF0BE9FD463CB788C335817173A6FF00CFD7EBA9C24CAD1C8B50FA7F10A7F8BB96F1CF520FE67F7EFC345A5DCB3034F2B5A82BECC6BFA69C2C83E00FE217319C2C412AF7C9F4E5E5CA7A473C362826E0EFAF4B535F1F078C9C2AEFFF00ED3CBCB43E476877A7CE5C9BAAC77BDFDD049B4F2B7ADB1B499449F9833EFA5F57D79C379D87527FB5DF6A03B59FEBA59E251439D2ADE3B48983C85AF33D798FBB0E4C8960114A5AB42EDD29F73630C66495281052433871D7AD76FB44958CED61248724881F6A08F74EFD7732047945E2F0C1493C29A54E9E3CFF008D618CD9132AE9248A06FA790D6B6A9AC4D34E6A073BF44B877B99116E9CA47979EFCE9998606612AE14B8360C49D795296E8F11CA9337662FB0FF00034E76A563B63D98EAE0CD7B54CB5857D64A123C52045BC5D2C7A8EB7C735ED464EB99865CC54B628428B9005FC2AD66FA35232795C99E8F9480541B4F57D999E96E663B0DDB9E9A4EB5F67FED074C5434568FE18D5435C49903810BA8F09DFF00A44C1B9F5C79C50A548CEE4F092026629C02CEC59E9F6DF68EE7D859A4F03BDD2D6A5B7A59B63A74F8FECF1B6E92B2AB2F4A4257499857B4A064484D4B891D62C2D6BDBD4FB1BB15989465C80B53012C30259E95E6DCFC6D1DE904AC7117AA535028C05E9E3F9864539E7246DF1EB1E5CF0F67CC99889C7841238B9B33F900DB42A94D416A7E1E3969DBA813111D7F7E677E589944B972E5A12B676ABFBE6478187A9040480CFAF37FBE9D2371713BF14FC6F6F3F2C39425240E1200D83726D7A46EA42920929206BEF58C1EAB4D35338F012B4A9BE131600A84DE236EBD461963D69952D550686A1AB606F570ED6E51893C33961093BFA036F7D23EEB90C0E9E222361023FDBDD8F9E53E52438291434F478F99099412E05069ABFAD2FF00C0A4284B29FEA48F7807ADBCA30C912439A3541D3C4BDC68E7CA3612D9FE6356A36CDF8F7AB830F25BB13007B848F3BF97BEC39E25654A25258508A5DD9EBE1CFD8D0E1D157653DCB6E051A91B1598B6CA499049E9E198DAFE9D77B5FA6C704A9C40A80EEF5BD49F0D3F986D3B0729D252800005C52BE766F76863ACD46D37BAC022CABF4DAF20CF2DB79C3B93922D740E75A7A786BD7A88D512C22890C34034AE9A9E9EC45ABF59B54E2CA0419B1503100DF63F77E789AC276754BB8552CE2D466F7AC3C94859B17D19B5A52B51E9CA2039A6BE80A01404743EBB7E6019BF2C5830BD962B22A5AAC081F6D7973BC39124283901BC86EC6C3F07AC40B32D78E389480E9313693FB8F58817C4EE1BB2490589D469CC9F1A7BA0791C1E193A21B7D34715A7DD8B96315F66DAE570A3C6AFFA8DA37DE48823F41CAC983EC8CB05249AB0D00DAEF4D7979C48270E4B101B4DEFE3AF28AEF36ED01C6403C6A13360A304027A411E738B7607B2B289B03C2DA313ED8FE09683F4F5B5CD00FA50FDA95A33C57D99768CE92A951833BA89DC1DEF37F3F741C5AF0BD974060C2806839834D5ABE02D19FD393702DB0D34707C07E2209996BF7564788C09B137E80EDCAFB6E6313F87ECECB940B84D59E8DBD0DEC5ABD76687125A43850BEE1FD3CAA4FDE2215BAF1EE4AEBBA8F4F5B49DFD791C49C9C964B03AD68431246F7A07BFD21E09C820820176D486D6ACE2B7BC43F30D542BF87896416E600279FBF9F4DBA4624E564D2D92C052E4B5791F1B56C3785D130711A38A11A38A6BEFD2B17AACE512789C37064F118206DFEDC879E24E564928814018D28FA07A73D6DE10E51310481C2C7CF73B1F3FE222F9866C1C4A421C208E52473BF3DE2779F4DF161CBB05270E829094EF6150FE22C346FC6B36499EB484D00B902F50DB1BEBE2F0C2FE647FE6CEDCFDDD6D73CFEEDA5D12E4B5427A33B7B1E1607487D85C190A0E9E56BEFEEEFE24A2566409252E12044413F70EBE9CA63094D9485060863FF2A02C1DB6E94360444F49C1800028046C5A8DCDB7A8B38A184CE660019E33111F68CFDFBF958FA02488E99809ABAA490C6A03DEDB6C5F5D6BBEF3A42024FCB5FF003AF2DFC7486D7F304DA1CE479F49E9FEF6E587B80C2CC90E26329CEAFBFF0022FE15B6F8292921C867715EA77AE9BFDE1B575C913E3B936379FBFA7C312BDDCBD852FF00CC487E9D1B0F2FE634FD787FCC3F13FF007633C12CD78475FE633DC27D83F984CE55CC8EF0DA48B9BFFEE1F2B7974C704BD93B697FCC63F4E8D8797F309555A0117F9917BD8DFCB0D67A521D9205054372F1B75BEC214972057852FD037D2B1A1CAE17857A7895CFEEF4C3585FF4B47E1A1D77BDFE6EB094D7264CAEFCFC4BC107E99A8CDCBDAA38FAF23FBFFF0072F1B71AB7F41F88C1C283700F5FFF00EA37355C91C442F988B9BC0EA48B0E64CEDCF094D2FC3B87F173EF4AD6B0F30F85490C523C869E6F4DE87CE395E62019E23FF58B7BFF000184A1D7E8D3B0F249FAFF008848BAE0621479F318236FD2816007BFFD5187D70FF71FFA8608CFE9B97BFF00CA33456024CA80FF00D4411849603D2F57F48C190137D793FDCC67F5B1FF00311F2C690774397FE23F307D707FCC46083BA4F2FF00C4473F5DFF00F553F1FD7041DD0E5FF88FCC29A7AE09E225C076D898F7C1C27334F18061D2AAB024720295F0BFF887046629DF8933B1BABEE9FBF09D3DEDAC67F4C9FF0088B6C9A7F3CC79C2D6B304413C493B4C927E026E45F6F8E352949B814BFF003FCC63F4A9FF008BF4F7F585A9AF4C8F1EF72388FE7FBE538C7026FBB6BEEFFE231FA245F847D835986C75BBF285CCE60949FB569E4ABDA76B8993EB68C359E0241005DABF51B7BDDA23F17252904049200AEA6FF6F7762FD4D99A2C02F94183FAF59F7FB8E1A4462F0E922CEF534F1EA6FD6DBD5F18CD5278471C7FF5449B4F3F9DA2E3D304021BD7686D330E0B70D80A8A1DF707CB9C4CF29CD5B8038C8E5B91173E73720F5C2664CB533A438D587E3E90D558740BA4575DFDEACCF174681D52AA1CD58097152A75B54955E10A06C6E248FBF9099ACF68B29973F053D6123E596B7617749FA3B57D68D5CCD70E04D96426AEEE1A80355AA2BE7C8DE3D7BCAEBDAD5BD87E78F00852AAF24AA055024F734CE8B98F2B836BDF1E16CD248C276AE4B025299EB013A1E25746714BD599A3A576397C0123F69F958B1D3C2FBF9EB4F8CFED532F465FAEF523688FFF0036AE040B01154EF2B44DAD138F4D64B30C9C2618874F1212487E40E8D4D5CD01DC18EFD964E3330F2C7EE00539B8721F7A1D686DA45798E83964C9665924076BD34A1BD47D5A2591281E9BECD6DB4BB6AC6353AA03867CFF000BFA61863713F3B0535695E6E050F869D61DA249E20402C2EE59C737D4F946BE31FDC46FD7F77C2B2316521B89F4676E4ECE3E97F087989522649EED0C54DBD453AF4673D19A1592D5552BB4AE186D650A52F6E1E054C5C03E2888F7DE711F99E238A54C7535CB3FE4F98E9CE2264489D267A2784964F13ED5BE8D4BBB7231F79E8692483607CFA4F33D3A7E78F0CCE0A2753F8D1879FB78F9A610E03D0D5F57DB5D2372DB40493C42C0F3F96E709A10789238581D5B6B7B3F78381B9F2B79D7488ED6D4A5A053C6011100902237E63F600C4D61E4BF0B8B81A5FC2DADBAF283839BBEBB7AD5ED10FCD3352DA13C2B07ED490409BF3BC413187C65AA531425478B46D34F3F37F209AE5DABBD5AD6E715467FA8D6DF170B8044ECA1CE3A1DA62C7AF95A7300A98E01944BB35DBD0780A8F18C26497B39A69E3D4DEDE622A9CDB58AD9FB6B242A62E6DC26F6E9B7BFC8E2FD96E144DE10A9646EA20FD00A5A9FE21DCB96524937D2C7D2B5EB4E45A2BBCDB5B92170B55CC889B83D36E5E5B46DCAEF80C9E5A824DA81DC74A0F1FF0030EC218543BDCE835EB53EE910E7F5B59414B226D04EFBCFC62F137C4D0C914E381015CECCC76A3DDEF7D054449E0D245746D859B969A575F288566DAD93713E97B7BED7F48E773890C364D3D0CE87E82BA519BCC5A8D41121107ABD522AAE49841E6779DA2667CBF238B0E172F9E900041F6E3F3AFD60F7D07B6888661A8132A957B819F5E401F77E589FC3E167243841A5A8CE5E9706E7D7AD4888D4E7685127909DCFDF079FC2313586C0CC9C3E6490ED52DF4BD7931AC67F4C673102A7F8E63C3F9788B57E70832479F1413F7C4DF78F98C4ACAC9144BF16C76B3685BC7A54C2C8CB961EE096621CED56356BD6DADE22F559B990524A4C192491F1DFCF68E9E92B2325208F999E868FCADCE9CF5687A9CBE651817D6FE0DE218FD1AF1FA8CE1641959581EA2F71CBD3E3CF0FE5E4CAE22126946FAFAECDD6B48772F004DD241E86B7DFECC7AEACCEE6AB51FB479D898B5FAF9C6FD23AE1C8C9E63808AEEC6A0BEB5FE3986896C260121412450B5C1B53FCFA8BC36BF992C09E226677F48E7CBF0BCEE4AA9CA2626A2B6DCEED4A9E9FE1A7A4E050006482C5C161AE97D35AF84256B3155F8D5BCC4F9CC70F5E5B5BA61C270252C5436FF17E56BEB1209C2B248E17DC8D2874171E2E7C2BC3B5CE411260FAF59DCF2FDC61CA30E84B3801AF41CAB47DBCFCE23E7E1493661BFB1B37896A351B2A6BD5E0B9B024816B1F78F2DA2FE77C36C5A65A47CA41248DBC79DB6FB554C0E1EAA090E297E67DB9D078C36AEBCDF7F2137F84DFDF862E6EE5F778933873FF0017BD5EDEDF9F8C70D57295C526C47F70DFD27F7EB8C3EAFCDFEF07707FE3EA7EFE5BEDBC60BAD11BF3B78B7F9CFEEF8CB9DCED7F483F4EAA7CBFFBAD6BD7E9CE13AAB48820F90B8F91F3F3239EFC9A4F533EAFA93AD3EFF8E8ACAC39049663E07D5FDD7C343958B04EE6666E39FE1FB3869C67610BF72ADFE9F9F7B084A6B960917F88FDCE0E33B080C957D36DBA8F7BDE31FAFA86E63DE3F3C1C6761EBF983B857B03F31926BD5E220DCDA26479EDE42D84D6B347ADFED6F661C4A94A4D086E647531A5CAF72E01168237F9FCFA634EF03B51EB47AEADF673D690B776378D62B9CBC903A6FF00AE0EF361EBF7F380CB1A13E35FC4726B564CF11F404C7BED8CF782BF2F42F6F483BBE7E919A6B14641519F7FE53F2C36985CDB73E7FE20EEF73F6FCC67F5A3FDC7E7FF006E138CF00DCFA7E20FAD1FEE3F3FFB7041C0373E9F883EB47FB8FCFF00EDC10700DCFA7E2334D6A93B1E7CC9F2E91F3B61399A78FBF7F783806E615A2B960DD56F53F7613804B7DCF41A7BD7D216315EABF885BCFAC7EF6C101975D41E63CF6D87942E6F31541F189D8127D39F5F33D7041DDDAF6F3E6397B78503317131E3F2DF9CD8F3BEC3973B9C359C6B4B1FB010D71320936B8EBCB507D1FC21DE8F335DBC44C45CC4CFC7A7C4F5B611861330EE9735D29D46DE0F73E7477FE28B0A49E3DBFD44EF1BC47CB6E7821A2F0B47776D36F51F7EBBCB329CD96384F1DBD76F9C8FC799C10D26615DDEC76BD1B57AFAED13FC9B54FF000DAC61D51528CDB8495472BC0B5CC826DD31AE324A6665B8B2A0ED2D4C06A58BFA3442E3B08A98A49093F2B9A3F96AE6EDBB7378F6CBD997355EA5F67BCFDE52A4D3E5758949245FBD4BE9304FDADF604FC71F3FFB649123B5982401FF005712B04805CF0A9EB4A6CDAD6D13591CDFD3A892A090180A736B6ADADCD5F78F93FF00685CA9CC9BB50D594EEA5499CCEA1490A052654FB8A98224CCFA73C77EC19E0C34804D3BA43518B848A7979DE958EFBD9C9C3138292C6CE14D5B9A3EDD628C2A80241133F2FDFBBA62D597E294994B00B16D4E95F5B5766DA2EF2E41090598F5D2FAB5FA5234B8B24A523ED5EC0C9B6FE1FD397C22A7628AE6AAAF5B57EB7B33B36BD61D4A944CA98487B51EDA6FAB4042CA0AC24C0DC81205E37023E3E784BF5CA42CD4802CC5DFC896D0B188C9638B1291A150B8B870198E97F1AC29CBE9DCCC5F6B2C485F1573CD348E0495ACACAC25094A520A89248989F3BE2371D987121614A77259CDB9FB6EAD169CD25CAC165CA9C0252B12CA9E95A55C9B3E9BF847DE977E9FD93F963CA8403711F2A7BBE7E9FCC24AA7C04D8C588DFEEDAFEA396E30BC997C4A7091422A7617F0A0D2FCE0EEC6F6B53F98AE73EA829E205467909D81F7DFAC98EB8B460240212785FA8B1D797234783BBE7E9FCC55B9BE6EAA44A932541C993C46D137079FC276B0DF16DC1E5B2E7FEE48A33D2FC853CDE977730A224F103A9341A6DD5BEBD04529A9B3509529C0FA9B324D8157EC7C3DC716ECBB219331490994058D5ADBD773E3CE90A8C314967EBC9BF3C9C7845379BEA072B141B455F129B24429B080667990072DF68E5D6F381C9B0F2582C25205CB8A7875F6EF0E932428DFDE9EFD451EBECD735CE5BE25165B0D5E1C0F34605EFC324C8FBBCAD8B5E12565C3E4EF0120541A35A84BDFD97870891A31A54923DEDA163B1A4429DCF5A794B4D4D690B444212D1B13BDD3BDCDB96F7DB0F26E6395E5F45CC9638AE4A817B73F7A521C0989902CFA0B7A38F74A52196AEA9E767EAD4F5954397754B50A99E9C2855FD2DEBB9CA3B5393CB0077F2ACF5501F53CA9A5B68C7EAC3BB73AD9F62D7D6C075786FA6D3DACF3F5AD19469CCCDDEE48EF09A5A96878BECC153402BA7C49EA17476E32094DC588C397D0CD40A8AEFCFEB4615C8C524B92083E9A569E74AFD62454FD8576D19B81F52D2554B04FF5B896E3D78C00236E5D779C253FE28F66B07FF56749177E15856BA70B92E2951E942ACB9A8501C4BD580614F7BD7D2AE87D927DA2F30095536892A09992AAFA54403B1852A779E56E7883C5FC77ECA61292E78249A32555AF20D6D5F95ED37815A12ECA490C18961A787516AB52EC81FF00637F692BCE8804117FFE25487E1E212379DB9ED84E57F507D98A033A9A517BBD68DE0C74E71312D72DCFED1677228C3E9E5118CD7D8FBDA329921751A114A4C1852330A7544033210553EF1F9626709FD40F67669E193312F40428A83FFE4297F57DA1E266C9B28A5EC198B1E4DE75FCC5539FF61BDAB69C4ABF8B68FAF63BB9E20DA16FC0E63F96850BF53BFDF6397F1B72650752E53901BFDE4F8EBFE3EAAA67C80400C40BB306DADA9315366990E774CB08AECA735A22991DEAF2EACE111BCCB2058F3DAD0716FECF7C51C97342522749413A77A9513CD9F7F4BD2CF244E0A53A025401F992E900DB52DC81AB1E42B11475550CB8505A1992447DB50A45373B82954131E9BF962D67B5997B3C89F2C837F9817D857573A69E313B875C9984F11EE82438480540F881EA28FE70D9993CC3686DC7AA0B0E89EEE9D282B0DFF702B13C53E77C2A7B41859A974AD249D5EFA52A29B5EC3C64A423BD05405750FA581BED5E9CE1BE9B397140A1CA9E200785250124F2898916EBB79E3538FEF090920BB1047A519E96FF00308CEC27CC4F0B39734A1E5B8A0A5DC51AAD182AAD6A2A2A6CB69DD04DF8BA9DAD7E57B72C379B356A2789C27A9248F3E7BBBC2B86C1A407721EE386CDCEEDB75BC2672A81BF17A99FC62DFAE10E24EFF587BFA54D9CBF43F47FBFF089DA9008E131D60FCEC09F960E34EFE8631FA54B7EE3D58FE6FEDA357D689DC93FBFFD3838D3BFA1FC41FA54FF00CBD0FF00FC51A9CAAB893BF5E71EEE56E5CF7C369EA1422ADE1AFB3E3A43997870E0B3F890CDBB937F6743AFEB3E7FBFFA70DBBCE5EBFC438EE07FC07A7E639EFC281926DCA3F41EFF008E0132A1D34D6BFC41DC03640F06FE613ADE4C89F76E07EA7DDF760332EC3A560EE07FC01F2E576A7BE75E5AA8826F3B474F41B981E9EFC379AAB134049F7EF58048E7C23A3D7C08FCC6FF00AD790F9E11E34EFE8633DC7FDFFF00B7FF00AA13545403C3CBD27FDFE5EFC1C69DFD0FE20EE3FEEF4FE6137D60753F13F960E34EFE87F10771FF007FFEDFFEA8DEC5481C5700F9C9B7BFF2F7E3459059B478C89203B906DFDBD79FDFF951F5AFF5A7E18D236EE872FF00C47E60FAD7FAD3F0C10774397FE23F307D6BFD69F86083BA1CBFF11F98D6BAA16950E7E5D3C8E119AAE16A3F8FBF6F183252756E80463F5BFF005FCFF4C23DE72F5FE231DC0FF91F211B1BABB9F1FADFF7E7CBDF83BCE5EBFC463B815F98DA94D6B7E56F58588AB103C5BC45FAFBC6FEA70779CBD7F88CF703FE45BDF9FA78C2E66AC492553EF9E9222D3EE048DF1A124DC93D6119B87245F8B9B337A9A7BD6AEB4F5A9170AB7979ED79313E7BFC318866B9203862DBFE43D3F8A43B335C991E2045AC4DFF003BCF58B804D8E0840CA150534BBE9EC6DE90FB4B9824404A88E978F3B79C580BFBB04365C8493C4CFBF3D37D4ED5F1AC4BB2ACF9346164C2839C299578A0191FD524738F90D8E179CA6CAF16583896B63B0E13A589AFE758426E042E5CC5D9858815EA6E0B79F808F71FD95EBCD0FB2ED5D6344949695DDC13FCC0E54282E4CC90248BCF4137C7843B48944EED9E012520A7BF9E56C43020B8DD81E4DE8229B3E7FE96690E032806D5BDB9E54A068F05FDBDF432A935AA356D3B60379C3CF297C090005320054C08B99DF73D648C7674C9270F87521354A45BA002F4B6BD3731DABE1D6681695CA597E3E16F326C7D1AA7D63A00E38971BA5B01F6828C7398FDF9DAFB626F0292A96AD29577EBEDCF5BC777932C2A47117AD46D5B57434ABD2FA3425A86DBA37DEAB026A14128A74DC821638551B83123E1CAD88F97294664D5317AF9543B7315A9778D258E14AC3BBD816771E7FF00768DD636D3A2B1861CCB1100D47F31E5282645BBC4DD5B589DA76B622F160C849AD43D0EA1F6205A86F5AF846CC42D13BBF2966502036C58BD346B335F778EF6FB03F600AED63B51A2D479CD314E97D1AE1AACC1F7507B8716A6CB8CFDAB28871B1B489B5C462A198E35499530A13DE2E89097624AFE5706F477A7E04557B71DAD4E1300AC31980152140A5C38614F3A07B1E51F58E1D3CB88FCFF001B63877007E5B7F37F778F9F9C01DF4DBF9BC25AB74847F548D8111F8DFEFF00961E48284B0A51B56BF96BBDDB918024026DC872F1BC5719F3AA2493369DCC1E87E3F23CA3169C04C92809798916B9D35F75FAC67853B7D62A5CF90A7DB5109714B483C21B6DC5933BC84824440DF165C366F83C1DE6254ECE1C353A6BD357DA364B4B2F50D7677D47DE2A6774EEAFCEEAFEAF96E455350951294A9C4A9A499302EB40817BEC79198387A7B6F83921A528248A30587A72A0AD7F9A43849E201D56E5E76B747BD8561E97ECAFDA4EA84B0E2E81BCA1944971D152C2D442AFC45016140813637B7B8C0E2BE2B4A94B3242D7C7503E55106B4AD4791EB487680901DC30B546BAB5CF2FF1132C8BD89F2547039A9B582D6E0238E9452BAA13CD2548570F94ED88BC5FC58CC65ADB0F8733127FBBBCE137D99EA74A1B5377085201254B02C01DFDEE6A7A98B4F2FF0065CEC474EA52ACCF4FFF00885C708EE5DFAC5453776A4EE4A41F1151E4623A9338ADE69DB3CEF3CE032E7AF03DDFEE1FBCCC7A5EC1B938BEB0C71B3004FC81FA503EDD39D3517BD8F92E82ECEB4F84FF0002D0F4AC70C7097541FDAE27BE428CEC7CEF88539AE70B491373198A7B8019E8D707D6FAC46778ABF057FF005505B4D1EC6BCEB411384559612114F95E5B95A2200465F48E97472921A0470F29BE21E6CC2B5154C9D3D4A15713A6001479057E5B771194CF9B60199EE7C4E8E437D2F48C175599387F969A65CC7D8A561991063ECB698FC3EE406214876338D35993162E373B7AECC20FD44FA1A5A96BB9E6F6F510980CD883DF2C5288F070A52AE3EB3C3B797320E14E29F8A002261436F523CEFB1B6F511A2B1D8894411C4C0E85B8ADB786AD4246D081F4D692AFF3EBB5FF00E198DBDDD6DCAE07A6F2F05892586206946035BD6D4DEF7B46C337C4B8002B954FD7D98E292AAAE9839C59824154471D325CE28F250300758BF2387A301895103BF2E3FE25AECF40CFA43C4E6F8A21DD7B357EFF0088455B995528101343524FFCCCBA9940DB9F1B4A3E9B1DEDB4C94BCAE69487C4CC06C7FDC56CDFF2F4737D459CA33AC5ECAA5CEA7616D2E77A3C42739A2CAB3E6CD1EA1D2F95E6748E712168451D1D31095483E36D90AB8B4CCFE2A4BCD330ECE2BBCC06227267AAD302D6BB16259448FB75D657079BE216405F130AB59EEDA8F0E7AC755FB47F61EF67CD76CBF579436746E78F0528290AAAA94F78648F0CA5BDCCEDCC88C5D725F897DA494A40C499B8E24D57C7DD700DDAC76E9EB76CAF3C521011DE84248658500A2DC8A99A9B75D23CF8ED5BE8FAED3B47D2AF36D26FA759654C079C77BB0C5338C34992986CA94EB9C491C8488913271DD3B2FF0014F033A748C2E3712A953E610132D615C20815759F97CCD7D0DD3058CC3CC40216971552C2C3AB88B8F968CDD181F38E8266B95D4E4F5CF65D9EE4F539457D3A96829A86DD6C1520AB8A0AD0849888B4CF58C7A4322CFF002AC44B96A5E3651700BF12542A0355D9F4DF7E73F28C9989052A0A49146A934AEE450727BC449DCDDFA975CA7247774D01B200D9513717DADF28C5AE74DC2E2403849A89CC3FB0BFD09ADF50FA6912299094212B02AA7A359BDFA084AE54AC78BC50373B7DE07E186852A4D155E6CD7AFBB429DDA9BF6D3C1BA6DCE113952A26C6C6F63EEE9EBFA6D848CD40B9EBEFDDE8F1A8049600B8A5ACFCFEBEB1A8D4AC0B98F327CFE1B5B18FD44A667AEEFF0068C9045FEA2353952AB024F316BF5F2F220F48F8B798B4ACBA4BFBD6A76DBF10B4A415548A6845FC287C7D79E935046F23D47FF6E112A22E9F5FE21C77279F98852C544855FE71F801F29F3C63BCE5EBFC41DC9E6DD45FAC62B7FA104EC2E3D4DA3D718EF92ED4715BFF001E9783B93EDBCA349A829224C1BC7C0F41FBF38C27326254086AE977BF4F7E31A2E480D4726FCB6AD1F583EB47FB8FCFFEDC2109F75FF6FAFF00307D649E7F13F98C10775FF6FAFF00307D60F51F11F96083BAFF00B7D7F984EFD491C3E2DFA1E9E83CF09CCD3C7ED1BA255E8478FE49F7D213FD68FF0071F9FF00DB84E14EE4F3F3107D68FF0071F9FF00DB820EE4F3F3107D68FF0071F9FF00DB820EE4F3F311B1156AB8E23F13F97EFE184E669E3F68D552942C09F23F4F7F6D9F5A57F71F9FFDB84E35EED7FF00131B9AA95C9FB5620DE7F21F0B7E4463815B7A8FCC2D455192788C7333B7CBF3C60902E5A0E056DEA3F31B455994C2ADD419DBADC45FF6318E34EFF5D6353254AD3AEAFA6F0B98AC54C71729E53EB1791F1913D2300524D8DFAC21370C412149F16EA199FAFD61C45728100199BEF7046FB0BF2F775B8C6D0C662129714BD7EC6F4A0FB43C51D63C2150AE198920DFF2837F7C8C10D7BBE3A243D68D424DB7A373D2241475CA75496388953EF30D260C905C702009E57311CE6DD433CCF172F0D96E2FBC584032D4CFA963E3AF4874890D2660586F94B02CF6EA3C74173B8FA1BEC932E1D9FF00B2B68FA5ABF0AEB692B56FA17214A2B778DA2524711FB408B1E51D71E199934E33B638F2E5430D3D3DD96268B25EA37B9DA38EF690044F4F0D52565C8B33EDCBCB7D0C7955ED5B912354691AE79C6F8DCCA3BF5B64265403EB2AB089DAD69F3C77CC34A98AC249F94FED0496A014F07D3CE3A3FC3AC54B44D9616B01D40124B061A07F7E11E28672E2A8A502789B75C1C306603846D048B7DD79DB137815CA08582B014CC4539D6F4D6F1EB0C1CD953B088E050AA400072035D35362D76DF3154DD453A2A160ADC6C0EE85E49912600331CFE06D8D1084A4AD4A2CEECADE9A7B6BD223CC89E678E142B81EEC5BC09D0EE2D7A54C4A74DE9FCEBB44D4791696D3ECBAEE699C54B6C90D24A9494A5C6C2AC0181C04CDFACE2A39E4E9638D226A52A6E27BB302F63B0B18DF3AC5E0F2EC0CCC4CDE1265CB2E95109F988212C4EC40FBD63E95FB2CECA72EEC1FB12CAF4165E86D8D5B995353BFA8AB1290871402D152DA54B1D1B5A9278546DBE2858291331F8F5620712B0F294D862D4512196E1AAC46A3CDA3C21F113B633715984F9689A5654B502534012F40002CC07896E91EA7B1926655447D58771C5B712527DFE2B981E43A1C70B9B89080E54C0D5C124FDDBCDB511C942944D0FD21D11A1B377071E6199B6C22070028412AEA0106C3DF73CAF88F566409694A5129FDD460281B91A335E90ED091424373BDF56D3C39F8F1FE09D3E811982D35A6E1512824F9413CB78FBB1AAF31C451A628307BDBA907C74BDE1596CE695F31BFE3E9B46EA5A0D0D917789A4C992AAAA93E15282DE128F25A4A52098B1B61AAB1D8CE204E295C25F8925DF956FA5FEF189AA008A577F0FE7AE919C67750E7F96A7A5A7A256C94D353A5413CBC41015EB27D26D8D44CF9F88F1926E4AD46ADA827E83F108F78BD090341B46EA8CBA128287DC2F19EFC254A0279020103D23DFC861F2677197500E2E4A413AB69F8680AE6A59C902BA8A37BFF0031C3542120711BDF71C511D49EBE67607AE1C8095A5C067A6BF4A46C0CD21C1247D2BAF46F5F2DCE5234EA47110422E2448E879DCDF6F28C289509746A35F66DFAF4A985E5A4AFF73923AB0DCF5F2BF38D7DCD3B444AD23681C201B7BC79636078DF8535DDCF5B102E3F30B7729DFD0FE61BAB6B29982D8E2499E21C8CFBC9FDFA61497825CD04A659D0D8F4ABECFBD3D20EE0173D1FEDA8FA4361CF295A925C47C0088F779FEC6153944C51A20DAC4747D2A280F5D20EE13EC1FCC6A7354D12225D47389208816B79FCF7E787523249E6BC0455E9B1DF6BFAD2B19EE65B5520EE5839F12E69A43255EAAA3330E3441F31F76DBC91B1F75C3F464588B842A94142399FB5CD39DA329932925F801F7EBEF48627756D1200971B93E693F8FE7E98728C93141B841D34660342F63EB7687689128BBA035281BF07C36844E6B1A1360E376EA40F59BFCBE6360F5392629A81637FF3F8A561D2654AB042481AF969D7900DCDE1239AAE85F04075B91E622FCE06C07E56E78752F239A0033251535DD2F72EF5E40BB3EBA34394CA40FED62350DB03E9CE8F57D9BDCA8A3AC061D4926F2089EBB83BFE3E58D66E5E24A4B4A0826B415A78529E7F58DC4AA6CA3F228A46843D3E82EDF9A533A677F8705BCCACA9C5005BA85ABBD698FEE0A6164A17C62D04731EF64B95396381C841FDCC9295F50B4B283105D8B6E43346F81CC7132D6089AA0C402EA2CC6FC8EEFE5A452BDAEFB3B7657ED079255B59D50D2E5BAA10D2FB8D40C301905D20904B0C25B42BEC84893326712B83CEB39CA1094E13113A6E178A924CC53CAADCA892A2EE0D7A6B1D4722CE56952146610B0DF31A82FA312D6D8163E9E0676FBECDFADFB00D4028EBE8AAB34C973175FF00E139BA1A3DD38D3249517036161B02401DE284F58DFD2BF0AFB726485271B89EF0A827E55A98A696625F5367B3C757CAF128CC51C4C94A92050597CF61E7D2ACDD7B66A2AABCA9879BEE129DDE490E4C4CCA40B481CEF3E631DFF0D9D61F30ACA5A40536AE6BD0D2BA6FD626BF4D2D29725A96B5ABF7F0AC37BEF369754C21125AB17B889EF49F2330009DADCAFC9FAF2B5CE485256EE2E3CF4EBAD3D61AAC4B42411FBAAF4A80F4B0AE82BF68C50A49DC7BB9FE136C4062B053B0EA3F329B986A7893F5864A4AAE09B583EEDEEFB721995A524F4311BCC01EF3BFDDF0CE04A8F1025DEEE76B6AD0E308EE41767FB8E9BDFF00883BE4F4FBFF002C3F2A01DC57FE3EDFEB121C09DBD4FE611D53B3C3C260DF6E9EFF003C319AB1500DB5A8D6AC6CDF88D880407167ABDFF10938D7FDC711EB98A7724977D4C60002C238E359DD44FC30AC82E76D59F67FE1E02906E1DAD071ABAFC87E587718E04EDEA7F3071AC6CA23E1820E04EDEA7F31CF78BFEE381AFF009F67CA0E04EDEA7F31C15ACEEA27D630D67000800333FDA3200161071ABAFC87E5846331B5B59BCDF6F238208DBDE797CFF4C10462A722397CE7E58D9258B9DBCF940C0DC3C63DEFFABE5FA6304B926D030B353683BDFF0057CBF4C20A5BD4D00F1FB46A5293A0FA7D20EF88D9447BBF4C325CD2C43D352C0F9341C09DBD4FE63626A426788CED1D6F31F71C21316695AB12696FB69A43BC3CA4283148DF9DCEB5E5D2B0AD15224907736BF436FBCDAFEB87324D5B6A75773E1EB08E250928500966B53EADB8E5D6E61522AA1485893C324DEDE5BFEEFE7187C491C2A0683CEBE86D6D0FA56E6C924AC17F9EB41E76BF36E557893D16A3294861D4A7822012120C5B9C1F2F4893CCE365E21294BB81F73C9C535D7C637C160F816EA0E97EADB6EE5C9F08B7BB19D22EF693DA4699D1D94053EFE6D9830FB81092A296E89D4542ED36F020F911CA71C5FE26F68060E5772998C262174E261C4052C59DECDE05E1BF69669C2483325A820A12C43548550F5A1AD3D5A3E84BB5B798A3CA72ED22CAD29A7C972BA569B0D98417051B45C848313C6920C0277C710EC5E07F5B3BFD426CB3DECF984CC2760A3C26DB0D686387E6D88EF2628514C5C171527AD407D457768F33BB46AAFAF52565129292AAB45434A4AA088485A504883262FF00AEDE9AC2E0D2AC0042501FBBA0A5DB571FC987FD9CC44E953A584ACA7E6B0E55A79D3C23C43ED37275E9BD63995238DC043EB294910077C4A840023FA8444EE4E39DE33098AC2E294A05411C44EAD7AD4B69F6A8B9F5F763B18676070CA5AF89540A725CD69D1B9B03B5A21AC9719535434A98AA52BF94BE1E3E10B32B49491078C2B844891BE169F998EE38388021245C39A6ADB3C74CC666585C160D454949570FEEA51C07A6AC0D7C1E3DB0FA3E3D9D329D17962BB79D754210F6608074750D4A095B0B48553D639C047178D452B1C690003E13071CB71EBC4E331F351256B51E2F9C970250351C94E1C3E9E71E4BF8BBDAD5CEC28C0E0A6148477826CD0AFF00ADC45D3F2BD022C1AE7531DE6D53AA2A6ADCA87AB1E0A6D4496140A6C89809B2A6C205EDF0117CECDE5AA011C49A06AB0A93ADAFD1C8E4F4F21284DC46314B9CA2B254EE5CD8FF0000B374D23D7253B5B5622980667688113F033EFF004C78E0CC67A927635FA822357ABF8C6AFE159A2FC558E29E1B23C6501039EC6FB5FF0063092945449DEA6DD2A5B9FAC3D41241E5AF2FE291B0656849016B29B192495F43D49C6841208767F7F785E5EBE1F785CC51A5B0A534845544151584A7BBF4E2DE77F59F5C22A965C104BEED41A59DABE118980167D5FED1CBD5F4AC8E17561A3B140492262F71D4F4E9B5C61CCA96B5800034F0A3EF6FC7842600028290DCBCC2848269CC9FEB93F0249DF9EDE677B893938659AA83026BCFA7DCFA40C0B3D48861ADCE12D9512B4003A293CBDFFAF2F5949382510004923EBE3A8AD1BC8C6CE588DEFE1115ACD56180425693C57FB43DFB19FBFADED898C2E5466B7125C8616B1BF8B75A38EB0E30E81A1BEF7BD6BAFBB3D6119AEBD534490B1239F17EA7FDEFD266B0D919268871FF00A7DF8EE75D9DF77CFD22019A7680E3BC27BD1E12A89501327E1E9CFEEC59F05D9B26AA96C0B386FB36D5FB6B0777CFD3F9881667DA2BEDF143FC37BC2A46D6B4FE9F218B1C8ECA099FB500D350DE1F814D2918E02FF7F7E1E7AB188357F69D52D903EB0428CCF8F7DFCE0CFE42062C380EC8238085201234E1B3DF9D7C0F331A9412086E5BF37A4466A3B53A8850EFCDC9895DC472DF7E973E589A95D9094A1FF4D9887A1623621ADA9B96A6B00429ACFAE9E2FEA4F588C661DAB55254909A832267C7681B400679C7EE43F4762D0A149628CEC923D5EBC853A42F2E5A941EAE7705E9AF4AF28655F6AF58524FD60DF9779B7AC91B9FDC9C3C47629240694073236E82BE5E5587694AC0DD46F6A372B7E00E708DCED76B1929E1A851E23FDD3B795EE4ED3CBDE70DB17D8D290C9941F9279DED51A96F4891C3C92B49D4B5697F77E4C5A1DA8BB6FAA640FE793B48E21C88DE7D7A479E20315D8A98A04F766D6E1B79529ADE94AD1996330A482403CC5CBEA473A5BAF3690B1ED06E32A4D3BAAEFDA7C8E2638A3BCE1823C60786373793B75C404EEC54D49E2EE94E2D43AF8066A306671A38786EE95296183925CEC5B5E6D5B7DE2CFD3DDB9E48E1698CCC269E956414D3059924EF2EA6151241B9B6D30311388EC8E2405AA5A4A2616E13C20B35689B568FD68627B058A992AAEE28E2BA1A31A1A369FE2E8CC72DD01DB3E93CC34BE7B47415B97D753F754B5AE1696FE50A5A49E26E65E59716A04C111104918A8636466BD9EC6C9C54954C4CC493DFC90E0625BF6D6825F00BB5DA3A9F65FB408929E098A6B1049763CF42093E25F9478ABDBDFD1F3DAAF65598667A83B3EA7735468AA95B8FA9D692842D968952C2528254F2A0950B09B6DB01D3BB1DF14254B9C893899865E210405495929035B9A59CF3A8A878BE8ED1616700998A09243F7AF5E4C91D408F36F3ACAB30C9730A8A7CC69AA696A92B297296A69DD616DA84820075292A122E403D27618F4A647F127013D2841C44B51200AA83027406AE39D6AD416890C2CF4E264A149140FF00EE38255D520BA4528F7E7A321AA29540B106F0608E7F1DBDC0F3838BBA332C2E6684F76B492B0E450DE86A37A781B8A3484AC22A790D507602E06CCC3CF581152553C46E37BCC721FBEA00368C4762E58C190A019CD2ACE3F8A7A9BC3A565EB9041524A5EDB10DD5AF5F0EADB03E39284F90B88E7FBF74618FEA945E8E0EC7CEAD5F6EF0770B735D9830A7AEB1A5D72786F3BDB6FC3F5C36993BFE5A5A967B79D2DCA306490E49B72FE79C69EF3CBE7FA6102B0BB69D75F01B465324AAC7D3F983BCF2F9FE98D90B2922AC3D9FAC68B41433977F7EFA41DE797CFF004C2BDEFF00DDE9FC4690779E5F3FD3077BFF0077A7F1041DE797CFF4C1DEFF00DDFF00B7F8820EF3CBE7FA61354EDFC2BF602364A789EACD0779E5F3FD31AF7C9F6FF88DBBBE7E9FCC6C439B88F9FEFEEFD4EF93B7D7F1EFE8777CFD3F98D9DE797CFF004C1DF27DBFE20EEF9FA7F31A1E74880047BFF7F77BF1BA5616682DD75DEDE1D3946C257158DB5D23477CAFDC7E584D6B147A0D2F58C19453737E5FCC1DF2BF71F961B4D582181A8F7D6DBFF9C777CFD3F983BE57EE3F2C342B0297DF97A467BA3CFF00F1FE63053E411336BDA3DDC87BF7F9DD25AC121D85FD9F7B987B87965AFA736E5ADECFA6C291BD1526264F283FAC18BDB96DD670EE5A81D6A40F41F6DA1ACF0CA524835A00DE1D7DD0DE1E32EAB090EA9C850013E76F416DB7999185E6CE4CB492685A8747E5E8C7C7A9232E1398F01351F5E54EA75B0DCB830EB398AFB9694942B69046E4C6FB72F4B1D84E2AB9866C25950E2B3EA69F5B830BCCC28C2A4A8A5D22E35D4BD3AB51A879C7AF1F46476448CBB506AAED873A60AE9F45B0C8A05BA8FE5BEACC987183DC2D4385CE051495168AB84DCF0918F2C7C5CCF138AC6617042710A9F32810496E1525DD999F623560E6392F6F730E14A422812E082DAB114D7D1AB1DC8ED0F3DA8CC01AA5A897C3D505D24C12DADD25B1E8106398F9E3A176170A0612495A43290928A6C056803BE963778E32B9C66CCBBD89AB35C6BA077F60C74B35CB08FAE665560F829928537D09524CDCF9CDA37F3C774CA25F1CB94959AA8B35ACD46B7BE7164C94913D079BF4ADAF5B1D9ED1E52FB4464FDFE7C3374B453F5D5A8A951013DCC004AA204EC27DD7225AF6B72A97230C6680012851240D838ADAD4D3C418F4B763330E094002FC3C20279F21CA9A56269EC6DECF755DB57692DE719BD3B8D688D34EB1519F5538DA836613DE52A5B240539C4E37C2AEECAB732236F36AF1789C4632749940A8A14A4F059DC900BEE967E64342DF123B649C932D01C0C4625244B5F13997C20713A6B705803F68F6FB5867B414D449A4D30DB6C65140CB3454397A385A6D80D212C38E0042412E1471EC08E66716DC932698A4A3BF509D36A56BE009245481A03C2081AF8C790B3BCED59A2D4A2A2788927E67A9F0346B68DBB88A7EBDFA948A6A075E2E97B8D5C615207F5904824089237D85F7C749CBB048C3CB0A609006C03F2E5E772358AB8C331E337B7315BF95A8FE74FA0166912C8492424889EA46DB7BBF1EB8F9E17600F100F4666EA7C5EF5F288500A8B0ADE8D7F1B53F8BC735110DF88CDE4498DCFF00BFC6C70BA1249568295677A7BD7A6B0F91FB46DAF99F7E3CE1BDCA869BB2943CC4EC3CF95F0E048E20DC26F7624BF4635E45AF4BC2D2F5F0FBC3555674C5288E3038A440316E460413F779E1EC8CB5534FED25ABE760CFA3F37B429107CDB52D3F8BF9824837B4CFC763F9E2730D92A8B320D69635E9A75EAF04416B75630DECE01320F8A36EB16F96DB6E062C586C8944370D9AC1BD9176822B7CEF5835E387881B59663DE27E079F4838B1617B3A5407FB64EBA8FC0D18736171522A9CE75F268882878A839C5278F6B7207CE2E2201F8DA32DECD93FD8C7667B6946D3C2EE758752120EC0EFE6FE240F467115A671DA72A15E3277FEAB917E9BDE79F2EA316AC1F66C3B775E36D6BA1FF3CA1D7766EF417A796BEFC62B2CDFB4B528A4059B49B28DE3AF98B1DBAFA0B7E03B3A97004B1B540E4581F7B883BBE7E9FCC40B31ED21609FE6AA6FCF96DB93B0F889B8E58B7617B372D828A45A800B026DF6A3F283BBD5EDCB7F1880E6BDA22D6A49E3322608519F7FC7D368B62C382ECECB485120076D07261EFCA1D4990662598902DB68EFD6D5B5DF588A54F682E03016444C9E237F74DEFE9CBAE25E5E4726AE0519E801D7EBF5BC3B4607899C585E94D2BCB93B1D285E2335FAFDC25242D5378854FE16F8F94C61F4ACA248E2F901B7BFB5A9CED0E118124B3160EC451FA5DDB5F1D5CC313DDA0BB1F6951E6B2239CF3E43EEE7B3E4E572831E00FD03F88F62BE6E9182A5BA51ECDA86EB4B6DAC256FB4170714AD5D6E6639DB7EBE97E507189995C851AA1236A8F1E5B5FF00C49613046A120B16D0D3C079DEBD6315F684B93C2A23A78B7882791F593D37C6BFE8586994084316D05CBF5FA91E10B4CCAD4BA10C3A16D8B57CC5DEED0A287B45524A8A89266DC47ADA0123E406D1CE70CB13D97C3AC1696914E87C75E5ABD9A239791A89A21C7420F236D1B6D46D49053F692E0825C36123C4444C6D1D3AF2F7C62BD8AECBC9493FED8A93A0B073BEFD234FF465A2E867DF939DBDF9C58DA1FB69CFF21CE69F30A3CC5C6F2F60CD7B4A76CE050F04052A41046C07AE39B76B3B12314852E54BA804D12FE4E29F810DE7E171185FFA61418559FC3E97F5DBD79F679EDE721ED4B4E2F2B5BB4EBAFA1427FCBD4703BDEF112A52781C0526C0C883B89F2F2C76BBB3188CA718BC4A50A12D45426F0F12598302E19DC81EA4BBC664637168042CA9C7ED279173E82A5FC6C6211ED05EC5FD8EF6F34B53A86A6869B27D62FB6E062B2999534961D424A01532C8432AE30126E39CDC9C55B29ED563F2E9B2A4714D0994AF91456A20825ECEF4A569B522F3907686761DD066B22614858531B17A136F4D2D1F3FBDBE7B16F69DD8B66B5B555197D4E6FA790E38B6736A740290D4920965A0B518102FE64ED8F55FC3EEDF2E709427CF73F2D0A80A0E4588B5DAFB4769C97B41829825FEC4B0058904F3E95DCEF7D7A8A288BEB7FBB2A6CD3102A4B80B6A76491C3C0B852784C8902FF7F72C56792B1F2E5F7530120025883B0D2FE4FD0459B1F8A938896832F84D3420B16E54BDB61CA836B596BEF254BA4506823ED490663A027D4C6E27E0C462D540FF00C5B9357CB66A444A4A6BC49E2F13F57A587AC25356DB84B1C10F3261D5DC8513B1DA3972DF0A8C4059E151A8F7A795F96B0290400480CAF6C418E7892398FBFEEC3842B436D3DF38D638E34FEFF7FBF8E09EAE1A055C69A8A751CAFBC2339C800549F4B17F4838D3D7E47F2C35756E7CCC36E156C63052A6209F3DC60E23B9F38D822EEE36A8FE63193D4FC4E073B9F331B700DCFA7E23893BCDFAE14429C313516AD5AFF98510002075BF898E64F53F138DE178D88544C920F52795B9E08233E3FF0057FEEFD70411A9C50312A077DCFA6364AB85E8EF046B91D47C4632A5B8666DF58C100D0C71C69EBF238653161CF0BB9B9FB0F7D231C097FB69F9F58389279FE1F7E1BA95C2D4778DA3153894F39BFEFD7EEF3C204804026A6D12B8295C52D4793F3D5AAFB6FE5025C4AA6F11D7A47FBF21E587D2940DCD2846BE1F6E4622B152DA6B58F139A795B7F1F1854CBCA553BECB07F9CE29A09DA7838877963D1336E97E8434CD279972CB280614DDF6D77F41B44FE57212521C3961CEFE96BF90DE2CAD11D9E56EB3D6BA7B4BE9569CAB733CA965B7D2D712BB94214D97CA8DF8470951B91B475C714ED3674B9054429E8B7AD281CF8916B78C42F69B132B05879B3967FE98A21DB89C5F9333B7F88FA71D1BA1F2EEC7BB2ED2DD9BE5DDD8464D445DAA7109E15D43B5A94542D2FA8789D2DB8A504F78A5445A0638263702ACFB30398CBE2577B31248539E012D4051D99DAA68EE5DE3CB9DA7CE5599E2169E30424B30346A016D19A95B13D280ED12B920BBC3037DADFB8E5F9E3D25D8BC29461A44B218A529141B51C7A73D0EB15A929E250043F3A8FE3AF5E74E9EEB4A9A9A961686CFF97593F58322641F04F337FDEF3DA3072132C21668CC40B6C4DBD0B3F8D22C980024A9045DEDD341A1DF5ADB9F5AB3EECC737ED773ACAF43E594AA76B5DA81F5D7D081C2DB0161C27880013FCA0660824CC620BB699949565D352A58480929248A82CD6A12E6836D869D3320ED18CBA6226B717082C97672CC5DDEDEB4A47A59A6F46699EC07B39A3D21A6BB953ED530FE24EB690971C7970E14B8BBA97C2A2A0029460898031C3723CA5588C54C9BDD90952DD2752E4FA1BB18E71F13B3D9D9BCD413314A751700BA458000025B4D2BE51535766C336A779E71C2D8E2528A42A2E144C5A01B827F738EAF80CAD322585283300EE0FDF6D869AC50B01835291C641552A1BC286A5CD6ADF688B5255E699857D0E539334E543F50E16D4B00A8A1054028F1198F099EBE9BE13CC7304619052080002545C0B57EFEC98DF1BFEC8370C0B1EA79EF1F44D599B06F8A1409B990403F01CBDC7A63C0F2704EDF2D3A1A7DF5BD3CED570160964B0B33B9D6EE6F5D0D623CFEA0201957853360A173EA7A749F81C49CACBF8BFB0BAA83A52A08FB3E95AC3A9648A58A7EEFEDE2119BEAA5B6550E0000330AF97BA44ED89595969424012DC9D83F37B86FA1BEA216439249E515C66DABDE723F9974F15F8C017FC081F941C59F28CA8A93C4B450B0A8634B796AC2FAB43897AD36FF001EFF00115D66BAA9CF12BBEB9FF501E5B4CE2E584CA40E1025D68CE9D5EDE15BB7A38522B7CE756BA8E187C5C13F6803378E7B9FBA05CED68CBF264A81E2410A1A33F859AD6E45B4822ABCF357BDE287A08B9F1CEFD2FF00BBF5BDBB059225212D2DC3683AD0FB7E71B702B6FA7BD62A9CE75629453C6ECFDAE63EE9B7BF7E569C5A72FC88DC4B6DA9CEA3EA2FB50438929A07A359E807F80DE25F578ACF39D5890170B060C9F1794DA0DA3AF2B62C786C9549209960100B16AF3EBF53AD1E1D3278801CDEB4B1D5F9457F5BAA42B7546FB99F5E73E5EE3CF13D83CA8A6BC35A0B0F7616D3D236128AB88814A01CBAD7CAB110CC352A49278FDD3B41161F1B462770F8166052DCF98661AD799D6D1B270D3174483D4317EB703EBADAD0FABD42924CAC9898FC7F193D3D6EF84B12EC9B5B407C7A537E91399760560FCE926C6FD5E8DF588ED4EA049264C0E809F95EC363E5EB8CFCC5E9C3E47EDB0F11B44E8C18FF00800598354B02FBB56F6EB0C5539EB64595224DCF53B6DFB163E8BCA510DCB51CEFF78729C0A890C9A0B8E5F4F426196A33C499124474371D2F3B1BF3FC70E78D2039142D473714FBDB9D2242565E6C12E59C6A1BD2DA1DBCA10AB3D42448541E927EFE7D7E1E9889CC3126590516AFBE836A6B68792302A4129281522A40617D06E7D884ABCFD06FC5D058FADBAFFB88383098E5310A074151D37D696894465E1403A59DF4E85DAAF4BF95291827512533E2DE2F226C67A72F8EFE5896FD5CB2E4ABC1DC96DFECFF00430F539525491F2D1F6E9A31F4DFC21C58D4C9060AC587F76FF1E436F7F9E186266CB268A07AD3DD8D1A8FCA345E512D4E38452C680FA5AAC34B9B80F0A1DD48B7CB6CB5545A2E1E2212AFB7C3732418100409DF60271B60B0586C64A9826F0BB7F7355DFE82953E1568565F6764E2524109046E2F76F5DDABB3B45E1D90F6D59AF65FAE74C674CD538DE5B515496AA9A4AC94A8712199589200054771CE4440C716EDF76330D8D973BBB48527866592E4163C24B6DBFE1A2BB99F65F825CE32D20AD0C50281F7A1342351A57768FA23D3FAEE8F50E52C67678174599D1D2B9421A70143CA0CA0BA12EA0C24A566E2649B6FB78D732ECC8C1CF5492C67485AFBF510C500A89438B971CA976D4728CD26E232F5A9402801448E86B5D1B5EB09F3BA4A0D4794D56599AD15366F4952853672D7D0D4A12A0413DFB8951E7C5BDEC0488C2580993707353370AB5226CB219692A2363F2DAC7D0F8B7C376DF1386F912B5914043B352CEEDA72D6D1E457B4D7B026579A22AB56F66B1455680FBF9A652CA09EE54428B612A5101CE2B93C22D231DCBB19DB1E2C47E9B315AA48584893314494CD61F35E8963E7E11DBFE1F76B55994B28C54E60867E321C397B93F6A18F1933ED3FA9346E775392EA262A68D54EE38D82E34B4F1C122764F9441FC31D7E4665865DA7A58B310417717BB01D2ED1D725E270B8948326625445569E214DB5AF3E66CD0C2BB2D4509841D9569579C1B89F3E989595325AFE64A817A82FD5CFDABADA14490A6E1ABBF266BDF6A3F3318952809260752001F18C48A1429C25C1201FF27AFE6374A16A0FC247DA39E251124C03B18DF69823A0336C693663060A7DC6EEFD5BA78D1A1B4F42812E0823F87FA3FBA16FEF3F03F9E1AF79CBD7F886D19A386F2E7C41FC4E0EF397AFF118248B07F168CFC1FDE3E1FAE0EF397AFF00118757FC7FF708E0C5A140CCFCB0ACB983E67F96D57EBF5F778712412412185697F17B681B9BED0614EF11FF00210EA30592220F5FC3005A4D8BC11871ABAFC87E58CF1A77F43F88235B8A55AFD790FCB194CC4837EB4351FC7DE0626C1E35F1ABAFC87E58D57352A71C4035BF1BE8C5E33C2AD8C1C6AEBF21F961B19A80402475766E55FBB46785550D7BD469071ABAFC87E586E66A058BF4FF00107028D924F484EFB91C337DE4C7E42DCE7D3E1ACBF98B8AB5CF33FE6F13B9620095338F67B59B938AB8F1BF5E1A58292A83C3C88048313E5FB8C3DC3AD0A04715B516D4D9FD4DB7DE131692A9C78773EA691CD3D6770F21C68F12B8836122EA5170F0080249B9B002FEEC577B418EC361A5AC4E9E94382CE41AED7A7589AC03C994A2B7400E5CD2EFE4C1EBF48F7A3E8E6F6776345699A8EDAF545377CBCD508569C66ADAE175954A997D496DC1C6012B064A40D88240BF99FB5D9B4BC662266130AB3314E4AD601646A2B6214C4339357BC719F8979E61D1226265CE495F0AC04822E6FAD68EDBDF471DECD635D54CCBEF39C6A7F89492140C22E52090792488BFA011675D8DC377C959989F9924740E59DB9D39EBBC799F2B9B37158A9EA98E47112092599F4DF537D183523A8DDA1E624878070126E52140F3F2248DE31D8F2859C36265A00F95C7CDA50694B8DF6F4B3484CB04592CFE049A5FED58EACE66E56E6598D3E5F4E14E3550B536F250389416AF0B648124788CC8F59C75D562F0E8C119A5680A12DDC903FB7AEFE3A43C54E4A40F983FAB83B0A57AD393476BBB3FD2947D96E987B31A869B5EB7CC9B0A69E570F1B6D90AE6652921856DCE23CB1C4738C5E2339C6224CB0A5E082D42600ED34834622A38540EB51084DCC57292784B91600DA8F7E7CEB7E462ACD4DABB8D150D3CF29FA97D64BFE22A83C44F224589D85A05B962FF009065089694AD6809A07040B01D03D1EBFE0454C4AF309892B06849AFF9F16D7A308AB4E64F543AD51D38528BEE04F0A012A32A8FB224989BDA7CF699EC7AB0F8794A485A41092087A58D05583EE49E82D137879587912C82B4A484EB4F4E7AFDEE3B71A0324CA7B39C85DD4D9C3487330A9642E8D2EC071B54113C06542E41F1016EA231C4BB478B998C98B9387515842889894870E5CA471015E6DCDF58A8E72A0E4CB75036367AD2951B1F0E71EA36659C3664717226EA36B409F3B728F80C79D70B8304FED776B8DB6AB0A3176A7A4457027D9B7BE6F107CCB3B4240FE6753BC7A73E53EEC58F099792DF2D000006A907EA6F190902C22B7CE73C412A973ACCA8C7BBAD86E39FA462CB85CBC10029034FEDBBF852E06BCF9662B7CD73B6FF00E6708BDF889B6FB6E4F945FE3369CBF2F649E14072DE7B6D7E5CBA64122D1566779F24154BA45CFF005284EFE7602FCA716FC1E0520A4140AB68C4B7416FE3785E2AACE73B4A88FE612255038CDA796FEF91E96DB170C065E9FF008245051ACDFE75FB42E00141158E739B83C443A7983E237F2EA4F5E5E9B62DF82C024B3A053560341EB6A783C390C34A569FE7D8D22B8CCB34E22005A8913FD47DFD63A927DD6C5A3078364FED1A5C0AEC341B523632F8806A1DF6AF8546B6B59E21398E668F102A207A93E47FDF9CDE263139230C90015005AE1AF571A3736B885A561D45882E353A9D0F97D1A2179866215C30AB09E7FBFBA0DC937C3F972E5D59228D6E4FF4899C3616CC1DFCC56C2F7BF880F678BD556A493E283CAE679F39E63D3A838708968AFCAECD7FC79FE22730F82040743125EBC98F2634B7DA2355B5A2D04F393227ADA39F2F59F5C131080C486BD757F7FCEB12F84C210E079816F5B753E42D1CAAAD4927C4444C5FCAC664721333CF081084A41201B87B52A3EECDAE9AC4A4BC3970C97DE82BF5D343AD7AB2B95A0920A8DB7827693EF883B911E778C375000B00DAEB57DE24E4E1C16743BEC2BF47DB7E621ADFAC499B9F333063CFE07CF7B73C36529CFD044949C20D45069F9FC56D48697AB120024DEFCC47BE08F3933C8F48C359C0177AB3372B7958F9F3112D86C1214DF2D587570D4E74E8FF00442E5724EE7AECAB7C41836F8C0DF0D432052A0BB301F514F7E4F0E0827467AFED3F47D377F268D06B5226E62FFD5D3ADBEE9FC7092A72C502BC341CBED00904101E96A066F0DF95631FAFA3FBA0F3F10FFB8619AA6AC9352DF5EBEF946E306B0EC0B1F3FA1F6F7731C8CC9C410A6CA890A489E29DCC6F262660C1F29BE1D499D3112661130A69A7FF00AB4E5BB7285E4C8293B2B6D4EAD7D6C29E178795E7EF32FD352125448E2124CA4C05483CAF04411E5388BC2AC4E4E204E50997FDC1C6BBB8BEBB6B18C6E0FBC94A253522A6DB8BEBAED6D35F7B3D853B48675CF616F69872A0AEBF43A9A04AD654F2BEBF54560152CF11802D72074DA3C87F16B048CBB3999899008566055DE84BB204A0424DDAA7616F5E19DB0CB9284CC1DD8643906D777D8EB4D43DC388EE73F53DD17521C238D2D917327853248827DF706200E58E7FD9A946609CA5FCC0115218D497FBB694B6B1C52661889A43317A0F1AE8CCCF7F5668462B5AA94BE92E250EBC9E14154149004282C2BC2AB75F4B5862CAA966594841E14A4BB815A9A310C7AB1357A6D3B976327E048EE96657135412051BD5998E9568E977B41FB33E8FED432FACA9551B0CEA1085A9AAC6DAEEC2DC8241212128E82E637DE3172CAB1B3414A16B570822BC44B5294EAD6148EA9D9BCEF1699A850C42810DC4E7881D0821EA2D7E54263C32ED47B1DD57D93E78E51E7D46F399754BAE8A2A94A49404B64CCF76088129E7BD84CE3A9E513E624242A605022F4A027ABF9B78D1FBC6579948C6C994A03BB9881F3077EF1D83F2D49FADE295A97EAC3C94A877F9783B240494FAC4AAC79CFE38B74B99C49705F7B78728B8E1A6CB5212A291C400047A3697BFB10B6A54A0D30524160825A47347F749DCC99DC635984D1CD4DC56BF6D3AFD90C7250B4860C79ED616F523D211779E5F3FD309C45F723979983BCF2F9FE9820EE472F330779E5F3FD3041DC8E5E660EF0F43F1FD3015F06F5E434EBD616932921DC0F5FADF783BCF2F9FE98C77C79F9085F813B7A9FCC6D6D60CCC8F98FF007C67BDE6DE03EC0C1C09DBD4FE636F1A7AFC8FE583BDFF00BBD3F883813B7A9FCC705606D7F97E18D173096657A7F1070276F5309DC5EF3D2E768F86FF00BDF6C20B5AC10CA6E97F1FB78C1C09DBD4FE6908DC73602FD3F7CBD39DCE1098B5503B3BBB787BFA343E4A10003C21EF563EF96B1A7BCF4DFAFCBD7F71867DE2FF00E461544B4D5C3F5F18C915612B4B0A00A5E07895BF08489B1DC7388F2EA313D96AD3DC4E2B2EC9BF817EBAF421A821C7767BA584001F9B6FCE8E5BCABCD653D638D52D496480C01146540492490F44DC93CA7D4621F058D299D89055F213F292435C92D7F5D7AC43BCA973E519A38A73FF00BA384B00FF002B814A0A3B51E3B8DEC2FECA99AFB41F699475F9952BAC68FC96A13575EFB895772BEEC77E80788A64171B22C48B99118E09F16331C415BCA9EA425D99277236BF4FF10876B73C9383CB664B90532D66529D8D5DAE37F5BB347D2566ACE459464747439486D8A2D3B4EDD232C3490DB4A84A5824348E149BA249E1266E2F3344ECDCB993CB4E05666A5C2D42CC28F7771D4D58E823C2FDA2CCF158DCCA6056215313DE2800E5AA4EE49F7B33F5DF54E6EB8AC696A5292903EA4493BA812E45CEC771CA04473EABD97C0F77317F2808243B01536FAD35DE25B0525326425412028A4540BBDDD869E1CEAF1D4BD4AA79CAD577854E3AEAF8384289B1302C081CC63A2CB97C3502BEA1ECDAD7946B3A62D36253F97DF5BDAD6BC4FF0046E87C974851D46AECDD095D654252BA143838B8080428F0F885ED123716DC6196267E2B153C60A54C5140FF00ACC4D033A40635714A7A43513660209516FEDBD77E5E3466F3AFB5BEBDABAAAB5B8AAA4F0BD2869A04029481C205B6111B798E47172C97279328213DD5989E20EFABD5CDFC9CC399438CBABE635777018FF9B7E628DA8CD5FA6A9A879F052144428F8F88AB6481B9E298117BCDB9DA31F3118390C964324D2CE4793EDE35AB449A0A254B53258B3123EA29A79DB578EC5F62FA169DA655DA1EA767B9A0482ACAA89E07894E5D1C7C2405D9CE1500A4911B5B1C6B3CCD2762710BC2C89C5D4A214A497084ED7209507E8F6D62B3996216569E0511C2EE428B2AA34D18D2C1C72BA5ED4B582AB2A4B752F0352DF185F01E068B51FC901B443638500030395E0EF25906070E129946582054F11E2249A92497275678DF2C96AC4CC1DEFCCEC2D7DA9A7BAB47A7398E70F193736EBBF9C733EA71C070F80424B82E36236A353EACF488A880E6F9CB8024827C455CEC4FEB6FC37B59705824A883D2B60343D6C7AF8411586759D3A4AE144EF107D79DBAFCB16591854A00702D717DB4E9FE5E8456B9A674F447113B9224FDFF00B988E718B3E57864872A0030F1F3DF716A1DA08ABF3CCED7E205666F249BC91B7975361E87168C2E141F9A805399B8F5FC5E1C0B0D22B4AFCDDC528CA8AB7BFCBA1E7BC7C3171CBF0A1D23CDC374EA36FB5E1C457B9CE6AE78BC44133CF9413E9713B47A8BE2E183C325213C4028D6835DFC052DA6F0E694F567AF2AFD6D5B30AC0AAF3270932A3B9B5F793E5B5C6DCBAEE6691204A161A786DF6AECDCE24B0B28299D2C28EE5F99DEFF00E221D99662ABC1379FDFEF97BB0BA789C7FC6AF67D1BE8DB8D1844E61F0A82E05D2CE5ACFB575B797488ABB5CB502788DBD4F9003CAFD473F52E258357B166F5FBBFA44E61B0813C2281CD9BD7F00F8F363AAAC549B9136206DF21E7D37E4230E25EBE1F789B918349BD5FDEFCBEBBD63B5B58A004DF7D89E73F8FBAFB6E71ACE7E17D1EBE9F8898C3E112970430A5BC1B9F2209D22355758A13722D37BF5F311BDFD6D866B24853F2AEFF008689195844BBD850F9FE34DACED76572B172649E7FED37EB1CAD6EB86EB511E3AD0337F1D22570F84492C19C5E9BF93D18E8DF46B7AAD706E4F99BFEEE778DE2791C332A7B519EAFEED5F331232B09562001FDC47E2A3D37F16A76B166209833FEFEF9E7C8FA0084F3ADDE9D29E147B5BAD624B0F87482DD34D6A7ECC2D4840BAC50E7E637FBF7FDDB0CD4585013BEDFC7AFD8B93246C0F8FE77FF00309CD5B9D499EBFBBE1B295C2D4778D3B87A801B4A0E9BC71F5959DC7C0C7E1FBDEF11868A5851F95C0AEA7A7DA36EE696F17FE5A394E6A9A675A6D6990E104C9FED20F4EBEFEB6B1CA56384D6A4100877F3B4389785E22549B25B89CEE5A9E76630B9FCF1B72AEAAA026F4C1A4A4F4E301260F381F08C3196BEED6B06EA2C696B8F56FE443D9B81FF00648201E204A74A01E8F53FC523D2BFA35BB42A9A3ED79DD089528D26B3656E38893C3396D2B8F24F0DFF00A86F1EFDB1E68F8D5FED6265B31EF2CCDA33B120DF61B3B35B91F6DB2CE3C0CB9894022571F78453767A024F87D80F65AA3345BC8A9784FF0025F2D4F203BC2D816E97001F2BE39B766E58972C922843B7A9DFABBD19E9531E75C5E1409CB61AB721EC6C776A421CD1EA7A65B2CD538A692B0141692641226D11249B7A62D2A962600B48D6A0D486A539D397DE22F184482962ED6E56A6B7BD296686CCCF35A814BF5653519790422B090547CF8638F7B46D3D4E24F0321226898872B49A2743B3E9D4B1D0522C790E3A624A4034357B7997B5AA0F8C50FDA2F679A635E64EF506A0A269E67BB7050D52920AC29625644026CA20448C5D7018B9D2672552C711769D29C86164D5E828FB73D23B6F67F305B25894B70B58B9E7F4FB3B478BDDB876059AF66B9B55D6E5090F644E38B500784008DC40512AE768131E713D0B0B39D20A4B12016726BB5437D368EA981C72D68055FB8332874D68E695AFDC47565F0E25454567854480DFF6116313D4CED874B2EC742EDE7FE2260CC33D22E08A13BFAF43FCC2793D4FC4E348D7BBE7E9FCC127A9F89C10777CFD3F9824F53F13820EEF9FA7F31CF12873FC7EFC11B253C2F577F7BC1C6AEBF21F9608DA3636A55EFD3A79E0823671ABAFC87E58208E0ACC1936E76FC8608212AD66E67D07EFCBF7CB092EE3A7BF6FFC9089D5ED373CC7B87945B084CD3C7ED0F93FB4468EF0F41FA7EF9FCB0CE1697AF87DE32EF9A292D287F39653DD1BEC3EDFA0E107F330061EC99A65C998016241A72A8FE3A9E6625B0D2C2A5AA81D85478B136D5A96FB5BBD8FF65B9C76D1AFF21D01A7C91F5EAA6C344708E26D252E544F14720A1731EF99A066B982B0489F3662F825A41516E4F76E61ACCE763152CDF1A8CB7BC9C5026CD5823859B85835D8D4695B8BD23EA3BB30ECA329F679D0995E89D354CD53E6E9A563F8F54A10038A52909704AA24C82B1E156C6D36C70ECDB1CBED04F5E317F3617888C356DC2785742C4B91AF3F0F35F6DFB5335026C9E3539E20456C5DBC0023C2ECC2346AFCD29DC5B6DE5CB3F554A54AABB93C4B899337FB5C5E5E800C5A3B35844210AF943900696736AD1ABE768E13865FEB71A56AD5679EFAFAEF4B168EBBEAFCECB74E16A324F1269CED24920CEFCF99EB8EAB91E1021D40073566F3FB8BDE3A409625E1D054588143BBB303D2E5AE2C6231A474F36E29FCFB3B4F1B490A71B045844C6DE839183169C486366AD2A1270DFF0055640E96777BB8B546B1173C025459C01FB7C3466A8FB08AC35EF69CA0FD665A904D123C14C018080278AC049B89369BF3C59727CA6505214AACD5B152CBD48D2BCE97AB54E911FF0032A610372E0B7E69C9C9D7668EB56679C3150B5666FD4AF89B51286A1504A8909E703CCC6F36C741C3E01329085B86E9771B796AF1278595354A1292975173C2E03B03F40C6CE79C5F9D88F6655FAFAA9DD5FA9804E89CA54D3956490429464538213FCC82F2520900FB86397FC46CF93972A4E0A59271789E21264DB88062B3C4681857573477A95F1330A2539D010B5731403F9E51716BCD5AE53D4AE9A8DB0CE5D4AD7759751A2020B696F84ACC40160177124C9DE71CEB08927854A24CC51F994CC5CD5BC2D7D3668A8E2141732D47A5F91B73B56DE71D1BD55AADEA9CC2B180F29D430A90E99F171924A6F061311E62F18BE64E966A1040AF31E5E0E6D5A6F7EECF6010532A610FC676B358D29F4B47CB3E3F3111F6BE0C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C1041820830411FFD9, '1', '2021-10-06 01:15:47', '1', '2021-10-06 01:15:47', b'0', 0); -INSERT INTO `inf_file` VALUES ('add5ec1891a7d97d2cc1d60847e16294.jpg', NULL, 0xFFD8FFE000104A46494600010101006400640000FFDB00840006040506050406060506070706080A100A0A09090A140E0F0C1017141818171416161A1D251F1A1B231C1616202C20232627292A29191F2D302D283025282928010707070A080A130A0A13281A161A2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828FFC200110800EC00EC03012200021101031101FFC4001C0001000105010100000000000000000000000701020405060308FFDA0008010100000000FA14000707A3E3F659B5F2B3CB1B171B57BAFA2C000BE1ED8731AFC752DF3F2F2EF249DF79D0000A465CD59E5ACA5BE7B09BB71441BBB943DC0017447C95DB0D662E4FD0192237F3E17E8600039B8AF556E579647D0B60807A3DA49368003D7E7AC1A5B678CA3255081A4AEBC0007AFCF5834C6E8BA3DDF756902CE39200034908796C661E82C04073E003D755A4B2FC9F48A34CFA172404152C6F415C4E175B9BB879F8EAB41CEF792A807CF1B1903B7BADA5DC0737D47ADCB3CFCBCE3FD2CCBDB807CE35CAF5E8B3F0757D0FBF1BE7DD655B65965BF384B9397B80F9C6A2EDAF577F05A0F3D9499958BACF4E7F41D0654E168118657B59A8E2E43DD71B31FC73ED26EE33FB0E939E8FB135FEFBA9528007159783CAD981B8C5DDC9596A5231D6E17173476200BE26D8351AFCEB33FBED077DABE2FCFB6DB59CE463365A018B156E4A3CB7DDBC65CDE3EDF71259C945B3D7900725CFFB554C0EA3B769E32BEC92F794A4711EEE3BDEBAC0380C657CB7FD6E50F3D4E266EE0C2E2F9DE73CA6FD90237B7CB7FDB5F554B6911C8BB8A948CB039CE5E79E94230B3B6E98A82945453C225BB87D44E3DA158BB77DF56A00A1452DE6A2DB397D6FD5C562696B215002DAE1E4D29CCF8471C9DBF4E9EB03CF952A028A539DE8296E1C7DD3C2DABFA80BA3690760A5C28514A626A37F4A523DC2D7E9A772B1CC9B7733B2DA2828A2DB628EAFABA523DD1D29302BC6767EE88E46DB1414A29486A1A9CF8E99E2BD91303CF98ECE8897A9EC5428A294A70B04E5E279751D613038FECBD5485BA5911428A514530780D5E9B7B62930B93ED2D6A222EA64A28A514514ADB444FE56D7FFC4001B01000105010100000000000000000000000001020304050607FFDA0008010210000000F3600075E70AD558EA46005B9DCE33E1B7367000694AC32CD3CC00034E58A1A69A59A125A512766681ACD81C9A194D4F44E2B280D94750E8BD1383E7AE6F60E4D500BB0F4BB3CCEBAC540E7500BD5CB7D135B33E0E769342FA6DDE51AAADE56CD084D7DE780014F9CBF8EFEA2E800346D4CDC87F57654104628C38ED9DE6B841064EB5978DEAAEB155104115A7FFC4001A010002030101000000000000000000000000040102030506FFDA0008010310000000EB00043FBC939A35CE4003A76164A7AFC9800061CB22B8CAC0006EDA78C4B0B845F5B8C23981D3533A3CA742D7F0DDCD006A346783E07D9FA05BCFF7A92016EAF9EE0FABE6CE8DD4901AE84ADC1E8F5BCDE0CEC483FA72520BD62DE8D54E46B8F500019F429A318AC001259BEAF3215C8009BC1B5F4C55D2B5924B9560D55CB5AD2490B4EB3FFFC400451000010302020604090A050403010000000102030400110512061321314151203261711014222330425281D11524333440537291A1B116436292C16382E1F0357383A2FFDA0008010100013F01F4FC6B4931051908C2222ACB706690B1EAA397BE9E719811335B2B68D800AF9C4D735CB6D6A56E48036229BC3DF575B223BCDE861A84ED71E3F95AB53091D672FF00EEA270F1EA66FCE8C8863AB187F68A335A1D58C8FD2953F932DD2A628FF2DAFEDA3249FE5B5FD94F2D9BF94D3415FD236D4518C6ABE66D627A9E194AADF6047585622C3B866352E54C49533297E43C3684F61E54E105ACC946B788038D09B2E495063220A77802EAFD696EBF721C79DBF2BDABBC93DFD0346AF750424152D5B9291727DD587E8ACA9090B9EE888DFDDA76AFE02B0FC270FC3BEAB1939FEF17E52BF3AD62A9195C405B4B4B883B8A4DFEC0B4A1D694D3C80B6D42C526B12C39583FCE226672028F96DEF2DF68ECAC4594AB24A64EC3B7327876D22521D4E5988CDFEA246DA7A294A758C9D635CC784D1AC330F918A492D46B04A7E91D3B91F13D9585619170A6B2C74E678F59E575954493BFC3F25BB11CD6E1129C8CBF66FE49A8BA55221B89631D8BB0EC0F37C6A2BEC4C643B0DD4BAD9E47D38B1052B014856C20D488BF26622B84ADB11F1999278734D3CD969D520F034CBCB65576D56A25895BECCBDCFD534F34B65595C16FF346A0C473109CDC465594A815297ECA79D448CCC18A88D15395B4FEA799E88A75B43AD943A90B41DE0D3C1FD1F9499905CB344D8A4EEEEA0A0E34DB805B3A42BD3E92C432F075A9B1E7E3F9D47BAA7283A961F4FF00311E14485253915671BF655FE3952D0082B64E64F11C53DF583CD187630C495FD09F34E7603C6962C766E3D1462130904EA7F0E534EBB20A9A8F159D74B705F28DC91CCD46D185BEE25EC6A46B2DB7528DD4A3BAC2C06C03D3B7B4E53B8EC34B4EA98531F72FAD1E1357208209046E229C3981CC37EF238FBAB43315D73670D92BBBAD8BB2A3EB2797BBA3872017F32BAA819AB4559221393DC1E7652AE3B10370FB0B5D7152961C7A42C6E72438A1DD7B785C7128EB1DBC071350B02C5268CC969319BF69EDE7DD4DE8728FD63123DCDA2B0DD178906735284A7DC5B66E01B513737E824EAF0A98E0DE465FFBF9D436F5387C4680B656923F4FB0E3738C083E6B6CA7CEAD94F6F3F752C25166D06E940CA0F3EDF061B02462920B516C9423E91E56E4F6769AC2F0785860BB2DEB1FE2F39B5468A89DFD37ADF213DF8BFC8A1B59688DD907A20835227C18BF5898CA7B335E97A478524D92EBAE7E06C9AFE228C7A90A72FF00F9D0C7D9E302701FFAFF00E6938EE1C4F9C53CCF6BAD102A563586C58FAE3290E83D54B67328FBAA6CE7A64A54A90323A5391B6FEE91F13E04A1C79C6D9605DD7559103B6A2456A0446E2C74D9081B7B4F3F43193AF852637150B8AD1E942760CC281BB8D8D5AC768E9EFA992A3416F3CC7D0D0E00EF34EE9148977460F12C3EF9EDD4A87325FF00E47107560FA8DEC151F0B84C7518413CD5B68009EA803BA8D1A34F448EEAB32DA467F680B1FCEA4E1EA4254A64A9CE394EFF00CE92A0ADDDC472AD098E97A5CA9AB17D479A6FBCEF3E899714D38168DE2A338E33255270D7FC5DF59BADA5F51CA87A48CA9496B1465511FF006BD4FCE9BCAEA02D95A5C41E2937ACA7978522FDD5896901538A8B82A75AE8EB3C7AA9A630B0A735F3DC5497CEF2ADD49B0161B055EAF57A2689A346A7E30F78C29A8694D926C5445EF4EC85BEE053A84B723DB1D55F61F8D684048C04A13F4A1D59713C526FC7DDE910FAC2321F2DBF655B4530A61B5E646BE3AB9B2E5A9B9F3B66A31726DC1D40AF95B1C693B04391EEB1A5693632D9F3986B67B81A7B1BC5719CD0C3488ADFF3549BEEE550E3B71590DB42C07EB4FBEDC76CB8F2825239D3FA43B7E6D1CA87359B531A4842AD263651CD06A3496A4B41C616149357ABD5E8D71AC230886BD1790EBA91AE5A5C257C516BD4194BF18650B480D1010A17BDCF3A8921FC2DC131ABAB56723E8FBC4703DF51A435362B72A32B332E0B8F4C1453D524771A87AE7DD09D6B9946D3B69B425B4E540B0A52821254A3648173498F37185AA42595AA3A4F93C8549929662BEEB2DA17A95645051B1BD61AFB38A5D011AB780BE5E75143D86C82E37D5F593ED0A8B25B94C875955D06AF4FBEDB29CCF3894279A8D7CA71782D44730DAAD45F4C98EE884F20B994E5B1DC6B0275E6D9721C8D6A2DD64AB7281A7F4714257993E689BDEFBAA4C96A2CA4B6F1F36F2721ECEDAD1F9FF22622B8EF9F993EADBFD0AE7DD446E236A4EE3E813A1E7F9B89AFFDA9A4E8743DBAD99257EFB57F0861BF7D27FBA95A1F879EA48909F7D3FA21251730A685F24AC5AA6C79B86AAD3D8213EDA77560907E6F9DCD855B4FC29C8A35B649B0B5EB1D516F0C91CFABFAD600DB4CE09112DDB206C7FCD692869CD209EB67E8CBA77568FB4E7CA91CB69E3B7BAB1646469C58DA40D82B0D8A21450D5EEAEB28F6D3697E63C598405D3F48EABAADFC4F6541C1A24539D49D7C8E2EBBB4FBB97827E0F0A68BADA0DBBC1D6FC950AC423488032CE0A7A2DFC99281B53F8870EFAF9D048CA10F208D8A0ACA4D3985096A0E4C514AF8250760158AC44B91EE91D5163DD5A218C2B38C3272AE7F92BE7D94458FA4D2D7C96A261C9EB495E65F6213B6A23EDA59B28D88A724A8BAA523603B2B1B19B0C7EE6DB2FF00AD6172DF430194B8AD572A95804790F1790ACAA3BC54382C4004A7CA739D7D6E50B6D69A55D479AB9504392A408B1CD96A175AFEED3CFBF95458EDC5610CB09CADA770E8101408201076106BE4A5AF5AF610E06D21C524B0EED4120F03C29D5CA8DF5D82FB607AEDF9C4FE95F29C4E2EE5FC4922B15318A82E3C8403BD3955B8D68962C716C36CF2AF299D8AED1CFD1A05D429D77C771D9926F76DAF30DFBB7F87158AA99096CA1412A36DF50E0C88EC84A9E43847022DFAD66929D81827B42C56A243E7CFA836DF241BA8FBE965319901A6EFEAA109F589DC2B0F8660425EE724AAEB591EB2B977560788B8E4F991E5150505272E6EEF04B9CC450758BF2BD91BE9CD296028846AFF00326938FC89CBD461CC05BCA1D6DB64F693585C4F1282DB19B3A86D52B9A8ED27C0A48575803DE2B178EC2602C865B06E3720560EB30B4B5ACBB1124588A56C51F4531EF168129FE2DB648EFAC211920357DEBF2CFBFA4EB8865B52DD504A06F26B0684B71D4CD94828007996D5BC7F51EDF0694C53E3D16446506DE5052566DB176B581AF18C4BAB9503B75A6D5E28EBC6F31DCC9FBB46C1EFA4B6848B252903BAB01467C656B4F55A672ABBC9D9FB7431F72CDB4D73398D48F271BC29437EB2DFA8A77AE7D1697B9ABD1E75237BAA08A69391B4279003A3E3216EEA6321521EF61BDB6EF3C2B0DC1D7AE4C9C4B22DC4ED6D94ED4B7DBDA7C38AC3F1D8A50956475273215C8FC29D73C5DCD5CB4961CE4BDC7B8F1AD6200B95A2DCEF4D2D7255921365F5F31D51DE6B08802045C8559DD51CCE2FDA3D0C614A54F702BD5D83BAB16D6F8E40547FA54AC94F7D31A4B8CC43F3D8A1F6C6F396C7F31585E9161D889080B2C3E7D473E34A491DDE834CCDD186B1EDBD7E83257254530DB2F91BC8D891DEAA6B020ED8CF794E7FA4DF928F89A8EC351DB0DB0DA1B40F5522DD15A12E272B894A93C942E2BE4A819F3F8947CDCF2548C4998A754CB79B2F04EC02B0F9C8999C25252A45B37BFA12633525367537E4788A9FA3C1E19DA78EB1BBA9A047ADC298703CD058D97DE391E22B11C2DB76EB69365F2158563B3B082942FE710C6F4AB78EEAC33108B8AC7D7435DFDA41DE9E9E949CD8E618DFB282AB781D73265012A5AD46C94245CA8F6544C194F0CF89916E11D0760FC478FED484A5080942425237002C07A03B8D390714724A9866304241B78C38AF27BC0E3585406F0F881A412B513996E1DEB573E963917C46619681F357CD9DFE85FB5DC68D6251B617503F10A61C7F0F9224C0564706F1C0D6038DC7C659B27CDCA48F2DB3FB8ECE96909CDA551C704B17FDE9E73568D892B59395284EF51E558461BE2BE7E45973163CA57040F653FF0076FD89E6D0F34B6DD48536B16524F115219561B24457AFA93B1874FAC3D93DB46A5B3A978A7D5DE2BCE30FA64C45143E837045617A510254342E63896246E5A4F3ECE871AC636E972FFA628FDEB47E3090F2A7AF6A5376D81FBABFC7D931D85F2843530DB812F6F483B95DE3FCD403250B5C793B54DEC39B62D3D879F7D62A9F36857236F03B192B5E6B91D01BEB1F51563D2D2D6C756866324F6AAFF1A8ECA23B0DB2D0B21B4848FB03EFA59C80DCAD672A1237A8F431E694A845F66FAE8FE705B88E229C8AC6330997C9C8FDBC9751BD3F11D958C3722235AB9A80368CAEA7A8BF81ECE937D7AC3E5993A62DBE47997242F2F7E5B0FB0E1C7C664489AADC545A67B1037FE67A12D84C98EB6944A42B883623B6B47642E015E1F33638855BE07B8D62AB4BF065B4B48394849078D4A82B601531771AF638A7BB9D254142E9DA3A093635A4C9660CEC15D650869297944D85870BD4394DCC6CB8C056AAF64AC8B05768ECF4F2DCD54579C1BD0852BF4AC0148560B0CB7BB563F3E3D1D286836F44969EB156A17DA0EEFD69C92A5EB2FEBA520F78F03F874779C2B505051DF9556E86C00A9442509DA49E1410349E787568B6131890DF02F2B9F750000000B01E0C6F11F1169B4A7E95D5048ECEDAC35F5488895B9D6DA0FA4202810ADA0EC35A3B3061932561524D834B3AB27D9E0698D21C35F9DE2AD48BBB7CA0DBC951E40F434CDDB4161A1D653A93D2DE6B1B5AF11949C1A2A8A507CA94E0E09F6477D30CB71D9432CA421B40CA948E1E1D28CCAC563A6FB3589FDAF58565F106B29BECDBDFE974FE225296662363AA56AC914127665D878562DA4AE468AD371D00CB50DAB56D48EDA81A5188C792954B73C618BF969290081D94FE2D15A4660E67BEEB7C6B1A7D53A6C7521C4E6CF982378B749D7931A3BD217D56D2555A2ED2BC4972DEFA696B2E13D9C3A1A48ABCC2AF61D47C2B00776BAD1FC43D2E99435CBC1EED0BAD956B2DD9C6A1B49912DA6F7A6F750ECA95152C4D534D9590948B85F0A71BF20D3816E93AE56729397B36568FA72B4FEC1B17BFDDD2D2E51F929A8E8DF25E4B74CB619690DA3AA80123C24D85CEE158A2F5ADBCBE6ACDFF00EAB0755B104F6823D32224742CAD11D94ACF108158E600FC99CB950D6DDDCB67439B368E37A8BA332B5A15296C8037041BFBEBF86B1242F54DA1A5206E74AF7FBABC45386B288F9B3BBD65ABB4F4B1FDB3B0349DC645FA18B2CA2039978ECAC4C5E0BBB48D97D9583FD7D9FF00BC3EC4EAD4E3AA5ACDD4A37E87FFC40029100100010303030402030101000000000001110021314151611071812091A1B130C1D1E1F0F140FFDA0008010100013F10FCE0B032D36BD74B69C8F6137A56A00C92E87777A82C152709D05827769D2D7B9F63F9A46C9B00FBB58E2CDE53EC547DD0BE1FDB41C2099E4F34E5A46241F4524D856723E655FC52A491A36144F10CD40C4961A5C0BFF8103389AB0DE8E169ED3DA981205B99E90B6F348CE90978FE14B61C15F4914ABF205FBE8D3D0A94B3D0E3F81769770BD97397E02682183E43CB1E2294727B5459448C1F25223088FE782179644A756382AA57C9FE734AE1D0F0A701E6841A16200E50FD7B5470BDCBE9DFD05429E19C96DC9A7BA2ACC52D45BBE8705A90953D65F35AD3FEB99A590583939461F10F15A997264EE64F3F9E17411A4473255DDB9BE3538D3C6F578EB43B9A352612C991EE56128D1979DAA72568E4EC7A0FF3C04C5986AE87347DCF7BCBAC9AAEAFA548290C636AC7B65C8D3BACB3232B35930F151AC466D20FEFF3CC91C50966E4F24FB563C096344FFBF1D1A6C29CB58E56553F01BAFC6DB92D589215DF9F161A0910DE1309E91A4CDA29F33334A674442CB680DA8854C0743C2EDBC7BD0282100D0FCE0719341D4A99198FBCDA64FBA69E8D4598425190EC4041DDA3C5B82951A60E51DDAA3E3B52228E4F427CED4F18FF0071508A74B9647DCD673FF804D4A38B5059803F0D34D47E461BF60AD946AA06E1BD452466E708EEBFAAB2938A163582A6777A1B4417B4508404404130FF00C248277E82EF8177C57B207167C957A5BF1A24CFA0F83DE8309CD60E1D0E0A6EEF1EB825B909A199214F63F0E714B2520DDA2A51BE056E096A589D2F5DAD52A33D0919F769379F44C1EF4895CE0F71A1286E36727605FDE2A69EC7647BB3F36C7484A6721AF6095ED45888919D64EAADFF0009631BDD8FE42B946162DDFC47AC15012D0471C8F60CBE29652EC840344313C2BDAA752C85BC7FE2A0133A73F9A3E01C400FAA4EEFBD2A6A65A33146488BB82F4E5E9BB25DB53DE895948C8215B268D0F0109B429EF441E5A5555CBF85500DEC3C539B9C696FD37699342E895CEC3DCE6A18E24207DA93D5489913A5DE017574A0FEA8371DB47BE3BD33BB64287CE7EB8A02103004051428F502ABA8AEEEBD8331B14A11200C06CEFB7BA928269B796034B0FC8B944B27FF000F15DE8A43C9AD4025299D5E162529513F4BBBD642AC6592CDB6B71A6A54C1026E2FD19AD4FE9D56EF35A945965D8DDA621FED4050052E66C78735ACD18C8EC9A3D0D1A2A1B3BD4F34B5BCA10E9114E98389E470D4FF00E47B1F402D3C157ADC184DC4D11B27E1289EBDE9A95790A51C2F23B1B79A020917BAE5776A73848E819A57822058E3777A12C6DA4081E68776F0320E1A9FA41C6193BECD61BD6E422644D1A69C1E605290A6D53DD14EC582B905A4C9521224524A4A6F522922B4B3B54EE99E4108D4C94B898ECD23C8CFF544090121713F036F227061F745B95C4087DD76EDA1FC5679B4929F45446DA8786A51E4BC5E51984B7EF8A8C0B0846F3A781F3489EBB4DE198A24320B3903483C8D4C2A4A7CCD00A4B060A597DE69CE00BDD97A839230195B07BA5199B32B5613E2D1531C9029E2FD2F31449AC5B8EF06C780A2C416363151862F7BB7933D9A8BE618658C8659D948A121381A28DBD9A3492C7BB254BBC94292C0466187B944DCA59CBFE7DA9A24FC6498A56248B9542F760F7A04762C3ACBA525502026850E3C127540D1A046D2B454B42CA124F6A72E4227A1C5044809A72C1ECDDF053088498961EF606AF050512C64795755CAEAFA0CB140488E89519BAED8014AE5DB0516E50404E66EA9146859863DCA9B889A276AD83EA92922BEBA4BDA1FEFF1C1A9B1F9B6190EEFDF54A42870B38AB1438400D8FE454E3B10FF009A619765E0DAC03C5EA43892D4AA039573DDAB53A1BA0B0E1603F9ACD1C4C659243819B76A8767DAA22904D9477D03BD04082D2C5F21158C6E001E16580F35255E63C4C7DC3429853B50503EC0FDD36AD1A0667B50146DEACA90E39068C0E7F143BF432DF3152AC253754FA8CA2CAA029E88A344D93D1160C837BBD0AE5E121981C4B0E4A5489372FB2682C64C80ABCB2D1328C00A7B21306CD1EC9A8EA60376EC163E569366ABDE4FE684245BF12BC8C9E32CFEAA0500B670450FA1405C987F403BD4CF6F28F7AFBF834EB02C03C9074791669747BC1CD8C5A934A7A8C5065C622F3E1838A8357E2C4BB1B183D02C2003EC99F32D12B97A62200EB6D2B548D8B7163DCADBD6912F183F15756FB8FC196AC3F11FCD4CAF49A52B50B97C96F04B436BFA8F698F913B560E6C31FDFA1A6AD7922786818BB16A38A686076D63E8AC2D08B30CA09EC4F9A9A7A427A30DBB0D1B85CC0C6C5DA684C5487C95939192811733667B73C52E6B2309E593B62AF84360DB27EF1587D473B2270C3367E28A13D80DA61FBC1AD1449DD2ED0DDF047750AEB8181B018EB1D5E854861441DA94CA50A46CAEAB513914657E8D0F531347030F63D80F3DE8503721835E7F9A70B66248EA27EA99413CACFD9F4A4461B3E832536A2B57F4A8242424AF03BFC6684A9180FE006EE5758F5C7E078E92244C952415959E636E392F4444491B2351565ECD31F559963FDE6823CB5310D61A3E830A3321D4BA4FF4AB81AD22063BEA2381DFF2BE99A5A88064DF8934DB21BEF460EA448D0346C1868D8B794F09FD534A825C81AFA04939A2ED9229CC98E0978A80023E023FBE87E6C7179CC09B6C05D5B06685426CEA4D34B57E252E63F717EE14980B7EB539375AF53A83177B1BF23C539F4991382F4C8109B710E07708F7A3F24F468BB065A6BC089D4C23915EC14B4BD09FCC0E497026CC51B17AB362717045F4A0BA5FB81446803032E45CB4719A26D2613D17789DCA38AC640334FB538887699CCB7744DA7D735353D66A7A26084F09FD531AADD9CC899795A9E93D0F68921BA65DBED404EAF3B86FF153577EECA2BBC1AFA08B60AD002EAB57153A1D4B7060B7EDB1320400401B1D00ACA5ED58A4175E8081873E89A9A9A9E934B53445424371CD397D2CD97B1113FF006A2D52499E215FBD3ACD030B14386DFBA72F7A9F4020196808A198B6F7247C73446CF80054F4BB44F801C3EEA232129773254FA96A6A6A6A6A66A5FC86214473E2D5282BA08B43367DEA76ABB504090CAB36C77A304BC800B021331AD16000384BE2EB1506C402D1D5E0BDF55A5BFA6226592C4C18FD79A8F63DE31876CBE881F77D885F74D25600BE1FD749A9A5A9E9353D27AAA8B716502437B53C09D614035DAA5D36095370388A8ACDD20E56C548A3D3591858C050002B042E9063B7AAEFA600C4998F8286E0083608A9A9A1658095E299DC9DDD894C4D1AF69FD7A67A4D4F49F464C0062F98A8FF00F9260110139B5A9AB865D03BAD74D0A5F6D3000272E5344461216360FF006DD1A9EB6AA660E40FE6B4A73D1254306F0B0D43C7824E1B25081958925CB7F57AADFA36E8DBD0E29E8B03DAA75809A7AFFFC40032110002010204030506070100000000000001020300110412213105104113202232510630618191B11433425271A1C1F0FFDA0008010201013F00EFA005803589B860B6D0578F61615918EED5D98EA4D1897D2961075B576D147A5C9FE2BF0F14BF966C7D0D4913466CC3BF0CFA76726DF6AC96391BA55CAEF57BED4C5635CEF52CEF2EFB7A72EC581006F5886CB1647376F711B67456EA34E445B514F1F6C997A8DB996CAAEE3A69EE625C91853B9D68024D853CF147A6E6BF1A4795451249B9E4CA5A3751BEFDC8E1793CA2861E34FCC6B9F8566897CA9F5AED97F60FA50923BDCA0A570FE2AC4C9D9A651B9FB7776371BD3AA3EAEBAFA8A38788ECD6FE452E16306E5AE29E62DE14D052F02E20D1F682136FEFE9BD302A72B6879E178370F970CA81487B0F17C48F4DADFE5710C2BA390775D0FCBBA401BB0AF07EE1F5A319B5C548731D36AF66E34476C532E62B602FEA7AFF005A50C5BE6BB6D5ED7080CC9227988D7E3E9586C0BCE331D05370A005D5B5AC171AEC90418AF091B1E84563F1D1CF8C695366FF0005AB130766732EC7BD86F046D27CAAE6B807168B02AE92FEAB7CAD53F1BC3019CBDCFC2833F13C419A4F28FF00AD4B6B694580DEA444986561714FC2A33E52453E0F247949B8A6194907BAFE18517E7CF0D8379CFA0F5A862585422D30B1AD0520B0D79620D909352E14C84BC66F7A65286CC2DDCC568557D0561F0B24E7C234F5A8387C716ADA9AB5B99B2EC285EDAF2750E0A9A9E37C2CA452BA4EB6715340D11D76E428C071188C9D2911635CAA34F738BC3ACE963B8A40639321A5716B30B8E51AE670B58440333F527DC13D2AF47515361927B31D0D4913466CDCA30C5C64DEB0CAC175A26DDEBD1366157E43734543687970CC383E33D7EDC9F6A1CAF57ABF26B11AD48E249028DA9E219C2AD5AC4D5F9605408C7CB93EC6877C69A8ACCD7CD7D79FFFC4002E110002010302040503040300000000000001020300041121311012204105223251811330610614A1F02391C1FFDA0008010301013F00EB3B559AA88F2A7535A5647B566813524EB1FA8D3DC17D947CD3C3247B8C8A041EB5668CF325238750EBDEB7E13CE53C89BD63B9DF81914024ED52B2BBE536FB168D82C9F3C6EA3E53F507CF1BB3A2A7BFD9B55CB17F8A670832D4F72EDE8D053176F5371BC182ADD04814B148FB0C50B53DDA85A2FB9A365ECD4A81005153BF3BE3B0E9650C30C29AD31E83FEE8C128ED9AFA721D31515BAC63277A6F17B20FF4CCA33FDEFB50C30C8A0280AB8F16BF8AE1A4E60533A2FE33EFEF48EAEA255F4B6A3E7A4DDA7615FBB5F6349728DA6683A8D0D78FB3CAAB6A8DCA18124FE0634FE75A6B28D63F2EFEF5FA4DE6681D24F483A7FDA9EF121381A9A5F12D7CCBA55F7833BC867B3F306DC7706BC3EC1E1B25824DC7F1939AD54F2B6FD5127D4900A118049AFD41E152DF9478775CFCE6A0F04BD7C465703F34B1A786DB8863DCFF00734C083AD04276A46784E41C1A5F1271B8CD49389FCD8C11435E9B25C966E33DD2423DCD4B2B4ADCCD564904CBCB268C28086DD73A0AB997EB4A5C708572401455A3D185039DBA2C47F8F353DC2423CDBD4D7D249A0D07428E6DCD1C674E0AECA722A1916E2306A7B4C6A9BD03D8EFC6398416C1BBD3B973CCDBFD9B59DA17C8DAB21D79854F6E24D46FC09C0CD5C31C2A7B0FB0077E0A706A19DE1381A8A8E5590647038C6B5211A0EF4064E051D3A95720D6382EAA281236E12363845EAA61AF1C56382120E94A9CA849DE94F9799AB3A0C7190F08877A7DFAF359D318E3FFD9, '', '2021-01-13 17:15:36', '', '2021-03-12 20:30:44', b'1', 0); +INSERT INTO `infra_file` VALUES ('1c164a1d-5f2d-460b-a0bf-dfc33deeaab1', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010402030101000000000000000000000405060702030108090A0BFFC400511000010302040305040804040404040309010203110421000506311241510713226171088191A1091432B1C1D1E1F015234252162462F1335392D20A4372A2253482E218356317192655648393A3B2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004A1100010204040306050303030302030607010211000321310405415112617106138191A1F00722B1C1D11432E10842F115235233629272A20924E21617344382C2D225354463B2F2FFDA000C03010002110311003F00FCFF00F041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C10418208FD87B813D3E67F3C7788F3FC6E69363C22D6FDDF0411BB815D3E63F3C104286410153D460823760820C10418208E4027618208E7815D3E63F3C1041C0AE9F31F9E0820E0574F98FCF04119A10A936E5D479608525EBE1F78DBC0AE9F31F9E08520E0574F98FCF0410702BA7CC7E78208DADA0999B6DE7F8E08236F77E7F2FD70410777E7F2FD70410777E7F2FD704118A93C317999C10CF13AFBFF008C638219C72013B608232E03D47CFF002C1046694F0CCF38FDFCF094D4158006875877214CC4D4FD59E32C6132985EBAD1DBC7E9189A1DBE576B559DD9FA7DE0C2D0D1724AAA4545ABF8AC18553348A7AD1FC695F7ADF44E1946C9F53F76F5BC6C473F76174E33BB4F03024EB57AF9368DA3830E51803308511C2536ABBB6EC6FE9D1A366135E0FBF1DE92CDF335347DDEE075873FAB3873DD005AC29CB7F4D6B780E5F4D5A851A8FB2D5C6FCFDE363F973C309B988C092848E23661A353F0E1FEF1B1CBBF5AEA52806AD7954F9B1B391E70DFF567A9D7C397282190654A510010227ED1F523D3E3A0CBA7F68FE44CB50E2F95D8D8BEBB6EFE908AB3AC2766471AE623E4A8721E9CB4B73D7AC467586B5D2BA4A851555F54D2B3108594242AE1691B7849036DA2498EB6BC763FE0E62FBF335285B02145D07567AB3373E839C707F8B3F13F099FCB1290B41E0052E143F8D47E2EF1E7E769BDBC67DABAADECBA8415508529008E12384980678418B58EC46F7DFD51D8BEC1E2B2C54A331040053420A6D4D5DB4616EB78F1AF6AB1E8C5266709A17DA8E49ADFDF98A15D4F1A96E288FAC39726D6264FDE7974E5B63D138341C3C89686F942403B1259FA01BF3146BF11C561D4AC41535D46ACE2E3416D980B78C33F7B56CB87BCF13677208B0B58013EFE77E5BE1D4FC4E164A0103E602A5EA0F46E9EB5B45932826536F4DD9C352D4F3D2FB3D52AD755FC9CB69D6AA85405AE080831637111067A72BE2B38BCC82D570DD5DBF34FB545E26B329A26A101DC0DBCB6D7DF296D2692FAB2135D9FD5200FB41B252088822E08322C6FCFA5F112BC5898E259248B9B01B6DC8F3B5AF09DD10CA04B0BDBDDFCB5768E2B75F6579237F56CBC0EEC82952B8ACBE1B022790F58E57DB0B48C089EB97C60A9BF6D051CF2BDFD0738CF0B7ED2DBEBF58A8B526BFF00AE05C41924CCDE6E6F620C5C7A82011CBA064F952259494A49B3DC57AFD1875DE32C5EF4D9B4FE7E914E669A892E9971405D51B73DE4FF00B8169E78BD48CAC2C070C031353E0C4FBBD214960D6BEFA7D2AFD5CC57B9BE76C282A48264F31F388F2C5830A8561C0094150029CEB5B3D2FEE90B02458C5659CE748414107884AB8960CF0743CC103623167CBE79596EE94016DFA3DBC474D602A56FABFBB539443ABB50B652A4B55A16A0090D94F09932624F43E9E98B127284E3903893DDCB7625C9A1A3B5F7FB466F57751D1B9EF688457E7D9A212B536D0A74916295A5C2F728099244741BF4387185ECAE5929655FAC4F10A974B355CDDB63E2E7687F845F7038881A74156ADBD80C46AD1966479EEB3AE4D1D165F58FBCEAB852A34AFA112AB495A91C113E7F3C67138DCAB26429B1929D22A0A92096E4FAB69CD8690FD58B29038998F420ED607C5F4D23B15A53D8935667C935FA8EB5191D227816D347B97D758857DB061C0A68A45A08BCD8CC6397E79F18303226AB0982FF00E6785D2B354849D2A4172F5A13B46E9C6CB482490966E120BB1B9B1EB77F28EC2699F669EC9F45774E57D00ACCC1AB9A90F3A8950DD5C21445FEE0440C72CCEFE2063F16B2A9092949774049513D0B75BF4143185E669593C441239EA1F73A0A103520EF16DB35D9169D60B392A825A5A424B72A3C2102D75493EF323D310723033BB529EF714852384BB11551275D400DA3B93D22B79BC93982870034D75F00FD4921BF2C198EB9692092B4DE67C43A5C6D6B5B162C2F651583471CA4958005003E16BD3F310F2B2598925C103426F5F2B5B5BED15FE6DDA286F83B92823C5C478922236DCFC45EF893C360F1085702B09316C59FE617A060C77E40F51599C365533880AB01424569E5D6C4E8763F43BDDF9FCBF5C7C6A8FB131B1B6F7BF4E5EBE78208D9DD93B19F77EB8208CC20A6666FD44608239C1041820830410A1948215239E082377027A7CCFE782083813D3E67F3C1041C00EC27E38208D884004CA62DE7E5CFF0C10A4BD7C3EF1B3813D3E67F3C10A41C09E9F33F9E0820E04F4F99FCF0411B5B481303A608236E0820C10418208D0FEC98DA4CFEFD7E6704369C2A7937D0084D82108DEC6EAF4C10429C1046B7397BFF007FBEB85E454A81B375D768D54A2080CEFEDBE91AF1B2C0248D296E821DCA415F086277E956F0E9061B2BE57D5B6F7E71209C10500785CF3A0F37F1A6FAC7307A1F81C3757CA1EE7503D2B6E7CA36FD3357840DEBA79FE233458906C4EC0D89DF61CF1B494158E32A219CF0B78EFF0096D371A99A9927846B43A93CB95EBEAD1B0DAE6C3CEDF7E135E3E725624CB4A94FF28A3EDCB9F3DA31330B24CA33662920B7155B7D4927E9CB584B599BD1E4CC2EAAB9C42184A655C6A090A001DA489F389DBD316AC87B198ACF6721465AFE6503504B545C0B373357E4D1CCFB55DBEC2767E4CD4A26A78D20FF00700C40237D3EA6E0D23AA9DA97B41D332DBD41A6DC42570A471A162EA883736EBCFDF8F507633E14272F952E66270E1870A99419EAFAD5DC0D2F78F2376E3E2FCCCC8CD932672812541252A3F2935B0BEFA0E978E906A3D759BE6D50BFE3B50F2FBF512C00A5917BAAE9240B0E6664917DF1E89C8F23C248C3818591292500098FC2CA61435D983B0A9BED1E7CC7F6971666A973E72D426124024D35B39BBBD3C621A3307585FF002524A567ED106D3E666F7B01F118B1AE461928799C0929B0000E7561E7A97DAB0C5199FEACB1750258B9F017E6684EBCA14AA96B1F5B45995B951FDBE2E020C0E289E1BF5237EA31058BCD254B79682DC2E2EEEDD2B5D4EFE0DAAF0495BA8861A335EA46F41A915AE8226D94E87AE6529ABCCD680C7DA2952900F08BFD9E2927CCFEB8AD4FC7AB1130CBF9893D75ADFDB1A690DB80E1EA0B373BD036B4035BD3C21C333D4F91E46D0672361B554905350E18F09488175023D23F2930B96E2312B515F114D38433B5DDB5E437F28CCBC419CE92F6605DDC543DAFEDDA29BD41AE1350B50CCAA949249E16D1C5C23A094102DCF7F28C5830B904E5280E025C8AB352FCDFC7CEA215E015F6C3DEBE91546799EADC2D990191C45B5055C8E7304116DAF8BBE53D9A595259160E5C10CFEBE9E2D521962CF5DC5BDFD3C04573996A24B4140AED3D63EF31D07E62D8E9596E401013F2ECC1897A56BE356BFA1D420EA5BDF5F7F4AEF3AD4C1DE0E05C70F14DEDBF95BE1E78B561B23E2203300D417AB7974ABD342F0A2106AD5F2F7B8BC5719A67CE9E2217293B4131CF97E38B0E1F26C34A40330A53C357207DCEDE20C6C4117D62249CE6BAAD6696929AA2B5D7D5C284B2D2DD0924C429494A8226D1C513CAD384B1D8DCAB2F149D2828034701D86B5F76BC64214A4A940512CE5F7B7BE9168692F674ED1B5938DD5D4E5AACBB2E708597D6EB654942B9941215B6FCE76C737CE7E25CBCB5E5E194E5CB70D8B01A5B52CDE71AB6BB74BF4BEFEDE3B33A5FD98B4069B525ED515BFC7AB7C0A61A525D61348A4C158F0A8A1C0B3D640E9D39DE3FE2666999CD2995355864A5DC825D6F4AD886FB36D19FF74A552D2EA0BB8D49EB4AEBA336BADF946F643A6A8D34993D150D22109E14A8D3B0A58E1020F196F8A6013BDF7E78A86638BC7E6734CD54E9F3261FEE0A98906C2C0B1D80A51AE6012E7B01F3569BB72BD76AF4110FCDF581A4595F12AA03F370EF7496639A532019E805ADD4E12C0E439962A60E34288243B80E4022E59EC7DDA35EE26B5016AB0DF7E5EEB158675AE6951C6B7B312DEE4B6A4A9503A711BDFF00327963A7E4DD90594A0CCC389967240A1D74AD58C024CCAB8507D2B5E75F75EA22A8CF3B4FA36520533E85405719EF00EBB898103974B7AF47CAFB21C20BCB4CB048E1000DE9B5D80B1F4895C0C86204CBBD5F9BB0A8A50783F952FA8BB5C5242F81EE217809503693D2763EF1B5B95D309D9BC0E1C0FD44C9680003F3149D8D8989944992194DC99AF5D79BDF9161B0A9332ED3B38CC1C4B7468AC599321961D7449DB88A52A03CA6FE7189299FFD9DCBC12B992262AFFDA1DBA56A75F5893952E4FEEE14B269A0BF2A75D8C7D9F702BA7CC7E78FCE947D488CD00899E7820856D7F4FBFF001C1046C7397BFF000C1046BC10472013B0C10473C0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208CD00899C1042D47DA1EFF00B8E082327397BFF0C10A4BD7C3EF1AF04291B1BE7EEFC70411B304118A93C51788C10463DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1046C4366F0472DEDD7D7046AA4F13559A33E03D47CFF2C11AF77CFD3F98E0A4A6262F820EEF9FA7F318E083BBE7E9FCC6494F14DE2309AE7095AD4DC0F4D21ACC404AB702C767F7AFD9E32EEFCFE5F1E78C27121542AB50F46E9E17AD59E25B0880407143F624F87500F231AD41485A63633263D63979F581BDF0A0636ABFE7F36F48972BEED2598003A7ADE9785E97611E000AA2C009933E847E5EA6CA0C3950709AF536F63DB457B1D980960B1B3EBBF386F5A1F2E7795280D2904965C2425206EB27607C89983B637460B12B9A897250541440A026B4B5FCCE962D103333EC1C94AE64F9A947007F995AEFE837E758ACFB40ED7B49691A171BCCEA9BA8AF4A141A085414AD22D3DD9BEC3A73DAF8ECBD90F86188CD97266AE5514439526D57B37516FE787F6DFE2F4ACB53364C99C0B710042BCA8EFE1D0DA3A0BAE3B6DD45ABAB3EACEBAE3792A4B818E05F0C2153CD30A3CAEA9F863D51D9AEC160B2097C62524CC64F1929D980615D49D2BE71E43ED576FB17DA099302672D94A2ECA25DDF9DEF67D0E800A32B5C72AAB0A299C5960A8A9C5A964913E2B9513CE79F2F71E852E6CA54B1282412DC219852C2D7A6F60E3568E61370B880B3396A528383577AF89E7C8E9631ADEAC697C34AC8EF9C62CB4F0F1294544110482607979F3C44E331ABCA5887F9AE1D83D7F353E71159809B882020171471F6E648FE1A90F794E98CD7365871491474A2EB2E04DD063FBA08B4D801E5D442CFCF7138C3F2950068384925CEED785B01297214935040AB8B9D6F5D2BCF689839FC0F48B45197AD0F5554A4FD6D44F180A6C0E1E10A2A09BCDD3E569384F0F87C4E26612B4A88A312E5FD0BF8FF009B14BC406093C9CB83D2BD7A00FE759EA5D6AEB895A50E2D2992084A8C46DB0F4E9EEE58B9E5D9271315203D2AD5FE437D5C447E2809BC4003A7B715A5EBE42F151D76A72E71F78A22E4824C13D46F3E71B62FF95648944B0A080E68430E6DCCFADDB946B8190CA20861A1AD7C3EFD4968AF739D40D10A2B50B4F43BDA79F5F527618B8607260E9FF6C1377200BF20DB7F889054A0EA6340CDEF5D76F48ACB3ACF95C214D3A4F0C9E0130A9DAFB88FBF6C5AF078144A07BC481D40A6CDE9FCD635EEF9F5F7D22AFCC750D45495A16CFD58DE17DE7113CAC89E76DA7D4C624E4E270F852429495736614E47CF7D768C940A72F50F5AF9FF0010DF94E5B9FEA5A85D0657435598D4A9494B290D3ADA254620BBC3C2396E4623F31EDC65D93389810A55C7CC01A07D3ABB3788A4615F29A51DDC69E1E71D89D1BEC9FA82B8B199EBDCF13A5E8950BFA806915E5D418F09534AE24CED3CA76C732CF7E2B4EC68523289267AD2E95242FBB67E65810078F2302502BC5F28350757A93E7B1FB476974DF673A0BB3EA7713A6B25A6E3AA091579A3C43EAAE5343C2A4B2F051A7E13C93C24C99C73AC463738CD27CC9B889D312EDC3872A5349767F9C11C4F7A337AC60D0326BC5767AB1D9E9515A316F25D5DA83EAC9296F81A481012D8091FF4881B4DA3D061C48C9674FF009A6ACAAF42E6B5D5C9B5691A457D9CEADA068076B1CE052788A1C924A6638A403723A6E3EE7533B2B389419128A8387603FCF9D0E97896CB90851F98F2B0D3EB5DAA75BC5459FF0069542942D34E7EBCB4880B528D3F099B58C4FCE0FCAF5D9EEC84C982599C8E12083548275F3A00C452912E2549092431B0E74DDDEC35B750D14966FDA5D6BAB5F7CA53886C92D36DAA4B53361C175CEC378F22631D7705D95C24940527BB42884F12C81F330E76620B9153EB194CA9003900DEBBD1CD6ED53B3B18AF2A738D47AB5E34795B55656E12800D33C94C9B7FC45242779B93077E589350CAB2F9759D282807532D0F4D83DED6DF9C60C99360D7200602E4120BD9A950D123C9FD9B35B66E876AF50E6E720A65F0AD912DD49A94AAEA94A17C4D948EA39FC6859BF6DE5CB5AA5E58B338CB2CBE1052CF600B17F0AE81AD08CFE0C30534BE252838214CDD40FC01436689851760DD9DE429073DCCD39B3C800AC28AD90A2093221640B08F39BDB1589B9B67999A80968C4278AAE0A983F26B7DBC223CE2A7AA8A24241B52A0D59FEBE1A38896D1661A0345B6B190645423BD003CE3AE36F13C164901E4A888E7004DE7961493D96CEF1E52A9B889E90AB92165B4AFF86E4E408C9C54D724120D2C6FE1FCEF4DFEA0B813D3E67F3C7C448FAE1182C01103AFE18208DAD7F4FBFF001C1046C7397BFF000C1046BC10428640215239E082377027A7CCFE782083813D3E67F3C1041C09E9F33F9E082315262201E73B9E98208DC8FB43DFF71C10464E72F7FE1821497AF87DE35E08523637CFDDF8E08236608236B6099813B7E38208DBC0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208D8DA0C99B5BC8FE3851129730128492DB03F88D4A929604B3C6EEEFCFE5FAE345A552DF8C14B5DC41C69DFC9CC25A84414C49B1E584BBD976E34BECF1B42683D0FC0E144FCEDC3F33D9A08554E82AE29062D68F774F31EBB74223333973D2C532D5CA86EDEBC879C68B0E40F60381E3F6850503991EFF00F7BF2E9D79623E4CD5A3F7862DF6D6EFAFD62530A81F2922ADA1DDCE87DDB48E52D852D28304AE403C86D79B6D7FCB161C02D33F85D8BB3695ABEBE239F284F30C64B9328954C4861A9D9E8CFA74DF94346A0AFA5D334CBADA8A86509402AE15BCDA4D8490125533F38B5B173C164F8AC424193214BD5922AE76A55EC06DE11C833FED56030CA5F162D0821E8A50B8EA59AECE63A7DDAA7B49A94CA32BCA4A53671B79D6D4991FDA640133E47CFCB1DFFE1A7C3A39924E231D87E0EED890A4DDFA8ADBC9AFA793FE2AFC5299972C4ACBA7F7DC45415DDAF98A509A57968DCBA35A8B3BABCEEB5CACABAB72A8B8A2AE052D5099E504991E57E533338EFF0085CBE4F673865CA94084B00C1B7B9FCB6E1A91C067E718CED0054CC44C5A42854124924EDB30ADC784343D5A5B6437629779003C3C3BDC093BFEF9CBC9C7FEB4F0A93C06C4BF938A0B50EA79561A0C18C19EF0AF8F5F5DB7F0B7431BB2E4399B1197E5ADBA9754614E702F8403170A2909023CFD30E4C993844F7EB9A193F31147DC51DCD7D0E85842C31699E44BE10D40FE62A49A0DEDE57B0E934E64BA5984D4E62B43998B838D282AE2248BC5A529B5A481327AE2BF982E6672BE1C3C95144B35531170C0B1E96D7A42F2B2EC3A4778B5A49502458B36F5EB7FA9AC3B52768350EB6AA44C5234994A3BB29320587D88378EBE7732712195F67A6383310470B1729DCFD69F5EB0C7152E4CBE208502DA8F1D411BFDC08A6B36D4F5544438FB8A750F71142F8A763264090396F13B73C745CB324C31212402B4B3B80F514A11B8DF588552D6E785CBEDD357BF4D6A6915F663AC12EF1092679C9F988B753691E918B2272A5CB712A5B8A51987D4FAC48E152B985969246BD01A7566AF9440338D4895C70AC08E2913173F03CCED2475C59F27C2290969D2CA53A72BBF27F06A5A251587080080D6E54B5BA69BB12358AD735CFD6A514A572A13B193F0DC9BEE2E4CF2C584CE918541AA52DA9A9D3D2FD5BC635280D40C7993E30DF9465DAC351542A9F22CA6A2A9C5A9295BEA429286428D882B4049045EC63E2315ECC33F91282809E974BEA97D4DABA680758D084E8AB339DC9D3A5347BF28ECD683F65862AFBACEFB42CDC30530E0A20DF15EC4A4A9A544C45C8B1BF2C72CCEFB6B880A29C0A3F505D414CAE1E1AD0824D79B7F319FF6FF00B884DD892F6D4B6FE3CA3B2D97A748E8DA6396699CA695A0A486DCAA5212A5BBC0212415A0A916BDBE3CB154387C7E7E1588C56257420A52C7E4D48A5FD9B184D402E882585E80BEDD05B6E7AC36D7E7294A56BA806F24153A4848BFF4931EE03D7AE24F07947E9871A0998A0C48E121D9AA6E796E1ACE29A2A5AD3423F1AD36DCD7EF15E57EA96E902FFCC15A144C24130D81E7263E3CB98179895350A5241C39045096626C0559A8DF4D69191C61C90EF67A5BD9D2FE71516A3ED0D0C970072499E704C728EBCADBC8907170CB24C89A9038784B8D59AAD5F3EA06D4318214A366F114F7E315557EA3CE73E525ACB32FAAADAA04F70C06DC4B6E1302EE9414245C1249B832671699589C065724F7A25ACAAA1D497A6C2F60458D61591395248649A967AEFB1A59FEF1BF2FEC875667EE7D735BAD3A532F242843ADD515A39C869414391B89BDFCD15F6F24C99331380C195CC450000A5EAD761CDFCE1CCCC54C0A294925243B87E47E94E74BC4E99D15D94E97434B08467EF23ED54ADD718EED49DFF96A242A6368F80C404EED57687325A532C4DC1A4B8E04A78DC1D8B53AD2E23518D50354F15033ED7F1DEB47109732ED674CE4CC9A4CADBA3A100708E1A7694A03942CA267DF208DE775A56498FCCD5DE4D9D384C2039254012756240E54E8F185636610DC2A67E9A860ECFEF9C53D9FF6C152D9E2A3CD9FFE7717136D32B7A609800241088BDA00DAD8B764DD98C065EF33319885BD7E7604355DC972FF0047E6CFB0AB188A4C3C2D4F9B5AF33EC88AFDACDF5CEB3ABFABE51936659938B5405A9A7E992A2A3FDCB404C5F798138B0CCCFF00B3D948225A641290593C4870DD1CE9A3DC0D61E1C3C915E201BC6E2EFA0E55040701E27B45ECDDDB3E7C84395D90AB2AA65805152ACCD9594A5512A2D1701300EC47E00D6F17F19329C29549C3E152560904014D6AECCDE7472212386921CF186D6D576BD5CEE2DA120C7D69E3E0F47D6C80807700FAE0820C10460B49511161CCFE9EE8C1046D423E1F7FEFF41E4410A020FF00E91E9F8608232EEFCFE5FAE08237349E124CCED8D16680737F2FF3030370F1BB0946186C3C840403B807D719722C488180B0020C62061B0F28C929E29BC4608CC65DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1042AA64F09573C1042AC104182304034306081850B5ADEFDB4189CCAB32C3E102C4E0090000E1FC8B7D9B9C6ABC14CC5074288E1B73D3EC7C6FCCC218F9F2F18E25D097B36B61B59F5E95B335C89987352FC2EE0DDAA0F27B6F4F28E201DC03EEC5715964FE22A0A535C162037E0FD358C271A38B8483521EAEFE0C2DF6D9A081D07C06257053460C8EF403C2A04BD2BA8AFDEFEB137879667B0142C2C3A8B5396DADB44EFBD50C42984CA3FF32C3DDC89B1BDBD0DB12788CD70F8C09969949530201A6F714F0BEBB46D8CC30C2A4AD6A6D6BAF83F3AFB7E02D971B554D43818424712CA884EDB8F1116B1BFAF2C2723B353735534A96A1C4400C1E87A0ABEBB522A599F6B30B964A513312E906EA03C6FE26FA333C541DA0F6D7A674BD306289E6DECC21C4852553C2A168316E9626FD48231D2FB31F09B3099325CD54B99C2483549EA2FE3F5611C1FB61F14E4290B44A9E051428B048F5F31E0F531E78F68FDAB679ACEB5E1555CEA69829412843A4002F000491E86DF3C7A7FB21D809597A658C4C80B147E2480777A820E94FE44791FB63DA2CCB369B37F4F8B98905DB8546E6A2C5BFC6E0353ED39F5BEF50E71252DC0EF56A51E2264CDC99F75F1D824A30B95202644B4CB7150960ED7B0D3CF9C735C160B1656A56653173C9248E304D39151D5C3728D0D507D62A52CD3B6BA92A500549E2013B740A1B99E7CFAE23F1D8F95381709D6A6A75A134AD1AF577D8C4BA42650F91013C3FDB667D1FF001A88B432BD0D49414EACC3397D219090B0C2889E662C67CCD8F96F8AE9C61133BB9293C4AA822C9BD7C5DE9D21B6214A52439A0D1C543F3F4FE6AC79CEB3628D2BA4D28869829052A584A7888F252D3C5C8DEF688C4AE1302AC510AC5A9534E8092914E42F4A795223A62969712FE471A6A75D68DECC55199EA1A9796A5D538B150A278C95920ABFD227840B1FB3BF9E2F794E12522584942526C01001A35CEB4A353684D336711C2165B9DA8F4A07D5EF468AFB36CE5B85294E78AFCCC73EA6D6DCF962DD84C12569E14A472200A5431D3CFC7946122613572FA93720DEFA3914E422B1CEF3F70777DDD484B7E20E34471F780EC02BFA63A889D8733896C3E4F3259E304EE4B353C1CEBCE8FA448C8420BF100C3EC06FF715D62B1CD756B6959629E9781D5482B0E05993009E1F9E2C3231185C394F7E525290DC2435854BDB6F06A8B44B495CB9690C90EEEFA6BC8F2F58D794E88D73AE1E0C64740FBA0901EA93FCB45325C363E20028104CC6F1104E18675DB3C0602504E1D32C5083F30736F122D63CB91DE74F49D406B6B4F2DFD3A34766344FB30E4FA74379BEBFCED35B54385C145DD9042B7E096D445AD7237B75C726CDFB7B89C428A70B2C94A9C779C4C13CC03CFA7943454C4B925437602FE1717BEADCC98BF69DEA1A1A3728B4BE594F454CD25282F169A2B7922C93C4B4858889306E0ED338A82B133F19342E74F54C5BBA6A5210ECEE01634D08A784325CC592529A03D2B7F2D7EDCD9BF88D6D1F7AE57B854923ECF140883CA63FF6FC394E60F2B13C0E22492000C08776D75A7F8864B953947F716B9DDD8B337ABC40F35D4F4AA538A6DA085A64874AF842226E12A0019F5F518B5E132B97804242A604A1603A08A9AD43E9734F2890CBD1C0FC4E4D402742F5DF76F74A8339D7CC07974AE55BB5EE9202596DB5C09361C4806D31CEF1BE2CB839397280485A11C41CBA85FA13E5B3BECF28426EA0EDCDBD61137936AFD4AA6DBCBDB5E5197BD77EADCE17613C8842E15617107CB6C2B8B19561105969993B4484D49D03D58D817D34A46532788B80C3572C3D6BEBA7521DA97B3AD1F912BBED539BA351D427C61B334812B17E1250A20DEC6D163EB8ADCEC563D5296AC3619724A8FF00B6A0EA7008AF0B6BEBBC6552D095014551EFF7F5D59E8766FCE3B60A3D2FFE4720A0A4CB29D00A1A6B818A85D504F475482B411D4193898ECEF67CE7EBEF33698A42E5D415CC32C3171FB78922C36D9EA63454C42414801376D58F53CCF872678A633BED3B51EAAA834D4B479834F38A29406987DD696546DE24365B4836332201F762D98BCAF26C9C30C44998A483AA43EE1DEBB35FA930DCCC4A9D400246BB8B73B7873BC3B651D8F76C1A8D21CA8C8D54744F416EB975CD71F02B752A9F8829300FD95004F316B56E776E72FC14E54A46150B5208621373D598BB7A8DA324CB090428125C10D6F4B45A593FB2665A809ACD59AB0D42800A732F148B49EA51DF2147E37E4646D86B33E2662F8BBBC2E583855699C403529429B83A75148C254805D469A5363416B1D06FE962651D96F64BA5160D268D6EB2AA53354ED738A0B52765774E7104ED31104F2DB15BCCB36ED0668A4CC9B982D085391282384240AB3A59F6DEDE08E2B1219A586291A7D37A6F5F48B21AD48E65F4FF0057CBF2ACBF2BA303847053D22D684C58F106F8C9F7C8F9E20D7964CC44DEF67CD9AB59673C6A00B07FDBC5F4E9710C3F578866EF0B1DEBF588F3B9BAEBD6E29AAF5BCB0417525469D289D8004A527A1816F7E2464E5F2C30984166009009EA4FE5F78D3F513BFE6AF323E847E23DECC7C878FB35060820C104668483337DA3DF82085A845801CB73CBF7C86082378481B608239C104184E669E3F6820C27041820830410A69D20F1126361820855C23FBC7CBF3C10473C00ECA9F77EB82083BBF3F97EB8208C8009993BFBBAF9E0823991D47C46082091D47C46082091D47C46082091D47C4621F3113411DD922EED57D4F93B1D59E257018A972814AD9C8A39A16E5E2FB738CA0F43F0C38CBB106510269AD1C973776A73FC6B1A62A4271615DD01E06FE3CBDE91C7BBDFD316B463642D2CC38D8598EDA7DBFCC404DCA57294555046B5372FBF5B0E8638E24FF70F88C4762B013B141465A4925D9ABE81B4E9CA91B0CE64659F2CC58043072469BDDEDF7860CF3525269EA735D52F30186D2A53895BADA490279150240E606DCE3161EC8762B1D986251C52E61054E070A886B9FED6E9BD6AF143EDAFC44C24890C99C80A092C428072CE351D2BA79C7457B62F68A73375BF95E9474B4471216A6CDBA13361E97F4C7ABFB11F0F4618CA3889628C4BA7EFE75B08F2176EBE22CD9C26093394CCA145EEED626FBEBAD1E3A69996779ED6BEAFAC3EED43EF9256788A8B7B9BDCC4836F98C7A432BCAB2EC248484CB40EEC072120396AE9A757D3568F32667DA6C762B107FDC591C45AA58392E0BEACDD3D21BDA7F2FA154E64EA9550B8E1404A892A2622124F5DA06E3918C298DC44B961E5A512D20162C34B52F5229C9DF789EC8B13DF9499EA249209E2BF874ADABA6C048B2DD2F9FEA073EB4D27EAB9332429D5B812DF78DAAE3842A167C3BC4C03E726978FCC53326A65713A96EC12EAAA7FE4D673BB06B4587384C94CB49941367A36DECF5058D584E4E69A774A52F7394B68AAAD4A48754A9B2E3C5754F3FED36E62C30D6565F89C428F1A1610A6F95DDC3BBD2941E9D62AEB584D8F12AA09EBE60536FBC5699F6B673325254E3CA6FBAE2E2A70484906C048201B7FB5F169C0F67E61E17430A3121CDDB930AEA5C4205D4E4D46BC87BFCC54B9BE785D5A8B07EAEA932A9DFCC93113D245A7173C0F67C84A68C056C1D8F205B91F1A3C375CB7341A50FD8F5FBF5884E699FD5AD0DA1C8847142D2A04AA44CF86E23CF9F5C4A4DCA972787802985E9D35FF00378564C906F53A8A55AA3969BEFAD4D659C678E1529216A2ABF824924DF95C99F4F332379DCBA6A70AC66D367274B97366AF9738597213AB31140DB7F25FF10D195E9FD4BABDF5D365740FBAB94A0BAA4A9086B8F9A4A841041E46DE5CA4719DA5C1E1E51056805B7AF956A29467A79EAC6C68123414E5B54DBC394762344FB346459625BCDF5D66A0D4D9C6E93BA2AF172492DA88DE05E773D231CA33DED5E23133169C04854E9609E29817C3C2E59D8D09D4FD890C999852FC4A22EC2A6DF96FA0D62F7A3CCDBD2ED2F2DC9B2F62832F74043354036B5D4A50224829E3470EC66F27E15F91819B9B28CEC4297C52AA904A83137700D40E6E28C1A1133D75483C40B798DBCFEAD0C55F56D289A9A86D554E93214A754900998F0CC45EDC8C46155640FF003214E454802C006BD3ED194951503A9B87DBA52C1E83A8311C5EA4038C38FF007684CF7680809088E448DFCC9E7F0C208CB664999549D1F7A727F7D21E4A4BA8248626C5BCDBD9FCD51A8F54E7755589A5CB10E3E952A09424A80E57201DBA74F2C59F018D561E850CCC03FAD4DDFAB3D2241186E3B5199EFF009630A5DD179B6694F49519C560A1A532A711092A701024182088DB6C6732C562B31E197870A2514570DAAC45474EB5368274AEE1228C2C74D9B5356731B54AECFF0046B25CA6A0A7CCAB523894F2AA01525606E1B5151372791B817DC8C60B2AC62B87BD9CB96C352479D5F416DF9C240BFA1FC7F9EB102CFBB58CD7345A32AD314350F553C4A1BA56A95C4366E213DFF77C207424C74C58F0F829186509B3B16898A4B9659156DAA4D033DFC2360A2011E5CAAFEB1865BD8BF6A5AD9095EA0617A5D959E21506A5BA92A49933C09585260728BF2DCE1EA7B6B96E01250252710B45199813B71330E77E718D9CD0D5EFE3EEBCA27D967601D9E64C108D639B1D4158C90695052ED3C2EC5CBA150676932003D23142ED776CF34CD8A1394E19783624284924B8A307481CCD183F388FC6CC52280EC47E3C770FE348B8B2BA8D3DA5E9114BA7A86872EA74240495D3B358E2D226DC6E214B13EB23AD862B3864E6D8F081994C9F420875AC1AB12E1D8EF0C0629490C1C13D48600D395EFE50D953AA1AA8716AA665D65D905D79BE3E07093E129680E04C5AC1201993CA2E385461658509D350B0C004A800400198A8B957992D7D635FD612096AEAE5FD1B5ADBC5F44C9ACCEF30584B4A79D4AA3C3DCA933B40E22981EFDFE58D978FCB70C4944B4A9B6200240F07AF2FA467F52B7DFADB56E5D474D6B0A7FC2B9FD514ACE524857DA75750968A3A10851133CEDEFDCE23E767F2E6B2508091A1150DE1D18EEDABC67BC330D284D087BDBD34BF2EAE6D7672E389E3ACCDD3978DD48E10F01CB70A8F94EF86ABCDE6A52552D0A98480750F566D9C0DBC63520BDED42297F7EF7D4F68BD23430735CF3F882893DDA50CAE9F808FB576D438F8AD726D1206114E79892549549286622AFE83C7762488D8D855C540B0FBBFE0347B95C0AE9F31F9E3E55C7D9E8DADA0999B7CFF007FA608236F77E7F2FD70411B5A401337DB718208DF8208304106082324A78A6F1184E669E3F68232EEFCFE5FAE138236B68179BFCBF7FBE98208DBC09E9F33F9E0820E04F4F99FCF04107027A7CCFE78208514E002A8168C1042AC10425A80094C8B4608213F027A7CCFE782083813D3E67F3C1041C09E9F33F9E082324D10A93C72AFE544004DE76B741F8E1DC8C3A2783C407537A3B01BF37F37B44E3953D2B4997C4CE6D6DF4FA6BAEF0E0DB8FA07748488800C807CBA44F337DCF28388DC6E0D6853490E09A84835666A8EB7F1312F97E3C480F38B505C80E3CED4FBED1A5F7174692BA9521B61CE2EF14A2910123DDB091B73C3DCA329C5E226A3E4590486A12CE45A9CC72DF410CB3EED66070D87983BC9614124FEE48D0D3AF2AEB1D79ED47B63D37A5E9DE672DA943B570A078566CAE7CC8933CB6F863D15D8EEC1CCC70477D289A24D52FB568C18EBE2D5AC794BB6FF00113B954D32A707054C12A1CE9473F8B3D5CF40F5FF006A59CEAD71A43952F21849761A4BAA48712ADA4248DB9C83E5CC63D43D90EC4607289056A909E32126A914A54543F3B9A3758F2DF6A3B7D8CC7CD5253354415100859347B383E914C54BB534C4AD973BA0ABAB888515493375C1BDFCFDF8B96225C8C24AE3949482DA5096D8E8CDF6778A32F173F1A499855F31AB9A52BEFABD617646D56E64EB8D6574CB0FACA454542C1291FDAA01620082660F493D2A58CCFE6A55C090404D1C3D2E6A35FCDE3072897FBEE4B3E9FE2BD356DA2C8634C69DC890330D50E22A6B40E36C724AA398448F2BF2DCE231798633174758E226B52C05F4DB4FA464BE098A0971564914277F53E8F0C59FEB9398A1BA7A750632FA4E24D321B86CA81B10AE182AE51C409BF217C5A3B3B94A5466CF5CA2A9931B88A9D56B33D07A56F183984DC480164B25E8F67ABEF563D68DB1AA735CE91255C769EBF39264FDE791B63A160F2C007EC0E7968CE0FD3A728DD0AA9737667F7FE62BACE738010568584AC025299BABCA79C5FF002B62D183C081F2292C926AA6019B5E74F585C70A5882F77BD7F0DCEF155E67AA9F5AD6DBAB0CA45B912AE5B8BCDF95F9C6D13D25183C3B1510784B5D859DDBFC7842C9009259C8BDDCD051FCA18E91CD439E3E32FC832EA875D78F0AEA8A565082A220C389200BC83378DF0962F1F824216A98B425206A5209A56848B51D88D2F028F7601259DC74D7D6DEDE2FCD11ECFAE53A919CEBCA80F03C2EA59B022D37EECFA4D8F4C730CDFB49266AD72F2F52A628062405009BDBADBD7A616B143B8717AFA534A55BCE2FC6ABB4F644C228B4FD3329425212B525B485022C2545215E867EEC50B158DC5CF980ACA96A7F94D58576B12DCAF7686EFCEFE2FEF7861CCF3543AA2E3CBB7424C08E8240B7E96B9C4E65B2573B87BC04715E8C0ED41BF87E74324AEA5C9DDAF6D010F119AACEA9DE6D4A4284B1C50A5287849E8933EB6D8E2C404BC0002628049BA451C6CF7FE29BC09C3D406A93434661CF42DE3D4DE0EFE7199660FA9965E5D409212DA5B2916FF58106C2E6479CD8617958EC19708940391FDCEFCFD61C264A87EEAFDEFAE9E75BF5C93A7731AE5A6A334CC5BCAE8A98F12E957C0A35C954784AF88291C3039DE71B4E5CB5292997244C2B70482DC1B1E6CEFCEE6B0FA4C804B936A8D3952BEE94DDBF34ED0720D3ABFE17A572952F3357F2CBCDA1CAB0B7088064B6B489DCF8A3AC61EE1BB3FDE052F198A4774AAA65964B001C7CC0825835361489044C9690C181F37E5B5ED6DEC68DAAD2DDB06B30CD4552065F973D252FA9DA76E1B277EE8A924100DEC3D37C6ABCE72AC8A62E4E19231539D94C951029AA8022AFCAC39435C62CA920B7D093BFA379D21FF2DEC4BB3EC9168ADD539DBD9A6683C4AA64A2A0202FA12DA94D913D3CC6D1883C7F693178D98512B07DCA1569BC605D8FED6069615F2AC4705A48E251A8FEDF6DBBFA74B0A92BF2CC98219C972E672E60C065D1469AB71F8B4951694B6A37B91336E711189C0AE7A92A56348A12471D89157655486FBF4D04D2096B1B0A7E35F4E70F02B7516663FCBA1755C768314DE83C5C200E5B5B0D8C99787078E626601A8AD87224B7BE507784D002454F3DFF003BF28C17A1AB73458733C6DBCAD283FC950A843EA7A7ED4F0A8F0F0C73DEFE987D82ED0C8C220A25484CD5D944A4023A15276FA0A6B0CB1838882B0C3A8377D06FEE90E4D68BD2796A439559877CA489293C66E04DA146DE5E76F2D3119C62B1CAE14E15287A382353CBEBA4302DA17FF34F4BC64ACCB4750A0F754A97DC16061420898DD379E968DEDB61AFFA4637145C2D487B3F3BD29D5C884F84EA3886E28DB0D2FA0B08677B5CE60CA94DE5342DA132027F968317371C49E912461D48ECC82927118863A82E3D5F71EED19083606BA52D4EA012DBFDE1BEB351EA0CC0215983A5A0890D25B084833733C040F59F779CBE0F24C14A1FEDAC4C7A17D1BA9B97BBC38972D44BD9B9FE3DB8863A8CCEBCC8352E0106D0AE9E768BCFBFCB121FE8D216DF28045ED47FF1FC428401AB9E43DFB6D21ADD715557AA754BE01E13711CCEC47C67AE355E4320B1041BD185BEF6B51E8CD180CC5CF41CE3E827813D3E67F3C7C7F8FB3F1B5B481303A608236E0820C104182083041060821553278B88CC6C36C27334F18215777E7F2FD709C119A1004CA80F5FF7FDDB0411B3847F78F97E782083847F78F97E782083847F78F97E78208CD20098333FBEBE78208CB04118A93C51788C64249720381730463DDF9FCBF5C6AE096D76F7D63608529983BDBFC5E0EEFCFE5FAE1512A61B24F913F40605A4CBAAC30DFF003B41DDF9FCBF5C2334F73599F28DCD3C77AFE37AA299A859E14972341527C89B7B78534C9525445E1504988100733FBB4DF082317316B12F0A0CD0A2C420D9DB40E75AE96A562630F2F2E97256BC7CF97228E9EF080E79390FE1C9B788CEB0D5F41A5A8DCA875E6429092A20BA806403C8999DB91E5B418E89D9DECF63332988E3C32CB91562589E4CD476BB53998E3BDB7ED465D97226FE93192D7C214DC2A1663B135DEC6F56AC744BB53F698A9CC94D65794ACA427BE6DD5A0C8BC817FBAF8F48F64FE1AF109532661D8FCAAA81D59CED4D0D5F58F1AF6D3E27634CD992E54E5A9CA83824867A7D7C868D1D42CEF3E5D73CED4D7D4ADE75C5710495120711FF00EA039FE938F42E47D9A9397CB4012C7CA120BA59B9D458372B470CCC3B498DCCE61E352C827576AEEEDEDF788655B952E3EC968294F2CFF9742415711D8F144C0DBED45FE387B9D66E9CA6584259D42A686DE9BDB9C37C265E9C5152E62C39AD7C4EA77BE8D13BC974066F99A5198EA17052D23403810A521329F301493CB68B4CC75AB4CCE958B484A428A967E54D58BDDEE282F5E5D1E9C2A247ED62CDE8DCFF0005DF61128CC7566579553232BD38C349718053595090388923C264893CEE955BEF7182C82762662A6E25C216C509290C96B8A0A9DDC437562D95C201A5E8E7E87E8DA3EF54671A8D0B5A8D73E5F52893E2511C27DE6F1D7A7CEE380ECC4B29042028581671CF47D0F23D2009FD439340AB3F8374A6BB5B940B31CD5A4C2997070AE7C01511E9E5EE1B7A62DB97E59FA67404301C3A0F32E1FC7A50886B3F08B92C5150A3A07F56B6CCFAC40335CD9C4F100BF326401E46F1E9EA316294844A0EA4B3022A2D6FB7D6D1ACB1301AA4802D47AEBA6AE7ECD15DE69995556D4D35252A1E7AB5F2A4B01A6DC713C52012B294A929DC594403060E1862F389387491DE253BD406141B8A8D39DA1E4B06A542B4BFE2C0DADE9170E89EC0F36CD4359BEB157D5E96CE21B252494EF10D906E2D713F7628D8EED580B992A44C2B58B241372E3F75A8EFE778792F800F98F08AB9D69EFDBC76068FF80E9160506459730E180976A6101482810140AD24C9BCC751B462A1986698EC54D96662662D21D9292A003E8598173BDBCE23F30C414B7764177AD2FBD34FAC26A9CF5B7C2D352F29D4A859B014902DD45AC23F1B4E2532F94BC40654AEEF89AF5D28E5A97FB8BBC45A264D591C454403CF9EFCFEED588CB953474A8A87DA4C950920927840BFA83B7BB6DE313B23279666A42D21DEAED762E5C359ADF4899C3A09038B6A6FB721AEDE01A206E664FE6D59F56678F854A8309200927E7D24DBC8624274AC3E15C24A681C00DD69B695F21BCACA93C4C4DB6D9BA69FE3687E7B45505232D57E6F9A8A765292B5309256B77994F0A145423CC7A6F3881C662138C981082FC27E773C2C0D475B579B43A4E1A5862A2036FA9F37A368DBEF0C6BCCF35AD7865BD9FE9E5BC80425CAF765B027FAC77E913CF63CBD063051230C92A54E48091F33548A5A85FF008B18D4A253965060ECCE4539BFD4D1D8C3E9ECB9FAE432FEB5D48595BD25596328E22B3B9471D3AFC3130277D84E1A2FB45DD14FE9C7788018AE8967A588721F97F0D2694A49F99B60E45AF725DABB7D227FA6B4BE41A711DCE95C9425FB7F99A86CD471AAFE206A10AE199EB691888C6F69A64D2518A52E6CA49F965A54A9652F70E92FCC68F4869FA9E0A8FDC054DC17BDDFD37D61FABB4AE7B5EB69DCFB8282957C45A79B7D0070FF0051EE5A5262DFD247BA766927B6B2706152E4600AC1038B89D45BFF005281347F5EB0DE6624CD62A2F7602D7E839B7918E5BCB343E46DC9CE0668F0FB4C2E9D6140F3016AE2927A8E7EB25A623B513F18B213853281B10FAEE3847913A7584DD2F715E7AD21BC6ADC9E914E0C972B69852A05429C21D0E47D8E10EA484D85F86DBF4C2F84918AC6AC199314800B8BD1FA5E9BB585E91B8243B6B786AACD4EF541934AA120CF7083EEFF00869171CE2F8BA60B2247085CC9E8593A294000D615569FE37813C27FBB6D3DF99D8B88630F66398929A3A6AC2763C61F0049B01C6047BA67D7066392E1528044D948D7852A492B6E8AD07F26129F2EC01E2B3062C0BDEC3C284F58DECE8AD61527BD6E914B46F0E3C94C4DAFC4479741F2C44CACC70B97100AB8DA8C0120FE29CC4371289B1DBDFE37E50E88ECD757558E34D332D773757154D39E29E775CD874E91B61E1ED8E1A538EE540A87CB425F42580A78D77D633DD172C41B569FC736BD4B73854741EA36C774A0CB6A00ECE30AEBD0C0F7DFDE30D2767A8C602CA992C1D4254E1EAD40F5DFA467B956FE405FCFDEF18D3F673AA9EE33C54EFF0040AA8A747044EC14ABCF2E9F2C311DA03972BE554C98146DC0A16EA0EA5DDAD6DE3432D40396E61C13CADE31ADEECC756C1229E98EE20D5D34DBCB8E3A6DD646D7792FB6CE2A8586A97496AEE18743E71A80F6FA81F5863ACECF33DA28557B494850F0065C43C6DBCF764C6DCC5F962630DDB01378B8525811C44B8EB7B5EDE87508502035DF51A728F7531F24E3ECFC6C6F9FBBF1C1046CC1046494F14DE2304119777E7F2FD70411B5B40BCDFE5FBFDF4C1046DE04F4F99FCF0410A69C01C51E5F39FCB04288D7C214E085235B9CBDFF008608C100DC03D635E08186C3C8472013B0C1030D87908E7815D3E63F3C1030D87908D8DA157B74E63CF040C058011B3815D3E63F3C10307076B78C668044C8FDFEFF0076C6C2614B2407E2A01D2BEEDB3C359FC5C40006A6F4D05DBC2F5BB346785D385A778A21EF7E9A13A7D99A24E44B44897DE2CF152C6F4366A90DE16AC1C2AE12A4C42374F320D847A794EC6D8D6667327040A182D5616D5DC59CE9EA219CD98BC61328A4A454055A9AF8FA3D1AE212BAB65B6D550B712D21B054A2B206DBEF122DB7218CA32FC57699918696A495020F00DDDADF8262B79AAF0DD9D44CC5CDC5051038F8491FDB56A9B5361E4E2284ED37B7CCA34C5322872F79B72B569752A29503E24881C88E7D7A5F1DAFE1A7C1CC561CF7F8C42A677842871A0B5CEF414F3178F297C56F8BB88CD8FE972F9C70DDC128265AC8E236FED22ED53D4F21E74EBFED6732D575AEA33079F4B4E2D413C2EAC24024C084900F291BEF8F567677B1785C0703E193403FB6D4D4355F937DE3CEF8CED26678B2A13B17326715C9528D198EBEF6D62A879229525C2BE2454DD3C4789422E7724CDFD79C6F8EA38746130E84A1084CB54B152183BDBEBAF9B522BB89526629D63BC7724AAAE75F07EB42F7B99664398E67529552214585195A9426C62FE2DA2F61CBCED8431D9BA2524A1243B338D7C00BD9CD8BF488C561D0E78500381E0C5E963EA4DA2DCA4CA74F69BA32FD429B5E6CE241610BBF8C0B813206FEE33EFE7B99CCC466B8860925292DC4347EBD3F11A80A940949290A34BD750EEDE8FB8AB18AFF0039D4F9AD71719CD5459A3121AE05048206D6410761F9626F26CB1485238D1C5C2DA37D07DD8B6D7D54B529DCBBFF0098AD6A3306D0A78D2BDC2DA2EA59333EB26E3DF7E5E7D37098796108050EEC0066AF27B0FBEF184A52028ECCE2BE15F637DC57F9967F975538B69F05D7A4C2C15244DEE427A799F5107162C2C9320278260969B94B03CDF88DB9D7F11BF100CC1D85DDBAE95DE20D9AE6C9A3E04345556F5448A6691C454D907621326E0F38F888C482F1B85920AA64C4A5491F35871B3B16D0D05BEF0EA414AA93038A54BB0A6C74F3076898689EC7F5BEB379198662E9CBF29242D69742012DF41C5C2A88E979337E543CEBB628904C994388A9C24A6AFB59FD5857A8859425004200E26673D76FA3116F18EC9E53A6744E8869C672A6587B30E148AE79C4F7AA2B47D828EF02B809BC94113EB8A5946619C4C98B98552D0B6E1AD3CC1F4FE59152411F2B12474AECE35E7EC21CCB54B8E9534D921A1221321201E8040F2DAFD2F187527B30A92F38CD2B53394B17D2BBBC47AA5CD24A9C9074B54F4A5BA6E6230E6614892A52DE879C32DB241FE6904C82B261113CFCF98C4B610253FECAA504B515314038E6C4574FE630241511C639EF7DEBE875E5766AACD2ABBC08711F524A8C02DA7EB5C5B6E5B0787DE47BB94903849201252B53514070D7C286B6E8FCCA889291FDAC5C31A13AF5F752F1B5BA3754D97EADF729694C71250C29F5D6CEC0A100AD920F2816E5D62F1799F00A2824070EFE55EB4AD4F8C3A4100304D5B7BFB7261D6974C67999B61DC932D4E9BCBC5D79DAD48A979C4F350A273F9A9BC8E1099FC2B589CD0AE67019C78D40F0B3905AB734AB0D6B7D62465CE64BB0005FC6CFA9DE9D00892E4FA1320749152E556A7CDC91DD553A8A8A1692B06F2D2C06A395C006E7D21A662679F9C4C082788F0F10268FA82F56AB55F90A35C5CD247CA4B52A2D714B7B689F2321ACC9A9C9CE730A6CA68801C148C32C3EE2D16F0778C8E3498804933798C3246266E20A97294B98A059414E90347A96363E50C8CC58001554BF51E2E6EDD3C6191FCC743658A2FAF2071E7D5766B5558F2FBE527ED1EE1455C107900266061412316B981427F0CBB997C03415F17A6BE75867366926A493B1A37D6BE5D06ADAE76859DD52CD2E474EE32C1F0A51F538001DA5C53408B79F9CE1C7E8A42D7C5318AE80FCC2E07FC41EB7DED0D56B58D68795AD478C469BD61A865EA97954284DCB86A12B94A8CCF76560A607288EBC861F4A380C229A64A0A245B878812D6259BEFB5A149014A075B6B56D287EBF57785AD681A3A24F7B996A843AB172C7D5D33E63882C9E5D27A635FD58529A5E5E9087A2DC55F56E17047DC690B306BD7663F58D4F37A3E9212FE567315A6036EA5F71A8237242779E876BF5BE674DC4BBC8986504B12909041A6ED46B0F3E990A2976D7F98DADEA6CA6800FE1F9421881E12A577845EFF6C198C20BC562D48E05AE62C30B122BEAD56661F88C0252EC5ADB69E11B5DED033152404229DB4806006184904ED278413EFDADCF19C26055885BB4D26E5E62C8A6C0F8EF734A46C662CB39B72F7688C663ABF50D5CF7550100FF006F0276EB045C0E87160C3652400E8A0DEA7CEFCADAD76844A1C92F53CBD2F11A39FE76C294AABA97561CFB1C2E28011B93C26FE73EEC4B48CA9142A969F14026FD2C7E96178C701B7153DB307AC267351D6F279E33BAB8D667DE5437F8FBB133232E9691492936B20680727209F08CF07FDC7FC5B5EBE7E6DD51A96BC1003EFA45FECBAE0DEF78541D8753E98CE232993359E4A054D4A053500B03BD396D0DE70502DC47A837B6A0BFAEDA426FF1357EDF58A983FF00EB391FFF00DE18AB2295A4A4D1EC903EC5E1100837BB6F7D353E821C6875A673421C55357A9A0A8E34BC03DC7D000E93C31B1E1DFDD76537B3C95824CBE1356091C3BECC096F5F187D2DC3B726A3FBFAD63DF2C7C938FB371B1B04CC09DBF1C1046D83D0FC0E08214D3A24AA645872C1042AEEFCFE5FAE08233420099501EBFEFF00BB608236708FEF1F2FCF04119A4013041DBF1F3C10A4BD7C3EF19608523058262013BFE18208D707A1F81C1046E6904CCDB6DC608236F77E7F2FD70411B9A6F7B13B6C0FE1FBBE0823670A7A7CCFE782063B462B4C0040317F4E5CF12783C3226254A590E03B1D99CF4FBEF1B15A1287203D6A5B7E77E5E20F2D720EC715ACD7309D2667732C1370C1EA3766353CADBECC82D7C454B244B7724D9AE69AB72F1A3430E7B9CB792532B3075F69BA7610A53C95BA8471003601441277DA7A461FF66BB298EED06253C4898CA5025D24DC87D85B67B58C577B53DB7CAB20C24C509F2FBCE134E201884F22EDCEEDE31D13ED87DA357982DFCA74D3DC05054DAD4DAE4133133B6F3CCF3DB6C7B47E1C7C2C465E9933A7CB0AA24974D281ECDD5B6F28F10F6FBE2F62F37C54CC34998A12F8949052A2C41A587837956E7A559EEA3ACAF792F56BCE3B56A52D49F1120124F99178DBEF818F5065B94C8C3CB0992896942000484A68E3C398AFD8C70DCD312A528CF99338D4BA91B390F7353CB7F186A6AAA9EA15C35C897366C4493681B0FD70AE33BBC2A7E42900BD38478DF9FBDA253882A62E41A3EADCDC8736DFF1129C934557672B5D5BEB0CE5F49C2A6C3D08E34AA09E1E382A8E71276C52F1D9BA04D1292BF9A61200487A8A55AC5FA5BA43D94492EC40D79FDA9A743D224798EA7CB74ED31A1CB5082F2014A9420C9D89BFCAF78E57C272F018AC5BAC9514962915A0EAEEC40D7587899695330E44F9F9D5F97845319CEA4556540AA75D5F7CC9596D209892798109DA3E4479DBF22ECED38E6A6FA9FE7CBAF9C32C64A0804B8A55F7045075DFAF3222199A6A4AECCC776FA825B48804285E0C72BFEFAE2DB2B289723F6A40DEC29EC57C623A2135D9A06F853DF453890F80A92676100C9B9E585D4A124306A74FBF88A6D56104194E99CE75555213A6A996BA752A1E75C050009BDD71B78B9D8FA623F179BCBC3A0AA6CC609D4338D2C1DFEF4BC0C5DB972F4F0EAFA6AFD83D3DD96699D28DA731CE386B33480B534A0A506D62E76E24804FEED8E6FDA1CEF1989983F4A261924B05071C41C034D81E84D2052CCAB1A9049E5F987FCE353D45731F51CBD69CBD840E1086C253316004705F6DFAF5DE4B26C14B992C623128E298402AE22FA9D0F3E8EC291A4B9CB5900A80E47ADDEFABBF5D6B1057DAAD4142DD54C932E158973E26F1D3D39E2E127F4E10AEE40240B04D88FCF94498410905B47B83F48E5450F2785082A7369402A9923A0373F0BFBF090C5094B69DF225E8E740357341BDBA438952C077B6A3917B03F7685997E83CCB3B2B742D6865882E305B23BD0AD8070C14111CB103DA1CDB0D2912CC85A4294E15C2DE16D0DFA878526619203A6E0BD7C373FCDA2C3C9B485365E90DA1B144BB0571A7EB7C645CDD5C404F381CF7B038A87FACAA624852DC0DEFE8DCF4A8686531205856E096F13A0B023A72894B191A288AAA29D4CE5F605ECC9D4B6E848022452AFC37E612075386989C699E82953AC2AC904A49634750723EF6A3420B5F097E26167BB72A36BB7ABBC20ADCF322A074394F5DFC57334EF56DB2A65A4A87FF00D327F967680784C917C212D6A5A12E8EED350A415711FF00C9891E6618AF1252A3F3120D8F3E81F5BBD8D7AB4BFA8B5B67A453E4C94D2251E1A851A569B35A954F004A948496F807349133279E159587C3021641F92A3E6248772410E7D6DE91B4AC42E6FCA4BBD09B7986B071E7CE1C29346D406CD5EA6CC4E5CB2389414B35416664C2428813BC45B688C2E7109207E8E477CB7A86EED88717342D537F285CA080E4814EACE396AE6A368E10CE8FA55ADC34E3367198EEEA0A96D06CC5CF74652A98DA396FB61E0C3E2A709678BF4C43F12182C2B6E41BD2EE690CA6AAB51C6FB16B015BFBD21054F6888649A4A26996DAFB01B14CDF108E5DE16C1B0E7EFC38465120A84C582B9A2A5414A0FCDB88016FCDC43798B2C00A0AD3F9F1FBDDC98FD7E7AEB890B4B8AA253A09E14ACB9F58E920186E04F4EBCED33232E4CCE10A008A5581296A8EA793F28CC87AB12051F9EE39535F2D621B54F55AD7DE2E8DC75333DF7D6942DC8844CFBA3711CF1228CAF0FC410141E8FF002B5090FE7CE1CC694661510A4D354164A7EDA548E38E6002ADBA6F187A32492082A4A549558BD4EFF7ABDC068C804D8437D4E635C8E22B7839E7C294CFC36FDF538712F21C22D8AC01BFCA0D43B506DEAD625A33C2ADBD47E79C34AEB1FA8214E2CB6048179E299F75FA1F5DF1212B27C361FF00E90E27B800A6A7ADEA6FE42321075207AC6835A968FF00F33B5A26D7F203F7BE1F232F4B8694F4FE6FAE8EF4D2F19EEF9FA7F31A9CCE5B48852FBCE9CF879EF73FB89C3B46014689484B3D680927AB7BDF4C141D0BF266FBC373B9E20589BF9188F4117F3C3A4E015A3807C7E8FF00568D82030715D6BF83086A73C64F0F2DF73F98E71F2F3C64E14CA7E21C43A1F03A73F386F3D0281BA1FA7DE879C26FE36D7EFF00DB1B230E85D801BD0D3D457942299628D53F4E7B7D7CE1155E6297D4DAC37C696E4ABC653131161138728C14BAA480E450B061A6E77DF485D2909622E35FE0BED1F4AFDDF9FCBF5C7C3D8FB350A69D20154C1B6E47CB0410AA0741F018208E426761EB10304119702BA7CC7E78208D2EA488991EFF00C8FAE0823540F3F89FCF0411B5A493C51276DCFAF53821497AF87DE37702BA7CC7E78214850C8202A45E7F7F760823760823058262394E08230E0574F98FCF0410AE99E2C25C4981C7B6C76F7E08238642DC778B913E7F18FDDB98112100D0C10E75CE328A64B40A42DC163D001279FE9F3185A54C9C169972D2A5719E12DA3F423476F6D198E988920CE5CC094A0124380030D5EFB6B5DAD14F6ADED0324D134350BCC6A9B2FF000ACA47109E20091201F302637F763A9F657E1A4ECFE6CB9864F105104BA4D053537AF90DA388F6EFE2F60F29C34DC348988E209525D2AA82DF5372C36778F37FB52EDA730D5D990CBDB7DD4654A5BA16A43CA40E124DCF0907D24DBEFF0052765BE1AE1F2244B5AA4A1C00E38439FABD5BF378F11F69FB779B67D8A9AD3A6196A52BFB8904134A3B3331D5ECEF1D73AD71BA7AC2CD02D4B43A654A528A8C912492A9BDF69F21D71D6B0988952909932E58433024306601BAD3EFB456D05253C53140CCE65C83A53EF5EAD182692AEA1F6E9D8A75ADF74F85E825283CC9E569E640B61DE2330FD22490BBD4D852BA02C75F7687C526629557297B6EE6FF005DE2CBC9B4AE5F92B69AFD46B4BEEA405A1361C24DC02127D224408E4315AC5E613F1A0A6529552012D41E7B8EBADE13485020B11EF5DBDEB0DFAC7560AF6A8E9A99D0D52520743286886C90409E32D9055B082A07CBCF6CB3294AA719AA492B9853DE12E6DCAAD7D186FBC3C97354E012C2BA7E3715F6D14B66B9A13C5078B7B9373E649FDF3C752CB72D421090120160E48B5B97D34D9A1F4BC400003403526AF567FB115F5881E659C2DB5A5B0986AA09E35822101331F7CF9F438B1A244A928E3550A050333E9CBDF3108E366A6600010790343671A9FB38A188DF05754D4A58CB1876B3BD304A38A1324749EBD45BCEF88FC663A5A41248480EE5DBF0FF009ABBD21845CBA5BB17A6AA6C66BA81EE1202568A55133782A100824F3BA76F953331CE809C9952419855C4E412C9E6EF5EAFF48D92970E4B6DEF6FE768B6E9DDA5C9694D164686E97812132128055C22665404FC639ED0045AF0E714A0BC4BAB54A41347E94DB9BC0542A1346A3EBA1FC73F1778A5566B98A56EA89E22A27BC2A215DE003FA649023CA36DCE25F0D82C2A929EF509734402053E971CC5793426651984FAF878F2FCC46DF759AA5296E2BB87A6787C44ABDC0817BC5AE2679E159981E075CA514A459AA29BD75236D2309C32829CDC10C351E2FCF67B33C6DCBB21D4BA96A053E5D42EAE92988151532521295DD2785513D6C77107081CEF0D97527A93C6A1F28A39005B97E4F9484B2A0068C0737A1B036BEDD18068BDF4FF0066F4D94B287AB2A43EF708516D4DFD9205E4FBBE1EFC513B41DAC18A131121010CE1252A724D6CD6D2947E7787489812CF524073B7DBF1CA251515D4B9636942DF699660CD3252826A026D0A5A6EDC4089B99E56C51309371B8A5CC54D52C8D0173AD3F716F768C4EC40018AC33073E0EEC1EA3F976888661ACBBC7052E4B953944FA8F087D3C5549715D7EC94A77F75F78C49CB90B47EF5D4E85874B9F2A93EB0C66E252A040A91A35B7FA56BE4EF0997A775167686DDCFF34148C0054C84F04BC93B8521B50298062E01331C8E1DC941E258BA92DC418B07B56C4977FE61929455521817A7B25D8C6E4651A5F20477C809ABAB45C28A8F89436B1240F4B6DEEC3B4380AE24B59CDC1F2BEAEFB97B3C335CB2493663CCDECCFB7DEB0CB5FDA03ABE063BB4502192A0D77684A8B808DC94266D1B9263961C61A5212A2AE1AAD892A2FC4CE6C6829D1FC61690952487B569E0FF007F3A4476AB3CCC3300422A1E7A6E3C0A2083E57B795A399E92885A1218048E6004BFA0F6E6B0E88704421629B397B8BB969E215B80D2A075984FC663A6D8593894A58A949049A02A0391D9EF5DA1A2C5880799F76A7BD96A348EA7ADF137401C0AFEF521A37BFF005011F1E9B6379998C8921D4B0280923E61E2078D89F48414973415EB7E5D7C9F4736507B35D66E82AFA8B4C81713594EAE29F22AF0FA19F99C309BDA495288EE54B26AEE950D6A2A069EE90ACA414F13EE05F6FC74DE13AFB32D6A1265A6B9C4D5306DCFFACFC3D631B48ED6A9FE67045CF09FB06DFF008061686DA9ECCB5E0134CC30491E33F58A69B6DBA89E5BCF5E789893DB293F2F7814787604B1A5E9F53CDE320136D39C42B37D05DA432543F8621F1D5350C73DAC93CFD7A62730BDADC3AFF6A08D6C4539B80EFAF93504655C563FE6F5880E69956B1C9C4E71953F4C854F741A9A82E017325A49E083D627979CF60FB4322791C4532CBDCA833317E47CB58524A544579B167EBB72FAF38ADB33D5154DB8A61541534E663BD5B6EA408E67893005A7A40C4F49CC654C03854950701C11A16D0DE90B777CFD3DFDE3450EA4ABA54BCAE36EB52EC120B886D54D133209255363FBB4ACA5A2714926DA3DFAF21A8F1A46021E8EC45FECDD6BE4CD0DF53AA5A2E052B304A164925908E28B1B4881899932524710A00185CBEFFCEAF19EEF9FA7BF6758E06A34BD1C46020595F678A7CA6DF87C2313F00A981D20A8867715F0D3A8FC468A92E0907E63EFDB8F0DF7379EB53056224733CEDCE2DB73C248CB6705070BA5C70B7DEDD5B4F04BBB0356D5ED5DFF00970DCE36399D34AE14858F71BF5BDFA75DFD2D87C9C14C4B7C849E63D2DFC7D6125A824B5CF2000F478FAA9EEFCFE5FAE3E0C89885332856DA7D63ECDF02B6F51F98C80099922FD6DB7BFCF1BC60822E232C6C124D40F51188DCD0078A481B6FBF3C1C0A360FE519009B08DBC03FB87EFDF80A14039040E719E056DEA3F3182DB248893EEFD7CB1AC60822E230EE8F9FFD27F3C1188CD08899313D446DEA7CF046E8203BEB1B3801D953EEFD704280836AC66941131267CB1A95A45D43CE36E151D0FD3EB19411B823DD8C7788FF00908D84B59B249E958CDB4154F84988D813F763066CB01CAC010195305D0A1D4465C09E9F7FE784FF005521DBBC0EEDEF9467B998CFC26CF63F86F568DCCD1FD60D85926E7D6379F38C2C852564041E27DBDFBB5DA135BA012A0C05CB8A7BA7B11CD77065ECA96A504800995111600EE4C7EA4FBE42565B8C9DFF004E4A95AD219AF1F8496FC7392967B91A7F98EB476B7DB153E92A0094D436AAA7D2E86381D4A8A0A78B7292637B131F9F67F873F0FE766EAEF71521480820FCC9A1AF303AEBBD75F377C6BF8943B392D387C24CE3EFB8904A14CD60F404DD8F851A3CD6D53DA1675ADEBEA55985538A602D5C03BCB419E40C72B4F9EF79F54F66F274E46512D12010800060D6D682BEF48F1AE6ABC4F6856AC54CC4948592B292490C4BB5FD05EF15AF7DC4AA8654B01282384A884CC9E52798F2F8F3EA32387152871A780B3049D5FE9A73BC56A64D97820650471173F37A3D8D76D1C561E726D3AFE78529A00A2A4AA54E14F840DCF88C8137BCED26D338AF669265E05E677A01A9617BD07F97F1686D2A5CC9F30289294B82CFA03BD2EFA8AD4B88B5159964FA6281140F34DBB5E5252B7400A2D91CC403FBB7962030866E6B88A4D644BB23877B5F7D5BCE2566995C094801C0152CFF004D856DB6F150EA1CF2BDE5AD4DBCA758519093E1E117D81DBE5CEC062E383C9815255C3517A7959BF3EB0C968490F46FAECDFC6915D3F52B6CAD6A7788AFFA788908F7DFCFA4F4C5AF0F9726500B4A78599C357D456BD4D4EB0C660208AD9EBE5B7BBC44731AE5A8A9216093602428C911D66E64587CF12273097857723E5624BB6B66D7EFD61A4C9F32A00B8A372BD6FE2F4872D2DA2B36D60BA8525B5B34148506A9C790503856411C05613C5707EC123699C43E65DA790E995DE00A502129152E342D41E3D442B875A9555BB356BEDF4E757768BD727674AE85A72CE5F4E8AEADE185A8A54A8541132A0A1FBE5B629F9862B158E70A52A54B770805F883BBD08EAD57B43C0A480183B863EEB42FEDA1AAB353FD72A3BFEF14C3927829E0A5279401013B6E7CF09CA4CC4942425C02439AFAD75FC35DF5AA8EE4FAFE3DF266CADAC76B104BCA2CA87D9E19326D13C302F6F8F4BE2C384402DC4013D767DE9716AF8B46C25AD4EC934FE3F30C14ECE735CFA29DB438E2CAA28CB692BE393E2E220787CB8FA88E785F1624A071F7C9414876240A6947AB723E0454BCC2CB493FEE029E166D8F503F3CF78BD7487640F5425ACCF57114ED8E15A10A2078409B8491D472F238A4E69DB43210BC3E0BFDD98974958B0D19CB8F5B3F8AF31284915001A33EBB7E75AD79DB5519CE41A529914997A986587070385084AD4F706D300A9245BF7BF3DC5CFC4E6B34CD993162612E0D404BF205B5FA88426AD09E24A0B00C431BB53C3A52FD1ABCAECF755672EA98D33951553384872AD4EA510956EA09700279EC76E6409C187CA4E1D499D3E695A49FDBD2DA9F01CAA223D731492CEFCA94FA78B8077D192A34C657918359AA33A554D4D6F89597776B2029024A038824279C9116E9B62C38752E6BCB918701219A7050A3EA451F66B5219E226A8872A2FF00F115FCEFF4D2353DABFEA08EE34BE5CD503401497DC08A852845C80EA54A13C883387C32844DFF00F1534CF208524A7E4E12EE47CACFB3F2A43718850601241D5C3BF990D406B4B7288EAEBAB6B5C52FBAA87AB1E3FCC7077894715F8785221099F281D79E1DAA4CA4242414A5800EE1CB6875A59FAD21DCB3C572DD747DFC79D39011CB1A3B51D72C3B54E7D5E9946656E249E1DF6E20498FF6DF0D57325214521D6694009F221F7143B3C394CA04124D34A375D625D43A6345E5A92739A94D7D42C0E0400A4F7253F6AE92649FF6C349C9C62D40CB965080CCA05DC11701891EEF48DD4254A624B93BFDAB6DDC79C66EE6DA53290A19765887B876F11B40B5940FC79EC71B0958C23F7AAB764F9DBEDAD79424A992C9141C989FC81A359B4DA1B9CED26B18F065CC3396255FF10961A7FBE036FB48053C3E5136C61596F7E52A9C998BE1FDACA2867DD8B79DA1B4C9C12A74A80045880D66D8F95A962D467A9D6F9B56821CAA0B077E06D2D5FA0E100EFD0751B0C4861F06245449240B12EAA6E5DDFC4FAD61B4C9BC4CE5B71CB414AB36F0C1539C562883F597999076716BE23D202A047291D6713123264E3D24AD212CDFD8C6B6FF0088F7717856428105B96B777A8F7F58685E6F5C3C23317C0BF35106E660150F2DBCB0F13D96929D52C030A0D7D9EB587108DDCE733490A4662FA60D812BF17FEE3F327F2772BB3126951FF88DA87E95A1DE08554FAB7356665E5BC446E77BDE64FEBBF2C3E4767F0C3FB80074E11E9E3AD057782143BDA066EC94F030CF0ABFE221D69977BC03A7789570C738009E588DCCB23932F80A10B9A03F094A9496A87B1A8F7BC3DC37100588ADC10EC2A3DB11AF8A0ABD47A5F3F6CB1A934D53BC14005B88525926F04CB4DC8F71F7E12C261B31944A70F3978643060A495DABA97676FA43A4A52E4A92EE46BC87DC37214A88AC353F62DD9DEAC4A5CD1B50AD3158D859AA696E3D509AD5ACF8002E2C25AE0DA475BF95832FCCF35CB26138E7C64B531130327BA019CF0A7F7120BB35348DF825ABFED3B56BF41AF5D39C75EB56F60BDA26960E5751D02B35A16E562A1A79B512912A2AE04952AE22DBFDE7A0655DA9CAB14B4484E27866D1D2B4292DCB89403973F50EC29A2A42C00A6A6A5C1E761AB5F4B5A28B7F5156B6EB94954C3F49514AAE1710F36B6C12491652C242A083B480778C752C85781C4820CE96554003A6A497FC579EB68C77547D2BA8F02D7B5E95B8B18D88D44A3E12E0E5042C48DAD63F95F9C62D072C94A0E809376602BE156EA2908AE592E521DAE68F6F03B721E50E14F9EB8BE2FE6131037FBE26E6F724EDE78417964A480C815059CBB74DFF00311D365AAEC4B3BEF5ADAA63EC831F9C095839AE5C94B333823C0398FB38AC4CB510CCF5F1F21D6343DBA6F11CEFCE7CFCBD7CF1212A470DDCEC1F53D2E3EFA4604CE21FB5C0BBF875DE3142547727DE6607E7FBEB87F2C0003D8D4B6DA0FE3AB460254A2A60FC8066E9F9FBDD634024102794F9FEFA7973BE10C4E255254E84710E9CABE95D3988DD0A4CB07BC152D5351E819AF5F02446DC3318C5AE851D5F6D49A563071491F2A405528C697DDCB78C641D71BFB09E2264F5836827FD8FA1C2A898482E1F4D00FA7A69082E7CCAB21C1079D79DB71B5F48DC871F7265C089882426D7F4F891F3C2A99214FC47A06D2EE7DFDA1A2B158B144C9596772029F968C0F58CDC436803EB2A352493C3C1E1088899E106645EE46C71198FC4CDC2377492B7BB75E9CFA74710BE19626907123B903FE619EFAD350DE3AC6D645393C2867879F89447DF1B7C4619CA9D8CC45449587E4EF7BBB7430F26627052407C42001B2853F9FCC294B9C0084A1A8E654E206DCE144193CEE3E7897C2E498FC5B34B5D6C58B87FAB577E750D0CE676932CC3FEEC44B2D562A039EFECD0D210D566F9753A66AEA2999817979B047FEEE53EEF38C5870DD89C74D01C2C9BBF09200AF27B74F5864AEDE64F2B8BFF009892C3750BD3737F43B558B4AB5C69ACB829F39E5236C27FE38E26D731F641F11208EA089838964FC32CC316C89689C566C02155BBD746DABAF48AF66BF15F2BC17FD39929628E42D34F00F7E5CB9C305476AFD9F38E2AA17A96910DA264909827CC71016B8B7E786B3FE10E6F2CA4AA5CE06A482953EFD6A3C7AC42FF00F7D39714F0F1A050D5C1D1FD3760ED788F7FF882D0D48E3C8A0AD6F306CD9C711C490D948812448215D2D389AC97E1C63A4CD48992D65881F32496B55989EBBF368AA673F19B0BC0AE05205C82140BE87974AF2DA3ADFDB07B4AB6F52BD4990BA12A712A49295410152362266F8F41F63FE1FC996B44CC4CAEF08E160A4B01CACCC3C79C70BED1FC68524CC12A6F0B3D44C2D63A3F414DABCBCFFCEF3FCD7397AA2B739AE71D6DC512DB4A595589364C28913E5BF28BE3D1990F67F098342448C3A50081600585EC037D9F78E19DA2ED8AFB5530AA6CCEF382D5048E757A121FA446DB63EAE3EB617DCB0B3E14195151260EE64413CA712F88561B08E1494B8B9A0B7E39379C57933A620325440E4FF9891E53A1EB33CA962B2B12B6B2C2AE25386521494FFD244907E26F8879D9F4A48299412E91400F09D79FF24E8F08A997FBAAFAFBF38B0F31CF69B49D28CB321E05B65252E2C70C8B4925464CFBE397AC28C2E23362672F8B8DFE506A05480D56B35852F405A3604A1D293F2D35F3A0714B6A08D6292CD754B85F7B825750EAAE5478BAF5902DD395C8E96DECEF6695862A993430353A3E9FE29C8B184A612E9726A4DC935BF9DEB110ADCEDD434B35EB0804184FAFA5CFBEDE5B1C5C026560EB4E11577DBEDE0D5D85352A2431F7AFB6886D353E77A82BBEAFA769DDA94A963BF6FC412B04D8F78A10809DCF5DB0D713DA0C3006A904023D8170DAE8046840343EFF00117C699ECC74FE4C84669AC1D0FD7405A3282A50E1501201750608363703F3A263B158BCCE7AA5E1507BA3FF00F7014CDD13AB9A5EAE0BDE0EE65A43962A06DBBEAED421B6D5EF589466BAAA99A63EA8CA114F428494D3D13294A14DA62FC4EA1216E4DC8E2923118325C661A72A6F0AE6AA690EAA96B58924797D291A9412C123A803D77373BF9C578BCD09A82AA263BB0A2495384A84F33E3F3F772EA7167CBF07C491DFB020390696DF61B579428896430218DCBFA0FE34FAF0FB88AE537F5B6D55552927B84B28E1851201E22D0215CB7B731E52AB460E4310B42529152549714AD1DEEE000C6E3943A97C23E635E16A351F4DFC9A2CCD23D946A4D45C35956A19665A98510E841251B11E320FC2F7C52B38ED4E1702BEEE5AF8D6E78528048A740CFCDC561F4B5A58D0067AD3DD7DEA62D166AB44F674DBC8A453559982C27EB0BE12EA82D03C3C09855CFF00A76E722D8A74FCD7139CCD69AB5CA969B24122EEE0B16AEBE70D3173C24012C877AB6E0D3968FCFE91F7B38ED0FB415919165AA4652930BA871C45284B60DC8438104C01CBE7CD354CCBB0491DE7F796763314EF42400E2FAEDD623BBC98B3FBAB7BB7ADF7B56B4B8829F24C8F272EA733AE39AE6C882BA5571A514CB1BA439250B0A33245875BC61696EB5132E5F04A1C244CA7CCFCB46D7534B426EE4B9BD4B9277AB79C32661AD2B985FD4A887F0A4A894A03480F95721240913205E636C3E3292A6E3F99BCBA37DC3460DCEBCF78D74BA7758E7A7BF790A7583E245538529E049BCF02BE7F773C615899520F095849D921CF90B426B524508735A5A9AD6D1236B22D3F91242F3CCCD1595200229D0D91067ECCB648DCC5F975C2B2E6E266B8949212A3498E4335D81A9A381BDE13EF24A48AFCF5F958DC73B56953C9A0A8D5F4F449EEF2ECB9B6985C84AC84ACAC0D89E24120C7291CF0F519799BF3622615ABFB5BE5D2AE030F5AE86D185620243A52CF76D2AE3D75E8394305767B51988216A5B73C924A449F48E47A5CFC04DE1B052E526890ECD50EFE27C06BE702B16433DCF36BFBEA74148634D3A5B2A529C528B907C4A2A889E64902797AF4BE1EA6420B02905BC00F0B7A13F66988C4296C1D9AD57EB7D3ABFD63538844C48EB78FD9F761512258B2436C403FE39D3486DDEAFF00E47D863E7FE1A113E1B000253CE0C739F3FF006E5CB0E65C941A8961B9900D76A59C6BD631DE2DCB93B54BBEFD3FC6D0DEB2DC1F10E8449FDFAE1C8C3A4DE5B1AE83F0DA535AB41C6ADFD0437D43EDB407881E2917E51B6FC8003CFD30F644874B24330D8B1A9D87D07D1A1F609D8EDA7ADF43BEF414840AAE6047119236836FC7CA77FC30E53875357C6A47A53D6EC224211BD5CD9E102204FEC4CFCFCF0B4B9452E2DB6BEF5D6086F5D6A0837F75BF7E779F4C29C0DFDCD6B0FE75B4109975295F0C19DC99B812622DD630EA54A4A920A98DC5439F571D4DE1594A29762D6FBC2571D4926C24F97972E60FAC5F0B1932DAA81AD424026BEA7CCC2BC6ADFD07E211FF0011629DE6E9DC42BFCC980B42949E0E1BC9281CC91F9E18CC934B50BB16707CE81AB4EA233C6AA9E2AF415F187D4EAED47A78368CBD62AB2E77FE221D0878047310EF11DA7CFF00185C56592F10A4AA623E641252504A087D8A4A49F41F58D84D98971C47C61AB54E97ECC7B4EA7A56338A5628338752E019836853629DD588054868210BE251FEA369EB87582999D65E5588C32A64D91218A6471F0950D7E62788F09FC757D84026FEE5313AFAB01D7F160F1D27ED53D9D759766CF2F36A243B9CE975A8B89CD18BF76DEE3F92D95AAD2522676338EB1D8EF8872B19325E127AB827A084AE52D4C52FCD4CEE7F1AC3A9984E1142E0DB571A9FB5E28C7739532D06E83892572971C7014294A4DA0A1705252AF8F3E98EF3844E17152FF51316821829297147B9A1ABF36AF230DD58628F95497357D497059BD2AC07578FB7CC7E6CC4E4005806DE9E2D43E61ED1F5CE5E196E2E583391BB3D89F01EB189415DC49E1DE01547AC6D84578800B685FC391A3FA6FA343D44934228055B7F13B356362131629B799223F3FC30DCE2175E10E2A3416F0AF41E70F654B48AA9403914E7A3FADF468DE4445EE7974FDDFE18DE562012CB6E840F1041FAFF00889191946171B59D8844A61476AED7352DE4238F3E5D712386C32710C10872A346035F27EBEA4D21A63301966041271B2CF0D7F7245B9397B338D8E91C8AC66990B5B8F32DA40995B8DA66378E2509F77CF6C58A47661738A7E457CC47ED4151F161E1E02D57A8637B5B93E59C5C58892AE1B82A4876D9EDE1BE9101CFFB54D1790717F13AFA747083C5C2F24ED7BF02AF37FC2716AC17C33C7E2D295CB9334BEBC2A1434F6C7CB4A9E33E3664181E249321D3AF120BB5F715B6AF14EE7FED67A03254A5392BADD638B2A0F82B578236FB522FD131B62F9D9DF8178CCC4A8E264A900311C697E2D2C5A9CEE5EBA472FED77C6FC1E62C9CB9694B38265A83DF97DFD228FD4FED9B50AE2FE18C84CCC70A84011623C3CB6BF3E78E9584FE9F644A62A4A69FF60150068FCBED531C8B31F8AF8E524A53316EA06CA3A740E39741B98A473AF6B2D7B9BAD28A2A97691B4157111C278E6C394DADB7588316B4E0BE0C61B0801EED0786E784333BB1D0F98BF8473ACD7E25E6CBE2E19B32AECCA50B31F37AEE29D22BECD3B5DD679E89ABD4552C71CCF0855A6DFD2A1E405B6F3C4E23E1FE1B0A18C943501748E5C9E8056FF68E73987C45CFB895C3327D4B8F995D75A0FA72885D6EA6D4C1B729D8CFAA6BDBACBBFC4B71B0D04191BAAFC57DA448B8C5D7B3BD9BCAF0C952E7C89448A25D209D41D1DBD3D1F4CABB519CE68A3DFCD9A18B3A8ABA01567FAB6950CD543459FEA47539551D6562005CBAE77CEF0113C46545511CB78E90621E67392647264AA74C44A4B876E104D4D0301ABD9BF02D12F178E58613D6FBB9A9A69E7ADFC1EE845651E87C9D1943657519854208AA70BAA708524784924A80927918B6E314BC176770D8C9CB9F2E4A65C804143A402A72C6E90430A9603D6AD71A718A4979AA73D69ADDD9BADBA45479857ADFAA5AEA1D212B55815710B93CE6DBFB8822778B8E03249320829480C050003425A8C683D691CFF34CB71B3CA8A96A2E6A2A5A9422F46DC68613AB2B26A29AAD4FA9E4492DB224F1156D10542248E5CB61CE4A7636560E5AA5B04101B4D68EE7F36342C28865597CEC1A9466125CB80797234F5BF568B0B29D2CAA85B59AEA43F56CA5B1C4DB3CCC0B4A130BFB4049239913BCD1F34C67EA94A9723894B07F68762F5FDD7B7E0C5859EB615E6DEC96F3DA156A2D76A4538C9F2C4258CB784A68DD109242478CDC0572DC993CAF7C43E1B27C54D9FC650A01452E6AC7566B060F517D235AB004BB453798E7EF309729D0B53AF2EE5464D899373236B833E57DF1D4320CB5324244C484877A803C6BEDBC6088356E6FFCD652DB6B5D4051EF42413727C26D3F7C7AED8B6AE7C8C2A56164310024380CC2BE06CF616A54C68BE11C240735706DEF5D45625394F66D9D6B071AAFA9596689052B50721129064C85149881EFF7E2979E66B2427BB0B20A8909094953D6CE079D830D2130926C29BFDA2EAA2CC720D194472AC9E95B4D6B8808ADCC4242CD3140012784A55C7C664784CFBC629333078A9F3828A95C176F9AA0D6F46D3D01B4093C229E66FAD7AD621398E64E54BAA71D756F8513FF00C4AF6E63F9009B0FB3616126D8B5E592C4800ADA8C48A0714F76829B7F17E7F7D21A1B0D3ABEF944BE1933DE10525EE2D806CC404999B79DF13B331B879728A54B44B49FECA2B81BAD5CD2DD3ABFC3A41A90E5C317E97A9BFE0BDA24F9668DD41ABDF6D748C8A4A0491DEAD4128F04DFED7018201BEE663151CE339C2489265CB98CA51674B9E2B5481CC55FAC6F31254556029B507A036BF48B9F2F6BB3AD0AC34CB884E639FAC40470B8B097936B1852609B4EC27CCC731C6CFCC674C5913D6845D2789F8C747A30E571E30CE62F841653BDE8CDE1EDF9B346BAEA9D79AB941B654727C98447086D00B676B0E056D1D7CC1DB0D30B2972D45531E6951ABFCD5D4B976B9A5295864BC5292E09DD80F0B73AFDE358C8B4D643DC3950D7F15CD5525352B795C34EB024A968E25257C53B1B401D7124A0B2B4909EE9201E2481FBDEDA79F2686C310A5062E0AAF514AFD4F23A8F04399EB6CF549FE1EAAB0BA758E0698A669B67844C0054CA4131379DE2F33824616521456996EA56AA3C43C8B815D79C1C44EA7E9F48479668CCFF0032EF6ADE7BEAB42F14A9DA975490A693CC84AD416E7A2648F961E2E722594CBBAD60F0A52924121CB5289A8D5AFD6000973E25CFE624ADD1E90D38D9552AD3A9F3148BA57C54FDDAC5F759E130768B58FBB32A5E618A0AE296707C27E5B2FBC1F6A3539E91BFCA9B1E23E829A6FB7DE19EBF5A675512CB6AFE174A652AA642438427902B48936E7CF7BC62530F952070CC5278A6007E725C3B5684B0D98FA5223F15356976376DBEC75D2911879D0BE2719A4358F2AEA79C78A003BF17028FA98FD99697842861C2C1EA001F8B1F1B56EF0C7BE531AD740DEFEDE3686D7F316E80CD5BA1D53A3C2CC4060A6C405010AF5F899DA4A4E116A50253A9AEFB528370D077C40A54EC5BEBAEDE7686D7B3C61CE20D909E704C586C2E39FC4FBB12F270A6CC6D5A1EBF5DB954C6BDF2D550695029D43F5E74FB43554E7BDDF04B89E1331E20408FDC733EB787F2B02A2E58B8B8009A7D453E958511C531C9E55347F01FE3A4352F5118BAC4F5E2E43CFE64488C394E5EA70E9BDEC006F1A783F9D6151289B1F4FE61B2B752287042C73BF103F8E1DCBC0106897A75DB73F43E1780CA22E6F6B7E7F10D4BD48A9238C473F1263F48C38460554F9091B55ABD1FEFBF28C777CFD3F9844E678AA823F98070CFF5723D0DBA4F2B03D061E49C1949FDA45C9A337AEEDF6A54BEC2A7868EEF5DB7FC5FC2C61BDCCD557858B03FD42DBDB7F4BFCF0E061AA686843DD9BC7DF287D1C3599A94092B163FDC3F138C9C2BD8795BA51ABEDE08D6BCC094AAE08DB7079DBF0E5F0C63F4AE1A85C8D09E7BF9B7DA08C98AC0BE2E2500444091B5FF00630A264A903840A5F60078D61497AF87DE335D40EA09E5E216C1DC294A26E1FA7ABF41F4DE148D6DD5B6D05171016372AB029DE62449DBF59C0708667CACCFA5EA2D572DEF9C118A3306AA41432E48120A4836B9B5E0FBC6D37B63656042032920061517661CE96621B4EB1935EA6FEFDECC183E28140AE345424C120F024A9256A1B10A0653C27CF63B6C70C3172A648E032C128550B6828366D75894C0021DC6FD36B8E7F5893E59ACEBF2D6159457329CE74FBE3BB5E5AF849EED06D679C0A54DF885E6D88DC6E5183987F592268C2E392CA44F413FB83DD23E52F6A8DDE25E5CC09F9549E24D68CD53CFFCC513DAFF00B39E47AAE81CD53D9D14525536DBAFE679536254CA9409406F8882E711927BB4AA22F02D8B0F67FB7799E0F112B2ECC662D9C264E28D133C0607880608614009ADEB1B89095974D7705CB0A6FF006E76158FAAB14EF3A0A90E82D93F6004F101D36FC7CEDBE3E20C8913A610385441A00EC29F4E56ADDE91F59F118E9125DD490DAE86FF006B73715684CA72BE9969450321B4B9FF00CC2D7C30A236238C5A04ED3B1C4F617259D3880124BB12361D5B5F3615E55BC6769B0F21C7789003B90459BF3D5A346659A64F9630AAACD6B594388054A05C48D874040B11FBDCD8B0FD92C4CF1F24B596607E53AD99C0A3B781F2AC623E206130E5415350E9E62AECDA86BEC6295D51ED01A1F23B1A969E750141084AD5E28DC120981B419117DEF8B7E49F08F1B9C1E24CB5A58D5924BBDB9BD29CDFC389FC45F8DF8BC9001815A960BBF02C96B33B37AD772CC23AC3ACFDB12B96B769321A314A83294540712E0F230527D63CCDB6C746CAFE0AE2706B42D6851622852696E83DF28E1F8CF8F19E63C1733920B82CB51E5EFF002F1D76D4BDB8EBCCE8A5751A89F7D2A2BE065A6FBBEE42B70A53647174BDF9F3BF55C93B11272F20CD9292433F12013460E1EDE94D22A38FEDD6719985033E7278BFEE56BF9E81CD2B68A8EB739CEF3A714AAE456D5F19932F3C99044EC09DE76F49BE3AA65D272EC2CB4A3B99492033F08A11C9BDD6F150C4A332C7289563660E225DD458EDFDD61D7C43426469E72A882C650FB6AFFCC52AA1C571CF4E2F2E60F98F27389ED0C8CB292C2268D025012C756615E60B786ADA42E764C5466CF334A8BBA95FC91AB6AD48548D25999108A4EEFF00F538099F45183CE07C0DF0F307DAB4628006530AD1CFE3ADC3BD0087E8CFE5CD0C58BD49241F520B06FAF36852D692CC385C76A0329EEF8424171A4C9263FB8191F1BFAE24BFD6F0CA21012A49554B851E66C3D39439978BC34EFDC94101E85BA7D768CB30D179DB9429AAA32CC0FB49EFD904806F04A81EB6DF7EB8653F38C1AD6649242CEA50A6259EE4352D4859385C0CD1C4532EA4172C585AAFADEBE2690F5A734057E64D30AA94A5AA51C4730702D2AB054A6E93E1E60F0D8F989C406639D7E854132144A9764F86DAD6CF5D21B626661301592122CECD4622F46AD6BF7A43FE7799651A5DB396641C2B70A7856EA0788280BF8A09DC9D8EF6B622E463E76366056252A59249E024B002C0D9CF514AF323546768482134E747A57933D7C1DB56A8EAF37CC8D438AA90A71970F8D2A32A50E5C24CA844990244018B1C89F44B27800601A8D6F036D6B67DE1519DCB200501E2CC5EB6228CDEE91B586691C5216F952D959114E38B8812481712AFB5F95B7C490CC0CB04710068C68767D41B6946B0BB46A71F254A07840511BBD2F5F0D398B345A5A7B4E52E5684E6D99AE19580ACB185927BB800B9379B9FEEDE3D6299DA2CC2662E60952145453FBF841ABDABAFF815863889A998414A425EB4F1DB9FDD9A10E7DA95556FA90B3FC9448480610001174A77B81FB3891C872F993129529152410E2A3CC5295637F366CE6A37BF845339AD7F7F52F9AE7434DB5FFCA5E37FB51C246F6FC76C74C9197C844B96A44B4A94C4AC1A11B5E97F2DDED9E1E1153C3B58BEA7F930C748F56E6358DD1D1503952952827BF01400E222E4C5F97CFD31179A6351824B23852402D50FF8B35AD188BCF23D03956414DFC5B3BA865C7DF095B2C2928968A4788113CED756C67C8E2818BCE711899BC082A213422B6D6D4A0D7784E669E3F68E730D45F5D49A4CB406DA48290A6BC00804DE131BC7E00E25F299299A7BC9E1C83FDD5D3636E7AF22E634249A3D36FA7979727AC4442D4C970BAE2540901C4900A957EBBF53FB8C59952E4147CA8482D7A5B96963B0D2EF1903E663CDFC9E1C28281FCCD696F2CA25F093E271415C3732480A1C36DFA1E98A8E6D8C1872A12D40B39A1ADB6A9A07BFE4C6B164657A4725CA50BCC73A790EBE8095374A91F6940494F0A099320EE3CB738A54DCD264D532D642483F315370D767AD74ADDC42D2A6A50E09620382F5A93E57EA2F0B135FAA3533E9A1D3944ACAF2E42B816F1010148062656944D81BCF48C5731B8E9C14AE07984E9FBADEFD758DD7890A003EE6ECFB83A6AD489454645A5F4C334F5598BC8CC739502A5124ABBA7073201503276DAF7C34C3E231B3A6F0AA42F84D2C751CC396D6CD7B4305A8A892FD36F2F65A19731D675B99B2BA64B6453A13C2DA5A1C32361050013E7E7D77C742C9F2CC3293C4B484294CE144DAE4B28D2BA72B690D264B54C2017A390296E6435BC341B430E41936699EBF56A710ED253D2A9257DE9528B895CDD25571B5E397BB0E33DC26070E990254D4AA64C7F9501C820589492CD5A529CC424652921418B26E5C83E1FC52FE32DFABE9BC97C41BEF2BC5C2D456A057B4C1246F7F5F8E2224E0A628B5810E4004D08A3D6E45BD2350417176BD4B8E5B7A1F4864CDF3FCCF38EE997DC2CD352F10A7436AEEC10AB10AEEF878B6047145E4811898C26532A592B4CBAADB894AF9AD66E276F2B3D636330292E406D0DB7D2E756F015A4459C71B6892577EA5444D8F9DF6E7D7DC276560410DC3660EDBB696D81D4D810635AEA7AFBAC37B99BB4CFDA583C5CCF4079DEFEEB6E67A49C9CB8948012FB966D0335FD6F0DE7A0A8063E1D2D5FB75AC30D6EA1607142C2605A1511F0FF7B79E2464654A2DC487AB501A574BB8EB4AC35EE14C75B785DEC69A5493C8443731D44D150E250E70499F7DB90F3307CB13527292C192D4AD3EA7C3F98C890A1FB8172FEC445EAF50B4A9870081D773BF336D8DFAFA5E425654A7608A167A6C18354BEE3703CF412964870D5DF476D1FDBE95860A8D42D7FCDD89FEAFBA76E7B6C6D896C3E50A2E782BD356E5CB95BA3079213C3C4E18500ABEEF4AFBEB0D2FEA36D323BDEB7E2549BED161D7E76B6245193F100F2F95A8FADC1FCF5870DCBDFB3EB0D2EEA141301C9FFEA3637E5C5F2E5EFC381939000EEC9ADDB4DED7FC6B04225E7EDC1FE61F39511CFC893F324F3C3A464FC207FB6FE14B73A7BA410DEFE7CD9E11DE1E67ED91F71FDF9F25464C546881E1414B682B530E246B4A7E34F7E9AA6FE3ADFF00CC57FF00E457E78DBFD157FF001FFDC7F30E23919E36777543FF00EE1FFB8631FE8CA76E1ADEE6DD5E08528CF51B1709B5A547EEE21F2F7E30AC98D886B356C2D4A182370CE9300A5C2379851EB6B138426654514E177F06F16F75F1511AF87BF585EC6728FF009849E9C5D49F3B587BAF384C601418701A9156B3D39EEEC7561A39521C539B2146EAB73BF96DBFDF8D7F46520B259AD6F6FC818215B15EDF1020A44F21CED3D7F51842661D4456D63F6D7D5F94652A29FBC2DFADA5704116BC0249F4F2B0E76F761BAF0E0A5495241705BAB52A5F958DDFC5E49C404A48258BD0687C7F8FABC6F6EA87507FBAF7B100585EC3CBDC714BC664D8CEFB8DD5DD951219E82FE03DD2A21F4BC4A0D8B6FB1B31AF8D8DADAC3FE539A54D02955B40E115D4E4162482D142A03A1683FCB5CA0C0E206390E78595270F3A48C34F40285065814571519943E60C58B067E7123271001704380C09E6075AFF0036BC7BF3AC7B66D1FA494E135ACADD6F8BF969741937E84CF29B1906048C7CAECA7B258D5A920E196F7FDAA0FE83C4F531EF1CEBB7580085706312431FEE1F9DABB1B4757B5DFB5DBF5C86A9F4FA02035DE25C5226564D9264A790E9D37B63B1767BB0AEA4AE7492C4070DFB480696FB0D2C63887693B7EC17DDCF0407019635E43AEC7C2D1D5FD45DAAEBDD64FA9A554D4B2D3AA2375253076E968F3DC6E37C763CA3B1D9722524CC4A12C3E674876E76B695BB33C70ACF3E206378C844D5A81268146A1C9F7F48853F9054370F6719829D2FC90AEFB8CB7175484ACDC83CC7E38B7E06760B23491839299A411C4C86236D3D436BCA2A0BED5CCC7A9B1897FF00885973A58973F52E29C92BB4FA36851C7519B87D699259EE9627AA78879DA6D6E9CA6E5E6F89C6D25E0B80287EF6700F88DCDFC2AF1B8CCF0F313F2E1D24E8CC2B6D35B68D76D21A1CD6BA4E81696D8CAD2667C6A755FCC0911212A16117813F09C292F2CC66255FEECDE02BA049400D5A07363E760FCD2999868892C75BEDD2BBBB6F4168459876AF96D1B455474CC36A1BC14AF6B8DC6F613313E71189C93D869F8801E729955A24B7938ABE9ECB338CC52D8CB4A9AE4077DB4AFB1CE2BDAEEDFABDB52D287596D2926490D2605A2640F88EA22F3890C37C2C389502A9856D5FDA4B750E6BE7D1E1D61B28C5672E161496620170FCEF5B6ADAF843731F685A900977326DA039A4208DB62523CBDDD799B5603E142920140528D4905045056CDE3604D77874AEC74E92FF00EE1009A51886EB42E7AB8A369100CDBB7EFACB8C0FAFAAA5B1C657C2E16529B5AE08076DC0B0F22709E61D959395A4A66A9285D8829009E8EF4E5CEF1A8ECE62921452A5280AB0734EBCFEE41BC4F3B2DD59A9FB4BCE11419526A0E56D2D3DE3A9714A6B845CCAC9E1DC1FEADE6D7C736CF0230A0A829013BB25CB1664B3B9B7DC434998799875042A694AB4049A1A316704EDFC476FABB3CFF0F50AB4FE584A2A8B694D7B9DE71C92014F0A892266C4249DEF7DAB581C1CBCCF10578850013FF4C287EDA005EEEE2DA588A40AC14C989056A25DEF527CF5A1ABECD1515467148DBCAA62A2ED72D478944AB72646E623DF318B6C8C830F2C02569E1BBF981AFD2DD2B0DCE5938170694AB1A8D2A2DA3741D23706DCAF7A8A9A991DED792AEEDB4DC2A6E66011617B8D88F3C63112F05212409C800025DC1B03ABBE9AD74E9AFE82671001449E8C697D7AD0B7A87B7F28D3993E4544732CDD4DAF36E12A452954C2AF7B4A4181B102F8A5E3F138898B230C82A92927E70E3A535EAFD378789C1AD20294B246DA8A01A5EEDE0CE22BACEB573CF1ACFADA9490084D1308F106D3B1FB13B8BDF7F8C4CF65F2D56625467A3F6915533EBA9BB336EDAB340A32A4D0CC0496A3B9BF3AFA1881566A25B74A43A92A75C308812A99816BFAC799C5C96309971212B438FED76F20CF72DCBC28A04952428541D7E9E75FADAB0F9A7BB38ADD4494E699C2D4CE5E921684AFC1C693720494A8F2E477F3931B89ED194132A5B296A042529A8B6A459F991EA2123365A4B15007626F7FC74E7168A6A72ED374668F4CD232FBA94F0B8EA8A0293D482EDCDE763E5CE0577103118F5257892A72E529721AA2EC454EA2BF58732D132601DD825F502876D0B5EFAF237AD734A8ADABA89A9AA5ADC7092E3409086AE6C9E1F09B1B91E5BE25B2AC9A432A6CD02805E8ECEE0EE079BC253A52D052160A5ECE3F9DC74BD617656DA8A85252216A71C84850429504DA660F53CFE42C9E2F1185C1F1095312549B80A17D0BBD6D6D3EA8CC065D5747ABEF6E9E9F58B032DECDFEA4A39AEA1A8029DD85B2D12018173C412411331045E0E2A38BED5AA52952788D1C392D7722E2A0FE63596D33F655B6D3C36D983562734F9837DC8A1D3F40142380BE940213CA78949BEFD794623518A4E378A6AE6710350E77E4E6DB39A6B1998B4A4F091C2545AAD5A3B6C2A3434A3DE36D1E9AA3CBCBB9B67B541E7D10B6698A8DCF310959102C208BFC31178BCB06371084E1A61E00FC6A14096A8D6AF57A7833B33C515A0029716A8D7E9F5B0A8611AEBB58E6D9B32AA1CAE91BCB291A051DF24B60A9239FD94933C3313BEF899C064986C214CC9FFEE2B73AEF434AFDED0D133575150CCE29E429D2B70FE706A4C9B32CD2B1D6689D5D63C149FAD2DC909493241415CA4DB7E13EB737B14CC56598792FDC21C0D05475000724599FD21CA160B82A1BDFEA7CAFD22CBA0A1A0D254E1DCE50876A0890810BBDCC4A245AC36E700E2AD9863664E495E102920B874B87D03A41715FC720E5065A4FCC43806C41D8F4D79BD9CDA23F9CEB87AA5484D2D3A68E9FC4105011FCD02D0A80088E5C5EE1318C64985C5E2262953C2D4090DC4E48E94A5F47F178618C9B2C2992B751A000B123A7B6F07887D5E7A5C3C6F360CDCA94B13BEF1CF6E5F8DAE585C192689D589FA0B1BD6B5F0061B9933420AB84807521FF0087F17FA447EB73E652905A792557949504F0CF2127C899B49C5870997AD4C384814D2A4935FE6EEFA330D5089C43B384D8B1A3BBD1ABA9B52B101CDF5496F8A1C0627FA80B6FC8FA6E7EEB58246553385F80B51BE5D29E36BD34A42467252A62B0145831F16E5BFB3104A9D56A755FF140E136F10BEF1B917E53EEDEC6C183CB0949796F673F6A73D1FCAF0F25CB2B62490E1DD9DC54F833D2CEFB445EBB51B92A3DF0B72E31CFD081F9E2625654A2CD2AA6D4361BBDACCCEDCAD0B19029F35AEFA74888665A91C2A402EDAE6CB11F7824F3E7EFC4BE1F2B98C0196CC2B4D99F7F4F38D44820B3B0F7CDC9F088BD5EA35AB77A081FDE09336D81FDF5BDA465656A0C44B735D1A966B72F7AE5586AF102CF62DC98DCB69AE85E23D53A85DE4E026E7ED475E84CFEEF7C4DE172DBBCAA1D83FF00FB7F9AEB511B09640147275D76D74A35294B986A7F50BC2DDE4DCCF8891CED73E6791E5D70FD3966BC1E9BEEC0F3E7B178CF028E9EC7A7B1B874275039C4AF1CEDCC7CEFCF0E519726A0A1DB71F753728381434FA7E634AF3E7099EF08DCEF73E5BF2DB0E13972187C9C8D016F27F483815B7A884AACF56A375931CC2B693CFDFD3DF8C2F02948FDBC2D761A0A0A836F621442141C949D3EF1C7F1B56DC67AEF68EB311843F4D2FF00E5EBFCC1C497670FB4033C5F270DED3C604FE3F2F96373824B71105AF51F9A42810A21C0710A919DAEC7BC2473F10178E7CB9FE58D5385973094A594D46BB574D746A0FAC618BB6BE10A5ACED6A27F983FEA120499BCFEE309CECBF87E6200480C5C33BEEE2CEFB3C6E3E43F3538980F53EFAC3AB19D2A44B824EDE2DFE7E7F7CC6E19AF06548744BE2A35001EEE1F91703585C4B5A83A524F4F7EDE1F28F3852F8897072E7F2DCCDFDDF2C436324F700712784A8D396F435F2DEB1AA814FEE0DD61F98CCD500F18F5E21E5E639EC797CB117FA79AB2549415234228FD2952F52CF0977892581726C07376D46DBC3E51E653214A06C902E0FDA1E5BC193C845BD1A9C2198A0B52486771B1D76F7CE349A569524B108A574E7EC08764D428414AC137240222E041B7974EB718D664A49490A48200356B68FBBFF9E70B49C428D2DA6EED52DFCF833B43AD354ADCE249516E9AC5F7044A4FF48091E2326D6DB9CEE2B98ACA2522677A164A892A096D056F6A1E8FD686564CC55DE8343B86B54FB6DEBDD07F2A7EB966BB51E68B78995AD25D5113B9B0599BCEDB472E7E6F464597E1788CAC3A54117FF6DADD534E7FC3C6ABCDF3458FF7315354FA712ABB0725F4EB5DA1A2B750E92CA94D37474C2B1E1C414AE35A4A08D8DECA2623A8B47338778693C7300972C4B492001C352D46259EFB986ABC5E22692264C511FF00A8D5C5E95A7AC46F39ED12A92C292D25AA66384880947104C750028DFCFD2716FC176566E2D940A9054DA16ADF61B16FBC32323BD72A0E75700FD4D77B52298CD7B44A36D6A51CE9548A24F1A1495381DF20552940126E3FDAC69EC4E270252BEED5890B63FB2CC694A8FCF3786D332B54F520CB1C201B8DBA1E6CD5D62AFD41DAD65B468529354DBAB0492B2E804F9F093607CF963A3767BB2A7112D972532980705007D40AD35A08B5E579384201980A8D3A790D9DFC2B14E673DB930E3ECADB5B95350CA5D4B0594AD5DD29C0526528078A7948E56C48E65D93C1226C84F7D2E59E2A80D70A17636A72AEE6A5DE27052D2582343A01663EB5ABFDA2AD7BB48D5CB52BEAABAEA976A164A58348F2001C5207196E0083126398E78E9995765B2E19795AA6C952932C70A8CC4248201AF0F103FE1ECD19C1CB44B5FCD2D240342C0F3367B3E9D4421AB63B57CF9756E8C8D4D53381B97175CCB5208B1E12A4949EA2079F5C46644BC164B8D9DFAB216852FE43C25693C2589F95D88BF9178BB607F4C8427BB090A57EE0CCDA8AB7956ECEFAB4BBA27B48AAA734EE5336D33B92ACC1827726092E037B8DFD31D025768FB349E29AA2A134821291216C4B14D592C295F3F04F345A5212124352CA0DB55893ED891689B766DECFDDA4F6919DD26554CD2A8A868D73985621E6DF4069638941442884CA0280BE3CC1F17338929C4F7B257C1296A2C0382A721B84382CFB0B448E5C70EAC24E2A092A09BD284397D6C6F67A8AC7A7DA732DC97B11D3597E8CD2450BA9792539954777C4E3AA0429D8717C4A4DCB9B28C0F28C732C0652ACDD2AC5E632CF73874954849510FC42A48043EF5D758E17DA5CC38735484CD1598CA00528A037E571EAD0B17574798B952FF7AA6DA2106882B88A90E11FE638D47C4A0573F6CDA60784E18E132F3FA99812582154140E03D035D9BC46A6F12D9866024E1B0E65A5C902DD2A7AF3A6A6F11F6B2319957A5145C55554A5C2D494A884A64026448FB26E7CB7C587198708C1A953A67720268A26F7602BBE839C62566A66CB09EE6AD550D49AEDEB6D748BBE82874FE81A46B32013559F54B6A4788A8FD50A93DDDC2894F882B9C4103D31CA55226E231AB95326A9520AC10AE2FDCC5EC0D3437ADAD48C2E7CDE207BB2923400D1FC3A78F898ACB39CD5D6C56875E50AE9E342F8E5203B2B03864A620C6DD77C752C065B2A64AC3B04AA5AD2C4F0B31096AEB53F4BEE86231844B50E0341CEFB6D5FAC4332646679EACD1D0D2386A9A59FACD4AC12921C24A080B1C161CD24FADF1B2BB9CA933921494853948000239DDC97F6CD151527158AC424A4AC242EBE63A73FC345B796690D3D90B09AFD50A45555C05B68BC0526F109907E1D3DFCFB1737118BC4998952D48E3372AA5580772FBBBF95A2F5875265E184B27E7296A80F47D34EA35F44B9F6B2A8AE0C50D2B41BA06F8D14CB6CF006D077E2E10999B7DAB75DB13D95CBC261B8A7CC03BC980099C5524A4101817029A8BE9568AD4FC1E2A6CFE21C5C014E1BC4D34F77A9784B8E3C1F0DB6B72A9D70C70B7C52924F3299D846F3D622E5FCEC5485281484B519A81AD7F3A5045EB275CAC34B4A2704B902EC7424FE3E9BC58F90E81AF75BFE259BBA9A3CB602DE715C2A7109DE128FF88B9D8C030664E21339ED0A30F2D586904F785268976700EA0303AFF22233B438B44C9F27B9E1090A62D5A53C6F5DAEF6898399DE9FCA194D1E94A0EFDE309566DC2A52F8A409FABAD2A32488B72BE39F65AB9B8C9F34CE9C4A492482AB55C7CC4D3D3C19A1C66186C24EC24A2A9C996AE0A92D570FBD74AB0E5A339655A673BCD07D6F52D7C65EF0E26B8949417920DC774950537C361B49911B1C37CEF0CBC54F1230C851EEC8E352412002037CC28AB5DCF50042DD9CCAB2CE19AB9B8D965C5124A5F5A371120F2EA7585359A8E9B4F28E55903086A980E15D42871957532E5F73C8EDE78B4E51D9996AC27793D4AE34A5D280EEE41D9B9162348AF768A4C9938B47E9A7A540289201150FB8366A5F95223158F1CD1C52A9C3B53528238D0952F856A5ED00022D3CB7F29C3695227E0674C13414A41F9490051B525B98D2369C50B912C149058B3D74E61AA36B73A3C8B25D159916C667AA6A92C65691C69A2942145226CA285070C98DC6C79E1BCFCC4AE67712945531F404A438FF0090A1A6C74DE23BBA0012452C2F5AB3D6DEED78DF5FA8F26A40963226C36CB414145208593112A52BC44C89B9C38C3C99EB09131454A2CEE1C1F3F00F71F56137E42A2091B1777636F7D6D4101CDF55B8B90B5156FF0068CFDFB79EC36C5AF2FCB52B002E502555228CE395BF35B4305AA6EB3157BF9B0BD2FE3E1100AED4C9511C64240E28D87C36F9F4E98B7E0F2B4253C294840236AE8C6C37D0FDA23D52B1137198758528252A0540BB2AA3C3ABC42B35D4CD99977C239050006FB41FC39EE312B96646A52D4E93C2F4241E7607E9B3523A6E3F1386958194C8485F08726EEC1EFA9F0E9726BACD751B6784A5D2278A7C647A7300EC63D2D7C5CB099294948E0F9410E0A76B7BDCEF11996CF958B97380482A4A5836E41F33D0D6E62BECC73D016497491267C66E26799803A7511EFB449C0012EA803421BD34BEAF6715B452733C24E46352A4F184859A6843F56DDFAD2B10CAFCFD2A20A5E3CC471458ED3CCEF6368E932313380CB93F334B00534A8F4B8BEB16F12C0C34B2470AB87CFF00C9D1FCCB3C72AB3C041FE7122F038CFE727F1BD8DCE2764E5E0542075007833D3A8D28CD68D00510351B5BDBE86AD11DADCE92A2901C2626E556B8DB97DF389291800E494826971D3D4E9A52D0B212096D05C75B577E4F0C2FE6E9B8EF0C8907C47EFB8BD80FC30F9182096F901A12C45697723A3FD68C21CA659507B253B877360DD3D986E566817B393BF3B01BDED249F2E7F3752F08003F280C6D46E9BD3FCEA61544B4921C13BDF6E51A1CCC904005C1CC8827F318553866D007E87DFA9BC2DDD207F68FC7B6D6B081DCC900CF1C5C8E511F1BFEFDCB0C3A3500F4FF00023532050D4036603DFD3531ABF89A3FE67DDFF763612258B068D7B81FF23E5182F366D304AF6E7E667CE22206FBE37FD089E93F2920820330E7B6FAFDC08732D80EEF878B8A8E0506CFB0D2E3D04708CDDB5184ACDFA9B0F53F95C93388F3D9E0999DEA945DDD9B47D6A7C2EECD08E2BB3C427BF132AAF9C241AB01D76E6232733147085779F3B9F77CA6FCB71872BCB4CE0100708662406BD09D0FD39B5619E1A64C4FFB2A964B1E106951636DC55F42F66781ACDD04C0548039288BC5BF1EB6EB8424640308B334AD4A51735A00FA5F6B7D7589BFF4542657EA0CC0EDC412CE6AE483D3F9856C57000A8BA46DB133D7D48F5B8C6715844E29065A2E2F4B3353404BFAEB48ABE3A64D9B31294A58254D66074D28FE62B5B557B79924812B320F3511F1826E2C6E6FEF386D86C0F7482820716A2AE0396D2A3F1168C9CA12825601F946BAEE5FED7E6D0F9439A24260ACC7FEA3D6D6F758CDFD6062A1DADC02D430E65820F128A881CF561D7EAC62333A50AF754D4B56AD43F4F6D0FECE6D0532E1B40B289036FC87CC72C39C0604A7088F943B397DF4B83E15D75884CB92A5CC2555622E79EA2E7F160CCD25A4CD53F694E9D8589DBCEC418DE399EBBE19CDC2B4D989090D4F3AFABF96D58B062A48084828D9F57736FA1A75DE25F9766A92412EC8B58C1F84FE5F9E22F158321D9246DE7BEFEC0AB06A895F351343CF93EEFEEA369652D7B6A0003CC4DF7B8F744131BC7CB1018AC3109502284353DD8EC2BA8A43F961980B0B8B6EDCBA6DEA7B219EEAB6E95A5FD62B0F0806C571EBCEDF87AC1C72BC364431A383B8097A12C1ABB9603936E213329C38A0BFF817E7B34509AABB4FC8B2921C6EB5282AE3E200970A88D801E254CF48FBB13384EC54B94A0B52425AA03020D5CFA7D1ED1852284804DADA55AAFBFBD5A98CCBB5ACFF00523A6834D52D5D53CB3C083DCBA841262095291C31026E408DF7BDA70E8C0E5AC26A524A06AC2DB780E605232A94A007C8DC562EED67A7F35D233A0EC93B5CD48976AF515635A7A8442D9529DA6796F21775F842C2D25201DFDD87A3B7B9660D6654AC08C42D343721F467497A11AD76891C3144A523BC20F17200FA8FB574A3337E61D99766590A8AF54EAA566D5693E3A5E07D94A9437485A16537DA45B99B4E2532FED1E6F9DA972B2FCACC94AE9DEA48F945DD8A6BB7D22E9829B2152E8D50DC3EEE3E9F46AFF13F649A51B7579369168D414CA2A9CAE5BC5C52365869DE28F3040BE37C4762F3DC462A54EC4E2662F88BB04B04837143CEEE6C4C31CC70A99C7FDB04390CCF770EE6FD0559F68ADB3CF683CC909AC5E5E28E99B69486E998FA95328A78CF008516E7722E76BF58C5F51D91CB30180188C7198E99654B3DFCC40E24A5C538DAFCBAB5838CAB26C4CF530043B3029A9028EF5EB6FE7BE5D867B04FB587B54F665936BFD1144AABCBF35EFD65D69DA461BE14BA529E1515A4288023C33067AC63C6FF0012FF00A98EC8FC38CDE7652BC5A0622528A4CB215319AB555454784770EC87C1FCC7B4B2FBC9485814F980671E8D51FC459751F429FB6CD45452B4F65D54D31DEA4BE456529051C60AB67B98B48EBEFC5070BFD73F64BB95A573D05C3026517773AF07BA458B35FE9CF374AD053C6F6142D701D9F5ABFADE3D1DECBFE8BAEDDBB30D1D4995E4795AC6639B3406A2AB5BCC2DC694CDDA8EF16A32A25425044F4338E2BDB5FEAC7B399EE6527101626092B265B9525290A6770C0286DB1DAD133967F4E59AA3018842B8D948621AA684DDDE8F60F6D68F49EBBF649ED5F48769DA6742E7D95139CEB535634C294E324BAAA26B8EAE405148DEDC660D809938B8647FD47E418ACB674EE20512509EF439B90426C059BABBC79E7B4FFD3AE689CE25A5D65E691FB08FEE6707E9A3D445AB4BF46CFB42D49425ECA96D0A920BA0394E4348DD3052ABCA6F6F43B628B3BFA9BC9938B5CC1352895C44035B24B7ED6E46F78E8723FA6ACCD78592172D7314100D53472295FA9BB7888B7B25FA3E7B5BD1D4119564FF005DCD5D480B2B5B03855104F8C916079100C5F0AE69FD4A767333C2A513310489696484F125C9A87600383BD2D4D636C2FF004F58FC3CE32D724872CDC20B8D03D7DF9C573AB7E8FAF68259733472856DD3298A9AACDA5C615DCA699B53AD0482A9B84C7839D8CF3A8E5DF1E32C9D984A0AC50095CC4A5142CE4802CF476BB5EBAB4BE3BE044FC2E11734C83F2A492E8B53EBAF2B39B4744F2EECD7501A8CCAAB523BDDD0D3551A7714A292AFF2EF29920A428AF7411CFD71EBBECEF6E138BC04AE01C4B9B2819600DD2FC4ED4F2D3908F3F768BB1C8C04F54B5B009514970D50762E7CC7D627398E63419027EA790D334964A10972A470852884813E283636DF9623B1B8FC5E2672153D478CACFCA280026D60F436BE94D6B53728918596B52784FCAEEC36BBDCEFE1B56203579AA5F59FAD2D55255B24491799802474D8751B5B173C065F2D7850B253C5C37200D9CBF56DCEFAC51B138952311C01C241621C806A1ABF7AB6BBC2FC9B4A6739FA9C396B4A6B2F4149AD5BA9EEC2127EC96FBD00AC58CF0131BF4C54B37C48C24E1282C3AC901296502C6AE4394D09201009D00B45C30064AE4B9090403767B0E5F48B532B4767BA3592D102BB3822E9521D514B906627893BF4076F53886188C66266097DEF75243712A84A86A286E6A09B51E915DCE731FD33940248240009607951BA73E6D1853516A1D615AA7D2E2B2FCBA9552DAD5C21086D7BFF002CF0F78142C2C626D18639B63158541938792672A6063303922E2AC091D7AEF15CC3663331934959258B81A07D68D600D0FA3B89AF0698D2D4E56C5334FE6FC278F3499471C183F5720A01E5B743BC1C4365D819C95F7D3B8932D45D726A14AD5B881A35ED53A6CEF33C262B3195DDE1E72D2A01833967ADC569ADEFB88ACF33CE2B3317D6E5456283DC47EA8A49E04BE09F100DA4A528E110088E5318B4CACFE46101C3CACBC84964925D4A0DAB94B91AD7C394060FB2F9CC8529671B3B84D59D41C07A5FC8D3D5A0A5C83526A501971AEE196E097C70994820CC88B408DE60C1F39FC267B83C220CE501C4A0590FA9B86D0BEE2FA343B3956324CD42E6CE5AD94092A2FAD6E59B975E5135A77B2BD254EDB3488455E6CD24F79C5B2957224AA5361F740E78AFE27319B9CCE99C492251344F0B1AE8EDCAE0DFAD2CE71495C9972825949001377207F1B7E62079FEADACCD5E2ED5552997D3B5189088B08E2042222E3A89C39C1654785294228F43725DCDEEE1FEB5308124B925CF3E7B69CE20799EA4A5612820043EA90FA7886FC8CDC13CB9F9EF8B7E03252A524A935A55BC0D5C3FF30D4827881AD68F773FCF8DEF15FE6DAB1A1C44293BC0F101B9F2B8FC63D062F797E48470B259AF4FAD74F65A1232DC07152FD1BAB50DFCAF48AD33DD521CEEC36EA418513E21279D8137B6F63E6631273302A9588C3A384B2D55A74BB35C1D3A8112D9765C898854D203A6ACDB68F6F0B6A62B2CD753B8B2A0974285C1215BC7483CBE5E7B63A461B2F9186972D53120384DC35C36ACF43CBAD0C46666B9B3C2D087570529CAD61BF3FBC40EB351BA54415CC722BDA3AF3FDFA9167C365F2972C2D0010402384392FD1F573F8A46BD9533533D52D692C540317B3DAB7BB50DF42C222798EA074951EF02A761C516DF91DF636E9B6109582519CB41140450587B6FF348B567995210A93338402AAD03EDA003DDD8C44DFCF5D244AF7079DA7EE9371FB8C5AB0780EE9344B95004783BBD0BEF7109AE4714B4252C03063C837D3D5A186B33C74AACA2520112153EE1D27D2F7E5B4ACBC1AADC229C8F4D05858EF51D124E1406E2A91AF95181E5E3CA19979BB8A90A5445C5FC8F9C74E62DD36C3C460CA4B101EF4FAB51A95DFAD4C3A97877341437A7F3EB0DF519BAA6CB85007FAB7B7AC7422FD075C3B4614901869F96D7DEFAC3A12000346BDF573BF88AFD2A959CD5C5154ACC0E40FE33E44EE4018752F0459CD01F60D6BE1D616461F4097D6B46E752F4FBD0462E664AFEE5DA62F1F8DFDDBE161826B26D46625C697FA53D046E70E59CA03757F1BD3C5A123B9829444A95F133CF19FD116A20F93FD49BFA368F5C770FFD8EDE2DEB1A85728FF52EDB9981F3FCF18FD1285D247FFA47DC08C19005E581D7FCC62AAA539CC9888337F7F23B7C2FCE709CCC44BC1944A586E270E457F1AB75A68D0BCB4265A492900914047A83A50EE2F7BC02ACA08014491B9076E77106F1D63EFC48A1099C90A0C41A8E6799A6E2FAE9681299D354000A52491462CDD756F61E35BB982D447888BC448BF49DB9F90DF0D1139026141961206B7048FA0D776F387F3B2E912A57794E221D98120F9BD6DB73856C3EA4A544ABC46F79F8F9EF617116E9853152D465ABBB62520B10D40472F7AC442FBC532524948705B67EB407939FB70ACD5482471F0DC820AA0D89E46E3DFF007401179361A64C9738CD4170A277B13E54FCB40BCB810998104F139701F913B52CE2D0EACE66B21104C9DA3981B91E97F3B79E1A6608561710084FEE34DCB03777D3C29A3C3544B5E1C28005B7D00DBC2961E20830EAD666E20825563E640B4F537F873BCE1BE232F4E3D09F95DAACCF5FAE9CFD68C710833ECE6C4DCBF81A79EDD19EA97355909E254CF98DE663CFD26DF18D3F41DC4B292914140DBD35D687CFC94C1604A5567259CF2AB1A8B575A8DDA2434D9A2B652FED6C26F6EB11163B5BE2710EBC110B52B86A76A86B0B1B736DC6B594C4C970070B90CD5FBB816160695A0897E599A2E5202FA589DFE307F1C4662B04A20921CB5473D77E85F9814868249492FF002BB102FEB6F7B3458393E64A58582AB2787FAC1FBFDF7E5CE3158C661BFEC2F5F99ADE15D7A575AC2A896439BD9852AC4BEB1AA95BED3BB4FABEEA8D87E8E8DC5417950070C6F0A026C3CEF3BE2898C9F86CAD049280946819C54B52EFF61E6A892AA0B3EDA791A7E62C7A0EC034D64094661DA0E6C9AD7C80E53305C20A08BAC10DAC83E844748B6206676B26E2499584415D6ABAA7836A1BBDAFD79EE24F0A5492C4534AD399AD1ADFE21C337D75A5B4C512E8B48B5474CA690529714CB6A5981B853A8E29F7CDC1C3CC364F8DCDC714E0B592494B3A58DAC3E9D7A46BC0EE52E0747B5ABA30D472B475AF51F6C59AA96F2330A9714B54FD58A1E5251CC2A1283C207AF96F8BFE43D84537793A4F11A28F121CD37D69D4EDD59CFC3CF5AD250E438AFA5B93781A36FD6DD55AFABAB5E73EB4D2DF4A8F857DE1B0246F17239C4F43EBDA7B23904AC2A4A512932CBFEE2069C8B52F5163CAD6DCA708B0904A8956A2BA695A3F5A54ED15C6639A3CD394D58BCD3B84A43850C4779F68006402608F39BF96D7D3819331425094028302A34E27346068D7A5A2DB86C38580172DC9E16511FB18EC68417F30D488857EA6CB154F507EB1F58AC514F842549248513204401CE7D7A62A7DBDECC77F92E289C40C30EE54CAE2BFCA6A5886F16F48EB9D92C9F0D3D72C280D2AC391A5F60DA72B47E80DF413E62DE61F47FF0064E92D04BED8CEBBD709971415992C2428993610624F4B5B1F9B9FEA872F9B967C4CCF659C519E81353C0B27E5A26C1C90EFE7A47B93E15E5F87C160125084A8D2C91CF46DB773473B47B3A0212121490BDE2C3CBCA4F203D27738F33489C661583352E08A3B372BFB6DE3A6E63DD95A099009E497722CF46DADBEF53AEB94534C5688111E1005EF1BF972B73C45E284C9988969188FEE70CDB8D8DFCAB611218432C4951320370A87084835E122AC3CDED48F25BDAB2B6BBFFC5E7B3204B24203FA9803C3B4D322796F020FC71DE3B31842BC927A913C02657CC2F50926B6E82D51CABC1FB50A9433843E0C319AE0B3595436D77FABC7AB54E7868284A129054C3455E1927C099E53F198F2DF1C2F379B8C958F98254C51489847083407888D7DDC476BC8F0D859D97CA54C9284932D2C0A43DB524736AEBBC2E14EC8325092B804D85CC5BC85B903EE8C4A499D3D5201571061B9A96F0D796BA188E9D81C01C67089681534606CE76DCFE221FAF1B791A6B3BA86929E16B26CD14E3600F19144F70DE0C41BC5C6263229AF8AC3A66A8F12B1128A0D411FEE0241B1F173F730DDB6C1E1B0F934F9D2A5241125668904512696DDFC0C7C74EAAD78F54E7BA8E85D2AA7E0CE730484892920573C36063D3A5B9463EB17C2DC189F9560F8940FFB32D9D8FF006063BFDC9A88F8FF00F15FB55FA4CE3112C0349CB000A37CDEEDE1486BA4CA737D595F4F4F44DB8780F0F72A96D3565C8BF784009E1113E2C745CE30586C1CA56257313FED8E23C243F9024B1D5A9CC473BC1E74BCD148929155B301FF00736BF6E717552765234BD3B75F9DE4B505D653C6DB050EAD92A5899FAD2525B3C8DCF5F7F3F5FC43C221472F958D4495717013C40A85588E17DAACC0EB68B3CFEC362E64838B3216470F1F10496B3D4FD47942456619FE7B52D653434DF51A7A7E24B25A42528602A64ADC484A5E9E8A51E1B6D189B09C0FE8E6637BD0B9B39214B593C5C647ED29492787C39C73A9D8D9F84C5FE94B8659480EC4176F176B7D3495E4DA0E93295A733CE72F7350D7892EA69D2E28B4A3211C4194AC1DC6F698B6397E6FDAC95809CA9499E996A0AB93A38DF96B70E6F17DC0F62B159EE1FBD44952F892FF00B5EFD0381C9FC18D63BAA6BB33A52F36285DCB929FF84C10A6D6DA0C9F1029413E188E2FBB1D0BB199A65F9C4BE35AE59596FDC52A0A7A30AD35A6B15ECCFB233F20528CF94521C9A829147D2FF626FAC41D9CE93528465C285FCC2BEB894B496CB8A51524F2080A1CC4DFE76C5833C9596E5E8562A6E224C99680E949524F16BFF2046F60748D3229189C4CDE091215398B3004DF981A0EB4A0DA27F94F6579952B4C669AB296A68D2EA92ACA2816CB8555414A1DE0052906DE1DC1EBB639D27B7B93E2272F092FB92CE933810784876241BBB72D758B566395E6D864248CBA77090C7E45077F0BD28D485FAF2B339D26C50D3D2D3D569CA5AA491DFB94AE3A1C4881214E204483D441331CF1BE1E6E0313350B463E54CE253F0256950AE84051DDAA2DA4404ECBB16A92B33B08B96C29C40D05DEA01B7F9ABC52BA87508CB5483F5AFAD3AF24A9CA82384AD452083C3B02276E73B6D8EB192659271B2E5F772D20331501C54F01CBDD445352489D312F54A99A8FE1AF3F08A773CD646566403C8CF999D8833CAFE7B62F597F66CF106451C3A9835F636DD85DE1624E9E5BFBF22D5D08ABB36D53F598E2708E19BF15CF3BDC7588C5F703D9E4CB0974D5AA1AB50CFD4302F4D61CA5254453AB69D3D748AF735D4083C52E1EB1C4479723BDBA7E0459F0B94A5000096AD9AAF46A9F51E5A0859325C907A3EAFC86BA7BBC12B73F68B88594778A01690F178A031C40832926153CB7239DB1B4CCA0CCC5E1D610084A9DAE28DB126BF8D5A27F0004AC1CF0402AE1B9069422C76A5BC225DD957613DAE76E4C6A66BB23D3CEEA9AFD32AA75D586AA50CF748AC2A578B8C904700306F611BE28DF1A7E20657D8691949C7CF460A6630284A429871776520B10D5F017D5A935F0FF00B213BB4D371E65CA54D12880CC4E86DE5A7A5E2A0ED234A6A9ECCF5256E92D6B96AB28D4D96142731A353E1D5214E242D01412400384F2DCC1BC63A07C21ED3E1BB5F942F15879A99C829470A8317770C0FA59C6ADAE734ECA2F20CC528992CCB06654314D9B5F3E5A456157992493E2DC5AFF0018F5F2F3DA71D6F0D94A44D9930A5C1219EB6B7AD6A5B5BBC63B440A9186421AC28FC853DD7EEC6EE6095ECA262473B4F5E5D45883C84626E5609291448716E54DDFCBFC4472243CA4921E8ED5E5D1DF52417D4B59ADEAC02615D64933F21F77A83E4E9184A82534B966FB9AF56E70A230E285827A56DBD6FB3F5867A8AB4920F175D89B8163791E9704FB8CE1E4BC182430706E763CAE6E21D4BC33800077D68D47AB1B7BAC372EAC6FC4608224EDD391803D7E18708C154B80E19DCFF3434E7A43A1863F2B33694F47AB1A7836CD1ADBAC4A64F11B98DF90F79E7875FA5E160DE94A575377D7F98728C2392784BB6DCEBAD2BA6958E175A08038E7717206FBC926FEE8C6C9C3D4FCBEFC2BF6854E149B20BEAFB741BB743091CCC1488EEC933B9E5E5CCFE07CB0A8C3B8A8D742DF5F41A78C6461535E2A7D69E3CCEB78D5FC51FEB1EE18CFE993AA5FA91F983F4A8AB971D2B4B5493E8D0E1495DC6CBAF39501A5330024A67BC0B3004F2F5F7629FDA0C1A5536532C4B636B95390481A3F87DA18E230C7BD972D128CC4CC77502C11C350E357BB3E94A9A6972ADB5FD692D3A9A3701680A92A0E719598F0B64C6C48D8F2E58C62E72725C21C4E226F04A4A38895960400F724742DB30D00E83D9CC8862F0DC265712D88059F90637B30229BEC0595A6FB32D55A9F2ECCAB729CAB32ACA3C99943D5D99268AA4310E24AD04ABBBE048B45947DF0239D4AF8A7D9AC6E3D3814E3F0DDFA97C28477A80B2A70FC20A9CB78DCC2799F6233390B33132D66597247012002F5D74E86915A8CD2B5C72A51564D1AE956A69B70A78CACA1452A1C02F3298163E831D6A41972B069C54C295485238CA8AC335DC9A7F2D6D4B5C1F644CCF9420AD6A241604104E9677E4DB44F74B767FA9F57E5B579B655A7B33CD90C20BB595C9A5AA699A64B61452A24B45A5029178200FBB94E7BF18BB39946612B2EC2E370C674D982594098877E262C389DDDFC9EC4C4F0EC2E324CA066CB522500AE005069A9A8A914D6D5862A2AA4512E9DDA9571B8D2AA1B5B1B290A6CA9041024CA488BEF1E78E8786E1CEF069C62450A02D2A1FB4821CB69C874A450F39C957852A48B28906837FE6A07D840D6726ACAE4F025B24A5237B93631723DD699DF1A6580778B92AFDC0B01D1DE86956BB5DCDA2BE32C095213FB9CEDB11D79B72F0872A7AE91E9E67EEDF6B74E73D5FE2B0CE8259F930EB4F643E90F4E0061C0570D5AA6E3C5EC6E7D22434398250492A2640B93B46FBDF975FC0E20CE1DC9252C4934059BDFE68290C8A4CC253A0D2953B8AFDF9F496D06669041E2BDA21476F8EDF7EFE586389C30AD03D6AD4BFB6A168D152002771A558F377FBFDDA6995E6A94A95E3224833C47CB6BFE43CF6C55F1984624A8380E053EB4D39E90D94185410A0F4AD7A731EEB48EEFEA4D77479252AF2ED2EC314A96D250A791DD83000BF88024983B6C7CED8F2FE5F2B159ACEE2C5256A5ACFF00738034B160586A767021D9E15324103503DF58EAE6AED6A97D6971FCC5EACAD1C64B3C4B09428EF1E2298B721237E738EBBD9EEC22310D366A42258296200A825BC5A8C45EB58D84924EB7DABEFEBA0A18EBB6A8D522BD4B4BEE2E98A49809528CF99E1D86D73C84D8C476BC9BB2F84C0CB4A932D130001D4A6480DB0259DF97A429FA550A31074E7BF4D5B72F78A8736CCEB9D5B4C37DE55074A934EB6817140CC1909E2373D7CF718B94B5E53859478E74894784BA0A904D05831D0D1EBCDA2CF91E5986C413FA852659A37151DF968F4D236E4FD96F6B9A9DE42729A15AA85D23C6F06D9E14AA2E7BE00C409EA7A6D8A3665DB8C264EB599684CE0825B816C684B38483ADA8CD56117C9794E0A4CB79650A0055A8F461F5A569D69169D1FB2556B259CC3576AA6B2A091C4E5325B6EABBC9890436E1E189FEDBC8E98A663FE3263D73E5093819894F1101B88155280FCB6E76035BC45CCC74B9426489412A3C4385419C005C80CE4BFAD75A0794763DD87E9FCC5A7334A819C901417097D89213127849893B1DAE7A5A37B5BDB0CEB3DC8B1457266E18092A62144B82935A00CCCED4E82B16DECE674AC22E58528A7898026868DFC0A53CA3EE03E86DA1D2543EC5FA019D1F972B2EA39CD4477AE3A14057AE08EF0DAFD2C2DCB1F017FA8F38D9FDB8CD25E2F11DE244CFF6A802925892E412A3CB88B801C56B1EF1F837987EA700389355004A8B905C13FE45FABC7ACA84A9284C99266474B8EB279CC4FCF1E5D9397CF13261134A413B9AED7FAF5A476AC5CF4861C1C4776B0E8DAB7DEF0933104A50A0762094A60D8103AFDC0F4E738DA4E0569C54B0B98684B924D6ECD5DF61A7587B839D2CA1654001C35A5A87F9DDAEF48F33BDA9ABF2F4FB577B32B6E368EFBBDD4BC20800ABFCB372424DCC0E9CB7E98EF9D90C2CC392E604ACB2658E100D4D0DAAE7ADE388F6AB17874E71292A97FF00E630346FDC2A36F623D30A31C6CD3AA3C219660721FCA4C5B9CDBF1C7259B2509C6E256A524A8CC3C2EDFF00222DBFDFC23AEE5B342F2D9440E11DDF9B871F9F17E71B908714F49802E77E97F81DFE6061CAD52C4A60CE41A02CE1BFC7973AD6E5C9C4AB1C5452A090B2C482C2A77FF3D4888E6B2E3774AEA26511DF2F26CD12D091E22285F88E5BFC46F8DF2B9DC18FC299859A721A97216920817F5AD3AC3FED6611589C871A07EF4E1D756FFB0E9E6E7E8098F90FA6ECDA9EA7516A6CD357A90C3633BCC56D78924280AEA8200283D2279DCF4C7D2EF869DA6C5CACB30DC1296DDD203D69F2800DAAC757BC7C4BF8C792255DA1C50E2048C42C5F751D743F4D9EB0E8EE76D51D7B74FA66943CCE5EE35C4C349F155265370E04F123840B998DE77C755FF534E272EC7E2312A2B9E994BEEF8C90124A486E13436614A748AD64395230D9865E388042A6238CDC5D37D1A95D478D7DD6EC934769FED6FD96E82B337C929575AEE5B5AB7A987766A5B5529594F13E91DE8928B49079729C7CDDED676B731CABB6D394A339027E300487504B05B0205850B9661E71F47724EC46599C762A64DC22A5CF9C8C239084A5441E07A90E0171CCF311E2EEA7CFC653599E69EC969052A72EAAA969D4148EF29D21D73861C52429C2A026C48000EB18F76763710ACC7B392B309DC6168C2F15492144CB35634A31E6795447CD3EDD65389CB7B5E70AA92A42558C290188FF00F319B9F869ADE3D58FA3C3B28CA33AECE6BF5BEA2A76733467A406175C84A52834CF2DA50497A5224DADCE37B63C55F157B6389C3E73324E1714501135695B176F9A9A1F1711F48FE057C3CC366191CAC462B0E95F14A41495258074814D76AFD691D5CFA403B28CDF24ED3720A9D3540D51E4DA8BEB7F5B094B6DB4D2699A4849E22129209322201F3C760F81F9FCFCC30AA973318A54C40485A8124BA8D280DC78D7CA391FF531D8D9191F02F0B2C251F31570A40A029ABF4AD746B8887FB20F66D91D476B9A4F2FCC6859CD65756AA84A825C4A0A5A2B4F1C71A45C5A472816C4EFC699F9865D951C4A7319A014FCA975077206A473A8D2F1CD3E036024E6B9870CBC1A715C0B4F79404258D5FE53A0AD7AB5045D1EDE1DA9E96ECEBB5CEC972CA3A0A5A5CA74EBB5EAD48865B42B81B710D2E9F8D9420A956981C2666D8E19D83C266F9B23133CE266290B4A9D64A884B850DCDDDEF4A9348F58F6C256478491264FFA6C94AD80092948515001EE01BFE2D48EB97B607B5EF62DDA7685CBB28D06C37519BD2D3210E3832E76894D38037C652A718471EC762769E77EF3F073E1B6759A6638B9AAC74C9B2913905BBC2B48471925FE62D4E8ED68F3F7C431809981693804619625AC06481C6480DFDA34634DDAB68F22739D68BAB6D0E0A97EADC1DE175A4D33884B026C0391C2B1020F0CC45F79C7BFFB3D84C9F2597FA5C462E4255292848599882A5961C4384AFE562750E4C78F8767F375E3311311859AB965648012A00004EA017E474F28AAF35D4B59561468E96AAA409934EC3AF8B1DBF94857A72DA0F41D07099B767247089B99E1D0542814A46875756FD7CE26B0FD94CFA785775974F98CD6428EF7F969E3E1159E61A8AA0294D3A87699E132DBE95B2B3E5C0E2524C499F4BD862F395E2328C6B1C262E4CE701B8549376D028DDA8FE71BCFC8733C00FF00E6F0B370E752A490EDC940575D85DACF09CDF3DA8209E3299B03313E9B4CF31E91899C5FE932F94666216994801F894C186A5DC7D5B5D042984CBF1189253265296AA330249F2D0D869E31147EB2B5E6BBC3956695C82470FD5A96ADC41837975A6CA52204DD5D205A04049ED7764D13C22666D8497312AE101531018920070577EB4899576673DEED43F433D12D49AABBA5916A5386DCFF0088FA24FF00C3F34FFC4F38F69DEF288501A4A6D32426A521C5A78A9DE3F65E128248E8279EC4E3E6C7F5FBDA5C0E3335EC649C163538D4C95E278D522604865AA5900842AADB97F3B7AD7FA5DECB9948CD5799A4A030215365F0E8AA7CC0077F2EAE23C90FA4F9F799F6D1ED756B1C2555196A65238504229624204045A2605EE4E3D39FD1162A7627213278569C3A254A290B51506A93F329F9EAD63AC56BE39E5584959AA7F4265CC5198A7086705E96BD741EA1A3CFB62A6AAA96B14ECBF544D9229D972A15249E4D25667CA3F1C7BB3199FE43810462730C348EEDF8B8E621268F4AA9361E6F1C1734C9F3198A93C7849C525B80842D4EE06C08D75DA123D499CD2F78E55E5799D2B523C5534354C220EC789D6D222F3BFBCCDE1307F11BB1588C51C3CBCF708B9A5410940992C9772187CFE6DE10F53D97CDD3290AFD0CF08E176521428C1B4766360073B4332EA9D75410D256B52E7850D852D4A22660264FC26224C62ED3331CBF0D253899B88968C3A805A6628865248705C9666E7E17847FD1F1B2D410AC3AD2A51FDBC25DDF52DE97F186EAA5D43062A1B758528F843C85B73D63BC026046D244EF8532ACF327CD57DDE5F8C953D4925C2169241ABBB13F4B36D0FD792E370C90A9D8698806A92524537A86DAAFBD748481C71E3C0CA5C79667C2DA14B51F720127A9306D7EB896C663307974B13719391211565AC8F17A8F74D61F61320CCF1C954CC361664D4A3F7292951677BB258D053ED78D2E9A964F0B8CBAD2B925D6D4857C160131CEC7E186D97E7D93666B28C163E4CF502C52852491D589FA427FE9D8996A32D72D499828A0526EE69B0F7CE13A5558F71772D3EEF0DD61A69C584FFEAE049299E40C4F2C3AC666795E585031B8A9520ACB242D690F6B3900D4EC5EB5348772F25C74D415A30D316848752824F08BD7F6BB53F98D68A9712EF74A4385E5FD96D2DAD4E123786E0A8FB87CB0D319DA3C87052933B139848932D41C294B400433EFEDE12939662F1333BA91216A5A4F094A52A517766A5AADD7CA1CCD2E6E96FBE5E519AA59DFBD396D586E3AF7859E1F3DF11586EDD76471733BAC3E75849B3096094CD412EEDA178959FD8FCFF0D2FBD9D97CF972D9F8952D6CCCEF61A08D2DD653394D52D5532424800B8A25B2D284C4A6CAB9226622DB8B61CE6B81C3E3A4A71D22705F7693351C350A08054E5A961476DB788FC160CAB12996B4578825448B0763D3A781E7ED87D1C5F46D7651ED01A2D1DAD76D5AE32BCAF4AD3B89A84D1D656314EA7514EF10524FD65A7374581078B90BC1F9A5FD527F5419DE4017D9AC9B289F8A9C53364A972F8C04708677082F67BBD3C63D37F0FBB2194A9289D331929165709625CB96297D6DD23E8A352763BECDDA0BD8D7B435762D94652FE4C9C86A1A7B3A453B6F2AA1746D3EDA16DBCF214A212E20DDB70C8E626FF363B07DBCED3E63F12726CC733C5E310538A9B351853366A59D5C452A4F1071703886CC184764CCBB37835E5AB972F08853240337841715AD459B5F5BC7CE37D1D3EC0BD9C7B4E506AAED5FB5CED2B2BC9F4A6439EE60E1A2AE14F4A5D6D19A54A3BB014FB4E2802D40213B444E3E907C52FEABFB4DD9AECAE5D91E4DD9EC4E3F159AE0E64B13E5A9694CBEE258E251504101C56A43E95B50324EC4E469C619B89C6C99650B1FEDAB841249B00F4AF237D9E3E9B321F67CF66FD2BEC9FAAEAFB23C9F24CE3237B4D66ED8CE986987455B941495282B4B8A42D40A5D41921773D6063E6164DF157B5DDA0F899819B9862317215FEA282252D7308495CE4F121A80B3B07A8F37E87DA3ECCE00E4CB99859289A132DF8D207CAD7AB5776DF5A47E7EB99553CAD5DA81FA670AD946A3CF5A4B53E14A5BCCAA5B09126200004011D06C31FA51F85AB389EC06553B17F2CC9D8294A73534969F534A3B11D23C5FDB3C261E54F9C94949505101340CC5BCB4D3ADDD61A9E179C360A20152428409120743783F3DF0D64CE50CDA62250E24998C4836A9B36F5F50D578E6D2240E30E011FDA4EB537A68DF4BC2EA5AD22C5422473E91B19FDF3DF17B9D870653B7F66CE6CFCABE5BBDE15CC30EA4C8701C0069D28F4FCDAD687715CA44428136BCC6DB72B72B73B46D18ABC896A993660092C341AFDC59ACC1BC62B3224BAD4EF7DBDFB2D787EA0CC9700C9E5CF6E5204D8F4F913CCC46195574B06EB7AB81AF8E9CC18DD72D9C1A8FA3F5BDEE225B419A2E6EBFEDD95B79DBDE3DFD6715AC7619469C06AE280F4FF01C5BAB329A9B38FF00D5CEB4B794762B54E6C071A83A41333E237F58DBA5EF7DE71C7A565D225E253C12921883448152281C6D51B4339649559857C6F7DAAD7D6281CFF365B6EB4FB0A9711DE44999E4678A6C7AF58C769ECFE110BC1842C3215C2EC360E2CDE21CED13786AF8375E9EBD1B5178A7EBB33ABCC332397B6477F5B534F4EA240801D712824721014762248DF125DA5E2C2E54461D4A4044B515106AC2B73CAA7D889895278A6254A4FC86C79B0E5A901AC3AD63BE792F641A23B2BCAB2CA9CD69855E76ED326AB89D4AD694ADD6D2E8B282907EDCF3DA48031E5F38ECCB35C73E1B1737F4FDEA90085AABF310AA39208E7F888CCD676264CE0B0B29516A804381414040EA79B934AC573AED1B387EA1C6A90B34797A014A034869A21116FB294AB94FAEF8EB196F667032A44B99350A9B3D41255C4B591C4C0BB17162697DAD161C063316BC1CC2A9A543828EEE457C6CEFCBA5285CF359E62BAEA86E81D76A5E724A94BA8500929499E14AD445FC85E3DD8B22B29CBD6A92956165A96183809716636ADA9EDA23275CD5E3546628A92A5901DCB876677E74F3A98AD6B350D7BB46E2EAEA453BEEBED0727857094BC018BF4990236DB1359E76764CCECFE365230E90A561A6540AA7E451156AD3DE9178C405CBC5E0FBB0CEA4B80F40E9A96F36F311F6FF00F44CFB487627A07D8CBB31C8339D5749499930D6646A43A8292A5AEB0AC0054A093626627CF1F9D6FEA4BB1B9D49F8859DCF5C92705371044859500ECE08FF0095F4E4C358F7CFC27CD64E5B92E1C14FFB9DD8E335776A58789FE5A3D3C67DAE7B07A893FE35A0513B789223FF00783D368C79E667657311C24E1C8059994039DE86DC8C75D91DAA91312B2A092C39967F06F7CDA305FB55F624AA86186B5AD125D7C90DA000E070CC09F19E1DC7BB6DB0CF19D97C6257294B42A5A9C355DF97F9BBDAB0CD1DAE90913425600D6F5607D456DBBBB831D07F690ED5FB27CD3DA6FB08D495F9AB0EFF0085179EAFBE43842426B29D00294942B8556BDC1B74138EDDD8FECCE3E6F67B1C6493DFF749E04B0D01E2BB5EB7B4705ED876C24FFAEE140AA0CE72412EFC405B9791FAF7968BDAE3B1147749FF001C51381D6DB4A29F8384B2A420050278A4C9EB1B5A0638D637B25982F1B3D2B796B4CC5380417254FEA5FA73AC77197DBBC2E0B2FC12952C282E527889A30090C0536D47DA256DFB4AF63B52D17D3AB290242642B626D22DC40CEFBFA7A88ECCE612CA122515B9B920077D9CF21B35ED12D84EDCE027CA331284B84972D504F36372E5C0A39BC42754FB4E7636E64F9B32CEADA572BD596662C52B009056E3D4AEA001E21CD437F8EC70FD190E2B0D9860538895DDF14D965831765A6ED43B78D4456B3BEDA8C46539A32C1692B09029FDAA05CD3DDA823E726BB4D6A1D439C662AAA74D2E46E667983E97C29278D976A9E701001076563E90760D587C2E43841DC85CC3212C1AAAF94063E8FE11F1E3E27E67FA8ED1E2C951FF00F10B377BA8F3DEE1F76D1D5A15A4F42B81592559CCF34752A43E56C2D2195A92522EE05257C526FC8EFE53B2E4E2B3454D95DCAA44A7AA41278C39B6C035999AB668AC23303225CA5057FB80122B66622BE9EAD1EA67D1C3DA356E6B4DAD74267D5014D965A4E5ECACA600A843AB73BB40B0B284C0DA77E5E47FEA07B392F2DCC32FC7C99211DDCCE359081F310A4DC9036AB9FCC7D02FE947B5666659986131F33BE4CD95C284CC53B5160F08579EBA691E6DFB57D02F43FB446ADD2F48CA826B336CAD9A6436D1850AE711DE59293301D2609B795E3D03F0CBB5D82C6F60569529089D2706B4A8135044B291B3500F0E748E49F1ABB1E319DB5C26270F2190BC5B92948ABAC56800F46D9DDE3D63D679EB5ECDDECA7A4B4FD3D70A0AFA85E55514DC09EE9C70565753543E0410612975415CA3717B785F3FC9A7769F3FCCE76154A9A11885BB025BE657E29A1AF87B5BB159B49EC8F6772F913C0940E1D00020020F025DF7B86F1140219FDB652DEBAF673CB7B42A1A84D65465397D0AA9DF6520281A92C21F3C683E466F3F3C74CF833982BB31DA219762014AA7CC9685A9668CED650DCEDA5ACFC77E3BC8576AB239936534E2A9534A384026B4D37B80C28D778A1FE8BBD38ACC751F6A7AE3362A552E434B4151953EE712D3E0A675555C04CC41410A8FBA23A6FF005398DF9BB3D83C3AF8D3981095049A2788CB0280B7F73D5E28DFD1B7674E447B478BCCE571197F34B334587FB960A0478383D2F1D00EDF3B4DCB3B5FF6D6CC1CAD6C57698AECE692810DF787BAFF002FC34CE0481B12B490A81EA2F8BA7647E1F4EECC760A7E2952D4A5E2704660590470BCB2A0C5BFEEA6BE04449FC40ED2C8CE7B5D2F0B8629E04E2420A50A0430500D4F3A6D631D85FA4C7B09ECFBB23ECBF446A9D0990B397BF5B42DBB59DDA882F71A29E49E202D0B5796E76C3CFE9073EC42737ED665B8C9866210660725C83FEF70B29CF0B10051ACC6AC218FC68C99183C26453652693929E2012CF496EECE68EEFD6DADC5EC3BEC93D82F6D9ECCF95EAED55A69877387A87303535EA75C49A782E214E10980B800AAE6D1CB1CA7E2E7C43ED4766FB6F3F0F85C6CF121589504A12B57FB80AE8007A338D2FB88E87D81EC064D9BE469C5CDC1CA0A449054B29490E52EE695766F13E1D77CB7B55FA307D95F5337D966A5ADA5CE7575066CE50E74A5D0E6150D2DDCCAACA695B0EF03AD00D77A124A55102F187F2FFF00BD4ED5E0F119A617178CC26151251370C4052C21900AEC6BC446BBC5C3B2C9EC56598D56031587C199A66776C5281A90033737E8417878FA4D3D843B14CDBB0EA1F692EC3F29672E6F2DA36F31AB5D138E38DE60D661DDF7278388251DCA16491C2798306062D1F007E3B76A724ED88ECFF6AB319B3947132E5494CD74F02428853D4D081AB0B1B8880F8E1F0DB28CC72F46332AC24A948EECA94A9612D514B0B3EDCE3C95FA3EFD8CAB7DAFFB5072873D529AD09A51F4AB3B7B825B525C0A52525692950F1B651E156F36C7B53FAA0F8D583ECA76572F5659344DC6E61872112E5CDF996B2945B87626B7B4713F853F0CF0F88C7CC33D2172E52D24852416626EEE28CCD7F331ED076B5DA3FD17FEC44ED37657AB32FCAEA3324B69A5D4714B53982DA70B63B9529C6DB78B654553E150BEE4C63E7164B86F8B7DBDC662B32C1CFCCF0F216A13249489AA4A03BB3BB105FF00168F54CEC1F63B2E912F0B3F0B8452929E151504024D8D1BF8AEF1DBDF602D2BECA39865BDA876B9ECBD5AC3B9676954F42FE7397B02A1B5529CB5A712C0522A085A78C95010948E5046DC7FE30663DAFCB73DC932DED38C44D9A89FDD89B394A257F3201531729091A3F3ABD1DE5792E513F038E393AA5C80B40F96530268A37074F1A7311F2D9EDD9A0F5876C5F48CEABECE34B65EED466DAC334A1A4A4A169216B534C53A1352E955FBBEEDA25C85471011D4E3EBE7F4EFDAEC8FE1E7C239B9DE3B1B2A4ABFD3CCCEF145293C5C059342093C54E57358F3EE33E1D4DCC3B4015899AA9A9EF8B25609A055C13AB55A3DB2D21EC57EC31F474F627956BBF6A534555A86AA958AB7EB6A8543AF5454B8A42C34DD134A70ABBA5B81B3C283B49006DE1EED3FC50F89FF001AFB4999E1BB0F331872FC36226A672F0F314A010A52C24802B5636F08EDEBEC6F65F26C1E1978F93875AD284901410E4802E48247E5CD843AE8CED37E8AFF006F2AD1D8C694A4CA58D699834E31434BF52AACB54C843656DAD0FA9A612F153402880A244C1BEFCFE7E59F15FE1E6608CFF1F3F349F2B053113664B519C12A2140A81724338E90DE68ECAE3C8C2E1B0987750605212785A9B397B5DED68F1D7DACBD88321F60BF6BAEC9B33D4CDFF17EC2359674ED3525229B506128796C539429E1DE3A65EA800159F43C3B7B8BB2DFD48E3BE26FC3CC660A5625597E719560D689A9E22B521610A0826DC5C5C1D45758A2E73F0FF0D2F32C34D4E113DCAE62492122A388122DABBB73AB3476CBE995F611EC7B40F609A23B68EC4B4CA74F30DE5B435D9C2A9DC79F4D50CC51485A512BB2203AA22DD7D71CE3FA55FEA0FB519476C336C176971F331C9FD6777253314DC23BC58701C9A863A8F38DBE28F65B2EC365584560F06842D329D44243BB26EC0BEB61F58EB77D0CBEC69A0BDA2B5EEAECF3B48C9115DA5F4A379686DFA9714DD3B8BAE6149578EC9052E8B4F31B49C7A03FAD0FEA531B90766B2CC264188386C66310A226CB554B942943875A1ABD5E25BFA7ECBB2BC6E0B35958DC14B9CAEEF853C4134A2C3D41AFD77148CFE9C5F64DD15ECCDAABB21CCFB27D389CB322D4633E5E7556C294EB01146DA0B01448291C4498BFCB101FD0C7C4BCC3B6D8BCE26E7799ACAB02252D6664C241E30A51A1506B6C45F68E55F113B372324CE3113A5C905136728CA4705140ACD1EA035F9DDACFD87FA2DFD917D9F35B7B1EEBFF00682ED6B49359BFD7B23CC6A324CC2A5E7996D353963756DA8A00849979B48E524629DFD62FF501DA7C27C41C9F24EC7E70B9185C04E50C6CB90D30CC1F229292C5C380776D8BD7A9FC3CC8F2AC66478B18FC1CB13264A696A5330252AAFEDAFBA433FD16FF0047C7633ED01946B2F6A3ED7329198689CB736CF1CD319170BC80D51E519856D354789985B83829D2BF1209E84E3867C56FEA47B5D9965594653879D88C2E2B13284A5CFEF540A0808054524A5F8AA7C1F9C2BD81F875976133AC563674B973A4A269584148660A510CEE282EECE03C76133EF6D8FA209F5EAEEC8F37CAB2FC8AA72466B32CA247F07CC5C73EBADB6FB2905F14C140FD612920A951B99E78A9F6313F19666639763324CDF31C62A6E2242A68016A4AE5AA624CCA9240F95EDCAACC23B1F6C71BD9E9992CCC20CAA42572E4A92662529BF0900B04D5A80D5CF947CB7F6DD98682A9ED2754D0690A448D286B5E772AAC69C7385FA7756E38D1088E26F852A40009E77BC63EF5FC2D19AE27B2182979895FEAE6609099895D4998A9490B725EA0B9602C0DE3E7D66984C361F1F8E992F86B3144240FD9F329AD43EEA5DA204E7699DA05168C4E8ACBB50E6F43A64D7D10EE28B31A9A50106B10B221879060991D0DE6C4638DF6FBE086071B85CDB35C76024CF294CC9A17325A4AAA16A35209A0E679984BB3798E2E5E6F874CBC64CE033405490EC9AB0ABB1E63611F719ECCB4196577D12940C55079D6DCD299BA9CAA7DC75C71C5F0BCA256E2CF1AFC7B1528C998C7C5CCCB0B87C17C7E46130C844AC2231E89699290004D92599AE6E1BD23E876569953FB10B98B960CE18572BA12FC14D3CBEF1F1263B45D6195D26A5D1596EA0CCB2FD38ACFB37416286B9FA34A93FC52A5442FEAEF2146E49BDCDED8FB5123E10651987C3D938FC560244E9BFE9C572CAA524A83C804949524A83BD5887E758F9EFDA2C6E6327B52A12F1B350062FF00E902B0923BC6625C69C888FB62FA37436DFD10F45C0FD454A91A67582955352FBD50EB8A5AEB4925D794B70DC9FEA81E58F87FDB0C1E1B24F8E786C34A9489586959AA1299694A5213FEEA1DE81DCEEE7C9A3DDDD9793FAAEC4A97894F78B5610152C977F91C13B6E1B6E71F0D41E4FF0019D517B1D4F9FDE7AE6F567CB97A48DB6C7E8E7B00A188F879911C3B07CBA58615A8949B3035F060DAD63E7B76F113067F8C96147804E5F0DD802A3FC39F106F07D6386A5E954FD98127A6D791711D3117D9EC22E566589993417E371C557D4DFD3FCC56E4E19425CB2454025F5AF2BEBBF4D442B65F4A549F1117D8133B9DBF111118E9C7826CA5310DC2CD7D0FBB51F70D0EE6CB070EB0A0F42DCEF4F5ADDEA21DCD581C104806C04932237EA6F6F33E51882C348EEE6CCF9581347D1AE08A8FA3F28AAA241EF4B503D5875A537EBE46EED495890078A368BED3D3E23F29BE179A8490C589624F869F6DFCDA313648276D542BF9E477DED125A1AE4C99267C30677DAFB99FC09DE4E21B13265F1D520835622C4EC74F388C9F29945C5363CF5A1AFA9F38BB35566EB3C70BEBFD43CE36900188FC0922390232E2A9C9530A9AB077DFEC7D98889490A55ACD5AD7EBAEDA738A4F33AB7EA52E21A5C3A2E825406D1363E5CB68BCE3AAE4321387929EF43A05F50E5DB4B124B7B1161C248B52A0723BB1DBE9BC55D5D555F97D6B398A163BFA5ACA575C3292785A7D0B31FF00D2920C5AF8CF69B0C313835CB961C290B4816A28105EDBB1B78C5A70187965491387FB6012F5A16A73D06DA7231EC2D0E6343DB5F64794EA9C890DD4667945070670DA16953A8521096592A6EEA121063C33F7E3C9887ECA769A7E0318A29C3626705604A87CAE3E69B7A0209D6F0CB37C009C25CC4A6A824289A382ED4DF7DDF58F3FF55D53A8A8ACA6756ED33ACB8A429B295A4D94531C8F974DCDB1DD70D99499F230FC052470804820B8206BEBAC38C2614A306BA31092CFBB6C3D19BEC6A1CE2A1B6E94D552D6298A961412A012A529C0E2A0DA64409E7127A0C5AF0384EFE64A524D8855BF8A03AF2E710793A267EB485A010A98782AC181A8A16F0FA51E155F574F58EBB978796F3ED86D6E28A54890A0144126DB74F77417FCC241959262E7CC4A512BF4B31C382C532C87BEB52CEFD63A16225A9388C0CD029C69AB87A902B7D3AFD63ED77E88CF630EC27B6BF627ECBB55EB6D3F559D57BA33712D66B5F441A28AF536ABB0E212E714011702DEA7F365FD5776CF189F8939D6065CC12F0786C47FB44049E2E2249AD598BFD2CE23DE1F0CB234E3B22913520F11949E2150CE06A59F5FA3B523D456BE8DBF65AA623FFE03AE03911A9336303CA1FF0021D463CC333B578E584BE2980141C29D7EC2C1FA474DC3F64C244D704F10B329CDDF97AD18C3831F47AFB34D0BED3B4FA1EB42D0AE20E2B50666AEECA60A6389D26FE5CF0C31DDAB9E152C4F9C95936F9406F001E9EE86AC91D9204CE025100DEF5A3FB60199F58E8D7B457B34F63B90FB4CF611A5D9D2D50FB1AC1CCF9A52179BD60211434C9FEA53849B120472B0C769EC576BE6A3B3F8FE09E1333BA1C33784167E270DD287626D568E0BDB0EC71FF5FC277608499C1856EE1CF8F883AD8C776E9BE8F0F65F3DCD4AB485635565B6DCA8FF00E399990494050801E001E4607AE3924FED5E28E37124CD1326198A2E400D521C001B6A0B58EF1DE25FC3DFD5E5B81EF16C44A4B062744EA0E8DEBA6B2647B107B36D3B229C698AC526200FE31997DFDECDED68F3C03B439AAD49299818170191C9B41AF3A1B81489BC2FC3993230EB48554A7FEEE7CFF817D4B4373EF61DF66CCBA92B734674A568CC6932FCC2AA8E737CCD490B6695C7495254EF0C4A07DA91CE3A3E959C63B178EC1AF10B0A289F252FF2820296806D5B00ECF50FD28D9D7638E132ACD5810F26656BA254CF50FB7947831A8B5585D456D065B50728A0A5CC6BE999640FAC1E062ADC6805289E2D900DE37DE44E3EA4760F2892AC83033D127BE52F0F2CB92DC24A126D50F577AB97A5488F8E5F14303364F6931891C494A3113372FF00316D0FD39EB157E6DA919CBE1798BCDD436A5781D84A0C922E40F14926D72676BC0C746CBB234CB13172FE4580EA05360493737A1D08F431465F7E664841258D0726605EFBEAFBC7643D8BFB54CD727F689D274B96075594666E3E8AF5281699504D390D7138B0126E6DE2BEC271E5CFEA1B24978ACBA74D080A5484AD5C406C1E80835A3787311EA5F835DA09FD9DC760E54B9851FA85A1376FDC4021AAF43AD9EF1E95FB45F61995EA4F69BEC673E6F2B15CAD6AF57D4E6CA292A43472CA765CA72B51494DC8944C49B0DF1E36EC176EE6E5F2339C12A62A5CA96932C20A8BFCC169FDBC8B75BED1EEFCDBB132B3A9D94E63DD85AA6844D2784528824DBAEBD23AD7F4A7F69CC52E7FA1B413084A19D334CF273069A7C6FDC32BA7EF1B4AA525251299026245B7EFBFD3C761D3DA34E6F98CC1DE89EA2B0E976F9A61D47D7978729FEA2BB4733B289C9B0B2D7DDB0082104876E00CC36DABD358BFFD99EAA97B78F624ADC89D712FD65265798F7895381C752A654FAD80A049298E04F082013CAE71CD7E2CE0E7761BB62AC5A5E54BEF9250C0200E020166BEDA50C59BE17E151DB7C97867FF00BA7BB4B05391F303BF5AF86911CF672AC47B3A7B09EB3ED133C0296BDD6F51D1D4B8F8EE5C5835F5D474A49500612952786D7E538D519DCDF89DDADECBE0A6CC52E5CB9A8E034570F01965B672CD5B6D175C5F66657C3DECE677899284CA54C92A24A592F45D68DCD9BA574F9C3EC1F5EBDA8BB72D195B5B52A5B95FAC2BDE2932B5BA87736E26EC24C00A107EF8C7D53ED664186CA3E162B8E5A50519594824004B61C8A3B17A73158F017C3FCD67F68FE214E4AC952518FA3925819A7EC03E9A0BC7BC7F4D6D6FF09EC47B2F57D6453B4F652CA9692910A866948B58DBD31E0EFE93F15C19F76C8B904E215F35DBE79C2D7343E5E2DED0F8E39209B97767D93FB25A6800BB4B7F13AF808B4FE8FACFD549F477D567542FADA751A6B51A9350941242D2DD604A936894A8026098DE7149F8A586979A7C5BC1E1A604AE5CEC74B40492000EB4824D9A8790A1E7171EC14B184EC6631228A4E14F096B325479F3D0347C5C675A8733D4FAAB3FCF33FCC3F8B664F6AECCB82B9D400E2CB19DBC96B88993FC9094000AB940B1C7D81EC77C2AC9B29F86BDEC9912710B9D960592109F915DC71000B106A48A3171CDA3E7F67FDA7CEA4F6F92893366F7631E9494B90083380E8D5E5E31F657D9FBAF6A0FA23A8EA350D51CC1674DE661E5B80AD4E16DC70530264901AE1481702009C7C62CEB02B97F1C71B8192938799FEA00219C703289A33338A8A6FA47D19CCF2FC6633B0183C54C4A9415820B59209249402E6E472DF68A37E836D3D97D07B32F6959EB85B39ED70D46E553EDC38E452556666907123888284252902463A27F51133192734EC5E1E74D5CE9689B2C1E25BA4A4992FF00292798DA39F7C1CCB958939C1E13C487090C410471F206ED4FF11F2EFED8FA8F52EA1EDDFB4CAAAD79DA976B73A79AAA1564B8A4A296A1D431C21E24B7084A638627CC63EC27F4CF90F64717D89C395E030857FA1905733BB944BAE587513C3423E66249203D5DDF907C4D999B617365204D9B2E5F7AA0CE4502B7A7B2F4B1F7A3FF000DE663AA9DA2F69CA1CCAB9FAACA72CA6D37FC1A89C052CB21D69F35019512507888957081B7A63E5D7FF101ECDE4B9676EF245E562428CCC4CCE3EEC207012A433B683CE3ABFC229B889D8498A9B89513C0010493C4E0DDCB79D7ABD5E7B03CBF24D4DF4D0F68D575CD30CE6D9355D21CA92FF03A0177285F7E5A6DC94A89008514A4C4C9223152ED6CCC661FE0B49948C44D38695879616842D690BEF1496A820D09B30F1022F08C2E1FFD53884F471F192D4DBAEDCB77B88EB6FF00E230D59AD55DAE764D903A9A87749D28CE52CD0F7C5AA5AC52D868F1AAE107B8761694A8192200B63D3DFF00C34F22CA670ED22F30548EFE7770654C9B2D2B291F395278540BB8A170FA93148F8AF3A6C992832A72827849E04A8D580377A7361D291E2CFB2666FA9325EDFBB38CE748E72F2F57E539ED1B74CDD3346996EB15B52C35508213C29792DD3A949921462488C7B6BFA81EC7F65476273EC4FE93088C423093945932DC321452A0C9B967A5059C5E3987C369D8AC6E745D4BEE4CC40092A2A0083F31725EA6AC6D1F57DF4EE657923FEC8BD9F6ABCD99646A8D3949A7333CA1F79612F37501FCB6A6B0A4AA0C9524C83F2D87C73FE96F23C5768FB5BDACCB30EB52B0F3A7CF429491F2CB4A0CEA10ED50001401A8C418F5EF6865E0B0781C14D9851C72D095558392013737ABF56630F196E6C7DB87E89E6AB2BEA1ACCF3F3A7DBA6532036A768FF84389658909B9E2453A6091F2C42E6B879DF0CBE2F4FC3941978638827BCB267900A8D2A070977B3DCDE2A99F60F0FDA4C995DD11314896470A43905801B16D872B3563A8FD8A6643D877E8BDCF7B415D40CAF58EA9CE5867EB253DD55775976A834D716591DCC0936817B6273E21CDCC3E3576830D8096959C3E4921656A014A48EFA53A4B86A120B579D59E203E19E5E7B32719DE3A3F50B02B4601441E573BC5A9EDED95A7DAFF00E8B1D29DB250BE8CE35150399652D3543284BEF819967749435012A471281EED478C4DEF24628FF0CFB77987C09CEF3BCBD6B992A5CF284AE695143F0850173BABCA85C45C7B4FD94C1F69049528A14A7252C94921C826CC4D40BD5C3888E7B42D72BD89BE877D2FD9464B982323D579CE541540853694D43C330AE69FAC480B214B05150A077001DA76E91F09F21C57C6FF008BB8BCF66838BC1A274A33E6295DE252148F97E524EA3D0C547B5394CFEC764A9186E2E12820000B903722B6FA5447523E874FA4FBB34EC3F4D669ECE3DBA54B590E5B58B71AD3D993A953CCD5273971D7F350E36D2421BEF3EB0471BAAB4C836C76AFEA6BFA64CCCFFA6669D98C3AE64DC2A0AE6C99287131410909AA4109621D9AA4EF7A87C34EDF19B3F1387C4A08257C20A9554804824BEF5F5D6DDE1F694FA20BD9A7DA6B2BCE7B5BF657D4395E4F9BE694B559BE6147401399AB3AA82D395094ADC53AA142A2E1544849515584838E71F07BFA83CE3E0866986ECE76F7B389981731121189C4F04B32471048290A96EB0C45886AC7A0D59060BB4592E3F112260E3EE4A82407E27492D7DFDEA7E40BB5DD09AABB12ED0354766FAE3277329CFB22AE55355D33AEF7CE04F78A0C3BC424C3CD04B800FB33048DF1F6F7E1276EB2CED864F97E6D8032C61B19290B9694149487487629A50D3ECD48F9F3DA8CAB1180CE71D875850509AB090411FB496A9B50F5E948AED154DADD6D0EBB14C2AE8545266E3BF6CC72E639EC3963A6F6F932A5764B3498B4A7FF00C24EAB80DFED2EB434A79F9BC7767B0CD98E1D64007BC0E7982057DD5AD78FBEAF662AFA773E880CB14869229BFC279D8EF645E3EB039827DDBF524DB1F9A1CDF855FD47AE7713FF00FCDD2424D984D1AB81A5E84599CC7BDF23C6A7FF00B26B95C54FD310472E02E763B7324B5A3E04330A827526A39794298EA1CDC8DFFF00E6753EFF008FC36C7E8DF26C560D5F09F08BE14850CA4A4D451E4000EB73CEF7B4789FB418642FB4AA25001562814ADFFF00F23F9D3EBB53EF17E8DD7C39F43DD125091C08D2FAB036A172AF1D6CF29989FD6C4FE6E3E364B549F8F1317254ED9BCA5708714EF52687A104FA55C1F727663853D8DE07001C29DADC157B0153CB7BC7C2A3EFAD39C6A42018FF0013EA08FF005019BD64C7327AFA5F991FA25F8098838CF87D9226657830328126A6B292DEFEA2DE09EDCE042F3EC41480C672DE9CCF5DD9CFD5A3172A549A9709901411C2677B5E27E605E3974BA63F049C14C9B36581525541AD7DB6BADA22315970932A5F086A3B806D4A0A69E1A6AECA115465266E0F23C87DE7D63718322C51C52E625CB75B1AF93D01F5D221D587E397303513A1F16EAFB6FABC38AEB4422157326D73E9633F3208F291890C534951090C4D9BCEBE1B79BC41230CCA5921874DC9BB37BB42DA5AB55A5506DFD5E963EF3F872C45AE6BD5FC5ADBDEEFE95DE119B2039A3020B86DB9EDF5F52FD4D5EA491E2E917E91EF13F0DB0CE6A8AFE660143C7EA3D988D9F86AA986CFEE9EF5D22ECD40F90557B78B993D4DA3E47FDB15AC1E5E95B16A534B3B78FF00377AC5670C82E3776B3DCFE4D8DDADB54D9ABE12410A20C988B4753337E5636FBF172C149125212C006A8BF4D34B9DAF16BC149E2670E77AFA86E5E0E4BC56D9CBF2570A3799BF39B5A4733D49336318DB1B244E42924536D2C34E7BF268B6E1B0E0814D7CEB563D43D69D2B1D8BF644EDD6AFB31D768C86AEA4A74EEA7710DE69DF2B89942584F80042E42788A88F0804DB7DB1E5BF8C3932D58BC3CC972495A78CCB524170A2285FCBFC5DF62300674A2AA0E023E56078838366269B36FE3DF7EDCFB25C8F5C255AF34025A348DD38A8ABA36133F5A2A6813C3CC4104F8419918A6F65B3DC7E5C24603385A84F0A3C0A51A293C4E1C82C960C189A9E704CC20460A6AD2070941AD058359F4A9FBE91E5F6ABA775AAE7D54B4EBA179B70A1CA2752429B521453243804F111C42C37168838F4C765F3CC24F5490262492120A5DC681F57BE9A6BA8A165ABE1C4995310584C265CC7BFCC49D34B171D62B87DFAD69FAA7AB82509013E201209B47282771698B5A717AEDC62049EC8662BC3034C2CC345137428F366735DB58BCCCFF73138201F88AD0C1C9145245AD6E576ADDBF421FA081E6DFF00A3B3B225A2C952B3DF173319ABA0C1F224F5122DCB1F971FEA4D53719F10B3D52C9E3562893BD14A16D396B4AD23E8D7C2099DCE47210A179483E40793687A78FB2AA6CAA07148163F2F3B7FBDA31E7E998351E021668C08F2AB7A4760958896A0B205007A5BD3C357B469ABE15367FD31045B9ED68B7EE310F9AE5B3166594CC371AB00DC3CE96F6E211978D9604C5300100BB867B8B5796ECFE5E4C7B5B1AA57B657B27D400AEEE95FD58091B0E3A56C5CEE0F4BFBE6D8EDDD83C0CC464D8B2B55049AD2DF2A99C6FA0361D2384F6BF3195FEB7840502B3C696F9921FA5391FB7AAC8610A436F95C7794F4E08BC59A02F11EFDB718E62AC0A978EC4CC0A202A6ACB7451A75D5F6F08EED2B3A95232FC17124377496AE9C290CE7F834E8601429510B0AD89277B0F5E717B7AC61E04AA5293C35B8A9DD85A96FBC3D939E499929443304D7A0B576EAC79C326AC729DAD3B9F07109FF00F25CD477840F07F917E4F513E58525E24C8CC72F05C257390493AF0AD275A1B0677FCD373ECCE5E2729CD014848EE576BD9557DEDEB678F8E1D4F9E32D6A0D474542DAAB1F5E7799A51C00F8146BDF1B00A8B9927CADB463EAC7C2DED370E418342905411225B56CC8079DC0D46978F8CBF15A44A9DDA3C629D81C4CCADDC7191BFBF48D794F66398E69568AFD5EF16329716DB8DB6B570C2525248F0A82809EBE40E3ABC9ED34C9B87C42654BE29841E1029BD5D9A9A3ECD72639BE27092654DC312404B83D76AF93459D996B0A7D019AE42EE8D2D3797D2D7D025EAA6C252B4A45432167BC23886CA04F15C18338E4BDAEC9F17DA2C973097390553CCB99F2B3E8AE10DC9C5FCA3A764989461734CAA6CB53211325970E416282F73AD58FDEBF499A435D685D45A334A6BCCCB39CA9FAACA32353D48A5D4D377CCBA28501EE195F182A5A609B4F3136C7CE35F62736CAB3DCC72F460E7AD789C4A124A652F8529332AC5883451B6EF1F4DFB3BDB3C12F22C04E9F8894572A424104A5252C90DCDA805BED1F2C5ED9BDAD37DA37B40F69BA9D7998550D53F4AC51C39DE3605334A60F7601294C9489E10279E3EA77F4CFD805E41924E070CA2664996A09292EEA492AA915624D0DFCDFC45FD50F6A65F68733CB8489A0895318F097A0296D756D6B1DD9FA1DFB66CA5BCE3B40ECF33FCE986F2FCCBEA21A159528A7692840716E06C3CE2130A04F170EFCE71E78FEADBE1E4FC595E3E4E1967B8528F0CB4173C6A6FED0F7FA0B08ED5FD3776B70F96E1B0F879F31290B4CB492A22C000E1D85377E7179FD33BDAF694D0DECA2F765BD9F5565CFBBAC5C4AA918CBABE9C70FD533043D530197140F1852CA85A7A1338E73FD28FC32CC734ED4A71188C34E4A72A9D2D40CC94B0E165E8480D6B579DEBD7FFA81ED86053D9A9D2B0F350158890A4D140BFC9B3DCE9B79B7CD77B2766A32EEDEFB3072AE9196D0BCCDB577CED5B61A6141C68B8A5052826E649E23F9E3EA97C69CAB118EEC0CDC26124949C3E5F302B80151534922C072FE77F017C0B92995DADC4E3262811FA90B750666593ADC6ADCA8ED5F79BE9D9D6196E73D877654CE4F99E5F9A5553E5A84BAC52D7532948E24520095069D2AB0041045A27CF1F3E7FA49EC8E367E73DB554CC34E92133C8495A1697F9A6B91C4002D705ED48F717C4EED06171F82CAA585A0996800B10744DAAC35D3CAAD78FB04EB9CA32BFA322972CA8CCB2BA4CC9BD33A992ED23B5D489794A79157C03856E05137B5A6F618E61F14FB219E9F8C32E5E1A4625CE3A41429329652405209F9827845AA01ABDCE88E51DAEC265DD9DC44954C9602A5147015024B8237AD4BFB68F8D0FE20A6B3ACCF2DFE18DFD61ED599B283E2A91C1C2E674FAD2AB9E002140CCDC791C7DC6F8739663F07F0B70CAC5952972F2A53CA5A492B6C3D2A41208DACFE31E4BCC065F3FB6386C72928E0FD5A56A371598087F324EEDBC7D8F76739E65591FD132CE50EEA5CAD19A2F4F578550AABA914EA438E2C941417B8A549510044DE7A63E2DE2B2AC6F683FA929A065D364CB9F992A5999C0A0901CA1DF85855F56D3578FA378CEDA64EBF87F230B24C92B4E0D2821D2E0F00167A35EA0757631E6A7D081EDA3A43B2BCFF005CF619DA03AC65B926ABCCAB98C86B2B2B521A612BA9AC5D61256A4821D2EDB8D4041F0F2C7A13FABDFE9E33ACAB2BECD67D96CC993E64A93FA832132C924F0CB5247102598D5ABAD63897C24EDBE5B95E6799CBC419694CF9A52975003F72858B543EC2978EC3FB64FD0D190FB42769B98F69FD9176C990698D3DAA5F6EBB34A76CE5D5296DB442D6A05CAB04132A5129005E3AE285F08BFAACED47C30C966F67F1992E3D589EEBF4EE654E676294B132882E1ADA758B476F7B2B96F6BD68C5E1E74A4852B89D251576367B0B55ED6611E837D1D3D8EFB387B29E95D73D9668FED4723D49AEF2AA2A56F5F66685D3D297DF71A71745655429B5F772A4FF002C9B092463CE1F18F37EDE7C4AED2E5F9EE3F27C7A30D331266A25944D99C492B4963F238D0E8E29710E7B1FD8D9393E1712138E4105150E915093AB862ECECFB6F1F33DDB8FB4F663ECD1F4C46A1ED372CCD5BCC34FE4B9C50375B554EB40A5758CC28934CB529C6CADB5F76971517544198C7BA7B13F07715F11BE14FE8B1597CEC3A4E0E92A6216145728129FDC12A1F307F3022A824A64E76427304BA67317208AAAA2AAA96A5C37D7E813DAF7D9B3B11FA59BB1ED21AA346F68F91649AB74ED122A28EA7EB14AE3E8A8AE4B2AA805A72A5B5288525408502236F2F337617B67DBEFE98BB4B9A6066E4B8E9D2319394995365CB9BC0844A2BE1AA65905D245F7EB16DED7F6270B9D60A4CD46310A5997549E162E03D4AA800FCC7527D943E861D25ECD1DAA50F6E7DB776CD926A3CB3479555E59973AD515021A0868A544ADAAA01E3E04AA540C102379C5CBB6BFD55F6E3E20E538BECEE0F2BC623179924CA0A2998C94AA8B042900170A34E434022A1D98EC9E0BB278A13D7390A757168EE1CE84F202BCC563CF9FA747E900D37ED2FAAF48F62BD926629A8D1FD9B0ABA2D52E53387B9CFF00BE6DAFA88412477628D6D7FE52941405C441C7A5FF00A01F80398E588ED467F9E15C939A2113128992AA85A9331F849A9752812D67AEB087C4DEDA77B2F0F2F0EA2C804712554228D4D080EF7FB9EDDFFE1ECEDF34C6A4D2FDA67B3F6BAA9A5FE1540D658D51A730AF45335C351DF3CE06D0F389063651493245C1C79FBFAD5F8659CF677B468CD7012A6CD97227CD5F14B9449214A0CFC214751BB5A8224BE14F6865E2E4CE958A57CAB486E2340C0BD0DCE8FCEB5BB37D3F5DA4E8BD03A1FB2AF67DECD1CA0A9CA73A733E5E6AD50660CB8CD3943E8AB68AD2D2D6992B24A4820CDE4E247FA39EC5E6FDB0C6E7B3730C24C4CBC6A30C897DE4AF993C09525552028B9706CD6899ED6E7185CB1483865A400A51E20407ABBB3DB414B02EC0D6F2FA0EFB42D17DB1FB2AEADF66DD739965CCE55A0AA327AA0335AF6025C5D4E647304708A97533C2B6D2004930400231CD7FADBF81D8BEC8E6B968C2C99C3FD51538CC99264CC3C265F090FC009ABD1FA0687BD91ED29C74A99356B0132785454542805682DA1F0AF28E96FF00E221F684C973ED77D94762FA3FEAB5D93F67F4999B59A2B2ECC1B5538EF6959728F8D34EB2DAFC4D88DE3CAE07A6FF00F875FC20FF004DC873AED2E3662C4C9F252B9726721495BC94AD2C38AAE586973C8423DB1EDE6599C4B565AF2D7DDA4A388917218BF3A6D7E51487B197D12992FB6E7B2EE8CED8727ED3F2DD13AFB33399A33AA652E99CAB4269AB174B47C295D534B47F25008E048277B9BE257E2DFF005739D7C30ED563B23C4F646766982953C4B933940A92A4053121E52DA9CEC361150EC9F6224625189C6E16600A53A884B50FCC6CFCAAF4F08F793E8ECF653CCBE8CDD13DA8D576BFDBE516B1D33995031534197E67534ECAA8450B4FB8B6DA53D5AEB87EB0A2010902D682231E11F8FF00DA8C5FF513DA8ECE4FC83239D95AE54EFF007C4A90B481DE197FB9425201E1FF00D4760D1D0BB35DA49BD97938B918C2552D614900AAECE0D34636B5C3968F907FA447B67D33ED09ED73DADF6A7A792C3391E695F46C65686214CFFF000F42A91E712520254165B2AB822FB99BFD73FE9B324CC3B0BD8AECD649889F3711330F2815CC585024CC29531724D1DB661E5E67F89599E1F33CD66E230C94A553564A929E1726ACC40F4E82F1D247948AD71B69A3C6EBB574490B1002385F6C12784DC01733F7463DB1DB544EC6F617310924A95825B0B9FF00A65869AB59F7BB98AAE538632E7C998CCC41219C82FCF4FE35B7DDBFB336A1D3793FD1114D91661A9B2B7EAA9F4B66FC544BAEA565F42DC2F2908E00F070CAA364C9DF1F9D5C776733199FD434B9630338056684F7E25CC2857CFC553C2C963401EEF736F5164F99A11D9F989EF83995C25259C3EC77607E952F1F0AF98B15CFD56A6AFF00A9341273DCDFBA685437E20732A80DA80998363E933338FBBF869388C2FC36C361895059CBD824920FFD216075B53D77F336793258CFD2B04F0F7C4F78C4DD428C2F6F1E8F1F709F468EA4A2C9BE879C99BCD33DCB28F323A7758A2AB2A76B690D4203AED6A590A429D0E7892411E1988B63E137C46C8B198EFEA09787999662168566329489E25CD32CB14A89E2E129A1A5CB178F5A6419AA47645C4D48E1C3906A1CFCAC19CB8EA3A5EFF1079D56A9DD479CD0B47EA85AD47A8D65EB2D2B0EE6956B491C8820C8B9B75B8C7DEAF8272BFD27B2F95E166829030D253C268DFEDA685EF6B0E81AB1E46CEA60C566F3E61629338B1707FBC8AD6951E62102EA1F436DB6FD4FD6384A8254121300A8EE2D3F0F48E7D23B4B365994549775A48A6C03DDA9B787268C6712929C2A1807E116704061E2E6A3EF1922AA23C441F5F9441DA3DF883EC8A0F14F51258177DAF4B57EDB45630D85EF44C0D41A5FC5B6BF4DA17B3540F3E7613EFB1B0FD8DED1218FC4254B2904120D791D1FAFF88613F0641248D5B6BBF4D7EEDBC39B15299BDCFADE00F3BF31FBBE23FBDA0A38EB4F0F188E9987242810054736D4B915F1F5AC3E51D5004CAA768E7CEF73B794DB96136F5FF10C26E16F4E7EFCFAEE445EF9FBCA495C99916BEDE5E63E7317C37CB7BB3C3F3247450F3F06F5B450309C248A8D4B1D694F37766F4200A9B337AF24C133CF7822DCE08F95F6C5816B961988B5C355B5F0B922EFCA2E99690C12EC59AB4FE2B7A45739CBA47149067CED07A12768E7E98CA172C9F988FBEA6DCF98B45CB0286006B4B80C1AF77AFA6F102A9AAA8688729DC534B6DC43BDEA55C2B49696958008330A88B13D3683880ED276670B9ECB4A804AF8056D4B6A3A6BE4F13D265204D42D49E24B1052752A70E79EB6E5AC7B09EC69DBAD16A3C859CB7357D0E56E4ED064513AE052AA82C14990A3C809BA4FE5E61F899D9E565A0FE9A590563E65A41E24F0331A5473AD87384330C0CD93869E94A14B0524A5816AA5C5F50E0121CFAC4E3DA13D9FA83B45A1ACED1744308A4CC5092EE7B97B0907838070B0520402560711EED26F20CEC28DD8CED5E272BCC70D81C629687584CA98A27FDC018977A066662C4EED1C7B0699E8C7AC4D744B42CB248019D4E59D89FC1A691E516A5C933664E654556DADA76994A4292E24B6B3C2483E15709361331B796FECA9D9AE5F99F64B152578A97DE4CC22AEA492FC0A162AABB8FF00069D070D353331B8128F9F8549B312038BDDBEB406B1F7FF00F40754328FA39FB1E678871B6ACFC2E08327F8A3BB7C7AC74DF1F9ABFEA9B013301F14BB412E5874FEA125019A85C92799BF851C47D21F84F8633F219135350258141B74A6F6B5CD047B573C37170AEBCA3D3CCFCA31E7054C50E1FF006EA6F5B3791DFD6E0C752958644A4AD2A50254F7D3933DDEB5A53484756DFF0029464057862FB99E40C72BFB879E22F1F899A0CA4A65120104B5AF6B3C30384470CD26684EB56B56BA3DB4DB9C7997ED4C8A65FB4C7B3BBAA092ED2BD9F84A8C594B6100F39F90C769EC5E38232AC64B5A7878E5A68D664976D79B6FAD9F85F6B7088999F61BBB980844D1516FDC0E84801C7F916F48A8549FA95229C215C4C35179FF00CB06C07E679FBF9ACE5CFF00D6E238657CA16A6A8DCE9E57E7BD3B9E1729958CC0615256DC32D249A97A07EB60FD042D4BD07812D9E13304DA39449E9E71CE2708CC54D0A41E0B9AD411F57DABA9A56F0F5394C8C3C99893307EDE4052BB8FA9FBC43B5AF0AB4EE774EA8E0A8C9F354B8B240E0FF24FED7E60F97BF0E25619789CCB2DF91E5A27202C805EAB481CBAF4E91CF73DFD3C8CAB3596710973297C2E039649E7F47FB47C9CFF0087F4FE94CDB52E62C96AB6A579C664B21C50250AFAF3E47DB2779DA01FBB1F53FE18646064797CBE220CD92876154FCA08A354D5A9F48F8F1F144E2FFF00B438D54B96B52062165C02D45162FA8F1D6BBC55DAEB5E546669750ED48629297C3DD214059560070C1E42605A2F6DFB5C8ECE1C0C852E5A4A8CC0E0849B8D7CEB7F38E479AE2B1AA5E1C194B0C468695076E5E3A87B50F9EEB658CB5CCB43D14CF1E24BA560A92A6D457224CCF1446DF0DE7FB23D98563D73D18A90485FCB504382FA16AF879B45D329CC2711216A7E29401B331706FEFED1006BB78ED1F2C6574547AF330A6CA2950B67EA816EA92A4BA14DF081DE6C27A72F7E2771DF05B2D44F9589978290A54D515294654B7D2E4A5DEA48E62D48E98BF88D98E1B06A9285CD010801202D4D404559BCB4D0475D352EA97DD5BA0E60E5754BCE975E754A502B2B595192499DC9373EA39F77EC7F6364E4B82EEE5C84A4290DFB40B03A369CF5AEA1B926699EE63DA1C5099890B3C0B3C04B9D5F4B5BEC08D23B4DDA8E75A5EB5CACD3B995569FCD69D1097A95E741A80B4C2B88B6B483C0098924FA1DE9FDA8F85F27B4B8BEE276192B97316428AA58500E402E0A483726FF0066BE7663B5B98E46B9264159092976590CC41D19C035F28856A2ED63567696ED2D0EB3D4B98666CE9F53C72FFACBEFAD3FE6BC6F405B847BC9DE23A62FDD8EF82992F6170FDF60B0B25733149056A42128293A12007353AD9A8D171EDEF6EF34CEF05874954C502901438891A0E7737D2FA562BCA9D40FE459A65998E4B5AEB2F30E38B62A10E2C2DA5248B8F103722C7A581B62E0AEC761F1384C56131081313884291C2A0084F102050D3534A0D2D669D809F332E13B1330702D4CA36492589E553FCD8D1F75576A9ABBB412A6B5A6ADCC337A4A06826969EA6A1F5A112DC0094A9C2081C291EEF2C503B27F0872FEC763B19330F879481984C75704A4A48724D4015FDCF5D9F58B2E69DB1C7E2E6A10A2B28413C2EA2CD57AB9E60DB4D2B0DBA7FB70ED3322D34AD3997EB0CCA8B4E5225F65BCBDA7DD0D38D3E56140A43804428D883BE2C78DF81D90E3B33C3E3A661244DC4718985664A38A9C2AAAAA46C6B5A42A736C5E2E5A13DF2D0966238942A7714A5ED7E45E29276B87091C6E77AEBEB74D4F12B88B8E3A5C2B3B1278953EFDE71DA26E5B2B2CCA1196CA940C8549324200040053C26C0EEF42F6B34426264CD97884CD1338940951AB12407605FEEDBF3B353DAF76A54BA75CD08D6B3CD1DD38FB62687EB6F25969B47F34A0254F0042CC8B00224918F3F49FE9D322476865F69132E4CB9C7102795F7238828A8170581A1B6BA691D4FB239EE2F31C0CEC2E227AD12D29290952CB0670CEFD0FA91AC55D97E635EE553D9A503D5394D530E05A2B29EA9D69D6561478969536B428971424C2A6E649C768EDDFC3FC0F6970795E5D8C28C4A70C9084A972D2414B2284104580F3DE29598CDC564B9909D869CB525530FC892415392FF303A383E1B34596D7B5EF6FDA7285DC928BB50CF5BA1E014ED527D62A57DE34B942C77A5E253C2826FCEFEEE57DA2FE9DFB213A660572B29C112E0AD430F29C905372106B4D4E84C751C176C33395839404C5AFE573F39245050172FD473888E53DBA7695A1AAB37CD74AEBECEB2CCE75496959C569ABAAAA55616E40E24ADF3C3C016A48BCEDE98B2627E09F63F0323087FD1B09356809242A44B64D059D3BF4AF844BE13B7D987E8F1038E602A490071177A8FAE9A6A6B117D41A9EAB52D43F9CEAB7DCCFAAAAF8559966AF3CA4D4D5A80F0124953814D936214622C462E384C8F2DC9300A9383C049932B807CA89684866A8094A40028C4806BEBCCC769B34399098274D333BDE2EEBE6660A7AA8D2D5AF41A448342FB40769FD9636F27B25D5B9DE421B5346980CC6B1E69238A5CFE53CFF00040BC023CAD8A64FF86BD95ED9A7128C7E45835CC50204C99265A8B977214A43F3A9BD6BAF4CC4FC40C68C3C896B9EB432085312402C1A81C1D9EDF7996BAF6BEF6A7ED1A84651AC7B64CDEA74F3C80D869B0B614C881C485165D4B8E0717E12A3B5ED6C73EC37F4A1D99C2667FAC9383C2B77817C2244B00317350351E075BC452BB7388C4A529257C697A959215B720DA0D49A5E3AE55D4AFB4A7731ABAB71DA9E24ADBAA71D53EE38A599597256B52CAF97193C3336838F487677B3780EC9E5DFA6CBB0C894020256109E00AE1D580F17A8AD1ED10B8ACCE6664E272B881A1048B68C6A030E5666ABC4B3477693AB3B3DAF567DA1752D6696CF5F6C8AF4D1ADD6FBEE0414B454A42DB49F092773B9F29A4769BE1764BF12153139A61249AB1EF65A5770C28A05F97D350FB25CEA764AA3DCAC94A8FCA453AFD5BD2D0CFA9BB4AD6DDA356B59AF68F9F57EA4CC925EFE1AE555438A2C820A5CE02A717C05405CDA6DE470C3B29F0B724F845881FE998594B18958E2084252031352C1A8ED4E82D0BE79DA4C56629497514268B3C4494BB0B7D5BC636E94ED33B4DECE686BDBECFF0055E63A4559CB8D2B325D13EE95560A75CB417DDB8829E00624F5B7385BE27FC25CA3E24A7073F192A415243A44C968594BB1A150A3F215F5898ECFF693FD3B018A40593DE2181763622CFBF9DA36679A9F3ED6F9A576A0D5B9C556A5CD4B6C8CC6A6B2A1C2B57F2C210525C7167ECD884CF520EF8DBB15F09B03D85C3AB09829E89689C9632E5CB084B005D82193635A728A5CA5E2F1B33118C33152C05A9481C4FC45CB6B46A3D35B6D38ECDBDA27B6CEC7D8699ECA35DE67A5B2A60AD4DD0B0FBAED3A5C512AB32A7782EE19FB20199E6629DDB7F813D98ED8AD788C5E59869D393C44CC5CA4151513772924D75BD2B6ADFBB11F11B1B904D9B82C4A55312BF941366B5D8BB8A7A5ECE7AE7DACBB7CED8A94E51DADF69B9D6A1FE2922A285A7EA32E4308A732DA4AE95E42561D4813D3AC99315D88FE99FB33839A56BCB70C9EE8828224202878B39F7766893ED0F6867E67C5364932CADC800D01FF0026E47211D79A9CCF2D06BA99346E51B34FC011C6F2EA14E71FDA59714789449F11BA8DE099938F42E1BE1865F95E1E5CC91C3DDCA1F227858D00A017A352C34B4727C7E0B187172A6AA615AE693C40D804B6B6FB0D8986AA253ED24D45112A6DC50214A3050526410150A9E7D248F73AC4ABBFCBB1197CC4912D52D52FA8208B1D34F037AC4FC932A470778A4A66242788022B6D8E9D5ECC77B799EDC7B60469F6F43653AE7356B260DAD2BCA9350F374FDD9F1B8982F25B3226C419F2DB1E6FC2FC0CC8979F9CE152B0FDF77E66059948E3078B8BF71F9BE96B35AED83CEA52705350270AA18004D4D59C3DBD8058456B4E8A377EB05552B156B5713882B594A9C995AA4909F12A547D63963B2E7787949C261B2B92014A502529A80064A45052C00D3A544727CCF118B56350B12C2A49987E7A1FEED989A9B5ACFCA2DCCA3B77ED9748E937F4A69BED0732CB34CB882CA7256DC7154E50E921C484F7A1290A2A26C800CFC38FE7FF000772AFF51C366430B865CF52F8CCDEE659980B823E729E22D472F5B728EB595670A95932E5A9652F29B85C80696634F1F48A997589A4A751CCFF00CC562D4E3CB741BADC7945C52894F52B24FBCC0DF1D672D9672AC36170E80C1090030D801BEDD1E968E42A44CC4663326C90425535CA49B7CC6C4DDDA837A5A120AF55434C9EE032DA4ABBB571F115C9BCF3116B9E7BF9CB6653D73A5A454FCA34DC375F3E9511379980BC3CB48A900B80795F402D460C4794642A215008B7E5BEC3DE01EBB8C3DECDA3B9918A333E5252E09D686C2C746B5ED588CC04B4852828555AD2BCACC5B9F95995B5504CC72E5B7E1F84F9EE3103DE4C5E2A6853F0F116F07E41FECFD0C6B98E1857853C54E54F2F7CAD0EAC54A85E6E39C8B18F78F4FD92E3D6212661D4011C377E5FC74D1DC5EB0EAC55A81B2A662DCA39FA4DF7F8E1C4454D90B0E18815F467BD7CBD63B31A83FF0030F9729F3FDF5C5772ACAB109E1FF714DD5EC0023C58BB56F1C87064FCBCF5237BD9FDF8454B9AEFFF00501BFE1FBF23B62EF2329594FEF248BF27D37D7F2748BBE560F9DFC3C0D9B56AD9A2B8CE261572771BF33B7A4795B9DA30DB13964C40A2D887A8D46947F7CF5BC6096A6000B063CECDA06EB5F1115F660B2961D00F8942537BC03B73FC7737387196CA54942C2D7C65ACE76B6B4BDEE1E2D3804898A4BA4900B7A87B3378FD1C44F3B1CD74E7669AB726CED2F2D2AAEA80D5537C6A094A0A92D789174FD9513F64091B49C72EEDC61246213338A5853F1338043814A1D4B57A88BAAA4495E0D49525259140D770E5F7B8B92F5762447BBBD9F6BC0E06B32CAEB52BCA6AE9D872A11C21E6EA389A056DC2B885D4549909244CEE31E5DCEF2C4712FE4E15851E152404941770411B30B50EF78F3E76CA58C3E216A909EED890C000FC8351CFE34AC535ED49D82A35A6529ED5740E4E9A7AB6997D59BE9DA75A54A76525A0F155B7014F42516DBA623B2ACF335C3ABFD3B178F9AA2974A165D299A935E16FDA3803246F7DE1976471844EFF0076BF3A0A5CD5241AF9FDEB5871F656FA6A3B60F628EC4B24EC374A766CF6754BA42A2B02AA5CCC9144A52AB6B5750B4F74EB6543854A5241BC81320638FF006E3FA61CB3E296738DCFCCBE2C6E2780A94093FB53C3B905C72A0F38F72F60BE2CCBECC65430D310172C20339B33B3537F6E4C770B49FF00E240F69CD7DA86974E649D911454BAF52A12DA73AA5592952925C20A99E4992795AFE7C5F34FE89A46094B64148960924836A126FE941B6F0DF3FF008FABC3A138B4A949134AC896096649203902869B56A23D6CCB7E946EDBB32C8727CCF30D00AA3AB553A5754C8CCD874B8A7109264049038493CAF18E793FFA5BCBA54E992C4E49282C42914046C7463A87A5F78E6B9B7F54D8891296944A293C24385549B6DADC0E61A299ED17DB175FEB9D65A375E55E96FF0039A3D756B651F5E689FF003894A1710009001BC19E587184FE9EB0F830A40C425282188018116FF9023E9CE38ECEFEA5313331C27AE5296EB772A22C6E28CC5B4DA2E36BE93BED716BA5A2CB745B8E14252DA17F5C6E13090904CB7113CE4EFE7784CDBE03E4B800A5290272E6D4B121D89ADEB4F623B1645FD5CCC95874CB9A42025200E2581A731FE0B062D13CFF00F78C76CB45979ACCD74D251E00A4B66B2941822C2C276B0B6D1B6C6051F02B01895BE1F0EA4826CEA557A380F5F3B3E8669FD59AA705844D0285C85E8D4B6BF93BD693CFFE94CED32B5EAACB2A749A99A3A9A6ABA45BBF5D6D40F7ECB8D6E102078B91F23D7177C87FA70913264B5AE5174A90B49E134620EAEF51B8D2D58E4B9E7F5278EC6098133490A0A0C0D3E67BD18B83B1AED1E5CE7FAD2B97FC56A2B1A5533B9AD53F54A417F8E3BC79C7AD06DF6EFF00083B63DA3D83EC09CAA4C994A5525A5090E9A06006A4BF3D8EB68E099DFC44958F9CB9B3308959592492D5737A03D6DBC5199DEB069D0950A8E2E2E20B4F111B5AE49826DCF9FC477AC16449290854B414A406FDB5B3863E477BC404ACD70D9B14BE1C21ACFA7FEDD2CF435F18A7B506A469C04A5C22247085189322C41E66D63E51B62D797E4D230DF34B9684ACB5001E069B0FA18939494380848036B742FA3015D5AF58A8F33CE0155DC8E22A27C5B983B8B4FA1E67CA716C912A67CA9324CCE166A3F326C69E874261F224226065241069BD01E777B58E910BCC3356C93E3937BF15ED6E93D39CFB8E27646267A180C228B5D81B55A8DE7CE159396C90414CA1D5A8DCE84EBD1BC221B9A66685442828F8A4CC98F599300733D05AF13382C50278A7617BB240624786C0914DE9A4484AC24B42920A1D542CCDCF46A90DCF4AD6227515C8415149009DC8B4EFE9CC7BFE18B1C8C52267082C4358DACFAB8B9DBC6257825CD480B47101448B81666A7A8E9BC30D4D625704A8929B013D77E7E5D2FF002C4B4AC1A26BA811F3352D517634FAB57C21F485A657CA80C9147FDA080395EA1BC690C4FD741549227A137378DBF641F5C3A392CA9DC2ABA81B9F114F7AEF1212D32D4C4A58D093AF23F7F5D6120A90A0AB9BC5A48B74236F3103F1C18D9A8CA25A4A93C6E0806AFA3E9AE8FB43D4CA3352D2DC70D9BAD4D7670046A55401D2D7F4F5B1B8F761B4BCF70D3C1E342411404B1AD742F4EBFCC2FF00A25CCA4C25540CC0D35AF263E35D4437D655B29E1529E5A0DEE0124817E578063CB68E85EA71689A03106DC2011EF53EB6687B8595330A0894B28B384D1DFF003E957B086F73336F84B6CD42D40FF470290099EB11BF3369EBB61BCCC4E2CA9908330A59A9E9507969B0787ABC389ACA9ACB2352C589A8343420DBEE61B8D0BB592EAA95252824951793C4679804D8EFCBD712381C4255FF00F50099007ED330815DEBF9D4522470D3E5C84B2C150B003A369CBFC5C9C0AE812420D32BBC1027894B00C5E3700C748BFAE36C766794CB0D3319294002C389346E60E85BF9B4384E3E5A50A12D290821D55677AEAD7A873A36E63356599AD78032ECA6AF306D32169650F2BBBE232094212ADFCC72DF618A466BDAACAA43B4F94B4A6FF324003667D8DBEACF11E3159782B5AD6896AD0B713F27D08A0D2ADE12BD3BD9B6BDCF9E4D3657A5F365B8B20049A1A94A2FB4AD6C817E4662FBF2C52E6FC4CC9302A509788912D44D077881BFFDCF47A8A6CCF0CE766523898AF89239368F5F3B5B5EB7F647EC4FED1BA9592EE5FD9E2EB1901254A7F33A7A5EEC2EE0F0BAA4933D22C79E29B9EFF51585C866265CB2311DE71550AE266009A876D9F5BF3868ACD70284ACCCC426514D5296B96347A7D757B18B5322FA373B79CD78467196B7908541505D6D255F08F4EF8EDE5EEC5626FF0054D85980032542EE0A54DE3F2F56B5E1827B4985492EA0A4BE8A29FCB03FE22CCA6FA2AF523A38F3DD7AD50A94077484D132E1FF00571290E72F3E57E830D07F536B72AC1E14CC209E26251C3CEA9AE85EC393B05876B30E1242425059A8429DB91D5EDA58D61DE9FE8AE0820ABB4B440DBFF86A26FBC78EDB9BC09C34C57F5238FC494AA6E5A66105C1E3A83E29E42B082FB53289FDE189DFF173AB46EAAFA2DA9C371FFED6114EA13C08394A55DE1F52E7863AF5E76C43E3BFA94CD019694E0A64B4D4169855C351A70F2AF4DCD7795DA9C3A1DD6140DC7133F5B575AFA6B5FE75F45E6BC4073FC3FAADACE42BEC90D314A1C8DA429C1E42F204DB78C2F23FA93C50E156225AC002EE49F06497F4F4787D23B5387B258053BFCD4F0F3B33EDCE9ED4BF4777B43E996C2E9B224D734EF19EF1BAEA425B0904C96D2B24F15E39C99F2C5CF25FEA37018C5894A05C517C4952589E7C3A837DA8EC224A467B85042C043F25025F5737DF5703778EAA6B6EC6FB44D0150B6F55E4398875054389AA479C4A00B9FE6B2DA926D17E288E918EA7967C70CB25A4292B94870EAF9C135B386241DEB534262770DDA3953662509295710600A9AA2B525BC45FC1E2AA5BE5B5C3CDAC380C354EEB65B24C90788AC03311B89DC62DD84F8AB96E6B294A18847180591C4002FA00E2B436E578773D5331E4F0A824A59CA485B3EC5DFC34D8E9A066C95BA9A761BE3A8BCD37D8481B9872C36BC49F5C472BB55FEA738CA968E1492DC4CDADDC063BDCBFAC269C9E7A921E62B84F11EF1C93CA8FAD9CF8467515AD28B694B85156DF107D909527B90A8E1874001CE213B1F0EC45AEE8E4F3023BE91892B2594521A85BD59FCA1C232AC4489615C4BE136507636A91D2F4D6D5847DF892413277B9927CCC74EBD7094B54E0A6C42485248F995AB6CFD3CF5A5779721082954C4F1105C3D811C9A8FE7E158E7EB12209558D81262DCFF2FC3125326A26A50090B2072F201B4FAF487188C41527810A5252CCC090C3D3CBF980BE15F68957A927EF18D5D2400500B6E7F888D12824B82C6B6045FC63732F4C80600B6FB03BC08B72DB029408AA016B57FC5BDB465482AA1538B5BAE9D7DD21636F264C44DA4733F2B72F5B7963744E280C9A0B30342D4AB01E3184CAE0FDA5B5760EF1BFBF09E1BEF78FD8936EB1F2B37514051213525F66A79746D21708E200AABB121DFC1E961F6852DD4A6D06D17DE4738FBBCE7973C63BCE41C73F6D4FAC379B2900314860FB33574BEB6878CBEA412B24DAD37F75B616E971CF960331F4F5FE222E749410484802A6C36FADEAD7F08EDB6A0040701045BF3C31CB7304BA7FDB2FA579BFA3F378F3BE0813C15616661576D74F22D78A97340544F0DE27693D3A6DF2C5AA5E6A5293C2082756FF001A37BAC5E72C07C68E3A83CC7DE2B8CE5278556379E477822FEFF909279989C7672B03F6B9666DFA9D41BEDE16B9E0DE83D1EE29AE971E7B08AC734596EA29D441E0495950E5E11B73DF973F7C028E5D98AA695F10201DFC81D18EF4A79C5D3286A92C188B8DEFCADA9E95B98655D7AD550FD7107BA2A40A640994A93092A02D1E200ED1067152ED203384CB9A1E571B51E2EC84F1C9E009A81F317A105F6E434B691EA87B17F6AD539AE96AED10F362B73FA1EE0D0075F08516D6B538EAC15595DD340280327C3000918E059E610A662D4B5129413C619DCA8B245011AD0ED1C7FB6F9605A953254BFF006A603C079A5B8DC1A8A83B69B47A5DA2B519C9DD65D72BCE6B475414D66C1D6781B6A41406FB95CA48BA91294C18E2DAE68F98658713254152FBB5A6B2A60357049D1B50E4127504B472CC0A97976238D880F50E5AFE43C3C63A43EDADECD20297DAAF674B41A0AF4AAA33BC9A9A9D24502909096C95004AC3CAE25C25238660ED8E87F0A73F4489F3F29CD4044F96129C34F5B0FD55092364F7618126A6E23AEE4D9C4A9D2901DDD8104FEDDDC1F3371E05A3ABFEC4344731EDD326555708144E540A9429B0A054195252786265244D872F5C4C7C40C6CA380C47E9CA44DA061C24873A91B8A3BF8C3BED14AC3FE88CE511C2A4121D80703CEB4B5483A08FA26A3AE6695960B550AA86D68285A12DA95C240E14400098D87B8EDB63CB39B058E352A50410494A9C55EA4FD7634AEB1E54CFB339471CB94140A7BC29E170D73B694F26DC9892643A5DDAAA866BAB6A0B742B2E29E6DC470020FD910A20F316F973C73CC51C4AD6A329454F4F94BB7BAD4EDA5A3599230DFA633BE57E1A3B6DAEDD75AECF120CCF55E95D2A834B42DB4ED50078DDE107855CB84949111CC1E9230861F23CC33450E2428F0961720FF8F2D4F3A34F993B153552E44D52425458A7C7A7954DF48A0F57F6A4CD5171BA8AD524F8821B4A484EFB5845AC49881BF91E89D9FEC7CD94A4999873421DC3BDA963BF8C38919762D5533D570EE4DA806B715A39AE9143E79ACEA56C3ECAEB514A1EF152AFBB42CAF80F12BA14C6D7371EB8EC99476792908030BC4A02AC198598EFA6BD280C4FE172013402B9D5531A834AB5A87DD0C75E750EBACD16FD7BF515EAA86698B68427842678FC2600D87BA062EB23245CA4251264103CD893ADA874E4EE3533527B2D216C14B0A70EE69B1621EBE3D62AACFB53BA1C4968948209510A241E200FBB7F2F7462DD90F673118824CE2A961E9C5B6B41AD830E6FC9599934BCBD8CA214FB537A0BE962DB83CABECC351BAE182BEA6EAF5226E2C0F95E2D8BE60FB3699443CCE2F02C7C2DBFF0D573250490C1B42CE6EFD6C4D76A5E910DADCDD6E470B920C830AE978DEC7E43C862DB84CBE54A041097A0A8BDB7BFE7C62730F24380C5A95B3EE3DF5D5E2235F98BE6DC6522F2662C3CB909F3E76224E26E461E426A780780E5B0D89AFD627E4CB40482000534059DABB6E74F1DC4465DCC9C3FD44949224107E22FBCED8713B2CC3E350C3853B148A55B40D6B757EB1208C009A54501ADA6CCD5FC4335557B841324037BEDF3888E9CE7E1ACAECDA10070CD34B86ADFABF95442A32E54B7E21A8615DAB6229B5872AD5B055ADC2B009514C4917DE46F7BDCF5C494ACBE6618057116A358380CE19E8D4E96A5A164604B3F091ADAA6BB5ADE81EB085FA9B9922FBCD88E563BC8B79FBB0E06231086F914AF3A6BB73FC3DE1C0C3B1143535F0A0E7A1A68C79B205D5A927C2241BDCC7E22F63373870AC2E1B31923F56B4208144AD41243BEAA21E9A535DDE24B0613294788B6940ECDAF20CDF6D0C6C69398559029E92A1F9B70B2D38EA8F580DA56A3E71F28C44623B3F93212B51C74892054ABBE4D80D7E70283916D5E1D4CC5C8428A52A4BB56C35A5F517FB1898E9FECEF59EA4714C659A77347AA8A929612ED154B485294760B71909BDAE2C23CED48CE3B4390E43C6A939B61A7AA557804D43BEA080B27CD9EACE2194ECCA4CB524AD6025479114205081F9D83DE3B1FA33D823DA6B5829AA8A8D24DE5F93B852A354E56D105A5B55C9EED4B42E40E5636E471C7B35FEA7728C8B10A9070DFA8992CB06248537309203B1673E7584F159E6065CB4893344C24328BB70B36F42FD37D03C76AB4B7D18342E37DE6AAED03F83D43010A7E8D1446A038A31C480B69C8B796F6EA46396F6CBFA9CC776904B9595E58A9281C41644E32D9EA09701EDC9BC62B38EED62A505044C03621890297BBEBF715A76234B7B0C7B3A69A6D0D66D4BFE2CAB4402B57D6A8F8C88BD94A001E7726FF001E653FE26F697304F0A27CDC0F15E6199DE316BB13FE69688299DAB985FBC99C6F70297E8D5D5A8DCDE2F1D37D897635A24B8E696ECC6932E53DC25C79DAD35A1E0DC701087D2BE1E1E805EF388239FF006967A97FA9CF66E212A6F9423848FF00C4DCE9CB486533B461638904855C7CDE7AE8DD7D4C58ADE6EBCB1B0C65596E5542DA4404A72AA25280116E3EE38BD6FD245F1018ACAE7E366F7B3313882B26FDF4C0097B9653005C0B5F5BB207B4734D02CD5C1D7E9D46A2352B35CCEA7C4FAD3FE90C3696072990D848239C11E58565E117824A93889A663B7EF256D5A312FB8B7E62BF9AE753D750B21C9700967028F5D2A77F368D2A7EA957E37D20C41EF17CB7E7EB6EBBE1C24E1D54E140F2FC52FE3E110A3339E47EF556ACE58BFB0EF189A779D952DE748039B8B813D25437F9ED6C3D96990406425B56001E868EF7E9A5A31FEA9882ED315E2F4F33F6869A969D6C9875C302DFCC549173D7D3E7E787C89120904048D9C0DABB7BF53FD4E79A7117143534E8FC9FD3AC3154BC040A975D41FE8BAC91783B137E5EB1698385D381C2CCAA9085686836E4FBFD615959A620280E3350C2A59F5D77E5A5EB0D8E54BE3FF97CC9F644DBFE27431CFEE9C67FD270CA344A48D030B9F3FE6FC83E4669884D96A0372496BF3FF3053E619E33C6E0CE9C5017871B2B00F48595020F39C2BFE888A04A824AA80A5203D2EE08E5F6112387CE31003898ADB5BDADEBD6DAC6AADD4A9CDA9D596EA2C872ECFE81D05B794ED1D2B2BE056F0BEE4AE483BA4838513D9854A2A5C9C64C96B50A1E252803D38A97B35EB1252F3EC48293DE2C503976A35598B8F27A523AFBDA07B24FB3376A34AE53D16408D199ED5059773D6DDA9A914AEAEE1429414B6A9262DB74DB1B6165F68F245CCC4A272F1C5052A912BBCEEC283BA83BD29A11BD8C5FFB2DDAD9786501899C4059657117E837EB56D63CC6EDAFD81FB44EC9456661A5595768FA71216EA33AA608A27A9DB00A84D224A9E547D93693C338EE1D90F89E8C5A256071F2460F14964AC2D4286CE16400697A86A08EC9957697018A530527829C21C11CDDBCDBA523CF9AA7336A5AEAACBF36A3768DDA359406DE694D380DC292AE24851E1B8F10EB78C77CC9BB43230C12B13C6202C0243BD1AD42DE3E517644FC3622524A4A4F10B023A585CF854D79469EFD179880379B7A13C8FF00B6F8B81C761339960238252D983303B3E84B9EB4BC4163B0E2BC15B503F5BB36BE1A93A6C53E821245C1D8F5B5C5BA1DE074DB9C4FE8E76114F31F8093C24B904540D0B7E5F788C1294160A9F57A31A386234D1A30EF93FB9FCB193300A91EBFC42BC0373E9F88DCD3DF6B87CB9FE630779CBD7F883806E7D3F10B1B789F23B1FC2D1F3FD70779CBD7F883BB1B98C9EA854A60FC083F1B5FF1E671A2E630AD01E62BD76FE6374C9777A0D1DDFEA3DEFA728A93C8DBEEF740DFAC1BE11131C5C3D039B5EC694D07DED09CD906AC016A74DF7776E7B0877A0AA502A8369111E51BDB73BF2F2C678EA694A372DF4AC45CD90E750350C0D3EA7C34BC77CF51E5EB71C5051932AF0404F3200046F7FDED8432B12183292C19EA090F570FD3D63CC9817E2041A0D2F4B963420877F2A4545A859772E085200A5EF42A54921F2E70FA4F0C6D1F9E2DF839586C43844C042400414B33DAE35B6DE517DCB9822C1880C7AF2F2ADEF152672FD528A8877BD1CFC011689E83CB7F5DB18C5E512149078D2C7567B9DDF5736FF371C194B25CF2DC8A91F7E6CF6B456F9A07090A75239806C67AEDB7A7A4DB7849B21182A022AEC436AF7B74FA1BC5C32F21201497E4C777E57AED5884D70001B08DE3901FEF73CA715FC7244E428F0D4824017A1B791F0A6D175C11331043162C1B660FE15F758977649AF33CECFF005EE459FE56FA99629EA52DD692B012A6DF5A5BF182608095288F7F4C735CE32B528F1000A49571029D85C93B35CF8436CD728958AC0E213351C5340FF60B1F95CFCD4A03AD76018C7BED91EAAA6CDB2ECB731A65A2A29336A661C438D11C3DE25B4174786D3DE133D31CEF1D8732C2A581F32497B549B7A5ECE2F1C073FCA15855AC80C1CB162373E9CDDDB58B9F24AFA4A9A07B25CDD947F0ACE98729EA9D7877A965250A42086D5C533C53E1162271CEB3ECDC6553A44E49289D20A8A568F96F7729BBF32D70221F2699311315FEE94A4104F83DABA1D1C6D1D4EEC5FD9A33FECFBDAC296AB4A65CEE69A1F3172B2A1CAD282C329EF2956BDD60D92E2C8104440DA6D50CE7E2262716854B2E02B84125454DC2AF3AFAED61161CFB389588CB061D5891DECA4A8218D55C40BDB6A7531EBE64793653A529EA5FACAA6DDAC078D146B4825854CC49242A77988B4EDB55B179C62335526570144920052AE5541E219ABAF8011E67CCB2B2BC72A709DC40ADEAE3FB9C6AE06A01BD05E23F9F6B5ACCE10F34BE1629590784A385B1C2245B8426F6F5117D8E25328CA6520FCB24952AA5C955FF00F559DFA56D589718713B0DDCF7CC4A48DB403536DF4E44B375A7546B1656FA99A373BC5D39525DF119BED249BF2F2B7588EB1D9EC9A58964AE5A52E450A406F120120FF8E6CB2CC84C99B316495125C5BA915A7BD6F1486A0D50A056A2A04DFA488E62DE9E98E8784C0E1E4814492350D635A90187E6AFBCCAF00A4B324834AB1F2E75714BB549D6A1CEF527D65B2B5BE5A53615C12779F2E5B01F0C5A72F12D3312132854B6E5AFD0EFBF898504AC4A0060AA52943F47AD87561147E6DAA1E53EB6CFF310A2249D94394DAF07998EBD063A265987C34D4874A5058559EBB917AE95A3738591331628EA013A69FE0DB6ADDA2279C67C9643243E58EF02B89253C7C7CA24ED1C84CE2CD84CB82D4B200570B70914636D285C1D4D1D856B12983953B140F1254403525C9E6C0D9F666D5E21D579AD1B92A7495F9DD03DC200F5F85A31312F2E5AC072CC5A877E96A6B5DF78969381525884B39A505EDCB4AF97278D556654C920D22E5641E23C53C3D01067AFDD322D8772B2F41238E604116255FCB8E571B077893958650E1E305AE094B38B0667FBD9C07BB1D43F5AB9716F828BCA2104C45C5AF7F41720F39C2BFA1C3BB1C5A470FF00DC001B33A8EDA8A57568934F0A40484B1FF95459C825E95BEA46E2195758B0A8A5A4A82B9873BB65D7E49D884A52A22FD3A6DCB0B7EBF23CA10AFD66632934FEF58727C4D39FF989EC0A4A05D04914248F3A9D43FF00910FB94697D5BAA1D45365390E6B5EEB842508FE1B54CA5449B7F30B010073927E57C41E3BE21766B02852A5E658770FF2F7A8A9E4EA716F52D0EE6E265CA6134A43E80A4DBA758BAF4EFB1DFB456A250FE13A25CA3A77F83BD79EAA6124A55B1097824A60192239DF96396E7DF1FB26CB57C266226F0F170942F8830AFF00692396B7B3C68730C1A038989516622CDCAA3AFE2B1DA1D19F45CEBECD908ADD65AA5BD3E084A9D6BB962A7867ED0FE5BA0DAE3913CA39F3BC6FF565270C95FE9307FA8526C97297BD1CA5B415BDBC5BCCCD7082C108AB12EEEF6A55B7B45FDA73E8DFEC8723528EA8D53FE27523861A148FD206787EDA7890BF1F19040998F8E395F68BFA9CCF7B41C49C3E5F3B0411FB4A2612EE4D7E516E6C0F48AC66FDA456087FF293434CBD02883E20FA5FC5A3B0DA47D9DFD9F340703990E8C65EAE6C828A879C79E0549FEA28792B499B7236C73B9BF127B639B288566B899725414152FE6143A3B83EC86357A64FED1CE9B314B5A895A8D482C36D282DB8BB98B869AA58A64A5A6724CB1B61B1C34E96F2EA442909800CA92C711311751B462117271D8854C9EAC7E20AA6D55C53A6904F205675A9A798863373EC4AC01C67CDEAE343EC55E1CD2FD4D4A78471B083601B529A17E894948827947DD66B338E516989EFC821CA839FFC8824FD81D4C47AF339EA720A8F16B51BB8DB9D3F98D468452294A538A25DDF8D5C5B7BEF37DBCF1A771FADA22477406A05075A026DEED0C311899F32E49376726DABD7C347784AA4324C828F23001E5D0CEFB637FF004DC423F602A6152E453CFED5D79B41326AA951E20BF58E50A4A66556E84CFC24DBF19F2C06662B0F4EE896E4F50C7C793EBD68ACA335C072491AEE082E599BC6B4DE352D6CDE4A63F7E53BFECE105E718B92DFFCBA88AB104F3DB978C39E09859A85AAC01E5A9D2DF88C5A75A4856C7C847E53E9FB8798654ECDD1C53126504EE2EE48B167F1F08CFE9153182FE63573D6B6EBBD9F68D6AA865332073E6246FE40DBE1F761FCBCA59BE634B6E7ECC7CE3539730D0B1D6FD286A7C18BBBDA105454B728BCEFB1E7EEBFC236E987B2F2D20B124333B936AF3D34D7CA31FE9ED7040D75F1753F46F65B9CA84110543C849FDC7CF0F51810CDC64B5F95DB5AF3DF58DBFD39C58685EDE05DFEA7470CF0D954A6D7C3E14922FF003E5B9005FF0008C3D9187E1242AA92E1C6C00BDEFF00687787CB9249A07D8536D7A8F2AD21B1E423FB42444FA5FA81B7E1BE1F22525CB38E8FE546F53F7872701C24961D0D7C3A569F567742B284F100A067748833CF9C7FBFCB798274B0148048AD0D08EB736D9B5E90230C906CCDEF7E9AF386CA85260CC08312204FC23CF7EB783862BCC71F2AA994A34B3134DEC76E9CEF0A09006AFC9BEEF7DA9E570DAF02D34F5624A5229C0E2480257C5B7BF6DA4C9F84BE5988C4E34844F4AA5F17ED7AD06F4A74FA968AEE7388C4E1969FD3F130AB87172294E67EB0647A9730CB4B9581487B2F78143CC54A50F36A6D52850E07828010790B1E9C94CDF03879C8017F22E59E274ABBB248A872962588F1B8BC4F7677B4F8EC3AD1C4B50346049DABD3C5AD1D6FEDE3D913B30EDD32BCC73ED0E8A7CA35EA9A5BCA2DB6509A87402A212DABBB641E104481E7CF09E4DDBACCB24C477338CC9B2414212A249090282DC44B6B5D23BF767BB5EA9C2524ACF0967756D70CCFA53C447833DA4765FAA3B34D4359A5B55D15465CED23EB4BAFB8857054A428A9252A808BA40FB24EE3D71EA2EC56732332972F153316996DC2A282B1F33B16151D08AD6B526BD6B059849C5042E5965AA9C1722D5AB3EF70D4E8212E555138D34C50345A6980A06655C449B9955CC993B9FBB1D4F1B9EC9C721126524112D207159DF9B68D6D77A51DE230E95A8AC91C440E2200A1B587859B972D1C6AEBF21F96233BD2400D416AFF0010DFB8FF00BFFF006FFF0054668708993F2FD318EF08B06F183B8FFBFF00F6FF00319F7C46CA23DDFA6326613704F53FC41DC7FDFF00FB7FFAA39EFF00A92A1F77EFD0E1099340D58ECEED7D1BCF997D614461C382EED7D1DDFAC6F6DEDA0CFA5BCFCC79C1C23DEDFE6F4E9CBD3C79C6B3648014F534F7D7C07850876A2A88E3BEF69FD8B6F06FD6D80CEAB1557A7BB36DAF945CF94CEC1A95F4377DEF4D758F7DB59FB27D26A443B5DA635EB4942C2968CBCD121244EC8EF56B493FDBFA63CBF947C4ECDA44D48C4E1A64A941899A492E05E806EDE7E11E55C0844BE22B0F41C20D385B67BF51D6F1D57D4FEC9BDAC65EA29A3C9139937E28A94D653A83813B28202D453D62FE9B01D3F2DF8BB8698024CD5255F2820829ABEE40BD6C7E916DCB6721012153122F471A8B73DB7A6978EB4EB7EC3FB48C982FEBDA7EAD8E1E204B2D29F802D6EE90A99E9F0E98B02FE26CA29ACE43B3B1983ABDC1FF000E368B860F1B87494954C0C0D9C397AFDC98EB8E75A4751D2A887B29CD94429524E5D569098EA7BA88EB3B615C2F6EB038E5813F152D1A00482DA9B97E9A79C5B7058CC3A923BB5252DFF70735A6AFA68CF4A59EB6CD686B698AC3F4952D116875871B20DADE2408DF9F9CED8B049CE32EC427E4C44B503A710D7C7D9F38BDE498A925B8949B860E0877EBEC79986BC1D70A9A69EEE8929936B292414C90445F698E5CC5A2B369D84282D310EC5CB86E46F4FA3F9C5ED69C2AF0EEA29720FCAC0D1B4A56D7E7AD48F5BBD897B40CC75664343D9C966A2B333D36427EB010B7439F5A73BC400A09527C298FEAEB2236E319EE3F012664D267A0281759E260C1D99CB5A9A39DEB1C4BB7B83C3C997DE808952E6F1F761C1248FDCE2E2A4DC748F63B4776415EFB8C661AB9C34F42D842A9A9140053F61C40F010A4418FB42083E58E19DA8CCB09984F54BC1ABBF525C4C20370F9D08D3D46B1C1262E5CA4620A2684A8711005C8D350DD69AD758EC054578CBE9A8B23D3342C656FD1021CAE86DF754DA882485A815094822CA3BDE6F8A0A32B5A97326CC26622614F025B878384D41A56B7E948E5D98E678C998832D2B581C443B96356B68D5D76DA2B5D4B5685E66A78B8BE3504F7AE952825E21104845922FD2D04C729B4E599710B4B49766B0766E751E773D69B4DC22D720CC2A3C5C2E473DE9A170DCBC22A8D619D56B4C2DAA5580D1042B848063A7AFAF39922F8E9F926024F1A4AE50E2A3063E2EDA534B73310984462BF50996A52B84A83925B5FA1BBD0C75A33DCE99CB96A595CBAF93DECA88BA45AE491E91D6F16C5B71B2C20CA12889628080DBDF7726CFEB58BDCC989CBA52149F9CA920921EB4D48DA8D14CEA4D5C885F0EFE216923A5F96FEBBEF7C5E7B3B9461315C2676252E786854075A936E9E109CACDD2B3F3CBF4AEC28D4D2D41E315257EA1A7AB2454B6F786780212E2A49B5C207BC75F863A748C83072C20CB5C8530A9336586B6EADBD626F0B889136E024D1DDB6AB747D08E7CE34BA2CD337738327CAEBDD5AA424A28EA0DE3707BB20FCC5B91061CCF46558297C5331D2249009ACD411E6547C6C37E526818472192E1BFE3ABF87F9AC3ED0F60DDB16A984E59A6AAEA9498E02F27EABC1C7B7FC54A42E6D244C75938A7665F1532AECC71204E938E4BFF6CD4929035F94A987D5EBA44B613F472C1F9D32FC8B33D81607D88B334FFB047B43EA2527F88E548CBA8D712A35348A294D8981C4156116B138A4637FA95CAB0AB5265C932C870C3896D70F6200E861FAA7E0D80EF25922A15C4915BD9F77BEF17264FF00462E6301CCFF005CA72050E12E205222AFBFE6A00A1CF0F0DC08DF79B629999FF519889EEBC061D734172BF9CA0827F6B710F5AD199E90D66E6928278664C42B87FE991C3F2B9E4EFCBFCC5E5A4FE8FEEC5721EED5A93509D44EA2EB47D5AA69C2C8DC781440980091B75077A2661F1E7B43382C4A91370EA2E1333BE2BE1E60354F2AF5111ABCD81042A7858D8003D6AFF6DC98BFF21F673F678D2602F24ECFD8AB7EDC750ED4BAB00A2784F76EA488277023998DF146CC3B5DDACED3F12B139DCF4A0542424A59E8CE0B9D2A5C44163F3C561DBB952ABA851F1B1DCFF116AE5E9A1C95A14FA7322CA72E69B84A5272EA275691C80716CF17BE7CE462BD88CBB34C414AB119A6216D60264C079D38ABA73110ABED16281A2967672487F115E9AC6E7EBF50BDE27D6CB68FE8EE5965B007A36123A7481B63323033258527F50B98E0385F128EBAA892DAB0FA0AB39DDA0C58F99D55BDDC78339161EEAD8A756E2CF7F993A49DDB8584CF9C1F2DC6D63118789CB4104AA5850ABD03DBF9F462F4664BED062839F9C93677FF003E7FE5400C34900B21C0B175973681209124F2F5E584E6A8E0182240505120808725B5766A79EE7409CAC7CEC7179814CD406BAEE696B59ACF4846E54D2B5E215694C4FF002FBA1FF4F144F51B448E5B61CCAC589A901182295D3E600D6B701836FF00430B842D475009342C6A3504D6B7BBD9C98E59D4540D85875B48200E05752378006C236F96D892460B133EA1250EF46DC3B37BD28CEEEA561C29B8AFE94A917DB97AC3755EA8609FE49092072DB6371CF7F31E98929393A830981FA8DFE81BD29A43D978246ACC4588E953A7A0F188F556A171EE1529E8093065439F493BEC2D6EBCF0B4EC327049F96495BDD8174B741FC36B4108E2B0E89600410A05C11F4A9FCED7A437AF3C8559D4C1DA143F1EB6F31CFCF59730AC809C32EC78810AF070C1EE7EED0CD329CF090E6E77615A57E9FC423775129023BC0799F15C419117F873DAD8949382135819079BA49BBF27F5E51212F0C9201E163D4DBCD872A747844BD50A124AD244990543CB789BF3E57EB87E32394B002A5027FF00450BECCDEA21FCBC1A76FE1F4ABEA39F852139D565327BC03D543AF9903CB95FE1855191CB402112B843D404F2E87AF4F386B8C906511C20D5F9F9381F8DE342F562C890E0F14FF5A7DFBFBA3CBDD8DCE5069C29A0E458DF952BCB4F38E75A07CE3EC6BCAA7F10997AA564FF00C498B18526DCFD0EF8426E533459246C5B6F277A73BD1E3624F0B849AD8ECDCAAEFCBCE12B9A95524F1DCFFA87C7F7F3C31565D8A07F693CB86F7A0A13B59DF94612166BA6B46F3A16FE232A5D46A5F79C6A1023723DDCFDD387584CBB12A727880D4116A9D1BCBADE1D61D6438343BB86D7D3EFE718D467920CA811BC7145E27E516E9D231248C04C961CA4977DF6F06B373A73858CD27FCFE07F88C292BD355DECAD29E1893C5BF900489F5BE362860077640DAA5EDB8FAC26A9AA49AA29CCFB6A59C470FAD2A0A097048DEE0907DC64DF7B5FCF18135083594E2CC53AF3A6BE1AC6AA9E4D58FD7A685CB5FA436BCF30DB0EAAA1D2536F009F1F4FB33B72B4F2C2F2A782A4944BE0BB909F2D3CDFC01895CB72C939A85F7C4258382A67A3B8140C69A42043F963ECCADC2DA018EEC0599336F2F7EC3CF096372D9D8E6505148AF11B167D6A36DBC75847199248C32D4652D2003466A51BC5EFBF8D23625C6A9174CFD2BA685F492BA2524921E832B4A84C7900B917F8B34E130F854AE5CC94261218A88B3B8A52FCE15CB7133B07352CA20021AA6D5D3F3E24D44417B70EC334B7B50690A9A5CC2829F2ED7795D3B8BA0AA6DB4F15529292AF1A9B084494A07DB260911E2DA3E4E3B1BD9F9885C89D31380E225402947B872080C0BA828DB6B5ADDAFB359F70A90A54C09581A970C4070C4800E869B697F9D5ED2F416A2ECD35766BA475150BD4B59963EA6C294DC36EA3895DDA9B5A5210B1C204F0931378B63D07D83EDACBCDC1913480A40002890EA70EF50E3CCF2ABC75BC1E324E2A54B988980F183C4970599C56A5AA79024F9D7DC6A98813D20CFC2671D6C294A4F184929677D199F6DA1FA51C5FB520F808C16E2936B03CC117F81FDFE0D978E9083C2A5805D807D75E7E958C29007EE4B7A75B461DF2FCBE18593392B0E9623707F88C25295164873B545FAC721E5733EFB7DD184E62CAC809E8C2BB6BF56E861712BBB0EB0C0DAA6EDD6BE0F0A5B7AE20F3369DFDE479EDCEDD708A8197520872F7A93CAB0DA601707D2FCFFCE90B98A92926F04C11703CFF000E9EFC69DE23FE43667E7B7AEFE71173504A8EDCDEB4E7E14F03611EEB687EDA28B56E4B4B5F415A52AE04F1D1A5E217C560411C4166E3A7DF38E6399F626461D6102527814FC2B0078B860C29A8ADE3CD998767A74BE2480525248A0B9AEA39EB56D5EB178E49AE334453F7F4CFA815892D38BEF0A78605FBCBDFC85CEE76C51332ECD2A51504A4109B70A5B5DC5C575761B55AAD3B0B8CC3AC8429418B0BD0EB7A1058D37DE1F59ED3F380A087E9289F44C12ED2D2B93E678DB50DAFCFD0F2A8E27239D5265CE26E005AF437007260CDD6C61C49C46310A1C530BD1BFC3FDC0BD4439AF5CE555D4CBA5CD34F64F5497C4718A2A26C343FAA5419FEA9EBBD84E18AF21C793DE495CE90031502A5176EA6940FF589019B62A5283CE551810ED723622BCFCF522B5CDFB3AF67DD66EAF2FCEFB396332AFAC2502A292A1C6C256BB02453A20415036FF66188CEB38C8D4923325CB9693F32141F880E64D2F423AD6AF7CC8BB5BDC00264D2486A9558EB63B8E756E515767DF44BE94D4D5943A8B24CC93A634DBEB53D9865EB4AAA14EB44828405B8E25C4102D298266F84317F16D6B0642E712A0024FCE471102DF9DDF5BC5D95F1144891FEDCE1C481FEDA8A8324EB427E606DCAFA477C7D9F7D9C7B1BF67AA34A342D0D3D5679C094D4D6B85456E38911C443E55B5C0124016C53B1B9B6233E0A016B9724BFCC16544BF315BF372F1C73B5BDB4C4666B9AB99882B5ADC10080070B8700161A3B00FD62F7ADA8AFCDEA1E79E7128503FF00080084A06C0003853B03748F9E236528E440AE72FBD44DB155C80DA924F5276E42397CACC66CC5CCF9C92EE43DEFABFF001D2C18EA1BA868C90EAD5B7F2DB52A40B72067D66230EE5769702A2C6580FF00F73B3F40C352CC35F14CAD255C4B40E2B82456A6FAB730C2B10ECEF2DCD336EE9BA1CADFAB7D1C501495D3DD5612A5800CF9EDEEC4CE03B5584C3AD5C012C59EAF41767E5CBC21533CB049FDA6800AFD056FFCC41ABFB1BED433849527206E8A9553FCE56614EB21276250A58579C73C5830FF001272BC3AC209698080592ABEB5667DB9962F184B03C4940079102D52C34F0D1A22CE7B251CFDC0E6A4D7BFE1F553994308CB855F7FC5F693C6D984949B1379C2B9976FF173C4B396E0063925F8D426897DDD9A8C1DF6687285A6682274DE103F682C767D3F1B58564D967B21F65D4252333CE7FC431F689A77A9B8E05F63691CBFDB11E9EDC768387E4C1AF0AA028A13DF84F47FA862CCCD192890141960B37F6B7D77A0F1B356279967B3CF6099382468C4BCEA88870D53EAE229333C278A2FE93E7B618E23B5FDAF517FF599D2907FB5DEFA163A57CB7AC6FDEA01749D2EE5B67FADFADDE27796697D21A7CA7FC35A6A8A9383ECF1B0D3A44411FF0015B331FBB620330ED06758E97C189CC31334310E16B49AEC42BAD346A88DD38B9A97216435AA4937FF0015E512919B57BC022B6928D086ACC062969D98B00412D213C5B5A648F2C43E0654C26628AE74C2B238B8E6AD5FFF00B288D74617BC4763731C59002669D59A877D4F3ABF23B4267EAAA9D1C2DA96849D82145239DBC307E189232491F384B06350090FFE79C468C6E3CFFF009AB67BBBFBAFF986E4D23EEF117DC70C1044B8A264CF99318CA70A14C18005F4034B53D4185C6231441798A7A52A75D9EAFE8D7D2368A669BFB4A048DA483B6F2663F59C6DFA142A9C219EE40E8297D2947A987099939BF7AAD73CC31D7E8083AE91B05752D28225002F918E533B9EBE62E37185E4E02683FED2481AD2DA6D62C0DF43768590954C204C2549A9AD3A5074D61A6AF39A61242D23EEF94FE53CBA494BCBF1258976D86DE36A5AFE26B0A77097A02C3D3C798A5B41D6182AF5353D3000BA0C93CFA6D173E5D6D6DF129272A5A8025245AADF7EBF4D69019090C421C7476D39EAE59BC223957ABA94FF00E6206F7B731F0E5BCF3DF9E2564E50B15009A6C69E8E29F7B464E1A5A88F9051E8CFF5B7DE9ADE3D57AD92D001B766667C5C899037807DF07D7793939089A1D480A6FF00B45DEA6CFF00CF9C2B2E44A03E54B3D28E35F23E1F5AC46EAF5D1332E024F981703EF9FDDF1292BB3A84B34B48662070F2E9F4F387224814E1B5BC798F1FF26AC4FEB8248F1C8BDA76EB3064CDA67DE30FD1912524809BEC9D69F9F43194A149B06ABDC7E61ADED6E20F8EFCFC5CFDDCC7C2C230F5191BB30B96B379BD6AFE1195778BABD0FDB772D7B6BE02AC559AD9C514F0AC889FEA22F3B7EE63ADF0FE4E412CF1712126C47187FAFBA1D2329413FBEBBD6FB6F0D8E6B47044B86C6F0A3CE23F73D7D0BD4E4328544B40D43247E2AFA53F30B2252410421B9D2BB52F5D77844EEB4709003863AF11D86DB9F8F9DFD554E4B2D364D79240FB31F77D1DA2593FDB4F23EE9AC37AF59AC190B3D278A40F7491BEDBFBF7C2C32996DFB6ECE784D5B4B034A6DD2B0E901496615AD684DB66F7531A15AB7BDB29DDB621506FEA47EF95F1B272C4A5DD001E97F21E479C273A5098C0A5C8D4E9C98B7D630FF13A3FE72BFEB1F9E37FF4E47FC47FE3FC421FA51FF11E9FFF0014649D581BFB2E154EF2A063E78D55964B3FD96D923EE3DFD33FA61B0B35403B6E746A465FE3157F7FCC634FF4A957EEEBBF0A7F119FD3E8C1B664FE63735AA43C4953844742448F71F9FBB1B0CAD228897E694DB5D3A437992BBB366E8CC3DF5610B11A89B3092E18F27279CF33F0F3C68BCB4D7FDB05A96B1E8072D0C26505AD4F03E90A46A244801C2044471013D363CBC81DEFBE1BAF2A0C78A58DEC34BB346BC25DDAF7706B4FA78690BD8D428FF9A4C46EA3B73B49F2F293E986D332A4176403425B8454F887376D3EF0265077E1A1E8FCEF57A5DE168CF1A72C482636DC1F98D8FE7E8DCE5A949FD95BD874B1A7807D79C6C999364D251297BB38A3FF0027FC085CC668C9220A2368205BCF632447ECEC9AB06A0EC2FB69B3D7ED5D1A144AE6ADF896FE0F777A9A9AEF7FA2A7ABA99D085B8A03BBFB306DE2E824903AED88CC5617852410EE0D5BE85B96AF6B6B0EE5CA4B8243AA846AED434D9ECF53E149365999E694291539324A82E0385253C410601B9BC44FAF5EB4DCC6429414921D2F620B7277D798B51A25254D9929B814436D4F67AC7567DB77B00A5ED4BB305EB6D394AD3BABF4BB2E5454B4C3294BCF0755FCC2E148057C2DA55048558408B636ECD664BCB3324238FBA4A96912D4E594010E341C83FE5BAB762731981610B52969510169528B125D88B90C6B71E0F1F3DEDF7C9CD169A9416EA90E3AD34D2814F0AA9CA90F02081B7091E21D0EF8F67E419B4BC5E5492A292A54A0D624D00249A55C53CAC63BCE1132C278480A5000AAA0B712411A36BCF4A4697EA454D5BF503C285C252208129B1811D762371BEC3140CD6562958CE296A57095D6A433B5AB6B0D00E909E290002430B0FBFBF5A911C71A7AFC8E2D7830B97853C6493C22BAD479577357A437C2F0AA635C3816DCD79D6B5D7AC1C49EBFBFDFC79616CAF1697982656B47D2FEB41B810F33340084100301BF2DBAD86BAEF0718DC18F49B7FB7AFC70E715884ADF84B372BD6CF67A723CE2118867DB6BF383BCB8857A933CB6DF104A2B33388289ADF66E4F50631C2083405AE453F98BEF4CEBFCDF43E794F9965D50E9485A78A88295DDF0D81BCF01B5F613E9389CCCA4CD4A54264B2DCDE9A333756AF955AB79A64B214E90122E5D87873771AB063A47A3FD9AF6B949AC680D577E18AC69B6BEB6C71EC4A61302449317E104C11D714FC523052810B2902A5891426A5C92FAB5FA54C72ACE32B420AFE502EC58E976D2A03FF88B92975032FF000B3DF1EF098060CA89DAD33F0B9C432E6E5C16489B24DE84A74A015D7F8AD6B41C609525441205D9B715BD06DADCD9EF6EE83ECAB5B768350EB793E5B50FE54D29BFE2754B96830DAC8285202C02E710E48E5638E73DBAED8651934B95204C947133828042784BF0817297E17D373D5A2BB8D5A964996E529BDEFCB566D0135AB011DD2D15D90E98ECEDB64D251AB34CE4F0F1B6F36E0097089238DD053B93B1B45BCBCFD9BE69333C33A825243F090A492A0C492CF4E76356880C4E65370CC10B50A907ABEA4034FCEB511720D1FA973CA74BB9850A68287861084D6B6070931F612B498883613BE3974EC1E18E294938898A585314894B22EFFBAD4E6CEDE4C27768319C247129B60AA6D6F13E8C740859ECF74CE5CE17559BFD55D0656D80B724F31C5C5CAF7DB7C59F058F9F94200448336591FB94B09B5CD7DF48623113712A75AD4E6ACE6BB8B6FCEBBC3A21DD1F9780DAB2B39D2C1FF8A2A1CA5EEE01B9008E3E2F88F4C6313FABED08025E23BA425DD213C44BE875A31E5E4D0E01EE482C41362E4F56A1F62140D434ACC8CAF276E8F7E12B58A883E7C6923E0394E3597D9D9B29242E6289D4915BB3D01F7A1BC67BF528D15E0DCF701FCA13BFA8733AEF0D656B14FC00865A6E89A05C9B1054840222DB98F538DD1912A5926592CAFDC5CB6F625FC9A3638936770391FB8A35A181F4E60F2A4D33CA6C99EF9352A02277EEC1F7F4F33857FD3141642940A8EBC21D853C8F5DA35EFD4C3E7A3D8D6DD6ADA7F9AEC66899701EF2A94542E5050A3C3D07113B5AE7975C4A6193370547252451AD4B9676A1D7913A43895378C92E5F4FA1DA9A7DAA615A72DA350BBC1405B927DD333F9728C3BFD54D5DB88B9A72A59890799858924B98E54DD2D00965C4A4B932080EC91B1B931FEF8D485CF0CA4A8105810E2EDA5AB5AF2B883894050B35BDDFD61AEA734A76E4ADD4C83C92904F98E1FBA2270A0C02D5429241D473B56CFADBC633C4ADFE90CEE6754A248524C03BAA260F9FA8DEDD2C2F2585CB5612921041D0B3D4F2A57F31812C4CA6A2D6D8D1CE90CF55AB69A9F9A401207881E66768998B7A5BAE256564EB99520925BFB4DFEBCBEB1B230FC26A1F6A8007853CEBBED11BABD74DABFE1B89404CCC280BF2267EFF00C0E2464E44416E124DC534D74BF91D21D4BC3D89A1602C5C9F7B6F4D622398F682B6C2A1D49DFF00AC1BF9F8BE44FC70F9390AD80EECBF215BF4AFD0E94687430C4A696D5F9D59BEA2B10DCC3B45714524BC00122EA03F1BEDD207BF161CB7B3A560BCB714041B8D057EBF6A8877230E5AC69A569EF96BB0BC56B3B4274CFF003C1B5C718B8E5CC1D8FBF13F2FB3290C020B3EC69C85EBE7BD9A1D7E9940174D2847A3B1BDFCF61AC6730D74EBDC20BC07093B2D27AD890445C72B5AC31212BB38D5087DC375D5B5BF846BFA6511FB5B4A9B79D2CFE0F117ABD66F4121E1EE5811B473EBF2F762491D9DA0FF006DCEB415BB3D3DED5739FD312E025FA9BBB8E9D3A8A9BC323FADD4D59C701076F18E80CEFE5BF2B7962570BD9F24370330B30F64756E75610A230AA0FF00280D7D19ED5F77861ABD7727C2E5AF238A47CFA7CBA8C49272229BA7A52956AF8B74610A8C3916FB7E7F9E70D0AD7624CAEFE6A03E127FDB9E1C232276250EDA37E038AD7EF19EE0A86A474B5C6FD6F081ED729BC3969DB8A62FCEE7F2DBD70F139250108236A7F07EB1A8C31146D5EAD7D45C53EBB504379D6E924852F6E7C5E7D247C7D30EA5E48E920A59D8BB6CDEBE5AB88DFB824BB12CECCDAF8EC368D0AD689932A9F5503F8FE1F0C384E4D5B59DD9F4BE83EBE70E65618809171B31153CCF975E621139AD1004057583C561F3F7EDD05A7191947201D9C37A5479D7C61CA70E77E800000DFEDAEB7842E6B34816548DCC1FD7CB01CA3E604A75676F1760FB9A9A51E9ABC9720A52294D69E22AEFCE91A0EAB2F9F02E387FD43F3B45EF323A8C64E535A203176A7D69AB56FB18D2761EE5B85EF47D2F7F1F516783FC48EFFCCFFF00DBFF00DF8C7FA47FD89F2FE21B771FF7FF00EDFF00EA8DECEAA2D1571B9BC478F8BE65780E51FF006A4780FBA4C67F4E7424F8375DF979F9EFFF001827FE60F889F778BEF23DF8C7FA3F21FF008A7D7E5FA03E107E9D85490741BFA46D6F54A9E0781C1E189850E768B98FDEF8C8CA7874A3DC8481E845FCFEC9AB0E4E8EDCF7E9E1710B1BD46E5817418F303EE36F79DB91C6ABCB05004B3BBB5AAFBDEE1CEA4D18C2470E496143AEDE2FBC2D6B50B8AB9581111E2927E6267DDCF0D26654521F87992C3EAC2DCDEF194E18B12407D28C79BB17FAC3A53E7EB1B391CCDC193D37F38B461A9CA8104B709DCA5F9D01AB6B5D89D2038751B06F33E9EFF0FD459E2D6482E4111CC5847AF4F8729B623F17960FEDB1D5ADBF43EADB420BC3312141C9361F663AEBD4C3EB19CAC443827D45EF1BCD8DFDF798C33565E59CA496A0A5FEBB3D7D4C604B22C9DB63B0F2B44932BCC52FAF8AA163BA6E244EF3B6D24C6E0EFB79E2171D97F08F950E482CCFE24BD36D3CEF0B252DB82E1CED5E741E9BD22CFC8335A8A358718521748A0016E526124729BEE79F3988C5231F8104A93C3BDC5413A1F1FADE1CB52F6DEE7A7DE2DCD26ACB975754BCC1097B2ACD695FA6AEA75A789BFE732B65B24104594B9102058CE39BF6851330CB42652CCA58585058151C2A04B6B5142CD422F16FECC6293879C1CB391AEBD1EBCFCAF48F9CEF6DCEC453D8FF006BB9B53E5AD1672ECD2A955793A82785B525D1F58A80826CAB2C8DE4131CA31E81F87DDA6188C261E5A965CA02189B94809FA82DA72B3FA03B3D8BEF25D54486A9357A5013A0157D7C0C74D2ABBB052EB3096DCE5FEA480164CDEEA9FC31DA6465C8C4A5331828DC1AD1EBE66C7A686B162C47CE9048A1BD7A75F01F50212F193CC7CBF76C2799A46164100B508352C4D19EEF6FB5A1BE192CB1460487B59EB7B35FC290059E4418F43E938AB60712A4AD556726AFF4EBE3614A43DC6A3890973A58E9CBCFEC39C1C6AEBF218915CD2A04855DA94FC6DA188CEE81BD4E94F6F1A9D5AAC449F203FDFE7F942492AE249507BDADB7F93A36CD1B265814BFA790DDF6FCC7A3BA43D897DA2F5C86BEA1D9DBACD2B9C3158FD630D2824C1E3EEDE0950B72DEF1CF109DACF8C391484CC42E6A105415C251F3B535E10DEEBABF38C7769704B92172B12998B1747ED3714E22DAD4D6B66B4771FB2EFA323B56CA2A9399EA1D78747210A6D6AA3144CD726A4020A9254DAE121039911D31E74CF7E22FEBE6CC565B8A54C492A74F094D9C8A96176F66B4ACEBB4B97CCC32E5CDC083359A54D137F6124B9617A373DCC7A1DA23D973B3BC89348F6A0CF3FC499951F0127EAEED2071698B424C47879881C81C732C7F6AB39985412A9A82EAA85135362C08D34F0D8C714CD7321C4A505F0D4B03B6D4D816F2B477032AD5941A7B2EA6CA74F640CE554F4E8E053A82859AA000092AF00360247112761E58A2E2E566799E2A6623173A64D248E10AE2F92F6AF47635110F85C72269520AC5ADBBD1BC3D2B4763086BF546655AA2A4B08926CA0DA02B9DE4241B75B5E7CC99BCBF0F2E401DF715AAEAB378FF0098658C099AA50490E2E68C3A6CCC7576A924C372179A66055F5879E42531C0038B00850B82124585BACFBC1C4DA27E0A50FF006D12B88B392949B5AAA07DEA62115825153BBD4B1A7A6C6DA7D6323953847896A51B9924998247351FD7717C41E6D2D58B1FED6D460D76DB5D6C2BD0C4AE1308997C2A533E808E76A6AFBC6D6B23EF02C13B478BD7900227F0C23914B9B9671778E78F7D2A4B6B776F3AE85C6324215C212CEC4B0E5CFF000DF58548C992D7DA337DCCCFEE3F199C58558EE2B067E8C3ABB3F85B48622411CB7D7EA60759669C02549E7731F2263AC1D87C30267297706BCD81FB7E203294081777DBF3FC6F081DCC1A6C11C4205809B5A7CE3A5BF495912B8FFB59DF57D7AFE2F18187481F352DA93D69E7E9CD9ADFCF295B1E25A0127910368F537BF3BE1E4AC04C9A3E54BA74E4EF57E5B887985C3BD402DA1AD6FCED5FA54C45331D494C0C77C241BC28DF9DB90FDDC9DA4E464AB5172953D1836BCF7A57E9A43A1865392E4826819BEE0EBB9FB443AB75AB742210F7171CCCAC9022D6931E640E9EB89CC3F678AC0FF6D8EED7DF4B8F2DAD1B0C22B899ED5B73D75B369BF2787E65DA1A47178C738B83CBF5E7CE713B85ECD129629A1E5BB9ABF41F5AD2344E14872493A746D9CF336A6C0C40733ED0B6876082AD97122D0441E5F3E66F89AC07674A685048E8F6DC6DD2876A43BC361CB9E77A5697F434A75BC436BBB41324F79BFF00ACDCFBC4C723FB8B0E1FB3A354576E1EA3969F4EACF93874BD4D4B39AE834AF95222959AE43F056F149127ED913B8037F5BFBF13123B3547EEE81B427E809B914B386B343A4618306147AD1CD6C6BE0DE43788CD5EB068C8EF8DFAAE6DCA6F6E7BDBE589797D9B4A98F7551CBD5ACFFE7A3A4E1EB56E5B9B6B5E7AC43B3AD58DAFBBEEDF20DEE167EE9E5E66D36C4FE5DD9FEE81FF006AA2AFC3F5035AEFD61E49C307B1D19C1D2EDEF4B86788B3BA9D2265E3046DC6ABCEE7AFC671369C981AF776D4A5CFBEBD44385E19EF47D83BD3607CBF8A36BBA8D0A36748893F6D573FF508FDDBAAE8C9D229DD9ADA9FC72D6BE71A7E9056A6AEC18DC7D5B7E669B35BFA844477AA02F3E3E7E4388EE3D371CF0E1395049AA6BA387E9B37DF5A46C30E052B7A50FF001573EA219AA73D42A25D3B1DD5CA36267F73877272C4A480C0A8DC331157DDBCCB42A891566BEB5A5DF586B5E78DFF00CC83CA144DBA993CFA6DF0C3D4E5A1D9491E403EBA9D3FC6F0B7E9B97BFF00CA10D4E7483C24382F3324C7DFF8CFBA30BA32D4D999ABA13E2CF18186219EA77615EB5D36B5F786B733947F79224CF888FCE3E1BFBB0E9397A00140DB307ADDB9529BBF8C67F4C1852BC8D3EB60DB8BF846AFE309360BDA6FC479FC3E736E470A0C1A122890185C00F7E46329C355A95DDBEA490FF583F8B0BFF337FF0054C0EB73BFEE6241D7F4C904B2789DDE81EBEFA7285D3866360DE05BA0AFDFC213D466893C1FCC169B4813F33EE3B0DA231A8C3006A900B9B81AF9FBD03C3A120B8AB0D680136D39EF6E468C98E66836E3DF9123EF07F0F86F8C0C280A761D7DFE2B0E8480C38BC472D371EF5B473FC5120D9C8DB65728F51CFC87BED07E94034008E601FC74A8FA97D6761C10E030D8D7EBEDDB678E7F8B27FE67CCFF00DF83F4C3FE29FF00C53F986DFA73B0F21F98066C9FF99F3FCD6707E987FC53FF008A7F30770761E43F31BD19BA37E31E627EFF0017DD1F2C1FA61FF14FFE29FCC67B826EDE207E617339B213C5E33B8D951F8FE76B4EF8467614355218DC507466277E909F72C482068C43535B3BD5F4E421623371FF003150623C64FAF3133F39E9BB7386410FC201EB50D62E4B1EA5CFD8EE52DABEFF00C3FE617359C246EE131FEA8F4B4C7EF6EAD2661527FF004BF5BF466F00DE91A1C3A740FCEC7CADEF943A339CA0442C836985DBCB63EBCC01E47082F0A91D342C7C6FCEFEB78CA64243D1BC4926FB1FE6D7879A6CE923FF0030F23F68F4E7F9FC45CE194EC185E8F76205B9B3F98B6D0DE6C904BA412750697A59FF00C33BC49A873A4C0FE64F985493F80F39F29C355E5CC91476D19B6BEECED61630D55254E5A9B8D9AFBDF661E1131CB73D6D2140B84484DC93FB267ACF3B5B10F8BCB8A83F0D3E6E6E7714A536D61352787C7935A2C1D399FA03E805C24150B719EA3913D6D7EBCE6714BCC72E67213BF42EEDA7F986C0BBF36B16A0FB7D1B678ECEE8ECC935D4EF3282081DD13D4410641991307EF3B938E37DB1CB140899C25C3F85BCFDED0E30D8BFD3E225B1A715DCDF57DC97AB52F7B8E9CFD269D90AB53F64592F68F48D71BBA51BA82FB884CAC8A9752D278D43C4AB279F981CA63FB199D4CC2E3BB92AE14A16800380F4D282C2FCE3BE763F302B44B4B965D0DB7F16F2FA57E759550EBA029C04252A5049DBEC98363CC4796DEB8F6BF65F3046272F96A7015C1524BE9F7FBDDE3AC292424275A1EA0D7EE235973CA790BFAFCBEEC466758B4CC5292142B46BEC7714F5EB1ACAA2D3617FA1FAC6C43A6FBF2E7B7EA7D047DF5D912560B83424F838D74A335372D0EE727BD606840A86F2F7EB1B0B806E23D4E2465A295DEB7F2F2B9FA86847B8AD154E8E7EDF7FC62AAF7996D4CB090A2F885180600E932458F2BE375A8A0505073DCFA6BBBC6532120D4B87A7E49AFD0D23EE58D7D7B87F90F334A23FF2295968091784A12916E623D31F37578BC5A49054B501AACA97471FF27AFBE51F3CA5769715303AA6101EA6B5FE43ED5118703AA5A7EBD9D2CA567C08EE54A9F78988DA670B48C74C2A0F6342C03823C295B785A3188CDE74D4105448152E6ADF515F10FBC0E648A52C3D4AEF7A94C12A29E19D8EDF3369DEF89FC362659FFA92DC8D697A7DF5262A7986266CC25B88062E01D5DAA4330DAEDD21C9344BAA4210D27854CD9CB44CF4DB6F89B5BAECAC44A94B981494B2998961D0DBD2D5A44223193A4AD8053137A83D2DABDFA750BDACB5F6CDC098B4904DAF17E9B11E82F88E9DC331F8080EEE069D1F43EBCA27F098A54D62A0DB56FE9B3824C6F51553C7188045A0031B7404EC3783BF4D9A270D338832B6607D75F21CAEF1348E129D1C742EFF009FA51E95D2BAB49025503DD3D3CA3979DEC77C4B49904252407FBF99DFAF3D8319F8954BF9520921D9A8E487A300D7606D5D286123F9C374401EF078A6F206D1D7A5AE7E785958454D0C0356E2BAE9A68CDFC467033666214789241AFEE24BDC5F41D7CED114CC358776094B891C878927A81E5FBEB87587C996B3AB86A36A58F3BFA44909243D0BA7C5DDF9EDCA21B5BAD14EFF00E6A470837E310679DCEE3E78B061FB3EB2CE14E74626F66BBF9BF278DFF4E5DF57DFF9BB546819B6880E6FAD9D6F8887B69D9423AF22479FE63160C376616A1FB554D83D6DB7B1CDE35EE00AB7A1F5AFD6F15B66BDA0BE88870DE40F1F48E73CB9C1FBB16FC9FB30025416973472CEDE5A7869A562470522A6C69A0DFAD36143CEA220D98F685502DC7133FD53B6F10636F8FCB16CC3F6725A588439E9F5A55F95F6DA48E1C1B25AF63FCBFD36882669DA3383878DCDE784957BBD2D7FDC625A4644840712BA8B0D0FDF5BED77C7E98EC697DB96BB11107CCBB458E2FE77C553F79B7EE71268C9D9889543AB6DE1AF2A6F48C7E90E80B68000DF5310FA9ED0A7ED390449BAAC7A9131BF947C313383C8D731C22512433B06F56DCFD2978DD187E0366A790F7B539C45EB7B40041873CECAE77F506F61B7289C4EC9C8668209924071A52F7A57C0727DCBA9529D541C46CF6F01EFEAD11B7F5BAEA15097002264F1011D0EFF000F76DCE7B0D9404FEE4682E3A7D747EB630F112663064B02D522FABDB956CF6863ACD5CFC121D83FFAB6E53CEFCBF6226246552001C400A6DE27D9A6D7A391216CE433D4BEB40CF6036A18607F54BEB8974D898BF2EB24EDF893E78929796C9154241702A18EFA7E5FEF0F24A1449F9438B7A787AF367AC34BDA99C5132B248B595BCF94C7AEF85060D2094A6583762DFC35B975DA1C194B37413D4084ECEA0717C72E447FAC5FE26E6DF75BA6A708D6433BB8E1767DEDE756615A083BA57FC3D04277B3F59305C1CEFC5BF3F21B0EBE9B6105618B91C0430D8ED4ADFC1BD088C2A5A9AA8F4FB8722DF686D733D75572E584DA473262D3E5BFCF69DD18750154B73E61AD6E553585A5485100A505F723C47DBDD92AF3C5DBF99E9D4EDCBF630B265115B9DA94F7D75858E1A610CC5FD3F9F2109159D3A77583D25447E9E97C2F2E492C40A92761ABBFA54F846061542A5FC74E77E637E509579CB9BF797F5FD679F2FD70E44903FB69B381F7FABC6DDCA989AB3EDE9CE386B365A8A871DF7BA8FE07CF9DFF001467A120064B72B8D3D3A529CA364E1946A01AEC0F81B10357B46EFE28BFEF3EE3F9ABF0C35602C1A1C2308B001677DEFD1C68E2135466AB1C32B3B923C407A49323E1F9E08769C32C81C496E9AF3B8F6E7AA6FE2CBDF8CDBFD53F120C0BF909D873C10BCBC3B100A4DF5177F1A3539E83683F8B2CECB3F1302DCCCF3371CE647492359D86528D05A9AD3F3E3D2907F165FF0078FF00ABFF00BB0423FA49BEC472335593F6C7FD5FA9FBB0460E1660D3D3F98528CDDCFEF1E6388FC7D2FE57C118386982A416E9FCBF942E673654125520C589DB698E636DFDD717C379E3F69F0FAF2FBF5168495865F11A1AB3163CFF0093C86CF0B119B2AF0BE9FD463CB788C335817173A6FF00CFD7EBA9C24CAD1C8B50FA7F10A7F8BB96F1CF520FE67F7EFC345A5DCB3034F2B5A82BECC6BFA69C2C83E00FE217319C2C412AF7C9F4E5E5CA7A473C362826E0EFAF4B535F1F078C9C2AEFFF00ED3CBCB43E476877A7CE5C9BAAC77BDFDD049B4F2B7ADB1B499449F9833EFA5F57D79C379D87527FB5DF6A03B59FEBA59E251439D2ADE3B48983C85AF33D798FBB0E4C8960114A5AB42EDD29F73630C66495281052433871D7AD76FB44958CED61248724881F6A08F74EFD7732047945E2F0C1493C29A54E9E3CFF008D618CD9132AE9248A06FA790D6B6A9AC4D34E6A073BF44B877B99116E9CA47979EFCE9998606612AE14B8360C49D795296E8F11CA9337662FB0FF00034E76A563B63D98EAE0CD7B54CB5857D64A123C52045BC5D2C7A8EB7C735ED464EB99865CC54B628428B9005FC2AD66FA35232795C99E8F9480541B4F57D999E96E663B0DDB9E9A4EB5F67FED074C5434568FE18D5435C49903810BA8F09DFF00A44C1B9F5C79C50A548CEE4F092026629C02CEC59E9F6DF68EE7D859A4F03BDD2D6A5B7A59B63A74F8FECF1B6E92B2AB2F4A4257499857B4A064484D4B891D62C2D6BDBD4FB1BB15989465C80B53012C30259E95E6DCFC6D1DE904AC7117AA535028C05E9E3F9864539E7246DF1EB1E5CF0F67CC99889C7841238B9B33F900DB42A94D416A7E1E3969DBA813111D7F7E677E589944B972E5A12B676ABFBE6478187A9040480CFAF37FBE9D2371713BF14FC6F6F3F2C39425240E1200D83726D7A46EA42920929206BEF58C1EAB4D35338F012B4A9BE131600A84DE236EBD461963D69952D550686A1AB606F570ED6E51893C33961093BFA036F7D23EEB90C0E9E222361023FDBDD8F9E53E52438291434F478F99099412E05069ABFAD2FF00C0A4284B29FEA48F7807ADBCA30C912439A3541D3C4BDC68E7CA3612D9FE6356A36CDF8F7AB830F25BB13007B848F3BF97BEC39E25654A25258508A5DD9EBE1CFD8D0E1D157653DCB6E051A91B1598B6CA499049E9E198DAFE9D77B5FA6C704A9C40A80EEF5BD49F0D3F986D3B0729D252800005C52BE766F76863ACD46D37BAC022CABF4DAF20CF2DB79C3B93922D740E75A7A786BD7A88D512C22890C34034AE9A9E9EC45ABF59B54E2CA0419B1503100DF63F77E789AC276754BB8552CE2D466F7AC3C94859B17D19B5A52B51E9CA2039A6BE80A01404743EBB7E6019BF2C5830BD962B22A5AAC081F6D7973BC39124283901BC86EC6C3F07AC40B32D78E389480E9313693FB8F58817C4EE1BB2490589D469CC9F1A7BA0791C1E193A21B7D34715A7DD8B96315F66DAE570A3C6AFFA8DA37DE48823F41CAC983EC8CB05249AB0D00DAEF4D7979C48270E4B101B4DEFE3AF28AEF36ED01C6403C6A13360A304027A411E738B7607B2B289B03C2DA313ED8FE09683F4F5B5CD00FA50FDA95A33C57D99768CE92A951833BA89DC1DEF37F3F741C5AF0BD974060C2806839834D5ABE02D19FD393702DB0D34707C07E2209996BF7564788C09B137E80EDCAFB6E6313F87ECECB940B84D59E8DBD0DEC5ABD76687125A43850BEE1FD3CAA4FDE2215BAF1EE4AEBBA8F4F5B49DFD791C49C9C964B03AD68431246F7A07BFD21E09C820820176D486D6ACE2B7BC43F30D542BF87896416E600279FBF9F4DBA4624E564D2D92C052E4B5791F1B56C3785D130711A38A11A38A6BEFD2B17AACE512789C37064F118206DFEDC879E24E564928814018D28FA07A73D6DE10E51310481C2C7CF73B1F3FE222F9866C1C4A421C208E52473BF3DE2779F4DF161CBB05270E829094EF6150FE22C346FC6B36499EB484D00B902F50DB1BEBE2F0C2FE647FE6CEDCFDDD6D73CFEEDA5D12E4B5427A33B7B1E1607487D85C190A0E9E56BEFEEEFE24A2566409252E12044413F70EBE9CA63094D9485060863FF2A02C1DB6E94360444F49C1800028046C5A8DCDB7A8B38A184CE660019E33111F68CFDFBF958FA02488E99809ABAA490C6A03DEDB6C5F5D6BBEF3A42024FCB5FF003AF2DFC7486D7F304DA1CE479F49E9FEF6E587B80C2CC90E26329CEAFBFF0022FE15B6F8292921C867715EA77AE9BFDE1B575C913E3B936379FBFA7C312BDDCBD852FF00CC487E9D1B0F2FE634FD787FCC3F13FF007633C12CD78475FE633DC27D83F984CE55CC8EF0DA48B9BFFEE1F2B7974C704BD93B697FCC63F4E8D8797F309555A0117F9917BD8DFCB0D67A521D9205054372F1B75BEC214972057852FD037D2B1A1CAE17857A7895CFEEF4C3585FF4B47E1A1D77BDFE6EB094D7264CAEFCFC4BC107E99A8CDCBDAA38FAF23FBFFF0072F1B71AB7F41F88C1C283700F5FFF00EA37355C91C442F988B9BC0EA48B0E64CEDCF094D2FC3B87F173EF4AD6B0F30F85490C523C869E6F4DE87CE395E62019E23FF58B7BFF000184A1D7E8D3B0F249FAFF008848BAE0621479F318236FD2816007BFFD5187D70FF71FFA8608CFE9B97BFF00CA33456024CA80FF00D4411849603D2F57F48C190137D793FDCC67F5B1FF00311F2C690774397FE23F307D707FCC46083BA4F2FF00C4473F5DFF00F553F1FD7041DD0E5FF88FCC29A7AE09E225C076D898F7C1C27334F18061D2AAB024720295F0BFF887046629DF8933B1BABEE9FBF09D3DEDAC67F4C9FF0088B6C9A7F3CC79C2D6B304413C493B4C927E026E45F6F8E352949B814BFF003FCC63F4A9FF008BF4F7F585A9AF4C8F1EF72388FE7FBE538C7026FBB6BEEFFE231FA245F847D835986C75BBF285CCE60949FB569E4ABDA76B8993EB68C359E0241005DABF51B7BDDA23F17252904049200AEA6FF6F7762FD4D99A2C02F94183FAF59F7FB8E1A4462F0E922CEF534F1EA6FD6DBD5F18CD5278471C7FF5449B4F3F9DA2E3D304021BD7686D330E0B70D80A8A1DF707CB9C4CF29CD5B8038C8E5B91173E73720F5C2664CB533A438D587E3E90D558740BA4575DFDEACCF174681D52AA1CD58097152A75B54955E10A06C6E248FBF9099ACF68B29973F053D6123E596B7617749FA3B57D68D5CCD70E04D96426AEEE1A80355AA2BE7C8DE3D7BCAEBDAD5BD87E78F00852AAF24AA055024F734CE8B98F2B836BDF1E16CD248C276AE4B025299EB013A1E25746714BD599A3A576397C0123F69F958B1D3C2FBF9EB4F8CFED532F465FAEF523688FFF0036AE040B01154EF2B44DAD138F4D64B30C9C2618874F1212487E40E8D4D5CD01DC18EFD964E3330F2C7EE00539B8721F7A1D686DA45798E83964C9665924076BD34A1BD47D5A2591281E9BECD6DB4BB6AC6353AA03867CFF000BFA61863713F3B0535695E6E050F869D61DA249E20402C2EE59C737D4F946BE31FDC46FD7F77C2B2316521B89F4676E4ECE3E97F087989522649EED0C54DBD453AF4673D19A1592D5552BB4AE186D650A52F6E1E054C5C03E2888F7DE711F99E238A54C7535CB3FE4F98E9CE2264489D267A2784964F13ED5BE8D4BBB7231F79E8692483607CFA4F33D3A7E78F0CCE0A2753F8D1879FB78F9A610E03D0D5F57DB5D2372DB40493C42C0F3F96E709A10789238581D5B6B7B3F78381B9F2B79D7488ED6D4A5A053C6011100902237E63F600C4D61E4BF0B8B81A5FC2DADBAF283839BBEBB7AD5ED10FCD3352DA13C2B07ED490409BF3BC413187C65AA531425478B46D34F3F37F209AE5DABBD5AD6E715467FA8D6DF170B8044ECA1CE3A1DA62C7AF95A7300A98E01944BB35DBD0780A8F18C26497B39A69E3D4DEDE622A9CDB58AD9FB6B242A62E6DC26F6E9B7BFC8E2FD96E144DE10A9646EA20FD00A5A9FE21DCB96524937D2C7D2B5EB4E45A2BBCDB5B92170B55CC889B83D36E5E5B46DCAEF80C9E5A824DA81DC74A0F1FF0030EC218543BDCE835EB53EE910E7F5B59414B226D04EFBCFC62F137C4D0C914E381015CECCC76A3DDEF7D054449E0D245746D859B969A575F288566DAD93713E97B7BED7F48E773890C364D3D0CE87E82BA519BCC5A8D41121107ABD522AAE49841E6779DA2667CBF238B0E172F9E900041F6E3F3AFD60F7D07B6888661A8132A957B819F5E401F77E589FC3E167243841A5A8CE5E9706E7D7AD4888D4E7685127909DCFDF079FC2313586C0CC9C3E6490ED52DF4BD7931AC67F4C673102A7F8E63C3F9788B57E70832479F1413F7C4DF78F98C4ACAC9144BF16C76B3685BC7A54C2C8CB961EE096621CED56356BD6DADE22F559B990524A4C192491F1DFCF68E9E92B2325208F999E868FCADCE9CF5687A9CBE651817D6FE0DE218FD1AF1FA8CE1641959581EA2F71CBD3E3CF0FE5E4CAE22126946FAFAECDD6B48772F004DD241E86B7DFECC7AEACCEE6AB51FB479D898B5FAF9C6FD23AE1C8C9E63808AEEC6A0BEB5FE3986896C260121412450B5C1B53FCFA8BC36BF992C09E226677F48E7CBF0BCEE4AA9CA2626A2B6DCEED4A9E9FE1A7A4E050006482C5C161AE97D35AF84256B3155F8D5BCC4F9CC70F5E5B5BA61C270252C5436FF17E56BEB1209C2B248E17DC8D2874171E2E7C2BC3B5CE411260FAF59DCF2FDC61CA30E84B3801AF41CAB47DBCFCE23E7E1493661BFB1B37896A351B2A6BD5E0B9B024816B1F78F2DA2FE77C36C5A65A47CA41248DBC79DB6FB554C0E1EAA090E297E67DB9D078C36AEBCDF7F2137F84DFDF862E6EE5F778933873FF0017BD5EDEDF9F8C70D57295C526C47F70DFD27F7EB8C3EAFCDFEF07707FE3EA7EFE5BEDBC60BAD11BF3B78B7F9CFEEF8CB9DCED7F483F4EAA7CBFFBAD6BD7E9CE13AAB48820F90B8F91F3F3239EFC9A4F533EAFA93AD3EFF8E8ACAC39049663E07D5FDD7C343958B04EE6666E39FE1FB3869C67610BF72ADFE9F9F7B084A6B960917F88FDCE0E33B080C957D36DBA8F7BDE31FAFA86E63DE3F3C1C6761EBF983B857B03F31926BD5E220DCDA26479EDE42D84D6B347ADFED6F661C4A94A4D086E647531A5CAF72E01168237F9FCFA634EF03B51EB47AEADF673D690B776378D62B9CBC903A6FF00AE0EF361EBF7F380CB1A13E35FC4726B564CF11F404C7BED8CF782BF2F42F6F483BBE7E919A6B14641519F7FE53F2C36985CDB73E7FE20EEF73F6FCC67F5A3FDC7E7FF006E138CF00DCFA7E20FAD1FEE3F3FFB7041C0373E9F883EB47FB8FCFF00EDC10700DCFA7E2334D6A93B1E7CC9F2E91F3B61399A78FBF7F783806E615A2B960DD56F53F7613804B7DCF41A7BD7D216315EABF885BCFAC7EF6C101975D41E63CF6D87942E6F31541F189D8127D39F5F33D7041DDDAF6F3E6397B78503317131E3F2DF9CD8F3BEC3973B9C359C6B4B1FB010D71320936B8EBCB507D1FC21DE8F335DBC44C45CC4CFC7A7C4F5B611861330EE9735D29D46DE0F73E7477FE28B0A49E3DBFD44EF1BC47CB6E7821A2F0B47776D36F51F7EBBCB329CD96384F1DBD76F9C8FC799C10D26615DDEC76BD1B57AFAED13FC9B54FF000DAC61D51528CDB8495472BC0B5CC826DD31AE324A6665B8B2A0ED2D4C06A58BFA3442E3B08A98A49093F2B9A3F96AE6EDBB7378F6CBD997355EA5F67BCFDE52A4D3E5758949245FBD4BE9304FDADF604FC71F3FFB649123B5982401FF005712B04805CF0A9EB4A6CDAD6D13591CDFD3A892A090180A736B6ADADCD5F78F93FF00685CA9CC9BB50D594EEA5499CCEA1490A052654FB8A98224CCFA73C77EC19E0C34804D3BA43518B848A7979DE958EFBD9C9C3138292C6CE14D5B9A3EDD628C2A80241133F2FDFBBA62D597E294994B00B16D4E95F5B5766DA2EF2E41090598F5D2FAB5FA5234B8B24A523ED5EC0C9B6FE1FD397C22A7628AE6AAAF5B57EB7B33B36BD61D4A944CA98487B51EDA6FAB4042CA0AC24C0DC81205E37023E3E784BF5CA42CD4802CC5DFC896D0B188C9638B1291A150B8B870198E97F1AC29CBE9DCCC5F6B2C485F1573CD348E0495ACACAC25094A520A89248989F3BE2371D987121614A77259CDB9FB6EAD169CD25CAC165CA9C0252B12CA9E95A55C9B3E9BF847DE977E9FD93F963CA8403711F2A7BBE7E9FCC24AA7C04D8C588DFEEDAFEA396E30BC997C4A7091422A7617F0A0D2FCE0EEC6F6B53F98AE73EA829E205467909D81F7DFAC98EB8B460240212785FA8B1D797234783BBE7E9FCC55B9BE6EAA44A932541C993C46D137079FC276B0DF16DC1E5B2E7FEE48A33D2FC853CDE977730A224F103A9341A6DD5BEBD04529A9B3509529C0FA9B324D8157EC7C3DC716ECBB219331490994058D5ADBD773E3CE90A8C314967EBC9BF3C9C7845379BEA072B141B455F129B24429B080667990072DF68E5D6F381C9B0F2582C25205CB8A7875F6EF0E932428DFDE9EFD451EBECD735CE5BE25165B0D5E1C0F34605EFC324C8FBBCAD8B5E12565C3E4EF0120541A35A84BDFD97870891A31A54923DEDA163B1A4429DCF5A794B4D4D690B444212D1B13BDD3BDCDB96F7DB0F26E6395E5F45CC9638AE4A817B73F7A521C0989902CFA0B7A38F74A52196AEA9E767EAD4F5954397754B50A99E9C2855FD2DEBB9CA3B5393CB0077F2ACF5501F53CA9A5B68C7EAC3BB73AD9F62D7D6C075786FA6D3DACF3F5AD19469CCCDDEE48EF09A5A96878BECC153402BA7C49EA17476E32094DC588C397D0CD40A8AEFCFEB4615C8C524B92083E9A569E74AFD62454FD8576D19B81F52D2554B04FF5B896E3D78C00236E5D779C253FE28F66B07FF56749177E15856BA70B92E2951E942ACB9A8501C4BD580614F7BD7D2AE87D927DA2F30095536892A09992AAFA54403B1852A779E56E7883C5FC77ECA61292E78249A32555AF20D6D5F95ED37815A12ECA490C18961A787516AB52EC81FF00637F692BCE8804117FFE25487E1E212379DB9ED84E57F507D98A033A9A517BBD68DE0C74E71312D72DCFED1677228C3E9E5118CD7D8FBDA329921751A114A4C1852330A7544033210553EF1F9626709FD40F67669E193312F40428A83FFE4297F57DA1E266C9B28A5EC198B1E4DE75FCC5539FF61BDAB69C4ABF8B68FAF63BB9E20DA16FC0E63F96850BF53BFDF6397F1B72650752E53901BFDE4F8EBFE3EAAA67C80400C40BB306DADA9315366990E774CB08AECA735A22991DEAF2EACE111BCCB2058F3DAD0716FECF7C51C97342522749413A77A9513CD9F7F4BD2CF244E0A53A025401F992E900DB52DC81AB1E42B11475550CB8505A1992447DB50A45373B82954131E9BF962D67B5997B3C89F2C837F9817D857573A69E313B875C9984F11EE82438480540F881EA28FE70D9993CC3686DC7AA0B0E89EEE9D282B0DFF702B13C53E77C2A7B41859A974AD249D5EFA52A29B5EC3C64A423BD05405750FA581BED5E9CE1BE9B397140A1CA9E200785250124F2898916EBB79E3538FEF090920BB1047A519E96FF00308CEC27CC4F0B39734A1E5B8A0A5DC51AAD182AAD6A2A2A6CB69DD04DF8BA9DAD7E57B72C379B356A2789C27A9248F3E7BBBC2B86C1A407721EE386CDCEEDB75BC2672A81BF17A99FC62DFAE10E24EFF587BFA54D9CBF43F47FBFF089DA9008E131D60FCEC09F960E34EFE8631FA54B7EE3D58FE6FEDA357D689DC93FBFFD3838D3BFA1FC41FA54FF00CBD0FF00FC51A9CAAB893BF5E71EEE56E5CF7C369EA1422ADE1AFB3E3A43997870E0B3F890CDBB937F6743AFEB3E7FBFFA70DBBCE5EBFC438EE07FC07A7E639EFC281926DCA3F41EFF008E0132A1D34D6BFC41DC03640F06FE613ADE4C89F76E07EA7DDF760332EC3A560EE07FC01F2E576A7BE75E5AA8826F3B474F41B981E9EFC379AAB134049F7EF58048E7C23A3D7C08FCC6FF00AD790F9E11E34EFE8633DC7FDFFF00B7FF00AA13545403C3CBD27FDFE5EFC1C69DFD0FE20EE3FEEF4FE6137D60753F13F960E34EFE87F10771FF007FFEDFFEA8DEC5481C5700F9C9B7BFF2F7E3459059B478C89203B906DFDBD79FDFF951F5AFF5A7E18D236EE872FF00C47E60FAD7FAD3F0C10774397FE23F307D6BFD69F86083BA1CBFF11F98D6BAA16950E7E5D3C8E119AAE16A3F8FBF6F183252756E80463F5BFF005FCFF4C23DE72F5FE231DC0FF91F211B1BABB9F1FADFF7E7CBDF83BCE5EBFC463B815F98DA94D6B7E56F58588AB103C5BC45FAFBC6FEA70779CBD7F88CF703FE45BDF9FA78C2E66AC492553EF9E9222D3EE048DF1A124DC93D6119B87245F8B9B337A9A7BD6AEB4F5A9170AB7979ED79313E7BFC318866B9203862DBFE43D3F8A43B335C991E2045AC4DFF003BCF58B804D8E0840CA150534BBE9EC6DE90FB4B9824404A88E978F3B79C580BFBB04365C8493C4CFBF3D37D4ED5F1AC4BB2ACF9346164C2839C299578A0191FD524738F90D8E179CA6CAF16583896B63B0E13A589AFE758426E042E5CC5D9858815EA6E0B79F808F71FD95EBCD0FB2ED5D6344949695DDC13FCC0E54282E4CC90248BCF4137C7843B48944EED9E012520A7BF9E56C43020B8DD81E4DE8229B3E7FE96690E032806D5BDB9E54A068F05FDBDF432A935AA356D3B60379C3CF297C090005320054C08B99DF73D648C7674C9270F87521354A45BA002F4B6BD3731DABE1D6681695CA597E3E16F326C7D1AA7D63A00E38971BA5B01F6828C7398FDF9DAFB626F0292A96AD29577EBEDCF5BC777932C2A47117AD46D5B57434ABD2FA3425A86DBA37DEAB026A14128A74DC821638551B83123E1CAD88F97294664D5317AF9543B7315A9778D258E14AC3BBD816771E7FF00768DD636D3A2B1861CCB1100D47F31E5282645BBC4DD5B589DA76B622F160C849AD43D0EA1F6205A86F5AF846CC42D13BBF2966502036C58BD346B335F778EF6FB03F600AED63B51A2D479CD314E97D1AE1AACC1F7507B8716A6CB8CFDAB28871B1B489B5C462A198E35499530A13DE2E89097624AFE5706F477A7E04557B71DAD4E1300AC31980152140A5C38614F3A07B1E51F58E1D3CB88FCFF001B63877007E5B7F37F778F9F9C01DF4DBF9BC25AB74847F548D8111F8DFEFF00961E48284B0A51B56BF96BBDDB918024026DC872F1BC5719F3AA2493369DCC1E87E3F23CA3169C04C92809798916B9D35F75FAC67853B7D62A5CF90A7DB5109714B483C21B6DC5933BC84824440DF165C366F83C1DE6254ECE1C353A6BD357DA364B4B2F50D7677D47DE2A6774EEAFCEEAFEAF96E455350951294A9C4A9A499302EB40817BEC79198387A7B6F83921A528248A30587A72A0AD7F9A43849E201D56E5E76B747BD8561E97ECAFDA4EA84B0E2E81BCA1944971D152C2D442AFC45016140813637B7B8C0E2BE2B4A94B3242D7C7503E55106B4AD4791EB487680901DC30B546BAB5CF2FF1132C8BD89F2547039A9B582D6E0238E9452BAA13CD2548570F94ED88BC5FC58CC65ADB0F8733127FBBBCE137D99EA74A1B5377085201254B02C01DFDEE6A7A98B4F2FF0065CEC474EA52ACCF4FFF00885C708EE5DFAC5453776A4EE4A41F1151E4623A9338ADE69DB3CEF3CE032E7AF03DDFEE1FBCCC7A5EC1B938BEB0C71B3004FC81FA503EDD39D3517BD8F92E82ECEB4F84FF0002D0F4AC70C7097541FDAE27BE428CEC7CEF88539AE70B491373198A7B8019E8D707D6FAC46778ABF057FF005505B4D1EC6BCEB411384559612114F95E5B95A2200465F48E97472921A0470F29BE21E6CC2B5154C9D3D4A15713A6001479057E5B771194CF9B60199EE7C4E8E437D2F48C175599387F969A65CC7D8A561991063ECB698FC3EE406214876338D35993162E373B7AECC20FD44FA1A5A96BB9E6F6F510980CD883DF2C5288F070A52AE3EB3C3B797320E14E29F8A002261436F523CEFB1B6F511A2B1D8894411C4C0E85B8ADB786AD4246D081F4D692AFF3EBB5FF00E198DBDDD6DCAE07A6F2F05892586206946035BD6D4DEF7B46C337C4B8002B954FD7D98E292AAAE9839C59824154471D325CE28F250300758BF2387A301895103BF2E3FE25AECF40CFA43C4E6F8A21DD7B357EFF0088455B995528101343524FFCCCBA9940DB9F1B4A3E9B1DEDB4C94BCAE69487C4CC06C7FDC56CDFF2F4737D459CA33AC5ECAA5CEA7616D2E77A3C42739A2CAB3E6CD1EA1D2F95E6748E712168451D1D31095483E36D90AB8B4CCFE2A4BCD330ECE2BBCC06227267AAD302D6BB16259448FB75D657079BE216405F130AB59EEDA8F0E7AC755FB47F61EF67CD76CBF579436746E78F0528290AAAA94F78648F0CA5BDCCEDCC88C5D725F897DA494A40C499B8E24D57C7DD700DDAC76E9EB76CAF3C521011DE84248658500A2DC8A99A9B75D23CF8ED5BE8FAED3B47D2AF36D26FA759654C079C77BB0C5338C34992986CA94EB9C491C8488913271DD3B2FF0014F033A748C2E3712A953E610132D615C20815759F97CCD7D0DD3058CC3CC40216971552C2C3AB88B8F968CDD181F38E8266B95D4E4F5CF65D9EE4F539457D3A96829A86DD6C1520AB8A0AD0849888B4CF58C7A4322CFF002AC44B96A5E3651700BF12542A0355D9F4DF7E73F28C9989052A0A49146A934AEE450727BC449DCDDFA975CA7247774D01B200D9513717DADF28C5AE74DC2E2403849A89CC3FB0BFD09ADF50FA6912299094212B02AA7A359BDFA084AE54AC78BC50373B7DE07E186852A4D155E6CD7AFBB429DDA9BF6D3C1BA6DCE113952A26C6C6F63EEE9EBFA6D848CD40B9EBEFDDE8F1A8049600B8A5ACFCFEBEB1A8D4AC0B98F327CFE1B5B18FD44A667AEEFF0068C9045FEA2353952AB024F316BF5F2F220F48F8B798B4ACBA4BFBD6A76DBF10B4A415548A6845FC287C7D79E935046F23D47FF6E112A22E9F5FE21C77279F98852C544855FE71F801F29F3C63BCE5EBFC41DC9E6DD45FAC62B7FA104EC2E3D4DA3D718EF92ED4715BFF001E9783B93EDBCA349A829224C1BC7C0F41FBF38C27326254086AE977BF4F7E31A2E480D4726FCB6AD1F583EB47FB8FCFFEDC2109F75FF6FAFF00307D649E7F13F98C10775FF6FAFF00307D60F51F11F96083BAFF00B7D7F984EFD491C3E2DFA1E9E83CF09CCD3C7ED1BA255E8478FE49F7D213FD68FF0071F9FF00DB84E14EE4F3F3107D68FF0071F9FF00DB820EE4F3F3107D68FF0071F9FF00DB820EE4F3F311B1156AB8E23F13F97EFE184E669E3F68D552942C09F23F4F7F6D9F5A57F71F9FFDB84E35EED7FF00131B9AA95C9FB5620DE7F21F0B7E4463815B7A8FCC2D455192788C7333B7CBF3C60902E5A0E056DEA3F31B455994C2ADD419DBADC45FF6318E34EFF5D6353254AD3AEAFA6F0B98AC54C71729E53EB1791F1913D2300524D8DFAC21370C412149F16EA199FAFD61C45728100199BEF7046FB0BF2F775B8C6D0C662129714BD7EC6F4A0FB43C51D63C2150AE198920DFF2837F7C8C10D7BBE3A243D68D424DB7A373D2241475CA75496388953EF30D260C905C702009E57311CE6DD433CCF172F0D96E2FBC584032D4CFA963E3AF4874890D2660586F94B02CF6EA3C74173B8FA1BEC932E1D9FF00B2B68FA5ABF0AEB692B56FA17214A2B778DA2524711FB408B1E51D71E199934E33B638F2E5430D3D3DD96268B25EA37B9DA38EF690044F4F0D52565C8B33EDCBCB7D0C7955ED5B912354691AE79C6F8DCCA3BF5B64265403EB2AB089DAD69F3C77CC34A98AC249F94FED0496A014F07D3CE3A3FC3AC54B44D9616B01D40124B061A07F7E11E28672E2A8A502789B75C1C306603846D048B7DD79DB137815CA08582B014CC4539D6F4D6F1EB0C1CD953B088E050AA400072035D35362D76DF3154DD453A2A160ADC6C0EE85E49912600331CFE06D8D1084A4AD4A2CEECADE9A7B6BD223CC89E678E142B81EEC5BC09D0EE2D7A54C4A74DE9FCEBB44D4791696D3ECBAEE699C54B6C90D24A9494A5C6C2AC0181C04CDFACE2A39E4E9638D226A52A6E27BB302F63B0B18DF3AC5E0F2EC0CCC4CDE1265CB2E95109F988212C4EC40FBD63E95FB2CECA72EEC1FB12CAF4165E86D8D5B995353BFA8AB1290871402D152DA54B1D1B5A9278546DBE2858291331F8F5620712B0F294D862D4512196E1AAC46A3CDA3C21F113B633715984F9689A5654B502534012F40002CC07896E91EA7B1926655447D58771C5B712527DFE2B981E43A1C70B9B89080E54C0D5C124FDDBCDB511C942944D0FD21D11A1B377071E6199B6C22070028412AEA0106C3DF73CAF88F566409694A5129FDD460281B91A335E90ED091424373BDF56D3C39F8F1FE09D3E811982D35A6E1512824F9413CB78FBB1AAF31C451A628307BDBA907C74BDE1596CE695F31BFE3E9B46EA5A0D0D917789A4C992AAAA93E15282DE128F25A4A52098B1B61AAB1D8CE204E295C25F8925DF956FA5FEF189AA008A577F0FE7AE919C67750E7F96A7A5A7A256C94D353A5413CBC41015EB27D26D8D44CF9F88F1926E4AD46ADA827E83F108F78BD090341B46EA8CBA128287DC2F19EFC254A0279020103D23DFC861F2677197500E2E4A413AB69F8680AE6A59C902BA8A37BFF0031C3542120711BDF71C511D49EBE67607AE1C8095A5C067A6BF4A46C0CD21C1247D2BAF46F5F2DCE5234EA47110422E2448E879DCDF6F28C289509746A35F66DFAF4A985E5A4AFF73923AB0DCF5F2BF38D7DCD3B444AD23681C201B7BC79636078DF8535DDCF5B102E3F30B7729DFD0FE61BAB6B29982D8E2499E21C8CFBC9FDFA61497825CD04A659D0D8F4ABECFBD3D20EE0173D1FEDA8FA4361CF295A925C47C0088F779FEC6153944C51A20DAC4747D2A280F5D20EE13EC1FCC6A7354D12225D47389208816B79FCF7E787523249E6BC0455E9B1DF6BFAD2B19EE65B5520EE5839F12E69A43255EAAA3330E3441F31F76DBC91B1F75C3F464588B842A94142399FB5CD39DA329932925F801F7EBEF48627756D1200971B93E693F8FE7E98728C93141B841D34660342F63EB7687689128BBA035281BF07C36844E6B1A1360E376EA40F59BFCBE6360F5392629A81637FF3F8A561D2654AB042481AF969D7900DCDE1239AAE85F04075B91E622FCE06C07E56E78752F239A0033251535DD2F72EF5E40BB3EBA34394CA40FED62350DB03E9CE8F57D9BDCA8A3AC061D4926F2089EBB83BFE3E58D66E5E24A4B4A0826B415A78529E7F58DC4AA6CA3F228A46843D3E82EDF9A533A677F8705BCCACA9C5005BA85ABBD698FEE0A6164A17C62D04731EF64B95396381C841FDCC9295F50B4B283105D8B6E43346F81CC7132D6089AA0C402EA2CC6FC8EEFE5A452BDAEFB3B7657ED079255B59D50D2E5BAA10D2FB8D40C301905D20904B0C25B42BEC84893326712B83CEB39CA1094E13113A6E178A924CC53CAADCA892A2EE0D7A6B1D4722CE56952146610B0DF31A82FA312D6D8163E9E0676FBECDFADFB00D4028EBE8AAB34C973175FF00E139BA1A3DD38D3249517036161B02401DE284F58DFD2BF0AFB726485271B89EF0A827E55A98A696625F5367B3C757CAF128CC51C4C94A92050597CF61E7D2ACDD7B66A2AABCA9879BEE129DDE490E4C4CCA40B481CEF3E631DFF0D9D61F30ACA5A40536AE6BD0D2BA6FD626BF4D2D29725A96B5ABF7F0AC37BEF369754C21125AB17B889EF49F2330009DADCAFC9FAF2B5CE485256EE2E3CF4EBAD3D61AAC4B42411FBAAF4A80F4B0AE82BF68C50A49DC7BB9FE136C4062B053B0EA3F329B986A7893F5864A4AAE09B583EEDEEFB721995A524F4311BCC01EF3BFDDF0CE04A8F1025DEEE76B6AD0E308EE41767FB8E9BDFF00883BE4F4FBFF002C3F2A01DC57FE3EDFEB121C09DBD4FE611D53B3C3C260DF6E9EFF003C319AB1500DB5A8D6AC6CDF88D880407167ABDFF10938D7FDC711EB98A7724977D4C60002C238E359DD44FC30AC82E76D59F67FE1E02906E1DAD071ABAFC87E587718E04EDEA7F3071AC6CA23E1820E04EDEA7F31CF78BFEE381AFF009F67CA0E04EDEA7F31C15ACEEA27D630D67000800333FDA3200161071ABAFC87E5846331B5B59BCDF6F238208DBDE797CFF4C10462A722397CE7E58D9258B9DBCF940C0DC3C63DEFFABE5FA6304B926D030B353683BDFF0057CBF4C20A5BD4D00F1FB46A5293A0FA7D20EF88D9447BBF4C325CD2C43D352C0F9341C09DBD4FE63626A426788CED1D6F31F71C21316695AB12696FB69A43BC3CA4283148DF9DCEB5E5D2B0AD15224907736BF436FBCDAFEB87324D5B6A75773E1EB08E250928500966B53EADB8E5D6E61522AA1485893C324DEDE5BFEEFE7187C491C2A0683CEBE86D6D0FA56E6C924AC17F9EB41E76BF36E557893D16A3294861D4A7822012120C5B9C1F2F4893CCE365E21294BB81F73C9C535D7C637C160F816EA0E97EADB6EE5C9F08B7BB19D22EF693DA4699D1D94053EFE6D9830FB81092A296E89D4542ED36F020F911CA71C5FE26F68060E5772998C262174E261C4052C59DECDE05E1BF69669C2483325A820A12C43548550F5A1AD3D5A3E84BB5B798A3CA72ED22CAD29A7C972BA569B0D98417051B45C848313C6920C0277C710EC5E07F5B3BFD426CB3DECF984CC2760A3C26DB0D686387E6D88EF2628514C5C171527AD407D457768F33BB46AAFAF52565129292AAB45434A4AA088485A504883262FF00AEDE9AC2E0D2AC0042501FBBA0A5DB571FC987FD9CC44E953A584ACA7E6B0E55A79D3C23C43ED37275E9BD63995238DC043EB294910077C4A840023FA8444EE4E39DE33098AC2E294A05411C44EAD7AD4B69F6A8B9F5F763B18676070CA5AF89540A725CD69D1B9B03B5A21AC9719535434A98AA52BF94BE1E3E10B32B49491078C2B844891BE169F998EE38388021245C39A6ADB3C74CC666585C160D454949570FEEA51C07A6AC0D7C1E3DB0FA3E3D9D329D17962BB79D754210F6608074750D4A095B0B48553D639C047178D452B1C690003E13071CB71EBC4E331F351256B51E2F9C970250351C94E1C3E9E71E4BF8BBDAD5CEC28C0E0A6148477826CD0AFF00ADC45D3F2BD022C1AE7531DE6D53AA2A6ADCA87AB1E0A6D4496140A6C89809B2A6C205EDF0117CECDE5AA011C49A06AB0A93ADAFD1C8E4F4F21284DC46314B9CA2B254EE5CD8FF0000B374D23D7253B5B5622980667688113F033EFF004C78E0CC67A927635FA822357ABF8C6AFE159A2FC558E29E1B23C6501039EC6FB5FF0063092945449DEA6DD2A5B9FAC3D41241E5AF2FE291B0656849016B29B192495F43D49C6841208767F7F785E5EBE1F785CC51A5B0A534845544151584A7BBF4E2DE77F59F5C22A965C104BEED41A59DABE118980167D5FED1CBD5F4AC8E17561A3B140492262F71D4F4E9B5C61CCA96B5800034F0A3EF6FC7842600028290DCBCC2848269CC9FEB93F0249DF9EDE677B893938659AA83026BCFA7DCFA40C0B3D48861ADCE12D9512B4003A293CBDFFAF2F5949382510004923EBE3A8AD1BC8C6CE588DEFE1115ACD56180425693C57FB43DFB19FBFADED898C2E5466B7125C8616B1BF8B75A38EB0E30E81A1BEF7BD6BAFBB3D6119AEBD534490B1239F17EA7FDEFD266B0D919268871FF00A7DF8EE75D9DF77CFD22019A7680E3BC27BD1E12A89501327E1E9CFEEC59F05D9B26AA96C0B386FB36D5FB6B0777CFD3F9881667DA2BEDF143FC37BC2A46D6B4FE9F218B1C8ECA099FB500D350DE1F814D2918E02FF7F7E1E7AB188357F69D52D903EB0428CCF8F7DFCE0CFE42062C380EC8238085201234E1B3DF9D7C0F331A9412086E5BF37A4466A3B53A8850EFCDC9895DC472DF7E973E589A95D9094A1FF4D9887A1623621ADA9B96A6B00429ACFAE9E2FEA4F588C661DAB55254909A832267C7681B400679C7EE43F4762D0A149628CEC923D5EBC853A42F2E5A941EAE7705E9AF4AF28655F6AF58524FD60DF9779B7AC91B9FDC9C3C47629240694073236E82BE5E5587694AC0DD46F6A372B7E00E708DCED76B1929E1A851E23FDD3B795EE4ED3CBDE70DB17D8D290C9941F9279DED51A96F4891C3C92B49D4B5697F77E4C5A1DA8BB6FAA640FE793B48E21C88DE7D7A479E20315D8A98A04F766D6E1B79529ADE94AD1996330A482403CC5CBEA473A5BAF3690B1ED06E32A4D3BAAEFDA7C8E2638A3BCE1823C60786373793B75C404EEC54D49E2EE94E2D43AF8066A306671A38786EE95296183925CEC5B5E6D5B7DE2CFD3DDB9E48E1698CCC269E956414D3059924EF2EA6151241B9B6D30311388EC8E2405AA5A4A2616E13C20B35689B568FD68627B058A992AAEE28E2BA1A31A1A369FE2E8CC72DD01DB3E93CC34BE7B47415B97D753F754B5AE1696FE50A5A49E26E65E59716A04C111104918A8636466BD9EC6C9C54954C4CC493DFC90E0625BF6D6825F00BB5DA3A9F65FB408929E098A6B1049763CF42093E25F9478ABDBDFD1F3DAAF65598667A83B3EA7735468AA95B8FA9D692842D968952C2528254F2A0950B09B6DB01D3BB1DF14254B9C893899865E210405495929035B9A59CF3A8A878BE8ED1616700998A09243F7AF5E4C91D408F36F3ACAB30C9730A8A7CC69AA696A92B297296A69DD616DA84820075292A122E403D27618F4A647F127013D2841C44B51200AA83027406AE39D6AD416890C2CF4E264A149140FF00EE38255D520BA4528F7E7A321AA29540B106F0608E7F1DBDC0F3838BBA332C2E6684F76B492B0E450DE86A37A781B8A3484AC22A790D507602E06CCC3CF581152553C46E37BCC721FBEA00368C4762E58C190A019CD2ACE3F8A7A9BC3A565EB9041524A5EDB10DD5AF5F0EADB03E39284F90B88E7FBF74618FEA945E8E0EC7CEAD5F6EF0770B735D9830A7AEB1A5D72786F3BDB6FC3F5C36993BFE5A5A967B79D2DCA306490E49B72FE79C69EF3CBE7FA6102B0BB69D75F01B465324AAC7D3F983BCF2F9FE98D90B2922AC3D9FAC68B41433977F7EFA41DE797CFF004C2BDEFF00DDE9FC4690779E5F3FD3077BFF0077A7F1041DE797CFF4C1DEFF00DDFF00B7F8820EF3CBE7FA61354EDFC2BF602364A789EACD0779E5F3FD31AF7C9F6FF88DBBBE7E9FCC6C439B88F9FEFEEFD4EF93B7D7F1EFE8777CFD3F98D9DE797CFF004C1DF27DBFE20EEF9FA7F31A1E74880047BFF7F77BF1BA5616682DD75DEDE1D3946C257158DB5D23477CAFDC7E584D6B147A0D2F58C19453737E5FCC1DF2BF71F961B4D582181A8F7D6DBFF9C777CFD3F983BE57EE3F2C342B0297DF97A467BA3CFF00F1FE63053E411336BDA3DDC87BF7F9DD25AC121D85FD9F7B987B87965AFA736E5ADECFA6C291BD1526264F283FAC18BDB96DD670EE5A81D6A40F41F6DA1ACF0CA524835A00DE1D7DD0DE1E32EAB090EA9C850013E76F416DB7999185E6CE4CB492685A8747E5E8C7C7A9232E1398F01351F5E54EA75B0DCB830EB398AFB9694942B69046E4C6FB72F4B1D84E2AB9866C25950E2B3EA69F5B830BCCC28C2A4A8A5D22E35D4BD3AB51A879C7AF1F46476448CBB506AAED873A60AE9F45B0C8A05BA8FE5BEACC987183DC2D4385CE051495168AB84DCF0918F2C7C5CCF138AC6617042710A9F32810496E1525DD999F623560E6392F6F730E14A422812E082DAB114D7D1AB1DC8ED0F3DA8CC01AA5A897C3D505D24C12DADD25B1E8106398F9E3A176170A0612495A43290928A6C056803BE963778E32B9C66CCBBD89AB35C6BA077F60C74B35CB08FAE665560F829928537D09524CDCF9CDA37F3C774CA25F1CB94959AA8B35ACD46B7BE7164C94913D079BF4ADAF5B1D9ED1E52FB4464FDFE7C3374B453F5D5A8A951013DCC004AA204EC27DD7225AF6B72A97230C6680012851240D838ADAD4D3C418F4B763330E094002FC3C20279F21CA9A56269EC6DECF755DB57692DE719BD3B8D688D34EB1519F5538DA836613DE52A5B240539C4E37C2AEECAB732236F36AF1789C4632749940A8A14A4F059DC900BEE967E64342DF123B649C932D01C0C4625244B5F13997C20713A6B705803F68F6FB5867B414D449A4D30DB6C65140CB3454397A385A6D80D212C38E0042412E1471EC08E66716DC932698A4A3BF509D36A56BE009245481A03C2081AF8C790B3BCED59A2D4A2A2788927E67A9F0346B68DBB88A7EBDFA948A6A075E2E97B8D5C615207F5904824089237D85F7C749CBB048C3CB0A609006C03F2E5E772358AB8C331E337B7315BF95A8FE74FA0166912C8492424889EA46DB7BBF1EB8F9E17600F100F4666EA7C5EF5F288500A8B0ADE8D7F1B53F8BC735110DF88CDE4498DCFF00BFC6C70BA1249568295677A7BD7A6B0F91FB46DAF99F7E3CE1BDCA869BB2943CC4EC3CF95F0E048E20DC26F7624BF4635E45AF4BC2D2F5F0FBC3555674C5288E3038A440316E460413F779E1EC8CB5534FED25ABE760CFA3F37B429107CDB52D3F8BF9824837B4CFC763F9E2730D92A8B320D69635E9A75EAF04416B75630DECE01320F8A36EB16F96DB6E062C586C8944370D9AC1BD9176822B7CEF5835E387881B59663DE27E079F4838B1617B3A5407FB64EBA8FC0D18736171522A9CE75F268882878A839C5278F6B7207CE2E2201F8DA32DECD93FD8C7667B6946D3C2EE758752120EC0EFE6FE240F467115A671DA72A15E3277FEAB917E9BDE79F2EA316AC1F66C3B775E36D6BA1FF3CA1D7766EF417A796BEFC62B2CDFB4B528A4059B49B28DE3AF98B1DBAFA0B7E03B3A97004B1B540E4581F7B883BBE7E9FCC40B31ED21609FE6AA6FCF96DB93B0F889B8E58B7617B372D828A45A800B026DF6A3F283BBD5EDCB7F1880E6BDA22D6A49E3322608519F7FC7D368B62C382ECECB485120076D07261EFCA1D4990662598902DB68EFD6D5B5DF588A54F682E03016444C9E237F74DEFE9CBAE25E5E4726AE0519E801D7EBF5BC3B4607899C585E94D2BCB93B1D285E2335FAFDC25242D5378854FE16F8F94C61F4ACA248E2F901B7BFB5A9CED0E118124B3160EC451FA5DDB5F1D5CC313DDA0BB1F6951E6B2239CF3E43EEE7B3E4E572831E00FD03F88F62BE6E9182A5BA51ECDA86EB4B6DAC256FB4170714AD5D6E6639DB7EBE97E507189995C851AA1236A8F1E5B5FF00C49613046A120B16D0D3C079DEBD6315F684B93C2A23A78B7882791F593D37C6BFE8586994084316D05CBF5FA91E10B4CCAD4BA10C3A16D8B57CC5DEED0A287B45524A8A89266DC47ADA0123E406D1CE70CB13D97C3AC1696914E87C75E5ABD9A239791A89A21C7420F236D1B6D46D49053F692E0825C36123C4444C6D1D3AF2F7C62BD8AECBC9493FED8A93A0B073BEFD234FF465A2E867DF939DBDF9C58DA1FB69CFF21CE69F30A3CC5C6F2F60CD7B4A76CE050F04052A41046C07AE39B76B3B12314852E54BA804D12FE4E29F810DE7E171185FFA61418559FC3E97F5DBD79F679EDE721ED4B4E2F2B5BB4EBAFA1427FCBD4703BDEF112A52781C0526C0C883B89F2F2C76BBB3188CA718BC4A50A12D45426F0F12598302E19DC81EA4BBC664637168042CA9C7ED279173E82A5FC6C6211ED05EC5FD8EF6F34B53A86A6869B27D62FB6E062B2999534961D424A01532C8432AE30126E39CDC9C55B29ED563F2E9B2A4714D0994AF91456A20825ECEF4A569B522F3907686761DD066B22614858531B17A136F4D2D1F3FBDBE7B16F69DD8B66B5B555197D4E6FA790E38B6736A740290D4920965A0B518102FE64ED8F55FC3EEDF2E709427CF73F2D0A80A0E4588B5DAFB4769C97B41829825FEC4B0058904F3E95DCEF7D7A8A288BEB7FBB2A6CD3102A4B80B6A76491C3C0B852784C8902FF7F72C56792B1F2E5F7530120025883B0D2FE4FD0459B1F8A938896832F84D3420B16E54BDB61CA836B596BEF254BA4506823ED490663A027D4C6E27E0C462D540FF00C5B9357CB66A444A4A6BC49E2F13F57A587AC25356DB84B1C10F3261D5DC8513B1DA3972DF0A8C4059E151A8F7A795F96B0290400480CAF6C418E7892398FBFEEC3842B436D3DF38D638E34FEFF7FBF8E09EAE1A055C69A8A751CAFBC2339C800549F4B17F4838D3D7E47F2C35756E7CCC36E156C63052A6209F3DC60E23B9F38D822EEE36A8FE63193D4FC4E073B9F331B700DCFA7E23893BCDFAE14429C313516AD5AFF98510002075BF898E64F53F138DE178D88544C920F52795B9E08233E3FF0057FEEFD70411A9C50312A077DCFA6364AB85E8EF046B91D47C4632A5B8666DF58C100D0C71C69EBF238653161CF0BB9B9FB0F7D231C097FB69F9F58389279FE1F7E1BA95C2D4778DA3153894F39BFEFD7EEF3C204804026A6D12B8295C52D4793F3D5AAFB6FE5025C4AA6F11D7A47FBF21E587D2940DCD2846BE1F6E4622B152DA6B58F139A795B7F1F1854CBCA553BECB07F9CE29A09DA7838877963D1336E97E8434CD279972CB280614DDF6D77F41B44FE57212521C3961CEFE96BF90DE2CAD11D9E56EB3D6BA7B4BE9569CAB733CA965B7D2D712BB94214D97CA8DF8470951B91B475C714ED3674B9054429E8B7AD281CF8916B78C42F69B132B05879B3967FE98A21DB89C5F9333B7F88FA71D1BA1F2EEC7BB2ED2DD9BE5DDD8464D445DAA7109E15D43B5A94542D2FA8789D2DB8A504F78A5445A0638263702ACFB30398CBE2577B31248539E012D4051D99DAA68EE5DE3CB9DA7CE5599E2169E30424B30346A016D19A95B13D280ED12B920BBC3037DADFB8E5F9E3D25D8BC29461A44B218A529141B51C7A73D0EB15A929E250043F3A8FE3AF5E74E9EEB4A9A9A961686CFF97593F58322641F04F337FDEF3DA3072132C21668CC40B6C4DBD0B3F8D22C980024A9045DEDD341A1DF5ADB9F5AB3EECC737ED773ACAF43E594AA76B5DA81F5D7D081C2DB0161C27880013FCA0660824CC620BB699949565D352A58480929248A82CD6A12E6836D869D3320ED18CBA6226B717082C97672CC5DDEDEB4A47A59A6F46699EC07B39A3D21A6BB953ED530FE24EB690971C7970E14B8BBA97C2A2A0029460898031C3723CA5588C54C9BDD90952DD2752E4FA1BB18E71F13B3D9D9BCD413314A751700BA458000025B4D2BE51535766C336A779E71C2D8E2528A42A2E144C5A01B827F738EAF80CAD322585283300EE0FDF6D869AC50B01835291C641552A1BC286A5CD6ADF688B5255E699857D0E539334E543F50E16D4B00A8A1054028F1198F099EBE9BE13CC7304619052080002545C0B57EFEC98DF1BFEC8370C0B1EA79EF1F44D599B06F8A1409B990403F01CBDC7A63C0F2704EDF2D3A1A7DF5BD3CED570160964B0B33B9D6EE6F5D0D623CFEA0201957853360A173EA7A749F81C49CACBF8BFB0BAA83A52A08FB3E95AC3A9648A58A7EEFEDE2119BEAA5B6550E0000330AF97BA44ED89595969424012DC9D83F37B86FA1BEA216439249E515C66DABDE723F9974F15F8C017FC081F941C59F28CA8A93C4B450B0A8634B796AC2FAB43897AD36FF001EFF00115D66BAA9CF12BBEB9FF501E5B4CE2E584CA40E1025D68CE9D5EDE15BB7A38522B7CE756BA8E187C5C13F6803378E7B9FBA05CED68CBF264A81E2410A1A33F859AD6E45B4822ABCF357BDE287A08B9F1CEFD2FF00BBF5BDBB059225212D2DC3683AD0FB7E71B702B6FA7BD62A9CE75629453C6ECFDAE63EE9B7BF7E569C5A72FC88DC4B6DA9CEA3EA2FB50438929A07A359E807F80DE25F578ACF39D5890170B060C9F1794DA0DA3AF2B62C786C9549209960100B16AF3EBF53AD1E1D3278801CDEB4B1D5F9457F5BAA42B7546FB99F5E73E5EE3CF13D83CA8A6BC35A0B0F7616D3D236128AB88814A01CBAD7CAB110CC352A49278FDD3B41161F1B462770F8166052DCF98661AD799D6D1B270D3174483D4317EB703EBADAD0FABD42924CAC9898FC7F193D3D6EF84B12EC9B5B407C7A537E91399760560FCE926C6FD5E8DF588ED4EA049264C0E809F95EC363E5EB8CFCC5E9C3E47EDB0F11B44E8C18FF00800598354B02FBB56F6EB0C5539EB64595224DCF53B6DFB163E8BCA510DCB51CEFF78729C0A890C9A0B8E5F4F426196A33C499124474371D2F3B1BF3FC70E78D2039142D473714FBDB9D2242565E6C12E59C6A1BD2DA1DBCA10AB3D42448541E927EFE7D7E1E9889CC3126590516AFBE836A6B68792302A4129281522A40617D06E7D884ABCFD06FC5D058FADBAFFB88383098E5310A074151D37D696894465E1403A59DF4E85DAAF4BF95291827512533E2DE2F226C67A72F8EFE5896FD5CB2E4ABC1DC96DFECFF00430F539525491F2D1F6E9A31F4DFC21C58D4C9060AC587F76FF1E436F7F9E186266CB268A07AD3DD8D1A8FCA345E512D4E38452C680FA5AAC34B9B80F0A1DD48B7CB6CB5545A2E1E2212AFB7C3732418100409DF60271B60B0586C64A9826F0BB7F7355DFE82953E1568565F6764E2524109046E2F76F5DDABB3B45E1D90F6D59AF65FAE74C674CD538DE5B515496AA9A4AC94A8712199589200054771CE4440C716EDF76330D8D973BBB48527866592E4163C24B6DBFE1A2BB99F65F825CE32D20AD0C50281F7A1342351A57768FA23D3FAEE8F50E52C67678174599D1D2B9421A70143CA0CA0BA12EA0C24A566E2649B6FB78D732ECC8C1CF5492C67485AFBF510C500A89438B971CA976D4728CD26E232F5A9402801448E86B5D1B5EB09F3BA4A0D4794D56599AD15366F4952853672D7D0D4A12A0413DFB8951E7C5BDEC0488C2580993707353370AB5226CB219692A2363F2DAC7D0F8B7C376DF1386F912B5914043B352CEEDA72D6D1E457B4D7B026579A22AB56F66B1455680FBF9A652CA09EE54428B612A5101CE2B93C22D231DCBB19DB1E2C47E9B315AA48584893314494CD61F35E8963E7E11DBFE1F76B55994B28C54E60867E321C397B93F6A18F1933ED3FA9346E775392EA262A68D54EE38D82E34B4F1C122764F9441FC31D7E4665865DA7A58B310417717BB01D2ED1D725E270B8948326625445569E214DB5AF3E66CD0C2BB2D4509841D9569579C1B89F3E989595325AFE64A817A82FD5CFDABADA14490A6E1ABBF266BDF6A3F3318952809260752001F18C48A1429C25C1201FF27AFE6374A16A0FC247DA39E251124C03B18DF69823A0336C693663060A7DC6EEFD5BA78D1A1B4F42812E0823F87FA3FBA16FEF3F03F9E1AF79CBD7F886D19A386F2E7C41FC4E0EF397AFF118248B07F168CFC1FDE3E1FAE0EF397AFF00118757FC7FF708E0C5A140CCFCB0ACB983E67F96D57EBF5F778712412412185697F17B681B9BED0614EF11FF00210EA30592220F5FC3005A4D8BC11871ABAFC87E58CF1A77F43F88235B8A55AFD790FCB194CC4837EB4351FC7DE0626C1E35F1ABAFC87E58D57352A71C4035BF1BE8C5E33C2AD8C1C6AEBF21F961B19A80402475766E55FBB46785550D7BD469071ABAFC87E586E66A058BF4FF00107028D924F484EFB91C337DE4C7E42DCE7D3E1ACBF98B8AB5CF33FE6F13B9620095338F67B59B938AB8F1BF5E1A58292A83C3C88048313E5FB8C3DC3AD0A04715B516D4D9FD4DB7DE131692A9C78773EA691CD3D6770F21C68F12B8836122EA5170F0080249B9B002FEEC577B418EC361A5AC4E9E94382CE41AED7A7589AC03C994A2B7400E5CD2EFE4C1EBF48F7A3E8E6F6776345699A8EDAF545377CBCD508569C66ADAE175954A997D496DC1C6012B064A40D88240BF99FB5D9B4BC662266130AB3314E4AD601646A2B6214C4339357BC719F8979E61D1226265CE495F0AC04822E6FAD68EDBDF471DECD635D54CCBEF39C6A7F89492140C22E52090792488BFA011675D8DC377C959989F9924740E59DB9D39EBBC799F2B9B37158A9EA98E47112092599F4DF537D183523A8DDA1E624878070126E52140F3F2248DE31D8F2859C36265A00F95C7CDA50694B8DF6F4B3484CB04592CFE049A5FED58EACE66E56E6598D3E5F4E14E3550B536F250389416AF0B648124788CC8F59C75D562F0E8C119A5680A12DDC903FB7AEFE3A43C54E4A40F983FAB83B0A57AD393476BBB3FD2947D96E987B31A869B5EB7CC9B0A69E570F1B6D90AE6652921856DCE23CB1C4738C5E2339C6224CB0A5E082D42600ED34834622A38540EB51084DCC57292784B91600DA8F7E7CEB7E462ACD4DABB8D150D3CF29FA97D64BFE22A83C44F224589D85A05B962FF009065089694AD6809A07040B01D03D1EBFE0454C4AF309892B06849AFF9F16D7A308AB4E64F543AD51D38528BEE04F0A012A32A8FB224989BDA7CF699EC7AB0F8794A485A41092087A58D05583EE49E82D137879587912C82B4A484EB4F4E7AFDEE3B71A0324CA7B39C85DD4D9C3487330A9642E8D2EC071B54113C06542E41F1016EA231C4BB478B998C98B9387515842889894870E5CA471015E6DCDF58A8E72A0E4CB75036367AD2951B1F0E71EA36659C3664717226EA36B409F3B728F80C79D70B8304FED776B8DB6AB0A3176A7A4457027D9B7BE6F107CCB3B4240FE6753BC7A73E53EEC58F099792DF2D000006A907EA6F190902C22B7CE73C412A973ACCA8C7BBAD86E39FA462CB85CBC10029034FEDBBF852E06BCF9662B7CD73B6FF00E6708BDF889B6FB6E4F945FE3369CBF2F649E14072DE7B6D7E5CBA64122D1566779F24154BA45CFF005284EFE7602FCA716FC1E0520A4140AB68C4B7416FE3785E2AACE73B4A88FE612255038CDA796FEF91E96DB170C065E9FF008245051ACDFE75FB42E00141158E739B83C443A7983E237F2EA4F5E5E9B62DF82C024B3A053560341EB6A783C390C34A569FE7D8D22B8CCB34E22005A8913FD47DFD63A927DD6C5A3078364FED1A5C0AEC341B523632F8806A1DF6AF8546B6B59E21398E668F102A207A93E47FDF9CDE263139230C90015005AE1AF571A3736B885A561D45882E353A9D0F97D1A2179866215C30AB09E7FBFBA0DC937C3F972E5D59228D6E4FF4899C3616CC1DFCC56C2F7BF880F678BD556A493E283CAE679F39E63D3A838708968AFCAECD7FC79FE22730F82040743125EBC98F2634B7DA2355B5A2D04F393227ADA39F2F59F5C131080C486BD757F7FCEB12F84C210E079816F5B753E42D1CAAAD4927C4444C5FCAC664721333CF081084A41201B87B52A3EECDAE9AC4A4BC3970C97DE82BF5D343AD7AB2B95A0920A8DB7827693EF883B911E778C375000B00DAEB57DE24E4E1C16743BEC2BF47DB7E621ADFAC499B9F333063CFE07CF7B73C36529CFD044949C20D45069F9FC56D48697AB120024DEFCC47BE08F3933C8F48C359C0177AB3372B7958F9F3112D86C1214DF2D587570D4E74E8FF00442E5724EE7AECAB7C41836F8C0DF0D432052A0BB301F514F7E4F0E0827467AFED3F47D377F268D06B5226E62FFD5D3ADBEE9FC7092A72C502BC341CBED00904101E96A066F0DF95631FAFA3FBA0F3F10FFB8619AA6AC9352DF5EBEF946E306B0EC0B1F3FA1F6F7731C8CC9C410A6CA890A489E29DCC6F262660C1F29BE1D499D3112661130A69A7FF00AB4E5BB7285E4C8293B2B6D4EAD7D6C29E178795E7EF32FD352125448E2124CA4C05483CAF04411E5388BC2AC4E4E204E50997FDC1C6BBB8BEBB6B18C6E0FBC94A253522A6DB8BEBAED6D35F7B3D853B48675CF616F69872A0AEBF43A9A04AD654F2BEBF54560152CF11802D72074DA3C87F16B048CBB3999899008566055DE84BB204A0424DDAA7616F5E19DB0CB9284CC1DD8643906D777D8EB4D43DC388EE73F53DD17521C238D2D917327853248827DF706200E58E7FD9A946609CA5FCC0115218D497FBB694B6B1C52661889A43317A0F1AE8CCCF7F5668462B5AA94BE92E250EBC9E14154149004282C2BC2AB75F4B5862CAA966594841E14A4BB815A9A310C7AB1357A6D3B976327E048EE96657135412051BD5998E9568E977B41FB33E8FED432FACA9551B0CEA1085A9AAC6DAEEC2DC8241212128E82E637DE3172CAB1B3414A16B570822BC44B5294EAD6148EA9D9BCEF1699A850C42810DC4E7881D0821EA2D7E54263C32ED47B1DD57D93E78E51E7D46F399754BAE8A2A94A49404B64CCF76088129E7BD84CE3A9E513E624242A605022F4A027ABF9B78D1FBC6579948C6C994A03BB9881F3077EF1D83F2D49FADE295A97EAC3C94A877F9783B240494FAC4AAC79CFE38B74B99C49705F7B78728B8E1A6CB5212A291C400047A3697BFB10B6A54A0D30524160825A47347F749DCC99DC635984D1CD4DC56BF6D3AFD90C7250B4860C79ED616F523D211779E5F3FD309C45F723979983BCF2F9FE9820EE472F330779E5F3FD3041DC8E5E660EF0F43F1FD3015F06F5E434EBD616932921DC0F5FADF783BCF2F9FE98C77C79F9085F813B7A9FCC6D6D60CCC8F98FF007C67BDE6DE03EC0C1C09DBD4FE636F1A7AFC8FE583BDFF00BBD3F883813B7A9FCC705606D7F97E18D173096657A7F1070276F5309DC5EF3D2E768F86FF00BDF6C20B5AC10CA6E97F1FB78C1C09DBD4FE6908DC73602FD3F7CBD39DCE1098B5503B3BBB787BFA343E4A10003C21EF563EF96B1A7BCF4DFAFCBD7F71867DE2FF00E461544B4D5C3F5F18C915612B4B0A00A5E07895BF08489B1DC7388F2EA313D96AD3DC4E2B2EC9BF817EBAF421A821C7767BA584001F9B6FCE8E5BCABCD653D638D52D496480C01146540492490F44DC93CA7D4621F058D299D89055F213F292435C92D7F5D7AC43BCA973E519A38A73FF00BA384B00FF002B814A0A3B51E3B8DEC2FECA99AFB41F699475F9952BAC68FC96A13575EFB895772BEEC77E80788A64171B22C48B99118E09F16331C415BCA9EA425D99277236BF4FF10876B73C9383CB664B90532D66529D8D5DAE37F5BB347D2566ACE459464747439486D8A2D3B4EDD232C3490DB4A84A5824348E149BA249E1266E2F3344ECDCB993CB4E05666A5C2D42CC28F7771D4D58E823C2FDA2CCF158DCCA6056215313DE2800E5AA4EE49F7B33F5DF54E6EB8AC696A5292903EA4493BA812E45CEC771CA04473EABD97C0F77317F2808243B01536FAD35DE25B0525326425412028A4540BBDDD869E1CEAF1D4BD4AA79CAD577854E3AEAF8384289B1302C081CC63A2CB97C3502BEA1ECDAD7946B3A62D36253F97DF5BDAD6BC4FF0046E87C974851D46AECDD095D654252BA143838B8080428F0F885ED123716DC6196267E2B153C60A54C5140FF00ACC4D033A40635714A7A43513660209516FEDBD77E5E3466F3AFB5BEBDABAAAB5B8AAA4F0BD2869A04029481C205B6111B798E47172C97279328213DD5989E20EFABD5CDFC9CC399438CBABE635777018FF9B7E628DA8CD5FA6A9A879F052144428F8F88AB6481B9E298117BCDB9DA31F3118390C964324D2CE4793EDE35AB449A0A254B53258B3123EA29A79DB578EC5F62FA169DA655DA1EA767B9A0482ACAA89E07894E5D1C7C2405D9CE1500A4911B5B1C6B3CCD2762710BC2C89C5D4A214A497084ED7209507E8F6D62B3996216569E0511C2EE428B2AA34D18D2C1C72BA5ED4B582AB2A4B752F0352DF185F01E068B51FC901B443638500030395E0EF25906070E129946582054F11E2249A92497275678DF2C96AC4CC1DEFCCEC2D7DA9A7BAB47A7398E70F193736EBBF9C733EA71C070F80424B82E36236A353EACF488A880E6F9CB8024827C455CEC4FEB6FC37B59705824A883D2B60343D6C7AF8411586759D3A4AE144EF107D79DBAFCB16591854A00702D717DB4E9FE5E8456B9A674F447113B9224FDFF00B988E718B3E57864872A0030F1F3DF716A1DA08ABF3CCED7E205666F249BC91B7975361E87168C2E141F9A805399B8F5FC5E1C0B0D22B4AFCDDC528CA8AB7BFCBA1E7BC7C3171CBF0A1D23CDC374EA36FB5E1C457B9CE6AE78BC44133CF9413E9713B47A8BE2E183C325213C4028D6835DFC052DA6F0E694F567AF2AFD6D5B30AC0AAF3270932A3B9B5F793E5B5C6DCBAEE6691204A161A786DF6AECDCE24B0B28299D2C28EE5F99DEFF00E221D99662ABC1379FDFEF97BB0BA789C7FC6AF67D1BE8DB8D1844E61F0A82E05D2CE5ACFB575B797488ABB5CB502788DBD4F9003CAFD473F52E258357B166F5FBBFA44E61B0813C2281CD9BD7F00F8F363AAAC549B9136206DF21E7D37E4230E25EBE1F789B918349BD5FDEFCBEBBD63B5B58A004DF7D89E73F8FBAFB6E71ACE7E17D1EBE9F8898C3E112970430A5BC1B9F2209D22355758A13722D37BF5F311BDFD6D866B24853F2AEFF008689195844BBD850F9FE34DACED76572B172649E7FED37EB1CAD6EB86EB511E3AD0337F1D22570F84492C19C5E9BF93D18E8DF46B7AAD706E4F99BFEEE778DE2791C332A7B519EAFEED5F331232B09562001FDC47E2A3D37F16A76B166209833FEFEF9E7C8FA0084F3ADDE9D29E147B5BAD624B0F87482DD34D6A7ECC2D4840BAC50E7E637FBF7FDDB0CD4585013BEDFC7AFD8B93246C0F8FE77FF00309CD5B9D499EBFBBE1B295C2D4778D3B87A801B4A0E9BC71F5959DC7C0C7E1FBDEF11868A5851F95C0AEA7A7DA36EE696F17FE5A394E6A9A675A6D6990E104C9FED20F4EBEFEB6B1CA56384D6A4100877F3B4389785E22549B25B89CEE5A9E76630B9FCF1B72AEAAA026F4C1A4A4F4E301260F381F08C3196BEED6B06EA2C696B8F56FE443D9B81FF00648201E204A74A01E8F53FC523D2BFA35BB42A9A3ED79DD089528D26B3656E38893C3396D2B8F24F0DFF00A86F1EFDB1E68F8D5FED6265B31EF2CCDA33B120DF61B3B35B91F6DB2CE3C0CB9894022571F78453767A024F87D80F65AA3345BC8A9784FF0025F2D4F203BC2D816E97001F2BE39B766E58972C922843B7A9DFABBD19E9531E75C5E1409CB61AB721EC6C776A421CD1EA7A65B2CD538A692B0141692641226D11249B7A62D2A962600B48D6A0D486A539D397DE22F184482962ED6E56A6B7BD296686CCCF35A814BF5653519790422B090547CF8638F7B46D3D4E24F0321226898872B49A2743B3E9D4B1D0522C790E3A624A4034357B7997B5AA0F8C50FDA2F679A635E64EF506A0A269E67BB7050D52920AC29625644026CA20448C5D7018B9D2672552C711769D29C86164D5E828FB73D23B6F67F305B25894B70B58B9E7F4FB3B478BDDB876059AF66B9B55D6E5090F644E38B500784008DC40512AE768131E713D0B0B39D20A4B12016726BB5437D368EA981C72D68055FB8332874D68E695AFDC47565F0E25454567854480DFF6116313D4CED874B2EC742EDE7FE2260CC33D22E08A13BFAF43FCC2793D4FC4E348D7BBE7E9FCC127A9F89C10777CFD3F9824F53F13820EEF9FA7F31CF12873FC7EFC11B253C2F577F7BC1C6AEBF21F9608DA3636A55EFD3A79E0823671ABAFC87E58208E0ACC1936E76FC8608212AD66E67D07EFCBF7CB092EE3A7BF6FFC9089D5ED373CC7B87945B084CD3C7ED0F93FB4468EF0F41FA7EF9FCB0CE1697AF87DE32EF9A292D287F39653DD1BEC3EDFA0E107F330061EC99A65C998016241A72A8FE3A9E6625B0D2C2A5AA81D85478B136D5A96FB5BBD8FF65B9C76D1AFF21D01A7C91F5EAA6C344708E26D252E544F14720A1731EF99A066B982B0489F3662F825A41516E4F76E61ACCE763152CDF1A8CB7BC9C5026CD5823859B85835D8D4695B8BD23EA3BB30ECA329F679D0995E89D354CD53E6E9A563F8F54A10038A52909704AA24C82B1E156C6D36C70ECDB1CBED04F5E317F3617888C356DC2785742C4B91AF3F0F35F6DFB5335026C9E3539E20456C5DBC0023C2ECC2346AFCD29DC5B6DE5CB3F554A54AABB93C4B899337FB5C5E5E800C5A3B35844210AF943900696736AD1ABE768E13865FEB71A56AD5679EFAFAEF4B168EBBEAFCECB74E16A324F1269CED24920CEFCF99EB8EAB91E1021D40073566F3FB8BDE3A409625E1D054588143BBB303D2E5AE2C6231A474F36E29FCFB3B4F1B490A71B045844C6DE839183169C486366AD2A1270DFF0055640E96777BB8B546B1173C025459C01FB7C3466A8FB08AC35EF69CA0FD665A904D123C14C018080278AC049B89369BF3C59727CA6505214AACD5B152CBD48D2BCE97AB54E911FF0032A610372E0B7E69C9C9D7668EB56679C3150B5666FD4AF89B51286A1504A8909E703CCC6F36C741C3E01329085B86E9771B796AF1278595354A1292975173C2E03B03F40C6CE79C5F9D88F6655FAFAA9DD5FA9804E89CA54D3956490429464538213FCC82F2520900FB86397FC46CF93972A4E0A59271789E21264DB88062B3C4681857573477A95F1330A2539D010B5731403F9E51716BCD5AE53D4AE9A8DB0CE5D4AD7759751A2020B696F84ACC40160177124C9DE71CEB08927854A24CC51F994CC5CD5BC2D7D3668A8E2141732D47A5F91B73B56DE71D1BD55AADEA9CC2B180F29D430A90E99F171924A6F061311E62F18BE64E966A1040AF31E5E0E6D5A6F7EECF6010532A610FC676B358D29F4B47CB3E3F3111F6BE0C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C1041820830411FFD9, '1', '2021-10-06 01:15:26', '1', '2021-10-06 01:15:26', b'0', 0); +INSERT INTO `infra_file` VALUES ('26193c15-afd3-469d-b55d-eb1aaa2a4b63', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010305010101000000000000000000000304050206070809010A0BFFC400431000010302030603060406020104020203010203110004052131060712415161137181082291A1B1F01432C1D109152342E1F13352620A172472164325345392E2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004311000102040306040602010303010803010102110003213104415105126171819106A1B1F0071322C1D1E132F114234252081562161833437292A2B2D224258234FFDA000C03010002110311003F00FBF8A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A0AC4C7CF97DFD89ACEE920903F71909243FB3CA2953A948260E5AE5FEFEFD29962312647F261DADAB54FBB46C10A2D60FA966E70826F595BA5941E25A7FE44A4825BE9C63513CA69A276A214A097A9E03D63265A85DBDF46841EC5AD187C5BBCE0696AFCA56A0904F2039FCAA524AC4D018D5BEDC3CFD886932709658834BD0F0E56F3CA1E22E10B820183A1EBF4CB9CD6B326196A29A1B6B623B74F38525AC2D20DB510B05054C4E5D684CC2A6602BAFF71BC7B4A07CD9F841149580633FBF5ACC11E832268823DA20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20840820C73A5029934B8D789F7DA140A64711AF13F87ED142BF29F4FA8A6D88C289E0920391507D9F66D0D558B097A0245BCA9D7FA363108D34DDAE2172E38BE137E13C0A0608F084104E5F43A193CEABD8AC18C3106D7A5E95AE76A59BCA1791395398105EC3ADBD39DB268B6B10C5F0D18A0C3577187A9E42B5B958372743EEF3D2069A4803AB0FFBC8C2AF777C066624B736FEDA9A44C4BD90B9D2BE7192B552C843AB3A97D1C7F717BDB3ADBC96D6D2925053970E900465CEA6F0B8A18B97F31DC9624FBCB4F60464E90642CA14929539704311C0F9FEA1FB7CFD3F5A9295FEDEBF784614A710422BFCC7D3E828821447E51EBF53441155104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104450C4D92F5D301B70BD6DC3C400FCFC63FF00D79E70067D09F4A6EB9E106B400E7C75F6348C33B8F21786AEE2AD254C254D3E90EA5D5AD6A4C2184B492A25E3FDA08120FE99D64ED09094B93500D33A3F0B521AAB05316680B121FBD3D8EC0C72B7DBCFF894EE97D96762F197705DA5C2369F6F9E6D6CDA6016578C5E5DE18F825B3F8AB54AC38CF1485A6332248D0D5476EED793F2D5BAB4835A3874E7EFFF00F422DDB1360CE99392152D6427759C12921BCDBD75AC7CA1ED6FF11EF696DBEDE6E03B7F6FB718AE0F64E634D1B8C0ECB11BB61B72DDEBB69086C5B85907FA440209233D2B8BEDADBCBF9A425550A167CCB3B50F6341D23B76C5D8084491BF2C01B85BE90D6ABBEB6BF4AC7DC57B266DF5CEF13721B0DB518825F17B89618D2DF55C4F88A5A5B6D2A528992789526739EDCBAF783710711B2E5AD4492522A79F1F7E51C6FC6385186DAF3D2121292430019837A46CFA7DD05474807EFE357795FEDEBF78A94548585A428640F5A710426BFCC7D3E828821447E51EBF5344115510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510478639C7AD10422B70699F61F0D47D34F5A208B57157D9B3B945F38EA6D8B48756950570B2E808952AE4999091F97A647ACC06D3C4090824E8FA3D2D7E1A1830A37E72505FEA2DCE9AF5F58F9FBFE279FC5A30ADC058E31BB6DCF5FDA6D46F5F1369CB0BDB5B3713796D84A5E4F85E2145BAC3CCAC5BB8A5C990148988CEB96EDCF150C2EF8DF096041AD9BFE35B1CFBB88EBDE16F09AB1CA4FCC969992BE9282DBCAADDFAB335358F90FC671FDA5DB2DACC7769F6E318BDDA5C5F137957CEDC5F3EBBB603AF953A5A42DC3C50C9596C24C70F0C72AE57B43C6431130A44C24926E4BF06A7E7817AC76FD9FE071225A54248140C426D9E94F3E2F0CF67F1042F1861576C16BC2C4B0F36E1A4F0A045D37A13D3224E7998D6A2D13978D58512540A852F73E5435F661C6230A9C0A199B752ABB0A80457F0D7B47E871FC3C2E9CBCF65BDD95C3AA2B5AB0F70499984A9B09D73FCB15E96F044BF97B265A48AEE8A9CDC9FD7947977C6F33E6ED89AA77049E548DF55FFC47FF00A8FD2AF72BFDBD7EF14C8A58FF00893F7D29C4102FF31F4FA0A208511F947AFD4D10455441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041A510435372388A40CBA99E5AFDFCEB2C7431B896A29DE0CD5A674E9F78592E020120FA7FBADB715C3BC25315F2802ACFD9ED0C9CBC487FC208717EE9515244A13099827404C7DC56E656EA0294E1DFAF271EFAC371880A56EA475D3FA7F53A3C4BB8AB49B755CA92E04A78CF01FCEA4B73C4B039848127A0A693268403C01BE747A7EE91252A42A6B338720727B3DEF46FC47CEE7F186FE29985EE1F652F3747BA1C4DAC4B79BB4E872D1D5DB3C975FC1036471F096161EB75B8CA95196640EE6B967893C4F2113D7841FC88604B642ADF97D6863A6787BE1A6D0C74B4ED10A1F2CEEA9206F6B906D0E5FA3F1FB79B578EED16358A6D56D05DBF7FB538A381FC4F16C61C5BB8A153C494A1A7D5EFF00080A28009FC99682B89788F0D89C7854C94A2CADE2E496725D8B06D341DCC77FF0A6CC97B1CCA4CF4A545346AE547660DCB3B0E1157CEBADB8943CF5C34C13C43F0AA8599CC95F2CC991D672D6B96AF63E3913C952D4C55A9B5333F961C834761978FC0CCC37D284856E8029C297E35CF389AB3C66D117B84E1B609E2BCBABDB4E07AFA080A6EE1B27888CE55FDBD7A9AE89E1DC0ACFCB4AC97053C474ED5766CE398F8A12662672A596A1208003D3FB7AE75A47E875FC353F1AAF643DD5BD7E86D1706C6E38C36084C071213139990273AF50785E42A5E025A5A8406F795ECDC9DE3C83E2C27FEE73526E925CDEF6F4CBAB1BF41B8C2D05398311DAADB2D2433E4F5AB574EF1578ADA494A003DE96820520924E5F63CA8822B488007DEB4411ED104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104332D00B2A264F41A67FE32FB9A0162595D1F4E1EB0AA57BA8AB801DD850D4F7EBCA14CB4F80A5C6A73F21A7BE4E5A23713382CEE876163D7D3BFE60B124DC36DB82DE42AE20054E69232D46920FCE75D50C4CFDC40054ECEC1C503D7FAE1CA16C061FE6A9DA97E4C4971CEBDC0A67CC3FE259EDBFB39EC5FB88C6714BEBFB556DCE2B66FDBECAE1FE2A3F1172E3A54C5CA92D1525D596D2EA55EE194EB19556F1B8D4A50BDE57D441662E406B1A38EBE917DD8FB24E2D7266CB42BE56F0F98141C100B0619E649D4F38F811DB3DE2E2FBE2DBEC477BBB68E5F5D6D0E23777772117854E5BB69714E78296C392B03C352444E59655E7BF124D3336B29408A28B9CD9B2CA9991C4C7AA7C307FC4D8E996DBA4245281FA50E5EE8F67DC630E3D69885E5DB1174EA901808465EE2B8444E7F9634FAE74D14BDE90D9B503BB8EB763566E8F1954F06728D2F5BFE9F2F530861F8C9BC69CFC69875AE1E20AD424E49CBEF43553C6319A684107D8D732EF607AC5870B3C26592AB1029ADC55B5C9BEEF10B6F77737FB71B3563624A9C7F6870461A08CCF0BB88DAB6E4013970A8CC0F955B3C3E80A2839EF0E771DB8F7CA29FE22DA0942561CD942EFADEE1BB3F08FD407D92F6311B15B82DDC60086FC216FB3D873E5311EF5D59DBBEA310352A24F53CEBD29E1D4B602506144E5EC97F2C8671E50F13CEF9DB5710B705D43EEFC3311B3496C01CC7C8F79CBE1FA54FC57615A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821B3AB4A544150062403E5590905CD011E777E30DA62941C55893AD2A1BF5E50D9B7D2B497152809FEE5E49CF2CB49C87AD68A9852145C80900DE9C857B3422941597DDBDC900F9FEF9B461DDF76F3F04DD76C3E2FB658EE256B8761183E1F7777757172EA5A014CB2E38DA10A5909E35A90123AA8819CD56B68E37702885391966391F7CE2E7E1ED9E274EFA9255660D4AE4DD6DC5A3F385FE203EDABB55EDABED378B6338BE2574ADD8ECF623776FB0586B8EAFDF2CF131882AE995294C90B7590A64B5A82273AA06D0DACC6602B2581B9D41AD4F1AC776F0FEC69625A1210024350240BD4F0ADAD6F3D78731F17984B16E2C98B661B9485787C172424812AD358907A6715C7F6A6304DDA0B50373AB82E38687DB978E8F2D230F204A14614E1E61EE1B90E062C2C57690DBBA96D0C85DAA3881E24CAC98911CB23CE3E4269D024CABB535A6B6EB6CDEF586292A54F05A84E560F62C5BF3E916A0C4EEAED38A5DB07C312C809320E796401CBEE2273AE624154FB9626CFDEBE6F67D4889C4EF26428D430A87CEAFFDE71B1BEC8BB0979BC6F68FDD0ECC23C172E6FF001D6AE5697412829B2B862E3300124808300E522AF5E1B96EA41A0A8E6DEF8DAED1CA7C598B32BE692A20310CE6F4635E55E01F48FD46377F689C3B63F666C4A63F0B816156F0065C4CD85BB6AC8F29498AF456C30D8443061BA18767C838F7C4F9DF69ACCCC5CC59B93F97F26CFA45EE1415313975A9B88E8F68820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20886C47F0E9429D5BA50BE24C4A8246640239CD658B3B75E7EEB5F36704952C92029B32C481D7DB72A431C582DF612CDB381B6D0DA9C7DCE284A5284859248D321399023946551F8A5A82083762E03B3694CC8E76D042D2A484946F060E03666B4E6072CFA47C5B7FEA1FF00E2238D31B43B3FECA7BAAC7949FC4A710636E6F70FB950FC280843F68875C657EE789EF27FA91331D6681B6311F4AD5BEDB8F404125EED99E3766D0C749F0EE1C26624A430514F61A7A91CF4A7CB7EEEB0DBA432B6F197495DA3AA7B0DB85A8F1DCA9F70BB7478D43DFCCE64684E7CCD722DAFB40852F749CDC3DA829AE7C63D01B064A44A416B80030D296D5EC7D488C8D7D8C97EE5618052D70A5000D3DD10743A4899D0CCE46A80B9E6662F7AE5C0B335684D1BA718B1CF91BD4614A583D2A75FCF786A2D9BBA1FD4D79CFA4E7DC8D0E43B0CEAC7296AF9391A0D2BC3F6D5A7186987C2EF4C14203DEC0D4F98D3EF148B06ED78D981C374A4C003FE9F231E4395474C4EF4D14BDDB2B135AD0FEEB689B9D86DCC39A1B162C6BE753EBC6E3A93FC19B76771BC2F6F3D8252992EE1BB2CF5CB974A20A90D7E22C8A9AE230401C439F38F4E85E1B961E58FA6AC6B7E7C69F78E03E392A499C9245281AF7AF2CDCE7AC7E8C585B29B6B3B46131C2CB0DB690232086C240CBB0AEFFB1C3615219A9CB38E0B8B24CD24B3B914E0D7B5625DBE7E9FAD4BC358528820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A3C41C6524111FDC7435A15805AFAC11E2DD4A412015C65091268F98343FBF79F9410DD37D6E484A95C0B248285101498EA279F2A3E60D0C10BB8F36D23C45AA11CD59401D4924563E60D0DBCFF001C7CA08F5A79A7D01C656971B54C2D06526323047435B82E1E0852B3045256018CFEFD68823CE31D0FCBF7A208B571E6FC4F01A09754A5AB88140948E15030B1D3A538972BE64B52B78242323405C93D843DC24D4A5D0A6B356ACF50E39DB8D738E7DFF115F6C4D9AF637F67FDB4DE063772E1BBBAC1AE2DF03B2B2527F1CF5D38C396C9534DA882A0D3CB42DCE1CD284CF4AAAED9C64BC382F352E410CE32C9AEDCDB5689FD99B3558C50051541B9142E4EEB3D2DAF611F975EF2F7D5B63BEBDE46D36F3F6C7164E218DED5E3776FDD3AEBEB75C66D5178EA6C9BB752C952562DD4843892609C84015CA36EED295B8A295EF1ABB106D50E34CFBF38E95B2B644CC3142D6592902CF60CCFC18FF548CF1B05BB1DF0EDE26CC6C96C06D46D0D9A1294E197383E18FDD372EC078DC2DB0470C9CA0F2CCF4E1FB73C45829626A9588952D52DDC4C50750D031B9B679657E8381DB72B01BA161F75B7788AE763CFB0CA376B63BF8757B536D1DBDB963763B4ACADE1C454FE11789038BDE1242758C8E473CC93A57259BF123032316A48FA994438DD3D4135ABD357789C3E2BC2CD48514EEF16003B379B77D62736B7F8737B57EC6DA1BCB9DD86D2DEA1292A09B2C1EF1C591130014807FD55B303F11F67CF425090D40EE0573A375BD4BF087DB376F613133025050A0F5620B372377E753A18D3DDB3D91DABD8BC66C702DB3C0712D93C5ACD6E26F2D71CB65D93C82B82D8521C1C43887E59D4C413CED9B3F6B49DA0B4992B1BCA228E0BF519B699C5BA662A54DC2AB75988EA0B3963DEFCCDCC7D13FF00E9CDDDBDD5EEFA37D5B697765E1B7828D9DFC05FBE8E1688B861C4385A77A119647D729AEC7E1C401F2E8080CC59CF337A172D5AC79DFC7C903E6BBA9DC84A43A8B3D407AB67A0ABC7DB058A38D86D695A5423549904C09835DCF6497C3279379C701C511F394002189BD0D4E6D1209494CCC671FAD4AC368AA8820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A4AC0319FDFAD10479C63A1F97EF4410718E87E5FBD1041C63A1F97EF44115032268823DA20828820A20828820A20828820A20828820A20860F2149716EBAFF000319402A80206797CE9057F23CFDF7BC11666D2EDADBE06C1164D1BD7D2098653E249F4CF4CBEF2C41166E05BCBB7BCBA51C630B7EC9CB8570A1C71A0DA441E104151CA4C41EC2688232C5BC9654B5A85CDA3E029224AA124663A089F97C48224ECDB61A6108B7484340A884A4400493390CB5A591FC4756EF0439ADA08457F98FA7D051045344116D62CFDD61C9BABDF716D0485A52A24F021225D24682132673F4A8ADAFB59381C217207D24BE74239E55F3D61EE130FBF346B4E01F2AF0C88EA23E367F8C3EEF77F5FC42FDA8706DC2EEA2EEF2DB775B1572A6315BAB75DCA6C6E5388B4D3AE788B6789A5F84B43807101C24419AF2EF8CFE24CBC0CE9FBD3095249F96970519BEF54D9B22CF7B18E9BB025FC94277F777BFDEAFF713715CD99983F988D9AF63EFE047ECE7B90C1B0FBFDE660ADEF076990CB2F5E5A6256F6D8A61697D438C8436F36160024F1839C8AE05B57E2999C66113882778108564697269525F3F38BD7F9094C94EEAD237B2984351ACE5BB3D63B05B19ECE9B98DDC61CD33B2DBBBD93D9BB665294B16B85E176F68F909802108004981A6624F3135C43C4BE3138A54C57CC7DE2436F56A4F17A5CEBCE23B153C4C56E041537FF1121D2332C6C34F4148CB78761B6966E8559D93F6481012C7861B291119240301433F2D35AA12F18668F9EA2CF5AF0D78039641B3A4252E6808604115078F0A173C34D5A24317167736E59BE65C711C2414AC05020F9E5E5CF2E734BE0FC512B09352952EC46741AD29AF730EF67CE5CB9A3E42D285121EE120D09B7534C985E38F7FC473D89374BBF1DD4EDA6D3B3B38D61BB6384D91BB671CB7B4659B8B95B2953A0AAE024AD45296C2046931AD778F03F8BE4CF99282144311BCE456A2DABD6B9DF9741C16D4C42657C9C42E5B28109DD35B5779ED95ABF7B3FF00F4F9EEA319D90DD0EDC63D8922E16EED0DF8B5B75BE1456EA307BFB8B702559ABDC4011F488AF68782270C6C894A0E4A8249734B86BBFEBCE39478DF1BBF3378A80037C12E1C3D1F5173D6B58FA6FC25C53962CA94C9B739A7C2524A48E131307918915DFF00662372424337D3F88E233CBCD59077812483CEBC35FB448D4942505104144105104144105104144105104144105104144105104144105104144105104144105104144108AFF31F4FA0A208A68820A20828821647E51EBF53441155104144105104144105104144105104144109ADD4B7A83F7FEC51045958D5E3172EBD69E25CA1600109308CFA798FB148ABF91F77AC109605B396885975E6C5C2559C3E0288E7CF2E9DFA56B043EC6B6770BBCB77FC4B0687829E2654CB490E056B918EA069C851046161B6DB43B3B72E30AC3EE6EF0F61442129694B5F082604640E9CBFD10465CD8DDB6B2DA6C383E8B67AC9F6F272D1E4043A0CF240CF3D7BF6AD3E60058127562D5CBBEBEB045EA8B84ADA0E942900980958856B12474E7E559F9BC55EFAC11EA882B81993F2C86BD3E7419841673C6BD7FBB41082EE1A6D6B438A08298CD4400644E46B066D0D5563EEF19170FAC6B27B4DEF217BBFDDE6337B68BF1B14BE43769855B33EF3CE1BA5FE1DD52500F11084B9C448D0024E715C8FC7BB653230D3D1F308514AB76BFC6878E7DB57AC59F64618CD505252C10DF31EE4AACC1ABAD79651AAFB8ADD4586CBECB8C7EE6DED95B7D8FAD7758962A1224B6EBAA759487A3C42B6D973848568A112057CEFF89BB7277CE9FBB354594AA856A5D99F8E94B333C5FF00012CA081421830565A1F4A371E7B09636C6C4ADB45D5CBE98042DE5F12CAB55051FF00A857E5E511E47CF3376B6297356D316CFAB539D5B36F3AC4F7D6A4212B4CB3BAE086A0193529D33AC797AAC42ED4DA0A2CF810A9F1784F8E04823DECF3FBD29862264F9A1D44DEAD7BE7C6FE56B0D44909720A9943F893F4B8B3701A449B988ADBF75B425C504A4788E895929039F6323F5A55789F978420ACB806A491E76A0E19650C66CA284155537648A015CBC9F9B690DBF1A5FF0076EADD95248E4993DB5E9DC4F5E75CD7696D5988C428254582C3E6CE79B71FCC35953D52D745117A83DFEFEEF8A37C96F60FEEFB1F6EE2D9B364E5B969D4292381497429052444199C875AED1F0C36B4F9B8BC3A43B1525EFADF4EE474CAC92316A423E62D64A88A026D4AF916D3A45C3EC57B23826C66E3367ED365F09B5C3106EB1277FA4C21A5A94F5FB8E294BE0E64A8C1EE3AD7D51F84A93370787047D44249241E3566E57E4358E61E2A9E664C9CA2B5105BE924103CF37A664C6F95AF1F80DF88657C2388832248072F8D7A525A021200D07908E7A15BCFC0FBE5CA1C5291B414410510414410510414410510414410510414410510414410510414410510414410510414410510422BFCC7D3E944114FBBFF0064FCFF006A208A8249008220FDF4A208F780F51F3FDA88214488007DEB4411ED1041441051041441051041441051047848027E5D688222DF773E7EA72E5AE7F64FC48220578797AE4BFC392C8CCEA741E7AD22AFE4608B86C5AF0841CBAFC3B9ED5AC10929775F89B801014C80380998329CE3B7DE74410CADAD6C9DF1BF1366CA8CC9E3427424E79F59E9441186DD79EC1F780EB966DF87875C2D03C240842211072190939F39FAB259AB07073228FEFF0030466C2E2AE5F6024FF4D29E254130AE2483D391F856AE753DCC10A5C5C1B40FBEA9E11C013AF3CBEFEE300AB3513C6D04446216CEDFAEDDC4ACB49852DD5494C2520193D3219498AC2D442165CD12A373A18C8B86BB86E71CE5DE862973BC6DFEFF00212E7E236536023F1E12A2AB77DCBFB70A678A4F028A1D1CF307A9915E2DF8C1E334ECEDA33F0666B315021F813DC7987E71D4FC39840BC1A5652904E6CD6377A0F74BC66FB36DBB4C2587D88E06F8901034080AE14E404649033E990EDE20F16EDC4ED09B30EF05051373435B8C87DEF16642129510033588018937ADE95EDC22590A0E202D26028498D67CFF00DD51654B0BFA88CCDC31CFAD72D1ABA43C4AC001EA78DBAF0D0BFDD839289199E83D358E5D3AF5A6D8C9D2E425449A797E32CB9D32541053BB40C439D1CE5C7335147610D56E24B9075E632EFF007DF99CCD57B158EDF96B093420D34D2D5F778D9787DE946809AD49176F74E59BC535503825E2A7B004EF2AE7526A0B7E7ED158992CA66804B549616EADEF84620F68571D4EE9F1566D64DD5CDDE1AD3694FE6295DEB685E999C952794666BD1FF0AB602D38AC3929FF00720B805AE3D7EE7A494B5A84BC8848BF3D03E9D78D236AF725B3AD6CE6C060384840496ED10EA931C2429E4A5D5748F789CFE35F55BE1360BE460E43803E8431B56DC78646B58E6FE235154D9ADFC722F4F747AF2CA33D5BBA3C24F1647A65CB21CFA0AEF4A67A5987A7BE778A6243121C1E5D6FFDD216F151D7E63F7AD6378AC104023434411ED104144105104144105104144105104144105104144105104144105104505694983AFA7EF4411E78A8EBF31FBD1041E2A3AFCC7EF441078A8EBF31FBD1045054D289F7E09E522474D3CA882105DBA97F957944E4743CBEF9E74410E59429B6D295192264D1042B44105104144105104144105104144105104144109389242BDE0001CCE9FB4D1045B57B74865478B88C4CC73FF1209F5D288225B0E75B7ED1B7384E723319E47BFC7D6932824921BDFEE32013610B2D694C8022798EC7B47C72ED4990C723CA164CA0AAD85BAB642FDCF78667124A16EB5C6DFF004C0993EF264492AEDDB23DE88DFE466DD03EB9790C83968B3711DACB1C39C2D2EEED9F79F3C286587029D0498F7933AC91F5A23030E4BBB86E5EDF87E229C130379EC42EB13C490DA997FC35DA367FE46C47BC5615A7148E1035ED35ACDC12B70AF79AD406A59DDFECDC21BCC1F2D401B17E3EF236B18BEC2036DF0B412956504F200E9941D341A77E906711FEB7C904EFBB1739F063EB0A84A481561A8F67B656A44462D78D7862DDC9487149F7E3DD94107CF5C865AE50273B1E1B63CD9F2FE605BB07202AB5C855B8D78F08748C0AE60DE410DA532D6F56EFA462FDEFEF230DDDFEC5E278D5E5C22D12AB376DED7C4586C97DE41619E19227FAAA4E633CFCAA8FE2ADB523C3B266AA7AFF008CB5B82A1FF13C5A8C73CB38525ECE5CC514A6AA494BEE976E63D75EEFA05B91B0C75DD9DBCC5B1C478DB41B497770FE2D7484AD41DB745CB8BC3F816A1C4A86149078B2E432815F24FE39F8E93B43C518932261DDDF50001D2F47A5ADEC760F0F608CBC000A71F4FF00B8D0737A57FB8D87B5BFF0D3FCB1E65E408010B526100E5993CB3CE73E95E795ED799356E54482753AB96E678826260E11EA92E03B101FB51DCE629F68B92D0165A4B4B3C4A124A939A7324C4E50454B48DAA809DD20BB5E8C7F5EB09893AB5CDC90694AB7AFE21DA4CE71A9CBBE83EB95426D19D3315BC104806C051EF42C076D7ABE486247BF6D10B70EA19B8216415023DD1911F1D7FCF6A811F3503E52F7897E94AB74A7BBBF96B4AA5697BDEEF5E9D876878D02E20B8AFE93600256E7BA8CFBFA67DF49AB16C7C3854E4AA60012487F2B3D9ED71C6ED1058993BD314A4B3E82FA656E1D58C618DE4E3981DCE2182ECE5C62568E8BBBA415B61E49092CBA858E313919194E875CB4F587C3618695370E5D0900A6EC0BFDEF566A5A12FE32D60A4BEE9A0772CEC35A8B746168DD2D9CC5ACAD3F0564CBCD5D7896D6E96FF0EA0B0809653F9A208D07F800CFD0AF00ED5C14991210264BFE2960142EC2FD0DB5E158A26D2C24CC4C954E52552824A89F9819C12599E873CED1909CC52DDB70B706404E4223300F977F9D77594B913E58989C44A0E0382A0EEC38FE69DA2AD2F662948DE4A98126A74761D34E70A22FDA5E8950F3F5FDAB55AE52003F3659A904850CBDE709CCC1290F576CEDD6D6E6444A34F23813C326674923BCEB07C865A5335E325A4B0208D41E5D3386AA96A45F26E07D8CCC0AB9099046604F0C67E5AD23331E94644962C067FF00DB6F65A1B99890ADD37E7EF5B3C788BB4A92094A927A1107EFCF3ED5A2768EF16DD20D1DC0CF8D7D2174A0AC021AB50FFD7AC565FF00FA89F3CBE84D4A4A0A58DE2CC6DEC0F7D9F3F2D4ED4ADAB4E5CFFABC79E39FFA8F89A5770EA3CFF119F92BE1DE2B4BB2341E99451B8751E7F88D770F0F7D2140A07B1FBD3AD6A43163946A43163945548AD6524D0306E756E3188A0AC0EA7CBFDD227120121879FEE0838C743F2FDEB231209018579C1092AE1093041FBFF34F512D6B48506AF4848CC67666E37F231EFE21249804C7435932D42EC1F9FE23433C26EDCF2FFF002848DE278CA122549891CC489F877A426A8CB2D4347A024D9CE7FBBD28635389A80002F9BFE3D87EB09AF1065B5842D412546005644F909FD67E94C958F4255BAA0D56AD3ADF8C60E2802C401DFB33C7AE2D2525D198ED9CE5AEA7FC548C9DD9A84ADE8A7A8346F7C6F02A7ADDC27E9362DDF87115ADA1AFE2D80095389491FDA489F818A658BC6C9C3024AD34A9721DBDF0D03830E657CC9A5820BD1A9ADBFBB738B4368F78BB23B24C2EEB68F19B1C1ED500A8DCDFDC22DD8000CC95ACE83E755D9FE2BC2C956EA88E7A51DCFBCE26B0DB1717894BA10A3C0073D83FAE91A6BBD8FE257ECB5BA7656E621BC1C171E75BE20BB3C0713B3B9B90A4EA0A14AD7B76A64BF1C60104825D9EA18DBF7C62CF80F87DB631D284C4A02378D1330282868E32D7567D239FBB45FC797D98ED31FBD6AD30ADB7B9B7B72800DBB366B4AF2FED21C00F383A66075A8099F14B672715FE36ED49005BAE74EB6E313137E16ED3C3E1FE74E22953BBBCDAE9D39C7537D943DAB3653DA8F77184EF2F636C318B3C1B17F185B5BE2CDB68BB3E03A5959525B5149F7812209C88E8455EB656DC95B51095CAA6F65C3D7AE6C639FED4D953366A9495D4A0B1777ED973D637090EF124129209131D3E3156058280F43C8F2E1C620D13378B311A93D721CA2AE31D0FCBF7A13F53366FE4FF0088557F43BE515020891410D431AA54141C47B446D051041441051041441051041441142E214329313D4FEBA510441DD61FE31396B3A67F5FBE7144116EDC58E2ED38A45BBFE1B00FBA9E25089CCCC69D75FA524B51721E9EEFEF9DA1E61D28287500E4E6389F7588F5D9ED01822E675CF8D47D7335A43A094E4057AFAFB31430E5C38DDED93E034FA1290BBB57BA973881885E731FBF9D101166715CBFA3D85333990D706D8FC2BDDBEB809BABB0A2A4B8785680AE23A1226040D3A40E704614486622D576F6E7215B68F1925A49084050485240108D0002123E1197A695AE331625C929CCD88E4D41C751DA18CD413535009B8F3F261AF011497614467AFA76EBEB1FE6AA5225AE662F780533DCD337FA587BB57368AC48954CC137F74A9A30A5E18E236D6D76DF84B212E6AD9D0A888309D27400E7CE3A55F25E32660A56F95B0082F91A248CFC9F4E912180C7294A00541B8CDB3CCB665EA0718E597B6FBB8CEF0369B61B73F845CB96CFE2578B7AE54CAD4996EC1D6AEA1C89905082065067400D78CFE37F8C4A7FC994164B058A13620F117BBD0718E9BB0F65CA9F2862124013189529A841D73FBD3AE68C1997B05B7B2B266D90CDADAD95A5B97B87852A71A61B69C515692541473CABE5CF8C14ADA3B5E762007056A2146B43E77A791D22FF00224A30F2848241DD01F7454BD6A1D988E2ED17336DA5E22E3C443EB4E7C2D90A333066333D32CE67CAAB08D9EA2E40A92CCDCAD46EFC808C198949284A4A121C1DEE232F4EBAC4DDBCBCDA5650A6C1905247BC08CB31F4CCCF5A7A8C1AA8198B54E8F95B8356D0D17300A3D4E6FF007FEB38916DAFFAC18D32FD33F5FF0074E656CF35A10491522CFE8D5E5943698BDEFF00711A9B69FD311C231A6F0F0ADA2C5ECD769B397D84D95E70C071E756DDD024E454532476CF41CB28901B004C4098CE74B922D50DEEA79624CC095AC12B3BCC5CD5218656E02B7C8EB801BDC96F571869C631BDBCC5ED5974903F95624F200049309E21D08E5CA9038656115BCCDBACC2D6ADBCBED1BAD6925560750CF4008E397DE2DC77D8FF000A7AF6CEEEEF6EB789738C30B5AFC7388A576FC64CA4A5447140F9721573D81E2B56CD5A1456A1BA430701BCF26A1E1A1AC7CC595294459C5412E4B74D2FECE44C1F731BCDD97BD373856DF628B602006138B624F129012520980069198CF5EF5DCB60FC619D8308099EB1BBA28F0E34F40618CF4A672548504AD2F621C3F1D4E5700DE2FDC3B6977D9B1CD2157ED5BED132C294A5DD3097EE94F02660AC91309CBB1CB4ABCC8FFA81DA4852509C5CD01C0AACB3578E435111337092C277004A5811BA96043BD59BF558C93B37ED2EC17136DB4BB3D88583A212A58B50D3614041CD674CE672EF5D0B617C73C562952D33F124A54D5DE27CCAABA1CF38839FB28B1DC52C924B6F3B6B4D2FAE7D6335601BD0D8DC7941FB6C79AB37DC88B4B9B94204CE49080499EBD08EE4D773F0F7C42C163928F99392EA6FE4A0D5B9A97B674BE510D88C0CD4072016D3F96879F6ABF01191BC67EF5B4B8976DD76CE094BF6EA2551CD5C432939673E75D7765EDAD91884A54B992882D5DE490F9558F971A8688C560D2545D2CACF7A84B016CE8C5BD6CF5B6E069210DBA5D4670E2D4173D4714C64646556F9123093A5A66A11294156290922F46A3380CED9C2C896508B330ADC96FC5AD9C48B6E92331946503AFAC79D23895A70E92D714DD1DA83DDE82125ACB543317E3C21D0526341E801FAD468DA254A6097E3EC7BEF0D97308B5341FD7E5BEF5A4A4E994F2FF1A7C3D69F4A9E99A2B43D9E9E46F639776EA9CB0ECAAD3A67D7CEF0BA220693F3D4D616A4A5443B935157E37FECEB0A4B51525D5724FDA2BA44A4ADFF00AE83DF38DE102412634FDB2AD7FC71C3CBFF00D608F2B230E9F607EA086EE708566067CC810329FBEF4BFCEF94022CD4B1AB572311B389DF60F6C8FD87BBC15A1C600F9B5873BD1F58525CBF983EA4D746A5CEA0E82185F3B656ADA5E7DC5214A39F86614A8319CC4C1C8672396B934993D0B503BC1D4ED5CBA16032275A43D95B3D730EE84D732065760CF907A88B3B6AB6DF65765B0F5631B478BE1985E18D214A55C620FA185A40199E224267BEBEA29B4C9725492A2536A03F661EEB4687B2B62CC98BDD32D4496FA98EEE84BF06FEE3955BFDFE30BECABB8BBCC5B0D6B68713DB3C5EC12529B2D9BBAB3BF4F8A50A29496F8C2A01D408CB903542DB3E3093B2E62B0C998A0A4B8A1A6BA81AFA3DA3A36C5F00E37192913552A57C823EA0C77EA28D6F4E85A388DBECFE3CBBECDBBBEBAB7DD3ECF613B3D8195AD2D398EDB3F6D8B96E4F0AB89973878C8CE4643280245738DA9E3D54C27FD4357ABE5C6B9D2F46D6B16AC3FC3D129BFD206B761992DCACDDDDDA39D3B6FED7FED39BF5C5311B8DA3DE66276F86DD70F16096D8B5DA18680490B4B76EB51090A1DF3CA6A8B8CF15AE62C8DF24AAF527EFE4CDCDA2EDB23C1C990A4112D346B8C9EE28FE51AE78DE39676ADDDA71AFC6DFE22B0A3F88BA8778972493C4A20E67BF3CA342C7FEFAB50BDE97AD69E9E51D4B65EC544B4005291BA34A59CF6EFC811185B0E606278AF05B3AB37B8B62D85DA35689325297EF1A60C379900A57396A290C0C85E2F69267392EA15A117EFADC6B5884F154E461A42E582032482006B7E473CB468FD14FF8766E72DF72BECB3BB4C19C6CA2EEDB0D174F248851388F8770272CC8F167EF2F5578370DB9869273600EB517E793B5695BC7913C598BF9B8BC44B3FED53825994F577E047D9AE23A1A93C494ABA807E226AFF882529000A65C6CFE6DECC52B0F55BDCB9278302DE7CFD60041CC5664972068FE6F0E27D52DA8EB710B2343E7FA0AD95FC8F3F4A42328302346FBC57588560A20828820A20828820A2082882122851513208310348A208560741969DA8821A3D6C1C515152B38C81D0F68A457FC8FBFBE9CB942B2E66ED353E5EDF586CAB04ABFB9D1EA63F4CFBD6B0B7CEA30207FFEA9F6880C6F6751895A1B66DE76DD6A20975A5702D4279A867A081D46BD0119130D492492D9E598EDCF8C2D85E088C330F45936FBCE2923375C502B3273CF4D39FA5119F99CDBEF639B5BEF12008B5050AF154948F796BCC99EA7A74E7F5A467618CF0031700B3FE3DF2816A0A41248B331390B505B87DEB152805A4B8D9E21049CE4E43B4F4FBD4AB84C0224A82D4056B517A93C3AF663157C6EF952B75EFA114390A7363722ED68B7AFEE12DADBBEB8712D34C3370E34851E152FC36D456540C03F964768CC542F8A368CAC360E67D607D2A6FA99AE3CECF9D4D6253634A9C54860E094B8625DCB1CB4C9BCAFC45DB7F691D911ED23B53798B0BA7F15C11E6ADF675868A14AE37982D5C00951E3954641199244D7CE8F8C38D9D8A9F88521649758BD0D59A8C19B2B47A5BC298290AC1CB92B037581340E480F9687BE5568CBB84E39BDDDBE71972C1BB6C1B01BA585316F8925E63134B6A5492EA40291C5AA0E85275E55E47C46CE54D9A4A85779553EEAF52D121B5548978829960519D839A00D5152D4BF03C636D763765EFB02C350BC42E7F1576A4F12E1456DF144C0E283049F5035AC4BD937FA43BB00C41E449B0CBCEEF15F9B8A2A59417E2A0EDA70635ED98117AB16AFDC3697941A41512385220009240D27BCF7A7C8D904B7D15F27F2D7422838C3533C2014825441B90E7BBB43D459B89E69D3BCFDFCB4D29C276492A622DC1802296B1E6FCDE105621F3B59957E6FF88A6E703B2B8683A96909BC2656EC09510444919E42227A6B06A625E125CA921012A2B63BD620F07F7D2F088C5CC44C505281416DDB922D723956A5853587B6B87B4D33C0F296A580608323CB965AC79F28A86C5ECD4CEDE0DF5170187BFED9A8F189B899A4FD0CC4DCDDB872D3CE133873438D456E05E5C1044089D3991D79C54327C3938A8B254483F4BDABC72A5A03314A29DD2376CAD6DCB3E6C6D94242DDF7521170195849212482441EB3D80F86752786F0E63A852086B81A5FD321F78DBE9DD26CAE19F3A738F51645B5296979CE1207FF001B8A2D8408C91DF9FC69E0D97324ABFD451749FE24E79F115AB7A65A6EA492E91FFCC456B98BDBADE2DCC67671389A148FE578392ACBC47191C7E64C6BDC472EE2A57098F5E09492950013A65DAB95C1343586EAC3862417E7DA8C29EF40D8C712DCEE1D8CAD6CAEFD5835E364290E614E861614731275FDEAD381F8838BC090113961233DE37EED969DEB0CE6E0D2B2494D6AECDE85F864F9E822350FEF4F7560376589BB8FE12DCC26F9E7AE6E3806790100E444E9A4559F0DF1AF6AC8094A71539280400CB56B5CC0E43BC319BB39054E101CEA32BE84B7F6D431943607DA57673137D9C07692CAF301C552AE05DCDF368B6B0796A248F016A32ACC00ACBF3111DFD31E02FF00A81F9B80932313892576FAD7516E24F13DEAF1058BC1A82D4121806B51DF2F57A74A46D2DA6236D72C22E18790EB0B48521E4AB89B5057BC08568723967CF4CEBD0FB07C6B276F041F9A0EFB31DE70FA82E5F87488C9B2181A392E0822BCDAFCC5697687CBC4ADEDDA6D450B794A2470B602940CEA474CB289D0E95D43038144E4158DD60017C8BE64B1D73636BDE21E6A56926967C891CBD3BD9E1F255C680E04A803FDA47BC34D47DFC6955484CA528A4BB1CAC4559BBDA90C26129C8F4BBBD843A654481FF975D79C5472D6EB22AE0DC9B30CBB7087D20BCB079FDA14592001D67EFF004A7A9237732D702F5261588EB8BC0C29280CBAE951CFC34C84CF33F7D69CA64EF237F7D22B626A5DEDC9ABFAAE5AD6AF71CE2BB8B945BB5E32C1298931A8F3F2CE7A4674829494920A998B7AFE3DD1F1112DE356F72B73C169D5A1A897801C19CFF74F633D0014B8952E6A77C9497147A9A3BF2F4F386C70AA98A4B7FB89B7DF367E50C76876B304D9AC02F369318C42DAC308B0656F5D5E5C3A96D96508924ADC3EEA6025524FC63484C7997252A5EF064BB817BD1AAC28EE747B9896C1E109989941277CEB6D79E8DA18E0A7B647F1CEF672DCD59639836EF71DC376DF6B6C92F31F87B4B9B5C46D9BB8014801286DC0B052A1EF4E7293A72A26D3DBF2F0FBDBA40A666CC2E3D0E61FBDE3666C45AD43E67D24336E50915BE7406C3A068F93CF690FE27DED2DED3D8CE22FBDB71896CA6CB3AEB9E1E0985E217564A530A51848B7E2289E18303204F3CEA958CF1B1438334B00400154CF5E83BC5E70BB092129FA0BB8A33E62BC41D7D19E352F655AC731FC4978B5C620ABB2FAB897738B3CA73117540FBE5F5E739E692732233E75CAF6FED39FB4710A9A851AB9727D2B5E14A748EDFE1CC148938044B28E7415E56B1E3EB4CDE19526DA54DD895369F79C00F1E594827B0FBE74E9F2F12A7FA946A6AEFEC657CF8C4E2A4E140277464C186B5CFDD1A14C3F6999B26CA584DB32FE61C7D43856E6A004A844C4C08EDD2929180C44D58241041CDF3CE95EC38E51A7CF91203A4806BCCB52C33AE6D912F18537938DCADEC41CBCC482585202DA65CCD7C6A480509332003249D055830BB1672EAAE14A6BD73CB8D5E31FF7C932412E2C74A30CEB95697A56CD1D0DFE14FECC175ED3FBFCC3EE2DEDAE2F3677642F70FBCC5D7768E34BC55C0FB019500524A16DFBFC530418ED7CF0F6C55267CB74BD45817A5DB8654D699C722F1A6DE42BE6913004905892181A80E6CD501AEF5CA3F431D9BB0B7C1306C2B08B56C2AC6DAC2CAD136CD2415B26D5869A1EE400904A24EA20798AF49F8730624C8410186EB579598F1F5B078F2FEDCC519939656A054544BA5D98BEEB74A3BDB52232234A3E1254A82607E5F8019F3EB53D8B6000E7EA3F0623F0409054482C00A5AAEDE5F8E752223D73AD30EFBC092F42DFDFB6873882C87F7710E11A1F3FD052CAFE479FAD611945C13AB7DE2BAC42B0510414410510414410510414410510414410520A0CA3EF8FDE082B10422AFCC7EF9511973A9EF14D106F1D4F7860DF8CAB8BA4BE10AB684F8204951CA4F148826748F2E735A9C5A650751B02CEE7EF4E7A16778C09BBC580AE84063EEC6A6F9443629B4786601875DDF62453656B6E852CADD86D30013CFDDE5CCF6D74AE6D7F1548C14A51DE09DD06AFA5433177763D69430FB0FB3158B50F9680ADE672059B57CCD581E2F1CDFDE56FCB787BC1C6F12D9DDCD5ADB5CD98E3B5BDC5313438BB669B7125B51C35E6090161255C53202C0D6BCD7E36F89328A66CB137250A9B5C3DF507A3F38B860362FF008DB8A5218674B659B50DC509AE9168EEABD92F6236318BDDB2DA2B21B57B758E3CDBF7CFED0A1ABDFC1BC1D24FF2F2A4F88D8014A8933091E9E5CF106D795B5A6AD5BDBEE54595506E0E64D281B325A2ED85DA3FE1CB32FE61960060A0A62E1A879E7964CF1B9B63B1D86E1B6ACB8C3447B89290E2471A724FBA3A246881D001CEB9D62B664B52F7D018073614CAA3EEF4E108AB6B4DC54D50984153B1527302C78DB8005DC9891B64F128B440E10787CA63491A7AD272F67241FE2031B8041200E55E34EC0C6AB98A0EA2C5DCDC9E1C3BF9522585B86FDC48303CB9E7AE9F3A792F673D5A8C031D682DD1BF30C264E5283871AB0A9B0B547BEE785D95F0FF0014ED1B2C33EEB16CC1AF260DD4F7D10F9A599D479B7A8CA3D09E1CB3F5D6994EC0284C6018756BFBB423F3EBE66833D6BEF8C7B4A48D9C1C2D6064F47BD6AFAE5C7BC3844DDE00062D71E9D385E8D14139E5F993981C8CC4FCBECD4EC8D9F86491BC9191B015E7D87EACE12A041191BEB476EFCA1322091D3F6A974C9C24B05928A248A00F6CBEF0B82E1EC4E9CCC56940201CF3CBD7A695CBFC452A69C72CE1DFE5BB0DD2D95CF3F57845530A0EED2F753D7367D6A2CF9F5ABC2ECAF87F8A869783C44C0CA4AAA2D56E1771F9B88D7E6162412599EA73D397210C8E0F6C1F55F2DD5071504A240D073CA7A7E9DDEA36229406FA40725BE9E37CB3BB346BF31CB6EA8F162C6D639F56D213B976D5D4969DB64BE902389490A1D33F3D3F4CA96FFD3A08344922D720F4AD9C3F93C6C4004A98BF07E568B2368762764F69EC97677383376D7290A2DE24DB084396EB2642D0F1CD241CE6397A544213B4B66E387C952D3292A0480481A5851E95D7267845782DF3BE405050240CCE7A54B861E4D5318B707B4DE4EEAEF14EE0B8CBDB5FB3A544B96F7AFBB7CE5AB4924F0A12004208048E7A67CABD2BF0F7E224ED9864A67E216D2F75C1516AF33F8FC4362B6703FC5212EE2A08347B7EFD2367776BBE2D99DB05A70D52D16F8C3502E2D5CE04A90E1904044950CC73123E75ED1F097C58C163254A926783BC00502A1C19EAD6627D728ADE3302B1FC523743B8CEB9E56CE8391158CEC16A2DAA0057BA4A38648D32E5F0D632CABB16076A4ADA32C2A52810A17497EB47CFF262066E1EA686DA6432D0713C4F111E58ADCF0506E3DD72552279126358E47965D28988DD9B7725C9D052312D3BA902DC0C3C52D2A882329D48EDDE9FCB4921C0BFB17FB7DE3788F7D01FE34F8A5942735ADB3C2B3D33CF29D7D7AE44E9A99128953BB6593E5EEEEF187AFA9C873310B718B58D95A3A1E778AD5A0A2EDD5C94964093C456BD00027B0EF3548DA9B6C4B593BE46ED6FD43D6B5D736BB53748ABDF22E282A19B9F7BE4CDC7DF6F5FE2F5ECE3EC4D86E202E2FAEB6C36B196969B6D9ED9272D2FCA6E4A6129BEB6E30B0952C8200CE388C659D77FF5FE1E4A861953909995AA94C2E5DFCEE6D5368B56CED96AC44B44C4A014577C815625830B39B13C0B111F15FEDC3FC6A3DA8BDAF710BDC3F0AC7F1DDD06C3DE3AEB565846097379818BDB75A8A529C4184AD4DB9C42240CB356550FB43C609C4AD72E4CC1398FD664AB791517D0EA7AE6C22D5B3F634A97BBF4925FF92C7D4FABF0A7ADA395F84E078DDE622EE33893ABC531ABA597AF2EC294F5ABE552A0E070C2D4B20F12C9D5649E66A83B4F689C5297F2D4ADD36DEFE56620E82EDCFA8BF6CDD9E12120A4134AD08EA7FAD38C648C31FB5FC4A18BF47E19F1C291E100949E44C9CF21F03C8553B1180C5CF5B82ADD7767367D2FEA783C5BB0F864A775EC187D5567B90E07F4C4466CD96B816F72B6997896C04F01E29CF84731D3C8FD625709B2CA640F989753177048F57B171CF361163C2E21725210927746552D7FEE9F78C86E5F3C2D5E01D3F96667E1AC1EFA7956B330528120A6A08CA9D72E17ABD61EAB10B2C9049CCD781E6F4BDDCE6498C4B88E32BB40E3B7971E1B685136E4AA38D45449199CFDECB2F8D2B230B2CCC0C81CC0A3D05B3BD39C44E3A74C092A06CEC3837524FEA31DE39B4F717EB16CB42DFBABC7ED6CEC6D900A94FB974EA18494A355105C4E911CB4AB56170B2804B804532041AFDF2EFC22998EC64E439DE51BBD4B0FEAF957B1FBF2FE04FEC896DB81F662C136DB1FC33836D36C6D85D622A5B205D34D78CA72D64A93E20059746BC87202AFFB0B67A4AD13129B33306BD1B3399A76BC71DF166D19931464A95F4AB789075150D503DF48EEFD95BDBB3C4A67371E990A8CB52223489CF90E935D87038712B0E80C599C96BB0CDA81B839EB1C7F1B89F9B3D8549D7514AFB01CDA25D8694D3010A571112A999D4F144F3A6D8E98CB1734A0FBD876BB44A6046ECB2090E58D0713FAF6F0A224054093965EA6B6C2972391F407EF0A62BF80E7F88748D0F9FE829C29DCB97E36CA1293FC7B7A98AEB585A0A20828820A20828820A20828820A208283404E90426A58989223A18EDA73CF2D4532F9DF327096902B4734F7CCFEA36092438F7EEDFA8A38D3A052893DFA7953B54ADD04BDBDE43DE51A2F7902A070ABF93088C77114A2E0B1E138B331C604A64C6A67BC9903F5AAE62B6D4AC24C3294952C82CFCDDB3CF2BF384C6F28D378F04F36F7ECC2AE5DB698E24AF212A29CF834FCC7ECF6A98D9D306D097BE92CE1C0A7637F6F0BA70EB51DDDE21C3B17B67A03FDDE2DEC5B1FB3C3ADAE31572ED962C2C5B5B972FBEB096CA5292612AD388C10419CFA662A9DE2CC6AF65AD692ADD090A2429B9D5FCBABB185E56CC9BF3A51049269BA5DDBB5732281E39D9B7BBC0DADF687DA0B8D99D8470586C8D83AA6713C56E54B698B86C9215E0BED92DAA0A5691235307531E55F1E7C424C84CE97BE428053170C2F6FC9B9E317DD9721184402A439A1500DBC454D985B36343934664DDE6EC300D8AC0DAC330C75C200972FDA523F10F3AA3C4E9538912A4F19504C9FCA44F39F246DEF16CFDA78B5844C56E952AA0F13C69976062C93B169284FCA4A0518850147A061C5F57A5728C9E30D65B4B4D332EA1325C5BF9BB394709D067DE72CA29FEC3D978AC6292BDF25370E4BD6EFC2B50D4E358AFE2FE6CC7650E0C580CDECF7A1C83EB0ED4DDC7861A4B9C484880567DE8E84F6E5F0EF52F8AD97364CCDC25E81C1BBD6C19A86F0E30A7E5206F01BCEE5FF007EF46786ECD9B8DAB889124C920F3EBA09FF0011148A700C5C8F2ADED63966E4DEA61D2A7053B9150D70C29CF5FCF08921319EB4ED18548CB93DFD0FBE10D94B2682803DA84F33EC426A7529E44CF97EF4B09433096E03F50814A8DC8E4E5BD228E20A923E741C3CA374BF36FC424A9449AEF1E469D29482B53874D40602CD6B743E50B4A0524124B747A0A353D6E1F8414DE648985B74D9E9563A519BD5A1E226240AB5793F23584CA0924E59F9D47CEC1E35544CD2903FF2229470DC7CFAC2E89D2C2402AB727EB0BA084240CCFC2B28C3C84A00C44BDE99A90E686B535F2E1C6194F52A62DC1000E3F703EE62AE31D0FCBF7A5449C2972896906C1C0A33F0A75E9946A14A600914CC67A450596DC254B52E0C6423C8EBCFE548AB0C924EEFF10EDD790A6679E90A198A09A11BC727A0E2457850FEA02C3491FD3409FF00CB9F63CB23CFE1DD33849AFF004EF30E0587DE83EF78513369F536562D6A171DC8E6D10EFD95C5C38A0F381A6103DC4B248F132829781FCC397918D66965E0F0870FBB3100CD62E480E789CDAB6E22F487D2F1084A494BA89762AB26AC4A4D18B1B0CF85DAB9625F49B77382CAD888526C00429D11FF00ED1A2A7B81A9EB3542DA88C5E1967FC75196905C6E929B170E539DB33D2D0D66265B28A54A528D5D4D47B80EEC0BF105DAA5846BD6DF6EFF0013B1C5DCC6F76C9561F8F2B85C78DC4B56F745B0090C168712D5C20F10CFDE396822C7E11F1963F6762A4A66E21659401FA8B1008096CC9D72D6EF11388C2198414335406E3776D0D99B3E117EEE67DA770EBCC753BACDB65BB85EDCB29F089BC29658B85841582C970F88B052019E73CF9FD00F85FF001230F3244846217BCA5000B9A1714BD620315B266B19A94B807EA09FE4C7986A3871F88DCAB3BE57876C8BA520BCFF00190B41FE9848CD3AF2298CF31CE73AF4361F684ADA4533A5325243E42841E26BD74CAB159C4A55266143021E87D5DBD323A3C4938BE00550549001E2198331A7589135609612100EF2599C97146615BF6CEB1B4997F3684B1CF2D5A87F3EA230E6F3B7C5B2BBA7C32E718DA3BD69087504B5685C407AE1491010CA164712B888100EA467A550BC5BE26C26C991314B9A93BA0E632E9A8BC4A61F644D99BA405104DF235BF12CD4EACD6E6E6DB6F5F7E5ED28B7F01DDFE16BD87D81794B6EE318BF62E30EBEB8609502BB47DA25B59D609C80226BC87E34F8E7B3F674C9C962A3501B758F98EED46A71964786310A620B39760F605F95A3125A7F0C1F673C69C462FBC5C2DEDBFDA0716A7AEF10DA466D71271F7D47895C4E3A9E25210A242330427872E9C2B1DF154ED19AAC6C898B421C90016A0241602D6F4A5CC741D8FB31586C3225A92193725EBE55E74FCE16F685FE0B9ECADBE0D9C7ED304D9AB6D95C69B6949B17B0AB4B3B2610B2212A5292D9500204C09E94B6CBF8B0654C08F9AB05446F1DEB9763636A1AF4CA9328F9685329296A1147B54BD28F947C9E7B6CFF000F9DE87B186DE5CE0B7B762EF615E717FCA719B65BAE043613C4A4DD5C1425B1EF282120089D6BB3F87BC6183DA625283998AAAC16297C99ECF9F6033899C16365A5410C2AD6CA8D90FBDED1A02EB88B0B979448BC55B94153AB1C725794A5594C48E233D72E47AE6CE99849884A952D2491A034EA4F5A18B4E16626687B0CDC50F56C88CCD416ADA2ECC27690D9DDAD65695A161247826502139807491306329EB90AD316100ABE52581B5393861CE1D89E25CCE160722E2D5BD74EF172DCEF01BB7B7712B0F12A040800807389CF4FF0476859A852890189CAB53517BFBBE50E918E949014402CF7FC57BB4611DAADA6B9C6826C9A2E361A2B5B4B54849CF8B32390233D2233E54F307B3E6CC50AD1FB1F5AFDDF9C56D1DAD21285380287477ADC5AF9DA3AA7FC1DFD86B6EFDB13DA576371EC730A69EDD76C2DE1BADA2BDB961C55B5F29482E590B470A4B2E16DF6929702A20E99D5CB67F87F1535490154A67F4B1E5996A5F80731CDB6B788B0F21330A81234003F02DA0ED4BC7E93FB01B1D65B21B278760382DA37656F63676F66D5B9406DB422D9B43321090350991020FAD752D8BB25785968DE7269BD5156F2E39FDA38C6DDC71C74F5A83115DD29A5C017D403C8DE2EE4E1A5B750B4A885092449E193398112739CFD7CAEE89E94CB32C83BA02402C09D58EB9FF4E6291330330CD0B05AEF52280B0E41FCF8C4A21B73800594F144652447EFE597D2A33152CCC5BA012D6BF12D5FDB651338649948017FC99A99313CAF7AD7BC7A968A673067EFF7ACC80659FA816B5AB61A429387CC4B0A177ADBCBF10AA41020F5FDA9C13BC49D75ED09CB414062DD3A9FBC55588520A20828820A20828820A20828820A2082B06C73A1A6B04357092A910620C73F874D29B09252AF9C4589ED773A7E381261647F11D7D63DE11911023CB39FF13E5F0A5D33E5CC05233A000F31521EA74E7570F084EDEAB351AEF4B5BEF0D9684A5D04244281E3312721967F4CBD73A85C76C413D66600924D4D3215AD037BAB08DA4122C0F3AB7E351AF1CA20EEAE59B017F7D7AF34D61E96C952D6A00200499CC809198EDE672A8A3B5E46C1428CD584A520D5C0667E79BFA8689297294A28009330FF001EBAF0229F6BC6816DDE37B53BE6DA4BCD8DD8CBA5586C660EF70E23888716DA71343A78D6961D6E5B7BC35052083A695E6AF88BF12E562F1D3A5A673B3815A160455F419F48B860F0DBA8131613F31817D1A819EA1F3F3E394763B63B03D89C359C23006529B27004DF82948B953B3EF28F04020B854A93CB3CEBCAFE2BDA29DA6B9A42C2829F37B917B8E033B7030FC214CE48278753F8148C8ED5A316484DBDB28ADA4E609226559A81390C8935CC8ECCF95882A6DE0083BC03839973D79035B4094A941C8097CB870A690FDBE7E93F7F1E9F3CBA06C4C6A70410924815AD038617FB76D633B8751E7F8852A4F138BFF2166685120B541AE9C1ABEE820DC3A8F3FC414D44D39953F03FB8370EA3CFF108B8E70923E9AF2EF59F9BC55DFF0070141CABEF8C3271D83E5FE34CFE347CDFFE6E35FDF383715C3BDFDF1685DA3C4DA4F6F8E7AD1F37FF009BBFEE0DC5708528F9BC55DFF706E1D479FE20A3E6F1577FDC1B8751E7F8828F9BC55EFAC1B8751E7F88294FF10CE0666EBD9BD34A59E33F2D46CC7BFE20AD0E1021C6E8074A7DC463E5A8E9E7F88A82E0465975EF9F5A6EBFA32A644501F7CA32259259C41E2F74FC7FCD22AC484D013C2B4E8CFDED18F96751EB0D1D77357D807383DF5FA0CE9A2A7059D586AF5E27DFE5D252C18A401714D5DFA8B70866E3A0F383CE35D3CCFE9F3AACED762853598DF3A12FFA6D2B19DC4B73E6F4E74AF0885C55FB8B1B471F48438FDC148C3CAA55E004901DE23FD9C40F2CA35E754A933D3227A565552A1BB57DD635DE177E0F58D0A415802C9BB1707EE465FD574CB7FBB977B6B311B0DE56C95D2F0FDBBD970ABFBD5DAB85A4DE21094B81B940F11CFE8B452412012632D0FA3BE1EF88132848054CC520DAC14053A1F79EDBA4EF02DBA5D801A86AF2BFDF4CA7ECA3ED9580EF81DC4365B1B4230BDACC0128B4C42D710E06431F854A9B2E942945690E2195384919EBA1AF7DF8476DE1BFEC72F10A9B2C112E84A9896B76AD3D9A86D2D8E573153132D4402EC915AB87000635ADE9D1E28DF57B746CDE07B46E6ED776CEB7B59B5C54AB774618A45EB36CEA9328F13C1571A0093AE723C85517C63F1651B2513512E781BBBC1D2AF3BF00F916BDA37C16C73F4AD482294045B982F4EAD666B0C3381EEA76FB7938B33B59BE4BC7EED9B858B8B4D9F4ADD5DB59A490A48FC2BE084710E052A3533E55E57F15FC6156D33364AA7A95BCE03ADF5E3DC5338B461309B80580160010389CB8D73E31B8786E0D6186616C5934A4D859DAB6136D676E435200192DB040CE01CB339EB9D712DA32D1B794B9AB65397AD49AFF006FD2A1844DA48410000F99E7906F74D6B0AA5CF1471F006C49012040001C8C752209EB3355AC561938196A909002402E05B33E67DDE25E52B725303900C59DBF157CBA45550D253B93D243B3827A0E99FE61B2D2E4B8A5DFDE6FEDA39EFF00C4A7D97704F692F672DA8C1C5AB08DA0C3B0DB8BDB1BB0848B91F850BBA7385C82B1286B87DD1A6B3CFBD7823692652A424A9882C43B5A9A9B74C83DA16C0CB22728B9214CDA0028D90ADCF334D7F3D2DA1B16B66715BAC19E654F39657F8A58DDF12415715A3EEB08E2D39B79157975AF56F87B1699F2905C10522CF980DE6743ADDE2EB83514802AC59C727AF95A95B8D71F5962096C9466985AE12A1060A89032D321979CCD58A724A8D29C6CF4D58F935844899617F5172DDBDE66FDA14C4F1305B3067DD33DFD674CBFDCE68230CEA0A22B5BE872A0ABD33E30D27912D0541419BF8E46BA017E59579C3EC5ECD637BC4DB7C1361F044ADEC5F6A313B2B2C25A6B894A2872E1A6AE8F0A7DEF75B70A8C010019D60D8F676155BE9A549C85068F6E428FC294A36D9C7A50140920006FCBEFA77148FD383F8597B1BE13EC77ECE9B05B0C8B060ED462F8622FB687130DA7F101C7D28BC612E3BC216327783DFE4234AE95B2E514A529003D1DF2FD373BD9C57906D6DA2899355F52884BD07F153BBB9CC69CDA3AE167C66DDBF10242C0293C208100C0D7392209E5D2AE5202826B66D69937DF93C5594ADF2540B82491571D21D4099813D79D388D60A20828820A20828820A20828820A20828820A20828820263A9F2D68820A208681242C922049F9CFCFEF9D656DF254FA1EEE47DE164FF0011D7D4C567E3E550924B4D014480E737E3DDBBC22BFA9DB36F2688176E1F55EBD6ADA92D9F7787C6301C912A2D811300E7940F2CEAC7326E1E561D3316A0FB8A26A0E54DE7ECFAE90E64A52900A92E4359F8B3DE8DD41D234AFDA1B6F71CC5F6AF07DD46C4DD326E6E14E8DA4BAE35163096F843ADA6F548CD83728E24B1C63DF30398AF1E7C61F180C11C4A24CE228AA24B53BBFF0064F3B3ECBC3A66A1334A46F1D722096637D3B9CE2736476551B35875AE1F62B0CB366994BAD9097EF1E7614F9BB23FE44870A8B71A24E7CABE7EF883C6B88C4ED25FFAAA037D55735726E5FCE9468B44A9094824951DE1549341C86BC7F4D7BDBDA9171F8D7084BCAC94D23FE088E1E2819F16A74D49CA9CECFDA7FE531592A7D59BAFDC5BB88544B480C09E04D48FB7944BF0210785B2A299C8AE264EBA72074ED560DD9653BC012E1CE84578D630941DD01443825C8170F4F7E50F112013AF413D35CBE039D454FC52A52BE82522CC29AE9A91ED8C6CA4A697D037BE66292F2418827AE83FC7C2A57058B2A940A8DF2068393D89CF3F383743DBCB9D9F9E547F2F3C71FF0053F114F3FCA1A9FF00EA1F98CB0D07610D5E738946011A73CF4E51F7AD63FC9FFC8F71F9BF970818683B0868A4A892441E809F43C88158189FFCBCC77B8F7DE061A0EC21E30785B4854939CC79D60E24E4AF31FB818683B08578C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDEB2312A71F5663307C9AB06E8D076838C743F2FDEADB809C9387493BA685F9F11ECB528C6022C0123967941C63A1F97EF49E216835052189766AF36CEF7FEF0520906CC5E99F384D464935018A9EC0A4101AC469F7AFE348374053F0B69C63CA839B88DDB9AE8F977AFBA5E009038F3860FBC12E2926728CB91CBCFB7DE74CD38B4998C0DC970FC082E01F3B5DCE65D210E12EC4077198734CA9C61929C2A39653AF2F84534C7A3E64B531269C686BAE66F67E758DCCA4BBE438777A57852FE69BC8B552136F745D26F012DAD59A590DE64B44FE52ACE48D4F3E55CE31E172E7024167B8B38201E1957D18423F2C6FB8FF0069B0A9BFFB9BA37DE2DABA4E1D86B57CFADD0E61CCB4BFC5BBC414E94290A1FD654C70415083309ABEF8576A2E4197F591BAC6F6CEE39726B17221432986E9DD0A361CAA47366CC671C32DB0DD66DAEF1FDADF15B9DC762EC6CAECD38FA5ADAAC4F0E7DCB26EF90E5B1427F00F5B8E071C6E5C4BBC792579098AF42E07E2A1C0ECC18233C83BAC06F3573ADF2D39BD225A4E065AA4EF280B5185DEEE286ECC0F6CE3A59B89F642DDFEE52EF15DA0B172EB6A76BF1816EEDE62DB49E15E3EC3C904BAAB67C00E264A9404C9223A5722F1778AB13B5D530A6728EF12CCA26F77AB7A733708CCC2A0252120005DC9A10D5191CEF9F1AD36DF8906D92C3656B0911E33F9BE0F31C407E549C9234E181A571BC527186715EFAF77789724EAE6E5A909A30CA4555BAE1FE94BB372233B9191B3188F71588A53E0B2CD93CD2A789DB9054F0067349D01CE0796719558F666D91839604C249CCE766677B758D172AA9980A86E9A007E93615705EBC7F6DD09FC3FF4497164192B3EF66ACE275806009E5E54DF17B4938CC4BA4BA4F4FB56BDE967021D4B5A94002430CB53FAAF46BBC2C0CCE4479D26A414B4C71676177A9AB5A1DCB4B800B91C74C872A7E22036A70D6B1EC1311C34AD4D97309C52D9C4A8C21C17166F37A664E4A8F3D62AD1E1CDB22462A5277C065005CD4641B9F57ED0FA56F61953269495209484253553D89577E62968FCE1FDBFF76D71B9BF68BDE16CFB1641AB45627717569E2B640578CA76E1D288024CAA7202799EBEC8F877B4062E549ABB800BB31CDD9F9FE22C52567752A0E1C02791AE5A3E59BC73C6C31238978778AE161370B7810A3C21AF09453EF8D13C6734C6B945762992525767A03C2DAD4D5B83C4E4B989F92096E2EC4F1035AFDE9085E622CBEF1B62F21840506D574EAB8584B8A84B4852F40A757086C7F728800666A470780F98A480379449167A0FE9FD3855F6B6304B0ADD20000876008F4AFBD5BE9CBF8057F0C3DA1DE9EF2309F68EDE9604E5A6C86CC3EDDDECDB57D6EA43B71E282DADD425D470293C694AD2A428120826ADF80D9AC5F70D19E99D074AFE9E3906DFDA43EA4EF92B3BDBA1D817E14F76A47DEC5B60F6966194DA39C2CFE1D86322250DDAB4969A4B519084A52083CB402AE184C304904023785CD05079380DDACC1F97E371049672497A641C9AD34FC708BAAD0CDBA0CF16A27AC18CFBF5A9C9619091A08D64282A586CBEE4C39ADAAE2CD9EBC1A1682B30414410510414410510414410510414410510414410510414410D1C5F0AC891AF3EFEA3FDCD65C2D1B82E72A645EB58DB786EEEE7FB78A3C5EE9F8FF9A8AC6CAF912CCDCC027B5ECD93FB35D635DB7FFBD7C3775BB3AAC75E702B1828718C1EC10525DBD7AE3FA1C48689973C25AD2A907DD1279E7C4FC69E3D3B2B0F365998A4965004A99E95B1BD7B7689AC1E1C4C60A70090F43AFA5188AE547B6ADEE7766718B5B0C5B793B5FC573B47B6AE21EC6D2E7129766D30E2861C1A0B1C6D9532A471956B1EE98AF0CFC42F162B6D4D9E04C2A0EA04825EAEDCB2C9BBC5E70125084A120252080523DF0BD5DEACD48D85B17416112A99923FFA926075C84039FCABCCB8DC2CC38B54C20D54E1F2AE629476353689854A19003570C7D2255B74189D0F2E533944FF008CEAC3B331064EE87634B919599A9D4D78D2032D346038D05BDF778ACDC42A24F91D7E67F71156D97B437D206F0B35EB600D34D73A5E0328640371BF90872DDCEB9EB1CF3FA8D7B99CBE0DA7054E2FBD7B1CEEFA311EF211A992ED60DA7F5142DEE2513273E93E5D7B67E7CE9FE154508DD2E1ACC7524BE46BFDB9AC6532D21C100B379BF28A7C5EEAF8FF009A75F378ABBFEE37F968FF00888A819CFAD1F378ABBFEE0F968FF88828F9BC55DFF707CB47FC447857C2624FA7FBA3E6F1577FDC1F2D1FF111E78BDD5F1FF347CDE2AEFF00B83E5A3FE220F17BABE3FE68F9BC55DFF707CB47FC441E2F757C7FCD1F378ABBFEE0F968FF00888F3C5EB3DF3FB9E7525276B7C997B80B76EAF6AE59346BF283D83720FE8D1EF8BDD5F1FF0035A4DDADBC18967766F7C6B7318F95C13DBF5078BDD5F7EB51B3717F308DD51CE8E1ABA0FB40658C92FA9200E4D9FB7178F3C533CFCE73FBF5A66B24A492493C4EA7EF1B09696A80FEFA53AC47BE789C51CFD7EFD2A00E20A71052E5277B2350DEEC05B5685E52185817EA5EAF97B109559D28F9D87A312D5269AF6A690AEE876DD0FA35619E2171EEDBD838827F16974B57490786CD2D82A70B8BD1B0A00E63588D73AA76D4C12B7882D7A70E5616393F1840A1017F31949DDBB00CA761AD5B96B1A75BD1DBABCDB0BC7773BBBA7DC7B115BC96B1FC6DB59534DB2A5074A7F10D9E20435C6885039E54B6CB92B97BA0687AB545B8BFBAC6FBA972B20BE5BD91AD9ED761FB78CD3BADDCE6C6EEBF0A69BC30B5797EA6C38FDF39E1B8F3B70E8E3789740055C2E1508E5E750FB57138B958F212A59008A034ED5039106B68728C5A952C2024A124B7D4E0E840AB7BA59865AB14F0979F5C80B981CB2072CF969E8672D2A6366CC1380F9C5DEEEDC0D457EFAF11BCD595EE84814A123B822BA8B9F2314820C919093F5A90C64AC39964A521C0B518BF072EDD2372779B80CEE48BB0FEB8E4C551F68485851129C81A3FDBAB7611A2A56F26A2952458B67D73F4A9A380C345A0E1002889E84C1E672FAFED4C367A9631010B777CF2B75A8E5AF2604AA5CDDD043037CD8543F1A1FDC435DDC30C922520C99394F6FBC855D6724270BBDA26ED4B015F6EE468F13D8594A98000EC4DF4FC9E432A45818FE36AB76EE5F6B34B4A6D2A03FB83A4214394829267B738154995B53E56D0090B23EB19DC38AFEBA0D0582448489441009ABEF0700E4D42DA6BE71F187FFA81B65B08C037E5B0D8F61CC36C0DA56F1255D38848485A99B46C09226482A233F809AF777C12C48C56137DCA8A44B097399A171CB5E22968D1531686046E9259920330B061CF2CA8098F9AFC6F16C3F01B753EA32CB6A507594C12A2EA88494A4E47878B889E5F2AF50A2415CE09A0700D4DFE9E5635A67D5A155E384B90EF522C1A94CC6A3871615AF4A7F8567F0FFDA8F6FADF5607B3C6CAE99DDB60988DADEED1634A6D69B7BB4A568BBB66937052A65C0975A2D2C2B39C84E756CD95842A29DDA1166B9BD68294F6F1CFF6E6D51BB30EF1000CCD0BB017273A796B1FA6EEE1B72783EE3776F816EE764F0DB2B0C2706B0B5B44AED594B4B70B0D3695AD65109254A44CF73ACD5E7098408028038161439FE4E669D0F25DA78AF9CB2B2A721D8136F6E3F119BDBBA6D572D59356EB86C1F15D08FE9A4C1391CF5333D0CFACAFC94A4DB26A5037403D88ADA91BE52A193820F1EFEDA272C8116E906322AD34D67D35D0D6C030034871292120A4351AD9DFDD6BAC3BACC2B051041441051041441051041441051041441092DC28272C873E9973CC51190926D5EB088BA9310358E79F97F98AD54ADDC8C2BF256CFF004F272FE622B55C25313AF6CC72FDFAF23956A99814486208B8BB7BE0EF0CA7CE124805DDF2EBA8E51EF8E989391E5D23E3FA8A5189200773661EC778DE42FE6B310E6DC39E5A373D18C44BD769F1C85B6B6D103FACA10D679895729981DE7589A692A72A5E2F70B14DB4B86D4FECF3A3954B09CC96B817E94108BF74DDBDB3B74A5071A6D0A7096C923810095A87284804AB3119926293F104E4CBD9F3959EE1672327CADC6FCA1597237949033A17CB9D9A85B4B738E66EF0312B5F684DF658E1F863C87704DDABEE1714EA81B2C4977AD85280E194BAA61C411C8A142BE76FC62DB13C4FC42113084EF29802697B6597A728B66CFD9EA202897766EE351CA9AC6CB216C5B617716EA6E5B52186B86253FD101032D2047BBA488E535E503B4953274C1314E5C80F9B12736CAEF61C62F385D9AADF9403020135BB90FA66F5F2E3E32E301094B4AE28049464548E70A1CBB4F2A8FC62A52D5BE12695B720D7BB77AB878DF120C89850BAA8163BBAB73CE9D4C4BD9A177297148040409F7A73D724F726047523D22D78B4CBA80435DAFECBD7D61B7CF4DC8507B53F2DC871E8ED4871C9250E36648287010A1048981391891FAE54AE1B6AA779AC468CF7E9D69C236131EA283DBF6AB5BB42C8511014A1EF0CF3CC40CC1CFE3C888AB361B1E998016A0E1AF31F717BD046DBE38FBCA02F804C127A9075FDFEFBC2F33692504B120E675D33FBB508D21C4B96575AFEFCFCBFBF3F11D95F1AD7FEE5FF00946FF238F9FEA1637ADB2C29D5C908CCA47E6CC9D073F39AD86D548A10934B92470EF1A192BDE0901DEC6ADD69FB8A9ABF6DEB537694381BCFDD508518E83E1FAC56DFF764FF00C5376B9F7CB58D7E590B0870E7476F4849171E3B62E129712DA89038801106338319F5A708C57CC1BC081D5BEFEF58D5437494921C33F0F7EF48F5B790EAC368701513192B2FAD6FF38FFC8773F98D49090E6D0E5C696DACA0AC122261479FCEB266A8162A1DCFE6308585A428380758F034E75CBFFB4FC2B1F38FFC8773F98D89604E91E96D43FBC7C48D7CA4FCA9BAD13261041735B1F5367A7BA460170E338F3C357FDFE07F723E9594CB980015F38CC78A42BFEC08F3FD33FA52884AF371A3BD3AFE3F3047810A9C881DE48FD294620124B8639935CBCE084D6CA8AA6419EF303F7EDF6602660662B1466B9625D2EE4039BEBA52B6BC2889BB818B56CF7F56F3D2F08A93C399223D7EFB0EB564918B461A5042EAC2EC3F67D3362F0B09C86722BD1FDF0AB6710B7D6B7AF337EC34E20377CD29AF1164F8B6E1485364B247E59073EB94F3A88C66364CC0A1BA93BCC5C8167A65D385EB684D6A96A5A16EA1BAEE9C94FA8A8A1BF522AD18CB77DBA7C0F60938B5D3015718B62AE788F622EF0AAEA38D4A203A3DE02145226721F0672368C9C3972C0E428001CB5F3E548D8A92A2086DDCD3404DC8D7AD3B168C9565656968CB6DCBAE25256A2550A24A8F119E5A939F6D2A1F1DB4708B9EA56EB92694A3F91D47E21352492E0539D7ABB76E668F14DFB8EAD4916BFD36D260A55209197E58CA72E7A914D65ED24053CB05366E87AB0C8DD898565CB5937625AEE3FBB5790A98A537896C04290E123290099394E67BD3A1B494AB971A1A5F32286D0FD1254F5151D5C6B407ED96B0A8BB6C988503DF2FBFDB3A5D18CC29ACC48720DC03916ADAF6D0E7A29F256C4D2D4D7B1F7EB0CAEF186DA429B1C5291C898CE35FF03E154AC66D49387DA7BC94B277B40C187B03288B9B839A6782092E680660D0FEF219877318EB17C5D6A51E02A19926662750797293FA54D4CF14E1A6618C929014450903833D726ED16AD9B86504A41760039CA8DC75CF964D1108E0C4ECAE0282B85BE05BEA50F7441E240933055103AAA0D57F01B326ED4DA09992CD0A9269A13C34EB4E6626CEE4B60A20153900B396E17A718F91BFFD484965388EE56F30F69C4DFDC1C7D29B72902E5496BC24A961033E10905733F973AFA0BF03B616270D22482BFA1613BCE7316C9FC9C6B1158A989492A72082F5BB68F6E6EDE91F3C7ECDDECBDB7DED69BD9C27775B05862F1ABBBBBEB165F79B69DB8B1B265C71B3726F94DA54507C2F10A0C47109D04D7B1F0BE1DC44D289A934212C43E8D96AC18778E7FB5BC4F270D315209D453859EC7EFCF2FD38FF00868FF0F9D8BF61EDC9ECD6C761163871DA4561ECBF8F6256ED37F8979F7909B8E15BA948510DA96B400A04A408EA6ADDB3F64CCC3EEEF176E39E7EE833CD850F69EDC978A0A42412FC3E927537272EB6A474F2D597C2C2CAA19CC04926739991E64558A58DD46E9150C05F2BF7FDF3AACE5198A26956FB7A0F4859D65F449B54B0952BF3150890489CC769FF0035B924E64F38412863514D29EFDD61DA13C0909D32CE349E7F3AC428000ED9C5744660A20828820A20828820A20828820A2082880D013A434715C4A52635D0733E63CBD27E49AC29DDCB7334F661295881F3B70B57A31032CDA95AF11C23D44A567581CB2D3E87CFCC4D2A847CCA6A1FC9FF00A76CE25D202D0CD5D6B9E99F4F285B252028721A4FD7EFCE68124A54EE1B4ABB6869E4FD62176949DD0140125EA720DAF13E7CCC789546474F8C44E9EB4B8486DE1BBD2F76F7C222F0D8A549582350F4A1F6E69AE90C71071E470A1D6C2ECDD3C2B28054B4E907A0F78FE99738A9C532E6198A6A55DECFCC9E6FF889F94BF9A37C66327ADEE3323DE51803DA237888DD8EEEB1272C9F6158ADF866CB04B15287E2AE1378E8B6BA286C4159690EC98D009CF3AE67E39F13CAC2E0E623E601BA82010781672FD68FCE24F0682A5070E5CEF3B90F6193D34CDAAD47C05B97DD6A760701FE6AA529DC471A3F8DB975C1C4E9372A2FF0A9591211E2409D220738F9C5F1476FA7178B9E12B25D4A72F7E5FACED9C5E36728CBDC2588D054BEB6FBBB068CD178DA3F97A51038D4412233FCD267ECE42473AE19860A9D341BD4B9A72E943C2B4CEB65C3633E5CDF9854E08615043D079794610DB6DF7EECB7758DE17B35B518BB785E278EAD4CB4E3AFB4CA029212139AC82278801AF4ED5633B344D96E949721CBB11E57E2E0EA75852626662262E6B2776E2953472E006E4E32A9D7256098D26CEF5AB36EE957B87620DA5DB3C410AF11A295B7E283E2881FDE008CA4D57B19B254146840BB8CF5CBD34AB648FC9332525425EE924FD2A152D43973B753175AEED0D82DB8E871D924A8281267302626239F41AE7510306A9531B74E795B9716A126CFC2BBCBC39502774803FDA6F4A50573D5F36A3C453CFAD6496C92274FD7B0CCFC226A670CAF96C19890720E0F6AF5E91B1C329C1602AE685ABC4D78BB13DE1CDBF1169257F98C935B4D2E413435FB43C929DD491CBEF0B5250B430712B2B7828C2145303EB94E7FECF6A208B6B6CF6C98D97C2D965281C4E880207500FEBF648ACBFD2DC5FDD29DF5D6114CA4998A9AA776FA41CB870E3F710AE17B533B396B88DDF0B4C5C8570717BA4C2883ACC796B3152F879BBA801A96EDEF586B3128528907EAB299A94A3FBCE25F0DBFB57D837364E05BABFCA2665427403F4A5FE71CC6990FD5FF00A68D4A524314823944ADADE5CADB0ABB1C2F999049100481127204474F5ACFCF3CF9FF007A7B178025200601B26B4493572404F1106796647CF39CFBF9C1AC89E331F6FB98C14036A1F2F7CA152F24924C4798FDFF005FF0E25CE4B5090323637E7194A400C403D3CA0F151D7E63F7A53E70FF0091EE3F31961A0EC20F151D7E63F7A3E70FF91EE3F3030D0761078A8EBF31FBD1F3926E49EA3F3030D07611429C041CC47CCFDFD9E75AAA62425DC87B1A558D58BF4841490EC6AC5F9FB7868E3A0CC68222749E7CFE1F731F889A14336ADEF6BE64B74EF0572BE5EC4365391C51FE32F5981CAA1672C31006B5A3716AD1F9B51AA21D224A99D4286E2F6B647DF286AE3C24E6679C0E5DBFCC1A8A98B735CAF7A353FBCAB0BCBC33D774F014739F3EEF9D042887DB0D80BE119F389CB2CE7E597EB4DD5212B75352EF7EB5BF1BF3192E641DE2C0B51D837273AE75FDC20E5CB1DA4E5060E5E597D99E54894A6596ED41E4DCE164619776A0AEF55FBB53DE70CDEBCB4420F1293C6359E1E7E6723DFF006A497884A33D5EB422C3D7A7AAF2E4CEDE66514D2A5C9A37936472AB6B6ADF630D209085091D3AF7CFBFCE9AAB1E0160CCF7AF2E3A694A3F19346154523E9BEB9B574BB7DDA2D6B8C67C452A55AE5DC7ACF61F66699CDC3CAC42CCD252E58BE619BB0FCEB69393B14CD4A66D068E0B93A00DC7A677788A7961F920C939907AAA32D675EDFB5446325FCA0C94801C55ACD666D6B5A6594487F8270C91705AA32FEA8E1C0AC050DD859397574F1651C2A36ECA54128BA201E22F24FE74B27DE911C31564F0862A6A3192C0DE62A02F4B8AF0A8B9D3AC41E3B152D0E4941520177FE497161A7106F78F928FE2DBB15B6DED89ED59BAADC4EE6AD2E76BB6DF0EBFC42DF197EC50E5F611815A5EA195B8A754C4B96EA5DA1599508E341E409AFA47F05C4E9D8594B52F744B0874070B99BC5BE815762CEFABF3A16D3DB484298AEEFF0053D05C39D1F27ED1F4C9FC2EFF008576E6BD89376782DD5861D698B6F62F2C5BB8C7B17BF69879D178E23C52869FE04BFF00D22E2DB857E588AF6E6C4DEFF111BEEFBBE807E7988E4BB6A789F8A5AC6B95ABEE83ED1D6FB662FEE9A530CBE2DEFEDD69FC482A29494F14A4240CE38040E511153310F17E3265A46609090091A1500028FA99A208528820A20828820A20828820A20828820A20828820A208288C1B1E4622C8517CE7209233E5D87C7EE056AA0E1A970EEFE5E5FDC4392BFF002D3A035367FB716BD5A1B5CA0859D60E606B3A0EBCB5D29EE1C2001FC5AAEF91033EFE9778B5C82F2D23302BD5CF7FEE1BDBDFA4DD2AC432F95A48E27787FA425322546234CCF5A6F3F109966AD9E57EAE1EDC84218C47CC96C0820E952E2DEF4E514DF620D589425495BAA5988687114E99ABA6BEB50988DB52643FD429FF001B80E72A07A57CD9A2125ECB9AB5021248268CEC2BCB437C8D0461ADE5EF9F03DDF2B8AE14BC556EA08770CB321EBC656530D7F48C14FBC413968272AA76DDF1548C3C8528CD48DE0AA0354B0A3D476761A45F3647867118A904A5135250DF510C95BDD8B55AC7DBE9F5AE0D8FEF976F6CF6D76C0BCC6CA60AB75DC0B07B8E24BA4BC8857E29872504A5CE152383311E83C75F123C72667CF9689C4825565790639D29DC45B65F870C94B6E80B2C58DE99915D7DE7B316172E26DDAB77D216DB01484A19023C31EEB6003CC2409EB90EF5E36DBD8CC4ED0C4CC53A8A4A8B3127339BDADC8BC492B64894031008CF98E356CB84463F77C57DC2E7134C9FC81DCA32F28F879F9A7B32419652542CC4D3AF535E43843799869B292087292E01E5A535CE9E51A4FED97ECB167BF1D8EB8C4301BA4DB6DEE1A855D6CE3ED2C2429D6541E752B5A4170921B4A404F3D6AFD864A1526803B51AE5FD2CD4D5B5899C24C0996D34EEB00EA55AA4B579D3AB523597D8B7DA8719B1B8B8F673DF42DBC33799B38EAAD6CEEF142A65ABC6C296E23F0EB7CF8AE2BF0E84010224E90669962B0B2D414126A75671A8F47BF1B43B5253499BCA56E7FB52685C67A8FC36B1BD7B41BDAB6D9FDA3C3B08C430EC542B14586D8B84B405B8881C4A5A8FE43C52939E5C849AAD62708122D517A7DBF1C758587CB6E62805DFF7CEA7331B1764D86D16CB788507DA43A8291301480B00FF00E50623AFCE2E62371553714DD2DC3CF843654D1310A084EE94962141B36714E1ED843E514A8952125291020E47A4C773A4524E4DDFAC0874B254C546A48B70D3F5CDE282A09899CE88521BBA871C2929809044CEA403FEFF00CD10459FB5FB228DA572C8FB810C281742F22A00A4FBA331263AD64D4B8EC32F79F18C25C0637D6FD7F4F16AEDC6CE62D88B186E0D8238CDB61F62521C0B5142D4094295C213910485418F3EB4E5134331240C9EDC73F6FA4202490EA212497B73B07CF5CEDC22F7C36CADF0EC36CD8B54B9F8A6529F156BFCAA3A9208CC89F803E55933D0003BCC4F4A060DC283AD235095BA814009664B03BC5EEED4D3DDAE125DBA5078C20A8004742911DE0F90D6B6F9C923F9163C47E632997BA18249BD48735E90B250E2755031A664FE9F7D7A644C49B1B71FC1F28CEE81FED6E8D0BA5C310449E79E9F5A5A54E00665F2714BB3706FD46DF2F827B7EA2AF13B7CFF00C52BF3C7FC4F7107CAE09EDFA83C4EDF3FF147CF1FF13DC41F2B827B7EA0F13B7CFF00C560CF190238D0C06550D13D2FE91515C266333C8EA343F7D41EF48AE79A249715619F1CF8BC3298965301CB534CF96AD488F75E0924198E5CA74D7E51E7CB5A653A7F501E86AFF7CEBA7185E4497FA8D746B821F877B886EA7651C5233981A4C1E7FA7975A899F39F9370AD0D33BFEF94A22582580D2B4E4C32CBCF4884BAC4D0D4950CA4C81D0643EF4D2A29588625DD8E4EDDDE9D00FDCA4AC1A942960010FE6FEBF9702206E31795A9495108E40C65027AFC32E7999D1EC99C9F95957BB8D3BDEFC1EF232B03BA03A4139DAE68CD4F588A7B1A09513C66675D63CBA4C72F2A61899A9A8D3A3D457B8ED0E65E042812D7E078FF005C8365160E2FB50F357CEA52B70A7DD1C20E60C673A7D2A071588704037666E1986249A9B0A521DCAC03390976BE560180ED7A8F588E671D174616A5372732E401EB398D2674FAD41CCC4A92E1F5A82DC3334AD8B748768C1512424BB8A351890D95799B3EB1E3F752E05347C74082E2992541A1C8ACF29F9812749A4A4ED598957CA724921D892D56A8A5F4CF2CA2C986972FE4849025A92974B800A8E6D77A74899B5B96C302E3882D8FEFB8041691060F88BD131D73CC559B09B3713B4C2404ACB8191B16E1EF566783DA98997265A9C804B8634373AB30F3F58D66DF56F5B69F69AEBFF66F73986AB1DDB3C4D4DDA5C62A965773678234F14F8AB2F307C4B7529852F84C66B4E7005764F027803153F1524FC951FA93FED26AF7B5BD968E3BB7F6AA10A98C4077FA8667D8143CB81DAAF63BF61FD85F67AB8BADACC630EB4DA2DEE6D1A1ABBC5F6BEF5A6EE6FECDDE12E169ABE290FA121B714C90A27DC0139E95F4D7E117810E0B092553A5B6EA5156FE2585B3CDB83306B4723DA9B495316A0EA00B80067CEA4657FD3746EDEC997DA4BF66861A751925C6212952A6145440CF31A7527A8AF470C327084C90929DC09A10D421C79373A1BC41151554925F587F6987F86E1BA7F87F14E7FCA5BC90A8109CF5303AFD2B68C449252103852207EF441155104144105104144105104144105104144105104144105101A823586FE1A788A89023B89F4039F9F3CE26886A24BAF7DABC5C79FDBF709388490547967E5CA474F9D2AE5292C0B80E73AB07D7D1A1EAB109901945A81C74ADAF6B4312EB09539E18487140F12801940804911A012263A8D045336E6D0F912D41D5BC012F663A70F31F7470F8A4CF98108FAAB6ED6E27D5852F1A87BFBF687D96DD558DC5A1BE6AE31A752A0D329710A712B33038642A012274F21AD714DBBE2A4E1CAC0987783B906CD7B33776AD23B4782BC173F6DAE4CD5CB2892E08431DE50E34ED9F131CB8C537B98C6D5638ADA27DD7957F78F151B774A8B484A15C2DC209E2128E139F5F879E3C63F10D7284F4FCF25E8DBDAB59EADABD69DFD2DB23E1EA30F2512C48012025BE8E21EE199DCF5BC5E789EF677876564CAAD2E5869B4A470B4DADD060680A4440813DF58AF2B7893C5B371F88581394CA51600D2B980FC5F56CE2CD27E1FE1A63138696A531BA4123967C7F30D6C3DA0F78B83B8CDF5F8F12D9C2014FF54C0490939129039AA7D7CD0D95819B8B48592A20D781E39FA7770F11B4FC07874214061900814012033E46C6BC34E11B87BB5DE7D9EDB58B5737A017E0150000209D75248E9DE222A57158718445824839DDF80D0802E2C738E59B6FC32BC30509481BA92E428304F26F5EB19B6D5D6195171284A9E792461C56250D650E8569C2160C403999ED4DB0BB5BE58352F61A5D8FE78D6958A062E5AA5CC4C956EEE827E62452D66A70E995A39E9ED2DEC6786EF431B5EF67636E0605BD2D9B52AFDCB8B250B66EFCA3DF4B7C6DA4BCE1F09B2889993C22662A465E2C4E0E2F9BBDCB585EBD7A460630A1411BA4A55449193382E7CB2D1B28BB372B7B8D6FA766F08C3B6C30C361B5FB2AB5DB5EA9D694D38A2C381A69C95CACF88DB3C5240041D291C420292A25CA8E99F40D419E798A88DFFCA4A52A2A2129E3463E8C7CBCE375DB43D6D8759B0E125DB5E16C99954248488D0E806A3E555AC5A4A4D18D7B9FE9EC7864C013D2EB3425405072F6DDCC4DB8506548238541111CC8038BE73F4A6B785641242492E6AFE6DE4D0D5CE5EBFA510E6112BE12467E9FEE8820F17BABE3FE683404E9041E0B4E1E356AACC8273F89EDFEF2A6CA5D6B53C3280AC8A04BB66DF7FD73AC38430D11904E7D333EB98FDAB099A967292E75CBBEBD21352C87A5B2B9F510938436A281200E9A67EBF1D73A4D53D8900103A8AF7F7CA14402B485503E45FF0071478BDD5F1FF358FF0020F1F3FF00F68DF70EA3CFF114071434FF003F28A7D2A712090790059BCCDFF0636DC1C7A7EDE3DF157D7E67F7A5BE69E3FF00D47F106E0D4F97E2144A8900C9F89AD0CE2FFC88E153DEF5F6D09A831223D93D4FC4D63E71FF0099F7D23115AD7C29224C88033F2E7DC7D2939B30DDDCD4D2BE432AE7C2B0C268DD981C8CEBD0444DC3D3232D79F4CBBE71D728F5A8E9F3CB5ECFAD4D9AAFDFA448E1D02990BB0E23CBF77888BABE0DA549900A41E7D758FA1FD8D45CE9E374B1249B575EE05ABC3289D9186DF214C58E57F7C8F908B1B11C4614A3C4009D391EE467A7F9F3889F3D89255C6940E791F79E462C984C216140DEEC7AF01C323665EE28E1716105412065073E7F2EB90EF49A71C65B0259DEFF006ADF477AC4BCBC206629760323EADDEA784405C62AF1260939F39FAF2E5F62939B8B13050826AE4F32F47A9BF43A98712F0AD641AD2DCB830F53EAD416543F1AF9E22B994920E9968ACCFF00AA8C98B7CEBC3EF5F57FC48A3083737774D83B8E7C2B57EB11CFE396A494B162E2D5D4340CE9A46BDBE798A68B93F309DDCF8350B0AB707D2164E082412EEE1BF0282A5871ADA18AB6A1385B4F5DA9567676F6A92BC47F19EE36DB7F9878F9C02A483E1CF3F3AB17873C2188DA78B96B420A92A21C106B66C98B65D6D68ABED6DA88C1A8CB538525D88B82D96601EF7A59F1AD86D2ED36FF00F1C5EC86E4038C5885F818EE3376169C11B4190A558DCB1202800E0055978804F3AF6AFC39F83537188905521CFD25F7356FFC7F0E5C8B98E5BB7FC48196EB7002B30E05988D5F2BB9063A21ECEFECBBB2BB93B3B8BBB5BC563DB6989250E5F6338B2D171705E00952597C2439C08952120E890065CBD75E15F84F2B650953178748524057F0FA49A1BD78FE35E3DB4F6BAF12A539210B25812EA0C6AE1DAB4ADBBC6D43185DC22D941453F8F70FF59CCE0A672E13993EE9220CC6990AF47F87A461F66E1D329490964D52D57028CCD9D49BBF68ACCC2A98492470CF9D7B0A51B2B35C7616EDDB5BA5B6C242049F774E227DE3EA7CBCAA466CE33E62E612E49D5D8643B40CD4666CA1E52704144105104144105104144105104144105104144105104144105104365082260013AF327A4E9D7BD6C775282A3C7A37BB5CF2B64A9094B921CBE76BB53F37D612582E2480600D3BE475FF005D73CAB28589A93BA6B9FBD3A5B37AC46E210BC492104824B66396BC6E7A4620DE56D55BEC16CC6D1ED0E23728658B7B7E161457C30E3885211993AF194819F481CEB8D7C45DA276561F13356580048F79FBB6564F0AF86E762B684A96141467281005427759DEECF46D7331C0FDBDFE6BB61B4571B5FB557173756B7F7370AC2D84A94B2D25B5A9214EA579252612531CB9578D36DF8D24637113A52544289500C4644834D19CF7BD63E807C2FF000A0C2C99026049A26A43DB9FBAD2916E365D0865C60B28790A21453207003088CCE7C3A939033D6BCD5E35DA3889D8D9B2D2B5339CF50F4CBEF933347A464EC69094A54100D01A0A71D1B3BDEB6CA6977F72EA5B2E5D3CA527229E33C1972CE72EFA6623957309784C41C4FCC9AB5105540496E2D417ADAACF5858E124C807FD2481FF002090E72BDBA0E377876FE266F2DD36AFC847090824C09F5EA73E73E55D4F61ED5C3E124A11312E406A3353AF6D38C5776861244D0B4A659753B9201EA7B5B367B88B9375BB7F77B31B516D8638EA4DB3CEA42425478632C8E91AE703CF3AC6D8C7A31AE24DCD0352967A1CFF0021A39BED8F089C5A26EE86742D42F5604D4FBF38EAD6CD6256F8B612D38F2212B6905975B03C46E5238B80F2E23AE432F855657839F25615BC4A545DAB48F29788B64AF0F8F9B292485A56A0A3504B1239D8370CE1CA2D14029B0E14A493FD50AFEBBA0FF6BC7FB872CB9181DA4B0F315258A9CE9A1AD73AB68E00F5833805FF00C88B905CD38D39661F942186E0F8260388DF63187D9376D8BE221B176586D286145B4F0A5498E124A84C93FDC4EBA177331E9615655883F6B97CCF1E9097FDB6729D2B585CA268332D5A86A5453BD22E86FC37ED1C2E03E33924F9C9397393CF9795454E5A66390E730C055DBAF5AD2038652549485303425ECDE5F8EB0D2DF883294AC10A05591CB9C0FA5317093BA1F2F3D3D817EAF50A12992A356229C33F2851492A888CA75F4AD9EAD5B3DBDB7585C2D2598DEDE9EB1157AE8B595AC920E813AC69D81CE39F6ED5B8965445C33E5771A671B0FA8B023BC376AE43A92A85B60735989F2CF3A57E41FF0090EC6141294A2C18F27FC4542EB3949246706411DCF3D72F2F5351B3F0E42CB114A3D72B7285912D2C413517D28FC0BF67B52D0ED17262012083A8FF007FBFD2992C949FA95FC72BBEB7E9E6F48D7E52544B3685E80B727B7317E31529B71490EC9E15732639C72D73F865DAB51302C920D7969A6B1A24A524CB7FA93957CB87BBC22E079082B0DB8E0027DC93D7F6F8674E65C852C12C726B7BFDD396E152DC852C06C9C0F7EF486A9B97145005BDC02B244149F7639ABA4EA3B53D97845EE0217D01B57F27F30A6F4B01DD2D5B90E5B9C3E7D06DD29538EA53C5CB8B31E734AFF84B607E65F2DEAF60FF00DB884D1350B24043366580E858BC2A56866DD0F29C4292AD384C91A6BF326B6FF0D4120EFA4DA999E37AF956ED0893F3262920335C9603A5AD6FC4541C6CB45E0B1C004EB9C67397C3E347F88B037B7837AEA066F76A4608216106E73CBBFBC8670D7F148B84788D9201919E625391883DB979646A3A782951483F57FB790BE9F6CC69094C904AC28D4532714A023AF9F5311CF0528CE507F4E5F7DBBD35549529998EA2FD6DC214978A97295F5659528ED5ED668B471552D0B7110490066273CB965E79F39075A8DC4615402B8580C9F2361D3F713985DAB2414A4025DADC756BFDC5DE8F60E245D528E444C9CE7E072E5AE7D3BC557B1095209DEA905B85E9663F8E0C22DB83C7CB580024DAE037126B5886280532A492ACF9778D39C7D00E5511377F78BD1AB47160EDC395AB13D2E727E5EF121FB3E43DD07578897DB46797CA39FF009E9AC79080C46DB1859C6493551604D47014AF58712714852824062726CBAEB51C4D189AC5B58ADD7816EFF085FF004009047BAA2AD3863948D39FAD58306BFF0026426730DDA9F36AE44D844E26592905354B5FDF9E9A4686EFE7DAAD5B9D71D63FF8D75888504DBE18CCB97F72A5100218641054ACC683CB3AE8BE0FF05E23C558B9385C390153160382C5C9039350B3B5A22B1FB6246CF4933121F74D28E5875FBD8F28BA7D987747BE4F6D8BF5ED96D7AF1ED80D85696CBBFCB1B2FE19758AB00E69BE65614DBED909F7338E05F306BDF3F0E3FE9D71B82C3E1E7E25285164A8920F3A022FAC79CBC5FE2F96BC6CCDD2456C0DC654A135D4BE71DDFDD46E8B77FBABD9DB7C236570DB2C20B084B770EDBB4D30F5DB89305CB852238D4544924E664F2AF6A7833C2383D858542264997F312901CA5390B03AD0371F3E5B8EDACBC4AAFF0042AB515001A5327E757B5632F33832DE74B8B5B6CB2D41B55DB1871523DF2E9D0C91A7C66AFB35723700932C390CB7008045B77C9F3ED58198B54C2EED983E808F76B44D38C5C298E149487B21C44E4403064E6648D6ABB8AC3E296A2652F72AF4240E541D188FCC6C929DD0142B9B01EB43F8878D24A1B4A5512358D279C4F539D4860E5CD44B1F34BAB5CCFB6F7531AA8824910A53C8C41441051041441051041441051041441051041441051041441051043777FBBD3F4A471333E5C93DEDD35B5B27BC20B964AB3ABB31A665AD7F7942493A8FFB65F234D3098848739004FAFE5F2D05EB99402660268F70C2946E9EAF4CE39FBED86FDFED726C375387BCB61FDA0B865DE3428A54A6EC5E6EE5D120660A010759935E74F8DBB4C7F8589054582486735E5D3CAA6F1D5FC133E5C89C99BBA3E63D145A84598B86278F9135D0ADFF006CCDF6CA33688C3ED54BC3F0FB661B5AD282471969B4B8A94C0CD609E526329CABE7AE236A23FEE93025542A56772E736D7879C7B1FC11E235270F23E61DD550148A067D29DC51DDE359AD31242EDD2A194F16B99993224E5967D3A41D4D3F6E2C4EC6296E0839641C3E76A35BFBF4F6C1C54AC761659DE0E52F767CB98EB9E90A9C5B8753F319F3E833E59546CB90952B402F6FC5A2C5FF006E4CD1FC778351DCDDB43F704520FE65F8B2D34DAB83C3E2E220C1CC488CF3D7FD53B4CA4A40001BD855EB4E3CFADE18E2763225A553141212C487A373BF067B1E622DEC39DC4EE36F70C66C1B71C487D216B40240D33919CEB9F78D32A732E554580A13AD3A5FAF58E7DB57132B0626B94064AEECF50410EF9F9DC651DB5DD95BBADECA61887C12EF809E30666613F219FF00AA7330BA500D4805EDC32E0DEB1E2CF19CF44CDB98B54A6092B70D620E7A3E5AD5AF1929B679F08E51F31D33F9D20A4B80D4BB69C62A0A98CEE49D74FC7E22972D87171AB28898CA3E3113FBD24A940BD95EAF6E367F6D194CEA6E834269EC1D79E4FC3CF1DB68788540348CD664447727E79FCEB41280C94C387EA1252014A812378BD694B6B4CB4F410A8BBB6BE1F88B45256C2B24A92414929C95047FE535B9C1EF10A09D34D33A1E77A9A9BC47A42925295AB7940A9CF3B4149AA46EB500E63F43DF287096DE0CEDC6F68C31BD5DE2DD6C5A2D0B1B378A63085A8A54BB3B42FA07BC9008339C4E67AD247E972F67A8AF63D7A670EA4286F900B917032A1BF7F6C627367B1356D7E15698A7E0313C33893C4AB475A2CAF3CA382627EE69B4CC490A0056D41571A3D05FABF287895251552F77424DEF7D5BA45CCE2508570A1B75A4803DC7870AE6332477EB4D274F0E58A8035367045E819BEF1AA5616905D2A2E7EA4D8D7DDFEF0E5BCA472CBF5A899D33E616666CF539C6628657893D70EB508166CE683EF051912648CB590279EBA56F86016424DC640DEF5A8D5A9F68D0EE20EF3328D1F32FA7BA6B568C07BD0DF0DEEC93AAB1C3EC2FAE569047130D1704FA1EA4CD5930F24EE86E3F8B53F19B98C942557482DAC5B9BA1DEC63DB518DDC318A61F8930DCA4A03AD29281209D09EFCA9862538B44C2995BFBAF42976156C99ECDC4DA1D8C2EFCA7615663A5855F95B2A38D365D65FBCB9F7D32DFBBC2179F207E3FB522DB43559EAAF3AE8F5A3660B884F7112D164B7035D7227CB2ED0FF00C1B77C26D9D5F0AD04F12504011CA06BA77C8D6A46D014066139DEB614A572CCB7A335A8804A7743E79D32A1B93DE97CA558B1B52D1638CE70224139EA3CF38FAEB9E5231E4FD456DAFD458E7A310465A90E619AF10B490FBA4F5719DFF1EB68E76D1162E2AD90494A0E5399F7B333F7A5650898EF33F95DD9DAE731A30CF8BC2E8C52264B0E589B870C18D4B1635E511EE72F5FBFBFDE9E2774074A6A28DF8CB9901F856135A50B2295D29D295E3083D60D3ADA9E54C919E9CBA48F872E71A532C5A0EE9A00F73E8DC287AE8D0F30B212952737D398B33726A7A8367E2187B526129F2CB967E5DC728806AA98D949FAB334AE479EB5ABF38B8604A52C1A8C38D455EBA3FEA2CBBCB54A5C5A529C8691A67A74D34CF3E9AD414F94A09533391424F034E15E00671654282A4834B57817CFA4415C5B44E51AF2F872D23E1D39572BDB00FF009C5245942A347AD5B964D951A35C2A93F3455CB8AB5BAD3BD62DFBB5B12BB77ED0108523FA8B6F27648260F381C8E42BA3EC89811B2901490E00AB0FF90BEAE34F58B6C80A520AD330B043143D03A481422D60733A473FBDAA775DB118DEF977418E5F60AA4A1DC45D379C56EDFE19D297184B61634502749D7313D3D3DF01673F8830AC187CC40614D1DC176B9F28E75E25DF1266098BDE9890BA82E03BDDF46F4A47D0FEEEB0AC3767B66F67B0AD9CC22CF0CB57B0CB30E8B660328E14DB3441844093339819F9D7D8AF0B2B7B66480C0112D16E43D3DF0F2A6DF2A38D98A52B79D4ACDC062437BBDC878C849C3B0B5BCB471053CDC2968041CE388C8F31F1CEACA43EBCB23CF588389CB55214CA4B69284094849C88831A72ACB0160D0438A20828820A20828820A20828820A20828820A20828820A20828820A20828820A2086EEFF0077A7E94D31DFFF00CE585AA4E7937BB46410A4E8439639FEE8CD0D3C4E151C8CA4F3C81F5FF15052A6142580513F5540EBC3C8BD21171BEE6CF9F2F7EB1CF0DE75F398E7B4961966C1877000F02173C31776A348CF4274D33E599F2A7C75C699782C48CB74B00399A9E1E5C4C5E3C3D3D52D52C8240075E3A75B679DE24B6F360ED76A2CDFC2AE116EE256DACB8A700519E12A1C24EB072F87A7CE39FB489DAA402C42D65CDB3F75B1E11DDF61EDD560C4B5952D40148FA4E64B59F5ABF2CE91CD4DBCDC56D2E09757D7B8532877094AD45843416A772278F2480089074D75D4452D3B1226282D4C6EEAA64295A67D5ED1E92F09F8DD1264CB96A9A02801F49559FAB80C476E91AF8F5AE2EDDD2AD5EC2AFDB5A55C256A6149464489072CBD339ED584CE483BC9E058795C9E7EDA3BB6C5F19E1674A1F3160D01AD43D5B3CF85F4192F6D84ED0BD76BB6B2C23115AD6501372185FE1CF10E4B1AC139F965953C97884A98960D7CB2F75AD6B9C6BB77C5B874E1D7B8B48FA496040A8CEEDC5B91D2374BD9FB73AFA1D4E25B43689376B5256D29683293075E2CC6A34FA654F113921F788B6445EACD5F5EF1E62F1978C49337E54CAD6E68CF5CF896FC88E8561086B09B166CD49953408940F7784FE5D633032397A9A693B1A90A670CF4663D4971F71A479EB6A62958DC52E7BB1597BE97A07A3FDE26D18A5BA6650AED034EBCB2F49AC231214097A86A1258BF3CB8FA188DDC59A3B8EBF8E10B3D78D299012485DCA541A3FDC9294E8BE62797A7ABB42D24124D4E941D7A3716A1B46802CAC245377B17A86A7ECD9A916CDEB372E6CCE296616945FBB6F70B616A24240690E2CC9D46432F2EA327294A72A9A367FD1B65DA30B44C0B0A25935DE7CEFC2CCFEC4637DC3ED1398B6C9B5875F2D6AC46C6EAF9370FA892D287E25DE0E151CF2488CEA570F286E0373A914AE5DB816E75289511308DD25DB2A8A1CF2B7171190F15DBAD92C11CF0B15C770EB120C13717286C083067888A6B899692E02439CDB917E3D7808708FE40B3F0E9CFEF0C13BC0D80C6DD6EC6CB68302C75E91C16B6F72D5CAC139C040CC2B39E711509884EEB860746AE5C6AEE3C99E1C4B4266391BF2DEE41670072A80D9DBBC4B3D8707407ECDDBBB22DA789BB76C86D939716481D7288D66634A819C95256480A15E34CC0B55AB778709292A017B8B4B67535D6835CEDA8362DC5CDD5BA6E2E140BE4A92A6C93E20083C2091DC099A69353354951357676BFE6D7785B79091F2D09DD4A6B664D5EDCC9FB3522A6EE21C2DA9A71074952606463F7C874A60A42F78D77781241B7DC8EBC60157D058EB6B7786D89DD3785A9973C4BA5AEE891E1B4A05ACA06635CFEF2A7D8374919BDCDF86553CFCA130779F7923E934A026AFD69C6DE9AA3ED21BDFC4F7718687F03DD5E25B5F893E825955AE0CABE4F1651C45242B98D34D672156FC2A920241602973AFDFF00340D19001208592C482E5C69F9AD7368E79621ED19ED878A20DDEC6EE5DBC0DE7CA821177805F5BBA8014784A92D92448CF29EDD2AE183C260A74A0A5896F9EF370CEBD34D22630FBA258DE3967E6F522E29C69711682F6EFF00891635748786CDB564D13252C5AE28DC2409C872CB97E94EBFC1D9E5D928366603ABF3E873BC258854A0E00481A1142EC3A9A1F748F1BDB9FE237638D3CD8D9D6DD6121BE071EB5C514E12539F11919493CB410234ADCE03670500D2F3776A534B3DBEE2B10D3C7D5F4D53C1FCF97F778BD6C36C7F88F39709B8FE478606A4152556D8A710C84889E5AE5131F04CE07679144A1C02723971A6A2A223662544BB727F5C8768EACEE131CDE3627BB6C05DDE961AE31B6AA1703154B0D3A8B710E90C94F8DFD4CDBCCCCE7A64455136AC8969C4912F76A5D85880F6B53FACA236619A85B07A16A3354D838BF2AD6335A995940594940E8A107C88CE0E597F9A6C25B07B3666FE9DADC2E61D4A9B368EE793BF07AFE1B9BC205D053E085A4AA0FBB3A6A6239CE910640E951F8C40DDCEDDAB9532EB9E8625F0F88989FAAA00C8DE872EE7A72882BFB27735171A42359528803EB1D7E3D22AA98B96778F603DDC8AFE6B12B276B0412198B86701F8B7F62869AC5917C508756994B9C310B6C820F69C87A89D2A2572F7D2A49B31AF2E4FD43EB174C0E24CE91BE48622A03925E9EB977362602E16933EE91A6BFB7F9CA7CAB93EDD93BBB4142C4285EEDD43D3A73AC2F869844C046ADC5AAC74FEA2031369BB96D0B295A45B927FA6002B9CC4CEBA4C8D055E36691FF6B4822A1AE38DB5CFDB45AF0CA280B62499A1C0A9DD2054707E6F68D62F6862D5FE19B378A5D34D24E1D8B5826D1C4262E1017885BA1C927498E434D729AF487C059BBBE21C2906826247BA35685B57CE285E28584A26805C90AE21C8F304BD357B523B89B076E977663671F42DC8FE51619AC82A8366CF3191EB98F9E55F657C1EADFD932142C65A07601F33AC79636F157F9B3028241049648A317AF5D22F46F0F6DA7D572CE6EAC0E32B882448AB5D5CD9B2D78BC41D5F867FAE3D624D09E148100750349E7598CC5544105104144105104265C4804C1CBCBF7A208A92A0A008FB34411556017D473BC105660828820A20828820A20828820A20828821B9CD6A9CC6500FAFEA3E95B2D01728A48B83D59E8F08AD7621C31FD3FEB8B4337340498FD74FF3F66ABE642C6FB07A1619B077B81DB410BE1E5A66104BAB3A75BDEB4CF5B4738769DD461DED4D7AEDD9E14624122DF8B20AF0ACE17C33E7CB96A6BC73F1FD1B983C5354EE2AA78D7AD79522F1B170EFB840A5AAFAFF006D4E45E325DF5CAD372EA8FF00D8883A94A89000D728C88D39659D7CC7C74E5276BCC00D02D4FA5CF76FD17CBAA6CE947712086A0F263C01E34CA978B6EFB0F6D68530E34CB96C4150428711CE54796799E7A0D69D4DC7A81DC2A2DA13437E5E5C1C459B0D8C9921695A54A4B3074D0D29F8A7ABC630C5360B66AF5D5ABF9532A70AA494B29CD47EC69AE62954ED0144B816D18FBAB3D5F9BC5D367F89F1D2032671090D42A3F917E7E861E615B2983E1A84348C1D91E19399613399EBF4CA220E5269ECADA29B10096AF1EDE5C1EC6338FDBD8FC5952CE32690A006E8592035D867F9B0353191F0B7F0FB3424218433000C921307A65E596A2333CC56CADA2EB3F532438A13C46BCCBF168A1ED44E2B144FD6A5139972FDB950EB43130ABE4B878D2A949D0C920C7791E5E9D6A2313B4089CDBC40A31A01D736D0657E310E9C1AE582142BFF0090FBF3A57411E7E2BBFCFA4FFE54BC8C7B8037C971AD2FE7A0E1CA364E15C394D4E8187663A738F1AC4494DD28A813645AE1139FF508E28813CBA7AF598C3E31D2FBD40CFC3CF2A071EB18548DD5210515980B280D3A6A6D719E70FF0013C45855962188A9C436D5AE1B76209E1054E5AB894CCC892AD273FA54CCBC5216410A601B3FB72F6F084DC229081288256B25414452EE413536A7E99F9A9BAADD46F776DDEC6319B7DAFC4300D97BFBEBCFC33585DF3F6D78DA1372F2547840E01C473491320D4EE1B10552DDCD05CE63CABEB11B88409738241B268466C1AFE7FB8D82C07D923661929C4368F6CB6E7682E78F89C6B18BF4DD5B13C52470A84F01E8796998CC5CF0B046E9AF6FCC6A824281A1E7EECCFE90DB6EBD9D6DB04B91B5FBB0BB7EDB14C3CB6EDD5936B0965696C26006DA01454A4A4954F5EB4C572828300F7A69E96BDDE838C3B94A00B29802FBBC75CAB57B7EA3316C0EF5AC31DC22D70FDA6BB6706C7ECC06556D72E25872E5685704210B3C4B242499FF00CBBE6CD783DF0429E868C2879963C837385A5CB085A949AA660FA83580058A5ED72FC6B6B65DB8BA61EB6FC438461F2907C673FA485240C9415CF88099E73CB96666CE64394B1ED91EBCF4AE51A00259500A33534A3EF10E73E3D22D6676A2D97722C6DF86F94494F8EDC3A91DCA81073CA0EB977A80C5E1771C94BB3D4873CB85BEF710E08702A43642DEFA45E2186EE59699B8653C4C7BC97169120A8F16455D34D3BD452677CB5005E97229FDE79757786DBDBAB528289DE23E97766A503DF9430C45AB5B80953A8B7B82CE6943802A39E999E5DB3D3AD4A49DA3BAC1EB70097176B3F47CEBC6164EE8496078D03D73D0B0ABE4211670966F909BD0D2592E65C0D27850383DDCA3213FAEB066B49DB7F13294532D4B6B80096F2F2F586FFE62649F9656481404B392F6AD1AFC9AC21E7E1DCB51EE072120444FC2639469DB3CB44BFF0052634577D63AAB97DE364E2933AE4115BDB4E3CCD0E9A3B806D968E271A74BE7252B8667391993CBBF291DEB7FFD478C5172B9A49A9A9E5EFBC2A12B2B2C65EE64FAB572BDADF984D572D5B49517929EF97DE9D67B01347FEA1C633954D1CC9D5BDE5C6154E1173582370ABBB926AF9BE94072AD22D1C6378585618E38CFE29849464438B01C075CC4C8F3D4CD4D60E79C523E62CEF28805CBB8E64FAF03689FC0783F138C489C6429454CEC974364CDABE678674B5BFF00763669C70A2EB16B76C4E85F48F3CA7598F2E5CEA4E54B4AD3F5915E7951B8D5BEF944B2FC118C949DE95852A2057E93E54248A8E59B52166B6B366B10B8371618DDB38B7238509B84418906409F2D7BD34C6E191BA4A5493CEE08BDBF711B33C338B961A661A605077210775F51A30ED487779883CFB7325F6CE60A254387288EC00E474CE7AD371A8DD51AEA2869A55E9534CAA5EF1098CD8F3A5AAC6EC41151A7DC1B8E516FAD0149242383FF00150F7A679888CFCE2A384A065920558DC3D2AEE6BF8CA2CBB35065604A4E8589C9AF7AF1B54D2B7888B86CE720F68F9F7E5A7948AE41E221FF00F60A615DE1956E1C76875865BCD038977A55F3D03D7CB586B7486936E841C94E8565CF2E994E93D7E02AD580504ECA4B962400E4B661AAFC34CDA2D38652F789BEE07A1B02C34CFBDAF58D58F680B05B981E156ED82A0317C39413131FFF0020C2A600EF3CC65F1F40FC079C3FF51E140723E627D79D85F93C50FC533184DD6B6072E55AF677CE91DBCDDC2148D8FD9D4AE4286156120EA3FF0088D083F7A57DA1F042F7B6361C1B89693E498F31EDE2FB426E5C0E51901BE7E9FAD5CA21A14A20828820A20828820A2086ABFCA7EF98A208A9B5A528009CE4F4FDE88214F151D7E63F7A208AC104023434411ED1041441051041441051041441051043424176648198C86B33AE7D4F2E9CEB72B0894544380FDAAF9D73F758D0C82A0082C9258BF0E9EFBB3779B511023EFAE63A547CB5267853101DED7CC00435BCA1DC8099742483C34E141C9F9DDA39BFED41835E607BE3DDA6D6B4EB6C61C1DC4538A3CA5148056DA1A652B50112A260126BC81FF509B3969C162D6038DD57A6597B7A068BF787A6A0A65A7526FCCB11D0F1F31190F12B9B775A17691EE2DA69606449F701927A1C88D2457CB9C760D5336C4C0DBBF5AAEF5B923F27CF5EB3B26515A5082012C4D4519B2AE9606B70D9C5A0AC45374B2E953C8493010080070E472D0091CA399EF50DB492A918829776A1BE8E34CB5B6978B0AB6792948CF403882E4DC71E368F5174EB47FA086951A07733E797AE82A3D33560BBBF7E99F2EDCDD05E12623F8A95517724654E068E3D6137311BC5288710C0573E10A803947783D065DE9D2316A0C5EF7735D5B2EA75ED04942D0485134E3CF2F7A9AD2103E2BDF9A00EA24651DB3F4FF30B7F9A3FE4D4362FDDCF4A3FA187E89D2401BC0122D6A7BB74891B674B6D21B3991327E7D4741F604B398264E9856282B9D6D6D5F5E995984F54A2B200FA4D8162EDF872C7D21E25D52A20FCCE5F3E54EB0F2660A9272A039D2E3803ADFA4372B969A048ADC365DFDE9155BB6A40BF796B4A9A5A99F1500CAF2309CBF42721CF3CE730C85B5DB9870C2CFAE9979D5099889614974D43B1614F3D784629DF6E3589E15B2D6B86E08D3EE3F8DDC30D071A0541B6C5C212E874A4C89415012623BCD4D4B0A29156398A86E9F9BEB099C54A24EF2052C5AD950B9CEFE958CE7B01B396FB31B3369875BA43695DB34E909007F51E425C72748256A56B9F51315352710508092EE00CD83E79F768AEE38A553B7921C39627B53F079D69177780855A29859515924833A664FCE69C22782C5CB96BE7CC72D1FA43505887EBEC7DB9437B4B336CD3ECA5280E5D0212A0202A27883A4EB0321D01D29F4B9C802D7B161C2EFEEF6CF72B0552D4C92106A186F558E5E75ED5235577DBB97631B617B4F845CBF8663F8105DEF0DAAFC2B4B82DFF0054A5600E257BA888E67999A5C4C964592E320C395AA29A3BC3B46252E096034F646BD838D2301EE877C9BC0DF862F7FB2B8AD85D61786600B4DA397A869D67F121AE26F890E1252AFF008B33949351D89DAF2252BE4A83D2854C683D7ED0FE561C4C47CC012806A4B004B9A51BA7946EBEC761385600828B6538F2930971DBE292BE29CCA5423E27B557315B4254E2C96009B5B56EEC6E358557825B10028D1DC697D3A68D9BBB5ED717816E908754A49009F0CFB9CB4CC75F2F4AAF4E214A56E9A1B75AFBBF0D2139781536F14B1D0B057BB71BE70DD6F2D078ADDB6564EBF884C83CA323CF3A4521492E083ABBD7CB9C657842A052EC750A63CEA29A5B5E061DB6FADC424BAE1B75FF007376CAE06939EA94F53CC9FF0034F913A40401365A49D583DF577CBAF48899FB216A5EF6FB816AB13AD73EF7CAD15A956FFDCFDD93CFDE1CF5E7CFEF9D6462304A1FFBA1FF00D21F857A5DFCE1B8C3AF0EC93522F99F3619F9DF449DBD62C9B539E2385B482417152729249CB972CB2E5DA4B0B2B0B394375294EB4039796A7CA27707865E2421294A4A945AD5B81CF51EB9BE9F6FB77D69C14AACB0CB974DC12A48F097212447E6820C67CB908CEA613B224CD62025AE73D2D567B768EC7E1AF8798DC7C895304B092A624B149BBD69516F2E31A5F7DB73B418B5CB97577885C7F5CCAB85D564341A9CA408333967CEA4A5600490C94848E54AEBE5FD8AFA07C3BE07183C32244E40DF005C71073BF967A88B2F16BAB9BB928C52F50A339F8D1107CB9E5D35A7024EE8259C0EA3A53DE516E1E0A9332A10914190CC64F5BBFB7885636AB1ED9CE1559629882DE6CC92B7945A235CA35CBEB03AD31C44BDFDEB56874193D1CD731ADCE510DB4FE1E7CC967712900E5EB460FE6EEF6BEC76E6BDA4715B9C598C131A7D0E71A90D85BAA247432547F49CF5EB5E9FB326CD5B83726EFA3035B37E291C9F6E7C369A9139611500ABE905FE90EC32A8B657B88DFD62F59C518372CB8D28702567C320A0F1267239E7F669AED7D98BD91B3D78C98A1BA12E4039364E19EB4EF58E358AC0CCC22BFC7285A194B1F58666398A366DC18EA623DE09530A7828702499139C831A1D73FA9E506B814EC4276CED4299043EF3026E58F0EB7616EB17295F2A682A0487BF7E0DDA2D8BB4BD78F5BB8CAC25A649E34A8905526047A83AE9E622AE188C1AF66ECE0998090006A386A3E6D5E80D1DA2DF859E9F944D015062F7E5D88B91768C67BD2C1BF98BFB3D874B7E2E25885AAEDF889294FE1AE995AF8F2241201881DF38AEEBFF004F928E2F6FE0D69240F9A1C500351C6AC337E51CF7C52779334BDC28E55615CBDE79C760F64C26DB01C2590326B0FB341F34DB360FCE4CF5EB5F68FC264E1B64C8704FFA48B0B505A8DA0D34A5BCD7B4D0A998A98A51FA8A8E766367ABFAC5D68706700998CF97EB5615ED1DCBA559D0073F6EF118A94CCC4679F2E1CE29FC5B61C2D190A1033D331220FDC73A25ED0130B00DA960D76BFEA115324B13DE9EEF15A9F4A53C460F9199F21F3D6A4E52D3303EF2453335B69EFB422B9BBB6AF1FEED9E45DA1A7F32689E11055CD23F30E922644F2A6B371699733E581BC750FEEB52D0D958E420EE962AD054F5B0EDF6857F1CCA44AD40189099851F2075CB3E54E64A8CDD136BD39E7942A9C4A5428CFA77E3EF431E26FDB5202E14892442C7BDF09EDCFF00DED35489555CC401997B35DFDF9D21ECA96B9A010186B966D0D5DBF69394923E9CF3D62753032F8D42E2F6E60B0C4838896FA6F0A7E7BF0E21DA706A2CF4A805ED5EDEB163E37BCFD8AD9E5BAC6278F61CC5F311E2D82AE5B4DD278B3482D28C891046B919D2ABDB53C73B3B6661158A993659003B05269A67CFCA1D4BD933A6A884A084E4A214C75620D5B3A44161BBE9D8DC52E536F6F72A1C4603AB52037F107F59F94D3B67FC65D918FC60C2A14872ADD774EADAF06FC52313364CE96E4D8396D00E95F7C5B2A5AE316370DDBAADDD43CD5C025B79B50534A2333EF75D0475AEAB86DAD2715864E225AD242802038CC75E76E05A23CE1D61DBFDB70D51CFDE9AC488B8495A91C2A1C312AFED33D0F3FBE944BDA895CC0862E6D415FD18D3E529897142C469ECD2D9650AA161C4852743313DAA550ADF4856BCFEF1AA925258DE2BADE35828820A20828820A2086123C4E1EE0FCCFD8F5ACCE1FF00F156AC8053F2F64FA43A425E50E6A3D89A428540850E9233E7F647D399AAF6CC9CF8B32ED555FA9E1A8E35D1A358D3FF006C4D89BADABDD4E309C212A38EDAAAD6F6C5C6C1F150DDADC26E2E380A4710E26DB2150340796BCDBE30F860ED6D8B895A51BE4CB2ED930A8B708B46C09AA1302033259DF4539FEFBC6B3EED36C5DDB5D82C3F145A8A6E380D9BCDA8C14AEC57F8658209247116C9CE67B57C89F887B2E6787B6B4F985051B8B5D5980ADCF3E9A976A76FD893D9090E1DA8721916CF83BEA06513CBBA0D2CA262232D27FC6A3E72753C6315B4FF00C99A5649356BD78B67A533F4BBCAFAD00D19AE6C47BA7AD6176EF4883C5A77E5A473D24F61CAB444D2A65025F424F2E1FDF9EAB97BB4BB54BDBB55BBBB370878973C44858D0E99F2FD29E4B9656C5C1D4E9FDFEDA192D3BC4901ABCADAB663FB7BC3E6F9FA73CF2F59E7AFCE9CA70FBC452D5200BBDB27D32F586CB96C5C9BE41C9F4A768593F986BDFF00CF6A7689252057A1EB70DDA13521245125CBB96AD3DD38087CD7F6FAFEB4FE4A294E14CEE7F64F610DD520B12417E0FE6E3216D6247F061865370A59E1BC30533A701811A46672CF974A9995294102A0939569D1BDF488D5813173129FE528FD593BE6D9BE79C4D3780E137D6ADA714690FF0081EFB256124833C530A079C69965E712B225050AB06A56B57CCE6D9BF9B888EC42E682844A40512FBC482586AF67A9D6D71130CDDA14D27C3F7509F71232FCA9012072C801FB73AC295B8B24F2D1E9E8F73FD420B94490141DAA684D4FA7AF2857F140F3E7CE72EFAFD3D2964CC0082F4C8034D6C4FAE67A468A934A22B4CAA7DFE8DE28BAB852916C5A265B52B8C89CB88C0075EB3AE7C8D3D44D06A08E5956C7B674849324EFA8A92C0E4CD6E6EF6B8A33C597BCCC758C0B6471DBF7D21C1E034D2F9FFCF2D899CB32AD3BF5A5FE6EEEF68D972D5FB3539C6C892920100DFA5FD9ABC61CDCDD8E0D856CDDBBF86E1CD337B89BB72E3CEA1A4A16B2A794A0544004C71644C6B3E74EDA7337B12480CFF6D3DDB47A58F092C19037CEE8171950E63A17E4632D3ED356CD169D584BAE0924182273E79F3CA7A79C45C3E94B2B53A58CB1404B105867F76B71315D9AD2865012E7880490BE2E23A9E7CFA72E9446CA439706BC7DFE624D2BE21A8FB3CB5F58F5A21BAD172C5F30D78F7C4299CE008D4F5F3CB2FBD6929A58022E3F223558019B378497759812353399CC7C40FACE79F3A6C92C41766F7E578869D27E6CE600D081ABBB0E6F7D2CCD420617DEFEDD1D98C02E4B6AE15B8DAC20E801823B733CBA4198CE7F674D4EF07BD1DB8364F6CC9EFC3A5F83B63267E224A948DEDD62011435A3DCFBAB54471EF6A77818A5EED0DC397CF2DE6DD795C3C4A24264E838A6047FBABC60A6A77413502835E75BB79B5338F69F823610F91246E00E91D18662B619674CAB139698A85DAB6A27358EBE5940048CBB4CE841069FAE68D69975D72FBD62F58BD9CB9135920D05486D1FD8D6DA9A1CC450264881CA673ED32232C865E7A4B45CF21C034550B5A8DC79EAF0909CB9640215A501A375F4FC442DF620C2D21B5000AC11CA67965D73924D3499358904BE6E3F2EDDB48C7CF5CCFA06F1D3CFDF73CB155F3B89E0D8EB18861EEADB8702814A8A465E519C1E7AF3EED953774850259E9A65C73CBCAB0CA6EC59D892B265A88502EE1F5B5EF9F28EA0FB3DEF06F719D9962DEF1F5BB7496F85C2A5126048124E790D0CF3ED3517E319FF0033C3F32593BC4A1541A3E94F6ED78F32F8F7C3E246D09BFE9EE904D8354BBB5FA9D2F58D8672FDE369E0824159EB1A9E59F9F502673AF37787E4997B5F79882262A9D7DDC8E2238FCDD9C5134FD2D66A3356F5D21F5836AE04A543DE57BDDF298F9199FAD74DDBDBD3F05BA1DC8038E55E3FAB343E4C8F9729E808157A0FEBD8BC634DAFBCF1F7A3BACC178A4DE5D5EC26419F08A17CB98CF96401F5EFDFF4E3B3CCADAF84514D3E62090464F5AB797A1A8E6FE279A1299AE4FF0015371A1717EF7FCF607086FC0C36C520C14DB30982607BAD2464272F8EBDEBECEF8551255B2E402104FCB450B3FF0011CB4FEAC3CCBB571E99589526BFC959B677D726B696313CDAF23319C4472E994F3A9C9B8390A2019690CF50900F2D0B7AE511A31C998FBA4022A75AE753AE55EB0CEE6CCB8A53ED28A5460C1ED965EBEBF1A6337032D03FD30D43EE9E63918CA4AE654B9734EBFBCCDF934276A9712541E54C64028F2CC69F0EFF00AD7F1188998759FA983EA476D457DE4BA2402FBC2FA5DC7EB514E358A14CDBB6FBCF209F117054A5C78420671CC77CF9F7353B85C6603FC713710B921412E4A88DF06AD77AD3FAB16EBD9614B2B4A4BB50354B9C83036AE7D59C595B51B6FB29B3D6EE3D8CE2D66CBCD4C34CBE80EE5FF8AB9E407EB54BF1178FB66EC996BDC9F2C14BD4292EE1F9578E6D9C49613642D44028209BBA73A3DBCEDE51AC5B43ED3570FDC5E615B01B3D8BDEDFA484B18B6296BE2604E28C66879B54A929D164686BCD9E2FF8ED2B0DBE9918A7237836FD2828CC781351168C2EC898AFA0B849008DD05E9AE8C6313E26D7B42EF0093B5FB59806CC60EE199D8EBDB9B3C4D0D13201E3F74382418D2418CABCD3E20F8F78F5CE9865E2E6B026D315BB7E05BD2968B061B6484A424A3798DC8ABDC3D9DDF99A42DB3BB9DD9AB4B858C471DDA3DA8B84C156258EDC22F2FAE179921D78895250470A33C911AD72FDB1FF005098AC4C95E0A662E66F12410566B51C74CADC749D93B31A57F1019E940DCBAE9190118260B875BBA9B6B271AF0D24216A692932260830232D620F3E951BE17F8AEB95B4E54E54F213BE2A554BB3DF4634CF9445E376728021208CCB8F5A1A643A4671DD163CCE2B84AF062E14DC614A511240510E2CA877D079F202BE85FC29F8928DBD230D86F9FBFBC121B7B80A55EDC8966B068A7E330E641528A497BD1DDADCFB53A1319B5DBB52ED0B4DF10B9040274300C1EF981F3F87ACB666CE44E948C4160E01AD19C6B6CF47E0D7AECD5942DD2D5720356D502CF7D2272C12B45AB6173C512675939E7FA768A94284CB2509B0B7BF7CE1B6FEF926BEEC07010F2B119828820A20828820A20861C12E13A1E674CA75EB39E5E75B4D27FC75268CC4D79B81C896A71870957FA613C4F2677EFF00685384F14E5DE3AF38F3EBE7EB5AC14A54AC5FCC66FA89D2845001DB2F2A425314C014914BD788BF9F3D0C59BB4B602E59BC66E528751736D716EC323DE243CCADA59E13A81C5273981D00AB26D1C148DA5B2E6C854BDE3B8ADF252E1CBB0E4F7B75B895D9F89DD5A595BA1D2E41B91A17AF2B7511CAFC2D86375FB7D8E6EFDF4A9168E5CAAE30B5A0016CE97D4ABAB84B44E4A502A85009FCD97535F26FFEA63C1ABC34FC6CE91288AA88094B50BE5C3981CB3EC1B0F1EF2A5A8029A0606ED9160FA96BB01D22FDBC68DDB8BBB62196571C2DBBEE39EEF320693A8D6441E95E024E166C8529131C292A21B2FE5C6B4BD348EB3B397F370E8A3EF5C9CB3BE74E34B81110C5D715C7E1C1293A059C9073F4CB4CF28A792533010E6CF42723CF89E7120A97424B74773CA95E462EC6141A425A52D2B52466A4990673CA796639D4D6186E9AB16CB5B96F3F2A888F54B5281205C921DDEFD7F30FD1708E60E71A67F4D73CBE93528898803439BB71F6DA57386E517240BB54549E14ADA1C25F4710C8C7A7FAF9F4F4DBE6A29F50739387F5F48DBE48527F890780D0F2CE1EB770811AE5DBAD3C9335096AD7C9BED7FD6A92A4960DC7A5EB4B509D4758A96F5DBE0A78D0184478024C833EF710E5273CA321E553322685331D5AD4BF13DAB5D3364BC3A0951090952BF9716B1A72B73AE9376AFDCFE1C21F7029432053311A419E80F3F9549CA98C28AA6A48ED66EB7AE70C57242545D00306A0727F35F28789B84B00340CC6A44C7BD04E874D35CF2A8F9F39A6286F501B8208B7F41AD0CA6E1C95380467D3806D5F8985C5C9390933D24FEB23E535AA278554AC86B0767BDC7F40469F208B247507F07D61CB2E10D5C051953BC3E11CC84C6B33A03EB4F25CF600DF4E1ABDFCBA36692A428A907E9003EF0CEA29C3C8C5A1B65B3EEED5ECAE2F81AD683717EE5A2995289F0D2961E0B7028E664A410235269E23140A4835245079675E3E5C630A9133E6CA28291283FCC16274A5AEFF007BC31C1F046367916366C2521BB26C2484819A9491C4469CC4CEBFA56B1CBDE9E55A9763C35F7E64C4C4840548521CB960F6039F9EBD225AE116F7772E3CFF0019414C2008907860C8D333D34F9533A126E3CFD4F9F942A842A5CA084B120E76A9AB7AD7AD629B3B12CB094215EEA492924E704CE7F1EDEB58850A80A1BE6D6F387801403C5CB90CE33A234242886A1ADFF4FA43776E005409D739D065A9E7C8F5CFCE91981CD5D8B5B87F5E70DA6A4EF312472D381E7D793C473B720716A75D20E639E5F12338D7B068A705B8B3FB7A9C9FD690A6170E14B0AFE4A7140F4FC5AFCA35ABDA06C9EC4765AE54D254B752D2CA12904A879C67CA7AC75A96C34D4A1282097CF362F9DDCE56E2C2D1D8FC0625A315BAA01814B3D32A803BEA79C7212E12E5BE2B72DE2E859525D5786003900A233E2D3CFE11955B30389010904D40E5CB91CF933691ED3F086270E8C3CB48DDDEDD00136AE65EAD66FDD66EDF1342521014AE119252341DA35D0C1ED9F39A915E212A1722B4C9FB9FBDBB474199814CE4FCC74AF785C5F2FBEBC3524BA5DFCA09D673C8E7AF5D3D3E3CA9A2E6E76BB1CB4BBD7A74AC4362364EF1748CCFE3B353AD4DA2DBC6F114B4D32E369754B24CF081C880200A69367B8209ADBE92FA5DFDE8E23383D8A4CC054906BD0374E56D7998B5B10C51779E1212E21B724407494F4D633D20F6CE9B99C4B24292C3F8BE45A963AE917BC26C992894EA4151DD3FC402598DCDAF993FBDEDF65D45DB2CAFF10B4389584F096C92233EA0E7A03976279D43EDB9DF3B04B94A2E7748615A1D070F4AC7923E2F61654AC76254801201A0CC6A1B91E0D1BBC9BB63C4432A42F8D24498CB91CFE73D74AE4B84C38918FDF0199449360DAD6ED5A37DA3CED89967F9298BB8059F9D4E608EE0C5CF66A0FDC80D25442000531AF126065CC08EF19F6ABC0969C604A12E4121F3BB120307F4BF3888C57D3208240556A6C1C66467A6BDA30A5DB2BC63DA7F74F84DBAD017833B8AB97E09C921DB74B8D822352065C519E5A44FAFFE026C6323178599BA2AA15E3439F3ADFCCC71DF15CEDD4CD17A299893ABB5A9AEBAD44764AC5D53EC5B0692B090DA119CFF0062129303331918EC62BE9C787538A4E1A4EE9DD0501ABF4D0545FDF91F2FEDB96B56354966FA8B1ED9BEBF6CE9131E21B74A54EA5652A895019274CC9390113FB55C7FCC44A40F9EADD201724D389EB7F4D21BC8C2CEA50D6E75F77E19EB0D6F7136ED185DD29E6D16A94951714A809004AA4E8204C98CAA0369F8BB65ECF96A5AE6A0EE8352A4B5B57F2BF78B260B08A528259D4726BDF5B0CDBF6DA81BCEF6B2DDFEC7DC3D63678BA31DC59BE248C2B067DBB8BF5AD23F2A590A0A2A9CA23E735C47C47F15F634854D1F3E51500AFF00724316A06CBDD2D16791B2B78A7E8AE6E2F67FBE5525AED18A99DF26F8F78D85A2F706C39AD98D9FBFE34B0C630D5C59ED1B484129529F4A4F08E28E264FFD08EB5E58F1A7C7FC461715324E1314532D2540042C806962C4D19A99F38B1613C3E850F98505D4CC08A060D4E3A33F286F83EEBD8BEBAFE67B578E6378A5D9505AEDDEB90FDA49CD4025C1307CB3115E72F14FC72DA38D331271733EA7702629EAF70F6D74E959895B11200013F50CC870391616D7F35C9EC5AE0B8484DBD85A069A68421A4B690D891AC72922550333F1AE3D8CF1EE2B684C56FCF242890C55EA0BE60B3F9089CC36C800074017CAFCAAEE39D3562F0E9788DB110AB5682644C204FCCC44763F2A7123112F1A9798A1BC41CC568F6F7DA2451B2806DDA13572EC73AE75D1E0172C3612E59B4842B4571244667B69ACCFC2B8D6DAD9D8A5F889A4AD46515644B014E9DDBA64B0C1A93BC998DF5301BB6A5C97F4F2CA29BB5BB7C10D9E042345F0E47399024F3E53AE5E553F324E2767CB4CC0A208DDB38146D19FF3A986B88D9E8520B3922FBCCEF6D2FF009B45AD866D07FF00816D93174DAD630EBC75B4DCA947DD4121284F88720389648483AC7781EB3FFA7AF1BCDC36D4C24B9D38A46FA036F367673A80C2BD328A16D9D9EA017F48200A86AD7FBAF08DE3B2B862F059E20CA7DC71A42DC1A95788D8292206866467E55F62BC27E24C3E3763C9226254F2D1621DE96ADFBD41BD0C72CC7CA5CA5949AB6F55249B96E1A75EC22EB654168E21224CC1D469AD5A02D333EA4D8D5A1ACA0426AF7CEF427DDCC2B598560A20828820A2082B06C791821B05242B965ACC41EDE79D42A3682A6633FC32490F548371715360F7E02F585424945297AF5CFA450B751060C1E922467FE321E952EB929952D5319886AE43573473AE7CDE184E594AB749607372DF80FF009EB6E5EDB3D77885BDDA4AB82C82D2100E4E0793C264660F083F426743A61B694B5A6648762BA298DC07760CF5F22F9C3BC1CDA906C0E5AF63C99FD446897B5AEEC2E7F96DB6F0F0041FC7ECC3BE290D025DB945CBA90E8570895042279E4267515E6BF8D3E0346DEC2E2A7225050285127774196AD47C9E8D78E8FB0F68D65214C145986603DC8A548B1A1D230CE01B5B6FB5383DA5EB2A0DBEB425B76DE785495B4036B0539C4A924C11A57C9CF1F7857FECFB6A761F7373756A04377CAED6CFBBC7A2FC3A913300958AD03837A8E0EC4B6B571138DD9A5E1C208438661472332799CFBF6F49AA22B06A975673477C8E6DF819923368975A0272040AD9DA81DD837F50FD9F12CC780EAF8968CF8A7AC75EDDA0E99CD3698B12AE403CFDBD5A90D16029F75B81ECFE90F9AB9194E7AE720F5CA333EB34DD5B458DDC73FBD9F4E8E2F0D148214D523337E8E58439173A67D39C65F1CBE1E95A0C7392A05EB4A870D539E661DA255052ED762C391AF3878DDD6B9FCFFCFEBFAD3E958E342540D01A9B599BB1B5A34561F41DBF43D44495BDC7BA9274CE7BFAFEB9F99A9AC3635C02145F47CC11F8A54654786536433D393367E9E96A65128DDD8C803E7A09CF31A7C797954AA31E4A4EEAAE2D4EAFCF817A3F0862B906A4D6CC19ED7EBD61D78B2AD411E93F2314DA6620A94589B9A3F3C837B7864B94E5ACDC7F47CE1CB6F0C88C8C41981F4394F6F2ACA67106E7AFE7BDE8D7D234F95BA2C0F9935E5587497A10003ACC91E7E83EBE95212A783572096EFE9A793BC226555C01D6E3CBCEFDA00F1D38943D4FE84D3A4CE049A654D7DFB6307CA1C3853DB432753C6E295EF13F1F8EB51B893BD3093776603261EF8BC399602502A2BD2C4DB9427E17657C3FC5378DDC6A3B887CC8E16D23CF5F3FDA8845441510F0939A2BCFF5A05481AC651FC875F4310376E70BAB13A46435FAF7AC4C04023DB3DF85A1E270E26241677AD785743DA2356E8D4188F3F8CFEC7D4D47CE21CD0E556A5B8F07F511ACB0252EC03721E963CFFBB5F1FC1DAC5AD5D6AE1295B6E2542089047DE9F104D29869E1EB514A71CAE0B71EE0D62DDB1B69AB0D325AE5962935D4E7DAFC1A39E7BEBDC83AD3AFE2B86DB10254A8424C19F200CF4CC7A4D5870D88DDF50E73E5CEF46E3468EFFE1BF1B7CB952C7CD3BC00DE0FDEFA79E6F411A717D8662B862541D6821482AE20B0A0A80729D397C2454989E4DCB9CF3FB8D3FBCBBE6C0F19C99D8742553379D981555B817F2E76A45BCDE3AF070B6E96C198304E506273396791F5CE915CF228E69535A7077E1F9E57EC26D2958A1BC374B805C31E9F887AAC6F0F527C2B9E052849311CC4E527EB4DD53C005CD4D8BFEFEEF6A343D9B889724198161219F260D42D4F7E96D59E10F6D26D35ADB5921D4B2A74090232C8F29190397C2A3CCF24FF002163AB654CE8787E220F15E38918013126686014012AD417A3F316EBAF55F727B14BD9BC36DDB525521B4A8920EA44EA40F3CE464072A87C5E20A94506A05186B9B823A37121A8D1E56F88FE2197B5B15366214FBC7573F80FD684E95D86B5B22FDCADC1C86B1D3F688F8E7CAAAF3E4EE2FE6002B91777EB98CAA3AC713C5E2D23FD304BD180234A9EB7CE2E54307C36DEB7716D2D869F72E14150901B42949923B2753F2AB3F8687F938B932C1FF700AA0A694EAE699935BC436227ACA666FB1410C9003A8DDE8F95BB691AE5EC70FA7783ED65BDCC72F9D7B10B6D947B086F0C57178ADA0BF6CB6DFF000E4103310A098D3CCD7D0AF835B351253859850E06E9A0B97D2C45B331C5FC64A56E4E29504BD89341C0F3B6763CA3B5789ED2E0DB3B64A7AFAF2CB0D65A4125574E2590001275204C011E9E75EE3C3789365ECED9D2D33A6CB42D08662520EA796AED1C706CA5E2A66FAA5AE639A2921D357CFF005ADA91A3FBD2F6EAD8FD97B97F66B63ADEEB6AB691D516996ED128BDB52E8C802942828827A6BAF9F16F1C7C5FD9F804CE12A7241485070A00F30694D6B9F289DC2786A615552425814900D35DEA368D4EED1AD8EE31ED33BE7BA2BDA67D7B15B2B78AE26ACB0455DE1F88A1854487DB54A01524F4820FC3C57E3BF8E789599F2B0F8A5D94C02C80C5F27CB3EE6B16BC16C192809594A41A312056ACC33A722DCE329ECBEE5B77FB20DA6E1786B78E63EA016BC571665BB8C483BA9525F8E3E29933E43BD79536FF00C4EDB98C9CB32F1338A544827E628EA00ECED7358B3E1F62860771CF10F40039A01F7E228D1976CAF2DAD2CDB65D0AE36C11FD503C4009F7475E102027B0C88AAEA36D6231C8F998A9855354FBC564953D75A677CBC8CC49C0001212C4021BEFD4371A5C0842E3681B40842608F42627A6BE7A6994655178BC22B100A92C49773D684D6A5C7A7187C8C0A52E48734A016167A5AC1D8171D61A0C40DC8F149E12A9CB498819C93AE5FE62A167603112BEA028330FDB27B96F505E1F4B90909DD0C40347B8A934CFD34D63C37103527B020F61F5E9972D2914ED5C66114005AE94352CCFA5FD87857E50C9B3FF006FBEB0ED9BA1C31391981D0CF4CF4927A6B9F4B56CC54A992C63A78057724EA1B335F3CAF1133E6A513B74F604E63306F6CA9A0AB8768BAE1E124E5A723D758F803CBE34DB6C6D2C2CF96654B6DEABB52C5B57FD8D03467E599A9DE48398A3BD19B91FE8E4F696DEE12BC6B66F116AD65376B4B772DBA9C96855A10F40234E22800E42454C78076FAB63ED492B0A665A58823506B466F7A9883DAB800B0A7191737AB68F97172348CEBECD9BC73B6BB0D87AAF9D42715C2D4FDAE2ACAD50B6C36EA99B62B495482A4360898CF3026057D6FF0081BE2F5EDBC1E0E4098A51DD4821DC0343C1C1ABBDF2668E3BB6B67FCB9AB601D4AFA435581ABF106D71A3398DADB6585B414233E9D394768FF55EC9C34B32E5A42AA77479811525A0CB5141B8F7EC8A438A711A414410510414410560D41E460862B695C648227F7FDA7FC72AADC9D958846D6FF309FF0049CD896A0CC7EF3E30E12AFF004F745EB539177B7A77E109780A05464124CF9F3E9973F972922CD8B989561D72C36F100303D5FDEBADE3A7C92B5022BCBF40DE1838CDE36FB6B6548F0D321C4A89CC1CB2F39EFD472269D230389978BF9A15F4B92439AD6BEE96EB1B4A1F2D41CD012E06B959DF96A6F169E3BB3CF63AFBB657A8B6770479A710F5BAC152965C6C89283EE9851907D6A5F68E0656D0C22E44C46F132D40821F22053ABFF6F162C26D64480192833014FD4431605DB514B59F5D390BBCED96C7370FBE1BBBEC45A5B3BB4C5EE9B187DEB69526CF0E52C00B4DEB86196FC57DC096C8D4E4649AF9B7F1B7E10E315B5F13B4E525A4EF2D4285B95B864D51DBD11E10F14C8998144B0C16000A4E85C5F893972BC64EC531469DBC63F95BA8711E1B4ECB64282D2EA12B49491120A4F5F3AF0FF89E51D8D889926602E85148E2DD069DFAC742C1E2062929B97772CEE0D998E86F5E10F7F18AB85788E4A565290A072208196BD62738EDA455490938D4EF21C82F703D1F2A67931D2243FEDFF4FD36353A0A03C0E674CC712E1A749C81CB399E594E79FCFA73AAD6D952F0153BCE34FB0EEFDE911F3B0C50A2925CD9CF0CC77AE5CCBC3A0F1CB3CE791CBACF3EB9EBFA536C0CF5626589801A9B171CCF2B5A9C328752253201567964039A5A1E36F19D4E99F7CB223EFAEB52B2D6A04006835B06AFB6AE42B4817298D183BFBB5FDF37CCDC840824C8CC4E9EBD4F6E644CD4AC9C49481EB6B65DFA529C58CE4D1C0BDE9F7F3EF126CDEB41241041904401033F97CA633315228C61490C6EC286CD6A397D79B5CDA3A6A1CD081C39B69516D224117CDAA08E20349CB5119CC79CE7EB4E3FCE4B80F56B92C6DC0E9CB943338770E01A92EF7AE7D3434E90E91760F2313D33D3B0FF0073DA9DC9C5A580A1275E15A55CB54EBA3011AAF0E4243379F637FC3F387ED3A1690648D753F7CA3BD49499C0B35CE6EC03396CF2E875A886A431208AE60C384852B457C499F9FEF520858A3B1247507367E7EDA34514A6E9F20DEFCE1276E034E14C4981A673D3EF29A426252A39823F5ECD23644BDF4024917E63837B2F0A25D2A12065E47F7A4FE582F7A5EDF88C19605DC3F11F8F75D0C2A1E200100C7A79567712C2A789F6FE4234F941DFB1B9FB7F51E195273D4E7F3AD0A085820D01D687DE543181F4AAB56D3945B778DA8DC2C83CF4E5EA0919F5A4A6CE480451C6B7B3BE6C226F0CA48949A3DEA00AF57AC462D0B920900721CC91D79FED51F35495367EF30E4728426618AD6A21EB5A1ABF7B71F286E0381D25C292DC0084A7946B97DE51AE7484B1B84B92CE2DC1D9E093226C92FBC79B906F4FBF631058DE1F638A214CBEC8532A10414827969397D3D0549C9C60401BC016A55ADCBD5BA67160C163A7482085356A145B36E35A07E3A55F5976EF719B338E3B746D5BB965C7408E04A12DA55C3CA0729EBF1A79FF00714121BE9A56C071E4F4E6747A742D89E319D83DD1366380DFC4D5C3F37F77A46B2621EC8370EDDADD62F8A5B5289095384119CE7EEC4F5E99D657B450522A2BDF3357AB7BE7D6763FC59C2E0D094CC51A001DEFA3D7BE94E30F2C7D929C438CF8D736EB4A0FBE56A25644F972D23E191A6AAC6855986957E1C39E5EA0C9E3BE32E0A7CA32E5BD410F41DAA4F3CEDC6362B633D9EB65F035DBDC780DAEE5B852961283EF01391039C6667B742115CF46E9622C5F869FBA1E51C9B6E78E66638CC32A6A92953B1DE6353570FCCFEA873E3569658682C30829E0425290008C9207FAE9D6A03138B44B9A4A8B819BD6B5AD0F3CDB368A64CC5E231690B98B2AE65D4C4E7534FEAC21EE1AFB6C073C549515FE58823312013991969FB53156225E2C89680429D83655B3D7D2AD4D0D7F152A615956F11C9C963A83C7DEB61EF676F86C86ECF6BB1568B366E61F62B4FE22E3DC2E9B86DC6D3E12841570A8C1D62BA3782F62AE5E225CF56E9485051B937D326D29E71133C94975294F50340E35F7DEFCFEF629F6ABC3F753B27B6F8A61FB3B88ED0EF1768EF880ED9DA8BAB7716DDE3C18F1085070A5285A44E6400790AF69F82BC6F81F0E61A5A6784BA11761906A3915E2FEB5E7BB7F64AF6829C12525DC3BA4E8E3576EA6368D9C2FDA37DA2F13FE77BC8C69DD8ED9FC45616CE0B82DC5D585E30C24884BF6EECA525C4F091C8C9390D281F103E37CE5E3662309885A6539000511FEDC803C433D468F0C703B1918597F2CA522F972D47EDEE1C18DB2D82DCA6C16EEACD0E1C370EC5B106D2957F37C4D969EC4BC4199587C0078A46473AF3178ABE256D2C7159FF226105DC95927851D9EF47EB5112F2F00898A094A149ADDBE9367761620EBD6ED78DCE34965F5B96B7B74A57BA1285B92CC0C824091EE819013CA04E83914FDBB3F1138AE74C5A8135DE24FBEA732F60D3B85D9492005212025DE9AE741DDF3ADA1156D23CE0F7D8B4E28C9C4A7FA82720788C67DA35F854CE071F805247CF92925AEC1C1BBF4D444A4BD88CA13113266ED7E97A11986AD2FC03666B0D5370BB9578AE2CA8AA4EB33197C8683975AAD6D19EA56349C2AB764B80C3EEC776D4CDE99461783F94ADD0000097767D437322FAD6249A6ED9413C62546072CC7D67CFE13562D95890129138953E46CD6E0FDE9E51A2E510E52D56BB9623F2FADC3C78B6C2544344840D04C7E9F0D2AC8B99859B2C83287D4340E3A3BEA1AB9C6C896581FA4645857DE77308159491999FD3EFF007E9558C7E064A945494A5817A8D33A574CEFC214DC2C6B5CB4E2F0A22E0275981D4F799E71150F88C79449560A4D1767B369667BF9718AFE27013264E2A06E5E9F6F60F3B05C5EA0260851D7BCF6F53DA3AD57D5B371F289C44C98A29772378DBAD8B11A3E4CF47F879265202564DAF535D3D8ED9C95A62B6FE33368E5B5C2D170875B52820147BC929053AE401CFA537C3ED9187C74948554298D58B83AD7AE5D03445ED259099891BAE59A976BF96675CA312EEFF1373751BFA7F67710BB6ADB6776E1D4ADB507382DAD956ACF8812B39252A71C54467C4A98CF3AFA77FF004BDE3593825E08E2541481BA0906E3277E2CE6BCAD1CCB6D23E6054C4CB1BE9A25C6B43D1AB5B1A56B1D4EC32E9A36CD80B4A894254983F99244A543A820820F39AFA7F83F1061F1F85978992C10509B35683DDFBC731C5A0FCE59C89A6B76F66CD5E53156186705104144105104144108A8428F9CFC73ADF786E367FB778502C2535CBDDF2D229A6B3524BF166E8DEB942714A913273CF9F2E43A5353F4D48A8EE3BFB31A2D05E82B98B1868E351390F3CE79761A79E9583894804B81467E85AAE6977FDC6A2528107773BB569E768E677F11CDB0C0F07DCC6D1E1D890B773107D36E709B25709BBBCBA43E92836ED932B0CBBC0A5F0E6919F979F3E2C4F9733033904228955DB31968FCBB476BF03E0819067EF2895EE9097A067BF03E7A472EFD94F7E3B59738633B17BD8B7B7C2F1A59745862AB4AD9F16D82CAD84F8CFF00BC4A58F0D10040564328AF953F13766CB99B467AC005D6A3AD09B5BD34B8CBBCEC492C25BEF53270C72A81AE95B51AF1BE7637A875A43ADBE5F6CF170BBC5C41624899C811A11CA32ED541D958444A400774024DEE2ED4BE5FA8BD26480809005402F571A64C694B0B989C6EEC04C0D7427940EB3946703D22AB9E2BD9E89A8580CED7E3477F4B6552222F17860AAB5791A65D2F51FDC546F805646349CC881CFB7FBF5AA7E100C3A0201AB97007134E4DE79BC252E584CBFA921C700FA0E95B707AC3B45F080273D73FD7B7EA741CA45130383E791CB2B7A084A64B241296B8A5B5D2997E9EB0F9ABB0A0924CEBCF9E9A6A7B7FBA7489A1C54B771F815FEE23A6C925C1A0E1EACDEEB687A8BA190904E59C9E646BAFEBA74A7B2D6E1F7806B3963D7D3F55868AC31277999B571CB85EF539DDA241BBA1C2923E1F0C867FBCFA5644C014E1C936A023A5B5E6611128824D9F5D2F461687EDDCE5F9BEFBE79794F5CA9EC99C090D716D43DC53D7F508CC94452A470E9DDBF312B6F78021327AE5273E5A7FBA9A913451E8783E76E3EF50D0D26C81739817BE7C06991E31248BD498D27439E60FA1E7CA2A5513ECCD4B3D1C77D3AC3432C66FD7FA8A16B4B8B9009273CFAC7A74EFD666B2A9E1CD09E34F7D237480031CACDF77E3A43969412224E713DBB4749CFF007AD7E790F4BDE9FB84964166637F7EB0E909073398E5FE7EFE5419CF93721FB86CB98C0B676D7DF1FBC2B5AFCCFF00E6F7D61A9984162F5D2DD33FBF3881BDFF00FB0BF4FA547CE72A249046447DFAFEEF13D842F253C00EAF58897397AFE948C3E979F4FBC377397AFE9442910F73CFEFFEB4411EB6CDB2DA05680A590413009E713F71442A852C00C12D567EBC5E115DB594FE448CB2C81F9E5F4A216DF570F388F73094B8E179A4008511000E913CE338144604C228E09E37AF5F7DA1445BF8060888E7C8F231D873EF44677CB3325B46A5DE195C3216EA960483107D35C872FBCAA1B1D24A86F11ADA84BBDDDBEFC1A24E44D1B9420062E2A03F4C859891D2156ED867967A8E7A89888CF5D341DAA1F08F2E7821AEFA675AB59FEEF0DE74CDE71955CE7C75ABD6343BDBEADF686FB61B67300C21D72D2CB17BFB7B7C49E6D4A6C2DB5DF32D80B52722085100284679F4AECFE1ADA2254B960AB404BD2EE3B72A9882C5A86EA998DB893CB8F95BAEDB6E13D983763BA3D91C1EE5BC399BFC5EE6C2D2F1C75D6997125F7196DE278B841FCEA3CFE3CEDF8DDB72E54B24CC724506F123A720F4D78D22B6B5CE9D34A10909961F7CAA8AAD8A69DCB3F3778CF78A63F6CC214E9B7658B8094A421A484A4250385B006A3DD007D00CCD71BDBF8E189C42A606AD28294B5F53CEB7D21CE1B00508A954D00BBA9CD497356B062FC39B4639BDC7B12C4D6A6DB754941910091F08F2E5DFCEA838E1BE556A963C789E2E6E35B5225A4E0C862D42CC0587BAE6F720521807EE6DE1A714A52D2249CC9839F3FDB23CF5150A6532AC75ABB6AE78FB689AC3E0F7402E920D9854FB2F9BDA3DFC6BA3593F2CBAF3D396835CEA4244BA501B1BE7719FA6A748999787DD4821346E8697B7AC5DB85BA576CD2944E7C53D400A3A0EA0F5EA6293561C99AE1D9C06722AD9E5ABFF00422BB8E4EECD239D0FB6D28E4C5C4C3A32391E93CBE7A8F4CA3BD58307240DDA0B5989D7954B573FB3121C343A99CFAE75341C000E50000504325EA3CBF534CF14CC5ECD5E5F4C6628FBFBF8D5357249C715815715FCF0EBA3EB1B265A58BA5B98D79E7F98F2419CC65AD48ED29DB982292C193471FA61CCBD60549770C082E2CC69D2E215C26FEE9DC41E64320B5625210B293EF78B32674C8FCFCC57199F8829DA454E28B198A07700D5FF004080F5881DA1856A549503571CFBB659D7478C5FED13B2371B41B2831CC19D533B47B3AFDADEA5E68F0BDE125F6DE7405247147828502274E55ED9F81FE269782183056032902A585C020F534FB6747C7E08AB788723EA7A38A70F77B3D6378B707B7B6BBC7DD86CDED8DA5C05B86DFF000772D85494BB645368B2A03FECA6D473CC99F2AFAF5F0EB6AA369787E42C4C0A2A407AD7A8E1D1F23AF24DAB855231AB94414073BA45055CE9D5867AC6CD57A062BD05104144105104141A0274821051924FD690DFFA9812E6AD90CD8FDBBD2352A0FBA7CEDAC794BA405B0362EFD1FF0010A01F533F51C9E1A2AFDA4AD6C702CA9B8E22008CF3C8CE7F7DE9962C7CB04873EE8F5E1E6D95551294B248200701EB9D3F1EE90DD58836A4DC1085245BA14E28AB294A50546328D07330488AAA62B13B8953920A4289198B97BF3D3CD8AE65A9050ECADE20063992DE5DF83C70DFDA0308C53DA3BDA57F97DEBAB6363B6096EA2C6D41294DF2EFADA1C55D20CB6B2CBC9E268A47BA60EBAF8E7E2DF8C932F1589C31994015F4EF3B1008B3DB5FB08EF5E0AC37C8D9F2F7C0DE6AD8BB97626E6A6A1F8F18C3FB47ECDD6D87ED134AB8C47107459B9386BAD3A14E24982A43AA2326C1848098F7644D7807C73B6133B1335654F551777ADC1BF0FD523AF6CC98997BB5A8636A6552CD9B9C890CFC364366F07BFC2708B4B2BB536A7D8441282A28293920E9255C31C5AE7AD72E46DE4CA252179977229DEBCB99D62E122724A4070C33353C1F5EB5E81A2E24F1A44127976FD07EDA74A8DDA1B6538896AFAD2487A3BBD5AC09CA8D946D37FD4FFC7461EFB3B738F0B2E2A1D0A002B91999F211AFD67388AAB9C4BA94AA33DFC9CB1A3C315000D81072FCFA884D771E0E4A24C69C267FC73D7B1E74A2279A90A26D6B31F75AC69B81BF8D356E3AE55890B6BE416D27333ACEBE7039FD9A7A8C4501053C43FB670D952BC631FE3A540BB31E845F36ABC48B77A88E6077313F3F874F853A4CE71424BDD89667FD7B1091C0D281C7176E7D1BCF263128CDD254849139839120C41F879473E94A267310C4BDEB979E6DC5E194CC2906D6E4FD2943AB5B330F9BB94C6B19794FFBE733DCD3C953C13A72B1CAFC1C5FCB268A95914039DBF421F35789809F78F48EBF796524E7533879EC0390DA3F3F400E6C0D2F0D26C87FA5A9C8BE5E63D6B9C48B5700C448EBE7E7F1F873135288C40342486BB1A7BFEA1B2B0DBA93F4853DB5F327F5CE1E22ED2980788EA2674E739E5AF3CEB2B9EC7F950330259ED5E37E1AD2F0CA64920B817C9A9D19FBE6F0EDABC40000E2275D75ED964639FAEB5A0C439FE56737166AE74B65DF46EB9248219AEC452CFA57F6CFA44BB174D142409CE7F365D7B76F8D6558A2C18B1A66D72F91FD00781762B94A62E03E5FAA7A4394BC8509063EFF005F856AA9F675543D01704F17CA9701AF0D8CA5120EEA8B543547A5CF768B7EFDF425F58E6408EF20E7A9D23EF3AD8AF7EC4E4EC4B70A74ADE2C1844BC9045F3ADFDF488972E10391CA7E197DC510F100877CDBDFBF3868BBA41204191FAC511BC34710A767872F3F4FDBD28821C356E80DA78BF3738CBE7F7E7440E0355B480E1E16A8C8039F2D75FBCE32F2A23054407A9CEFE7124C36DB2C2595092999F5D2328D3EC5109B2D4ADE0A2125E84FE2BEF8C475C59A9D27878403D49FF7A7C0E9D688583EBFB6B5BCB288E368A6D5C2AE1319C8F975EBD49CB91ADB13212AC31555DAEC694CDEC4DFCAAF0B0C46EA00722B716377E197DA164A1291A09E754F520CB9C9235AF0D1C3F2E0E2958426621C3024358D3F7C757C9A310FB40EEE0EDE6EDAE1092D0BBB2BAB1BAB22278D28B7BC6DF7818132A4A2044F43578D97354896921541DBEFA6BC223664DDF514545CEF1700F7C99835ABCA32EEC86D17F37D8DC1136CD949366DDB25C7C43893628432EF11131250784822728A4B6A6D39A842920B8B67AF46E8C2199900CC0B0A502FFC41649B0A8F4CBD623B107AD6E5C5E6E2F382A519929C95E920FCAA9B331866A89726E35CEF7E5167C0615E50243F1CEBC8699E67388A6908615C4D0CE79F4FBEB1E94DD52CCE340EF4A5D9CDE85BA5A25E5C80C10121BFF217F6D5ABC2CA40721C580547398CC41E607D018EDD7518204EF29245F8335B2A55DBD1CD17004BFA40492D9FAE7E86AFC63CF01BE9F4F2E9D2B7124203311C68077B6B9C29F315C29CFAE79E7133689E06D0907213CCF53F79C69CB2ADD321D4E41A376CC598D73115DDA65E6D1201AF2341DBDB9A44F5B93A8F21D0CF3F9FD6A670B26A29A92C3D3BDFCA23A24D1A791A7AA4800D1886FC7BEF7821AB90083A0EFF00BFAD4562177702C79585FCA99C108ACC0D0CF2EB974EFD2A0D52809A565BD2B933166CF9C3A4A5CBE432D6FF00DC362E01208206533239FC39F5F86B50BB63103E5290E5D8D7CA96BF1E42D0BA50A5073BA34D7EF15B37EE5AAD2B65290858578E63DF24084441CF339CF2E432AE458C49FF0024AD2186F397B9ADF46074D4E50CF15864A812A033624DB50347B5B2D6B14D9B571892B106AF54971AC4187985A3320A5C6D4DA723AC050991EB39575EF03F88666CD5E1C15EEFD686A961F50F4AB7E1E2AD8CC227EAFA458D8703A52AF90CF568B0FD9331EBCDDA6F276F373B8A5D04E0E8B9B67F669BF10F02BF13C77777E18510930A589E0CC1F39AFAFF00F00BC668C56C0C24B54D752928497232C8BE742F71DDE394EDDC0033D4B523EA0EC5BFAF2D63AEF5F41A394C144105104144105609604E81E086C5414A206467A743A799EDDCD343FF00BC6A0FB8673F878457FC8E56FCFEA3C518498FBCE9F4914E9EA4FE217921C025E9F9311EA6D2975C75510A02644CC40EBF1FD269AE3801289CAA48FC1D783BE74021F8A25290EE6F7677A76E2CE6DC2CFDB4BF1856018D5EB64A549B37CE52238585F4E7979EBD66B98EDC9E5089CC48FA1449E878E59F0A350BC8E090662E525601DD26B424B90731AB5F83691CCCDD4356588AB17DAC712955F5F5E5CA5D5C02A2597DD6D3EF6A0C0CB58E5957CD5F8CBB4272FC47899695AB777D4C0167A1CAE6AF4E7725E3B8787E684609296C870ABD331703A8222F5C470DB7C495F895B214E2566094CC4188EBF4CA72EBE57F11E1E74F4AD6497A972795EADA67D62E586C604B7D4CCD98AB57ED61ABEB0DDFC1028173878652204690398CBEFB5719DA089D2A6299C313AB54F1274C998F08B2E17690A00A532A8EED40D634FD45B17964193040100F4E5DFEBA76EED70F2E6CE35A825F8FB2F406DCA827E562C2C0726BC7866FEDAA62354BE06C27A75F4CC0EBE7DB3E55ACF0A92B292F562C03D40ECE33F485400B5125C0A7A33F4881BC7413CA679F4FBE7977CE45665CD63987B81E4783F1D0BDA1CCB96EA029BBA9B5AFF9FBC356AF3812124E63F7D4F5F334F11345DD8E9996F5E196A61DA70E0B101DF3D32CADDC3DE8F0FDBBD0AFCCA811A93F300E59C098CFB9D69DCB98406714B17FD8B37BCDC9C28091BA05726FB5B958359A82262DAF416D2388F38CF3991C81EB3F38EA326794B3392EC4EBC49776E3DE223172B72636E8A52835F4E36E3122DDF640A8E5A139E44C67CBEE29FC99CC41C8DA9CC6AD5E1E511D324850702A323FD39E50E917C018E2CB9EB23319EA6A630F3892C72ABE5CF5F6EEF0CD72B781A116C980CA262DEFB2199E5AF78FA8CA474A939739E9F503E6071AEACCF943654B20B338399B7A7DA1637C028C100E53999F4C8C4E7D7AD0B985C392F5B7DEBEFBC64E0C285535EBA51EEF91BBF1061D377C081EF721A93FA7D6739D2693336F550A8ABF2BD7A7286D3304E480917A86B7603D4D75CA45AC440481C5A6B9E539763F31FE76F9F5B06F3ECFF7867336706074ECDCFCBD987EDE240089F8931E79447DEBCB22702CD57FF8F0C8DFF3C4086EAC00161D48A7EBAD32CE185D3E1C714BE67498CBAF79CFE7CF9C8C82E9F7DB4CF81E79292E58969DD1D6235C744E7F7E67A9FBEEBC291EB69E3015966796BE9E7E74410ED0D1CB98FB39988CBEFB9042A4418A21BA955739F97EA1CA3F30F5FA1A235F9838D32F6605FE63E9F4144642C6448F2FD4534463E6F151F7CE105B3C6A2A024E4797974D7F7E666A41697C29A3B8A9D397E6ACCD0D5734905CB0CAAD4BB77F79C79F86FF00C7D23FC7DF5AA74D40F9E684D49715E9F807C9E35130A894B8C9ABCADA583FE690A8B14DEDBBF6AECA982CB8953660825685465A183F09CAAD1B3641296C886E4DEDCDEAF7AC6AE5F526952EF97703CE30CEC4E38DD95EED1EC6A8F05C6CF3ADF829D14A17CB53878473C959F6A63B5F0CB014F6BD3DE95A178D92927871EB945E7F855B1FD3590A503C52733EFF00BDDF406A80B5FCB9C47F17E87DFB348B66CEFA64241CA84B71A574D32E791E1764FC3FC54CE1415B31622A479BE61AB4CFD0C86F8073705A90A04802201F4A9712A868321F904B5FAC60CC466A0F7ADFCE00848E533D62994D9612FA1D453D83EC504682725CEF100017CBD7D9F29063F2A2639C41C8EBAFD08EB4EB0F237D20DDD89A56BF815B31ED1018C98664E5682DD7A0313D6DCBCB4E833E8627976D2A664C90801C574EE0D087AF38690F0B9C23873D351D67F6CBE149E24356CFE6037DCBC10C9C7323973FD797A49FF5355EC49604D33FB7BFC410DD4E8EA66633F8F7FDAA2A79694559B2892D9BD2DC5A0FF2025410E6F52E5FB701C74EAD5C7233275EF33AE79C7D39552368CE2A252EE1CF50ED7ABE46F0FE54F490C7DD6F7B71B7DA85105B047AF4D4663AFD63D2ABCAD9C66FD6CF9E55604E4281D9CB5E9CB49CB1BA4920BB3035035234D49BD32CA6F04FF953E71F08F9FF00AE5580A5E0D48209494A833508ABE5E5C1AD15DC496DE21D4E7E902E336D3AF9346A6FB495CE2BBB9DE26C0EF5F034ADBB7C26FC338F968101D45EBACDAB25DE18E2090B2654401A7427E82FFD3DF8C97270D8390A9845500D7FF21DFD98A2ED8C37CCDF3A822D62416D73D1F32F947786BEDF479FE0A20828820A2082B04382350D0423E17BD20FC7BFA521F24EFEFBEA18FAD3DEB09A90492411580B64822467E7FB5390BDDDE24528CDC183DF8F0B7185659DD0C47B73F6310F7E16A6DD436616D14024E878950207FAD79C0A678D5FCC945097048CE8CE5B2357FB71877267A10BDE5B9B51BD72A458DB75875C5DECB6376DC4853AE61D74A46A724DBB8A39C4FA0F2F3E79B5F63E23132E7310C50B26A43063D4D1A85A99449E1F1D2654C4AD2183B119124B0E0E0F91E71CC7DC03CDB78662D6B700B86CB10BB45C30982E33E2DE3A10A713FDA15C8F31074135F32FE366097B3FC49893313BC42D5E635AB3EBE6CE4759D838C97330882924067EBF8E71B14E58DAB0FA2DB80C3852A4AC0050A044FBB9004A4644472CC579A76A6D5C2CC2A925237AA0D85EDF7BDEC0DA2D322715A4A81293902F6B56D434A5BCC45388336E0A9B42488033CBA7F831975CBAD4713E1DFF00B8952E58649ABB55BDFE844CE0D730A52B529DC9601C677FCB77D31BE3764A3C4A052224C73044E9F5D7302321155BC4E1E4EC452BE724109D450BD0655AF0D38C5C301342C01F507FF769970D39B73118DEF1F0CAD6D282894C024091FEB9FE99CD53F1B8A463310664A1BA1CB3160CC464387BB0B4C895BE9DE01C3E59F3E16CF567310370AE324E639E7E83989E5FA69AA2896A772483AD7D93E50F25C95381666636B0AFBCF867185B738894A81132333EA0F7FA75269E4A965C1736CED5CF3BD80FD987F2A5D1B93D7304DB8BF68593C7FDC72E93CFB7CFF6A7299643D546B93FBF5F387E84B07D4797BE9A4485BDC708824FBA3B9D7D7EFAD2C990A507DF23AF5D38F11D1A22717277E61666B55F83D439F489469D2B88240E84FEDE5CF97C9E4A429000FE4033387CEB71AFBBC46AF0E6AC017D0575191BEB0F1B5AE75240EE7FCF4F49EC2A4A4952581CF9BB072D7F2CBD192F0C5D8BA6DAD7DD0F0C8E92F6EA591AFC7FC6911D27D2A5252C30A87A3D6FC03D6D4B521AAE42F7EC00193776B663B8BC39257248574CA4FCFCBCE7E94AB2D44AFD1DC9D7A37EF285D32C0480454660DEA2FE74ED0B0714343F7DF38AD0DAC08CC1F7F68D572C2ACC3EDCA86164DCAC0E73D79FD72F81D3CE912B50140E732F5EE7EDFDE9FE383763CCFE0085917BC3C8F2FBC8E83CBBF334899DBAC2C43BEB93035D350D784578601CD0835A0FD71E10F5ABB42D299E2988D3A73CF954DE17100A035F314278BD7D1A9D622E761F754D501DDCB8BE56BB5FA457E1970FBAA10399C819FD75FB9A72678D5BB76BFEF8C246436BE9DA9F8891B76F85213AA87EBD33FF005F183FC814FBB57CC7BBBC24A400D56E7D7417A5A251A64902018E53E7F4CFB0AC89FA8FD757D783C375CC4A417E36FB711083EDA90E28149F203B0CBA65F79E547CF72CCDCF2E758899D8D42565390D6F09FE2380C9428913901E87AF5A772D3BE01D74CB57F7EA23418C41661424F1FBFE383C02E02D51C0A493FF006FF5DBA7952FFE31DD7ABE999F2BB369F78748585B0B12F7B7DE1DA1A52E22339F9524A94437DF3E4C215DD6FE4F5B337DFDFD9EA1809480A20913A41E87FD7FB9DD58A4A257CB2EC5DC5B577EF91A68623E7255BCC0B0F798E87DD28586D133FA75EB3CB9F2390CAA1BE519B38A85002087676E2C3FA2337AEA90C039248776F2A97CF3F21482CA6CAE8DEDC00BB27213E1A3374920A678498804C933A0F302D3B3D69414A480C5C16C88033073CEFD291A4D5AD52CA65969818825DEEFE63B738D24DBEDB9C0377DED43B33835F3FC09DE2FE2835C0A486D2AC3ED429297E620CA804EB988E8697C66CF998B973264B49284B6F100D09B7986AF28565624EE21DC29EC431A5E9CF8756AC6D25DAD0D043AEBAD2D4E0E24A50A95709CD32239A4F7CF9F3AE678FD913118A2681CB90470CACCFDEDC4C5A701894996135B0EAEECD5A8EFC018669BA64F17BA470827DE033D7439CFE952182C27CB29DE5001AE4B00D6AE9A30E62D12C10660040234CAF47D1B5D3BC3138A32501C436EAE54470240E210634FBEF15253664B427743161C0F2AFBE1902A9C028D4A9406AEDD731D61C33749791C7E1B8D8E8E260EBDA6A0F138A4A7FDAEC6C050F0B5ADF624C36560940D161455672EC03D7AFBA449D9BA16522149CF22AD3C869DFCB4D69FE071682907779BF17FCF688D9F832164A957B36A19F5A56F9F289F69D6DB4F115A4F380738CE7EB91F954F4B99BC90ADD773A39F57F7C5A18AA510696199B7714FDEB0E53C2FB7E236EA013AB64FF504728F4FF3AD23889732623E942BE907CDAE2BA5883CA90D953128594281E7979B7BEACD16D393EF24A0680AF248D39E9F7D6ABB8AC36254584A5B1E05AE19F8D3B5612389402DBC003627D7FB0DE6611530A0A212B43875F70CE7AFCB9C7A659D456270D8A5A0A132261CA8836CEFC1AE7CE3230867B4C133753715A7076E5E9788FB9429912E10913A9C819E7E9CFA4D55A7EC4C74C98E30F38392EE93577B8A802DE54021CA6589742B0C9E3A59A9EF9C38B6426E5A406DD6C83202A72272E7E9EBF0A5E56C6C52505270D3778D2893DB8BFBAC213E724024AC07C89146D3A8725F95E2EDC1F09750B0A2EB5CA73EDF64FAC9CAA2B1DE1BC7E20B891343116496350CD42F5D7FA82C4E20027EA0A73FED6D5A96D4D3FB8B6F7C1BBFB4DB6D8AC5B087956A0AAD977AE2EE2238AC10AB96F8091AF13606712623335DEBE11A71FB1F13864CC9733712B41208E233CA95D32A8885C60F99254776956A57335B90CD901DE3A7F5FA248F3641441051041441051041441056ABFE27A7A882193EDA65797FC8524C8FFAC1EBD7A7AC9A6337FDCFC3D4379460F0152439FCDB2E3C9A22311B5172EA6DD79B2FB2FB6E03D16D9466398F7B3EB4CA700A95301762936E51906BC88E5F9F28E4818DCFFB4D6D5EC662292D605B7EF32BC1D6E7BACA1766C179DF0C9F7412E2B329933A8D4D7CFDF8EDE145E336962B13B942546D900C2BC29C9BB751F0F4E57F8682972D47009CDF96B4A5D9E3688DC5AA516CDA96953B61C456B541E20F105B20F4E129D7B467957CF4F15ECF3B3F1CBFA4277546ACCF5E6E5AEDA5EF5B8E1674C04925442B22FCA9CD8BB80DAC33B94A16F39CD27848F513F0A4F66ED02256EEF55B95B8BFA16D22CF849E7752924B55B2A1E2EFF63DA2C8DA048085102241FBFDFAD527C5A83890B533F27AF17B39E5578B161B1664EEDCE64E57D491E6F4D2310DF31C6FAD406A731969DF239CF49CFBD50F0F8764B171C7F5EFD04742D9988F99870ADE3567626E5B566A56E395A229CB52675075CF2F49EF3F5CA9F210ED635A119717A3F5E59C4BA660480A772FC185756FBF0A0864A678544427D7A67D2453C9729DB2CEF7A57D294E5AC3B97352D40C0B683576D7CA29F0BB27EFD29EA25B5198E65ADE97872165550A3DFDFE22B4359E83D34F5CA94F9645037BE548673D637D8DC69C75B57FACA262DDACB4F86BCF4D7F7D4F3A70843007B7ABFBF5864B5B3EA7ECD7AC390214B1D08D3D69CA406043977A8A80C7EEDEA1E192CBA8D5F4CF2896B6E5F7FF006A7D2D0C904DEEC3BD61AAD63789A97F76C9EF0F29E243243FBAC60170F0526BFE47DE519829B1A13CCC1053199FCD5CE0855B742541249044E7CB49FDBE039E54B4B9E515A002F5AF419817BEBD5BCD92958AD40A8D47937189961C491131FBCF5D233CFF004A9097377F3A6751A52BD3CE2371092806AED6E00E67ED6E222E9B0B42EB285C4CF4E601EBDE239FEF272249981296724D1F2A9AF3FC1C8C40E2715B856E5865ABB726157AF9C4FB162604A7A1CA472063D7EA7BD490C0934DD069907CB835B5D2B77020E763807482EEED50E2AEEE69C69AD844B23096D684AD60151C8F5CB9E79FC63BE7AC7CD93F2E69435F30DA3B7E3AB06110F366898B726996ACCFE8CE7AF086AE60CCE5EEF6E5D27D0CE5FEAA5B0E96003529EA6BF9E3485253D1C9AB9ABE9FA7885B8C3421F52909F76004C0EDDE7A7CE9FABE9431CDF7BD6E3366F3D22770F301483C18EB9559BBB79C3450F0647965988C867F4E9CA34A8A9F340A02ECE031AE4FCABF7BBC48865243D7F3CFEFA455E3712667D0647EFCBA9E548FC9F992CCC203F70C3BDC7A738653D20ABE9CB8BDDB9FB162EF0D9C741CB2806013A1FDF4A889D3C492524B35F76FF8E57A563544A2A06EFD5AFC32D7A5A1CB0B6EE91E0A9400642811944AA639E7C8C771CAAC9B1569C64C4246EDEB93B8E635E3530AAE40975DD2EB66A529D01CB8C7CC77F14CDF9E27BB9F69CD81BFC2EFD617B118B205CF86E194B589AEDD242A22006E467CA7B477DF0B786938FC0E2F086582B9E84AA5AC8000DC054412C58E90EA5ECDF981134A084E8433F3C9DED51C23BADBABDAAB6DE8EEBB65F783865DA2E19C470AB452836BE21E236C32873249227881273D7BEBC3FC73B226ECBDA139003142883A79778929527E54C1282482681EC5B4E2332D4E4F192090EE182E90402252AD44C1E13D3420FC338AE4D8EDB0AC3120120A6843BBE4FABBE5DA26A44D32D5BAA72E29720357F41B37B88696D6A9504BCB2A434A909520C75060F98EF9FC9BE0B6A2B1AB4A12B2497CC16E9E553D21CCDC6EE4B2CA049B05337170F4F2B4480B1B8B53F8AB4745C253EF78774A2B4FC04F5F98EE2BA1ECAF0CCEDA094CC082ACD88705CE74EFAE4E5A20B15B551BAA4EF096A3729A372CABDCD6E6E9BFB5FB376AD78B8E5F5AE10FA5243BC4EA18B64C12014851CA4013AC98EF13E9F066293382132949723F8A481E9C34E4F1569BB6D3281419AA5EE9242965D44939B73A35338B77FF0077B77CD2D4D5AE28DE3CE03019C1DE6AE5E39CC7083A9CC0D64D744D85F0FB153F70190A24B0FE3DB9F3E111D37C409208DF14ADF5D756FB5ACD01886F796BB95A3677775BC3BB7CF086DDFE55C76AB3191050734FCA39E75D5F66FC1D9D88097C37F201C14126B6A31A0EA5A910F88DBE92A7DF0791C8D296CFECD488C5ED17B4A6D09E1C03774FDB30ACD0717C2AE90424E93C32272CFAE7356D93FF004FD3310949FF0012EC7F8137E9D9C6778889DE25912D442E72535A396B86A9A5BD9AD5EA775DED7F8BDAA2FD8676570E75F9E2B47137CD38D41812D819150CC6798AB76CFF00FA6DC2CC94F370690B0CE4A0022D67193B75B8A3B997E324225309A9292285DC16E2F51D351530DEDBD987DAF76956538A6D36CCE1ED4C7B9777AD40503966201D34D7AD3FFF00D9AB03BC01C1CB482D532C7FFAD5C3F5F26589F1B2508514ACAC8FF6A4BBF4773C47DC45FF0084FB126FC5BB768DDEF0E2E332E0B3C56E3F0F9CC16E53232D7F5CAB63FF004CF8100B616496ABEE25B90FA6BA655D33819BE37132BBD3522B42C08D2E696B5ACF998BBED7D8EB7CCC883BC6BA911A628FE79C83F9479721DF5AC7FECD18225BFC29433ACB19016A1AE79E5C1E317E2E249AA8825EFF0082CFF9EA6D6C4BD8B77DF89626F0777A37EDD884F86EB2318B808536EA7856387860852499D35E82ACBB13FE9B64C85A66A30B2928490412802D95B80FC55A1F7FEAC4AB0E874CC515BD80B87BFEB9DDE3AFB5EEA8E530510414410510414410510415AAFF0089E9EA2086B7124122252329EFF3FBF8B19BFEEE9F682231C5388B76C28053CA2785799004F3233CC72E94CE6BEE299AC6FEF568C8B87D6388FF00C52F7ABB3BBBEDAADD6B96AC5D39B6CBBDBAFC2BD6012432D8758FC42AE543FA890599E18E8794D79B3E2CE1B0AAC3CFDF03E66EA892C1F5CF4E9D5ABD9FC15B2E6E2704A9CC0C93BBF281077854EF026D5398E7AC65CDDEEF16C36EB6630CC6F0AB8FC4A95676DFCCD09585B81C4B484E406842C2B881CC19915F2DBE2761D29C7CF12C06DF351C4D45299E95BE51D065EC6DD5268F7BDEADE7622DADAD95FF009EB0D5B25F752E7094E6A104242722147411967AEA7ACF32D9B2267D34AB9CAEFF006F47B189991B294E027701A3839F6E3EB5D22C8C476B306C41F559DBDD34B7F4E04AD255C51A44833F18D09A4F6CE0B7904A810C0966A1FC37BD625E46CC57FBC2695041E5ED985E2DFB9B55A417142352126263B8E91A76D73C8D2578620B252284D142A75B8E00F23163C12C4A40402C2C374D388ABF0AFB10E4B6E15240854C72CF3F972EDCAB797870186EF30453830E1C1F8C49A2752A5F997E3C85EDAD6193D6F0E2840032D4769FAF96BE74F65C9DE4D1249A01981CE8DC8F387889E08A966E37AB52A1FA7F690B73CF847A034E938726C03EA5DCF973B08748C4351C97CEA416D0B8E7A7185516AB1052011DB9FEB97C8D60CB656E903B38AFE5B85A109CB04EF6F73D5FA72F6D4906D250334EBD35C8E91918EDDB48AD9282E1D8F0BBFBA43652BE92A0687337E9E77E25E160C29C25620054403AE5391D3CA9FC990017501C9A834CAFD290C674DDD0C286CD9BF11A0D3D6D0F5A49447167D87AF5E84D3A4A2B5AE9FD4332B2471CCFA43D4A4A9214220FC72CAB785E5AC04805DF5EBDE91413026915FF0023D3D042D14F18EFF7EB4D8DF3772FDF2820E34F7A6333F9AB9C10DCAD5F886D0028F8AA30672000CF8BA65E9F11496EA8AC685CDE9419F514EF1B9004B51A029A134715F3D22E8B0B65BE0F014FBA7324E5EF699F3FBCF5A90C2A14A50487617239BF60F5EED15ADA53D32D248CC540671CE8733195306C25E6EC99E25227DE397427AC7FAEA60D5BF67CA2C97A91600D07EDC76D68DCFB1D8F24AAAD90E19BB7A718B81AB55208E2E123E711967AEBF4AB3C99296714D5A9A8F36AD44434CC4A8B3E6ECC752097FEA1E1B67D49050501267224E711F7CB954262E48FF20B00C097A0CC163E8FAD6B09A66282805D9D8101F5CEFA72CE18BCCBC38812920EB1DF58F2E7D0C75C95932E9A6BAE7EB125266924390C2D50F415E86D119728096CF101C40667D632CA7BF3F5ADB10B094901ECFE97E0C6BC0F0892933095259C02406B5BCF5E5C1A2CEC4042A412069976C81D33F3FD0D5771130826CCF400D6FAB53A69C226654C06854406E9C8F319D43C44A6FDA6DF6AC940F88E85A92A3F97DC049063AC65F5D6A730E12AC0B9DD7637A9E47953D3842CB93BDF58766CBA926AE7DB5EED98C41ABB75E690140B0A09254323248047C33D34AE6FB5E62C4F5A52400F91625EFDAA2D47AC3B9528001D2406CDB4A75CBD28C621F1EC64E03678BE24B2536F8759BCF5C70FE672195AD01BD24A4A7DE274F4136AF07625B132C2D4FF005076342E685FB6BC8343D421139280DF5289DD24000006B5C9DB99CB26F8AAF6EBDB4BCDF06FFF007838A9755F84FC420308B852BC40BB36D4942923300F1B6082328AF6EF808C8FF1E4AD4582836F5890C7798926E07763589D932E504EEB0A52845D801CEB7CEBD23B37FC15F7CB8CED86E6AFB777B417EAB9BBD902B656971D52816EEAE1D2C8682C9221B48072E523491CE7E29EC1C2E2B6962276113FE8A80202D8A8A825CBF026C29C4B52313E5032BE61037D2A0CC03873EFD873D8B6AE1413738580A0A6D633232214A2A11A99EC34AF17F8B3654CC3CE58DD206F1A686D53AFEAF0AAE58090B60481FEDCF5D1EE6BDE13C5EFF196703C51BC0ACDBFE6584301C4A31042BC2BB2B495816BC32A594C7BC32CC8D75A6DE12D98B998B96ECCE9705DEB40D6D056D4269159DA139482400A21408DE4B306C89FBC6BCEEB5BDFAEFD715C4B0D5DF60BB2F6D62F29B76CD2EDC59E24B4F12802DB79CE499131911CABDE5F0D7C2523132646F212B2424071C017ADB3E0383C5036BE38E1A5AE62C929059DEBF51005C9CF8E71B8BB27EC2FB3B89B76F8A6D9ED7ED1E297AE2C9B9B07AF90F5982930021A7133C2A2339D743AD7A67667C1D938D08C40908292C689B934E3C3DB18E6BB4F6EA913968485D0515FED2E1D835CD6B9BD2367765FD99F74DB1CEB16D866C761EBB929917AED833C4484CCA9C0264E7399931D44753D83F086448521F0EE035D2185726D397EABE76F621614B52D2056809DE1C6ED52FC79659CF0CD8AC0B0D65B0C61564D38DE9E1B290948E5A0CBD79FC2BAEEC9F0260F0A9015252E007DE48C8532E178869DB56729759C5292ECCAC83BB87B7AF089D18724A4B72584447F408491D00D3BFA73AB6C9D818294001290198064836CEDAE54D4B988C9BB4C12CA56F914FA9CF5D32C8D3BC7AC614CDBA83BE33CEA89FF00F6AA67CC67E5FEE2909B83968594CA410336D45AB972FC42C3173152C268126A00C859868E21FA909223810465A8F39E823427CA915E1C9AFCB7A55DB203ABD3DB984CAD4EE951A8ABFA694EBCE17693C08E1002626001909E9FA8EB5812D219D0464E406A6B7E9AF184D454413FEE3ECFBBF584D4DB866081D3F5FB3D7E3B7CB4A88FA7300903234A9E3DE19AA54D2E778EE8AB3B1A7BA65DA18BD64B716D289013EF78C53F98FF00D6391E433E5E662D1853265482C9A32775C060D77F366D7842D2F18A928092E487A1B8E219D896E55346789EA46310510414410510414410510415AAFF0089E9EA2086970471251FF79F8A472FBFDA98CDFF00774F3682239E50532FCC715BB657DC0009FF007F6299CD2D2D674493025DC3B5C5B9F1EC3F6C3807BCFDDF2F7D7EDB7B518DE3A97719D98D83532D7F2CB9FEBD9B6AC4AC4B40B6CAA5293E280A3FF909D419F137C6AF14A70B8AC4614AC823783386B1D1ECCDFBBFA3FC1189972363CB4B805AD402EE4906ADA64FA3455B57BA8DE46C0E23885C6EA4AD9B7B3522E1581A83C1A7D025C0D22D99038E402003919F8FCF2F1763063F1F34BEF6F2CD2F57A357F74ABB45E13B430CC085A083BC1DC528D4E2FC5FCDA9D99DA9F69EDF0D862F82DC6C4B7B1F6CD2516E9BD770FBBB274F00285B8870120F1147171644C8275AD363EC733A585897401E81AF9FE6BA662A61F68E0F07BA9993F794B2774CD507357A13CF2E91963769B92C6B6230C38A6D3631758AE36A70AD4871F53CDA55E21C805C2C08239CF789A8BF116004996BB16A65462D7C9BBDE8F58954ED992A2109A519E8C5C6473F224114CCE60BF4BAEDBF1BE84B6E70C14A072190813398D67227E7CC66A01986F760070A6638E5911AC3DC34E48427754A50A9BBD0F1B3D6E3F5169B6D7F54C8124E51209D7A99EC738AD928208FA41E14CE9FBA7AC3D97354A2EF50C5BF23B7A8872F5B4AC98D6232FD60FDCD3F9325C5807A923ADF2F7CE1E89EC5BEAB5C56B736FB0A425F85EDF2FF00FE4D3912C3B96E82ADCF28792E6D01766C9DAE3C8F0CA1C22D55C2397CBA763D64F4D05349D2885BD0699655E7DBAC60CC4851049232A8CEF7F64E96854DA280399F847E95B4B95BA5CDF2ABB72F7A9A420B9A6C1BA1F5D7CA1C36C10800EA3969FA7ED34F522828C746FB4315A8B924BF2FEFEF48AFC0EFF3FF0014E25A094824004703EACFFA221BAA687D1AD7CF979D042C84F0A427A4FCC93492BF91F7943D45520FBBC375FE53E9F514DD7FC8F4F410EA11A6CAB9E67D608298CCFE6AE704327314B4B7B945B38A48B8585A5906388983300E663B4763AC4961F0A66201670D76E26E5A8789A0E2F0DF133D32D0A1BC58EA6EDC3EF78BDB656DEE4DAB9E28595A9692041260AC11944E635CE0F6A929185DD50200BE966C8356C598B5E968E79B6B68B0500482C43F77E347A072285DE33BDAB45AB76904442465A119099F53CAA7E47D1BA416CB466B79DF2ED1CF66628AE6106A4A9989E3ECD4085C9813F2EB53327115634D06BC2F56A97F4891932B7C0DE0FA021FEFC3830B887CDE6CA08C8906077EBF1FD32A6F352262C9157B51F953BBE9084E64CD2906CC468EC096F271CF488EB911247F8CE073EA273D73ED584A08A873AB0A67F91ECD1590B3BD514E1AB54FBEB10576725CCC4465CC41FBF3F8534C67D20BE6E3D07A889A90BAA493FC5E838EBC05F5AC59D7C499E433CB94683D4E507FD554B1AA62483C4D6C497FC8112B2945D24D5CD46B58C15BD0DA74ECA2B09BF52F8038E96A6624BAE25B83A4FE61CF3CA7954A61B1891830924D4103880F56B0CF21CE2D9819489B2DF7492DD32F315B74317BE1CEA5B63F1474B86EDDD0A3FF009A52AD4CEB320E939F9543694933662940E74E3C0F4C83D21499282544E45DBD1D9BB5F5E30AE2CCE138D377982E22A5A19C4592CB8B948042D0A4E5C4623DE396B9EBD5DEC7C47F87392B3A82E2F43ADFBD7BC3254D9921237777792E6BCEC39DFDB8E72ED4FF000B7DD16D66D5E298E0B92A77135ADD5A7899D5695183EE480788EB333A4E55DF7C39E3C184972E509E400000EAA076167F4FC46A36B848DE2EE0B1029997A598D6B9000B0CF9AF87DCE0DFC3CBDA9B6B764307BA2F6178F5CE18866C50B4A8FBACA4A816925293EF3B23203E157FC76D71B63672B1213F313291F5CC4FD5FC9DB78F90CF3E1166D9D3938C9414A3F4AC58B034D327AEA03738EEA6C5ED939B7F81E17B476166BB4188B2DB854A6FC39F7539C82275D395797BC6EA94A9D34B3073609A5E8CDA9BF7687DF291293BA15605B78FD5516EC4339E7AC648462372D5E165F6C2DCB64A4359122EBC44C2C1FF00BF00C8467E99554BC398E9585C6CB4A887DFC9812E68EF5A7BA44162F0895A14B4A4B170C4684D40B7DAFCA2C3C69FC736336A6C76D764AD0B4FA9D4AB14B1610A090D88412A691D51C4A12635F4F6CFC39F1961F0A8C3A77C02371AAD987E15FD8E341DA9B344D1312B4A54820D161C1BB16ABB1AE7C23A61BACDBAC076FF006558C5F0FB86BF98786D0BAB60B4788DBC984AC29092482A5856A79F6AFA6BF0CB6B6CFDA1B0A4E20EE1514A5CD08AB371CB36B5737E09E20913B0D8F3200795F5329AA033B1C8B74A335A336D9BD70F34D2DC6D293C2A0490414F0E4338E63EB1CABADE1E7618A3E86049B00199FD05FA031569A908DE0E09241BD6EFF9F6D1236E14B68294482641CF9490397A7CBAD3933124FD3514B446E2012694F633E3F68F1693A491DFAFDF9D369AB510C0916B58DB8D5B8F7A088E54B2E6BDCD7D214524FBA00CE0FE9D7CE95972D3BA3786F1D4D49CBD479F3894C3CC9611BAA351976E514F0A872FD7E95BFCB47FC476873F32528DEBCC57B9F48F0156A01E9A4E9F1158F952BFE09EC232F2FF00E447323ECF154AFF00F2F851F265FF00C13DA31FE987216FA073F7A7A47A41E11A73264FAE7F1E7CFC8D44E30CF4129964849B0141C853AFA110D664A04BB528F4A060D4E3CF5EEF2A4A330510414410510414410525F346F6EB1F7F76AE9C608F098127956E7EA4D33D79C10CEE13EFB5713EE3721439FBD9081E7AD359B294C585FECDEFD3382216F3FA0CE30EA892916370E003586EDD6A503DF281DFA5466255BB2A627FDC50BF43D2364075241B150B73A5FA472A372F7D69B4DBC6DEB5F1B0368CDDDEDA072F52D06EEDD368B7529F19CCF8A0A21327F29AF9A7F1E70B8A9FB7F13B8B213BCA60E6943F7D28C23B278713393B39265A8540606BDC7B6EE23653F9433785CC58B858B8414A0149E12E04C2071E5272034823977F1C6D0C1CC93882B9877B7555AB9BF2D687ED5116057CD9450877DE04B582732696E022B76C2F1A2A53178F31C6078ADB4E292DA80038613CF5939913234322CFB276C48C3C912E83E96233F3CE9CEB1B842A784AD602CCB3F4BD59E9467FC660BC327180E366DEE5A696D907FADC32F4F33C46739D7CB2CE6AB5E23DA32F13F3371218D2D4E24B52A6BD75787A84E2490A0B395892C45079675CE8E231DE3584C3AEB76EB25B0014970FBFEA4469CB98CAB9FA702A9BF586152C34737E072EF170D9B8A526484CC724D88A695E009F6CF161BB62E5BB854E70100C426675331D065AF6D7232A0C0947D4A0EF974C9FA92FCB48B0C89A16414921C3DF81197BD0985525B500A854C4729ED9F91F2F9D2BF2CA064C3BFA0896952C901414F7BD7CC73FB410DF43F015B25612DF4B9AD6872A3FB685144A033960D416E0D685836952530400064244FAE46905CBDE53D1858396F4B7B31877ABBF1850201D483E46B2943172DC2355390C3AF28A0A903224C8D634F4A581000A026BCC0E3EED0D56EFBB964D9B7AFF0051E05A39854FA476EFE797A56E2790C1879F330D57FC8FBC8452563903EBF7F7D4F30A029D4FA7E3FBAC494921494A7302BD3DF0786EB39475FD08A67301770D5D780FEBCE1E478D34B796A6D00929FCC6321D3BE7A691396B48250A5D69535FBFB2D094D9A9942B736E9091212EA9B70F841295A94E2F242781254428F2240CBAD653B3A64D5E75209ECE40FBD435E9947CDDA6896EE199DDC76ABF38C0EC398C6DBEF430C6B016DD461D83DC2C5EBCE85062E02C40F00A642A083C53CF95593058612E504AB87F63234198B1BC57F1FB553312A4A6EC5B8532AD33BDB578DFCC330765BBA60A4250D969B0B6FF00B8A92D804C72958273C8EB5226407253FEE6F629EEA1A2878D54C9B2D4564935B59AADD80BD2FC22EB7D3C2E148C8240CBD3CFE3D6B7F94B0C1A9CC96D32310B2B045453343DF4D0DF23EF330CDC4A95319CC46B94452E994A4B39A6A1C1CF3FEA9133280400E0E6F4AE62D7E3D6251949F051A640CE7D634EFF00AD3A4495302492F9BD8E61EFDB5BC47CF46F4D2CE0EA3F35D1A22EE96912241CE08E7E9A1E5DBB8AC4C589798A3DAB6D2DF885A4A0A540105DDED4D0FEBF316FE26F22D98F19638D2B07DD466A11AFD75EFCB2150D8C9A54F50F561E879BD4F0CA25A44B24A83170DC882F6D695CAD163DE5EB0B4832532600244F2898F2922797C6A78B49528872378DEA1AA0E6FD386994BCA410AA82D421813A9FDE87AC692FB5D6309B6B5D8EC259722F716BF49B6208E1E162ED953BC4467F9721DFD6A5A5ECF9A8C1266BFD206F1BEB47A53339DAE22E1B2E7265A260291F500C4F3B3836AF1ED7D9CB6291B3D67C4485B56160544FE551F05A2634E608131CA44D57A74C0B5996DF55452F9BDEBD472AC667ACB9600825C11C6AD9674666A56977C87DBBA6987FC2B6E063842CAC0F155C442473839CFA18D4D4263F19FE1B38600936626BAB0F5883C4052D4A3BC72A3D052B5BE7179A509C3D1F8F425A9F08AF879A5294492A19408CFCA62622A5BC3A9C5EDA9D2E561D4A495AC0A920D1474A1E5F7262255226294523799E86AD7CB857EDC63E5EFDA3C6C46F5FF8945ED85EE2B6D8B2EC6E6DD6EE1D66FB6FF82A670F4AC05347F292519E998E5AD7AE767F85B6DECDF074C33004C9C4CB054B5056F9DC538DD2455B3AD8D23A6F86B66A9787960A8EF245413624D7F5C4E423B41BB6DB1699B3C2F67B09B54DAE1F66C8650852381D012809C827DDD4035E5CF14E07153F18BC3209DE2A50705EDD6BD1F37D22E6BD82B9725539442830B9A8F20039EF6AD4C677B5C4829696C32EDCDF5AC96148405FFC827FAA75809C81D469558C2F84B6A22709A12B2C527783B1AEB99B695B88A76D532F09BC4A9225A87D6972E96A3A45B8FA69101B49BD4D8FD8FB7B9736871EC159C5EE9050BC29DB96D372A1051C0D30A3C45C283A7581CB2EEBE0AF0F6DB9D3244B419C3EA43BEF80CE3B5BD961144C5E3B0B30A93BC9176B3D439E6DD48A868CE9EC4EB6F1BC4F69F15C2ADF11B7C06F956EBC351788E148238FC75003DCE1528CA4A41F7609D32FAB9F077C37B5A4786B0C95CC50225A6E540D783717E46D48F3C78BF1D286D198037F22CCCF6A9D0F2E1DFA34DBF72B7D564D16C2D9FF00954660A48900467200CC4448E46BBB60F6763E4801531AC6E69C81D5F818A42A74A24CC6249C95566D07EF3E7170DB0FE8A40293DF3826615D32E9F3AB14842D29014A7A5483FD9075FDC339877944DC7BA7BF48A94839E52272E7F2D69D5086207322BEFA43428AEF1079353957EE6F09A9B5932263A67972D07DE758750A034CAA47D8FDB8C26A94A2CA49DD15BD6F971B7B68F381CEA7E7FA8AC12B218100EA493E4C2309973011F50E4CCFE515065CFF00B01DA4FED5A7FAAEFBE1DB43F985BE5CDFF926DA9F4DD68AC36A004904FAFED434D37507A56B956DFBE7A0DC2161AA1C73FC74E3092DB5CE4091CA34F9FDF2E54B0DD23EB1BC75F67DD21CA160065024EA0DBBDFAC3BAD613828820A20828820A208299FFF0013DFFC608A57F94FA7D453A47F11D7D4C10DDF8F060F323E4AAD5740A26D422BA0AB0FEA088CBB48B8B7C4D09125766F3601E7C6C2D1CB3F4F4EF5078D6DC5EBB8AFFF0012CF96BFD46E8A282B20473D3EF1CA8DD0DE59E13BDBDEEEEFDC4A2DF11B7BCC3DCB79012A712FA9CB85708D4FBAAD3FC47CF8F8D5289DAF8A2C1DD437855A86E74B3DF9D5E3AF787676EE0E4AB7C2420170F7E0D9FE6F48D9FB860F8E70F6D6129414124640C00A39F3333023ACE75E2BF10A77710B0E5B7A9A71E8DC6EEF16613F7C024558DF3F3152CD5E54115DEAC2565214141294891D426398D41CA399A819001994766CC039676D21C61C28252E0877B86A0A0FB7BBC03EEE7CBD3C865D796BA79CD36C7C8242980AB3B7953B0D29D21F4B99B94670E3B67EBA18B5F1148515AB2931A73119F7190F5F9D454A4196189001B83F6D6BFD44EE08EF252470BE57B83CC748C7F89B79AA67231979E7D7282477CF9450A5B549059D865D3F35C9E2D582965C51EDA3369E62FD2AF10215C038721CF3D73F514D262C176CDBC9AFDA2C9291F487A0F3E0DD83BC7BE2F74FDFAFD29AAD443005B3FEFDFDA139D2CD58B92DEA3200E86154BC024684E73198D7CC7D4FA51F30015F2B7AC611299357A7DCFE72FDB2A1D498EFE5FBD67E624D8BF01EDBCE02821CD0B778A090492343FB50169363D7286A45C5473A18F2B1F3124EAD9D0B79BC325214E49CF32EFE9053C97FFBB3D3FF00C8C3E904248245DEDD7DF48A1424A472CE7E54CE665D7ED0F45B2E968AADB1145ADF3768B489BC0BE124681A4C9CE39FAE47B56924172055FD06776FC5DDA23B184298B91B8ECD6CBBDDF3AF9E2FDEAED03F68DE178261DC49C476A9C5B36A10616916EE252EC419CD249C8491153F8697BC037F2B8E44E7F76F3CAAF8D55C062C1CBD45BB0F75148D98DCF6C261BB2781DB317ECB6AC64341DB979491E2294FFF005132A2388C255913A659F3A9995242432DE80114CEF6BE74ADDB8C5231F8A593FE92D3BA4B1292F66703B7AF33911A65E17EE3A82434954889394738E63C84F5D2B64A4A560D48EE0303964F0899E160214A0C457B5DD87BA50DA57C5F18970EA7231D801FA67DE69625CBFA70A46A1625A025352E74A76FC7482B216406A7BEB07CF660C4BBD5BD6B0A17B81A827A83DBA4651A7C7CE905E328500B3676E2D99BF3CA3225A96A7E447137AFAF017881BBB9009EA0664F7FA93DB4A6D327EF87D6E33A65C07AE50FE46195BD7714ED5F77F4316A5D5DF8CEDC34B3EE3404011C24913D73FD35CB3A63392A99517ADCD00C8367E5CE26E4481402E68E34177A587B61164A8B2EADE79F70356ECC9E251E1481AE73CA44E83A8EB4C7FC3330871987CB3A1E397DF211232A45992546C031A353DD7D639EBBD67D7BD2F686D8ED99C39E4DC613B26F5D3976E36AE26D25E652EA388891F99394F7E75318A5093B30CB269BA7D9CA83A71BB58F0D861F29D41880D6A662E4E678F2D63720E265F09C1DA02586DA68919710690903DEE7F96464749AA061C0998A2D72A24127BD85F2ABD68F0BAB084A416372D471C0B1B0D7FB89862CDD5A5B6C2C84AC852C4C0FE99E2D07FF0058F5D4532DB98054D4D03DADCE9906EE486B58C309D8437200A97A53B37AF36A4618F6AFDFD617B8CDCC6D1EDA5E5E21ABA187BD6F66CADC016A71C42ED814A4C12429409E1E7DEBA97C27D80A5E330EADD72E0B0150C7D915A986C30DF5292A0404B17670496B393668F92CF61ADACC5778DEDABB61B778FDCE1AE5C5DDE5C3DF8ABA5137696DCB77FC3971449108238794089022BDA7E295FF0087E0ED9F8647CEDE5CB9817BDFC28437CBCCD039E56BC593646397855A92E404B3659676E22DE71DC63BEDD9BDDA63785DA5B3D8A6D1ED0E2AF3E8B4C3B0F28BB0B712AE14B686810A3F98447EE2BCD5B3FC21336C6D641F96565732859DDF8FDAA6BCE2D98AF10FCBC210A5D02490E4B0605DEB90AD5C0B3E51BB7B0DB01ED2DBEAC3ACDCB2B3B0DDC6177A125C7F1B6EEB0AC7576EB208532A48292B2D994F2823BD7A63C3FF0003A66270B295330CC5490A7523AE61F87615A479EFC5FE33960CE32A689894A98896A06A49F537E2D6A08DE0DD77B0D6EE36510DE23B6C85EDCED428216F5D6D986B11B7F189926C94E242F873FEEE5C23CBBBF817E0A4AC362251561D0374B90A486A31D3A6768E398AF16CD52D43E6292836282CB15A3B71D33D408DE9D8ED91D9ED8FC391618261587616BE1E1FC3D830965A427904A52343EB9D7AD761EC846C6C1A30B2C04A4240205A8CCD4B0FC52299B5315FE5E21530A8A80620A8FD5C4E557A1034AE917531861656E3A552E3BA9CC9D343CF29FF007532E3511191276AC96194B64C90499F333400C19DF89821C5660828820A20828820A20828820A20828820A20828820A208299FF00F13DFF00C608A57F94FA7D453A47F11D7D4C10D5F696E363848100CCF998F9C7F8AC2E893EFDEB0432B5656D25E0EA924B808CB311075E472311E95078C1F4A8FF00E25FB1B7711BA54032732A04770FE91C96DFFE0EFEE7FDA7B01DE7BEA4DB6CEED638F358938825202D8B616F6FE31C91FF0022870CC939011957883E2FEC75CFDA1889A949DD724122E19CB71CEEFD63A3F87E624E1D290A04A5810E433D2CF99D286E7439AF13DAE690966F6D1C172E3C8438A6D83C6E04BC9050A201C804AA5463313A45786FC5D81323133090D53C29506F9B7957845FB0528CD6A64F517BBB6B4391EB4312D698BB6BB76CBCE78AE11C4A5A0F124CE704F54E87A10455264A82166A58DDED4A6BA1A166BEA5AC12F04B290A20D03B35BA70E459F9452E3E8733492274931965E5E5DF9E959C4CD4A839209019870E1C58E56E158D178662000CC6BAE64FE053B3C46DE2D01044891A9FA77AAFCC50249A804D2F6E96D5B9DE25F674B526EE4351EA471D453D78463EC56E5B0B5403AAB2006599E874CF974CF4A66B5BB8D7434CBCE8C7D88BAE0124848CDBB706777E9D9E2D371E0A515007BCE5A08EFD3F51AD3598B2976C98E8F6BFE338B0A65D057CBDF4BC781C49CC4C7A7EF4D973BEA05A87F593FDFD6135A0BB38A7DF8F6CA2A0F84E59769D7EA2B099848CB3BDEE6F58DD082C069ABD5EB483F129E7A7689FA9AC85105F5B8C8C6AB946FAF6F4A43943E8E111244EBD0796BCF4D7E228DF21C814BB54F6E6619CC940925883981D1B23C7FA8582B8A72D22B50A20867AF0A7584552D2A0D6EE59B3F7D697A4BA90A2933232F3A7D256A32C9B31BB90CC7DF484012956E0C9EAF5D7AF68590952F4103A9D3E5349AFF91E9E82174CC648FA8F427DE70DAE2DD01E6545A5AAE42FFA0E04CA120C05C9D47126440D29E61653A8646C0581777A59C5002C6ADC218E296774800126FC1DDA9F739906315ED8DBB877BDBBDBF7F0DBCB8C2F0372EC2D2D34572BB96D2949483EE901C92A3D3A9AB6E0F0C9012C32CF3C83EB91E19D22A58D9AC561C824170FA8B59AD4195728DEC43F6649716871370A6580A00001292DA7802A73900E731CC015349C2950752686D72D6E05BFB0E050D0312A4A17BA8AA5C977A5DCD8000BBF1AD9A1D7E2AD30EB72B79F6DD53D9210D2829633FEE1946B947CB2A49586A12D5D1980CAED4F2E1942682564862199C91F4D43D0C37174CB5EE292B4EAA055119FBD999E9E5E54CD69081BBBB9D0D39E5E94CF8C3C4CA5101ADA9D3B01F98A17895B2464B4ACFF00D5264FD3FDD24A2C0D5A85A1CA70EADDFE2E722D7AD5E8FEEB11CE62D6EB511C7C2AFF00A28C1196597CF49E7CAA1A7A8FCC56E96395487FCD3311272708B094967A685EE323CAC6910189620A6415FE1DF753AF1368919F33DB4131972CF5D10951D4826A732D5B86E54C9F4893912536DE4EF13FC49FAB27719EBA3748B22E71A4B2E29E55B5CBA2EA652DA24B013A97C4FBA2093DC024C53996904A5F3C856D77F22F1332F0C58170929AFD428AE01AE72FEE347BDA7BDA2B05D99B17B617642E5DC576BB14429969AC2D697BF04EAB206EC3678D0005C9C8C70ABA5384A10087506704B102859DBA44BE1F0EA5201DD6A5998E41F969AE9AE2BF65CD92DAED986714C6B6E6E2DAFB6AF1A71A798BA654B7434D15A95C2E2DCF7D2B0CAC2607F703CB2A8EF10CE929C3CC4E1BE67CB0004EFDC16FA9DAD5B3338E158B361B0FFE8A42B74BFF002045D886CB2E7EB1BCED5A06169BD1FF0022932B3A12633F9F3CB21D32AA16CD56F62DDDDCB8CCF16CF874348D9694B948CA8D91D1AEDA8F289CB472E9C4ADD688525F292C273E24041FEA8580722A12131AC8D79DBA7E193325870093BAC746350EF5A3B74AC46E211BAA2EC0203A9EC7787D246AC4579B8B3C7CF67F197DA3DE4E2988609B2F82E078FB9B16DB776E62AF5BDBBC6D4786DA5D4A9653FD3E10E26655D2626BD15F06F64E156B54D24A674BDCF928240DE2AFE54B939BB539C35972945082B295124B949A370EF6C8F111C3BF62BDFBEC56E9F7DB8BE33B4ECBB74C5E38DB4E2D80DAD2C061A5B4E0794B50093A83DC1ED3E93F15EC3C462F64E0E59412890956E8DD3FEF634147AFAEA61E61B08F34AD2D5ABE82C1E9DB4D1E3B84E6F77723B578BEEEF7B1B15895A3AE6CE623E2E2B62875855C137172CA130DB64E498515711194D33F875E0E48DAF2BE74820A56090A48D5C30B39E19B35210DB52CFF0089312E2A8527E922C4350D0BD69561CE3EBAF70DB7DB3BBD5DD7ECB6D8E149B276DEF70E61B6CAF855C0AB765B655C1C2602814E647388E95EFED93B1B052364CA5AA523784B00D038602D6637BDDB998F21F8A70937098DC44942E7195BE548517624B921474766190193C671B1B1612F2D2F22E2E9700B6ABA85B2D889FE9481034F38E74EF038CC1E1E794206E92CCCC18E6DCF955ED1CFF7267CC2A25543406DD0519B5FB44FB16A8528DC84F0B8AC80E402728E67B0CFE5562F9A99B5497196B5BF9E94EF1BA8104BDFDF285822E94A2A2A401C86632CE86CF4FBC6B0ED1C7C23C4E1E2E7C3A7CE8822AA20828820A20828820A20828820A20828820A20828820A2082738CF499E5FEE993FFA963DB837EF95608A57F94FA7D453B47F11D7D4C1142085028E9FBCFD7F5A260FA6B627DF2BDFA406BFA888C52E45937E202233EC3213CBEF5F481C6D88176367AB81FB1F6AC640048700D45F9C73BBDB4ED2D76F361312B25A02AE70961DBBB479A00BCD3AC82FB6904E69E371091035903BD79EFE20EC438944E9A52080959A8B9A8BEBD2DE7D23C37210501690EA5338B545DB3B3BF5E11CF0F65CDF33BBC0D8E7303BFC4D08DE661576F5A5DE0B70E91722D98BB5B2C28B0545DCED11C7310419D32AF9FF00F10F667CA9F3CEED5D54B70007DB3716B4762D8D854B254BFA521AAAB559AFA9B10E46A1A37AEDF13FC234DDBA894A9284F10320F1912A93D02A63E51A57009D30C85900589BDC70E8ECC43C5EE56CA0A961696622FA3B56F63DAA4C3F6F1B03FBB9EB3FB18E93A475A88C663C00CFFCAF534EE78548C9D9E911989D9E12545B30F6737E163C352D0CEEB1A4F1292173DE40F3E47BC6BF4A8F4CEF9A1C1770F7C8FBCFCE34C3CADD56EF2D72B657D0708B6EEEE7C624E5FAEB98F4F4E9A655A2945D81A70378B460259041160CF6FB50535AB3E7588570FBC40D01E53D8E7D629ACD986EE082FAB9E7C88EC45A2793603DE7F77FEE2A49040D3CBA5335ACB105DDE872CBED90A40A43D6C72391841C71295904E7974E9E63CAB644D094D5C9A75A9D7BFA438972FE9059DF5E19D6AC7AC51E2A3AFD3F7A0CD0C18ADF3ADBFB8C2E580E2E74BF937BE50FD820B608D0FAF4FBED419D57AF26A767AFAC32584B97EE687BF38916F9FA7EB58F9B5BAB3AE96D3DD28346AB4328B1E795C70F385916FE2282A241E71D32D63B659E5CEA4E4A8FCB0F6604F1D399D34615AD2227ACA66001F7AA4E8FE5EED12ECDB42047088D35FD8C759EFDAB604296F91D796919F9A1850726A8F3E5CFA43830DADA538DFB88564B23212759D6331FA8EB378196EA4B338F322F9E9C75CCC30C42C1DE2145D8167E1D6E1FAEB688DDE46CCE358A6CE9C5B654B4AC52D9A2B67F371F191970F067A8E46AF78291BC90401950799CB872BC5431B38296524907EAAD82AF50D7CDFF004D1687B3EEF2AEB11BCBBD97DE45EAF0FDA4B05F8776EDD385AB65A5454A60254EFBE47860033A9F4A9A4E1C10067AB301C1F83EADC338A96310A415AE5A4AC82084A43EF7D81E2236BAFC60CA6DB6ED1DB7BF4C8297ED141D20CCCF109D3B1FA5359F204B191E4C417B64DA9EA2F785306954E482A96B96CEE169637A900FA7586D70E36C8287997D694A07BEA124822609CE6328F86794C362250756F05240B1B71A5B2BE8EEFA4C61E46F91F2D52DC64554E1974CF4A345A78862D60C13E030F29CCFFB5249F841CFBC729E42A2672909A872D42FABB06E1C866F13987D9D38B29625EE8018241721858E8796BD2CF771F75DB85F8B6E80CC8CDB49FC5360092A76623ACF20338A40E18AD214452E08AE6F7AE7601F311292F03BAEADE50B50FF001391CDC83634F26318E76BF7B3B2DB2695AEE76C30D5BADE6AC1CDF2157EA3FF00F8D2C1CCAB4CBB839D6ABC3942410A1C52FEC53F1CE1DE170D28CC2932085021E62922B4A6E9CDBC9818D42DB3DFFED66F2EFAF365761AC6EF66F0F30DDCE2D7AD2ED6F2E90B0655873CD9217971054820020999CDB297B82A1AC090EEC5BFBD72A0113F87C1209AB2C38A1A80C459F8DF5F4B4367B7236585DDA717BC69FC6B14795E2DC6217094DC62EDB84F1152DC202928049009FEC1234A6EAC60466E32B3DABA9A1E1CC5DA611874A52280301A07D1A9973EB9C6CDECCE002D50C3885A5E48193A832328F74AB4949C95AC28543ED99BBF835281350DF8772C7B985C2D2964B860EE721A71EED1950A816020EA040FA4F2F38EDDEA9FB266286281BB28DCD454737ADDF8EB0D96B01C8AB8C83935E2DC2BF731459BB76A6DCB603F0ECB6A4C5C0949826550AE51A65196B15799939909FA98060EE003D79387EBC6184E5209DF512A77649AB90294A694BF3CE354BDB797816CFEE17783B4589E1D85E35F87C21C16CF620D26E0A16B6968570A9511EF473E5E95E8CF83B881FE66180A82A4872F67F66BF686A89DBC80427E58ABA2C29C2F6A9CCBC7E7F8AC6AD1EC4F69B1A699B7C314FE2B7B9211E0B251F8C7920339E7EECC8313957BE676C74E236326629D6528428331624034CEF4B5380A43A91B4A54A3BA4849CEC32E0C18937FB18CA1B078EED65FB89D9DD85B8C7D6BB94A9C5358629654E2DB05D48692DC924A802246B9F4A6FE1190946D64A9406F6FA5FA503FA35F94436DDDAF2BFC7584B541B1A73AE7ADAE35A7DC9FF00ADBEDEEE33B8CB0D89DE760BB45636D80A9E4E1F79B40C3EDBEF876E5C59E35BB214042424A63223AD7A802D6BD98128A3A0333F2E9E4794798BC61B411326CD015F5025CBB8EBC03F4BF3FA3AE1B90095A9B4A523DCE1273026049D328F2E5CE6A387C1E326E306EEF1651AF992E0706E79E714594A41BA779F2D3AFEAD5E5258738B72D92A7014AA4E4441D48CFE15D0F052E64B94913410B6ABBEBC7AC37C5A5299CA092E29D283F70FA9EC35828820A20828820A20828820A20828820A20828820A20828820A2084CAC82440807BFDFCBE349264952DF4B9CAD953D9E461354D4A5A84FAF4E5D22A90A919FDFC694002433DB33190B72CCD0D5B205C3A24C2635EE272F3A4674E64B641CBF5EDCB90B429761FD9FCC5ABB605430B79F4E41B4924692049CBEFAF3D61F1002D254E33E341CB4F5BDE8A22592450BB8B57BD3EF1CEDDEE5EBB77846D23B6D2E855A3C5E6DDCC02D34B29E103FB721C4491974CEB8F78C76A61F766E14A7EA00A5D403BEBEEC63AF7857045587429EA5AEEFA51C69C8691F3C9B1382EF176237B1B5DED03B349B9B809C4102E70BB1F11568A61A7576CE16D94C7BC1BE252A4FE6D6BC61E3FF000C2B68AA72E4AF7492A2082CF5E0E0F91CB9F6ED838340094CC01480CE15504BD3414636CF8C759F76BBFDD97DE66048C5EDEF9BB5C4DB4368BCC22E1C422F9A7A78172C0515005614AE7EE8122457963C43E119D83F9AA54D1F4924806B716B67714E0D48BFCA969420237286C52030622EF67A65967966BB0BF37C62D945D4A512A5A33427DD98528686328EBDB3AE2BB64CEC32D49DD2589A81C59B2A8BB67E51198E9297A86166199B1CF26F748A54F38B5A97242742093323DDD3BC1D33D33A4B03895995549078821C1BBBFA8E1C618CAD9E662B7D2C00A97762723CDAF5F48A937FC1F99975644E89D667CA7BFD73152482A591603B5C53DFAD22670F8732CEE82EFF006DEB30E3A08F42FC585A5B5A02B92844465E9DBAF2CA96183F98C4A921C9600B538E7F8E01E24501207D44150CB5E747CF4A1A9BC29C4842415109EC624EBE53DA951B18ACB99A91A024E94D05C545E8748092737F4E828DDA239E5A54EAA0C8E4797E9CF2E79D466270870E482A496D0BF7E2C7979C6C9C4EE108524B3163AB0E7AE659EB68F024AB3047DFDFDE751AB9A11A77A77F5FBC6DF337FEA0925F874E3A44B5A7FC694F3060FC7E3F4AD133F7D411BADAE473B1ECDCE8D9339EAFE4A6140ECDCAFA9F7AC4FDBD9B8E890A4671A98F3D7E35272B0A66241DE009C9C3679F6D6F58899D8E4A09705C8B916C867CB56CDE24D9B752141A50E229FEE198D0739F8FC0F3A723FD3FA0924E82C5B4B3FBCDE22E6CF4CC5EFB64398A7DFDBC4DB164E2C26074EDF1D79E87A9F83B9127E62812EC0E4FE6D97A437998842695D5EC73B71A44EB5847E2994B6F04F87A029FCD139E664663EE6ADBB3F0CC52EED537771C05F3047A8887C462D0EADD249346366E0D973CF4CA5B0FC25FB058432F2CDBA89E26D6A24C7602AE5833F2C00C28D931A67C7AF18839F342CA8AB76954DA8E00F32D66A8886DABDCF6C9ED9B4FBEE34BC2311B8482EE278725B62F5C291014E3B1C4AE180019D32E74F95B424CB05252E450167EE4DF4E0CE620A64DDC5804037DE0CD7B1B79E8D7731AFD8BEEEB7A7BB8E0FF00F02DA36F1465B595706D25D3CF4A78A4001B006432F9654CA66325CC2490CF9022957CF8FBCE1F499B2D49092CE4977E3A96D1F3D2CF0C93BC3F6810FA8E3183E0570C242415E1EC5CAD0B84804A4930731E951B3D6A9B41D2ED4356E9A6B5D626B048C3211BA120977DE663772C7ADAB4D22C4DB4DE3EF70B0B182ECF30D5C807DE7ED5E08E239CFBB2489988CA39D464CC395134B9C9DB5D072A7E62CB2264B003173CF875A575A4609BDC3FDA2B6F1A8C5F17B4D9AB57894A9CC11EBAB4C40A78A21C2A904C6424E4093AEB90B4C90CAE9DAB9B1A534787416822961951EFA7BD625365BD9C7F0D709BCDA0BBB8DA0BB510A55E62AB17373275295AC4CE7F28E8698E227CBB0FB70360DA5AAFA98732E720067D19D9FB0F76D699FB08DDE6138516D2CD9B4A2D8050EB8DA7C46CE521063204E59C6550F8898E5F4D73ED5341EEB12B271728252D7CC585697B3FBD62F746CC593A80A4ADDB77844AD82105E11925C3FDC00CBA807A45442D678BE4F6F51FBA1D0C3B5E3DE8908296FA8915D2963A69DE1FB762CDB302DD2CB4C944C2191C2DC927DE8EA7F32BA9EF4DF14AFF00230EB9207D6CCD9307C81EBC223D58E44B5EE83BC2EE6A4B9B7E05B5E292587418253C33966491FEF2E5FBD5691255B3E6FCE58700BBD09E5DF40FCE1413153599DCF1605F9B59BFAB4561DB8B45A96521FB55A7FA8D89516C9109244C244E797298CE9F61F6B1DA1351874214E54002DC6E3D96CE80422B94A2E09AE47DD072D0D59E386DFC4F76F36B37A5896CEFB2DEEDF137862FB4EEBF6F8E3985BCE78762CF1377091745A254D9532A504050FCDDB2AF6E7C06F076D09F3F0B8C4A52A09295044D7293CC58B33F2E05CC5E217B8E0A9DBEDAD1DF2A519E30C7B3C7F02DDCDECCBB61B4BBCFDA6DA8C79C7FC1BC7F0655DDBDD61E5E570BAE2576EEB67DC5384C89CC124E75EF79C572B00304B4A65CE284A775144D0370AF5376D229F8EDA0B913944294D56AD752D4E36CEEE5A3B3BBA7F635F65CD91C53086F03DD2ECA5B5C58F036D5E0C12CD172E848482A79C48F79440CF2CE67AC34F0FEC49F2F1E99EACD4EE4EB9171CB4B1AC53F6CEDB2A92A00AAC4104FE38971A67668ED0EEBF63F65F66F00B5B0D99D9DC1F03B4286FC3FE5D6A8B67084C157104E473F5835E88D9C52AC2225101F75A9996CFD4EB4B51F8A6D913311326CC0A356706C2AE19F8B8CF8465F72D564A0F88B2129FCA1592A00FCD3A904476FACB6130B2652B7CA06F5C1233D1C7B073886C295214525CB6649D2CDEFCA246C82C329E3E1933F97439EB9E7D7A5389C5256775F893C87BFBE9B4F52553094E801ED0F2928460A20828820A20828820A20828820A20828820A20828820A20828821056A7CCFD694979F4FBC3399975FB4548D4F97EA2915FF13D3D442C8FE43AFA1847861D7951AC69AE5D7F4A633BFDD425DB27A37EA16171971D22D9DB04716097794C20E5E87E3E54CA60FA59A8CAB0D787B787B21492A507AFD239D5E9E75CAFA472EB7B6BBE385ED5B587AC2568C3AFFC4CD420AAD9EE09033C8C46933A19AE35E35D94162762022A012EC3425FA51A3B078627844896934219A9EFC99AB1CC8F676DA96362771B8E63BB5364C62BC18BDE5A5F5B38DF8CE94DEE2EFDB347857D0382267B682BC51F11B6EE23662E7A5256129DE176D6B43D7A5C10F1D8B63E24290900B12DC496E1AD3D6CF0E778DB8CC1300C291BC4D86DA156C762375E15CDC5AE27749B1C3AE9774525A43086C4AF3720A4CFBC40D4D795F69788317B4F12A940AD414A20DCDDED56D795ED176978BDD4B29C8206EB64DABB172386958C6569ED8988EE871CC3776BBC9C3F16B5771542B87692C9A28B171B6DB0E871376EAB3494119E9D349A9BD8FF000E311E2097F35525DEBBA524294EF402C7CFEF11B8BC4826F40ED63CCB0D5E835E51B3FB31ED35BA5C4F0AB6759DE560092EF11F0B10C559178933987532633C93CB21DEB5C7FC1FC7E16614CB90A005BE9200A3E94E361A18464ED34246EEF3330A1153F67AD5BA5232059EF9362EFC8559EDAE07700E858C41B50D01E44E4476CFE134EDA3E01DAB8376953A8F6490E43816FEBBC48C8DA2852AA439156F215FDB9D1AB78611B4985E2EB439678CBF76E3874B57D2B615063DC00C9D33E53CCD50B696CDDB382DE644EFA49228A661CAE683AB718939535332C5ECC4D0FE7F65B38BC6E6CDE5301C7AE2E186C8FCEEAB875EA488FAE5F1AA4E2B696DB90B2DF3C373671A0ADF5A01D2AF658429802951B109A90E730DF6B68F0CEDDE436DA52DBFF8842491E2F105CE706543A69A11232AC61F6963A78FF5FE6151615243EAE3CF3F485BFC32A62D4C81E37F2CC919DA245BBAEE4E9CE09F5EB0465D674A9EC2A04D00AE845F79A94CC1737E40E9AB84E10243333D8E5F625FD4F794B5B900A3B4FC01FB8FAE469DCC952A5A77814BD2BA7B6B0A528D688EC561D92A2D4670DFBAF0F4BC5E36174084EBDFD7EFAE91D05444EDA8B904849342C188D3F54AE7567AD3F1D288DE167E67F75356191AD691775921B79285989333A671CBEFA73CEA5B073D7894256A241CCD8F3AF4BF9443952852C479FBD738BB6C996C464339EFDB3FAEBD39558F06A4A4D4D465626B4ABBE9F9CA22B153164DCB0A96E56ADCD7D22E4610D04241E181F18D403E67D0FA656BC1CE09DDBDBB3FE69CB8C424D52C28FF003FAADC3BDAFAFAD651A4B320C8111AE8341A8D3F69E756191884EE9750B52CEF9BB1B574E10C56A5870778B7FB8DEAC6F415B5DBBC392B4B44919B640D73072198ED9FF98A8FC56206FBBD0DD9AB4D7AD75A50445CD2A54C04B5097E595EAF5AFB30C2EACAD710052BE132208CBB46BF0133CFA014DD3880A7751072AF4D791BEBC21CC85949FAADC457DF4AD9D9E229DC26D6DDA36E8F0804CE47501464E5DC9903ECE4CF2186F31ADC9EBE599EF4898C3E24029290ABE55CF4FBF18B2F11D9DB77D4726733DA3BEB1ACFF9CE813C1A953E95D1F537D183DD844D49C45C8DECB831D73D2B9768861B3987B29085B6D29C4CCC0067B826397A10353A963397BEAF7DBA655A5A1F2318C0024B97AFB6A37EA1B39845B2092DB423B247307EF99CB28A6335EA2A79E97CAD5CB4AB34394625D4050BEB56E373DA1839837192EA5B0907310348EA0FEC7E951F312E906A497A135D0E55E5487D2F12919E54073E601CBDBC47396FE04C1397FDA728F5CC69CBD3234CD5289C800E5AEF77CC77870310F7722C5BCF33DA235D471B8489F41F03FBF79A48A04A49530E3A9F21D6374C833485901813C9C9662C1EBEEA4C51E17FF6EF97DC5203069DA0B1299CA8814142E6D636CF31CDDA464832C0A800543D2ADED87DAF83B7FF00BD5C3774BBBAC7B1CB87026FD4CA6D70EB30522EAFEEAEC9B767F0ADC85381A75C429C23348CF235D93C05F0A4E3B112270C3B82524326CC41AFBF3610DB178C4A105EE1D99FFA1F637223497D93F702E5AE258A6F877ACDAB13DE06DCBFF8CB87AE41791B34C30B51C3D36EA7878B686EED56DA5609FEA1194F3FA23F0C7C2C3C3F8792A52370212059AC2971426FEE951C76D015FA99DFB54D39C74556D2BF0EC052022324A522070A7241CCC6691396B3975AE9B8D299D8B0B4DB53A5AEFAEAF9DF3A76D09E263A81241A35C9C9DAFE77AB9CEECD8E6BFF00E6ECE468E0D27A8CB2E79FCC9CEAD3B2100292482F4AD0E9735D08E3D4C50F6AAC90A25D8851F7D2F4A9B523A5FB12230CB11C837A8CF90CBE1F1F4AE95B3EC19C30CE85EBE9AC51316B652C3D1ADAF21958916BC64958800F248F5FBFBF2B0A1B74019522292A1BCFA1A8E632852D7FE14FAFD6933736E96E9082FF0091E9E821C56235828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE863D52638CC0CE3CF2EB4CA6921EB666E0ED0B45B1B440DD61D7368810B75042547F28273127E1CE99CC202483983E4CF0E2424858551A94ABD639E5B7FB2EE5AE2D8E5AE22522CDF4F8772A689CD0F20A722A81A28820CF58D6A87E244A67E1E6CA672A0459FA51F3D2F5238F43D858AF96948DE619134CEDFB23CA3827ED7B816F1B703B67865DECC5AAF1ADCE63B89B3738A58D925DB8BA67C1B969D256DA21848F1D4A32AE93135E40F1F7C3CC46D9993B76593BE4D4268D5CF4EB7E21E3ABEC6C76E9402A3955CD6FC38BFEAD6D7B69FB55619B63B05B0581EEE302C7717C6DF5E181EC2F0BB64BE2D976CF5A150BA65A3C48E20954C89C89E55C9367FC12C4271816BC3D029C9DDAE76A5B2E758BCA71DF403BC59867C087F3F2A868DA1D97DC15EEFAB0CD99DE76F4367DA699B2B0B3186E0AF5A94AC45B32CBE9BD61E04428A791191322BD25E0DF87B87D9E895F3248FA4016AF1CB8B7F548DC563F75249512E0D9B8919BF71C5818C9B8B7B296E5F1B2BBB1B178260EFAD08416F09B0B761A4290908E3402990E28895AB9A89922BA54EF046C89E9DE992251240A1482C4B5DE9E561C43D7266D35A6690925B30D46B57DD39C623C6FD88B622ECACE1BB47B4F8324CC270DBB6984A7A00026321EBD339AA5ED7F865B271214061E4D41B203D7855DFDE913184DA0490E4D6FD18F43AF78C4989FB136F1709BB7AE7767BEADB5C3EED9016C338FED03AD614A58121280CA41827256999EE2B926DBF82DB3F129294E1651A963B81F3BD2A38D7C8BDB3058F620EF03931CDC67D2D50DD22DE6F799ED7FECF771C1BC7C393BC6D9DB7242AE7056AFB15716D27995BC420A881993D0F399E5FB4BFE9EF0F396B50C2A2D40101ADA6EBBD0B70B459B0D8A964B8201615058D879DFB50B5636DB735ED6FBBEDEB5BB0C3C95EC863A6517382E301BB1B86169240058E22A495C710CB30418AE29E27F8313365CD98518764A49A25059874ABBBF37E0D60C2CF46EA4156FB13FC8826B9BBBBFE9E3692C71766F57C2CF8859569723FE050D4292B920883D79FA8E11E22D9188D8AA9837149092C0976001ABD9F5AF9801DF2A64B525C0045C01573DBCB2A6B5996F14B761E0CF18700221C410A6D5397BA474D3B9D473AE74BDB334CEF92545AD7FB3DDF952D686388489B294424A5C588EBD2AFA54D327BE30ABD6DEE11C611A415981F1CB9EBCF2CF5A9FD9FB317B4589058FD5514399E2E48B53F351C7E15552524EACEE6F61C2FA3B6822F9B47168E101E41E8127AF31F2CC48F2E73E30A7027E530200C8D2B5D3F37D1A2AF3E490B2C9525EAC47BE1EC345D56778E048F789D34267F5D3B4C65E54F30F34EF3B86A3DA94E957074D2D11B3A4B92E90C5AEEDA65ADB43CDE25D1882A47BC124E441CA23D7591AF79ED53D87C504DCF177FDBF0639758879F214092C487C85B43C3F1E724DDEAD4212B132273F2CC73F3CA338A94958C02E68D9E8C0E9E54600C464C96A3BCC09CB80A6B4E1971B44AAF106CDAA5A85174482A0070FA199F3CF5E8669ACEC63AC8717CECDD48BEBC4F3860708B528A98805D8313D5C0F2FB4465BDCDC34E95A9529998075F4E5F2A47FCCD19C35496EDECB768593875020949A7FE26BCE9FD4387EF90E38A570E662720740074FAFCA8FF2CD5CD7A7A5CF06E7587D26514A47D2435836AEEF4E3C3B34352FB2AD5B9F41F3F8655918C04583E7FA76F46CA1D252B702A3913E4DE7C2211F682EE56BE121063DD034CB9448F43D474A513337C02146B93FB7F487282ACC1E7CB81FB6799BC2CDAAC513E234E11CE123303CC83F5D73E95BFD2D577CD9ADF9FEF846CA3382BE921F8BD2DCEED71F8641E530EF1065B2949D0A840F5EBAF98AD7E48517B067EA74BF11C98B6AF6419C024AC826B6726E496F2ED945A18A5A49E3F11B4E44813CCF58CC72E9D6B070C9AD3CF37D1B23AF0AE920998B7018876EBC98D47166BF216AB64ADE79A8E14B31C4F1C9A3C59A615CCFEB505B424CCAA520B0D38B66D9E9956D13D879A99720155D87D39E76F77EF1686DAEDBE05B01805EED1ED2DC270FC3ECDB538953EB4B46E826470DB9564B512008EA40A9FF0006EC79F8AC7C92A42F777C646B517FDF0E2219E231E84950DF7DD150F6719F6AE9A8CF99780BBB4BED81BF2B0DAF7AD9DB6DD2EC7DC3BFFE3F8462485A138AF8882DDCBB88319B0F165F6FC5B4524E47849AFA4DF09FC3587978590A99280FA126A90F4029E85B2F28AA63F6928957D74AD03FEC6BA1CDEF1D14B6C26D10B7B05C3385AC3184B097DFBD01372F78094942429320A1A52785B06084848CF5AEDFB4D48C048DD943758300037B033F5CA2AD89C5AA6A8BABB1E7D746E05E913CFB8D396AD3AC92B687B80EA4F8709398E597EC2B5D91BD8A4852C0E04DCD79B53F0E2A223D73094A9E8189B9F6FD9FAC5F3BBEC31FC4715B6798294A50B1C5C5209CC1E5AE433D4E626BA36CAC391BA7938E0F677E40DABC6299B594EA5358D40AD181E1EC115B08E92EC8D83ACE1966B52870844473919139FDF99ABDE0E584A4166E038801AEC6D4D2DC2287895A4A94337A12ECCF97AD59B8C5F0A525488FEE20CF4D7CFE952454539D2AE333A74D7D888D0A2093AE4D4F7EF575ADC10D007A9D3CEB20B807580972E7385AB318828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE862971D482519CFC3F63EB4C66FF00BA9A7DABEF585D201501AD7A0BC473F6A5E049E9CF33F7F4F432CE6074B9205C578C3A42802C680B5B87BBEB1AEBBD3D8543E9BEBF21C7137A905411986BC311247298D67F4AAB63702B9B38923E9341D8DE97E97A50B189AC0E33717BA19810D4E5A3BD4D7F348D16DA5D90C1F16B6BBD9FDA2C16C31CC31055EEDDDBA6E5C4024A8F0858E1064444E446424547AB64E15559A849A33103D68C7EDD0C74DD8D8B2A4A54E7A1E77007DAE6312ECE6E8F74183624F5CE1BBBAC35772957126F2E30B6086D59E6870094F0E83908D795339FB3B65C9FA932D00B6807F4E7C9B48BC4AC613280DE34B826C3977CB5B464271F7025586E1E52A62021BB56B3619198090819240CB4D48911A88F5AA44B27E5002E404B060D60DCB534AD5DC4663316A7FE4C2AC41B5E9CF216111CAC39FB64969F480E0FCC120C0E2322273D0E63581E555BC66D0C50584A0AC26AF520355BBD7CC4478529642AA756CEDF7CEBC6E5A21FB6F7A232CFD3E47D3A7C61B2319895FF0032B2FCEE6F4E27A7189492B54B00B9CEF7716EB51E9AC4270076E96CDD24861A23C328D64E66493D73F29E722B6F98A5B15A49702E0DA9CE822670B8FDCFF71F3670CC2D473EAF156321BBCB33875CD9E1D7387A870A85CA389CE1E73CBAE67D295DC94B4D51C983BBE5D470E71352B6CEE007798F0E81A97CAC5F9C68B6FBBD92361B6FD6BC4F64F13BFD92DAA92EB177B36F3763FD64C293F8F5A015F04800091913A646A8FE23F0DE13684B984CB495149674826D6B711C6F13185DBF91517CB30CD5D0F1B75AB4604C037DFBE5F664BE636237A9855F6D8ECB29618636970365FBE5DB320E4E62376EC368805324468ACA6BC7BF113E144CC67CF5489143BCCC9E6E5EB4AC59F05B5B7C004BBD5C105DEBDDF5E79D3A49B9FDE0EC4EF4B08B6BDC03686C3104B88E316F6F72DB974DA880A5B6E25130B42A52A1C8823B5793F6CFC2BC5E027AA6192432892774E5C481C75AB919C4F8C4054A71A33F6D3F7CB5CC76EFDBB37AA6D97DEF1983932FAB2544689D4E4397999CA9AE0D32B633226B0DDA1DE6D08FC30343965092F0C569214012450E8E28D90A0BBEB58B818DA3BB5DC00FA030B100B69052948190201D02B224EBDE69AE37152F1538AD0CC49B72F6FAD2948ACE236780ADD04AC027EA2C7D916AF570232560D8C21C424A97079927FD03D23CA3A53742B749AB3E7EFDBC4462B6791FC53958D5F4F36BF578B9D2EB6F283895E47BC67E59F6C892234D69EA66669533DEB7F38879B8577494D4065532E596773969126C148CC39E8159E9D20C680FFAA709C492C0A83F7EAEEF9F4B8B4464CC1A41FE1C5EC2FC73E34AE50AAEF434A28E398CCE7073EF041A426E21492594FF00D0A7BF468DD18305208043EA1FEDA367D228FE663A9FFF00D87ED487F94BD4F61F98DBFC2F7BBFA8ABF19C598224EA0AA08F9FC7215B7F9254010A19BBB7979F58CFF86902A97D4D07D87BBC1F8A13AE7A73FACE959FF2A9BA5EA6E0866F2039D5B9C63FC66760903437F207D4748709B849410A201391279687F5FF00753585585CBE2337F64E55D73C86BFE3A82AD4C9AA3ADCBE7C21A3972D0D60CF5F58D481F5E5D2A4A4A42981E6065D69AFAE90AA30EA51277496CDAE03707CDA20EF318650A5B08202D319E5CC48CB3CFF005D69F252281B8659F67F2A5290FA561CA40510CF4622D5CADA58D62D5BCBC6A49B8B94A1339852C800753F0EB9D394480B60A0CDFEE6615B548ABF67A43F461CD4B127219EBA7A03C1EB18C76DF791B21B1F85DE6338AE316D6CCE0CD974599B8421EC51C5025B6DA41203C50B0124488E2EF3574D89E085ED7095097BC090FF004B923B7DBCA19E2B1424A424BBFD5AB27CF2BD29EB1CFF0052F6E3DB476A8DFE32DDE6CC6EB706B8219B05872D177ED255C33E1AA597015B61407454F6AEFDE0EF849364AE54F121AC689FA4336A38393E6CF153C5E3021240512493BCA37CDB78FE7AC6F66CCECDECB6C16CF58601B1986B768D59365B2E25A4216B5180A52CA009E23267299AF54F86F672F644A952CA5B7404D29976E1DDC18AE4DC495AEAA2CF99ABB73FD680677731656D7366B75C3E0BCA12E1C84EA79E672D663F5AB6CFD9EBDA83751BCA243E6F9643C867935A044A2B2491AB7B66B0605EFC8C37B5B668B0DDA30A2B6D2A30A104925524C9EB9919FD26A5766ECB3834A65AD0410F96BA599EC2FE6D0C718D2DD35000A92EFF0070FC5B5A0631B29BA6D9C21E65C08C8A92743D729F203F6ABCECD96C94D2A72CC8143CFDD6B145DAAB7DE2E5FA7A5FCAFC6379F0867F0F87B0D10470A743DE0F3E5570C3A5887B1D2F62FC2F147C5CC725AEECF7D0FA5B2CB9C9D2B3087352DC72F3E5EE911BF32AC547B96F7AE435876CFE41E66B32CDEB4A379C2E92E906FC7AC2B4A46D0510414410510414410510414410510414410510414410510414410929064C6739D6E9504BBBD5BEF0D972D459859F5E1C22A4248249F2A4D41C11EEF0A24177666D61B2D8714E958238491A93947DE7F72D664A529D9FFAB37BFD2C181048B438E0CB5CFE5FBD22AC312962F93D3AE61BCE3255F56F0E8FDA2D3C76DEE31143F60865A29527878DD4CFE607F29194C76CA0674CE7210414EE90A66A8B355DFF00BABE4D0F30E374098A5115B3DF2B75B3DF48D29DE7EE81EC25F7313B2BDBC05C5296FB2870F8644CC25206801391CF3CEAA3B4B0F88FAF71442AC0825DAE486D1DB3B6B7BEEC9DA0896849B80CE3CA9FAE51AF97187B56F76B45BBD7EC37925C4BEAE149207BD09034267A73354DC4E0F686FD56A524E44927370030E2ED7ED17295B5D0B48029C2DBDA1E35E0DC6AF093682CBC1AC398694167FAAFF0FF0057A92950E799D40A4D3266A48DFD5944F503476E35BC626CF135254D52CEF6B86D5FBD7842F7987AC2D50A5A814A4F13C6564902412390CE04E4075A96C3E0B0CB4BAD0144DAC7B07FBE79D214958A44A001EF7B5455F9BE82916EDCD9A9274D394FFACB9E91D795666E1306827FD31FFD23ECF9D3DD1C231C951228C0F56767F23DDD806868E58DB78056DA26E553C5C63DC1D2329D2751F2A8D9D2A42086450568056CC2EFDFC9E1EA26850749619B96ECC6BCFCAB4B3EFF000643CA2A76E6E1067F2B4A1C1E5A1F8CEA08A62B54AC9200B3066B655A7439584384A966DDEAFE54F2D22199C2D9B275D5B4DA145407BEB48F117023DF235E824F59E95193247CD984DD2694B75F36CB430FB0F2E71008530D41208FB65E94D6CFDB0D93C236B70CB8C2717C2AC1FB6B84942C964294A4AA66788473F3C8F794311B0B098992A1364824E7BA33E80B3EA79E462D380C61925017500D49B65573FA191168D19DB3F664DBFDD29736E7D9B719698C5D6A5DCDF6CCE22FB89C2D0106786D2CED42540B89E22A0755281CF2AE29E32F86F83C7CB9BB92424A829B71201CFB777148B8E1F6E484240500695736CC5DBB6515EEC3DB771CB1C5D8D94DFCEC662FB2DB40DAC30EED13160BB2C0F891092EAAEAE55C45110AE2CCF9675E33F1B7C0ADB7899D357835AD287247F3720540A03A6B1292FC418520B8B86000147A1CECCFA3BDF4E87ECB6F036476B9B6DFD9CDA2B1DA16D684B89BBC3EE9174DBB29E2284AD33C4A6F342C7250E935C3319E12DABB0712AC0E2513173525B7D94451FD68DCDB81504F933C6FA0009360CDC0F2AF5CF9647C331B5292A952AD4A084FFF0022513248919E607603CF952A36362C23795296903FE40D7859FA13F686CB4058CB872396777E2F1778C6EF2D582B0A53EDA38214DF110BE331EEE70424913032F95436254BC2A94952542D71A6648E1D6D9444CDC1A4A8FD22AE48D3BB68F9B70222455B4D756C9694B0E2D4E09094495088D472F21D472AD64CD334B82C4317D35AB9B4305ECF0A2E052EF60EE7DDFBC4BDBED236FB4DADD65EF19C305B09F78198CC6713FE69962B1E64CD2820AAA6B46F7A9D78C339929129450A42891983FB1A8A5EF12C9BE44A78DB75949FEE713C20749E629346D12A3541166B55FA1B76E302512D401092736724F6730E1FBE6ED9A0E825E4A808F07DE27CCCFF00A83953C9334AD8258BDA9DEC5DE3099466160821B23CEC18D73FCC26CE32DBA9E2216D000E4E0E1518EC7F61F0A9093835CC75070EE4795EB5E59F3853FC298EC03926A2EC28ED5157340417F2886BBDA74A2E0B6DA1F7018014D00A403CE6397FB3AD49499A70E7E5EE289CC81D3BF377A55E1F4AD90552C15EE8A5CDFABE61F9579C20F63C86C02E3E1B075E3504F0889CE63A7CBD44D6096B9AB4B2147A6668E7FAA1CA30766194EE46EB3029A3D5BCEB9FDE31DED7EF0B67F6612710C4710694CB82438DBA928102082547AC0D27D6AF9B23C3789C79425093BCA6BF16CAFC0FE03422BDC94EF5E7FD30CEBEC6986F43DA1DAC5AF11846C65CBD7F7B70781A4D9AFC585188E2E054E848FBCBA76CCF851B4F18942805004A49B8A38B822A1E1B2B69C9942A0588BB3B38BE64F4BDF45F6437138D6F1D386637BDABEBC6ED2CD65FB0C2AD5C5254F052B8E31261E1EF24C24B607F6933CABD3DE01F86E76761651C4A0129097701E9AB8AD341776CC45076C6DB96310A4805AAC435DAEF903C637170BC1B07C22D6DACF0CB0670CB5B3425B6AD6C5B4B2C3C94A42429E424C29440E23A1E23AC57A2B65E070182C3A50A949DE48000DD1F8C9F26EB157C4635539F7598DFBF3E4FAC5C4EB4979A42AC98436B392894F0A0C18CA3393CCE93DA92C64844D98552C6E8B06B3741DBEC6B08494294A05F788B3126EEC39D756BC0F5BA516E52B0B0A508514446B999CFB919139CE862AC7B0F1387C26EFCF402F4767A5466D6FC67589CC3A928B9761504D6DC789CB8D5CD54D9FB12ABB6DA652B5238F20449CC826791F9F7CAAD8AC08DA2A4CF900250A62C030B72F75393C5736B632589AABD99BA72A37168DE9DD6E0AB432C2D480880932444E5241FDF3ED52985D9AB92A00D599F5176D03DCF1245EF147DA0B4A8296429839005CBD3D7CB2358D9069B21090001023A72FF00433A99972F728A72DA9AFA51F93DF58A5E2120BA83821C56BAF2A7B1A429C0AEC3EFB4D0B46F5B30C7DD623D72F7AD9DEBC5E1CB7926398D7F4F80115B253B800E17D7DFEF38712C86DD1FED1EFC88852B68520A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821A3EE34D92A2015467D48F989F81A6B324EF0248008CF5EDA5EB61942885FF00B4AA8198136BF6EBD22D6C5B0BB5C6D05B7DA42873E248394F2907A673FA9062713852A72433D2999B657F76A9895C262BE4021C90C0DECF90CDB80F28D76DE1EE5517CCDC5CE16D842CA491C020C81D00EBD0EB2222A0F13B394E0B2800EF43404D9F2B795227F09B5104805401C876A5EDCDB5AC6B35AECF5EECFDF2ED2F6DD6485405291F3CC8F3923E7509336792A50DD37BB54BE4697E7A44E236900032AFFED2E74ADAB9D9B5176892BFC33C5714B4A40040CA34C88F4F88CF5CE95460FE5A40666A3B1EA3856E087B16A557FF00304C6DD37CC963636AD9F969AC5AB79849930939EB9798CBAC4D369D215BA4B07197AB73EC61DC89C01363625EF4A9A9A38D74B59C413F61C1C49888EB9779EDDB3EF50F89C392E4675E56B7323C985E26E4CF70327B686EFF00AE15E56D5E589E239489CB43CF97AF3FD62A24C9625C647A6B968CCF7E31252A7848157D2A19C5387463E8D10AEE1DC4147864C667E323423EF2D49A66A5EE2C0341A350DA8783FDEB133879E0241DE07870B3533FC86CA21DFC3553A13E59FC2048CFFCE993B4AF7D208343D9F90F7A43D4625259E95701E8E3813A674842D2D9D6DF5B686020019BCB494A5723FEDA98CBAC75E9178DC399885101DC663EC6E3FA6178749C502A636C8022A5AAFEA22C5DB5DD5EC06D9A56CED7ECD5AE22873253CDD9B6EB99F3E258D4E93D7AE7547C76C654D52814BBB801A95A58FBEB50EC62B46073770C39E7C9B5D2358769BD8D5FC18DEED1EE5B6E719D92D176381BF889B2C2D970020A516D6E9C92E2C4AA224CE872AE7F8DF84382DAF89562A74894B98A2FF5A6A5854971D6834ADA2C982C7A53280DE6200706C5ED9F5357E04C60C637ABEDA5B98C69CC3F783B1B866D6EC55BF1A9CC6707B0BEBEBF36EDA54BF13C77086F88849CC889CF28AAEEDDF83982C3E194538745029BE9E1614AD39D2B7A449C9C626630B3B333E75FC3FDE919A775DFC477737B73776DB34E626E6038A61EA71AC52C318798B7B9B67944801D6B8A5292B04A246600033AF2A78F3E1A623040E213865224CC2AF953770842F74B16362D6247F6FE5044C53392736233B5FF0059E85B6C70DDFE6EE31265E36BB6DB3EAB87024DAA1EC41A0662600067211315C50F8731B266EE2028024D81D73A73CFCEB1228C0254086C9ACE03F215EF9D844B61BBD1C2AF8AD4D63D87B970DE65DB7B90A61433238153C80131A6A3A53F95E1433803350EB3A8E3FDD2EE6174F86D33C0594824D4E9E60FBB6717261BBCC43C1DF1F1266EDB6B3E169E0BC87627B453A1E0EA809964D724BB771EEB01F0DA10092814B960FED8449FFEE8E10E5AB6E1BB2C34A2A002969470C18248073CFBE94FA4783E72082892A615FE2FDAD715E26819A103B225A0BEE80012C5AEC73B8D323CA23717DEAECDD8E1EBB84E2C2E16904F84D3E9528F6893AE63B7ACD494BF0D62890912D49721C37767EF9706784FFC244B56FB208A31A6F646BE74AF58C4B79ED47B2B84D8285CA5EF1D5E22521213E285490264F32411D6262BA56C6F86EBC6E1D334C92544554525CB90F56EA78E60444E2F172A42C85123402A939D6AD4CF2B5B2C2D896FF76C31E7DC6B64306C43145BE48652F30B7904AA40808327CBE9575D9BF0B5689809901A87F8E8796A2B1098BDA89DD2029935B1F79BD9DF5156A309DC7EF7F7C0EA5FDE25F39B2981CF1A2DEDDC7ACDC08992149765209232EB273CCD764F0D7C3F32572CFC948008B2780D00C868DEB157C5ED10EE54C0BBD682E00CAF616A9E91B47BBADC2EEFF621808C3B0CFE6F7AC0138BDD32D3EB0B4C92B0FA6089339E672CC577ED87E14F952D2E9600682ACD4B5816FB457311B40289216F53C5891EDB96869995A64786385C0B0320419000C824764881A888F4AB72657F88D2AC2D4A12C3A31A55FF005159C54BF9EB52C3D3B8D6A59EDCA14F00F5F4E7F18229CA092A152473A5453843032FE5922BD7F1D7F1136D5E356B668429292A1324F39396BAEA0F202A4E4E154B1715A37AB5383119D3284FFCA1243B81773A5FCECFFDB1685CC4D7C2DB5C5240809D2644EBA9E43A72815252B66294A02C4B1A5AF5E43A8A645E3076ACBFF9E55AF36CAC3A3F08D8CDDB6EE55768B5BC799E10A2492A4F43DFF4CEBA1EC89224E1820DC5B4BD5C9D39E715CC6E3133662D64B019937BB8A3DCF1E91B8582E0B6D84DA2128400A4A7A69FAE675F96553491BA092CEDD3DDACFC0D62A98BC52A7ACA45100B30CF9F0F662E2617C6DF144493F414992E49D622E7A774A83BD8F7685AB10C141945BDD21540CBCCFDFEB446C8CFA7BF48AE88520A20828820A20828820A20828820A208FFD9, '1', '2021-10-06 01:13:39', '1', '2021-10-06 01:13:39', b'0', 0); +INSERT INTO `infra_file` VALUES ('427.jpg', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFDB00430006040506050406060506070706080A100A0A09090A140E0F0C1017141818171416161A1D251F1A1B231C1616202C20232627292A29191F2D302D283025282928FFDB0043010707070A080A130A0A13281A161A2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828FFC0001108017F038403012200021101031101FFC4001C0001000203010101000000000000000000000607010405020308FFC40051100001030301040507060A08030803000000010203040511060712213113415161811422357191A1B115233242C1D1161752545572749394B2242536537392E1F0264362083334374482A2F163C2E2FFC4001C0101000203010101000000000000000000000102030405060807FFC4003811010002010204030507030402030000000001020304110512213113415114223371B13235617281A1D11552C1233454910642B2E1F1FFDA000C03010002110311003F00E5000D57E96000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832600905ABD1F0F8FC4DA356D5E8F87C7E26D1EA307C3AFCA1F35F1DFBCB51F9EDF564006572800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000115001E49F5480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060C9802416AF47C3E3F136CD4B57A3E1F1F89B67A8C1F0EBF287CD7C77EF2D47E7B7D400195CA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000454007927D5200000000000000000000000000000000000000000002407DA9692A6B24E8E8E9E6A893F26262B97DC84928B67BA9EB1A8E6DBD206F6D44AD67BB8A931599ECC3933E2C5F6ED11FAA2A09D26CC6E8C44F2AB9DAA05EC74AABF6184D9B55AFF00DDDF2CEE5EC4949E4960FEA1A6FEFF00AA0C09AD46CCF51C6D5740CA4AA6A7F753267DF823B73B05DED795B85B6AE06A7D758F2DF6A6508989865A6AB0E49DA968997301E517D5ED3D10CE000000000000000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF500065728000000000000000000000000000004BF41E9EB75E9B54DAD95ED9E3C2358D5C70EDC7ACE4EA7B14F62AF5865F3A27718DFF948638CB59B7279B6EDA2CB5C11A8DBDD96BE9FA165CEF549472395AD95F8554E7C957EC3ABAE6C94F63B945152B9EB1C91EF6EBBA9727334ED4BE86F14D58CA7927481DBCE6B13B950EAEBAB9BEEF7064E9473D3C71337732B719E3EE2B336F1636EDB3631D717B15B78F7F7E9F24681B16CA29EE3591D352B15F2BF97777AF7131D47A4286CFA7BCA24A87F96B5513B9EAABC5A89D98CF12D7CD5ADA2B3DDAF8347973D2D92B1EED7BCA060032350000000000000000000000000000000000000000000000000000000000000000115001E49F54800000000000000000000000000000000000063217FDFAC9D58F4A525B6DECBD6B391D4D46BC61A245F9C9D7AB29CD3D5ED2621873E7AE18DEDDFCA3CE51FD37A6AEBA8A454B6D32AC2D5F3A793CD8DBEB5EDEE4C9275B7E8FD2EDC5D677DFEE2C5E34F0E12362F7AF2F6AAAF71C8D49AD6B6EF079150B3E4DB4B3CD65343C329FF0052A7C1381172DBC4766BC62CFA8EB967963D23BFEB3FC2695BB47B9A46B4F63A5A3B452FD56C51239D8F5AF0F71DFB1E89D41A9EDD4F71BBEA3A88E2A96F48D8BCE55C2F2CF144F7155390FD41A178E8EB3FECB1FF002A16ACEEE7F1498D0E2ACE0888999EFDE50A8B63B6A545E9AE55B23D79AA6EA7D87D1763B65C79B5B5C8BDBBCDFB8B0EE956DB7DB6AEADCD57A4113A556A2E15D84CE08F684D6516AC6563A2A39297C995A8BBEE45DEDE4CF0C16DA1C5AEB75D6A4E48B748EFD9127EC966A3C3AD3A82AA07A72DE454C7F95508954EADD53A5EED516DA9B836ADD4EFDD7B676A488E4E6985E0B83F43751F9B369E99D7977FF11BFC8D22D1111BBA3C2F516D6649C79E22D1B7A43AC97FD29A85772FD69F936A9FC3CAE8F967BD138E3D68A685E341D5C34C95F60A98EF16D5E28F8573237D6DEBF0E3DC43B0746C97AB8D8EA92A2D754F81FD6DE6C77EB379298F789EEED7B2E4C5D705BF49EB1FCC39EA8A8E5454C2A73EE058A8FB1ED09158F6C369D4CD4E0A9FF7752BF7FBFD641EED6CABB457CB457185D0D446B8545E28A9D4A8BD68A44C32E1D4C649E4B46D78F2FE3D5A40021B00000000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF5000657280000000000000000000000003260EB586C35B7C9256D0B1AEE89115EAE76319CE3E0A45AD158DE593162BE5B72638DE5A343593D05547534B22B2662E5153E0BDC4F6D90566BAA886A6E6D6C5434996E234FF00BC770CF1F611ABC693B9DA6916A6AE362C48B85563B7950B0AE73A69ED0ACF2576EC9D135AC7638EF3B9AFC54D3CD7ACED34EB32EF70DD364C7CF5D4EF14AC6F35F5F462B750D8B4DA3A929A26BA46705644DE4BDEBDA6AD1EBAB3DCB14F5F4EB0A3D513E7111CDF12A9739CF7AB9EE5739572AABD664B7B1D7BCCF562B71FCFCDEE5622BE9B2D1BC58D6C73A5F34EB58A8C4557C38CB55ABD68402FF7CADBE552CD56F446A7D18DBF45A84F765D717D5DB6B282A155ED871BAABD4D5EAF72911FC19ACB85EEE14B6E63563A7915155CEC22679214C3314BCC64F2F367D752D9B0D2DA5E95BF7AC7AA38090DDF48DD6D544FAAA98D8B133E92B5E8B823C6E56F178DEB2E0E6C19304F2E5AED2006CD0D1D457D4360A385F34AEFAAD4F8F61699888DE58AB59B4C56B1BCB58FB535354554891D2C124CFF00C96372A593A7F67F0C2C6CB7A547BF19E898B86A7AD799D0AED5561B1B560A18D923DBC1594ED4C7B791AB6D56F3B638DDDBC5C1B92B1935778A47A79A1743A0EF550D47491C74ED5FEF1DC7D8874D9B36AD5CEFD7409EA62A9F1B9ED0EE3322B68A28E99BD4ABE73BDE71E5D5F7C91DBCB5CF4EE6A22215DB5168DFA42D36E138E79622D6FC5DE9366D588DCC75D0B97B158A872EBF42DE695AAE8E2654353FBB771F628B7EACD473CCC8296774F33B9377117259F6375CDB48F7DF1606BF1BC891FD54EBCA98F265CD87ED4C4B7749A3D06BFA62A5ABF8F928CA8A79E9A45654C3244F4E0A8F6E307C4BF116D77E8248D3A1AB8D8AAD72A71445EE5217A8B67B86BA6B2BF971E8645F82FDE64C7ACACCED78D9A9ABE01931D7C4C16E7AFEEADC1F4A8864A699F0CF1BA3958B8735C98543E66E38131313B4C00008000000000000000000000000000000000000454007927D5200000000000000000000000000000000180A4CB67F65A693CA7505ED11B68B779F85E3D2C89C51B8EB44E1C3B704C43167CD18693796FE9FB551695B3C7A9351C6AEAA7F9D6FA17261CE7753D53DFDDCF99C1D58DBE5C60A6BFDEDAE6C558E5640DEA6A226530DFAA8BED534B545F6AB51DD64AEABCB73E6C5167846CEA4FBFBCB6E66FE1BEC9DAE6377EBA18B7B7539F4B1F344F5A27BD0BC46FD1CBCB6BE9AD4CF9BACDA7699FED8F48FF2816CEB453756256495334B052C0A8C6BA2C2ABDCA99C71ECE1ED4265F8A0B5F5DE6A53FC86E56AA685D96A45F42E13B373873E95FCFF00CA9F028E491E9F5DFF00E6513111DD5C56D4EB6F7C98F272D62768E9BAE45D90DA7F4CD4FB23FB8B26C940CB659E8E8A29165653C4D89AF5E6E444C654FCA4B23FF2DFFE653F4FE85E3A3ACFFB2C7FCA85A9313D9CEE3183363C75F1727346FE9B205B50B3EA9AABBD4D65BA6959676D326FB12A3753088AAEF333D857DA3ED7A8EE6CAAFC189A46246AD499193F45955CE3DC7E93AFA58EB68A6A69F3D14CC58DD85C2E1530A7274B695B66996D425AA391893AB55FBEF57724C2732663AEEC5838B785A79C5CB1BF4DBA7D5D6B7325650D3B6A155666C6D47AAAE72B8E3EF3F3A6D3BFB7977FF11BFC8D3F49A1526AFD9A5D2F7A8EB6E1056D23239DC8E46C8D76530D44FB08B44CC6D0AF08D463C19ED7C93B46CA7CCB237CD345144D574923918D6A75AAAE110B1FF14179FD2141FE471E742E8DABA3DA2A535CE2456DB99E51D2373BAFCF0663C73FE531C527CDE92DC4F4FC96B52DBCC46EDCDA3E9AB4D9B4F58E28B14F7557B299B331708EE19739DEA5E39E79535A92AA3D4913B4B6B0CD35EA9FCDA5AC7A61CAEEA455EBCF0EE72779CFDB25DFE52D58EA58DD98685891FF00EF5E2EFB13C0DB9DD6CD59A1E965A8AEA6A4D4540DE8D1F2C88D59913922AAF6A630BD4B9267BB9F4ADE34F8EF977DE67BF9C6FDBF4F5416F16DAAB3DCA6A1AF8963A88970A9D4E4EA722F5A29A858D0B9BB42D32F8E4DD4D4F6B8F79ABD7511FDBCBDBEB2B84CA2AA2A6153A94ACC6CEB69B3CE589ADFA5A3BFF3F2964004364000000000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE5000000000000000000000000074ECB7CAEB2BA575BE548FA54447A2B51738CE39FAD4E6022622D1B4AF8F25F15A2F49DA5DCBAEAABADD697C9EB2663A1CA2AB5AC46E71CB9162DCA1FC21D0ACF244CC9D1B5CC6AF5AB7A8AA2DB433DC6AE3A6A462BE47AF57244ED52796D9EB3424D0D3DD5EC9E86A9729D1E556254E784F1434F3D2B1B453BC793BFC375192DCF6D56F34B46D33E8AEA46BA391CC91AAD7B570A8BCD0CA16FD65874FEA755ACA791A93393CE7C2EC2AFEB27DE7CE9744596DCADA8AB95D2A3173991E88DF12DED95F38EAC73FF008FE69B6F4B44D7D776AECBEDEFA4B5D4D7D43771B51F45179EE275FB7243DDA9AB28AF171A9B5CC8C65448AAA8AD4545C725C2F592FBDDF16F953F2069D5661ED54926CE1AD6A7344F7103D4164ACB1D524558C4563932D95BF45C570C45AD3393BCF933710BDB0E1A534BBF2D3BDA3D5F7BB6ABBB5D29169AAE76AC2E5CAA3588DCF71C3077748E9E96FD5E8C4CB69A35459644E58EC4EF3667930D77DB6871A3C7D6E58AEF36B4BC69BD395B7E9D1B4EDDCA6477CE4AF4E089DDDE5979B3689B5F9A89D22A72E7248BDFFEF81F2D437DA1D236E6D150318B528DF323EA6A7E5394A9AE15B3DC2ADF535723A495FCD57ABB93B8D488B6A3ADBA55DABE4C1C223931C45B2CF79F2876F51EADAFBC4AE62B960A6FEE5BD7EB5EB23CBC7060F46ED295A46D58707367C99EDCF927790D9B650D45CABA2A4A466FCB22E13B113B57B8F8451BE591B1C4D57C8E5C35A9CD57B0EBC4B73D29748A5960E8A656E51AFE2D722F34E1CC5E676DABDCC18E26D17BC4F246DBCC2C6B65B6D7A2AD4EABAC91AEA854C3A554E2E5FC96A7615FEA7D575B7A7AB379D051E5710B579FAD7ACD0BDDE6B2F556B3D6BD17098631A98462771CEC1AF8B4FB4F3E4EB2E8EB78A73C781A68E5C71FBFCD3AD93D6B9974A9A4CF9B2B37D3D69FFD9B57ED435DA6B55D4B51566A295525E89FD59E7BABD5C5148D6839961D5743BBF59CAD5F61DDDADC28DBAD2CC9CDF12B7D8BFEA63B52BE3ED31D261BB87519238673E39DAD4B24371B75AF5B5A1B5346E6B6A9A9E6BFEB357F25C9D855573A29EDB5B252D5B1592B170A8BD7DE9DC6D69DBD5458EE2CA9A755E8D78491F53D0B23525B29B56E9F657DBF756A9ADDE8D7AD7B5ABFEF9889B69EDB4CFBB2AE4AE3E2D86725236CB5EF1EAA8C1E958A8AA8BC15382A28C1BCF3BD9E40010000000000000000000000000000000008A800F24FAA400000000000000000000000000000004B62D9452DC6E14D474C999A77A46DF5AFFA71F0261B47B8436F8A874ADA9F8A3B73516754FF00992AA75FAB2ABEB5EE3DECBE28A821BC6A6AA6A2C76E85590F1E72393FFA4F138D43A5EF17EB5576A06A31D1A39EF915CEC3E454E2EC263AB897ED0E6E4C94B6A37C93B569FF00CA7F8847510B4F6157748EBEBACF22F99335278D157EB27077B787B0AB10DFD3F7296CD7AA4B8C0ABBF03F2ADFCA6AA61508A4ED2D8D6E9E35182D8FCFC933DB55F56BF51C76E89D9A7A06E17BE45E7EC4C215E9F4AB9E4AAA996A2672BA595EAF7B97AD5572A7CC5A7795B498234F86B8E3C83F49ECDAE34F5DA3ADBD048C57430B6291B9E2D72261514FCD87B8A5923CAC52491AAF5B1EAD5F7135B72B0710D0C6B6914DF6D9FAEB982B9D8EDCE066908A3ADAE8D6A5F50FC3669B2F5555E09C5724EEB2BE9691A8957510C0AECEEA48F46E7D5932EFD37789CD82D8B2CE2EFB361EF6B1AAE739A889D6AA7E7AD65AD6EB26A7B8FC9179AA650B64DC8D237E1BC111171E3922F74A999F70AE62554EE8D677E13A45DD54DE5E499C60D2C7798E6EF55A0E114C13CF79E6DE3D121A6D69A8E1A98A65BC55C9D1BD1DB8F765AE44EA54EC52F4A2D534357A424D4316EF46C815CF6AF36B9138B17C781F9A910DDA5B955D35A6B2DB14CA94954E6BA4677A2E787BB3EA222FEACFACE178B5115E4888989FFB8F36B54CEFA9ABA8A99955D2CEF591EABD6AAB93E58E27A05267774E2368D9BD60BB4F63BBD357D2AFCE44EE29F94D5E6D5F5A122DA65B608AB69AF96C6FF56DD5892B31C9B2638A77679FB4873932A84FB492FE10686BC58645DFABA2FE99479E689CD513BB394FFDC5A3B6CD2D57FA57AE78F94FCA7F894010C9843255BA000000000000000000000000000000001832600905ABD1F0F8FC4DB352D5E8F87C7E26D9EA307C3AFCA1F35F1DFBCB51F9EDF50006572800000000000000000000000000012DD0BA8686C3154F95C323E57AF9AE6222F0EC393A8EF93DF2E0EA89BCD8DBC2367E4A1C808638C558B73F9B6EFADCB7C31A799F761D4D394EFADBC52D2367921499DBAAE62F1443A7AF6D8EB3DC618A3AA9E68E466F7CEBB795173DA722C35CDB65E292B1EC57B617EF2B514E96B7BDC37EB94735344E6471B37115E985771E65662FE2C6DDB667C57C5EC56DE7DFDFA7C9C6A1AC9A82B22AAA57AB268D72D54F82932D47AC28EF1A696966A6779639132AA89BAD776A2906C054C96BE1ADED169EED7C1ADCB8296C749F76DDE188911CF4472EEA2AF15E782F4B23AD36AB5C105354D3B62DDCEF2C89972F69456015CF83C6888DF66D70DE25EC369B4577995BB5DA734DDCAA5F34956C59DEEDE7392A132B939170D9BE51CEB65723BB1923787B50AE5155392AA1D8B56A0B9DADED5A5AB9309CD8F5DE6AF82987C0C94EB4B36E78968B3DBFD7C3B6FE712F85DACB70B4CAACAEA67313A9E9C5AE4ED45439E5B162D61417C44A2BB431C72BF8223B8B245ECE3D671AF7A01EDBA40B6CF3A8A593CF6AF3893ED42F4D4ED3CB9636953370BADE9E2E8ADCF5F4F387D7669624CADDEADA88D66521DEE5DEE23FAF2F6DBCDDFE670B4F4F9631C9F5B9657D44D35EDCE2B269F8ADB46A8934CCE8DA89CDAC4E0ABF615314C11E25A72CFE8C9C4AF1A5C55D0E3F2EB6F9867ACC036DC077345AFF00C556CFF17EC251B5D5FE9741FAAEF891FD9DD3F4FAAE957FBBCBFDDFEA7536B336F5F29E2CF06439C7AD57EE352DFEE23E4EEE19E5E159267CEC84AA130D9C5FD2DB5CFA3AB911B493AF9AAE5E0C77FA90E43286CE5A464AF2CB95A5D45F4B9632D3C922D7B1D1B350CD2504AD91B2A23DFB9C511CBCF0BEFF00123A8B93BD45A5ABAB2C6FB9C4B1A46D457231578AA2673F038284629AEDCB13BECB6B2324E49CB7AF2F37587900191A8000000000000000000000000000000008A800F24FAA4000000000000000000000000000000C2B55EDC378AAAA22027A427B7DCDA365965A16A2B65B9CCEA9953FE945CE17FF00892DD9DAA7E28EE1C3AAA7E0A4476BAE4A7BA5A2DCCFA14544C6227AF87C1097ECEB09B23B8F0EAA9F829963ED6CF39A98DF495BCF7B5B7FFB95231AFCD33F550FA1DAD11A6AAF54D7B29699ED8A38D8D7CD33933B8DEEEF52D766C7ECDBA9BF595CAFC717239A99F7158A4CBABA9E25834B6E4BCF551E0BAABF63D6C5A7779157D5C7509F4164DD7373DE98429EBADBEA2D572A8A1AD66E5440EDD722725EC54EE5422D598EEBE975F8757BC629EB0D606327D994D52E6E5296A1517AD2272FD846CDB9B447796E69A6A2EA6B46533FD2E2FE742C4FFB40222D4D9F2D4779B273F02B7A1656D1D7535545493ABE091B2B5AE85D8556AE533C0ECEAED4577D54FA67D75BD635A747237A389FC5171CF29DC5B7E9B39B9B14DF578F2C6DCB113BA30864FA792D5FE6951FBA77DC3C96AFF34A8FDD3BEE29B3A5CF4F57C81F6F24ABFCD67FDD3BEE1E4957F9ACFF00BA77DC3639ABEAF883E8FA7A88DB9929E66A76B98E4F8A1F14767B3DA0DE27B4BD926D9AD7FC9DACEDEF72FCD4EE5A77A7739387BD108C9EE095D4F5104CC5547472B5E8A9DCB9FB0989DA58F3523263B527CE1D1D5543F25EA6B9D12261B14EE567EAB97793DCA72C9AED7E344D61D3B795452C7267B578A7D884285A369534979C982969EFB3000219C00000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE500000000000000000000000000000000000080005920000000AA1E8B1F456B58A2A54A3BD4D8731311CEE4CEF2762F7F795C031E5C55CB1B4B7345AECBA3BF3E39FD16F576AAD332488B53D1CEEE48E743BDEF53A13592C35F44CA9968E08E191A8E47AFCDF05F615269AB6FCAB7BA5A6C658AE473FB9A9CC9DED52E694F6FA7B6C0A89D2F9CE44FC94E4685F0456F14A4CEF2F4FA6E2339B4F9353A9A56623B74EF2F9DDB6750CAC74B68AB54EB48E5F39BEA472724F6901BA5AEB2D550B0D740E8DC9C979A2A76A293ED93C756E8EA279679168DA9B8C8D578679AAA7FBEB3BCDB8D9F533EAEDB2235EF89CADC3B9AE3EB34B57364C569ACF58861C9C3B4DADC35CB8E3C3B5BB47AA25B26A5E92E557549F4638D1A8BEBE3F61C3D7D56955AA2AD5AECB23546278271F7E4B3F4FD95BA6ED754C8DCB3B95CE7B7098554C7042A2AEB65C96592A2A68EA5AB2395EB98D79AAE54BE1BD6F966FBF46BF10D364D36871E9F6EBBEF2E6032A8E6B951ED56AA75298375E776D96BECB2A52A34FD452393290BD5BE0BC7EF2B4BA53AD25CEAE05FA92B913DA4CB6472B9B71AD853E8BA34763BD14E3ED0E9FC97534FFF00E54E93DAABF71A98BDDCF68F577B591E370DC593FB7A23200371E7C0000000000000000000000000000000115001E49F54800000000000000000000000000007DA878D7D237A9D33117FCC87C4FA533FA3A9824C7D0918EF63917EC08B7D994BF6C0F576BCAA6AF26431227B1549B6CE7FF292E3EAA9F8290BDB1468DD7123D39494D13BDCA9F6135D9C7FE525C7D553F0532D7EDCBCFEABFD8E2F9D51ED84DDA9686E1574352F464956C63A2739708AAD45F37D6A8B9F02F4CA769F91ADF4F3D64D4F4F4713E5A8911118C67355EE2C28748ED05226EED554B13A9AB5DC93DA296DA36D95E29A0C59337893922B33E52BD6491B1B1CF7B911AD4CAAAAF043F3F5EA2875B6D4960A273BC9267231D2C69CD8C6F9CE4FF7D67DAE5A3B5DCB472255BEA2AA1C79D0A566F6F78678FA8DAD8D5CE86DB7BA8B6D6D2AC771A95DC64F2734DDFF0094A8A9C3EDF61333CD310C5A6D357498B266C578BDB6DBA797E2B4AC1A46CD628D128A8A3E93AE591379EABFACA4811AD44C235113D4641936D9E7F265BE49DEF3BCB184EC4184EC432031B184EC4184EC43200C613B10613B10C803CAB1AEE0AD6AA77A114D4FA0ACB7E85CAFA665354F36CF0351AE45EF4E4BE24B4113113DD97166C98A79A93B4BF2DEAAD3D5BA66E7E495ED4563F8C5337E8C89F62F71C593E8397B1327E93DA5D823BF697A98D199A981AB3C0E4E68E6F578A653C4FCD8EE2D7276A60C36AED2F69C375BED78666DF6A3BA7BB57F3A4D3CFEB75B98AA40C9E6D7711DC6CD4D9E30DBD88BEDFF00420645FBB370EFF6D5FD7EA000AB7400000000000000000000000000003064C0120B57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6BE3BF796A3F3DBEA000CAE50000000000000000000000000000000000000002C00000000001F482274F3C7146997BDC8D44F5952B1369DA1636CA6D8E8E19EE52A265C9D1C6AA9D5D6A43B565C9D78BFCF33155EDDEE8E344EB44E09ED2C7D412B34D68A4A68977667B12262A73DE5E6BE0995207A06D6B71D4502B93E669FE75FE1CBDE68E3B44CDB34FE8F4DACC3315C3C3A9DE7ACFEA9DCCE4D27A11ADCA24E91E329D6F77595452D4CB4B591D540F564EC72391C9DA4DB6AF74496B21B6C6ECA429BEF44FCA5E5EECFB481A1934B49E49B5BCDA9C673FF00AF18B1CED18FA47CD65D2ED2A9FC9A34A8A2996A31E76EAA6157B8F69B4AA4FAF6F9BC1C8A56461C9927D9317A2238EEB3688E6FDA16FC17ED357F448AA5226C8BC9B3B3757C17B4E45FF67CC7C6E9AC92F7A42F5CB7C14AD53872243A7356D7D96446A3967A5EB85EBC113BBB0C7E05F1F5C53FA33D78A60D57B9ACA47E68EEEBECE20A8A1D552D354C4F8A5485779AE4C2F343E7B564FF008962E3CE99BFCCE2C5B3D4DB6F71C572A6463E66A6EE7939B9E6D52BADAB393F096344C2E29DBFCCE2986FCF9F798EBB3775DA5AE9B86F2D6DCD133BC4A16003A0F22000000000000000000000000000000008A800F24FAA4000000000000000000000000000030A64013CDA7E6B6834CDD5BC52A6912355FF00AD31F79AD69A9D676CB33ED9436FAB4A37EF6F316937B3BDCF8F89B14C897ED924D0A7FE2ACB51D22679F46BC797A957D86FD06D6AB696869E07DAE199F1C68C5916654572A26338C193A6FBCCB8B1E2462F0A948B72CCC6D3FF0071FB23D60A7D57A7EADD536DB3D5367737737E4A5DF544EEEC242BAAB68B95FE8753FC127DC7DD36C75A8A9FD4F022F674EBF719FC7257AF1F91E0FDF2FDC4ED5F553263D565B735F05667E6D776AADA2F0FE8753CFF00324FB88EDC29354D75E52EB35A2AD2B9AF6BFA48E9B772E6E30B84EBE084A976C75EAA9FD4D073FEF97EE0BB63AFE3FD4F073FEFD7EE1EEFA94C7AAC73BD30563F56AFE156D1BF33AAFE093EE33F853B465FFD1D57F049F71B3F8E2AC44E367833FE3AFDC6536C757FA1E0FDFAFDC3DDF563F66CFF00F1EBFB357F0A368DF9A557F0483F0A368DF9A557F0486D7E392AFF0043C1FBF5FB87E392AFF43C1FBF5FB87BBEA7B367FF008F5FD9ABF851B46FCD2ABF8241F851B46FCD2ABF82436BF1C957FA1E0FDFAFDC3F1C957FA1E0FDFAFDC3DDF53D9B3FFC7AFECD5FC28DA37E6955FC120FC28DA37E6955FC121B5F8E4ABFD0F07EFD7EE1F8E4ABFD0F07EFD7EE1EEFA9ECD9FF00E3D7F66AFE146D1BF34AAFE0907E146D1BF34AAFE090DAFC7255FE8783F7EBF718FC7256FE8883F7CBF70E9EA7B367FF008F5FD9A926A7DA33915AB4753854E3FD09086525A6AD75050D05652CF4F3544ECF32566EAE15DC571D9C3DC4F936C95B9F4441FBE5FB8F8E8FB83B54EBEA8D457089B0D3DBE9FA456A3B28C544546A7BDCBE0368F566C739B4F4BDAD8A2B1B7979CF9381B56AB4AAD735AD6AE590323853C1B95F7A9123EF70AB7DC2E3575B2AAEFD4CAE9573D48ABC0F818E6779DDD6D363F0F0D69E9000086500000000000000000000000000000C19300482D5E8F87C7E26D9A96AF47C3E3F136CF5183E1D7E50F9AF8EFDE5A8FCF6FA80032B94000000000000000000000000000000000000000B00000000012FD9A5B52BAFCB3BD33152B77D7F5BABED2225B9A3E99BA7F46BEB2A3849235677F7A7D5F763DA6AEAAFCB4DA3BCBABC1B4F1975117B7D9AF5945F6A1745AABCB68D8B98E99BE0AABCC92ECF28E3B5E9892E350DC3A66AC8ABD7BA9CBDDC4ADE9229EF97C6B132B2544B973B9E11578AF827C0B1768B5CCB669F8ADB4AA8C599123444E68C435F2D76AD30C7EAEA68F2F364CDC432768ECAC6EB58FAFB8D45548AAAE95EAEF51AC8A39837E3A4443CCDED37B4DA7BCBD000954306401D5D3D7EABB1D4BA5A554735C98746EE4BFEA6B5DEE53DD6B9F5554A8AF77244E4D4EC434C15E4AF3736DD59673649C718B9BDD8F27900191840000000000000000000000000000000115001E41F5480000000000000000000000000000000259B2FBAC741A93C8EB38D15C58B4D2B579657822AFB71E270F525AE5B1DF6B2DF322AF42FF31DF94C5E2D5F61CD5CA2A2A2AA2A7254EA2C5BF3135A68E86F50222DDED8DE8AB1889E7491FE5227BFDBD85BBC6CD1CBBE0CF197FF005B749F9F94FF008482AE9E24D87365E8A3E956919E7EE2678B9133929CC96E4772A6AED87D4454F222CB4B036195BD6D76F27B95389512136F263E17CDFEAF37F74B2002AEA8000000000000000058BB0F8A3935157B64635E9E4C8EC39329F490AE8B1361B2322D457292472358DA3455555E089BDC549A7768714998D2DF64675F2359AD2F0D6B5111B3E11113098C275120AACE97D99474DC1B72BF3B7E444E0E6C489CBD9C3FF729E6DB6EA6D59B40BADC5DE848245A89A57A61AAD444C357D7BAABEA381AD2FCED457D9AB1379B4ADF9BA762F0DD8D392E3A9578A9333B4CCB5EBBE6F0F079562267E7E51FE5C2001475C0004000000000000000000000000000000003BF6AF47C3E3F136CD4B57A3E1F1F89B67A8C1F0EBF287CD5C77EF2D47E7B7D400195C90000000000000000000000000000000000000196B55CB86A2AAF62264CB1AAF7B58D4CB9CB84253B4BC827743B38AE9988B55590C2BD8D6ABFEE3AF1ECEADB1373575D3B913B15AC4F81AD6D5E38F37571704D664EBCBB47E32AB816CB74BE94819F3B246FFD79F39F78F93F44B39F92F8C8EFBCAFB6567B44B63FA0E48FB592B1FAAB9D376E75D2F34D4C9F41CECBF8670DEB5279B53B8A52D053DB61546EFE1CE6B7A9A9C13FDF71D8B63F4ADBA7596DF352C52AA6EEF23B2B83DDCA9F4D5D67E9AB24A79A54444CACB8E1ED35AF9F9F245A6B3B43A98387F81A4BE1A64AF3DBCF7F245B6516BDEABA8B8CA986C69D1C7EBEB5F670381AF6E9F29EA19FA3766183E699D9C39A96B5B1B69A3A1F24A09E28E2E3F464455CAF5E72466A367543222F93574E8E55CAEFE1FF007134CF5F16725FF45753C3737B1534DA7989F39EAAB0137AED9D5CA1CAD2CD0D42272CF98ABF123770B15D2DEDDEAAA299ACEA722653DC6ED72D2D1D25E733683538637C9497300EE54C283234DE800480000F2002C0000000000000000000000000000000022A003C83EA8000000000000000000000000000000000ED692BFCFA76F11D5C397C2E4DC9E1EA919D7E29CCE2810AE4C75C959A5BB4A71AC6D4B6CA49AF1A72557E9DBBB375EC6F28D55728D54EAE3C97AB910545251A33543AC6E9E92B61F2CB355652A299533CF9B93BFB53AFD66C6ACD2294B49F2C69F93CBAC7226F2398997C3DCEEE4EDE69D65A7AB4B0E49D3DBC1CBE7DA7D7E7F8FD51107969E88744000480000000000007574CD35D2E35925AACF9DEAE674736170891A2E55557A93B7D878D3F64AFBF5C19496D855EE55F3E45E0C8D3B5CBD44C6ED78B7E8DA096C9A6A549AE9279B5B7044CAB57ADADEACFB93D64C7AB47559FAF838E37B4FEDF8CB5F5A5C68EC9676E93B0C88E631735F50DE0B2BFADBF7F821040AAAAAAAAAAAABC5557AC1599DD974F8630D36EF3E73EB2000360000000000000000000000000000000000001DFB57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6AE3BF796A3F3DBEA000CAE48000000000000000000000000000064C1D0B25AAA6F35CDA5A36E5EBC5CE5E4D6F5AA916B45637964C78AF96D14A46F32D4A6A79AAA66454F1BA491CB846B533927564D9E4D32364BACDD0B57FE5B78BBDA48E286CFA26D8D7CBE754BBEB632F91DDC9D49EE20B7FD6572BB6FC71C8EA5A65E4C8D70ABEB5E669F899337C3E91EAEF7B269387D62757EF5FFB63FCA6EEA9D33A61158CE85274E0A8D4DF7F8F6156DCEA23A8B954555347D147249BEC6A751A88864CF8B07873BCCEF2E76B388CEA62295AC56B1DB67726D5D7B9A1489F5AF4444C65A9BAABE27267AEABA8E3354CAFF5BD4F8221932463A57B4356FA8CD93ED5A65E40305B661DE59000D8DE59472A72554F529B305C6B29F1D0D54ECC7E4BD4D403963CD6ADEF5EB59949A835ADE6937512A3A5627D591339F1E649EDBB4785ED6B6E74CAC775BE3E29EC2B23260BE9B1DFC9D0C1C5F57827A5F7F9F55BCB43A6754C2AEA6585B3AA6731F98F4F5B48A5FF0041D75035F2D0392AE24E3BA9C1FEC21B13DD1C8D9237398F6F16B9AB8545269A6F5DD651B9B0DD57CAA9F96FE3CF6F8F598BC2CB8BE1CEF1E92DEAEB347AEF77534E4B7F747F984338A2AA39151C9C1517A816D5FEC16ED554495D6C7C5E538CA48DE4FEE7779555653CD4750F82A58AC958B87357A94CD8734648F4973F5FC3F268E627BD67B4C3E20C193339EF2002C0000000000000000000000000000000022A003C83EA8000000000000000000000000000000000000614EDE96D4B70D3952AFA2911F0BD7E769E4E31C89DE9D4BDE9EF38A60989D95C98EB92B34BC6F12B0DF66D3FAD58B3E9C9E2B4DE1C9E7D04FC237AF5EEE3B7BBD88436F565B8D96758AE7492C0BD4F54CB1DDE8E4E0A73D1551C8E6AAA3938A2A2E153BD17A949759F5F5DE8A04A4B824375A0C6162AB6EF3B1D9BDF7A293BC4F769C62D460E98A79ABE93DFF49FE51045C99276AED077B4CCACABB04EEE2AADCBA3DEF7A7B907E2F5954DDFB26A2B6D73179239DB8BEEC93C933D978D7E3AF4C9135F9C7F9EC82026B26CC75335331D3D34A9DADA84FB707C9366BAA57FF431277AD4331F1239656F6FD37F7C7FDA1E09D45B34BAB1BBF5F5F6DA38FAD5F36F63DD8F7994B0E8CB53B376BF4B719539C144D4C2AF670CFC49E59F356788619E94DED3F846E83451BE591B1C4C7C923D70D63132AABEA26B6BD06B0D3F97EADAC65A681A9BC8C5722CCFEEC757BD7B8FACBAF696D71BE1D2566A7A16AA63A79911F22FFBEF5521973B8D6DDAA9D5171A996A265EB7AF044EC44E4883DD5667519FA7D88FFB9FE23F74AEFBACA265B56D1A4E97E4DB5E30F97FE6CDDB95E69EDCFA8861E51307A2932D8C382986BB523F99600043280025600000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF5183E1D7E50F9AB8EFDE5A8FCF6FA80032B92000000000000000000000000120D1FA7D6FF005CF8DD32450C288E7AE32E5CF5211F3668AB6A68645928E77C322A63798B829939A6BB57BB369ED8E9922D9637AC792D6752E95D36DCCEDA7E99A9C77FE724FB4FA52EB4D3CC7E237244ABD69163E053F23DD2395D2395CF5E6E5EB3C9AFEC713F6A665D98E3D7C73FE8E3AD63E4B8AFBA7EDBAA99E554D53F3FBBBAD918EDE6A772A15EDDB49DDADB22A3E95F347D52429BCDC7D8722DF5F556F9D26A399F149DAD5E7EB26F6DDA44B1B11971A44957ADF1BB0ABE0A56299B0FD8EB0BDF51A0E213BE78E4BFAC7641DB4B52E7A3129E6572AE1137172AA496C3A1EE3707A3AADAB494DF595DF497BB04A1DB43B5747BC94753BFF93BAD4FB4E05E75FD6D5C6B1D04494AD5E1BD9DE77FA133933DFA56BB295D2F0DD3CF3DF273FE1094250696D36C449920595BD722EFBD54F2BAA34B54B7724647BBFF00541C0A9E59649A474933DD23DDCDCE5CA9E10B7B26FD6D699944F1C9A74C38EB15F92D8ABD2DA7AFD0F4B6D7C513978EFC18C78B79107BC690BB5B65545A774F0F54B12653C53A8E35256D4D04C92D1CCE8654FACD526F69DA44F1C691DCA95B32E31BF1AE157C0AC53362EB5EB09F1B41ADF8D5F0EDEB1D9075A4A8E93A3E825DFE5BA8C5CE491D8744DCEE32B5D551BA929FADCFE0E5EE44257F8C4B5247BCB4751BFF0093BADFBCE15DF6895752C732DD036991786FAAEF3B1F613E267BF4AD76234BC3B04F3E4C9CFF008424EDB6697D371A36A920E9719574D87397BF1F71E3F0AF4BCB1A325466EFFD54FC3E054D34D2CF2BA49A4748F771573972AABEB3C389F64DFADED33289E3B349E5C38EB15F92DAAAD37A72FECDFB6BE38A444FA54EA889E2DE441EF3A3EED6D7F9B02D4C5D524499F6A751C2A3AAA8A2A86CD4933A291BD6D5C139B5ED1AA216232E14AD9D7ADEC5C2AF811C997175ACF341ED1A1D6FC68F0EDEB1D908F23A8E9773A1951DD8AC5424363D1772B948D5A889D4B065155F2271C762212C4DA1DA5D1E5D4751BFF92AC6FDE71AEBB45AAA8639B6DA76D3B57948E76F2FB303C4CF7E95AEC9AE9387609E7BE5E6FC2212DA082CBA3E95D1AD5246E7E15EAF7E55EA9D78EAF035AA35669AA97AB6A3122F2557C394F815255544B5333A5A891D24AEE2E73972AAA7C488D1C77B4F55B271FB563C3C38E22BE92B764D3DA6B5042AB6E74314C9C51D02A22A7ADA56FA92D12D92E4B4B339AFCB51ED73792A2AAA7D8685354CD4B2A4B4F23A395BC9CD5C2A18A99E5A999D2CEF74923B9B9CB95532E2C56C73F6B7868EB35B83538E27C3E5BFAC767CC00677300000000000000000000000000000000115001E49F5480000000000000000000000000000000000000C003200212185C271C267A97AD0C804ED3DDF48AB2AE36EEC75752C4EC6CCE44F89F575C2B9CDC2D755AA75A2CCE545F79AB83284EEAF875F41EAB22E65739EBDAE72AFC42222270320895A221E4C80000000001200090000000000000000000000000000000000001DFB57A3E1F1F89B66A5ABD1F0F8FC4DB3D460F875F943E6AE3BF796A3F3DBEA000CAE4800000000000000000000000064DDB6DAAB6E7D279053BE758F1BC8DEACE7EE3E75F41536FA8582B617432A26775DD8579E37E5DFAAF38B2453C49AFBBEBE4D5001650000197183AF1E9DBBCB4EDA88E825753B9BBED9131C5BCF2724AC5EB6ED2C97C3929B73D6637650C9843AD6DD3B77B8D3A4F4B412BA25FA2E5C3729DA99C649B5E2B1BCC98F0E4CB3CB8EB33F27254C60E85DACD70B56EADC69A4811CB86AAAA2A2F8A2A9CF4E02B3168DE117A5B1CF2DE36914C19530595650F4793AD53A76EF4D4CEA89A865642D4DE572E38276F322D78AF795A98AF9379A5667672000140C9800003AD169CBBCB4EDA88E825753B9BBED9131C5BDA56D78AF7964A62C9937E4ACCEDE8E51930096260004A40000000000000000000000000000000115001E49F54800000000000000000000000000000185036AD9433DCEE34D454AD474F3BD23622F6A9743F4DE8FD196D864BE3595133FCD49266AC8E7AF5EEB392271F81586CF2B22A0D676AA8A876EC4D955AAABD5BCD56A7BDC5A5B5CD2B72D40943536A6A4EB4E8E6BA2DF46AAEF2A2E533C3ABB7B0C958DA3770B8966B7B4530DEDCB49EF30F355A4B4AEAEB33EAB4F24704A996B65851588D7A753D9C3B53AB257BA0B4749A86FF53495AAE869E8B854A27D2DECAA6E278A2F1EE2D0D9369BAFD3F67AB6DD11239EA25DEE851E8EDC6A261155538657BB3C3079D13554B0EB3D59429B8C9DD5093353ADC98E3EF5F796DB78DDA11ADC9863363C569B4476969D737679A7EBD2D7574B4A950DC6FF004913A5DDCA7D6771C29C0DA5E85A2A2B5FCB5624DDA76E166898BBCD56AAE11EDF154CA72C2E7860D6D61B3DBF55EA8AC9E8216D4D3554CE95B2ACAD4DD472E551D95CF0CE3867860B1AF141F27ECD2AEDF23925753DB1D1B97A955B1F34F14276E9B4A273469FC2C98B24DA67BC6FBABED9A684A4B8DBD2F17CF3A9D573143BDBA8A89CDCE5ECCA7B892DB23D9FDFEB1D6CA2A3A474D85C6EC4E8D5E9D6AD77055FF7D477FE467D468186D146F48DF251C70EFBB8E115111CABE1922745B30B22E528AF957E5B1F37C5333CD5EBE08994F69131B76567575CF6BDF2E49ACEFD36ED1F8CABEDA069A4D337C5A68A47C94B2B7A485EEC671C9517BD17E2871EC3047537DB6C33377A392A63639BD4A8AE445453775969FACD397875256B925DE4DF8E744E12A2AF3F5E79A1A9A6FF00B4B68FDB22FE7429E6F498ED33A5DF9B9BA775A3B55D2D67B46974A9B7514704EB3359BCD55CE1517B54E26CEB67A97BA76DCAF0E923A157622898BBAE971C15557A933E2BDDD735DB5FF6359FB4C7F071D8D46AFD3FA02A9287E69D4F4BD146A9F55708D47782AE4B4C46EF398F5D9ABA6AD2B6F7AD698DFF000E8E43AD7B3FA49FE4E99B6D64EDF3375F2F9CD5EC572AF05F1227B44D9DC16BB7C973B12BFC9E2F3A5A772EF2B5BF94D5E784EBC9583955CAAAAB955E7DE48A4D6D7E75A62B6A572B69591742A88C4DE73718C2AAA67970226636DA61D5A6835382F5BE3CBBFAEEB0B65FA52CB78D27155DC68239A7591EDDE555CE11787594FD6B1ADAC99AD4C35AF7227AB25F9B18E3A162FF001A4F89425C13FA7D47F88EFE6522D1D224E1D92F7D5668B4EFB4FF002B37641A6ED37BB657CB73A38EA1F1CC8C6ABB3C1319211AE28E0A1D5972A4A48922822930C6A2F044C21676C13D0F74FDA13F950AE3693C35CDDFFC6FB106DEEC234B92F3AFC94999DA23F84700055DC00000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9AB8EFDE5A8FCF6FA80032B920000037AC75CB6DBCD1D52265237A2B93B5ABC17DCA5A5B47A08EAB4ABEA226377A07B256AB53AB92FB973E060C99BC3BC5663BBA7A4E1FED583265ADBAD7C94F82D1D95D0363B4D555CCD45E9A4DDCBB8E5AD4EFEF55399B58A0486BE8AAA34444918B1AE3A95AB94FE62B1A989C9E1B2DB845EBA38D56FFA2020BAAC71C162D150C93469F334FD33D1C9C55CA9BCA9ED5C113D9F69E8AF12D45DAE8DE998B22A318E4F35EEEB72A75A71E5CB9911AA8DAD331D2192DC12F16C78EB6DED68DFE5081A31EE6AB9AD556B7E92A2706A76A9E50B86E1AD2CF6AAF7D0F412BBA25DC7AC4C4DC62F5A734E5D7833A9B4ED05FED0EADA16312A959D2C534698E93AF75DDB9E5C7914F6B98DB9ABB44B2DB8145A2D1832C5AD5EF0A74F4D6B9D9DD6AAE1155709C910B4F64B1B24B0D52BDAD77F497734CFD461BD2DE2C3A6EB27A573F153348E9665646AE54572E7CE5EECFB09B6AE62D34AD779571F04ACE1A66C9962B13EBFFEB81B1F5F9EBAFEAC7F171C8DA8AFFC56FF00F099F6926D9DD67CA3A82FD54888D64AAC73513879B9763DC7CF50E9B9EFFAD5EEC2C7451C6C49264EDE786F7FC33EDC3178AE79B5FA746F5B4D6CDC3298B0F5F7BFCCAB005C7A8EF16DD2F6E6D252C50BAA91BF350639762BBAF9F8AFBC8169CB14DAB6AABA69AB12196356AB9563DEDEDECF7A631836A9A8E6AF3DA36872753C2FC2C95C18EDCD927CBD3F5464162FE2CA4FD28CFDC7FF00D1CDD43A1DF66B44F5EB5E93245BBE6245BAAB972273CF793ED38A6768952FC1F598EB37B53A475EF0B0ACBFD8AA3FD85BFC88413416A3B5DA2D33C37255E95D3ABD311EF70DD6A7D84EACABFF000551FEC2DFE4423BB298209AC555D2451BB76A5C89BCD45C26EB4E7D6622B6DFD5EA7356F6CD8231CC44F2CF7EBE8835DE782EDAA24922CAD3544CD44CA6155382722DED4B5EB62D3D355D2C2C73A246B58C5E0D4CAA2272EAEE21F4178A3B2EB5BBC53C123FCA266471F46D4546AF7E553B509CDFAE505A6D72D65546F9216632D6222AAE571C9553B49CF69B4D6BB7462E198AB4C79EFCF116999DFA76DB7531A8F50D55FE581F56D8DBD1355A8D622E32ABC578AAF77B0E4265CE46B532ABC93AD549356AC3ABB5840DA06BE2867C22AAA615A8D4E2BC17B13813DB957DA345D143143499924CEEB1A89BCFC632E72A9B7E3785B52B5EBE8E25787DB596BE7CB97DD8FF00DBD7F4538F4731CAD7B55AE4EA54C28452DFB2DFADBABE3968AAE85AD95ADDE58A4C3DAA9CB28BDBCBB17895CEB1B2FC897C969D8AAB03DA9244ABCF757ABC1514C98B51CF6E4B46D2C1ADE19E0628CF8AFCF49F3ECE3977EADFEC857FF81F6147A17FD7B29E5B3CADAE544A5E8F32E796EA2657260D6CED6A4BA3FF008F579F1E7AFAC7F2A011AE56B9C8D556B79AA27043C97258356D9EBAB9B6EA589F4EBF463DE62358EF5617811DDA85860A564572A385B12B9FB93358984555E28EC7B7DA5E9AA99BF25ABB353370788C13A8C3922D11DD5E9F4E8A4E8FA458DE8CFCADD5C7B7916168BABD376AB52544D5113AE1BBBF22BD8AAE6AE3E8B729F0EB3A769D72CB95C9B4B0DAA7742AE46F48C5DE56E579B91138278936D45A26796BD20C3C270DEB59C99A226DDA2237FF00B54C5EB65FEC551FEC2DFE44227B4DB0524148CB95344D8A457A32646261AE45CE171DB9E1E24AECD84D1547CFFF0002DFE4435B519632D2B6875B8568ADA2CF9715A77F75461E991BDF9E8D8E7639EEA6495E824B1433CD517B9A2599AA8D8A2918AAD4EBDE5CA633D9D9825157AFA8E3AEF24B6D03EAD8C76EAB99C33FAA888B936AD9AD13B56BBECE2E9F8762C98E32E5CB11BF977955460B9B54D9A9AF9627D5793AC356D87A68D55BB923571F45DF035B65D1B1DA71CAE6B557A777154CF5214F6C8E49B6DD9B3FD06D1A88C336E931BC4EDFE151E1CBC1A995EA4EB55EC430B945547261C9CD3B0B62A2FDA7B4DDDAA69DB03DF52F955F3CAC622AA2B955DCFB133D474F5A5AE96EFA72A6658DAB2471ACB148DE7844CE33D8B823DAE62637AF4947F43ADA979C79626D5EF0A50F4D6B9D9DD6AAE132B84E484E3675A660B8A495F708FA48A37EEC71AFD1739138AAF6E3284AEEFABACF64ABF2148A47BE3C239208D1519DDCD3DC5EFAADADC948DE58B4FC222D8633E7C91489ECA73031DE5B1A9A8EC17DB3A55A54D2D34F237A48A773918AE5EA4777110D05A763BD5CA5756377A929B0AE445FA6EEA4F5732D5D4C4D66D31B6CC59B84E4A67AE1C768B7376945DB1BDF948DAAF544CE113A8F05BB7BD5D6DD3B55F27D2D1748F89137DAC446B19D78E5CF1DC6C4715A35B595D3A41BAFE2C47AB51248DDEBECE463F6B98DA6D5E8DBFE874BDAD8F1E589BC796DFE54D983ED594EFA4AC9E9A54C490BD58EF5A29F1373BF5702D59ACED20002A000000008A800F24FAA400000000000000000000000000000001B36DA292E15F4F4703A36CB33D236AC8EDD6E5782657D782CBB97E1DE90B440E4AC4ABA654566236F4AB172C6555B9F6E53815631CE639AE6395AF6AA2A39382A2A75A16659F6B55D4B44C82E56F8EB646A63A56CBD12B93BFCD5E25AB31E72E6EBF166BCD671D22F11DE27FF00B4D765EDBABAD75B75D4324AB5154E4DCE993755236A705DDC26EA655DD5DFD656D414373D59ACEE971B055454F347374AD91F22B17755551B8C22AAF04E29DE7AD59B49B95F28DD474B0328291FC246B5EAF73DBF92AEE1C3C08AD86F35B60B9C75D6E911B33515AA8E4CB5ED5EA54ECE05F9A22366AE9B459AB1932CC445ADD223CA13CBE5E75F5BEBBE4674D34B2B9C8D64F153B7E7117B177797BD09AEAC992C1B319E9AAE6E92A56952955D9CABE47261CBED5555F122ADDB34BD1A23EC91BA4FCA4A9544F66EFDA41B576ACB8EA99D8EAE56B208D731C11F06B7BFBD7BFD98226D11DA5829C3F3E7BD2B931C5223ACEDB755D50CD35F3661BD6C72AD5CD43B8D46AF1DF46E1CDCF6E5150ABB66D65BCB359D13D292AA9A381EAB3BA462B111B85CA2E7B7960D2D19ADAE1A5F7E281AD9E8E476F3A07AAA222F5AB57A95496546D8AA16354A5B3C5148BC9CFA857A7B11A9F12DCF129F63D569A3262C548B56DE6DADB4C1F29DD74FDB69918EAF9164C22BB1C155A888BEBC2FB08737485DB4FDE6CB51728A3646FAE8636E1E8B95DECF57A8E5B351D63F53C37BAD72D454C72A49BB9DD4C27D54EC4243A9B6892DF56DAAEB7320F23AA654A625DEDFDDCF9BCB8732B368DF796CE3D3EAB4F4AE0A444D769DE7E69F6DB3868C8FF698FE0A75AD7241AC342358E7E3CAA99617AA7D493185E1DCA992A8D69B419753DA1281F6E653A248D937D25DEE5DD84385A5F54DD34DCCE75BA66F46F545921913798FF0FB899B44CB4E9C2B34E9A2BDAF13BC3E957A2F50D35C92896D55524AAB847C6C5746BDFBFCB1EB542C5BA682B1DAF447945DA356575341BD24D048A8AE7AF1DD4EA5E2B84CA761A71ED8E548D3A4B2C6E913ADB51BA9ECDD5217ABB595CF53AB1957D1C548C76F369E34F373DAB9E6A47BB0D9E4D7EA2D4AE48E488EF313DD676C42BA39B4C4F468E6F4D4F33955B9E3BAEE28BEDDE4F02BCD5BA26F3417CAB482DF53534B2C8E7C32411ABD15157288B8E4BD5C71C8E0586F55D62AF6D5DB65E8E544DD722A65AF6F62A7616353ED8E7489A953668A495138B9950AD45F056AFC47344C6D28B69F55A5D45B2E9E39A2C956C974FD5E9FD3F3FCA2C58AA2A65593A35545DC6A222222F7F055F1294D5F5CDB9EA7B9D646A8B14B3B958A8B9CB51708BE2888A493546D2AEB79A57D2D346CA0A67A61FD1BB79EE4EB4DE5E48BDC840C8B5A3688867E1DA4CB4CB7D467FB56F2640055D900000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000171E8DA88EF9A35B4B33B7B76375349DB8C613FF8AA14E128D0FA9A3D3B254A54C52CB0CDBB848F0AA8E4CF6E3ABE06B6AB1CDE9EEF7875F836AEBA6CFB649F76D1B4A6775CE9DD9C369D331D43A148F08B8547BD7CEC75F5B94D8BC52FE13699B6CC89973A486454C752AA35DEE55F610BD6FAAE2D410D2C54B14B1471B9CE7A4889C57184C617D7ED37B496B6A6B3D962A2AC82A247C6AEC3A344C61573D6A9DAA6AF8178A45F6EBBBB71C4F4D7CF6C336FF4B96223E70EDED52E294D638A89AEC3AA9F877EAB70BF1DD36B6613324D2D1C6C5CAC723DAEF5E73F0542B9D637D4BF5D52A236BD903188C635D8CA76F2FF007C8F3A5F5154E9FAB7490B52585FC2485CB8476392E7A94C9ECD6F07963BF76A7F57C71C4A734CFB9B72FE8F86A7A6969350DC239D8AD72CCF7A653E922B95517D8A5C3A4A1928B4B5147548B1BDB0EF391C98DDEBC2F6703851ED06CD335AFA8A6A86C8DE288B1A3B1EA5C91FD55AE9F74A27D15BA17D3C12262491EA9BCE45E6984E09ED52B6AE4CD1159AEDB33E0C9A3E1F6C99E9979B9BB424DB2D9124B3D7C8D4546BEADEE4CA617E8B4AD75348B36A2B9BDDCFCA246F823951090E8AD594BA7EDD3D35553CF23E49964CC7BB8445444C715EE22972A86D5DCAB2A58D735B34CF9511DCD115CAB8532E1C76AE6B4CB9FAFD5E3CBA2C54A4F58EF09E6C753FA4DCFF00563F8B898DDB51D05AAE1494750F5E96A1C89C3EA22F255EECE3FDA159688D474DA79F58EA98A593A746A37A3C70C6739CAF79A5ABEF10DEEF4EACA7648C62C6D6EEBD133C33D9EB31DF4F39334EFD9B9A6E2F4D270FA56931CF13DBF54D3699A716A62F95A8D999634F9F44E6E6FE57AD3E1EA2B6A5ACA9A4DEF25A89A1DEFA5D1C8ADCE396704FAC1B40829ED51535CA9EA67958DDC57B11151C9D59CAA71209767D24B5F2C96F6C8CA67AEF35922222B73D5C15781974F17AC78778ECD0E2D7C196D5D569EDD67BC79C4BEDF2BDCB8FF58D6FF10FFBCF94D70ADA889D1545655491BB196BE6739171DCAA6A21E9BD66CF2D63C9C9F1B24F49B4AF1B327FC1547FB0B7F910E36C8D3FA8AB3F6A77F2B0E5506BBA1A7B0C16F75354AC91D3242AE4DDC2AA371DA73F43EACA3B0DB27A6AA86A1F23E65951636A2A222B5A9D6A9D873270DF96D1B79BD95788E9BC7C36E78DA2B313FB34B50FF6F65FDB19F61606D23FB1F55FAD1FF3A1575D2E50D5EA675C636C9D03A76CB8544DEC263298CF3E04A3566B5A0BC58E6A1A7A7AA64AF562A2BDADC70722F538CD7C5799A74ECE7E9F5986B8F5516B6DCDBEDF8F77336673321D55123F199237B5BEBE7F61616AEBD45656C12D4DBBCAA27AAA6FF0C317861173DBF614B413494F5114D0B959246EDE6B939A2963DB76894D25224577A47ABF1873A344735DDF85F871275386D378C911BA384710C74D3DB4F7BF2DB7DE276DE1B169D62CADA87A5B2C2F9256B72EE895A9C3D7822DAFEE53DCAB699F536FA8A27C6D73712A7D2E29CB87124EFD7B65A389CDB75148AF54CEEB6346267BD7FD14AFEFD77A9BD5C1F5556E4E3C18C4E4C6F6211831CF3F372ED0713D5D674DE178BCF33E91110E7A17B6A2824A9D3159140D57C8EA75DD6A75F9BC8A250B366DA3D1B6955B4D4D3F4CD44DDDF44C78F12FABC76BCD66B1BECC3C0F53830D32D735B6DE3F942F47D2CF57A9681B4E8ECB256C8F544CE1AD5455CF67678962ED4E546699E8DDF4A499A89EB4CAFD86BC3B40B4246B23E9A78A77226F31AC4CAAFAF3F120FAC752CBA86A63548FA2A58F8C6C55F39557EB2E3BB063E5C9972D6D35DB66CF8BA6D0E8B262C7939E6E9EDB34F5A74F587CBABE9A3A89A38D1F2BDEDDFE3D8D45E073E8F5B54DCEB62A1B2DB1B1ABDC88AE72E775BD6E5444E18F5A9F2B06BFA46DB23A5BB4122CAD62315CD6A39AF4C63976F69F2B9EBCA58617C760A148A477395EC46A7B13ED31C62C9369E6AEF3FB36FDB34D4C549C1922958EF111D6521DA871D2927F8ACF89D0B3FF0062A8FF00616FF22108D55ACE82F763928E3A6A9648F56B91CE46EEF05CF6E78F2E47DEDFAEE820B053DBDF4954B2C74C90AB911B8CA371DA57C1BF8711B79B2CF12D2FB55EFCF1B4D76FD5EB679A628AAEDE973AF8D27DF72A471BF8B511170AAA9D6B9F81F6ACD75494150EA4B2DAD1DBAEE8F7B1BA8AA9D8D44CAFB8E368BD60DB2D3BE8EBA37C94EAE57B1ECC658ABCD30BCD3ACEDD5EBBB3C2F74D436F592ADC8B87BA36B3DABCCC96C7926F3CF5E68FD9AB8353A6A69A9E0E48A4C77E9BCA5B13EAE4D3CE7DC11ADAA7D3ABA46B5308D5545E18EEE470F653C74BAE787CF3FEC39147B42A75B6F4374A7A87543D1C8F744898C2E708995EC5434B486B0A3B0DA568EA29EA647F48E7658D4C71F131F81922968DBCDB7FD534939B1DF9FA444FF8EE8AEA37B9DA86E7BCB9C554889FE654FB0B9D7FB1ABFB17FF00A147DD2A1B5773ACA9635CD6CD33E44477344572AF1F693FFC3CA04B22512D3D4EF793F45BD86E33BB8CF3363518ED7AD368ECE570AD6E1C3933DAF6DB9BB7EEEDECC26649A5D91B172E8E57A3BD6AB9F82A15A6ABA59E975157B6A5AE6B9F339ED554FA4D5555454F053EFA5B51D4E9FAA73E26A4B4EFFA712AE33D985EA5276CDA159A68DAB5305431E8B9DD7468B8F795E5BE1C93688DF764F1B4DC43494C3932725A88851E86BBD5504554C4818D91BBC8C7B951E89DE9824FB257B194972A6739AE959322AAB573BC8A98E1DD96AFB4E76A6D7E957472525AA17C69222B1F2BD51151392E113E2442C178AAB257B6A69153B1EC5E4F6F62FDE5FC3CB931CC5A1869A8D1683554B6199988EF2B2752EA9A7B2DD24A6AAB42CAB8CB64554C3D31D59416DD592D450F4F6ED3B52B4EAABC6356F15F51F06EBFB2D5C2D4B951488FC6775CC491117BBFDA1AF72DA1D2C54AE82D14922BB186BA4446B1BD8B84CE78FA8D78C56988AF27EEEB5B5F8E26D97DA2397CA2223741B51543EAAF95751240FA7748EDEE8A44C39BC3AFE3E2734FB544AFA89E49A672BE591DBCF72F5A9F3C1D4AC6D110F179AFE25ED6F59790012C4000000008A800F24FAA4000000000000000000000000000000000005800054000580005800000005400120002150001200094800090000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F4614C9850960C9801564C80580C29930A40C000AA59064043C8009480000000000000003D00025E40010000B0000000000000000AA193201000003C80091E8005800007900048000000022A003C83EA900000000000000000000000000000000000160000000000016000000000004A0000400000000000090000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F400097900040002C00000002A0000000000000000000000003D000240001E4005800000000000000010000A800000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B000000000000000008A800F20FAA400000000000000000000000000000000000580000000000058000000000012800000000000000000000000000000000000000000000000077ED5E8F87C7E26D9A96AF47C3E3F136CF4F83E1D7E50F9A78EFDE5A8FCF6FA80032B920000F40009000079001600000001540000000000000000000000003D000240001E40058000000000000000000055000000000000B00000000000000000FFFD9, '1', '2021-03-13 13:10:28', '1', '2021-03-13 13:10:28', b'0', 0); +INSERT INTO `infra_file` VALUES ('5e8609290e915c4fa8b08e67.jpg', 'jpg', 0xFFD8FFE10DFA4578696600004D4D002A000000080007011200030000000100010000011A00050000000100000062011B0005000000010000006A012800030000000100020000013100020000001F000000720132000200000014000000918769000400000001000000A8000000D4000AFC8000002710000AFC800000271041646F62652050686F746F73686F702032312E30202857696E646F77732900323032303A30343A30322031373A32343A3135000000000003A001000300000001FFFF0000A00200040000000100000320A003000400000001000001C20000000000000006010300030000000100060000011A00050000000100000122011B0005000000010000012A012800030000000100020000020100040000000100000132020200040000000100000CC00000000000000048000000010000004800000001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD9FFED160050686F746F73686F7020332E30003842494D0425000000000010000000000000000000000000000000003842494D043A0000000000D7000000100000000100000000000B7072696E744F7574707574000000050000000050737453626F6F6C0100000000496E7465656E756D00000000496E746500000000496D67200000000F7072696E745369787465656E426974626F6F6C000000000B7072696E7465724E616D65544558540000000100000000000F7072696E7450726F6F6653657475704F626A6300000005682168378BBE7F6E00000000000A70726F6F6653657475700000000100000000426C746E656E756D0000000C6275696C74696E50726F6F660000000970726F6F66434D594B003842494D043B00000000022D00000010000000010000000000127072696E744F75747075744F7074696F6E7300000017000000004370746E626F6F6C0000000000436C6272626F6F6C00000000005267734D626F6F6C000000000043726E43626F6F6C0000000000436E7443626F6F6C00000000004C626C73626F6F6C00000000004E677476626F6F6C0000000000456D6C44626F6F6C0000000000496E7472626F6F6C000000000042636B674F626A630000000100000000000052474243000000030000000052642020646F7562406FE000000000000000000047726E20646F7562406FE0000000000000000000426C2020646F7562406FE000000000000000000042726454556E744623526C74000000000000000000000000426C6420556E744623526C7400000000000000000000000052736C74556E74462350786C40520000000000000000000A766563746F7244617461626F6F6C010000000050675073656E756D00000000506750730000000050675043000000004C656674556E744623526C74000000000000000000000000546F7020556E744623526C7400000000000000000000000053636C20556E74462350726340590000000000000000001063726F705768656E5072696E74696E67626F6F6C000000000E63726F7052656374426F74746F6D6C6F6E67000000000000000C63726F70526563744C6566746C6F6E67000000000000000D63726F705265637452696768746C6F6E67000000000000000B63726F7052656374546F706C6F6E6700000000003842494D03ED000000000010004800000001000200480000000100023842494D042600000000000E000000000000000000003F8000003842494D040D0000000000040000005A3842494D04190000000000040000001E3842494D03F3000000000009000000000000000001003842494D271000000000000A000100000000000000023842494D03F5000000000048002F66660001006C66660006000000000001002F6666000100A1999A0006000000000001003200000001005A00000006000000000001003500000001002D000000060000000000013842494D03F80000000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D040000000000000200093842494D040200000000001400000000000000000000000000000000000000003842494D043000000000000A010101010101010101013842494D042D00000000000600010000000A3842494D0408000000000010000000010000024000000240000000003842494D041E000000000004000000003842494D041A00000000033F000000060000000000000000000001C20000032000000005672A68079898002D0034000000010000000000000000000000000000000000000001000000000000000000000320000001C200000000000000000000000000000000010000000000000000000000000000000000000010000000010000000000006E756C6C0000000200000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E670000032000000006736C69636573566C4C73000000014F626A6300000001000000000005736C6963650000001200000007736C69636549446C6F6E67000000000000000767726F757049446C6F6E6700000000000000066F726967696E656E756D0000000C45536C6963654F726967696E0000000D6175746F47656E6572617465640000000054797065656E756D0000000A45536C6963655479706500000000496D672000000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E67000003200000000375726C54455854000000010000000000006E756C6C54455854000000010000000000004D7367655445585400000001000000000006616C74546167544558540000000100000000000E63656C6C54657874497348544D4C626F6F6C010000000863656C6C546578745445585400000001000000000009686F727A416C69676E656E756D0000000F45536C696365486F727A416C69676E0000000764656661756C740000000976657274416C69676E656E756D0000000F45536C69636556657274416C69676E0000000764656661756C740000000B6267436F6C6F7254797065656E756D0000001145536C6963654247436F6C6F7254797065000000004E6F6E6500000009746F704F75747365746C6F6E67000000000000000A6C6566744F75747365746C6F6E67000000000000000C626F74746F6D4F75747365746C6F6E67000000000000000B72696768744F75747365746C6F6E6700000000003842494D042800000000000C000000023FF00000000000003842494D041100000000000101003842494D04140000000000040000000A3842494D040C000000000CDC00000001000000A00000005A000001E00000A8C000000CC000180001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD93842494D042100000000005700000001010000000F00410064006F00620065002000500068006F0074006F00730068006F00700000001400410064006F00620065002000500068006F0074006F00730068006F00700020003200300032003000000001003842494D04060000000000070006000000010100FFE10DD2687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F003C3F787061636B657420626567696E3D22EFBBBF222069643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E203C783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D6574612F2220783A786D70746B3D2241646F626520584D5020436F726520352E362D633134382037392E3136343033362C20323031392F30382F31332D30313A30363A35372020202020202020223E203C7264663A52444620786D6C6E733A7264663D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D7264662D73796E7461782D6E7323223E203C7264663A4465736372697074696F6E207264663A61626F75743D222220786D6C6E733A786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F2220786D6C6E733A786D704D4D3D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F2220786D6C6E733A73744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F73547970652F5265736F757263654576656E74232220786D6C6E733A64633D22687474703A2F2F7075726C2E6F72672F64632F656C656D656E74732F312E312F2220786D6C6E733A70686F746F73686F703D22687474703A2F2F6E732E61646F62652E636F6D2F70686F746F73686F702F312E302F2220786D703A43726561746F72546F6F6C3D2241646F62652050686F746F73686F702032312E30202857696E646F7773292220786D703A437265617465446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D65746164617461446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D6F64696679446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D704D4D3A496E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D3232623834663439646366312220786D704D4D3A446F63756D656E7449443D2261646F62653A646F6369643A70686F746F73686F703A64633333616566382D343164372D343134372D626566652D3133623366363839326632642220786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D702E6469643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222064633A666F726D61743D22696D6167652F6A706567222070686F746F73686F703A436F6C6F724D6F64653D2233223E203C786D704D4D3A486973746F72793E203C7264663A5365713E203C7264663A6C692073744576743A616374696F6E3D2263726561746564222073744576743A696E7374616E636549443D22786D702E6969643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222F3E203C7264663A6C692073744576743A616374696F6E3D227361766564222073744576743A696E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D323262383466343964636631222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222073744576743A6368616E6765643D222F222F3E203C2F7264663A5365713E203C2F786D704D4D3A486973746F72793E203C2F7264663A4465736372697074696F6E3E203C2F7264663A5244463E203C2F783A786D706D6574613E2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020203C3F787061636B657420656E643D2277223F3EFFEE000E41646F626500644000000001FFDB0084000202020202020202020203020202030403020203040504040404040506050505050505060607070807070609090A0A09090C0C0C0C0C0C0C0C0C0C0C0C0C0C0C01030303050405090606090D0A090A0D0F0E0E0E0E0F0F0C0C0C0C0C0F0F0C0C0C0C0C0C0F0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC000110801C2032003011100021101031101FFDD00040064FFC401A20000000701010101010000000000000000040503020601000708090A0B0100020203010101010100000000000000010002030405060708090A0B1000020103030204020607030402060273010203110400052112314151061361227181143291A10715B14223C152D1E1331662F0247282F12543345392A2B26373C235442793A3B33617546474C3D2E2082683090A181984944546A4B456D355281AF2E3F3C4D4E4F465758595A5B5C5D5E5F566768696A6B6C6D6E6F637475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F82939495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFA110002020102030505040506040803036D0100021103042112314105511361220671819132A1B1F014C1D1E1234215526272F1332434438216925325A263B2C20773D235E2448317549308090A18192636451A2764745537F2A3B3C32829D3E3F38494A4B4C4D4E4F465758595A5B5C5D5E5F5465666768696A6B6C6D6E6F6475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F839495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFAFFDA000C03010002110311003F00FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8E35D5BCC737C2D3C9BFBFF666A389DAABAAEB92D09964A9F7C78D5CFA56B736CD2C94EF538F1AA82F96F534916762EE10D78F8E112B54DEDED35BD3EEA09B45B992D25620CA14D3265239BD8EDBCD5E6BB286DA2B8BE79A375FDFA924D4D3205B0232DB5BD4EF199998E5459C58F6A9ABEA16F71CB9114EF9125B120B8F3A5CDA026573418AA583F34D616346AB5298A09A424FF98F2DD0F80D2BE18691C4925DEBD7DAB05B61522434CAF2C51C6FBA7FE7122F60D17CBBA84175B333D4D7E6329E172714DF5E6AFE7ED22CE1043865814FAAB5F118F0B9A26F8C7F30BF306DEE7549AE2C8889391A95FA71E1499BC4758F3D5037A77ACDEA0AB47CBAE4E30713366E12F35D43F302DA14901531CE7ECCA7C72C11718E7796EAFE6ED57516663AA12A0515431E99608B8F2D430D9A677E524F3FAA4F5A9AE5822D0750978B98B8D140D8E4C63B63F9843BDC13F64532431B1F1AD0C5DB916EE72D8E362656ACB7457BE4BC3606368A13F2553F7E5321BB5F0EEDD0B6F916C0141ADD0558F5385BE2690CC5536E98B682985A4527312ABF1A6F5C9F44527A6F5255114979C48EC4E424136EE70A2D2593E54CA2516432D265A76A6F6B5FAACACBE041E995F0B319DE9DE5BFCCBF37E8C54E9FE619A075E8A1C8FE18699F88FA4FC9FF00F395FE6ED08C0BACAB6A71A302D2BFC5B0F98C890D8323EA6F247FCE5769BE63B8449ECD62F50F5D875AE564360C8FA2EC3CC5A46B32DADF898514F2F4EBD72B21BF14F74FF4D7626F1F53F8A192BF5207B785320439FC4115A4693711DBDF5F5F12CE8C0D913D857B640865CD910BAFAE46A41FEE46F95909115A6CE4BB46B98FAC20D7214C643662170CF7323C858AFA27E2FA314452DD56DE2D4F4C9F94A6B1827AF862DF163FA65C8FD1C2C11EADCA80D716F09EC33DE42A6D1472A2824F861069AB502C331D3BCB3E55F3C412795FCE9A746D05DC6CB0CEEBBD4A9A6FF3399784BA4D445F8C9FF3931F9253FE507E61EA96B145E9F97B57919B426A6C402C4D3AF866C605D3E41BBE5BAFA5230FC32DB583B90724F865D8B930CC5BCB5A16375C55AC5578E98AB78AA8BFDA38AAA2F7C55A3D7156B155EADD315560D8ABFADEFF009C6EFF00D677FC84FF00CD73E56FFBA45AE5A39349E6F68C28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF917B754FE45FBB34FC2ED532A855A803C71E1551370C0E3C2AADF5A26361ED863155D0DC52840DFC72C2A39A6893B3D0124F8D7205B423E172F227A6C401D86D9516714AB5F0D52FD80A139193607916A21A49641526A722125825DE9F335C1F4C75ED96C434929D699A6C96C434DD0F639708B519B2F86D62F8446DC7EB1F0971B52990CB0D9871BE87FCB0F341D3236D0D5B8C6E3E2981A1FBF28E17231CD35F3479E9A06B8D356666080FC7CAA4D6BDF0F0B9919BE7FD5BCC7246F2B3BB10C4EC4E3C2994DE7979AD87666AFDAE9921171331B2C0F56D4F996EFF003CB045C5931D8EF2A483F765822E3C93012875EBB1C988B4108794A034D865910C68BA38D5CFDACB0048895EF171AE4C36479A0A470A7A6580362A4738A2F877CC49C775A4724E0D32149016B354935AD71A4A1DD6BD77C7853689173C4000D282981B835EBA75A0AF8D30316FEB00F53CBE780C5810510B7617A1A7CB21C2C68DA6FA7EA011872EBE39021BC16463520EBC791A11BF8640867128FB5D46EECDD26B2B9642A6A021A6408660BEA2FCB2FCFDD73CBED676DA8D64D3C301752BEE42FCCE56437639517E927903F33746F37E9D6F35B5CC6CC69C5188FE272B21CE195EF305FA4D63FBD6531AAF4047864086E8E4B486CAF94DD3C40F0427627A64086D8CD96A5DDCDA59B81C5A07EAC065720CA52B09035922C373792515250683B641116276C6D6D61BBE6F53302029E9BE2DF179F4113DAEA124A8F54249515DB16F0CA34926E2FE49AEE5291C6018F7A54F860465161EA22FDB4CB9B1BE11ABC42946201CC9C45D46A60F8AFF00E73E6C935ED07CAFE6151B69FEA733E1CB966C6127479A3BBF21B5802DEF21BB07F772A9A2F6CB896A8B7129F492423FBC15197E12C7338F7CBDA14FB8C555475C55CDD7156B156A98AB78AA8B1353BE2AB6A7C7155E3156EA7C7157F5CBFF0038D9FF00ACEBF907FF009AE3CABFF748B5CB472693CDED5850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91688D3E8CD770BB55732D29BED5C3C2AA125C2826831E155317408208D8E02155E1B85AF4C8951CD358A7AEC0640B684DB436F56492BD16B9596615B5884496D2F7DF6CAE41B2245BC82F22E370C08A6F82213221279612262C82A46E7E599100E3CCAE5B8127C2F41C732621C6949524D42354F4A234917A1AE47306A2535D3BCDEBA4425797FA536DCC1FEDCC76FC4509A9F9B4384B899EB24952C6B5FE38D39824C1F50F30477E480698D24CAD8EDC5C8D85474E95C9C766360A4574C1CF635E9EF930D6404B3D13EA5541F0229BD72C01A26023D4B200A41E5D969BFDD9688B498A9C8A643CC30A7422BD32241B4C601C9CD0D0D4622D78559E6DA85BE9CB031A4148391EBD7EFC95A3758ABD0572A31B6611B1823A838384A95415A9D8EDDA98F09415600537EFDB070962DFD589EDEE477CA8B782D7D5877207CCE16629B36E3C4570F267C214BD23C80EE4F4C2427802690DB9461BF5CA484009D470F214276A6FE232B21980A5CBD19290CC580EB4DE83DF2B660332D27535212DEE8FFA3C9B487DB20591D9EA7E53F3E7983CB371CF47BA75B588D42722361ED5CACD22322FADFF002DBFE729E486FECA3F324A5B4F43C6EB7AD6B403F6B2B2DF0917D9AFF997E53F30E976D75A2CF1C72CA0114615DFE9C8172A322F48F2E1BBD5F477844BCCF02EA6BE032B937028CD596783CBD6EAE486690291DF2A6C890F3BF35C434FB6B478C9AC8A0B530D37C4879A9BFB99670B1D41AED5EFF2C0DE0B228A4BA8602D3935603D3A78FD1912CE554CFF004DBBBDD461B5B6949F4D3BB6DFAF32313ABD48BE4F08FF009CBD8E0D47F29B5582DF79B4BF4C311B9F889E99B081D9D0E789B7E39EB9664FE87818D4B86E5F7E5A1C5029425A239806C20F8732B0726190DA1CF7CC86A531D462AAABD7157375C55AC55D8ABB15506FB47156B155E3A0C55BC55FD72FFCE367FEB3AFE417FE6B8F2AFF00DD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91745DBAE6B5DAA0270038DFBF4C557A007DF1B569937DBBE025217C042073DC654C931B4B9E50CA83AF638153ED2A660AE69F7614A367BA58ED6466DC57BE210497946B3748D33508EB930030322C65AED519B7A6D930C0A4B25EA976A1A6581AD2C9AE872FB4704D38D012DCEFD72B6D40CD37A94DCD07BE2CACA024DF7F0C56CA8140C8FF00BB32CBD8569F0F7CAB27369C922D18005B7B89916CE2B561340E5BAB2F4EB92C64B5D943DB5FDB89F5295B5385DAF559A094950D1CE7B04AEF99B8C2D95595FCC31E95FA5A2F2DEAB79369A4C971E6692CA54B64886DBBF1E1B7BE654698F1747A07953F25FF00357CD5E47B8FCC3F2CF921F5AF26DAC924BAB6B8AEDF686F20A01B713919D1482F2ED2EE9AFF0053F4EEAE9567B5774B4D35A8AB291B1591BF678F6AF5C85320537786D4C727D62D7D2746ACB0024AAB57E1A37BE16C1BA0A592333C1F5AB6956F6452D6B040A646283AFC2B8B2D91111FAC46DF5AD0357B7907FBCF3A594ADC97BBF4ED8D30F103505E5DC61A19341D524914F1B6B916725593FDF9C698D3094C2BC17577C9A69749D5DD17E004584A7930F1DB6C698198519259239ED629ECE48EE637F5EE6CEF94DAB7A0DF64D1E87010C6D165EFA492CFF437FCEC1AD7982636B06996E39B2843F0A8095272AE0B6424C9F59F2D79A3CADA9E9BA7F9E7C8D3686FAFA7FA33DD1786BC056A3985C85331262333C3A54F76F7BC648AB4B360D5AF80195D16C12513E60D2CD80917D45D661916331703F0A31DDBE818981642749BC3AE6906375955CC900F87512A429FE19594FE60222D35781D3EB68CAD1034926660015F9572B3129FCC840C7E65D1D24BEB4B581E196ED089EE402E021EE32070CAAD7F3211EFE61B4168AB6D299934E50F75301F184E8085EF90F02523417F34193E95ABBEB4AB7361A9FA4427EFD88A72403A53C6980E92498EA8047DBF9C7CB567070FAFC915C4CE561708580643F1127B54E0FCA49C886AA2CCF4DFCE48343113DBF98273C2842D0D36FA71FCA172A3AB8BE9FF00CBBFF9CDB4D1FD0B6D435C905A2AD18F0A9FF896425A434CA7AC14FAC348FF009CD2FC9CD42C53F4D798CACC46EA631D7FE0B043465C6FCE29EAFF00F393FF00939ABD91B3B0F33299266A44F22AA8527BD4B659F932D90D6EEC1B4AFF009C92FC948F548E1D6BCDBEB7D5488E20B10E0B20DAA581E9954B4843B0C5AC0FA4F4CF3168FABC116ADA4C424D0EE943D9DEF51231DCD3B653E018736EC9A8E21B326B4D5ED26FDD28E20EDB6D8D535DDBC63FE7231043F97F76F6EA5FD68D8B83BD681BAE646271B34453F1A350B93EBFD65BAC723023C3E239B1C54E8B53B294BF1309FB5C0E4332C38504337F1C2CD662AAABFC3155F8ABB15587AE2AD62AEE15DEB8ABB80F1C55DD36F0C55D8ABFAE5FF9C6CFFD675FC82FFCD71E55FF00BA45AE5A39349E6F6AC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90949CD3DF35AED52FB89CF2AF7C55B86E091D7E78AA21AE147461F7E02A39A924D50F534F0CA99A334E620B96D86F4AE054F2D6EFD2473D3C3154A750D59DAD254AF1F88648734179BDEDD33C8C49D8E4C302C72E27356DE9930C6492F362E77DB26D6A44FC66A69B7538CD38D42523B1FA72B6E435483D7156B155F63A7CDACEBBE57F2EC774BA6C5E65D66CF4A9755A8E708BA9021600F600D6B93C70123BB466354FD9DB4FF9F49FE51E9B35B5DF9C7FE725E596D2C19259EC276B48A07400311EA48EBB7C865808ADA838F7BBEA8D27FE704FFE70B7F2CBC93ADFE62EB5E4ED2FCFDA1F97AD1F53B8D68CE66458A1AB332885B893F4E5D007DEA4EFDC5F217E7E7FCFC07FE716353FC95F327E49FE4E7952E35AD3FCD1A73D92DB5DE9DF548AD1A421898DE956229B1CBE2A0D9B7BB7FCFBAED6DAEFFE7DEDABC11C097125CEA9E608E58A641C5CAD0F02C474D8EF91931E27CE5FF386BF901FF38ADFF3939F947F9A5E46D4AC20D13F3DE4D4AFA3D5B502693D8AA5C31B692CB911EA29FDBA74FA3229E2A7E6C7E75FE48FE62FE43F9FB55FCAFF003FD93DAC31B9934FF32509B7B8B752CD0949A9C492805403D7037465694FE5779EB49FCAEFCC9F267E62EBFA147E6CF2EE9F1490DDE9774291BF26A6F8B2E2EAFDABFC97FF009CC4FCA9FCF4F37697E48F21FF00CE3B5ADDCD7052DF51BD5B3AD9D9DB103D4066084034DC570B1E305EEDFF00393BF9B5F917FF0038B736896771F9223CD9E6AD663E3A258D869FF588BEAA48520BA275A9D862C38DF24AFF00CFC07F285102BFFCE28EA5A6B472F2BE54D1A4243F7A829818193E5CF2EEB1F945FF0039A1FF0039BFA5493F92469FE42D5B4CB5D2E7D04C660314D0D43332281435070B0326BF337F28BCA9F919FF003F16F267E5FF00E5ED82683A169F269B7D6F08FDE822E95988A3D41D80C89E4CE25EFF00FF003F7E5B6B6D7BF216FAED56EE1B8866F5D446B172F848FD803B9CAEB9B3069F945A4FF8720F3D7902F7CCBA4407CA305FC0757B66735684CAA5B90FF572BE8DAFDCAB4F397FCFACEEF5A9560F2669B26AD218AD25536AE12579540001F528C7B5460970F716278AB9BE8CF3FF00E497FCE0E7E5E7E5C69FE7AF387E5468DA6F90EF8441677470419BEC02858124FCF23C239D7E3E4E29B7CC49E6EFF9F50CE925A2F93B4A8B4E1113C84120527C38FAB5AFD3938C224F543E93FC95FC95FF009C13FCF1F2BEA3E60FCB0FCA9D1F52D0EC646D3EEEE9E378D870A93D5DBC32D18815DDE0B79E65FF009F5A683AA6B3A4DE792B4AB0D6B4B9A7D36FE25B7763CE0AAB0E5EA53AFB75C9C71041BA7E10595CE9716ADE686D3E258B449B5DD4A4D123AD185A191BD15A7871A65BC23AB5926F67DC5FF3827AD7FCE27E9FA779F3FE865346B2D425D52E61FF000CC570865F4A341FBDA85652A49A1EB8384364645FA0ADE64FF9F54F0E2FE56D1154776B7907FCCEC7843689C97DBEBFFF003EAD240B6F2B684EC4D14185C024F6AFAD80C026539232EB55FF009F5B229F5BCA9A1AB20ABA7A7202A3DFF7DB618E30D5C459F7E5FF0090FF00E7DF7F9C370BA2790BF2B6D35DE5F66FADEDE6FAB236FD67595941DBBE1300CE32931BFF009CC4FF009C6AFF009C4DFC9FFF009C73FCD3D534FF0021E85E59F375CE85247E5495A765BA92F792F130866DD857B0CA66221CAC5399237D9E1DFF0038E06E1FF24BC8D6FA85CDC48EB67037D52742BC18C62AC09DCD7357A900BB9C123D5F4B695A658ED26C48DC819824539F1281FCC5F2E5A79A3C9FAA5A7107EAF03F15EE7E16E99386CD59793F083CE5A73699AFEB5A5BC6D088677081C52B466E999F8CBA3D4C5283B5B59A9054AA1A5733226C38110866FE39364B315545FE18AAFC55BC554CF5C55D8AB5CE9B53157733E18AB7B9DE9D715750F862AFEB97FE71B3FF0059D7F20FFF0035C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EE4B96A57F0CD6BB54BEE6E4F2FD78AAE86E01502BB62AB1E41CC1F7C05211724A0FA7E1953247B5D0458CD771D302AC9756E0B4AE2AC5EFF0053332B28F1E9921CD058C5DDC9A1C98605209A72C684F7DB2618C96890713936B5093F7854786F8CD38DBF476F6CADB96AC542DF462ABFD318AAA691E55F3379E7CD9A1793FC99650DD799AF254BAD31DD8AC8AF1B7C3C69EF976201C4CE5F60F993FE70D3FE739BCCF6ED6FE636BAD4D0A7A0BA64974C55430141414FC72EA01A2CBF643F2F3F273CFDA2FF00CE0F79D3F27751D3560F3D6A7E56BAD3AD2D236678CCF22154058926A49DF7C9C764136FC52D1FFE701FFE72CB48B23A6C3E43D327E0C6E11A590B4CA587B532C0520D3F6A7FE70B3F25FF00307F2DBFE70CB52FCA9F37592691E78BBBFD6E6B3B02DD56EF8984D76EA01C892C0C9F94DF94FF00F389FF00F3995F93FF0099EDF98DE46F2ADA43ACF97B58B9B9BFF5A5741716D34DCA84568C0AD6981417AE7FCE7FAFFCE51FE6E79534AF35F9F3F2AB43D1FF002EBCAD1B32EA1612BCB7E1CA1F51AE118D5072AD074C590953F38FFE71DF41F23F993F327C9F61F9CBA9DDE9DF96FAE3B23DCB201688E1C22891CF40316CE27EE04FFF003953FF0038D3FF0038DF77A57E43FF00CE2AF97F45D77F31FCC37D67656F7518A6957724DF097B9BD427E3626800C58195B18FF9CAAFF9CCDFCF4FC80D7BCAFA67E687FCE3DF94F59BED56CC3691AFD83497715B5C16A2A4323861EA03B85271636FABFF002FFF0038507E40CFF9F1F9F7E46D13C8B05BDA9B9D3F4E4445935042AC10CEACBB48C69B0C5812FC5DFF009C15D5A2D67FE7381F58D3AD6DADAD7CCBAE5CEAD690D688B677723CB1C6941D830DB16264F56FF9CB6980FF009FA17962F26790A01A3C56CD08AFC512BA95FA2BBE25B81671FF003F8D92E6E35DFC86B458964B3FAB48F6A53790B537046408641F93B24769776F1C5A8D8BDC5E5005AA9AD32A21B8153B8D1ACADF59F24FD5E27B49CEB5640015A8FDE83B570034CB9BF793FE7E412ABFFCE01F962299A79644D5F458DA471425D6A77F6DF2C8C6A9818EE5F822DA1697A868B63A7E97A1869E3B413DF5D92F5F5075EF84367007EF97FCFA0C347FF38C9E7F8608E44B9FF10DDC61C0FDA11353EECB049AB806DF17E12F9AB47B1BAFCC0FCCEB8BA8DA7BDFF156A70A3396A02262C6BBF8938253D9B3806EB5E3B64FAAB416104933FC0DC4D7EC8CC7F14B1F0829A683A75C3FD616C230D727F7CA091B8F91C7C52918C27967E5AF2D4C04779A2A4DE22AFF00D71F14A784226DB4BF2FEA7AAD9F93BCA1F97771E62F34DF4C9FA3B4FB38E4964E75A091954D4283D4E4A323252007E937E427FCFA63CE7E6BD624F38FFCE42EA16DE50D126845CC1A268937AB24A08A94B9E6D5414EA2B970B69343DEFAFBF303FE72AFFE716BFE708FCA571F975F92DA2D9EB9E72107A561A1E8CA67B496FC01F15E4C0B1526A6B4C8CA7B338C093BF27E59F9CF5FFCCAFF009C81D6EDBF31FF003BB537D6EE21B8F5743FCBD8E42FA6D9467EC96E276A53BE60E6CF5C9D8E0C3B6E1F657E5BFE6369D731586871B246D63122D22A1B745A50468C07ECE61711939F5C2FA534DBE8E15925460EAE054D72328B7C24CC22D5AC61D12EA696CBEB7CA290B102BC7E13918AE4E4FC43FCFDBED3F5AF3EEAA2CE0F41D256DA94A6ED997093A7CE1E1FEA48CAB1C8FCFD01C57D8667623B3AF229D96A1D8ABB155CBDF15546ED8AAC1D3156F15770077AE2AEE03C7156B9D36A74DB157733E18ABFAE6FF9C6CDFF00E71D7F208F8FE5C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D34BC51D4D0F8E6BA9DAA5D757887900C2A71A55B6D7229BB0AE34A897909F881D877C041506914D7085128E2A32AA2CB88285DDE7100A372E23B634578825125F3B6DE3DB0526D0734E0296AD08C9008291DD5D541EF920C0A4C65777FB27E7930C485FCC81BFD3930585174720E677DA9824530148B0F5141BE41B2D48B91D8FCF15B6BD4C56D917917CEFE6DFCBCF3E68FE74F25D8DA4FADE8686E21BDBD1FBA4E07970AF89F0CC8C3C9C5CFCDF7349FF3F5EFF9CA09EC6E2F7F40F96EDEE2C9C5CDC4A63A3948C50D169EDE39750B71DFAE1E46FF009C8DF3C7997FE70D7CC7F9F77D6D65079CF43D126F318B287FDE7668D4B05229D0853DB26021F945E58FF9FADFFCE5A79B35516DE55F22681E62D56E938AD859DA9967DABFB0057B78614BF5BFFE7113F3E7F303F3EFFE71A6FF00F34BCD7656107E6269DAB6B5A78B38978242DA7FD8475A7C2DB1A8C04354DF9BBF941FF3F0CFF9CA9FCDFF00CFA87F28345D1BCB916A1ABEA975A7BCB321458A3B4765E4CD4EDC70522934FF009CF1FCF6FF009CA8FCBB54FC9DF3CC3E4CD4B45FCDAB77FABC1A0167BE8560F85BD6561F0D6B51F2C5987E547903C85E7FFCE1F31E95F90DA75CE97A4DCC5234B6925EBFA51B3F2E410B7892705864FD16F257FCFA23F3F26D7B44BFF33F987CB7E4EB2D2CACD0DEF97A57FAFA5C210D14B5634E4AC01AD70A0BF577CE1E75FC81FCA3FCB5D0BCB7F9F7E7DD07F32353F23411CEF26B7325C6AD737D0F499537AB531624BF32FF00E7323CE1F9DBFF00392DF975379D3CA7E4D9FCB9FF0038CFE50893559ED75188C37B3C51FDA96341406234F84E1A60FCCAFC9CF2BF9BFCFDF9CDE47F2C7E5B79864F2479AFCE0F1D9F917558E43088E40A5C7AAC3703883D31E140897EB27E5E7FCFB5BFE727B4DFCF1F24FE6C7E63FE61689E709343BC49F53B89E691E765414DAB4AD6B5C69B86CC2FFE7EF9AD68DFE37FC9DF2EE8BA9A4BE67F2DDBDCBEAF6D237C36EB22928CDE0180DB2259805F3C7FCE28FF00CE04F9B3FE7277C8B379FED3CEF2E942398C3C1E42073EA05011EF913BF26775CDF5A68BFF003E80F35DB6ADA36B1ABFE62B5E3E957F6F77F57E65AA20903D055BA9A5300891D14CC17E927FCE507FCE31CDFF003909F913A5FE4E5B6A8FA49B39ECEFCDFF00EC97B4D954EFDF2C0C0CC9DDF9B23FE7CF5E6CB5D3445A7FE68CD0DDBB5651EA3052BDD766A644829F10BF463FE710FF00E717AF3FE717FF002A75DF235E6BF36A771A95F4DA9497719F84348A568373BEF954C90A245F9F1E67FF009F44F98B5AF37F9975FB0FCC06B6B3D7B50B8D4C42F211F1DCC86460C037515C4094BA289D17C03FF393DFF38B1AC7FCE29F9FBC85A4EA5AE9D56D3CC32395915890415F72727E1D06CF11E5115ADBC0BC0ACCAD3B3189E9B75DE990E109E22AF02A25CA98A4775EE7B60A0C6CBEB5FF009F6E24C3FE73B742F456393FE752D5CC824EC9C7E265F714DB2E8061225F657FCFCFFF003C3F35FC97E6DFCBAFC96F2179A27F2BE93E74D264D47CC3E6289FD3B9611CDE998B9D3BA8E9965048912FC9FF002E796B4CF2F6A1746D8A5FCB75704DF6B7A99ADCBC86A4C8A6BD77CAB200DF025ECD06A30454B7B39648D29FBFB81D251E0C7C335D962E7E29109E69570F65730DF69E56CA20DF15B45B4751D5BE6731E31A72B8ADF587E5979ECDFABDB5F5C28E2005E47AFE18261BE05F56793754B6B9B7BDD2DD11E3BD8D979B741B532B00B39BF217FE726FCA5FE19FCC1D4EE238EAB732332D3A1A96E999100EAF5043E588DA30F351BE22DF1A9EA0E67E2D83AD9157A1F0CB98BB7F0C3452D12075C08B5CA46FBE2AA8C46DBE2AB01DB156EA3C715773A6D4C16134EE67C31B5A6F883BD7AE3687701E3855FD72FF00CE367FEB3AFE417FE6B8F2AFFDD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87A96FEF941ACBF8E623B3B0963DF5F16DA5AE34B611515DDF541F571A5D9318B53BD42A1E4AA7ED2E0931927706A3CC0E9BE52D61166E7638B38A5E6EBE33D4E2D8103717049C52833FBC23155616C42F21DF15434B1D3B62A868D7E36F0F0C5894746A3DBE8C582BB461BE43155168462AC93F2FBF2CFCE1F9BDE7FD1FF2EBC9776965A8EAF19905C4E6900A1A7C7976271B31DDFA2BA47FCF9FFF003D7597F43CC9F997E58B4B688049A0B3123CA57AD18AEDF7E640F268B7EC4F907F217CA1F937FF0038F179F955E75D6E26F23C1A335AF9A359B87280447FBCAB9AD12872616DF1CEABFF003963FF00381FFF0038BD6BA743F96BE5BD23CF9A8D847C5755F29411C972838D2B3CEC2B5DC8241C905B5BFF003EB4FCC58FCF1F979F9AFA45BDB470DBEA3E63D675CB68140E5026A2EC544B4EFF00150E4BA2F0DB17FF009F7DFF00CE324FF963E63FCDAFCFEFCCDB44B09FF4B6ACDE5AB8B8F84DBC31CECCF23927F6C74DB010CB81F96DF9DDF9D7FF002BE3FE7253CE9F98D6F74D045A7CCD65A2E9970D50A9033C3CA01414E4054E56436C616CDFFE712FF28FF257F327CF9E6FF31FE72FE7149F963AB796353B69BCBCB6F75F56B8942307356F0AE459786FD51F38F93BFE71CFCE8D7B3AFF00CE71F98B48B4344BB5D3B5DE01005028483E032A32A3CDA4E2277A79DF977FE7DABFF388BF9C724FA9681F9DFE67FCC6BB8EA6F35A1A8ADDB0A750CEC07864F8C745E0A7D95F97BE4CFC8BFC81F25FFD0B3F99FF0036D7CCFA7F9B4496BA47977CC577EBDF4905C8A0B58A951C00FB2B931913C07B9F1A79AFFE7DDDFF003895F947E615F32F9A7F3CF59FCB2D465BD7B8F29DF0D405ACB64ECC4AADAB863C4A5683DB26269AA1C932B9FC9FFF009C6DD4E4B4D31BFE73E3CEE249C520787CC4435C9EA55985795326770C385F15FF00CE607FCE3DFF00CE35793FC93A9FE677927FE722AEFF0035BF320CB15BDBE9DABEA02FAEAE854A30AD6A780ED95C837C075A7C55E4DF31FE71792B429EDFCA5F991ADF923465E12CD616174D00776151B2E634B6673887D0DFF38F9E6FFF009C92F3EFE7CFE58F92FF00E576F99F50875F9E3D66F2CA5BF77A5BD9C80C9148A76A3807614C8F38DD72712517E82FFCFD9BF3BBCF5E43D53F2BFC95E46F376ABE50D47CC9A7CBA8CF75A64ED0168E297830629BF6F1CB9B7146F67E4949F9B1FF0039096D688A9F9E7E6F8AD66FDFCB72DA8CA013ECD5AFE382DCA9C283F6FBFE7D73E78F3479EFFE71CBCEFAC79EBCD5AC79AEFB4CF30DDC2BA85EDC34F27A0B192A159EA695A9EB8251704737E2FF009DFF003E7FE720AFBF30FF003022B5FCE7F34697A7DAEBF7D69A7410DF3A2450C729F4D68294016836C31A05CD8E332890C035DD5BCF3E67D574EF30FE64F9EEFF00CECFA07C7647509CCECBCF614AE4E73586911714D00BE54BA9663752A97D3E2AFEEC022A6A3E5989293951D3D2B5AB7A48ED5FDAFE3862584B1BEBEFF9F69C9EA7FCE75684C3FEA4ED647FC933991170F2C69EDFFF003F6FDFF3EFF26475FF0070139A7FD1C60916A897C11A8C06541DF8C9CA998F22E5C0A7769767EA8B08FD9ED9448B971679A34DCA08E393ECD77C85B75DB34B4D4A5D2EE2196CBA0209A64245CAC6FA93F2F7F32121B8B35B9702BC565AFBD3DB220B64F93C6BFE7316D6CB516B1D6AC183B3AD5A9F4E64C0BAAD445F9DD35A43EA99631F13EF2FCF2FE275A614A6E782D075CBE05690E243D3DF2EE882BC0E79596B937C78ED819479378B2762AEC55ACC79736D1C9BC4312578CB43592EEB920C097F5CDFF38D9FFACE9F905FF9AE3CABFF00748B5CB87260F6AC2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF864BB048AACD51DB311CEB4BC2B147612EE01C56D17621DC0AC98ADA65E8307525EA2BB8C124129D5B45D38F4CA501306040229D716C8A58E28E49D862D88571C9F6DC629548E36A8DB154D235AAD08E9DB1541DC42687E1FA7154A1D5D0F43BE282A91C8E0F4C58F0A3519A9BEC3B62BC2B8891BA2938AF0B21F2279EFCFF00F94DE7DD13F323F2F2682DBCC7A3AFA3682ED3D5818B1AFC51F7CBB1CA9C4D40DDEF1F99FF00F39CFF00F3963F99305EDCF983CE163A19D22DDC48BE5D88D8BAB28AD1F89353F4E5DC40971E9FAFDF975AC7983CE1FF003EDFFCC2D67CC3ADCBADEAFAC793AF6692F6F5CCACAEC87A96F0C9476B5A7F387A7BE85A5F97E686F0C4B71A859A08A7863264776DF812A09AEFDF240AD3F707FE7D29F951F9A9E58D67F327CEFAF794AFFCB3F979E6FD06D2D74586F289F5A962209786B4A13D6A72D06C289D3D0FFE7EADF9D7E75FCBCFCB8F2D7E4FF95F4E9747D37F3126922D63CDB6EA5623146D510C6CA2AAC4FDADF7C494F1EEF91AF7FE70E3C83AA7FCE05F92BF3AEF2F5BC95F997E5B8A7B89B5A998AC37BEA48591645EA49A0A13EF9592D8323E2BFF009C7CFC90FCC1FF009C9CF3F6A1E5DF285F695A3F99A0478754D4EFA15781907C3CD50EF5A6F91B6632ECFD44F20FFCFAB7F26BF2AB40D53CD9FF003943F98B1EAF1E9122DD31D16E0D85B451A7C6C6757AB301DE83A60113F0419DBEF0F30F9D3F2CFF00297FE7157CDDF985FF0038E51E8F77A2E99A34D3E87AB584002CA507C25DB882FDF7A647C2A533B3BBF9ABD5FCC1E62BDBFD3BF38B52F3E1D5FF00332009E6CB79656692289588A59C486BC597C06110A62723F717F317CA1E4DFF009F8A7FCE1B683E61F29DEAA79DFC9B6E93C371250BAEACB12ADCC53746E24D763921162676F3AFF9C76FF9C4AFCACFF9C2AF256A3F9DDFF392BAF68DAC6BB25AC8348D2EEE1F56DE1050845489C37C66B4AE4B8D1C4FC98F3C683E4FF3F7E6A7987CE9A0F95AFF00CB7F97BAD5E493E91A34D227AD21690B17B72BF654D4103C32B3367E3523BCC3368DE5ED38437CCF631C29EAC4D72DCC48631544A0AD49A532A3BA7C6B7EAA7FCFAF3F21AF74CB6F31FF00CE577E62D9AE9F1EAD6D2BF93BD61C560D302B7AF32F2A5140527135F00C38ADF0C7FCE507E6BC1F9E5FF3923E60F3559336B1E4BF277ADA2792A590F34B9B5726B3475EC1AB91F136761A7C24EEF13D4A2B98216F556DEFED9374B08928CA3C0D76C7C47272E2D9FB2FFF003E9130C7FF0038CDF98534B0936D279BAFFD6B75D8AA08A9C7E8CB89DBE4EAB83D4FC42B8373FF002B0FF346E6C618E5B6B7F36EA8E7D75E4157D634041F0C864950761A68F34C66823B9FAC35E7A572978ABF0C0BC42537E99852CCEC052AAA97948E11B154E30923E3000EC721E2309CC24B3CE90432F3902146A3D4F427A65F09383972D3EC4FF9F65C7327FCE717971E44204FE4DD65E13D792F03BED9990E41D74F2713DD7FE7ED2449F9FF00F92E10F22FE5F9CA7B833E5732B10F862E5828B84A5655AD5331E45CBC6126D3AF59262937EEF7D81CC79172E2F55D2984B0523352AB5DB204B918E36C8F4C9E559024919604D2A72B949CA80A679663EAD494CBE9348414FA32024DB241F9EDEF35FB18ED9C35C431A101FA819938E4E0E585BE39D634AB9D26FEEA39A268D2662D096EE3DB2EE370E5898E354B6FF7E6463938D38D34D18D88FA73281D9C5915363C7A76C8940709053734381B03B9A78E2AB81077071575478E2ADD3C329237656EA1F0C900C495DD865803592DE4A9812FEB9BFE71B3FF0059D7F20BFF0035C7957FEE916B96057B562AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF86BB8802C67311CBE240DB460B32F63B1C57899159D94483A7CB15E25595139003AE465C97891F6DF00CA9215659878E2D914A669013D6A7B62D81411BE21E18A519137BE2A8C57A6F8AB52BD57DF154A6615A629014E35DFF008629A469140B8AD2262C5682DBA92EE182EA4897D5B636D227A6366F588F8581F6C944B46585BF40FF00E70A3FE70BFF0024FF00E723FF0029B5BF3279AFCCB2E85E6CD3F54FD1B7D1CF7CB1F2A8279716604E5FC449B718C2BA3F4B7F3B2EFF00283FE71B3FE7103CF7F9456BE72B18EF350F2ECFA4796A059D267BDB87144850231219B975392053E1DEEF8D7FE707F47FF9C0DF27FE58699F9D5E7A920D17CE3645F4EF33E9FE629BEBB0472C5F6A58ED983503B74A0C9DA38084AFFE7217FE7E75E7BF365C5E7907FE719F438FCB7A1D9BB245E63302FA77D68A6A9F554D84551B9A76C78E9A678492FBA3F267F36BF20BFE73B3F246D3F2E3CE2F6ADE69D3EDE14F3568B7AC8B7B693DB95E53432C86A3D4707ECFBE0333C988C469F327FCFCB3F353CABE53FCBAF26FFCE267E5CDFDA3C1E60317E9B4B77594D8C5624344ACC8763215A1191E3A663097E57797752F3AFE5FF9C6C7CCDF943A9C9A0F9CF47B37B69ADC3304BA5917E290814069EF94F8AD834F27D89FF38B3F927AAFFCE6FDA7E64798BF3E7F37350B297C93A92E973E8C3516B68AE39C65D8B46CE015A8A5732465003038E4FD4FB9B5FF009C5EFCACFC8DB6FC88F3D7E61E976FF96F73A61B09B4D8665F5F8B1DCB4D11635DFAD301CF148C322F85A05FF9F51FE534B65AAF9524BCF3E5F69779EB5A587D6E6BA592E54502399556AA41E94A644E701B069645F0D7E4CFE707E71FE4DFE6779E7F353F27ACA7B7F2BDEEB5777FAA7901F91B67D325959D04716C81E8C454657F9A8B68D148F47EAA587FCE5D7FCE207FCE64F97A0F277E7DD8CFE44D68148A2F29EA333219A56D898E455E2373B03F7E40E51F51E5E4C65A390DBABF3FBFE735BFE7193F2E7FE71D6EBCA4BF931E6B9F599BF306493F44F97BEB7F5C7B6892AE2854B05A8A0C81CA48B3C9A8E9A47A24BFF3851F919E41FCF8FCE08BCB7F9D5E708F47BEF273A5EE8BF97374C527BFF4784AEC676A2B2AF75EE36C1C6472EBD57F2E62FB7BFE738BFE730D64B5BBFF009C5CFF009C7DB8B4B9D4AE02D96BFAD6931886D349B68C7096D02A1E279A93BAED8F89E9B972FBDC8C7A49134FCD7F2F791E1F2BD8A68176E65963AD2F474AB6E687E67304EA2CBD060D36C9D5FF00962CDEC2E4C7290D6F197694577A7CB271CD6DB9F4FB3F537FE7D471DBC1FF0038CDF9836D79756F682FFCD9A8A47EB4F1C6DC425391566046FE39B033B1B793CF4F170CC03DE7EF7E383E88DABF9ABF332F6D2329158F9BF538A57471C64549295DBED5731F3CEA2ECB1E2B0B64B2FAB6DC295ED9A83959F8450935A7AA80863180EB571D695CB2191AE78497A47FCE3F7E527E5A7E66FF00CE4DE8BF97BF9B2B736BE4AF3858DC5D45789762D544B6F1928399200E4453E9CDB69C931BBE4EB73E120D53F757F207FE70C7FE718BFE71AFCE927E65F912FE4935C165716D61ACDEEB114F0C16970A04CA23671527C4666125C2188F73F2B3FE7E3BF9A5E4EFCDFF00F9C87FCBEB2FCB3F30C1E6A87C89E5FB8B0F31FD554D22B812972BEA74AD08CA67CADBF1E3DDF31DAC4D05A3A188C69337A8439E4E1BFD6CC69173A18924F4C0BA048EF98E4B950C4F51D01855631D5C01954E4E4C31D3D46DF46944493053B8AE63CA4DA229835ADEBC6A5222C22EBB64449245AB5B5C4A54C33C541EF9938E4C4C2DE59F9A3E5C4BCB14D4ADE3DED50AB53DF2D949A32627CC778E915B014A4B5A1CC8C527559E348462CA23AF565AE6C22EB25CDCA390DFB64CB3839A315C836114B7D35C50EA53618ABB155C1C014F0C8916825AF572403025BF532603025DEAE5822D64BFAEAFF9C6B35FF9C74FC823E3F971E55FFBA45AE0661ED78A5D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF881BC880420F5CC3E20E424B0A857A1EA4ED8F12B24B50B4218D31E20AA8F08670CBB9ED809B0A39AA03C41076395F0B604BE5662C6870F0B30504E1C9AD31E165C6D29E277FA7070B21205171354FC382928CF8A83E78D2B8D698D2A12406B8A625A8D0D7A6D8B2B45B23300145698AD85F1EDB1EB8ADAA4A225884FC4CD3AB045B6AD0153D5BE8C429A2868F47BB86133689E66D47465BDBA56BFD32CEE6585789FB529E0402465832531E005338FCBB6FA84CE751D4B53D461B17E766D79772CEAF20E8C15C9030F8BDE98E11D11F0795F499EFEDAF6F2C266B595F85D69026222007FBB997ECB57C30F8C19F83BDB33B782934292BC7E8C4ECB672C2823F4231B2D78815DB6CA67985B64710EA91EA7E5A437115F68D25EF97EEA32FFA4F52D3EE5EDCDE06FB3511914E390F1E9B3C081768DE5FD3ED8FD72E26BBD7F5E0DB6AB793BCAF427B1724ED909E7B671C1001E86B6EF2DC590922A49044CAFABA1E2483FB240DF7CA8E50DBE0C52883F2E6D4EB125EC771AA59E917959750B0B1BE96DBEB128E858C64549F7CAFF3738F271A7A404BD4B4AFCA0F20CF6D75A85CD86A90996129159DE6A12DD0527BD5C9CA726AF24F9B762D180ED0FC95E5FD05E19F4BD0603769271769155C18BC68475F7CC796693B0C7A50F52D3ED674B48A28163B4912E1A66754142ADFB0C0751EC72BF1A4E6474B163FABFE5BF943CCB3DC5D6B1A12EA3716A39D98B522DA49246EB491402299911D4D7544B4B1287F227E4F59E81AD5C7992EAE2F3EB112D346B2D46E1EF7EAA0FDA0A64AD36F0C9CB59C5CCB8FF901D143CF1F94BA579AAE96F74992E3CADE648DAA3CDF6933C721435E6948E8DF1034EB9286B047CC2FF2782ED17F2EB4DF2AD9BD969566F737F74419BCC533F3993F9B9330E4C5B213D582092E54745188D833187CB62EAD134DB88792A75D40F53FC73046716D98F152B4FE598AD6DD2D6CC85957EC5CB0A807C48EF96C753109CB8F886CF269BFE71FC4B7D793E99E62D5B4A17B5B899AC6F26B783EB2E7E26F4A3206F99B1ED1A157B3A89682E5C54CA34AFCA7D23CB5A63D9C76B2DDDC475996F4C86AD3B7DA771FB44FBE5597571946ADCAC7A7203CF75FD0E64998087A1F8B35E32370D384AE0D338C0E49F4DD47C2C45687B6646292CB00609E67F2EBEAF0D8DC5DC93DB6B36CFC6DEFEDA5689E28C9F8802BBEE336DA7CDC2E0E7D2C65CD8A6A3A0EA36B2B45A7F9B35FBC8C7C715BFE91B85141D57ED77CCD3A814EBB369611E5F794CB42B39B42944DA3DD8824D64F3D75661EACAA4ECCBEA1DCE512CE1A2189EBB1D84090ACF0C6C2D8AF0F58B16E4DF2CA279A2E6431A0534EF527AA2D77CA2598391114CF346D3E7867B762945E42B944B286FC71E3E4FA7F44D352F2C21089CCF115DBDB293305B0E0932587CBA3D27458E8CC3714FECC00B0F0A439B17D4FCA324619C2D3AF41FD99930986420C0753D0A76B1BCB59D39C12EE58F63965F1726196161F1E79A3CB8D63A8CFCA32B6FC8956CCBC669D26AB1960ECBCB91614543C53E599F09874D381054A46F4E95D81E872EE265034A4F2F1343D698096C26DAF52B8A1557703155C411D462A8377F888AE203592B79FBE48062EE7EF93B6041772F7C9713120BFAF7FF9C68FFD671FF9C7FF00FCD6FE54FF00BA45AE066393DB714BB15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8779E6690D0E6BDC86E0B62C55A9D0D6B8AA7B1454C555F8814C473508693A9CB59A5E480C49E98AB4CE9E18AA1A465236C05945742699536F1047092A078E2B61716DBF8E15B08391B7AD701482A9130DB026D16ADB1FD78ADADE4395715B5CC6A062A9859FD93912D914FACBEC37FAD95C9BA09CC1906F8A6B0A0645AF8E565124EE5B5E56640EE320531482C21F4EE0AFF29DF2B9330CEACE0F56829B9C8368E4CDAC6C8B24629D3205B22F49B3B43FA35969534C81722095DBD8BF3A50F5CA8B97065B6766FC7EC91909392190E9DA51E60F1A6F539510D822C94E9842EE2B4182922294BE9CBBFC3DF1A6D10413E9C95E9808D9918A3AD6C100A53AE505ABC3569B4C47A10BB8C57C3455AE9E00E9D714786EB9D2B9A3F14DE9B62830A0F10F35689708F3388C77C945800C0A1B0924B69D5D00DF7CCCC658CA2C43CC9A64B085600D3332127032879C5F44D1D651B3014CBB8DD6E68EC9569E93493D373BE4096BC707D0DE5ED224BCD3238D81217E2194CE4EC2186C27B0F95E4120223E9ED98F22CCE9CB2BB2D12485E12E869514DB2B3272F498082FA3BC976F1FA31C6CBD80C00B9B2C4F5CB6D22065A85FB5D72C12689E35F75E5C826423D304E4C16838DE5DE70F28FA16FCA18FE12A4B003FB332B0C9A270A0F913CE5E598A54B82F0FC42BDB33232B755A885BE51D7EC24D3EE1A3E344EA332A05D2E68531CB9903428D5E99931710841897950E5A98F25656C595ABAC805315B5479401F3C56D2F91FE33BE4C354B9ACE7EF8B1773F7C55DCFDF157F5FF00FF0038CFFF00ACE1FF0038FDFF009ADBCA9FF747B5C9ABDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88316FCCD45335EE42630C7C17891F11D862AAE55A3FB5F862AA7CC9751DB08E6A164BD4E58CD00D192493F67C71552654F1E98AA832AF6EB91290B797134C832564620D6BDB1557E551B1EBDB1542C8AC687016512BE3246C4E0656881228DBC715B5E11CEE294C56C2AD0D003D7B629B4CACC1A53B9C896D8B20B34655607B9A8CAE4DD04EA089F20DF14C63AA7153E3BE56512656AC0D9EFE1902CA2C7A01FE94CD4D89DB2B9320F44D1A22C54D36A641B43D174E882B0E4366E9902D917A259DB936C4506FD32B2E44175B598E7F677AEF95972E0CB2D2D502EE3225C90C86CA10A46DB6574E481B270E8A474ED8D360012CFAA73AF15EA71A6C0109258B03BAD3011B3202D523B609F6B314B2E04D22B3590034AD714702362B38D4D08A62BC08D92CE26864A0DC8D8E2C670D9E75E64D0627B39A4352789ED928B8A214F04F4608659A2058B96A71236EB97424C65040F9A34E89EC95C28AF1CC98CDC1CB17806B5108838E3DE800CB3C475D9216A7E5FD3A7B8B80238C31276180CD9E1C4FACFC9BA25D0B4F4DA1019539357C331E591DBE1C2F4FD1740FAEC9C12352E3AD76CC796473469D93DC796E24291B4604886A6991E2B6EC7800667E5DD3440E9F0D0786112672C6F5FB14B68E3024AD587C3B65824D13C69CA476CD41BFB6D9609B41C4A77FA1C17F6B22320208EF97E39B899A0F913F337CA4B6E2E0DBC436AD4D3E59970C8EB33E2B0F827CFDA605F55B851D76FD599B8E56E935189E113865050F8E66C0BAAC91A520A4003B66406B05554D3AFD38A6D706A1AF6C56C36D20A7738ADA14B124EF930D6D54E28754E2AEA9C55FD837FCE337FEB37FFCE3EFFE6B5F2A7FDD1ED726AF6EC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88EB5527A8EF9AF72138584000F862AB580622B8AAAAC0BC4B6D5188E6A1033851F3CB59A058A952062A876E3FD715506A74EF912BC90EDF6B2B5E254AD00A615E25367618AF129FAA5B6F0C0520ABC75207BE0648911B1236E98A11A88C314DB60126A7E8C59C135B35DC644B745925BAED95C9BE09EC0BF08C837C559C5181CACA24CA6DC7A9694F6C814C52DB7B73EBF4EF95C9987A5E876C788DBB641B4727A3E9B685DA314E832B2CE2F46B2B6263094C8172609D5AE983903E395972E0C8E1B001694C8C9C909A5A5A8AF4E9869B849363682831A6626BA2B44A7D9C69B04D42E2D12A76C8C86CCC4B74B4DA1AF4FA3304B7DA6F69684F1D8605B4CC590AD298ADA30598F4DB6ED8944B7093EA9610CB613A9515E27F5620B488BE60D5F4C486FA62ABD1F7FBF260B19063FE62F4CDA08EA2BC72624E0E58BC2354B0E572DC96A9434F9E4FC470B82CB37FCB4D05AEB534E70FC3CBA91F3C066E5E2C54FB7B4ED02D6DED144680394A1CA2537678A349BE91A6AD9CA5F852BDF2894DC8B013A36A269D98AEDDB0464D9020B26D2ECD232A4AF4CB049259A5BAC2FC435053A659C4D134E3D3B7420F2C989341451B988008879061BE4E33A71F246D83F9B7CB36BA8E997521505CA93FAB32F1C9C2CB8DF97BF9BDA0BD95D5CC623A0DC8FC336584BA6D563A7C937D66DEA91D2873658CBCEEA0520658FD26E077D81CC98F27094F0AB44818ADA8B362B6B7AE4C2BB15762AEC55FD837FCE337FEB377FCE3EFFE6B5F2A7FDD1ED726AF6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A0B7896BB6D9AEB72116C388EA3DF1B553E05BEC918DAAA51C2F1E43082A94DDF21DF25C4CAD2AA495D8E3C4B68696564D88C78D6D62B926A41380C946EAA2367351B0F7C8DB2F0D50055346618DAF86B1E30C2AA7AE36BE1A82A146F886C7A6048852696F172DE98A784A64B1AAF5EA7A62BC255982D0D06F8AF0950E209D87CF10120F0A696686A36C0436C66192DBA1DBA6552722124FEDE2240E9ED951939312AB340C29B8391E69E1B647A78ADBF1EF4C8908BA46DB5848CE1C5284E57209137A2E836CCC428A5477CACB744BD434BB378594BD083E1954A5BB7443D074EB477A11403DF21C4E5420591431716F8874DB225CA8C29378D4505075C8916DDC48BB65A374DB0ADA6C232C36A615E3A44288D054A934C5B233B509551C6C0D7232E4DC0A10C04B0D866010DE3284DED6DD956B4191B65E222429077180C93C48F8684712363913365CD21D4D084954746072226BC34F9E7CCF02C124EED4249DA9F3C98935C9E37AF34B2B829F647519306DC3C91B49ECB467D52EE2855284EE49C375CDA31E2B2FA6BC83E4C86CA38E568D79F723227239F0C74F6EB4B13EA0DA8A17A1CA897240A4E96C569F0819598B2E1255C5B46801A6E3AE08C59C2242716691BF414A78E4D914D2283E3156D97240B4C85A36508CB452464F8DA4C54EDA89255892064E32B6990A446A33A3DABC22B475A0CC9C73A699C6C3E1FFCF3F2C7A51C978C8ACA63AFC3D7B66D304DD46AB1ECFCEAF30DB98DE4923015549DBBE6DB16EF2FAB86EC2259FD56E46B502999575B3AEE02A7CC7BE4830229631A9F6C242A91563DF224D32112570141BF6C226B54B4B81E3878969776AD7256B4B4B01D8E2B4FEC23FE71977FF9C6EFF9C7C3E3F96BE53FFBA3DAE4D0F6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A889788DF6CD7539086B99B8D6871A5538666618D2A20C8C0548E98D2A0E6FDE0A8FBB1A54BC2D1E871A540DC805F7F1C6954F9704AD37E98D3387344464BAEC298D37F120A6B794B7C24E34BC48A855900E5DBC71A5E257DA62140DD37271A5E24C625E031A5E256049231A5E2452AF2071A5E25F1435AEDF4E4834CF74CAD63A1F6C816706456895207BE51272E0CAADE1A2034E994C9CA8F25EE9C8D298C4ECD80A75A5C7521299125AA4CB9221146AB4F880DF2A2562CC7CAEB59D790DAB9025CB845EC16F10E4B45DBC731E5CDC880671A58A28DB22E6E309C2A0E75A77C5CB099451A918B021116F1FC74F1C5253A48A806D8B54954A2D3F8E2D9050E0B5A78E097272A28848158F4E9984425191A0414CAC8641A6A02476CAC86C0BD245515F0C810CC1A63DADCE1629187864405E37CFDE636699A6205687A64C313BB03B7D224BFB9E012A2B97458F876F5CF2D792A38E786478A8DC7C32333B2638A8BDE749D320B481005008194B7009FC50C75D862D8023046A0785316C010F20500E29A57B324134C2A426292B066C0D642A3CAD4A62D6421C5C145624EF5DB2C816B942D0525F173C589A65F02C0E379AFE66E996FAAE8570B40CE10D3F0CD9603BBACD5637E4D7E6158C9A7DFDCC0148018FF000CDE603B3CA6B31EEF25039027DF326F7757214D85F965D171A4E2BF2C99601BE3D3A65127231A9323576E9910C64A0C8D920C56A96AD0E58155D0035AE495FD83FF00CE337FEB37FF00CE3EFF00E6B6F2A7FDD1ED72618BDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A8F54702DC7305BD2695FD57E9424E2A898542F520E2A887914A15F11D71542A9AD452A7C7154BA7942494A6F8AA5D31323020D2B8AA22180135770569B8C5944EE8E411D28B8B6A1979198A114DBAE2AAF28F4D775E55F0C556DA71E4E7895A8C551EEEA829D7C062ABA08DA46240A0C55341198D6A472F962ADC13A92CBE99153D7161229DC101A06AFD19596704DECFED57C0F4CA24E5C198DB30740A053DF2993971E4ABE8947A7DAF7195B34F74A819650FD457A64496B3CD99C712CF2569C41A6C72B25B718671A0D9849148A139025CD84767AD58C01D5052847539496E8C7765768521A2952D4F0C0E66308812564340684EC3172404CE1734AF86282138B70052A7AEF4C5849368D948F0F6C5AA4B1C507DADB16D8286E7BF4380B9314744D4ED98A42551989208046F9590C8284C5BEEC810D810AEEDC0F6C8109972633AD4B5B765A9269D7234E3C4BCC24D39EE5DAA6B53D31AA72602D3FF2DE80AB74ACEA0EF5A530F139508BD86DECA389A3E294A0C04B394682747E08C7C3906B015ADA60E7885208DEB8B301184D462CC0404A18EDCA9E18B346D8802B5607160423FD440C7DB162434F32018B59096CD729E1B6374988492EAED549A0CB2326528B1CD465FADA3C4DF65D78D0E6CB049D5EAA2FCECFCE9D1E2B4D6AE233462E49047BD3377824F2BAB86EF96678C452C89D402733E06DD0E6145439004ED991170A4B8508AD29932C03741E19449C8C6DF25029C77C8863258789FD9C218A1D901AD053BE5A154591BB1A6495FD84FF00CE32FF00EB377FCE3E57AFFCAB5F29FF00DD1ED72618BDBF15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF89F0E3D33BE6370B90957306400773B63C2A893C9057A531A5414B39AF107738D2A6360038353D31E154BB508584E08FB23BE34A81F41BAF8634ADD1B74AFBE3C2A0A32D41F9E0E14F1353B32CAA4277A63C2BC49B7C0D082CBBE3C2BC484A537514C785789A1148F22D477C78578995C16E91C4848DC8EB8F0AF122B8464531E15E2524B74120A0EB919041DD3B55548C6525BA2BAD1AAF41E3BE5127320CD6CD78C60D329939514DA35E681B8D77CA645927FA70008DBE79592C3AB2FB280C8E1E9B1E99025CAC4377A3E8500E6A4FD39592EC71C5EA7A75B5694E990655453A11716DB172F105648A86A7BE2E5008C8F614C58108849CD7AF4C5A64994539D8E2D5269AE0B122BF2C5B20A911248AF42712E5453D8A9435CA2412BCD011E195C83243CCCBE34AE564360404C418A403C36C8D32E618B5E219BE06DFC31A6B1043DBE9C88EAC57E795C9BE019569D6D142438503DF2A2E4C4D0653115722831059C8D84C245063E98B00142301771D7BE2CC05766DB16C010ACA64AD0D08C595226D548A8AE2C486D890C77C5AC8519588077C2C084B26734EB954CA46C92DC826BBED8C249914B48F8C0FA7365824EAB54762F867F3DA0FF738E69DBFA66EF049E5B56777C797AA05CCBB53739B5C6E833F34BD97AE65479B8325C3651932C02ECA24E441AA0C88632688184315608BC47CB2D0AA4C8BE1D724AFEBEFFE719F6FF9C70FF9C7E1E1F96DE54FFBA3DAE4C317B6E2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88C69196127AED9570B9096DAC8649D09D80618F0AB26963050B571E15484A8697C287070AA610308CD41AF88C3C2ADCF2ACBFB1F11C78556B47C63E5C7B74C78552891B91200E27C7052A6FA64609DCD70213292D95E4A70A537AE0295CF6C586DB64789544DBB12AA13EC9DCF8E08CAD53386D49A129C6992B545CC68AA03538F6F1C6D54EDCB4A695C6D5368AD893CB9F4ED913BA2DB9A42B48C0DBC72A945BA324C34BB33248007EA6A4D328945CB8167013EAEA13EDD7BE5243951927DA622C90056D8D4E52609326436500120402BEF95CA34DB0C76F41D3AD38471ED94C8539B8F15335D2217F500029EF95172E269EA9A7A88E38EA2A69BE066237BA6E6207E2AEDE18B91134E238D3BF862DE26AF1C7CE9BF1C549B5AABF11F638B4C8A3D361F2C585371C7CBE2AD37C52364CED5796DE180B7C7226491D3F6EBF4640B3E25B27C3DEB4CAC864248095B96F5A65526D0508CFB78E479320503E887979D694ED9599B6844B5B86150DC699519338A6F6E802019592D802776D1D5280EFE3823CD289766E3403A65BC2B6A28581A15A0F1C7859892282961B1DCE3C2DA0A998985487EBD4E3C2C81B5D1A322B1E75A63C2B24BE49DCB9DBA63C2D6A4CEEFDE871E16B2859A1928183D699465145318DA477AF242A0D0B1390894CA0878F9B3A9A54115AE6C7049D4EAE3B3E30FCFBB7923D45AE78F2AEDC7EECDCE1C941E53571DDF1B6A16ACB3C8EC69CB7E3F3CDBE09ECE8B34774918D0D3C333625C1986E95EF97736B6CAD3BE5320DD02B9412064445245AF1193DF080BC2B0AB02464C15E1586363DF1B5E17F5F3FF38D029FF38E3FF38FE3C3F2DBCA9FF747B5CB03597B6E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D98A8B7639072125B39544C3E78AB27797F75F462A948156A62A88A30C554E163F584E5F67154E27E0D0D075A62AC7648CA82701546E95381285F7C8143339230D1864153DF2252A0A08201195211D0C695078D7C718F34A39A48047C76072C548AEC8E69C0D41EB8AA63A7C144E647CF154CE175AB8F7C082B1A1F524141D4E466CE2CA34AB6F488246F98F37331B2066569157282E4C59269F6CC5D4A8F848D865726639B34D32D97EB09C865322E6620F41855508551B28DB289976100C974992928A8DF2825917A04120E2A7C70B743927B6EDEA003B62D88958F93118B64516917100E2CC287A7F113E2716B3156040F9628E144C4B45DF7C578530B55EB812228A1CA83205B5425E546C8499452E7E54CA4B70429EA3C32259072FDA39410CC146A005699021B01B4CD015400E4086C0532B7978AD46301452792351CB76CBD00A2163E54DB61BE2CC145A41B74A571660AC922A0DB6C5B6254516BC875C5050BF54E4EE695C581287961E1DBA62D64A02694468478E63E50CE058FEA24BAA9032B8865296CA5C9A28E33C7AED99D846EEAB57C9F257FCE4246D0C493B2ECDDE9F2CDCE11B3CAEAB9BE25D56759642C050140299B6C01D0E61BB139012C69F4667E37026BD010287AE5E1A951BF865726C8AE465005722DA15D5D7EEC2AA9453BD3AE2AEE2BE18ABFAEAFF009C6BFF00D674FC82FF00CD71E55FFBA45AE5A39349E6F6BC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EBA9D962318514F1CA2DBD2086568E74237E4DBE36ACCE37F5223DB1B543A8E2F5EB4C6D51AC57D3E58DAA5F50581AD0D76C6D5305E4C8057E9C6D5053A108C08DBC71B5405BAFA73F20DBD712ACF6C6E8AA54A06DA943912944170E6BC403E195A15D2E022BD5474DB0412C76F2F19A4214D07B658AA96FCD8835E7E3ED8AB258A65861DE9B8E98AA5E977C653C68C09A9C5053DB39C33A92A0E426CE2CC6DD8351BA517A663CDCCC689854B5CA6F9417262F56D06C8488A37F63944CB7445A791C0F0DE2A28A8AF5CA497371067F6567249C7634A7DACC79173E316496561E8C80F224E524B221964638A281BED930D914DECE765A7C35C2CD3B81F93569D4E2D91473B6DD3166146353254D29BE285850F2229B62AAE8EE9B7018AA6768F4EA3AE2551ECCA83C72B2C908F286AED909328A11C8A74CA4B7041484006942476C052A51824824532B21368F8EB5DF61E390219829824818053B656436028F80A82141AD71884996C9BC4AAA011BE588053355AA29A52A77C5B01560CAA37C5982879248DC30AF4C59C4A0165547206F5C524A3519284FF375C5AC940DDAA052791C5812C62F1BE02C054A9E994E4512A414BC1EDD5C8A1F0C8C53C4E6712A20540420AE66E1165D76A4ECF9B3FE724B4F79FCBB1DD2C615947D91ED4CDCE10F35AA7E736A49E9BD1CD0F1155CDA61E4E833F349C0A0E43E23E199D8DD7CDD52DF115A13DB2F0D4D9A93D32B93645408F888AD37C8B6856403BB6154482B403962AA8154FED9C55FD75FFCE35FFEB3A7E417FE6B8F2AFF00DD22D72D1C9A4F37B5E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF876BBE87315C8485CF160DE06B8AB2DD364F561FA31555941018E2A88452D01F962A955584943E3B0C5538B771C77FBB156AE1D1D4A8EA70C552A02928F9E48A197589AAD3DB22528D63C72A4202EA7288287AE304B1A7959E5A7BE58A9D5BCAD12123BD3156E5D4491C4B6F8AA8C37039160D5A9C50591E9B745A5515EF909B38BD1ED5FECFB8CC79B998D3AB14E57287DF282E4C5ED7E598D43A46DE198D939B918D92DD411A5DA35075DB289173F10675A5BC7E94629BD331E45CF804DE8CCD551B786524B221388549550763DF2D8F2484DA24E00649926D6DDB16C8A3DFA62CC23ADE35E35F6C59D34235E67DF15A44FD5C374C569AF4590EDB602B4BDB91C8162A251B7ED909328A83A353AE525B8210A357A6053C9B58DC6FC71402AA0B1143B7BE408660AF5661DF2B219828BB695BD51BF6C88E6C89D936FAE84E35392620B23B5BB8E48802462D81AB89929B362D80A5227ABB0E58B3057AA826BE38A928D8CA804571604A1AEDD781DF16B258E3CF17C5191CB91A8CAE41ACC964482E3946A9B0ED8C42789A82CE732B2AA1E20666E1145C4D472795FE7CE96F2792E591A3FB009CDC610F39A97E4E6BCE5EF64A6C17E1A7CB3658DD06A39A5F08063DF3371BAF9B7407A65E393535C4572B9364541E262C48E9916D0B789185555436D8AABAAB53157F5DFF00F38D5FFACE7F903FF9AE3CABFF00748B5CB472693CDED7850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87BBB5531935DF31E9C863A543921B61ED8D2A6FA4DD324A200070AD2A7AE1A54E75173071F4C0656FB44E0A54C34F904B0716006DB61A54B2E222B72A00AA93D7052A342468952C41231A543955506452491B50F4C2020A1A83D415385871325D3E4F8B8F6E38299DA6373444E4BD7DF0708674C7EE1E4956941B1C1C20208A4BE38BF780B57E8C076502D386904501E00134E87236C8458C4B2C92CA6A00DFB640C99885A3AC80F4E466635076C788B194190E94DFBE06BDF2066CE117A759CCC4AF4D865129B9708B35F2E446F2ED44BB007F67283272A317B669F69F5495668EA76037E998F236E4420C87D2378E1CECC3F972B21CA86CCC749B3A471835AF7CA65172A136530C25187C35CAF80368926D1C2397235A9ED92029B446D328E20C37AFB6165C29A4302A01427E9C590D915C1586F5C520A362015401DF167C4E650096A9AE2BC48A85CED418AF1225959874FA3015E25AB6EFD5853293265C2E3180694EBB642526622AA2C95C7C24D72A25B4042B69D3A49CB882A0EF91E25217B5A3FECA60E363C28792D66542C62F8475A6478923642B46C3A46D8136B6349C3AF08CF23DCF4C40DD0648EB9B19446B21A863D874C953113455A7AB1A0E47638D33135D7771E9AFDADFDF1A6CE341C127AA58D7A0C04536C668E499D76FC7032E26A5BBE20107AE2C52A9EFA490F1DA98A0C6DD691722CF4E4D5D864A301269C9B328D32131373F4D4D7AD4648630A192470DBC70BCC8A0DC336E87A53333144071353C982FE6C68306B9E45BF515F552363C53C7369843CDEAA443F147CC3A4CB6DAC5F5B5C03188A4603E55CD96301D2651658DB22C5550DF2CCB8389382C415515CB9A0C5771CA6452154283414C900D814E445180AA9C6C4B71A6C3224A53058C507BE438D5FD727FCE36EDFF0038EBF9063C3F2E7CADFF00748B5CCA8F20D079BDA70A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8749E4AC447B652DE9347F131A77DB1557B6AC3386E9BE2AC8AE5C5C427F9A9B62AABA7B98D4027154C4C625607BF6C550579CA31C7BE2ABA08CC916E31415268087C5AD34B4E51B03F462D8134B97E51FD18B68415AA076901F0C05126A5B602A5464648097CC484653D32B6C4A963A927C7BE565B62B91FD30E3C4E218493CD1A4E532FCF2126507A969FBBA8F1198E5CB83D5FC9B6D5BAE9DF292E541ED92A18ADD683282E54026BA2C2EC39B0D8644B7443D0F4C8D782E5527222190C71AF31B641BC04C52104834EBD316F8A67142076F9E2C9305B72698AAB0B638AA323B7341B62C9CF6C7154C2DAD136DF154E560840F703014851692255F88019410DA95CF7766A08E601F1C810C9049AA5BC469EA8DBDF2B21B0228EAD1488C88E3938F872045325B15C4951591720C11C2E55455DD597B8C55DF5AB56EC98AAEF5ED88FD95F7184319206EAF2071C3D41926210735CC7140A43D77ED8B20C62FB52E4E141F6C5B137D2C92189E8C36C05B2298CAC1109C8B3B486F2EC28DCECB8ADB1A7D7218A5E25FA75C56D33B7F355A5BD393800E5B02C08B4DD3CFDA7A2D0381F4E49908D2D5F3FDB199B8C808E1B0AF7CBB1C9C6CF0B4A0F9D67BAB6BFB49B7826560A0FBE6CB14DD0EA30597E74FE7368325B6B97B7B04748A51C811E273638A7B3A2D462E12F9DA60F1BA07EE73371C9D76514887015A83C065D6E21E6B7204A40554FE1841D99A9C9D701296E28F7AF8E564AA37A0CAED5FD707FCE36FFEB3AFE41FFE6B9F2B7FDD22D733A1F48683CDED39243B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8739D15050D6994B7A56838C8A53A72DEB8AAACCDFBCF87C7154E2DE86024FDA036C551B6EBB6E37C551F1CA237523B763EF8AADBF40F1FA83ED1DF156ACE5E30D0D3962828D58E3937A5716B5748B7A1FB23A62D817CA6A287718B68528488CB15EF80A24AE5CB0C8C9012BBB4F877CADB12C8C1DC0CACB6C50EC84B1E58B0927DA3C6038206F5C849941EA7A38F526507AD36CC72E5C1EDFE4F83D39B95329939507AE9ACD1A2D3E119417371F2659A55BFA70F151DB225BE219469B190429D88CAA4E44427D6EAED3053F6720DE032686D01A6C698B604D52D1788A038A5328ED8F15DB6C5518966081B7CF1555312203418B2433E2ABE3623BD3155579F82925BA024E2AC5AFF5A8F81A380720437304BEBDB89598A49F09CAC8641266B8946E646FBF2B21B436BAB4F1FC21CFCF2B904AE3ADDCAF499BEF394B05875FBCA504E7E938AAD5F30DE29DE7A62A887F32DC471971354F4A610C648287CCB712CB4692B9260190C1AB4D31285AB45A818B30EB6E7753FC7B8AF6C5B1E81A7C451197A055DB0499DD35773908DB8DB22BC4F3ED56EE5A482BB0AE2BC4F2DBFBB732B166A11E18AF124536A2EE4297240E94CB20CE25080DECB25217600F8EF8934D9619058E9FA9F2462599BB1DE9928CF76899B67B67A56AB7118528294EC3336191C2C98ADE51F9ABE4D9A5D3EF649E127D0879A353BD333F164D9D06B70D17E7FDFAC4CD70B30FDF40E4474D86C7BE67E2C8F3DA914972492301EA50B77CCC8C9D613BABAEF4AE025B61BAB2004D3240ECCCB6F12D2A7224AAC0FC7E8CAC9558F3B76A7CB236AFEBAFFE71A8D7FE71CFF2049EA7F2E3CAA4FF00DC22D73610FA47B9A0F37B5E490EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87FBA8BD4048194B7B1D95BD16A1EB8AAAC3FBC353F3C553112FA6A476C553AB12255A8EF8AAF9E321AA3B74C5549AE015F4D8EF8AAC4AD76E871414E6D7B138B5A6C801E9E18B6042DC6DF3C5B52DF50A927C701449176CFEA353B646480985DD972841A74195B63152BC1C8EC0E565B62A4D4635F0C430927FA42FEF07EBC849941EA7A0445AE51BB0EB98F272E0F7DF2E22D40194C9CA83D12CB99611F5DF6CA0B9F886CCEB4D0C38AD3E8C89E4E44597E9F0FF00A415237DB2A939116530DA8F5850641BC06490460103C31649B2C6B4C551491B6D41B62A8D446A0F871569EDCD09A6E7164817B73BED8AA1243C176ED8AA4379764065AD6A08C55874D652DCEC95381B9520D0AE08355241C890C9171F961E43464A8F97F66565B0233FC191B293C7E2ED954F932E88197C9A00E998CC12CB8F2B8B78DA5E05F8761DF156297F6621AD206DBBD31563176EC6328B0B29AF5C218C90964D289B743D724C0335D3999E52A548F8716619DE89680B863D716C6573968D2918DFF6A980A4A4924C4F20FB7BE4516C475754653C37AD6B8ADBCDEE74C92791A83A9C56D42CFCB5732CDC1622E09EB4CB22764893D3347F216E924D1F1EFB8FECC848A99BD2EC7CA9630AA82AAC7AE40163C4CA6DF4AB5800E2829F2CCA84940619F99FE5A1A8F937549EDE1065F4986C3C01CCFC52D9D36BA1BBF1A35FD2CD96A5A84338E327ACDC54FF00AC7363864F27AD0C6648CC52943D466C205D213BAF4C9B978BBD156E393D0E36CA489BB4E2A3B57204A1219A52B5C892A8749F91A57A6564A1FD7F7FCE346FFF0038E3FF0038FE7C7F2DBCA9FF00747B5CD9E3FA47B9A4F37B6E4D0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88FE09E89206F986265C86217D18790FE1928CAD5640FE91DF2684C42ACA093B8C2A9DE95F01A1FB3E18AA6578547D8D81EB91B4A41229E7CB2064847C0EA29CB718612B2829FC7E888EAA37F1CBA835A26DDD016277DB225B0284E19CD17A65664DA103242114B30EBD30192D5AAE9FFDE644C9908B241CE489D4EE00E982D980C4F50B52AC59453DF06CD8024EBC91B89EF9125B238C1E6C93493FBD51DB2B914F000F5FD094ACC9C45052A731E45B601EE3E5621A401B7AE504B9B08BD5ECA14AAB22D189EB98B3951765860299FE9502D15996AD90E22DE22199E9F6D1FA9EA71F8CD2A7236DB10C9E1894B82474EF8B626B144ACE7E793114A611464B713D3C325C2153A8E3000DBA0D8E0E10AAAC0A8DBEFC7842AAB0F86BED8F085B40BF5C7842DA577708E2DC0531E15B62F3E9EF2B13C490712026D1765A5246DFDDED9512BC4C892DE355A7015A656496C125C88A29F08CAC96F8C95C01D29D72B2CEDC638DBED2D722634B4A0F676EC0D23049ED9548522987EABA7C6C5FF74BF2A0CA49626DE75A8E99C8B462314AF4A61848DEE903BD278F4708F511EF5CBEC32E109FDA69C435553E223AE3B278598E9903C34EC3BE1B09A4E652163241F88F5C8C9B211058B5DFED6FD6B9149800C6258DA4675AD47718B510A967A6C4CFF147518B512CE74AD3ECADD59961018904138AC4B2B49232B420500F9603BA69689A388D176AEFD71A452256FA9FB59206992716CF16A9A65E69B3012452C6FCA33DFE1399FA736EA759B97E31FE70E94BA6FE656B564578DAA3B3431781A939B9D3879AD6403C655A49EB34E794A5882DD36068336511B3A1C9000AA00074DB2B9158121176E55483DFBE52665CB8C6C29DF5C301B361E22A62C6E6766AF235C9B02104B38434069878583FB10FF9C653CBFE71BBFE71F1BC7F2D7CA67FEE4F6B9B087D23DCD079BDBF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8DAB09F719801BD8DDC8A4849EC77CB2294B5C736AA9CB1531B69285636FDADB0A19143FBB5AD7A60554F53D45627B602942BA77F0CA8A143D4DC01E38C0D154FE02C621E19719288A362069F3CACC9B045308E2046FF007E5664D822A7731064000E991253C2A7A7DB7EF3A64789908B2BB5B6AF30456B8F1331143EA7A627A65A831E26C1160A6CF94D41DB6C04B6C62CA746D3099936AF8E5722A43DA746D302F134DC65132CE01E9BE5C88ADC5076398F22E7630F63D1A20F22A1F1CC69F376388507A3D9C3C19401F4641B87366D610D29B6F8B6C53A4401C7862CD31B789CB123A65A392A610C3273C2AC8228C71507AD3155EF18A53BE2AD32EDFC715413AEF8AA19A307AFD38AB696D19EC36C0555BD140360065549010B22D180F7C810C8158401F3CAC86624B3991B9391E16C8C9DEB0C4C5B4168DC8405ABD3299452C72F6F1199878E6398A6AD875ECAA5C90054E400A4F0D2053E371B77C3C48643656C6B5A6D4DB1E254E12260BB63C4AB5A195C30F0C902DB89239AD253CBF56499C9237B57491B6A16C5A24995AC0C083DF16892730C8D1EC72405A225182E881D70F0B2B51376A49E477C7856D512ED36DFDB1E15B649A15D1127C3FEEC0CB4FA0E6660D9D6EAB72FCAFF00F9C90B196DBF342F66238A4AC493F7E6E74E5E73561F394A156460BF66B9B2076745946EA7FC72A996B886BD42A72AE6E643925D7331634C980892493DCFDA51DB6C980C4A56CE49D8E4C06A7F645FF38C1FFACD3FF38F1FF9ACFCA5FF00746B4CCD8F20D079BDCF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D880E040E87B66006F492FA2F88803AE5914A1C5B7186BC7E2F1CB108781585C46CDBAA9C2ACB15E3684803738154955A35663F6476C05285594BC9C6B55AF4CA8A157D052E2837C8F567109CDB3AA808D8993688A6B0C44B0A7D93DB2064D8229EFA01635A2D09CACC9B0456081581F86A720649E15D6F6AC1C7A6BC71E26422C9AC6D242D535A63C4CC4532BFD3CBC068B534C789988B036D34C731F82849C789B04597E8765C654257204B121EB9648B18400509198F32CE019C688A82652A286BB9CA497371F27B068CA81D582D0F8E5122E7E3E4CF6CCF29D2BD3C322DA39B36B4AF3F84D17B62DB14D56A5B03364368E811011BD284E5D1E4A9B200402A389F1C2A8F49102AEDBD3738AAE3221EA31543927715DBB62A82949036C550F473FB471556457A801A82BB9F6C555E458A31549BD4F639021925B35DB80CA2DD189E8DE190216D45EFA38AD889621EA53EDF7C810C4C92A4BB8DA29A46958B28F8129D72206EB19A0D2EA607D53C9D3F9299618B68CADB5ECB7069E87A71D3E2343944E0DB1C9691DD7EF83F01C58577198F28B609B1B78A560C492483F6B299C68365DA2ACEDDCC82BBE55C28675676A0AA80BF1531E154D52C588E98F0AAE5B1707A75D8E4A21B71A12EF4F2A84AAD0F8E58CE4C4E6B26939A96E2F5F84E2D1256787D2B16319E52C42AD20F018B449E6F79F9A5E52B099ACF51BD4B6B984F16151BE5916B2692D93F387C822A1B5B2BF223254BC4BED3F363F2FAE24A0D6D9B7DEB4C697899345E73F28DE11F53D5D2A7A02C31A5E2665E5DD574C9264F4F555256A428208DF2FC45C2D46EF833FE7278423F31E36DA482653507A13439B7D39741AB8BE3F6565BCB84635556345EC01CD903B3A2CA374422214625457B65536B8849677605E86832500E4C521B8B97527E3CB00625262EEECC791DCD7260312B94E4C06A7F64DFF0038C1FF00ACD3FF0038F1FF009ACFCA5FF746B4CCA8F2683CDEE7850EC55D8ABB155AE683E9C554F97B62AEE5ED8ABB97B62AEE5ED8ABB97B62AEE5ED8ABB97B62ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88BB53C866006F5971082E0D3BE5914A16E00488FCB2C42550D19E83AD76C2A98DBC844BC3DFA6054E2E29F56603BD3014A4515564CA8F3423C5C0420F7A65726DC7CD745704B8232B25C9AB6490DEA22A6E2B5CAC96C8C593433ACB1AEF9025B04535B4B70E188A1DB20649E14FAC6C55985464789970B281A7848C328C3C4D9108EB6D3DA78DAA2BB63C4CC063B71A3137205325129AA4EACB4A68DD6829824C4866305B32B2023B663C8B38B35D1A03EAA6D9492E6630F56B106109951E6E6C59D69DF100D81B073673A6FC4AA69D7BE2DB14E917E3C59A7D6B6C48461D0EF96C792A751A711BE155C57DF157703E38AB5F4E2A849BA62A82798462BBD71541B6A616B5AE2AC7F51F31D9C1192CC63A77C910D8C02F7F30F4BB763CB520A57AA93FD99590C0B179FF003C3CB167270BABC593DABFD99590D04A47A97FCE48793ED2A91852C47C27DFEEC111BB59953CAB56FF009CAA82DEE78DAC21A3AD1401FD99710C2390DA5F27FCE4A6BFA821FA8D89E0C09E407F665120DF1C858D45FF00391BAEDAFAED776C556BDC7F6663C839519BE91FC9EF3EBFE61426231805D4B961ED954837C256FA2AC7437AA9E3F4655C0DCC9EDB4C78CD48C3C0A9DC160481515C1C2AACFA79A834EF8914DD8D0379A79E1F7E06526177962A03963C585787BE2D1248D61963B1D453ABCB1B08FE74DB16893F32BF313F293CFDA8F9AB50BE8209A5B79A4668F8F402A7DF32314801C9A64C462FCACF385B6D73A4CF2D3BF13FD725B215D7F2EBCDF34CB1D9E893C751BB713D7EFC7657A0F977F243F30A7991E4967B343BD09A7F1C695F5FFE597E526B1A5DBC6DA96A0F34CAF5662D5D89E9D7251E6D1946CF1DFF009CCDF253680DA3EB11356474EBDFA1CDAE9CBA0D587E7F593C9373965D9DBAD73640ECE8B28DD16A7E07F1ED954DAE218BDCDC0124895E8694CBB1F26F88D9239EAE4E5A031921F8D065803595226876EB9301ADFD94FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A0F37BA6143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8294F845330037B52D4B29AF7CB2294AAF6BB8CB152D8D5830A547CB0B13C930854870DBD7C72122C2253953585ABBE54496C4A1BFBC6F9E441552641238567283AD7F86322299E306D98F967CADABF98AEE2B5B3B62C8C69EA01DB31CC9D8E385BEDAF227FCE2EC17515B5D6B32155900A293FB5BFBE5129B9F8F102F43D57FE716EDA2B988E9CF5403EC76FF89663CA65BBC10F25F35FE476B9E5FB932C687D193E1555ED4FA72066C7C10F3E5D0750B0B8F4E5571C4D0D7009A462A6616D632491014AF11BE59C4CFC20BCD9DC4428B551ED931309F0D012DB49CD59C50F8E094BB94C02636B1134F1C8711699C53368A452A791E9B60B6BA65DA0C94750C706CE442DEA763229E15DF289F3765879334D35C55476F0C8B7B3EB023E103618AA7D18AB0DB02DB27B16F8554F6197479330980DDC006A3C30A551862AAB18046E31545718986C82B4C585A57716ACD5E228322B691CDA75D716F8493BD32B2516F3FD674BD4DCBA4523A73040A1E99124A5E3BAE7E4DF9C35F467835BBB8977AAABD3F8E4F88A402F1CD4BFE71BFCE6F3D06AD732B576ABF5F9EF82D9D16357DFF38C5E757A97919DFF0098FF00B78B218D8A5C7FCE3179D43F22BCCAF4AFFB78F2639310E1427FD0B379CC48ACF6EBB1EE3FB720723891C459FF00973F203CD715C436F39F4A0604391B536F9E4253722185E97A27FCE37581BC59757B812AF2ABC2C6A0EFE15CA8CDCA8627D4BE51F22F97BCA10C49A3D9C5048ABC4B462808EFDF2A9CB67271E3A2F52B68AA828287C72102DE629D5BD9B4AA07877CB835909BC569E9815CAE4C0AAB428C0D08F837CA81B402424B733060D18415E95C2DC0B0ED474F6A973B835A0F0C5B0C424F1C216A196B4C5A6710105736314EDCC205E1B103BE0B21C59C2F9249756B69103CE352464F88B5F865298A6B78A5A450278D699602BE19661653F35154070DAF8659369F7D0DA144745FF4821547BE46CDACA1B6EC37FE7263C99179DFF2D64586D926BCB088C826A55C0E2C7AD7365A693A4D5C03F119A136BA9CF6922F131C8D191EEA48FE19B8C727439318B5194888DD21D890787B6DDB26402B080616EB44AB6EE6BC98F5C9844A21047ED1CB034C821DBBFD3930D12438DC9AE58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4F37B9E143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B535CC00DEAF28EF9645528BA1C8E58AA10C60B8AE2A5181789C045B590982FF7669E191314829431FDE36532D9BE22D52D2C9F52BE82D233467351F466365C941CCC18ACBF49BF21FC950E9D6105EDCDB2BD003C88F9E611CAEDB1617D71FE2ED0B4B8E21385E286813C0E512C8EC71E057B7FCCAD0EF6EE386270A76037CA2591BCE165F7369A4EAD6CF2CC527122FC209AD32BF111E03C475DFCB0B2D424966B78946E69B63E22F80F329BF2DEE609654856A17ED532D195071525571E49BB86BCD0ED93191071A437BE567442CEB4206DB6113B6AC90628BA7345395F7E98789C5945329ADB8462BD69D71B6BE156D224E33818F137462F48B49887515EC32B917618850679A4C84B2FBE06D7A3E9CDBAD76C5594DB8E4C3154E6D5C89197C32D1C9984DE13571852886FE38AAAC7D3154C228BBF638A6959A21DC74C82D21999882380CAD692C9ECFD53BA0A9DABE1919288EEE8ADE6B65F4924EA29838DC8F0D092DACA8793C8013D1BC31E36631A5773F003CAF01FA4E3C4D831B1E96F2047DEE86DEE72139ECCBC2B496EF568492A9722A7E798A7228D3282B5C489EAC373561D1413959C8DD1D3A274EB7964B80D2C859ABB2E40E46E1829E8D6914CC1226B6E117FBF48C8F1DB2963A65B6D6E11176AED96C0B5109D4238A82075CBAD810ACFCB8E5732D6425CED22568763D72B896043A38A39012454F8E49B6297DC5AF21257A0FB38B7249FA3958B6DF4E2D3916C1A423ACBCBB1DB22538B1F131ED53CBE8FCA87AE20B6F82C364D0258A60231C93A93938C97C047C505C5BAF43B6596BE026B6B0C976D645BED452127E583AB899B1D3D3AD2DC6ABA76B1A6CC39ACF6C63507DD48FE399D84D3A3D5C2DF87DF9F7E50FF0003F9EB50B20BC6970CF4A7F3B31CDB6296CE872E3A2F1CD4855D641FB4BBE650DDC7E4C4AE362C3C32C6322969FB67241A64876EFF004E581C7921C753963497F655FF0038BFFF00ACD1FF0038EFFF009ACBCA5FF746B4CBC72692F73C28762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B360BD730037A3E4A1E9DB2C8A529BB42C76CB10A50AF165A8A625211B55C622D8494E52786C77A8C998ECD60EE83BCF8AE9388A506F4CC2CFB39F845BD1FF2CB493A96BD68047CB8CAA6B4ED5CD5E59DBB7D3E3DDFA93A3D8B69DA6DABA0F4D1211555D8663176D8A2F2BD72D751D7353962B3321084B1504D32893B1C71D952DBCBBABE9EA26657046F5EF98F26FE009EE8DE78D5B41BD1CCC9344D45911892001DE99595107B868DE79D1B5B31AC92FA5310014069BE36930658D6A8E1DD40E128F81BC72C69945299F4A421AAA0D7C46581A0B0DD574359012117A1ED9312A6A9C5E51A9E83C2524201BF618789C69C58F5D69DC410476C789AB85274B5E126DF0D0F518F137C22CBB4752028356DFA9C376E5C0507A4E974053B7F98C2C9E83A6CA15803DA98AB288E7008A62A9AC2E480C3BF5CB63C998E49A42E69D4E14A395BA62AACADEFB62A9BDA5D536206D8B35F7373CA945A5720B4840ACDD09CACAD221232BD6BF3C84CA62375D2AF53D0E637139A12B9622FF0D49E5B6F8789B404A2EB492CA69DB071338B1A9BCBCCEE47106BED919CB66D88DD47FC2E3FDF43EECC4B6F115787CB8D1C8A40200ED902590A661A6E841543155A8F6CA8A788271E97A478D6A3C3082899B08E801D854E5F02E3109AA82A0153990C4869A471EF954CB590A2D2B32B0200C840DB54C25A4B89050903C32D6714C963F5A3DCD0A8DB16E4B64B295492010B5C5A72289825D8455A7ED655334DDA734BBEA32CA28687E782DC9E2583494460B201C9B71F2CB014F10448D060906EA3EEC9028E25F1796914F258FE9196C5C4CC2D36B6B45B53B2B03DC8EF97E39EEE9F518DF9A7FF0039C1E5223518FCCD15B8F4EE295217F9797539B2C32743A8C6FCE1BE9B8832EE55968066CF13AB9ECC50124B549CB4B594249D4E48354940F4CB038F2511D4E58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88089A86B9801BD338CD40F1CB22969E30C32C420D8713B6291CD6D4E4A00B1C8B58D46E69979AA681CD40FC7331F019ABD4BB4D353E9EFF009C74D21751D692A952B535A78669C9DDDDE101FA397F6CB6DA3D360563A01DF2120ECB0B7F96FE5B8F503777862ABD08AB0EDBF88CA661D96309BF99F4A3043246918E9D8663C8373C0752D0F50796436F096321A37C35DBEECAE99458DCB65AAF96E48EF4A4B50C0D02B78FCB101127D05E48F375D6BB6612E418CDA850BCB626B4F1CB0071E6CFEE66658C7BE594E34C149A525D1AA3AE46450030AD4EC83B31A6F91DDAA51613A958D0F4A6DD71DDA845864B6A56423EFC6CB7C629EE92854283D6B9747937067DA79A32E4959BE9FBB8FA31564A83718153C85A8A9F2DB2D076660A6B136DBE1B4A354EC3F1C2AAEA4D3154742E148AF862DC119556C8324C6DE256A74DB2B28559630B95CF92421D979661B900A87A7BF4C0CE25B30F2ED8B60696C4160481B74C05B224DAAFD487F2D7E8CACC5B812EFA90F0032042D9575FDD0E23E9CAC861C454DE124FA9D7DB214CA3225673F4CF4CB62C885C353111AB6E3A65CD65506A91C9DB2120C0B6F771D36DABD7238F9B44D0E675AD69972628BB797D571C7609D716F64B58A587871DE98B4CC162B7F21D31F8769872194E45C7612F87519A46A274F6C886EE229B44E646066D9874F96482F116416C22E23A64D788A756F2AAC4151030AF5CC989D98917BAA344D37488610E0E78BE6AFF009C9CFCBF4F347E5EEA73BC5FBCD3E2661B54FD963E199D824E83541F83FAA5A1856F216D9ADA5650A7AECC7B66EB09D9D0E6D8B0FEA58E5E5AC1D9072F7DF2516B9287ECF5ED96071E4A2A773963490FECABFE717FFF0059A3FE71DFFF00359794BFEE8D69978E4D279BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EB35F7CC572138A74DB2415A634196054B67900E44E487355B1CE38D2B96EC8282B9AB74F1CA665880A912F22CBDE99ABCE5CCC5B3EEAFF9C4EB113DD988815E25AB4DF6CD69767A626DF647999435D5A5BAB1D880403FC32B93BDD3F37B97962CD6D34832280ACD0EF414CA245DC621B30AD5A77B849A302A6A77CA2459494B4AD209812478C115DC951FD32316A1CD3AD5F49D15B4D91DCC3EAAA134655EB4F964993E64BFF300D235631DB30085C8F82806C7DB1453D5F45D7E4D52D54D6A683F56147084DE0BB3C9C4B4DB619645A728A49EE7799DFB1E992A68A627A944199EBD4EF8D2D30A9AD944BF3C6928AB440B28A61566BA79A30C559A58BFC43E8AE2A9F46FF10C55388EE00551E191BDD04A3A3BAA8EB8414A363B91B6FF003CB1B02312E47CE993661328DEB43E3DB16E099C4E38FF000C82A2606A656528D2A5C0A75C84D5BF4CE6310DA1A2877C890DB169537E99590E405754DC572239B656C98C511A74AE4E419C10D7111A1F7CA64E4001085780DFE9CC793090097CD7263A953F17860873681CD26B8D4E58EB5A6F97AC92A7BD9A405877E9938B4C9AB7BC9D09CB29A095433DDC8E4AD7010D68F82EEE0515D6BEF819C5368272159E9C69DF16F82223F307A4425457A62DD1016DF39D5F871FB4A28299092C804A6386EB4B928C84A9EE722C53D86EA3640CFF0068E2A98DBCF0D462A9EC13D221C3ECD76CCBC5C94A6B67744115CB1C2CE16F9AB4B1E63F2E6A1A4900FD7A090014FF00248CC9C45D06AE0FE76FF3A3CA4FE54FCC6D7347652AA9348C05283AB1F6CD96293CFE68EEF03BA6FDE483A10732E25A2B648E7152773BE5C1C69F35315000AE6445A96E5A036C407F661FF38BBFFACCFF00F38EDFF9AC7CA3FF00746B4CB43833FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B31D2B98AE426E47C3920A8694EDB6F9605482ED982BD01AF864952E86670D435F961B414D50730396D909A0370370B8907B7539AECCE5637DD7FF388F76A359642E05617A0AF7CD74C53B4D3737DAD359B5DEB30730410C280E63C9DEE9F9BD5EE3513A558B2745F4F8E5327718B9304B6D4629D679188EA69BE63C99496DDF9DEDB46B231B952D355547707C72316A1CDE15E63F38EA77F2C896933047A8A2939364C22DF48D42E6669E7E72173553D7157A56853DCE9A1622080682A715672D70DE9A3AB862FB900D72D838F991729E56E186EC7A81D726D2905FC25CA9FF277C558B5CDA9049A6D8AA95AA71931565567B32EF8AB2BB37A11BEDDCE2A9E46FF0010A9C55358CD40DF21D58946C792641191E58D811B1D6993661368998003C316F4D6273415E990423918D4532B294EED8065DF6F0C849513C465242789A2828720437464B553C7AE4087263255A002B4E9910376CB454520E3D69ED864DD0536219C0EA3C7289736F082BB1C50D3AF8E63C98C986DE4AC3950EE0E087368EAC3758BA99281493F2CBD125897130B346FDA66A11938B4C9111C92B15A6FEC32C0E396596B6D298D0AA924F51896B45C92C36A959402E3AAF7C8B6458E5FF99A0A18E21E9F0AF3AED8B7C5875C7984090BF30057662716F8A79A379A8C328726A95EBDB2052433C9FCC16DA94694515EE46458F0B514913505413E0315E14EED0C408E5F0FCF6C53C29D2CD1A2715229D46F97E33B302AD6F78A1BA81F4E4F89AA70B09B5AEA9CAE91030658C153FECB327149D36AF13F22FF00E7387C9B168FE686F3446800BE6259C0DAA6BDF3618E4F37A8C745F9A7786B7136D4F8B3638DD7C85256E09ED9787167CD408A66445A9665A1BA2FECC3FE7177FF00599FFE71DBFF00358F947FEE8D6996B813FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B33D37AE62B909B337C24788C2150E57E1396854A665FDE0C4AA4F29A4D5F7C802828E0F545DFC36C24A02E97EDB53C33132072B13EABFF009C5AD5E3B7F345BC6ED40411BF8D735F986CED34BCDFA88F12B6A36578375E20D730A4EF74FCD11E719DCE8F2CD16E6BC49CA64EE317278326AB710C14E5BF2E998F26526317AF79AA5F3210480A29918F36A1CD97683E45BBB86599E33C4D0D48C9B27A641E5FB0D360637340C47C18AB1BBFB6B494B7A43A74C550FA4A869DA222841A0CB60E3E6667058D09A8EBBE4DA503358061257F9B154A27D257D36FE98AA4034E546229DFAE2A9D5B5B22815C5536854290A3A0A62A9E47D302A2524A151E191EAC4A670CC7EFC90649847374CB1B022D26AE4D984E6396A06FB5316F098C6D5A64109A44C2A32B294D216A50D76AE4648298FAAA76C890805BE55CAC86D896F9656439112E26A322DD12A65C0EFF003C8C9C9C6D7D657A65126F086BA9818CF8E63C98C983EA32F10EC3C7A6087368EAC1AF2F19A4A7865E8936B7C562A1DF261A648ED37518849CA4DA996071E48ED7BF31F4AF2D69F25D4AEA0A834AFB62583E6AD6FF00E7226C2732CF030660C40A1FECC8B38A3BCB7E7A8FCCF6F73717527A224A7A5BD2B8B7C53237D1CC5E2AF348F7AE2DF1627A87E63C76529B0869198F6A0EF902D8032DF2B79D6FEEDC0E478B7BE4534F6FD0F5096499096DCE2B4F4225E5E1F175C5691261936A4DC76E95C9034D13E6EF425FF968FC71E26C10B08CB698D9D02B739240791AE64E29381AAC3B3E3CFF009CDAD163D5FF002CA3BF02B25A30634EBB54E6C71CDE57578F77E2BCF2195DE43FB44FE1B66DB0F27479051428EA3E79921C39A1E41B9F9E6445A90A577CB83745FD98FF00CE2EFF00EB337FCE3B7FE6B1F28FFDD1AD32C7027F51F7BDD7162EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87DB371502A2B98B4DF69C13D01C90554E3B7D19312094A275F8FF005609482B1EB8DA6F964225055E3625900049F0C9A014D110167327C238EC4FCB31F240B938E41EA3F935A8FE8AF31DB4AB2846332802BD413D7303340D3B3D2C85BF5FF4FBEFAC6876376AC1C7A43E319AF90A77DA722D34B906FF00CB573DDC3120663C8BB9C4367CFB35ACCF70B0202CDCF751D466392999A7A8E81E5AB7F53D69286408A48F0C62D319025EA16D3456B0085221D280E499DA4B7BA7C9A99268691EF418DA5E5DE60BA83439191E550D5FB24EF82D52DD0754FAE6A30B28E20FE396C0868CA1EC8564540C632011B31193B684ADC1624914DF738ADA94F1A985A8C09A614816C6CDB92C4D3BE282295046CBD01C55150EC77FC7154F22208EB8AAB2005AB9162533840A75C21923E351B64DB0146C69B64EC3208A89CF2A5698DB784EA17D86F90B54D616AD28722529AC6F414272242AA2CC01153898B0E0368F4DC546FF002C818B6C415F46F7CACC4B9116B953A9A7CF20634D91284B89000486195483978C84A4DC7C62AD4F7CA241C805B966AA1DFB65120C64C33569F843235413D86463CDA3917973DEF2BA615AEFD32FB6264159AF9A12ECC85815D864E2D5229249E6048924DC230AD01EB9686821F337E6C6A3ADEBF6F1D8D8A4A07A8DCD97B838086145E59E5AFCABD62E21ADDBBAF26E546FA0F8E459C43E91F2CF96E2D234B68AE18C92C207A2ABB9F7C69BA3B2AEA725EDB594AF65138918100537C5B8178FE9DE5BD66FF547BABE57ABBD547B64241B4483E92F2CE8A6CE18A886A06E70527883D934189F9AB73E86871A5E20F4069278F8904D3C7052F105C6ED89AB392DED80DB44B9B5F5BFF29B23BB91090554BE113C4C5AAA55AB5EDF3CC9C4D3A88D8D9E47F9E9A41F30FE5579801AC92C51B32C23AD02935A66C71BCAEB31905F8377711867B8848A18A46047FB239BAC3F4BCCE7152418076DBBE65C5C19858EBB9DB2F8B4A1580CB04806E8BFB2CFF9C5EFFD667FF9C76FFCD63E51FF00BA35A65A393813FA8FBDEE9858BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF874B265328CA593246507853C72259C513C07139596D0935D28562721D5279311BC929375CBA1C9A24BE0B90268E872F8F26013B9650F1EE72126FC68DD12FDAC351B5B98DB8B472015F6CC2CE36761A73BBF5CBF267CCA9AFF966D6D24903148C0A66AB287A1D2C9EF3A5AA3C9FA30AF10FBD735D91E8714B6615AEF96C695E6084C43E0998548F7CA29A739B7B3E89E598CC6B3247EA19D0034DE996403878B9B2EFF095959C5F5ABB70AA054A9C910E482F39F3AF9B340D26C192C028B85560E57B900D32B21982F8EB53D425F345F4CD2A91463C09F9E565B014C740B2D46CEEC39AF18D870F964E0C66FA4B4DB8379651ACB27C400D8E5B17166956A21E262886AA456B9634F54B2332383B6581C8835E9301B8DF0144D690475C0C694FF6CE2B48F85C01F2C569188D520D698AD2650B50628A4D633D314D23636DBE58A8B6D1C73A62E60E49A44FD37EF8A53BB6906D8AA64241B6298F36CB0241CB9C9149B5ACC1471AD2BB656BB2600823AE40ADA1A7038B37865534DA493C828731CB740A4B3C94AD3AE51272E054DAE1BD322BDB2892C8B17BEFDE73E7D32B71E658826968D7264A7535C21A2D327D2BD40401D475CC88AA42FE528A69099146F99015747E43B157E7243EA03D0787E38C92194DAF9574C8900FAA8DBDB20C9CFE5AD3CCA812D40F1DB154F57C91A75C45536C3953C3FB714A4375F9736C2559628F804EBFE75C8948445AF97520223A74C0A9FDBE962CF7036AD4E2A9DA32BC746C550727A49B03912CFA2025B845DAA3DB20D40EE827B9574702868466463E4E55EC93F9C6E3D6F27F986253F11B4947FC21CD962745AE2377E0879810C7ADEAA87AACEFFF001239B6C3C9E3B55F594A17F8E67637026B24077FD796171D02EBBE5526E0FECABFE717BFF599FF00E71DBFF358F947FEE8D6999D0FA47B9D7E4FA8FBDEE99260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF861D3DE432034DBC72964CB565278537DF2259C51C6600152C2BE19516D093DDB13CBDF23D5279308D403ACA3623C32E8726892193D65742548F039911E4C03258F9B415E276CAE4DF8D49039755A94A1AD7E5989945873B0BEE7FF9C71F39AD95CC3652DE0EC3893F3CD7658BBAD34E8BF49F4D9C4C12F512944AAC9E39AEC90779872A6B75045AA442EA420CF17D95EFB653C2CF24AD9FF94B596B3B6953D1FAC49C6853BA8F1C9014D111458679F7CD173E94886630F20691FDF890DC0BE62BB6B9D42E984E8E6366F858F7A9C810CC1645A779360216644E04EF9510CC1640DA298978C49CDA9BD30C42C98F1D46F6C2F56DDB946A4F4CB22E3CDE84B492C83BB0666DF2D69EA81876276DB261C88372321620900D3A602C8A0E414DFB604521F73B8FBF15A5652C3A0C5691F1F2A2FEBC56933849A5295C569348C9D85715A46AB506FF004E290162960DD3E9C5BC724C627A002B4F1C529DDB38DA8698AA6AA4F615C5239ABA1EE72E6DB541280CA396F5DB2056D324B903E127E2CAD6D7CF23189FC29D72A9A82C7AE255E81B7F0CC72DF0293DC39505A9D3289B95028069DE9D0D3C7289A494AAE999D08A6F5DF2B699157B5B55600D37C21A93AB6B3ABD38D76DF3222AAB3D8AEC547CF3202A360B3429B10580F881C64C8223EAE9F6792FCB20C913069A240EC08057ECE2AEE735BBF02E062A8EE64C4C18862DD32254242E8166AB0A6F812A978C161AFE38AA412DD98E062AD52062AC4DB54B862C0D46E72126CE88492FE43B16A6443472288B5B8E714A7957A664636F32F4A035894C9A16BEA4D57EAD257FE04E6CB13A0D74DF86DE6D503CCFAE85DC0B96A7DE736D8793C9EA0DC98F053E199D8DC19B9CAD3AEF96171D06E2A76CAA4DC1FD92FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD333A1F48F73AFC9F51F7BDCF24C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85DD35C96DF2964CB6023E1F9E44B20BA47FDE1DFBE5526E081BC7A2935E8323D527930FD45CB4887BE5D0E4D1253673CE1073223C9806516854C237CAE4DF8D12618E343336FDB31E4E66366BE45D767D175482E623455606BF7E61E58BB1C137EB17E5579EA1D734AB485E60D23280457E7EF9ADC917738723DF2D678ECAE638E75062946C7B6F94F0B9B1DD1535D496978CF6BF0C53281B63C283B21750D223D6007B800D7C7224282803E4ED387A4428AAE4086C05192E8F15BC5C621B814C810CC1632F697AB3858A22EA7A90322366576C7353F2BDE5CDCA4E632287241A26C820B0921B658DF7232D691CD4A5B431C6C476C9872209210DC8961BE02D94A72313B605E15200814C5695D6BBE2B48D4278A8F6C578531B76E9B62BC29B420938AD261E9B1FA714D2F119FA462D815D63DE98A53680D0818AA6F149414EB8AAE6980D89CB99F12D5605948EC6B5CACAF12A7D6292EE77C815E245CD755888F11954D416352CE7D43ED98E5BA086B89B92F1F1CA66E5C4A5D24C146E731E4A4A57713165F8776AE56D5229B69DCDA95C218B2AB5421AA4F514CC88AA37EAE5F71D33202A8C917A2373C6BB63264103FBB06A64A78E4192610DD451A37192BE3BE2A96DC319E4E4B21A0C551714AF1B202D514C894847CBE93A87D8918158F6AB72681074A74C55894D73C636538AB16B9999559972326D1F4A4C2EE477A1AD322E393BA716F70638580EAC4664636523B286BB2341E5FD79D8F10D6B21DFFD439B1C4F39AF93F11BCC8E24F30EB0E0D435C3107E939B5C3C9E6729B293667637126A2CB5AE5A5C7502BBE5526E0FEC8BFE7183FF0059A7FE71E3FF00359794BFEE8D6999D0FA47B9D7E4FA8FBDEE79260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85EB109D5771E394B24EE19497451D3950E44B208D724C840F1CAA4DC1037B50A4378647AA4F263B7B18AC6C72E872689206EC51A2653D32F8F26B08F82E48A440FEF295E39093918D3FB23F595759AA225EA7FCAED94172E299412FD5A2223FB75F8328C9172B1CA9F48FE507E663685756D0DE5D985C90B1A13B577F7CD7648D3B4C3983F4F342F325A6BDA35B5C3DC235D7006300824FE398C767698B202C860D46692358E54A18B704E0B05BA62D35B6BD77DBA0C890C63128A79D8107964086D102AC932B00246DBB9C898ADD2296EE2B643E8C425E5BB31ED95914CE3BA167D4A2991B946108F6C431940B13BCBC049111AD32624D3E19B4ABEB13382AC2993130DD114974E3892186F8DDB6092041DCD46D8AF12E6EA4D36F1C57897091456A715E2565993615C578C2656CEA69EF8AF104EEDA4407738A6C27B132151BE295540189A62CD1023351B7D38AA24232D0914C55148DD29D31559373AEC32DB544DB9A0F8BE9C812869C7C7C874F1CAC94B6F229000395CCDA84AA68DB996A6DDCE63B7C36414CE95A577CA66E540A45792D09DEA331E6C88B41C2FCE4006E7C32B6B9448DD9259C81283A64C45AF8939FAD3715E0475DF2E0BC4135B7BD2A9566CBC49788295C6A1137DA3CA9D4612CE26D8F5F6A9044A5AAAB4DF761FD723C2CE982EA5E7AB3B105566524D796E36FC71E15A63C9F9AB6B1D47A8A5BE63FAE34B4A4DF9AE92238128592BFBB507AFE39190544695F99324B308EE25A027615FEDC8D26DE956DA8C1A8C0662D56E831A5B63BA93FC7C23A927B531A543456723C3FBD4A313F86464D8262A90ADA70462426F91693024ECB5ADCAA0929448D8733E19763906194F0879FFE736BA343F26EA571EA7A69776AE96EDFCCC54803EFCD86298797D76404BF1AE617524D2CB74BC6791D9A415AFED1CDBE290AD9D1CE24EEA7C18F419990C81C498A5AE8C06E2872EE305C7A52E058ECB5CACEEDC1FD8DFF00CE308A7FCE35FF00CE3C8F0FCB3F290FFB935AE67C3E91EE75D93EA3EF7B964983B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BD3BEC652C938B6FEF53FD6C89641399500ABE5526E090DF3B32B11D40C8F549E4C7AFDE4E31FE397439344905217668C78E644793584C2C406BA27F9475CAE4E4637A6796B49FAFD95DBA0E455AB94D5B951E4C7EF266B5BC6B775A50D304A2CC4D7C26EBD7496194C7E97C48D5EF985931B918B23EA0FCA5FCDFD5B48BEB6B6D4EF19AD9481F131A537F139833C4EDB06601FA51E59F3FF9775DB2B764950C8CA3910457F5E53C1C2EC6192DE8D0C7672422789AA08AED91B72E050F34C84A88C74FB59025BC6ED2C8DF3F0C899354A289496A8CBD2BDB21236CF0C50922D011E390A6E314BA4B22416A634D44255246633BF638D3021033905B7F0E996C5ACA0682B5C92AC734247E18AA8337BFCF1572B74FD78B594CEDA6A0A62D914EADE652462CC325B6605462D89B4282A3BD71668EE031558ED8AB68DD3C3155772A77C9AD2989950100E56534A46707A9C84969A1254D474CA8A40DD648F5539516D8A4B350354E5126F821258048390DC0CA26DF14B638945C71E5C4D3AE463CD728B8A6358E05E4641B75DF2C70F850ADAC5B16E0660BC4D6B5C9C53C0D4FE71D2ACA2224B95A8F7FEDCB578581EB3F9B1A3DAC4FC640C4D42D3C7EFC945B2029F38F9ABF379DE597D19DD63A9E95FEB926C7906A1F99CD71EA52E9AABD4127FAE2AC557F301DE46ADD356BE3FDB8AA656BE75BD915E4B79CB2A1A36FDFEFC8C9059D7947CED24B7F18BB6661C803D7FAE455F61F973CE960B68891EE0EED5F1C559347E6182E6752B106A9C55939B95940658F8823A64486A3CD0CEF5AFC19590E4C64A2FE9B2FA4C2866EDF2C9C22E0EAA5B3E40FF9CA7F308B7D046911BFC71A9F86BF3CCEC71793D61DDF9A864E681D8FC4D527375861E975929521B91AEDE399020E26492E33A13C5B7236CB40A68B4D2CE28A4EAB9600DA0BFB03FF009C6A017FE71CBF2000E83F2DFCAA07FDC22D73363C83AFC9F51F7BDB324C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85CD3C715A1EB94B24E228DC303B75A8C896514F44323C058D3EFCA8B70499EDCB24B5A647AA4F2492F638CAAFF91F6B2E87268925A5E07F8D2B48F63F4E6447935854B3E4B73327ED15247DD95C9C8C6FA0BF26AC66D5D2F6D22512486A287A6541C8E8C6FCFDA1A586A5710950B75093EA0ED936B32A79F192E1220A4D2A39291954A1698CD562D4A485158BB2C8A762329389CFC59DEF9E40FCD2BDD0960334F2B46E42F52694FA7313538A83B3D36A1F767917F3C6C350B782092EC06A00431A78660183B5C595F44693E60D3F558D7D39939103BF8E53214E7C260B295B66E21832303D286B94CB666775DE8488EA781A1F6C31DD944D35246EC6A23603B922992A64648A11A98B8820B569418D06B24062FABC2D683D4996887A531A6B25884B751B92C84D0F8E16050F57FB5514C285BEA57BEF8AA9B9F7F962AEE42837C5ACA2612716C8A3A17756152298B30CB2CE71C455B16C64115C28A55A9418B3470B943D0E2AE3206E877C55B57A0F7C5548CFC07C677C9B6D20649CB37C26801CACAAAC659B71D32125562DC76AEE72A2AB7983515DF2A2CA2955F3D15941F88D29944B937C1A8A4021F8CEF4CA26DF1631A9DD7A3C9D1A86B4C8C39B29724A9EEE49E3203354E58D54C4758B3D4562F5226DCB5363BE4E2B4C2A5D0754BE722494F1EF56396AD05A7C8B6654FD61CBB1EC7A64A2B4935E7E5C79767564907C4C3C324AC0F51FC93D2262CF6E7883526BB62A935B7E45D8FA9B9A927AE2ACCB4AFC83B510CCFEA705E42A323241677A0FE53E83A5C81A62A597C722AF51B0F2BE90CEA96BB1514A2F4C55153583E99708A895DF638AB2386FDFD3459051FC3034CB9A2D6E19876C8F0AF1D34D342CF1CA4F1FAA2B35D7CBAED9918A3BB81AAC9B3F327FE7257CD967AF79AEF2D74D9DA48E0E4AEAFB6E2BD33638F1BCDEA4D97C82C5D763D3B66E30C7D2EA66511000C4572DE4E24CA356D6126BFB44EF86D880C92C2CE20061E26F8C5FD757FCE3780BFF0038EFF90AA3A2FE5D79580FA349B5CCE87D21D764FA8FBDED19260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BB6F848AE52C9904352B5F0C896514D3D7E36C77CA8B704AE3943AC9BEF91EA93C921BBFB2FF004E5D0E4D124854D2198FF94BFAF2F8F2601358471B966F18FF0086424DF8DF5BFF00CE24D8A6A7E63B9B6715564634F7198F234E544585BF9F9E5A934FD775396342055B7FBB1136B9C1F3100C614E4370B96036D06C20E54F8078D72756DB09334D247FA1C629B9EF9467C761CCC597853D827BFD3254B8B6BE642A6A141CC09E27698350F58F2A7E73EBFA4DC470CF3B988951CABE14CC49E276F872BECDF23FE7858DD476EB3DD8694815527E5ED9893839A26FA16D3F306DEFE28A55911380A28AF5FC32318A99D2723CCC6F10233A229FDAC970A0E54AEEB5C834C9030BD578C8E4C6BDF1E16A395E4DE74FCD485A64B586753DB63FD98F0B039103A66BAD7D124BCEBCBC30726C89B4F45EB1A2F2DCE2CD1092357AE2A88F888EB8AA834850D3C31605562B923BE2CE2895B86AD6BD716613AB4BB7000AF5C5B03238AF8FC3BEF4C59A651DD934DFAE2A9925C57BE2A89593E1FA314C79A065763BD726DF4A22BD7E9CACAF0AAACC13BE424BC2E6B8AFC43B6545045209AFB8BF5CA8AC50571741DAA4F5CA64DF04BE7D43802AA731E6DF148E59BD77A3FD9AD4E461CD390D04F6CCD998C291BD32C71B8D4EE6D2240640BCD5B6E3FC72617898FB58A732E4045EF962F1A51A8CB688AA88FF001D77C9C59C656C3A7748E4E6D27C35AE49938EB9A728547DC8C55522D734F520C7154FCB154C63F30B49F0C44411FED29DAB91920A5375AAF2B9553217A9ED9157A77945B99568C1E05A8D5F1C559B798AC80B713AA0E406F8ABCDE3D44F221CD181A53080E3CCA6D1EA238F5C20346495060DF999E7087CAFE5C17AB2859EED1C15AEFD08CCCC31757A89D87E54F99EE6EB5CF30EA3A93312B2B311F4939B5C50D9D266365881B52546D999195075F38DABDB5A9EC3194DA2504F60B08D8AF8F7CACE4651C4CBAC3490C071E9E190395CA8627F58BFF38EE9E9FF00CE3F7E45C7FEFBFCBDF2C2FDDA55B0CDCE23708FB83A3CC2B24BDE5EC59635BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85884F361C76CAF8536C96DC111904D6A301816424D4A58C5C075A65462CC6441C41E1560CA5C9E80654765394525D76A423B31095ECD96E336D12CA18F05E69242AC0B484107B6C733230348134E0FC0EA6849910814F964278C86F84DF60FF00CE1AFA8BE6C997890CB5427B6F98594539D8657B3DBBFE720B44F56E352AA8320526BF40CC7E2A679214FCFAD422F413895A713C4E591CAE14F6485D8351286B5CCA84C14464F40D0A20D0C709A127BE3964006F88E264377A544A16AC797E19892C81CEC008418B78D5951D6BE04662642EDF164A099E9E2EED2E565B29CA1435A1398920E58D500F50B0FCCBD6A0F4E192770F0ECBC4ED4F7DB2996CCBF3024CDED7F37358E01259E4E245363FD991B41CAA7A97E61EA7771FA705CCD461B963FD98DB0F1187DA6A375A8DFA09E4919F97DAED8DB1337D27E58965B5B3854B971D70F0DB958A7419A457ACD2AB576F0C781B78D90C37CB51F153E79122990926B15CABAECE3E9C090B6491493DCF8E282143D555F1F962C86C8859EB4A57DB1640A696D24840DF167C4C82094556B5C53E204EA09169DF14F1A3A19949FB58A414DE27523ED8F962C816DD4788A0C9B68CA165630A41EB4D8E40848CA12C9E4E3FB5F3C810CB8D086E9551AB5395485053249E694B3F2076F0CA0C911507B8526B5E998F2986E8EC954D3879295CA8FA999CA229B69D6F1CF22ABF422A708853564D4090A6616FA65804AFC5CA985C7F1107776E2353E99A8EC3240AF88C3AFC4EA181A508E8327C6BE2306BCB3672F20635EA41CB319B6DC79186DFC7292CA49A65DC2DBE284858411732558B1E95C7857C5097FE9178643C5453DF1E14F8A11BF5DFAF71E6CD13A0A2F1E87E795CC5309660CAF42B41EAA34BFBDDF6AE52649196DEDBA3AC91C6A21554A374C1E2065C69DEB17D722C9A3908269D7263763E2878E3CB28B89030DEB52C3A53261C7C99022CDF47042D34AFC238FED13964604B87972BE3AFCEAF345C799357B8D2F4F98FD4ECA80723B1AD6B4CD861C6EAB3650F99E6B7BA8AF3882BE99D9877CD9E3141D5E49A0EE2DC076006C3265C594952DA2A76CAE450236CA34DB28E591405353D7316526F8637AF68BA242630596BB6527239718BFA78FC884117E47FE4D443611F91BCBAA07B0D32DC674FA7FEEE3EE1F73CBEA3FBD97BCFDEF56CB9A5D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF858B4FB432AE36EF0D94C1F6457A77C789061488210F4C89DD81539220637E0C15E9F0B7865660C244524D756F13A52693D47F019761C6E31905B67E5ABED43F756D68EAAFB89E9B0A66C61065198B425DE8B7BA7DD4114CFD036D95640E66220BEC4FF9C378DD7CE37019830E62A335D99D8E10017D63F9B7A7A6A3AB6A7005E47D36DBE8198526DCA6DF997E77B23A6EAD25AB0E2A0D7200D38138B07922A10C33271C9AC459B79526E573E9B7602992CC6C3958B67A75E5A7308CA3A8CC493B0C692359B89375DF28C8E6C792BD9C6E26238E63C925131C00CEC5C5083B644C6D946549998D5694C1C0CB8D1B1395E31815AEF8F02F1BD5FCABE5F49D16764F8BAE3C0BC4F5AD3A16810474D94ED86A9CAC4764E919B983F7E25B814DE201A8CCD4272A93644A690F1029C8E41B0146FAD40003B0C5928B4FEF8A559273F0D4F862A9A5B5DD286B8109DC57CA08DF0B105358F50403ED7CF16C051297B08228F8B3051E9A8A01B3F4E98B3B6CEAC4FED64896622B7F4913DF205988A067BD249F8B204B608A0FEB47725B6CAA6526282B8BC201A1CC599445269AF5FB5731E4DBD17DAFA93480F63928868996716303222B74DB2E1071AF74EA3770295230F84B6A53B32AF23BD71F097898EDED5C1F871F096D8D4F0121885EBD72CC71A6C81B63B77A6990310BB9AE5CDAC12FF4AB80CDC50D0F4C558EC9A3DE3BEC877F6C551B65A2DE8956B1B52BB653910636F54D134C962319910E6290D9183D46C42C7C05295DE980067253D7A655B76DFB665422E34CBC8AE2ED959C0FB3FCD968838939879279F7CD7E8594D630B9591C1008F7AE5F8E0E1E49BE6986D2E66B998CE4C8EC49673EF99D8F675D96492EA9A6709AA13BE65C4B8336373E9D234AD45EF84968E04759E8D2B015427299C9B61167BA2E84EAF1931F5CC6939110F67D1F4BE318F87B65326F8BFA35FC955E1F937F94A9FCBE4CD047DDA7419D5E9BFBA87B87DCF29A9FEF67EF3F7BD372E69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF855B670AC2A330CB984B2785D5A23C4EE46C300938D3C8037146EC0D640A57B1EA73271C6DC59E7013FD17CBB7FAEB98A106353D588EB9991D3B85A8D50112F59D1BF2CACE1557BF01993724E5F8F03A39768B3EB2B0D26C08B45317A454D401F16C3C732BC3D971F68BE7EFCC1D3E117D1DCDBB5631C8041D7BE60E78D3B9D2EB789F437FCE1B5928F37DC48C4A6FCAADEDDB35595DFE973F117D6DE76B8853CCBA848F19742AC38FDD98530EC4EEFCF4FCE7D0AE26D50DF5BC263889E5D3AF4DB292D5283C3230655657431B275AF7CB612A6A31A651E578C9BE1C5A94A65933619E30F7148792460EFB653273F1AF4B1ABB029C89E87C3289B9B16EDB4CFF004A3F0F5F6CC7924A3C6845A6E741D7A530C5814DA3F2DB4D4A2D3DE99246E9B59F955DAE230141A7B62BBBD7748D35ACA255DABE00615B2C9238C83C9969ED95973709D912B1FC4081F31912E48298C7C788D8E552660A2D08A743EF90660AA7A95D80E9D31656EE05BF6A98A6D772A7C35E9B62B6898A4E3D4D7145A244DDF9D315B442DD11D1B1640A3E1B84A8AB6F8B65A6D1DC42109A9E98B3077524BA534DFE5809724144FAE0A9A1A6DB6449660A02595BFDF832A25B0150FAD71DB9572B994CCEC8692E958D28731A4D112BE38BD42083D7B656D97B325D36D5415240F965D8E2D332CC15408C00287C732E107189B2B7E207ED5465BC010A95E638B0AE3C0150B2DB07E8B8F00543A699CF9D453C32328D3762431D138B54D18785320DE8693CBF0CE45502D3C7156E2F295B83560A47CB154CE0F2E598707D351C4F865536704CA6D16085032D001945365A47724C33A90A7805EA3C7271834E4C94C63CC5A8C0B6EDC9E840DF3371E375B9333C3755D61A4574B67F1ABE640C4E064CFBBC875ED367D4A61297F881DC9C988538F3C96A56DA488630CD1737237232D8871A52B492FF00449A798BAC3B78658254D2425FFE1E666DE2A1F9644CD90C6C86C3CBDC40AC5DBC321C4D831B38D3F468D387EEF7A6F9592D822CEAD2C5234038819596603F7D7F27871FCA4FCAD5F0F286883FE9C21CEAB4FF00DD47DC3EE792D4FF007B3F79FBDE8D9734BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF84F5A9238F5CAA50699EA135805C2D19413C7A0F1CA841D7E5D4BD77C9FE4C9F5955BAB9531A36FB8A7F0CDAE9B15BABCBABA7B25BC363E568B8428AD2D3E13B75CDC474FE975F9B54642929D43CD1733551578D7C3251C4EA660B1C79EEA4E530908600D30CE1B231715A437D65F5A82269F76DFAE6A75317A5D04097D2BFF38A5603FC513C69B50F519A5C8F59A4818BDF3F32C8B6D7EE550D4EF503E8CC4C8EDA06DE35E6CD274ED634C8E1745F5C2F2DC6FDB31645BC45F0F79C3499F4CD4E482088842DD40C6326A9C55BCB703DBDDC25B66722B97036C22FA334EB45963889EE06093998D91DB69F1FA87E1AE5191CD8F245DB5845F5ADD46512E6929EC1A746D253877F0C8DD2631B66365A3C2101283071B2E0641A7E9B6AB2F22A0536C7897813496D944AA517E11D71E35E0463C28C415E94186DB63B2E580602DA0AA88B88F6F0CAA4DA0B74A641902A65A84D3164D09A9D7155F50686BD77C55DCC0DB90C554DA6A54F2C516A26EE9D1B16C06D552F883F6B0330518BA937F37E3859834AE97F4FDACAC96C1345AEA15523976C812CC4D4DAF474E5BE544B671A88B82CD4E5D72124CA7B2AAB0E42A7BE504B18B23B331FC3B8C039B6B27B39A35A6F9978A2D190A73F5D8F8D2BBF6CCBAA71495CB728DB636BC4ACB301B8F9636BC498DB3ABF518DAF126255154103AE4265C8C25AA467ED0CADC97048491B0C5556910EE31550692256A823DF2B9ADD216EEF23E34AE5643194D846AFA82420B33058E952C72EC637703365781F99FCDF662678397A8A4D0919B2C7074D9B3BCEE7D5EC0C9584D10EFF004E6588389E2DAFB7F4AF4811906B80C11C68897479C39A3D01E8BE19514A9FE8B71F69B204A695974DA007803EF4CA8C9CA84764C6DED78EDC0636CF85905B45180BF08069BE368213650028A0FA3157EEEFE50FFE4A6FCAFF00FC04B44FFA80873A8D3FF771F70FB9E4753FDECFFAC7EF7A265CD0EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85F8ECA6827585979C84FD919084FC474B9674F6CF29F906F35036D773218A18D833A95FB437DB719B1C3A1E274FA8D43DA2E0C763686D6D2216DC06CE3BE6D30E8F81D5CF2F11610F34D76CEB212EC8767CCC3300535006ED2AB986E56455F4CB03FB54CC7F1699CB7539675B32AB335030DEBB532B9E76EC1877633ABEBD05BC4817E3095DEBE39AFCDEA7A8D0E301F49FFCE3379B34BD275C3753CAABF58466DC81C4F875CD5E6C342DE931914F72F3ADEC17BACC9A94171F5A4B9DFD21FB35CD7CE36E44254F2DD5E40F74AC253188D3E28FDB31A78CB951C8F3BD4BCA69E67B826C23334CBD471FEC395F0D322049E6DA8F93752D03518E4BC89E28D5BEC95207DF4C2254C6389EA9A33F3B58E48979851B8C4CDC884699569EEACE6BD5FF000CA652722324EBD158255940E61BB6545927D6AB1D43EDBEE47865728DB644D32A8A7884600F0C1C0CC4ADAFAC952283BE3C0DD18DB27B39964B73CA3DE9F6B1E06C186DD1A90A6A77A9C9C62D528515707AED84848D950380A2A37CAA41902A4CC7B0FA3214CC490EC549353438190921A42AB53CB14F1297390814AD3B62B6A2C66F7EB8ADA8BCAE2B5E98AD201E46AFDBA62C97FAE07FBB2A7BE2CB89DF5C03ABD0F8E02CB8DB5BFE34F8ABF4E506569051B1DF7203E2C896C89561755FDBC8D3305556E7810FCAB4ED8382D24A252ECBB57A7D39138523252716B7C626525B901DB11869978CC9ACEFD64A7C5C72F87A5AE53B4DE394935E5B53AE5BC77B35108B8EE82903957DF229114CEDEE62E5566E43C3DF1663127705DC0A2B8B3181305D460208A74F7C05B618F854A4BF87C46001B2D06DA8C6BBF2FA3088ADA1A4D622029CFF001C9702DA17F4AC4C681BE23D05729CB1A5AB405CDD731BBF0F01918C2DC7C9B3C4BF35FCCF268FA60B6B78DEE2F27158E34AF434DEA332F1E3751A8C8AFF00959F947A8F9D3433AAEA90B5BFAA2A3983B75F119B1C717499A565BD67FE71E6F9B549EC74CD4B9F04E6005EE7B74CCC842C38E254C2A7FCA7F39795E57730C9731C7D5829FE991941B23240C3785A76B4BD06DEE22DA507B6634E0E4455269E35902A2FAA9DE40731CC5B8056F5410027D9FD939518B9319505E8CE36AE222C84938B13CC8A8E9D708091BA7885760570A781FBABF947FF0092A3F2C7FF00013D17FEA061CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8797343B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D2F23F91A57BA4BFD6D6BC0D68D99B874D4F199B556F6FBFF00315959471D8E9F1AA0A7024019B9C18F85D466CD6C59E49EF25615E4332A52A0D50DCB2DF2D6856B70C52551CE43DF31324DCEC38B88D3D353C81A7CB0F32AB551E03FA663193B0FCA3E7DFCCDF2B2E9FEABC7B2C7E1F4E53293938B4F4F9C6F56297D485DF7198E64EDB4F0E146E83AFDC797196E2DE46AA9A00091D7E9CC6CDB876719D3DDBCB3F9BD24F2C31DE0DA94AB1FEA7308C1B0667B4D94D69ACB0BD12208D97E3151D3289636F8657A07911B4F7D723B3D2E146909A39DB7CC738DBE395EB1F997F96F6BAE687305B355D42DA332D55454D47B0C8F03938A76F86AD6E6EFCB17173A65F42C9F1955E429DF0183920B2BB7BC4616F2C5B16DDC65660CC165F14EB3463B9032071B30532B566E2C3B83B65538D1499526D019BBD6990E16719A6917C5DBA63C2DF19A6D6F7CB1008C7E8C785BE395344BA420107AE061396E881329C892A0DAD663C8D0ED9592CC054571DF2BB6C017F2B7FDA1BF7C2A8599ADE876DBBE2A82372A361D3A0C5541AE7155295D4AD477C52934EC6BB6D8AA0C87F138AA8307DB7380A43AAD502BB7865062DA0A3E1269D7A60A6C0510A5BF98E34D80ABA3316515F98C69369846687AE16B4C2075322A96D8F7C55328A7F498156AD31564767AA23108EDDB08544B5EC55DA4FC724C81444378A5A9EA7BF5C2CC14C92F401F6F6F9E06C1277E9458EB593AEC37C84CB6715A849AC27412F4F7C8829421D6A25AF292BE1BE580AA026D6226DC3FE39602A841AA52B2C64B329A0032AC82DC5CF9B81E8FA0797EFF00CC36DF582AC8AA3AD30C62E064D45B23D2FF002E746D666FABEB1682EAEE27FDDB915A27874CCCC61C0CB2B7BEC5E5C8B43F2FBD969AA96E889B050053F01997034E0CE16C3BC93A446D35E6A37975CAECB32853E03A665C25B38C63BA6F3C3CEDB526BEB5496201B83151EFED82526710F942FF00F2B62F34EABAAEA1631FA2F393450294A57DB31E45C8807897983488FC97713E9FA8CA1A624844277CA0B7C52BB760F0C4E05030A819590C81A45AF5C14CC14D74F6F888F0C7859829D237C58D3305FBB9F945FF0092A3F2C3FF00012D17FEA021CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8796B43B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF911B5D4CA4450905BBAE74F1C603E6D3B48AE67FACCEA900FDE16A6D9682038A626D9EF97B49957795D99CFEC9195CE6E660C6F47B1B58EC87AAF540BB961D4661CE4EE74B87D4191C5AFAAC65616692836E5B65066EFC600F1FF3E4D71AB45708F1045607E21F4E5329B64703E3BD62C6EECB539792FEE8B1F88FCF31CCDB04292D9AE9C158E18C484915AE57C56C8DA31A49596358E416F21EA54E44840059C68FE69D574B44824D51BD24151F16E7D8E63C837C6DEEDF96BF9A30697AC437F733A5B98C8A9E5D7E798F272216FBDBC9DF9E9E4FD7AF7EAF7B7111F56309212474C003978362F14FCFAD33C9F3EA31DFE8572B34929E46314A54D7C301736DE23636377C39471820F5F6C8101B0499559B2DBA8F59E847619590CC14FAC751B37996105CB374DB6CA671B613932D59618940988453D0F7C8F0A04D136CD6F2352390BA9FDA1BEFE18385B064A593E9D74D30689498C9DD8E3C2CC66461E76A80354A81BB65538EE9F15B87528DDB846416F0272B316C8E54DE3BC454025A06EF4CACC5C98E45296FE05DD4B37B5321C0DE24BA2BC570095007BF5C8B0326E59EDE9BB004E28B4B5E48F7A1A8C56D41A44DF7C56D45A4DB167C482797AEC315E24135C76A62BC4A06E0D7A75C4A89287AB43D72921B414545734A53E9C785B01B45ADC8F1C785982AE2E42D0D7A74C14C89D95D2EEA2B5DF035DAAADD92C17953DF15B4CE0BB006EDCBDF15B44BCE78F247A3FB6109050E2EEE01FB44FD392664A69697B329A93DB147123FF4A3014240FA71533A434FA846D148EF394310AA81DF018DB28654A6E3518B9DBAC324B2198D1CD3A60106CF142A299A4BC92D622F2040086237DF2622BE28651A77947CC5A9C4F35BD83945E8C4102996082F881EB3E4EFCA9BD9D44FA8388EA7918FE5898BAAD7E4DDF4559E9967A26872A40024C828A0EC09C9083AFE3280F24DBDEACF7535F5BA2C8EC5A075DFE1DE997C4522ED966AD33DA5A4934D2963312A213D299785E152D23CBF696D62D3ABB191FF007A2BDCB76CB449A670DD4BCD4C2CF402DC4249715529F3DAB80C944698D7953405B5B06BB9A61140D1C923CDFB5D2BD32B25980FCBFF003D4B379FFF003D6EF4486FCC7A769D39ACAA7ED509EB9021982FA1F54FC9D96DF4DB7BFD27525BB9258C39B52C28BB0D85322907778AEA52AE8F70D677C443780D046761F7E2C814CEC599516534A30AEDD30365A6515E425FE26A7B61676FDE9FCA021BF297F2B997756F28E8841F63610E74783FBB8FB87DCF21A9FEF67FD63F7BD172D68762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EF578F9B5C06FDDBF4CE9B8DE267A6651E54D1967BAFADC9BA72AAE552C8E29C1BBD62DE25826E4AB45AE56656E6E0C28FB8B9068427241F697C72B9F276F871F0EE94C97B4256184257314C9D96395B10D522BB9CC8D23058687965129399116F07F30E857BACDF35B58446572D4F8728949651A4E34BFC8DF335FC6918B3912693756A76FBF2B126118D966FA67FCE2079E3569D2425E28DBA7F9F2C4C9C918596BFF00CE13F9AA29D1E5BD255853896E9FF0D944A4DD0C4CC2CBFE706B5A9E359DB5858C2EECBCFF00E6ECA2526F8E265563FF0038CDA7E8171691DF7994594A8F4F50494E4476EB91126D11E17A95A7E487956EAE62177E6E597881D6407F8E032660A7179F957E4CD35D2DE1F32C444A28C798DA995993602A69F929E539E932F9A6293BF0120C812D82491F987F2C348D2EDBEB1A7EAA048836F886E7EFC46ED3964C33FE55FF009A2FECCDDDAAFD7517A01BFF001C970B57131F6D13CF3A6481DB4B6B5B68FED02A454F8E3C28F11136DE77BCB598417D6E4229A31A634BE2338B4D6B48D6A25442179EC6BE380C2D81CD45BBAF28385F5EC65A93B8A1C81C6DF0CC92CBA4EB91A13E9B3D3BE40E37331E54BCCDA9DAB7EF6D0923DB2BF0DCA8CD53F48A85E722346C7ED2F8661CC516CBB516D4ED5BED311F3C82AFFAEC741C5B63D3E58AA8B5E27F362AA2FA82F4AEC3BE2D96817BF5AF5DBBE29B59F5A88FED62B6DFAF19EF8A82A2648EBF6BAE45B42BC6CB4FB5BE1640AB2B8DB7C0D815B92D3AD70164AD1B0A75CA9AD7F2DC50EF8551D0135A5715477A8513956BBD310CA3CD6FD61BAD324CCA9BDF49F663EB8B548A3ED2C750BFA705635F0C5ACC99E795BF2D359D7F538AD591845506507C0FD396E38DB0964A7D476DF933A0D959033C4867812AEC7B6DF3CBBC363E2A47A4F937C9BA5DEDDEABA95DC29145BF027AF1FF006B2C18D7C5629E7CFF009C98F23796F4ABBD13CB56714B76A0A0950577029E1ED93F0D7C57937E5BFE746B779ACC375AC4AD0E9CC4B70EDC6BF2C84E14E3E63C6FAAB53FCD9F25F9AEDA0D1F43981BDA8590AF5AF7ED80069E07B5E83A3AD8E9B6019FD4927456E47B03DB260278588F9D0BDE6AB67A65BF660580C902ACD043E8C3A7C1D2A02B8F96264C4861FF00987FE997DA7E996FD178F35191E2470A335A8DA0F265F5869B66D3EA4B6CCA0815DD908C921F9C3F96FE439FCB3E7ED77CC1E77D224852EE6768DCA6F424FB9C3487D831793349D5EC21D5BCBBADB441E3E6D64ED4E1ED4C348B7E587FCE45F9ADF47F3B0D3667A346FC5A64F6A60E1660A1FCA5F98F1DD086D6693F771A84563DC78E34D80D3DA2CEEF4FBD50F1CC391F7C69982FE81FF26E83F287F2A829A81E4FD0E87DBF47C19D061FEEE3EE0F25A9FEF67EF3F7BD232C69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8BED12FA6D457F46FA12ADBC7F626A7C47E6736E72BCD5193DAFCA1772C114D67796EF4894FD51E31D5BB72F6C899A63A6B6609AB5DA32C37B6E2DD587C2E452BF2C78DCDC5A4012093CFBA5D95C5C4123AA9B7157693A7EAC13C9B39630D30CD5FF003318397B28A39E2ECD18AFF0CC4326D863A62B73E79D575085C4517A61F6F886DFAB29949CC807D51FF38D7F96B36BF24BE60D7A33C62F8E30BF64F43BEF98F29378C40BEE7D22C74E69E9269D0C76D07C10CB1AD18BF45AFB655C4CBC1E1DD9E8BFB58ED1ED0C421BF857933462881478E266DF8E16F93FCD9F9B3A89F3543E5DD06E92E5E7904370EC6BC2BD48DB2894DCD86114C9FCEFA4EB5E4DF2D0D6EE7CD33CD77749CA3B3864DAA7B5331A536C38E9E45E5CFCBEF30F9C746D43CE7E64D66E20B0B2532DB425E858FB0C89C94C463B64BF967F973179E359223BABDB6D26DEBEBDD31A6CBE06A32072527C17977E75585B796FCC53E81E54B9BBD4A68BE15773C8F2DC640E56DC7A7B286FCAFF002B79ECCC351D62C6F9A0421B801F0F1EB959CAEC31767F13E9997F303F2DADECC68BE67D3A6B4BB20707028DB6C4E1198863A8ECDA28BB3F307935EDBD0F2EEBB25AA1FB2B2BD313A92D3FC9A82D7B509BF41DC2C9AADB5F475256456ABFCB251CE4B4E4ECFE17805ADC68374F7306A7693F224F0940D8E644276EB3361314A5FCB71DB96BED36F0C31F22521734232F0C2386C59661A17994D9010DE5D212BB75C90882931A7AE681AF68FAB442DD6E22172B5E418ED919419C7210C953CBDA4EA2A566A7ADFB253ECE63CB6726398B18D47F2CE695A4789223131AA377A7DF98192365CC86434C1755FCB7B8B552CB1866F0EDFAF2A316CE379BDEE87A8DB170B6D29E269D36FA3234C81481A3BD462258245A7B645210F34BE98F8C1030B7525C6F2035058838B3115212F03591CFB53148802A6DA8C6845198E2C8E20022A1BB59A95241F6C5AC48A3967229C6B4F138B30510B73D37E98B74510B703ECD7AE03BA65B045070AB50D91E171BC42AA92EC64AEEB9131489A36DAEC3380DB0F118084892266BD759111006889DEBD71886C81DD1F0992E18C50C4657A7C210572CE16D243D3BC97F957AF798E482792310C524A1645E8426FBF5EB8F0B8D393EB1D1FF002374CD2AD24B8FACC8B2409CBF7A76247D38F0B8D29A0B4DF33689E5E3793CF730C571A7D79F134A8197618B10789E11F993FF003955A5E97697F6FA0A9BABC98323B49BA8EA36F87325AE669F188F3B7E6079FAF9ADAD2F561B59FD46B94534201A9006C3C70DB8E7290C5B4AD3E1D275392DB592F717334A03C8FBF53DB27C69194BEACF2AF93E2D6E1161A2A492974A3B36FC411DB2B99B6C8CDED5F941F9172796BCC4FA84AD2CE8CFCA6F537E277E9BE56CF8EDF74C691C2A8109E1025501F6C3652082F3BB1AEA1E6A7BCA739223C78FECED8DA683D06F1115A198578A312DEC72F8C0485A90180C006AFE6C9243F14708DA982500189A66B1C4F1488518AA4B5E5F25CAA52A6069E4DE67B48BCC7E67B6D2DADD25B585C7AEC07C54077CABC621AF64279ABF2B6EF4DD2B5AD5741BE6B484216823534A0A0EBBE4865B6C1005F879F9B02E6E7CD9A80D61E3BA9E1958073B9DB26269E00F3089B568627BAD3D12358E4A1E636E3ED960368D83D2B43F3C4F63259C11C9CE5968272DF641EF4DB274178807F551F9093B5D7E45FE4BDD350B5CF913CB92B11D2AFA65BB7F1CDEE1FA23EE0F2DA8DF2CBDE7EF7ACE58D2EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90FF00CB7F20CFABEB70F9784FE9BBB0569CD76FA727E3B8A3474FD1DD03F23BF2F3C93A589BCC5E60B79AEDE3E4119F707EFF007C7C76C8E969F1C7FCE4679DBCA97925BE9BE5331C6DA651649E3E8DC698F8EDF1C34F985743D435AB73A95C5AB244568B514F57DBDF01CEC8E34D74AFCB3F36EB344B1B65B6B63FB4C074FBF29395022CB74FFC91D5CEA169646F0CB792B82B02D6868457299657271C5FAB7F90DF96FA8695E588AC2E2331968C027E81941CAE6460F7693CA361A1E8F705C896E5DC145EFCBB1CA8E46E10BD9F397E76FE60587923CA7269D6404DE66D67F72186EC81E9BE0395C8861A60BF911F93BA0E956D75E74F38EA0B3DC5CC06ED8B36E8C6BB75CC79657371E36216F637DF9B9F9A52D868F792CBE5AD35E9287354A2FDDE198F2CACE589ED7E70F2C5C6B0963E42F2E5C1B68B4F939DEBC6688E0F63959CAD4715259E7AF3EE89F933F97B37956C5565F325C2141243F6F930237A57227236E3C5C4F19FC99FC9EF3579E357B2F3B7982E85BDACF299409BAB2F20DEDE390395DBE97476FA57F323F30348FCBD8C68F62F6D3B88F837115DC0A7BF8656723D0E9B40F813CDFACB79A75A6BE9E0145242328E80E0F11CC9F65F131F9AC2248F925F4B6EDE08D4C81CAC4F6481D1434AB8BFB2BB8A73AACD71A746F59A177AD4F7C9C32BAFD4F66D07D412F9D7C87AC79623B2D3ECA38F5644A34B415E599B8F23CE6A7414F0F3A6EAF7777248B3B95AD16253B53E599D8E6E8F2E1E03499E9BE5C56BD53AB192DE2247276DB2F127127165D7FA0E8F0317F2EEA85EF1002C8ADB93E18CA4D6229B7953F33A6D26F5346D6AD65424F1FACB0FA3AD330E72722117D2D63AAD9DEDB42F6B79CD5D4155AE634B9B971E48AF5AD89E372BCD7C72B219A1DACF4FB9E4A6C57813B371EA3C72B21B2293DE792B49BB25BD08D49F6FEDC810CC3CE75CFCAFB296390C4A2B534A7FB78B787916A1F965240EFC54D05698B6061D7DE50D42353FBB240E9F462CC31B974CB8B7E4B25B9AF8D31672E4848D2584EE87171AB74D61B9A8E25295D89C5B150951DF1640B4B28A80A773DB14CCEC9AC658A0DF22E2A3ED62326C7A1AE34B68D58A15824653F18E831E15B645E43F296A9E67D5E1B75899A194D2B966385948C9C2FB83CAFF0092FA779295353D5A2170654E410EF4AFD3991E1A0E77A4E82DA4699F5ED6AE255B3D3ADE3630C55A55C7418F86D32CCF3DD5BF33AE7CE574749D20496F6ECDE9B4E36047CE98F84E34B23CEBCF1A3792FCA7A1EA926BBAA97BEBD80FA4BCF7E743D725185328647E5DEBFA8C32EA57C2CE212DA991B8B91534AE4A98E4928F9735ABDD1EF0DD69B251CAB7A918F9634E29927A350BBF32B5ACB1DBB3DFB5C207A0DFED634CA2FD64FC8CF29C1E5EF2B0D66F63A5CC9081F17662A3010D8F77F23D85DCB6FA9DE5CC815667261AF8646922D3CD6EEC69D62189A168F8D7DF1A6C8DA43E4EB4FAB9B9D4661B4D5E24FBE34CF74E755BCFABE8B3C8C68ECEDC7E9E9878E934520F29DB1B2824D4E71BDC92149F7CAE5918905956A139B4B19A73B7D514927FD615CA253B6B312C23C8F6AD35FDFEB972B54B824424FBE5129313128BFCC0FD23079435716F2B969636A460F4DB2D8DD391189E17E06F9FFCB7AE0F34EA9A85FD94CD01998F220D2996C4B0902C7749D26F7CCD7834686136494AA9229C865824E348909B47E4F86CB506D288E57711A09325C6E399C83FAA2FF9C7E80DB7E437E495B375B7F20F96E33F34D2ED87F0CE9307F771F70FB9D2E5DE67DE5EBB96B0762AEC55D8AAC7DC7D38AA9D0E2AEA1C55D438ABA8715750E2AEA1C55D438AAFC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF233CB9FF0038C3E4DF2ADCBEB13B133D0B1911C0CC3B2E7ECFCE5FF9C95D5A6B1F346A1A7E95AB4E6C625612C5CC96E229B03DB1B29A0F89DEDDEF00926B97974FF5394909AFAA47BB63653C2FA87CC9AF797F56F2279774DD25D34B4D3A86707FBD6A0A751BE365061B337FC8DF2C5E79C752B7D26D6F2E0CAEEA11B937122A32B258460FD2CD3FF27FCBDE569F47B4B9B432EAF28065BC6DF8F427299172618DF40456B6BA6D9C16FA4C4102A51E4661D69EE72891A732106272C4F737978F79C94DADBC970B272AA1F4C578D077395D972B1E3DDF9E76B6317E6E7E6FDCDAEA08F69636B318F8CA7ED509FB35F96425272B829F42FE69F927CBDF977E4FBCB5B1FAE896F63315A4924C4A7A8694A0F0DF28916D8079F7E5DDB5EF907C986636E96B7BAC9ACD7DC6878B03D0E512939118A6307E6459E97A6DCD968086FF00CD3316F4EE07C67936DBD2A72B2594B0DBCCBCB9F94BE65F327999FCDDE78B1B8BA4327A932C95E0141AEC08DB2264E4E9F4FBBD4FCFBF9ABE57F2AE8F0E81E52E7677F0A18E242F550D420EC32B26DE8F498007C75AEDF5D6B378B7DADDCB4D7B292CBBEDD7C32B327A0C31012DFADC21FEAF343EABAED118C5283DF07139825174B3C0842B583B13D2B91254CE285BAB580C5EAADAB41714FB1FB253C699289759AA31AD93BF21FE5BF997CF5AA25B7942D9E390B52E6465257DE9B6676393CB6AA9FA0BF97DFF0038C4BE5FB186E7CD3299AF1497996BFC33618E5B3CA6B620CB646F9AFF0025F45F3497D3AC6330A8F843A6C7C3AE64893AE9C5E7FE59FF009C4B6F2E6BEFA88BA9E78B90608EE5878F4C12935883D1FCE5F91FA16B366919822B5BC450A27550A6B4CC49CB7722317CD97FE5DF30FE5DDECA90C72EAB696CD44F4EA683000D8F40F2E79AEC35E884733AD9DD746B7907C55FA7010CD983EA0F1AFA3C1404F85180EB9590D812B7FADCADCBD6F84F4036C810C834F248AB406BDB7CADBD21BA53293CD41C5B42552E936F221AA038B20C2B54F2BC3217A44BB83DB16C3BBCCF54F2A4B17F751803E58B5F0B13B9D1E5B706AB4FA314243346F1FDA53BF4C50A5146DC838041076C0589927F096E03236C0A6F6C582FC3D7FCEB931BB548A3A0D2A6BABC820B40CC2660251D7AE5A22D7C4FD0BFC98F24E95A1E9D6B7A2D985F08F90673515A7865F8A3BB4CF23D4FCD9E6780AC36D247CE78E3ACC3F6683AED99341C7F11F21DDF9E17CF3E61BCF275ADF243A7D94865BB8D0856A0EA2B5F6C691E25BD5935BFCBEF2569062B7A34F0A7266EADCBFD6C683025F9C1F9BBF987A879ABCC37C25AAE903E1B5727627C0602144A9E07E85AB1755670AC4D77C1C2C2791D64B67A6DC898BB2CBB8849355DFAD463C2D5C56FA7FF00203CAB16AFAF433BBC73C664570817DC1C785BE127EA25D4634ED0934E0BC04DC5828DBA0ED9121CDC401E6CF7CB6D0268F089CBAB2814A1A7DF829BC4425FE6C65BF8AD6D636E3561C877E38D331009F689666F74B92DE195614B215766F6C69B0462C1FCF9AFE876D2C3A341AA4308545370ECC0EE7AF7CC79C776C1008D7F39FE5FDA687656D77E64B5630D0944700D7DF7CACC14C22C4BCD5F9C5E4792D27B1D3F5980FD6C2ADC55813F08A0A6FB640E32D6718653E49F37F93EEB4286C1756817D221A3F8C035EBBEF90F08B0F0C273AE79A34C3A7CF099619CCBB2B5410C3DB7CC8863A0E44202980CDF92FE44F3BE963EBBA72FD6AF3ED3A902B5C3C0C258C3E78F3E7FCE23685A523EB9E5EBAFAB6A963FBB823076A2F4040EB83869C69E10F9423FC92F3C4BE66FAC49A6CB33C8D46B8553C4FE18971CE9EDFD0E7E5058CFA67E52FE5769B72A52E74EF28E896D7087A8786C21461F78CE9F4FFDD47DC3EE797D40AC921E67EF7A2E5CD4EC55D8ABB1568FBE2AD547862AEA8F0C55D51E18ABAA3C3157547862AEA8F0C55D51E18AADC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF30EE7FE3932FFBDDF60FF7998EE4BF25BF357FE537D53FE39BFB5FEF6F5EDD716D0F1497FDDBFF001C5EA7FB9E98B745253FDFDAFF00BC7FDE0FEFBFB9EBDF23264793F4DFFE7143FE3BBA67FC707A2FFBC7FDE74194B18BF42B56FF0094853EC7D8FF0077F5E9FB194CDCA83C8BCEFF0061BFE521FB5FF1E7F63A9E9ED98F272E09DF927FDE49BEDFFBCB27FBDFFDEFFB2FE3953938DF1A59FF00E4EBB4FB1FEF50FF00783FBAEA7EDE464DF27D01FF00395FFF001CEF2EFDAFEF63FF008C1DBAFBE53258F3625F985FF92AB47EBFDCAFFBCDF6BA663C9CDC6F00FF009C69FF0094FA7FEE7ED0FF008EAFCFB65679B9717EA37997FE51BD43FDE3FF00799BFDE4E9F64F4C94F936E93EB7E3179D7FE531BAEBFEF43FF7DFEB9E998E5E9B4FC921BDFF008EDDB74E9FEEEFB1959E4EC23C936D3BFE3A375FEF1FDB1D3E5DB029F8ABEB3FDF27D8FF009E790973627E2AB17FBD717F75FDC8FF007A7EC7D39383AFD47C5FA1DFF389BD2EBFE385D0FF00BC3FDF77EB99F89E675DC8F37D49AFFF007D71FDF743F6FECE6645D066E6C5344FF7A24FEE3AFECFDBEB99117124CCAD3FBE7FB5FECFA60C9C9AC3CD3CF1F69BEDF5FF0075FD398736F8BCA74FFF00A587FBC7DFFE3A19747E9497CB7AEFFCA552FF00BCDF6FFE95B80A43D7A1FF00792DFF00BCFEEC7F7DD722DB1504FB67EDFD1959641565E9DF2A2DE12997ED606D0843F4E2C825571D5BED7D38B6B12BFF00DAFB3FECB14179F6ADF6BFDD78B51611A8F5FF00757D18B192017FBB3F67A603C9804543FDD8C805926D69DF2E8B44F9BD2FC89FF1D6B7FEEBED8FEF7E797C5A25CDFA15E5BFF8E6DA75EA9FDD7D1F865F071F27262BE69FF8EB6A5F6BFDE47EBFC32E71DF97FE4FFF00C995E66FF7BFFDEC93FBBFB7F4FF00938ABEC7BDFF00943F52FF008E77F70DFEF47F7FF47BE2AFCCCD7FFDEDBBFF007A3FBF7FB7F63FD8E1632E4C6A3FB4DF6FE8C0D3245C3FDD5C74EDFDEF5FF638583EDFFF009C50FF008E9C5FDCFDA5FB5D7A8C0E4C1FA41E6DFEFB48FB3FDCF7FB3909399064D63FF1CF8BFBBE9FB3D320DC3E2C67CC5FF1D0B0FB7F647F77FC71671F8A62DFF28CEB5FEF67F74DFEF07F7BF4E167F37E67FE65FF00C746F7FE526E9FEEDFB5903CDBA3F178737D97FF008EDFFCF6EB8127E2952FF7FF00F4B5EBDFAE2D72F8BD3FCA9F6D7FE526E9FF001EFF006708607E2FA3EDBFDE1D1FFE523E8BFDFF004FF65930DD1E5D5F5BF977FDE0D27FDEFF00B2BFDD7DAFA72054A7FE6EFF007960FF007B3A8EBF47DAC816324FB4DFF8E7D97FC733A0FB5FDEF4EF902C1F62796FFE51ED07ECFF00C73AD7ECFD9FEE57A7B674DA7FEEE3EE1F73C7EABFBD9FF58FDE9D65AD0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD9, '1', '2021-03-13 12:45:48', '1', '2021-03-13 12:45:48', b'0', 0); +INSERT INTO `infra_file` VALUES ('6edb3893-8ec8-4bf9-aa64-c04f1c7ad98e', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010305010101000000000000000000000304050206070809010A0BFFC400431000010302030603060406020104020203010203110004052131060712415161137181082291A1B1F01432C1D109152342E1F13352620A172472164325345392E2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004311000102040306040602010303010803010102110003213104415105126171819106A1B1F0071322C1D1E132F114234252081562161833437292A2B2D224258234FFDA000C03010002110311003F00FBF8A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A0AC4C7CF97DFD89ACEE920903F71909243FB3CA2953A948260E5AE5FEFEFD29962312647F261DADAB54FBB46C10A2D60FA966E70826F595BA5941E25A7FE44A4825BE9C63513CA69A276A214A097A9E03D63265A85DBDF46841EC5AD187C5BBCE0696AFCA56A0904F2039FCAA524AC4D018D5BEDC3CFD886932709658834BD0F0E56F3CA1E22E10B820183A1EBF4CB9CD6B326196A29A1B6B623B74F38525AC2D20DB510B05054C4E5D684CC2A6602BAFF71BC7B4A07CD9F841149580633FBF5ACC11E832268823DA20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20840820C73A5029934B8D789F7DA140A64711AF13F87ED142BF29F4FA8A6D88C289E0920391507D9F66D0D558B097A0245BCA9D7FA363108D34DDAE2172E38BE137E13C0A0608F084104E5F43A193CEABD8AC18C3106D7A5E95AE76A59BCA1791395398105EC3ADBD39DB268B6B10C5F0D18A0C3577187A9E42B5B958372743EEF3D2069A4803AB0FFBC8C2AF777C066624B736FEDA9A44C4BD90B9D2BE7192B552C843AB3A97D1C7F717BDB3ADBC96D6D2925053970E900465CEA6F0B8A18B97F31DC9624FBCB4F60464E90642CA14929539704311C0F9FEA1FB7CFD3F5A9295FEDEBF784614A710422BFCC7D3E828821447E51EBF53441155104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104450C4D92F5D301B70BD6DC3C400FCFC63FF00D79E70067D09F4A6EB9E106B400E7C75F6348C33B8F21786AEE2AD254C254D3E90EA5D5AD6A4C2184B492A25E3FDA08120FE99D64ED09094B93500D33A3F0B521AAB05316680B121FBD3D8EC0C72B7DBCFF894EE97D96762F197705DA5C2369F6F9E6D6CDA6016578C5E5DE18F825B3F8AB54AC38CF1485A6332248D0D5476EED793F2D5BAB4835A3874E7EFFF00F422DDB1360CE99392152D6427759C12921BCDBD75AC7CA1ED6FF11EF696DBEDE6E03B7F6FB718AE0F64E634D1B8C0ECB11BB61B72DDEBB69086C5B85907FA440209233D2B8BEDADBCBF9A425550A167CCB3B50F6341D23B76C5D8084491BF2C01B85BE90D6ABBEB6BF4AC7DC57B266DF5CEF13721B0DB518825F17B89618D2DF55C4F88A5A5B6D2A528992789526739EDCBAF783710711B2E5AD4492522A79F1F7E51C6FC6385186DAF3D2121292430019837A46CFA7DD05474807EFE357795FEDEBF78A94548585A428640F5A710426BFCC7D3E828821447E51EBF5344115510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510414410510478639C7AD10422B70699F61F0D47D34F5A208B57157D9B3B945F38EA6D8B48756950570B2E808952AE4999091F97A647ACC06D3C4090824E8FA3D2D7E1A1830A37E72505FEA2DCE9AF5F58F9FBFE279FC5A30ADC058E31BB6DCF5FDA6D46F5F1369CB0BDB5B3713796D84A5E4F85E2145BAC3CCAC5BB8A5C990148988CEB96EDCF150C2EF8DF096041AD9BFE35B1CFBB88EBDE16F09AB1CA4FCC969992BE9282DBCAADDFAB335358F90FC671FDA5DB2DACC7769F6E318BDDA5C5F137957CEDC5F3EBBB603AF953A5A42DC3C50C9596C24C70F0C72AE57B43C6431130A44C24926E4BF06A7E7817AC76FD9FE071225A54248140C426D9E94F3E2F0CF67F1042F1861576C16BC2C4B0F36E1A4F0A045D37A13D3224E7998D6A2D13978D58512540A852F73E5435F661C6230A9C0A199B752ABB0A80457F0D7B47E871FC3C2E9CBCF65BDD95C3AA2B5AB0F70499984A9B09D73FCB15E96F044BF97B265A48AEE8A9CDC9FD7947977C6F33E6ED89AA77049E548DF55FFC47FF00A8FD2AF72BFDBD7EF14C8A58FF00893F7D29C4102FF31F4FA0A208511F947AFD4D10455441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041441051041A510435372388A40CBA99E5AFDFCEB2C7431B896A29DE0CD5A674E9F78592E020120FA7FBADB715C3BC25315F2802ACFD9ED0C9CBC487FC208717EE9515244A13099827404C7DC56E656EA0294E1DFAF271EFAC371880A56EA475D3FA7F53A3C4BB8AB49B755CA92E04A78CF01FCEA4B73C4B039848127A0A693268403C01BE747A7EE91252A42A6B338720727B3DEF46FC47CEE7F186FE29985EE1F652F3747BA1C4DAC4B79BB4E872D1D5DB3C975FC1036471F096161EB75B8CA95196640EE6B967893C4F2113D7841FC88604B642ADF97D6863A6787BE1A6D0C74B4ED10A1F2CEEA9206F6B906D0E5FA3F1FB79B578EED16358A6D56D05DBF7FB538A381FC4F16C61C5BB8A153C494A1A7D5EFF00080A28009FC99682B89788F0D89C7854C94A2CADE2E496725D8B06D341DCC77FF0A6CC97B1CCA4CF4A545346AE547660DCB3B0E1157CEBADB8943CF5C34C13C43F0AA8599CC95F2CC991D672D6B96AF63E3913C952D4C55A9B5333F961C834761978FC0CCC37D284856E8029C297E35CF389AB3C66D117B84E1B609E2BCBABDB4E07AFA080A6EE1B27888CE55FDBD7A9AE89E1DC0ACFCB4AC97053C474ED5766CE398F8A12662672A596A1208003D3FB7AE75A47E875FC353F1AAF643DD5BD7E86D1706C6E38C36084C071213139990273AF50785E42A5E025A5A8406F795ECDC9DE3C83E2C27FEE73526E925CDEF6F4CBAB1BF41B8C2D05398311DAADB2D2433E4F5AB574EF1578ADA494A003DE96820520924E5F63CA8822B488007DEB4411ED104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104144105104332D00B2A264F41A67FE32FB9A0162595D1F4E1EB0AA57BA8AB801DD850D4F7EBCA14CB4F80A5C6A73F21A7BE4E5A23713382CEE876163D7D3BFE60B124DC36DB82DE42AE20054E69232D46920FCE75D50C4CFDC40054ECEC1C503D7FAE1CA16C061FE6A9DA97E4C4971CEBDC0A67CC3FE259EDBFB39EC5FB88C6714BEBFB556DCE2B66FDBECAE1FE2A3F1172E3A54C5CA92D1525D596D2EA55EE194EB19556F1B8D4A50BDE57D441662E406B1A38EBE917DD8FB24E2D7266CB42BE56F0F98141C100B0619E649D4F38F811DB3DE2E2FBE2DBEC477BBB68E5F5D6D0E23777772117854E5BB69714E78296C392B03C352444E59655E7BF124D3336B29408A28B9CD9B2CA9991C4C7AA7C307FC4D8E996DBA4245281FA50E5EE8F67DC630E3D69885E5DB1174EA901808465EE2B8444E7F9634FAE74D14BDE90D9B503BB8EB763566E8F1954F06728D2F5BFE9F2F530861F8C9BC69CFC69875AE1E20AD424E49CBEF43553C6319A684107D8D732EF607AC5870B3C26592AB1029ADC55B5C9BEEF10B6F77737FB71B3563624A9C7F6870461A08CCF0BB88DAB6E4013970A8CC0F955B3C3E80A2839EF0E771DB8F7CA29FE22DA0942561CD942EFADEE1BB3F08FD407D92F6311B15B82DDC60086FC216FB3D873E5311EF5D59DBBEA310352A24F53CEBD29E1D4B602506144E5EC97F2C8671E50F13CEF9DB5710B705D43EEFC3311B3496C01CC7C8F79CBE1FA54FC57615A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821B3AB4A544150062403E5590905CD011E777E30DA62941C55893AD2A1BF5E50D9B7D2B497152809FEE5E49CF2CB49C87AD68A9852145C80900DE9C857B3422941597DDBDC900F9FEF9B461DDF76F3F04DD76C3E2FB658EE256B8761183E1F7777757172EA5A014CB2E38DA10A5909E35A90123AA8819CD56B68E37702885391966391F7CE2E7E1ED9E274EFA9255660D4AE4DD6DC5A3F385FE203EDABB55EDABED378B6338BE2574ADD8ECF623776FB0586B8EAFDF2CF131882AE995294C90B7590A64B5A82273AA06D0DACC6602B2581B9D41AD4F1AC776F0FEC69625A1210024350240BD4F0ADAD6F3D78731F17984B16E2C98B661B9485787C172424812AD358907A6715C7F6A6304DDA0B50373AB82E38687DB978E8F2D230F204A14614E1E61EE1B90E062C2C57690DBBA96D0C85DAA3881E24CAC98911CB23CE3E4269D024CABB535A6B6EB6CDEF586292A54F05A84E560F62C5BF3E916A0C4EEAED38A5DB07C312C809320E796401CBEE2273AE624154FB9626CFDEBE6F67D4889C4EF26428D430A87CEAFFDE71B1BEC8BB0979BC6F68FDD0ECC23C172E6FF001D6AE5697412829B2B862E3300124808300E522AF5E1B96EA41A0A8E6DEF8DAED1CA7C598B32BE692A20310CE6F4635E55E01F48FD46377F689C3B63F666C4A63F0B816156F0065C4CD85BB6AC8F29498AF456C30D8443061BA18767C838F7C4F9DF69ACCCC5CC59B93F97F26CFA45EE1415313975A9B88E8F68820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20886C47F0E9429D5BA50BE24C4A8246640239CD658B3B75E7EEB5F36704952C92029B32C481D7DB72A431C582DF612CDB381B6D0DA9C7DCE284A5284859248D321399023946551F8A5A82083762E03B3694CC8E76D042D2A484946F060E03666B4E6072CFA47C5B7FEA1FF00E2238D31B43B3FECA7BAAC7949FC4A710636E6F70FB950FC280843F68875C657EE789EF27FA91331D6681B6311F4AD5BEDB8F404125EED99E3766D0C749F0EE1C26624A430514F61A7A91CF4A7CB7EEEB0DBA432B6F197495DA3AA7B0DB85A8F1DCA9F70BB7478D43DFCCE64684E7CCD722DAFB40852F749CDC3DA829AE7C63D01B064A44A416B80030D296D5EC7D488C8D7D8C97EE5618052D70A5000D3DD10743A4899D0CCE46A80B9E6662F7AE5C0B335684D1BA718B1CF91BD4614A583D2A75FCF786A2D9BBA1FD4D79CFA4E7DC8D0E43B0CEAC7296AF9391A0D2BC3F6D5A7186987C2EF4C14203DEC0D4F98D3EF148B06ED78D981C374A4C003FE9F231E4395474C4EF4D14BDDB2B135AD0FEEB689B9D86DCC39A1B162C6BE753EBC6E3A93FC19B76771BC2F6F3D8252992EE1BB2CF5CB974A20A90D7E22C8A9AE230401C439F38F4E85E1B961E58FA6AC6B7E7C69F78E03E392A499C9245281AF7AF2CDCE7AC7E8C585B29B6B3B46131C2CB0DB690232086C240CBB0AEFFB1C3615219A9CB38E0B8B24CD24B3B914E0D7B5625DBE7E9FAD4BC358528820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A3C41C6524111FDC7435A15805AFAC11E2DD4A412015C65091268F98343FBF79F9410DD37D6E484A95C0B248285101498EA279F2A3E60D0C10BB8F36D23C45AA11CD59401D4924563E60D0DBCFF001C7CA08F5A79A7D01C656971B54C2D06526323047435B82E1E0852B3045256018CFEFD68823CE31D0FCBF7A208B571E6FC4F01A09754A5AB88140948E15030B1D3A538972BE64B52B78242323405C93D843DC24D4A5D0A6B356ACF50E39DB8D738E7DFF115F6C4D9AF637F67FDB4DE063772E1BBBAC1AE2DF03B2B2527F1CF5D38C396C9534DA882A0D3CB42DCE1CD284CF4AAAED9C64BC382F352E410CE32C9AEDCDB5689FD99B3558C50051541B9142E4EEB3D2DAF611F975EF2F7D5B63BEBDE46D36F3F6C7164E218DED5E3776FDD3AEBEB75C66D5178EA6C9BB752C952562DD4843892609C84015CA36EED295B8A295EF1ABB106D50E34CFBF38E95B2B644CC3142D6592902CF60CCFC18FF548CF1B05BB1DF0EDE26CC6C96C06D46D0D9A1294E197383E18FDD372EC078DC2DB0470C9CA0F2CCF4E1FB73C45829626A9588952D52DDC4C50750D031B9B679657E8381DB72B01BA161F75B7788AE763CFB0CA376B63BF8757B536D1DBDB963763B4ACADE1C454FE11789038BDE1242758C8E473CC93A57259BF123032316A48FA994438DD3D4135ABD357789C3E2BC2CD48514EEF16003B379B77D62736B7F8737B57EC6DA1BCB9DD86D2DEA1292A09B2C1EF1C591130014807FD55B303F11F67CF425090D40EE0573A375BD4BF087DB376F613133025050A0F5620B372377E753A18D3DDB3D91DABD8BC66C702DB3C0712D93C5ACD6E26F2D71CB65D93C82B82D8521C1C43887E59D4C413CED9B3F6B49DA0B4992B1BCA228E0BF519B699C5BA662A54DC2AB75988EA0B3963DEFCCDCC7D13FF00E9CDDDBDD5EEFA37D5B697765E1B7828D9DFC05FBE8E1688B861C4385A77A119647D729AEC7E1C401F2E8080CC59CF337A172D5AC79DFC7C903E6BBA9DC84A43A8B3D407AB67A0ABC7DB058A38D86D695A5423549904C09835DCF6497C3279379C701C511F394002189BD0D4E6D1209494CCC671FAD4AC368AA8820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828820A208A4AC0319FDFAD10479C63A1F97EF4410718E87E5FBD1041C63A1F97EF44115032268823DA20828820A20828820A20828820A20828820A20860F2149716EBAFF000319402A80206797CE9057F23CFDF7BC11666D2EDADBE06C1164D1BD7D2098653E249F4CF4CBEF2C41166E05BCBB7BCBA51C630B7EC9CB8570A1C71A0DA441E104151CA4C41EC2688232C5BC9654B5A85CDA3E029224AA124663A089F97C48224ECDB61A6108B7484340A884A4400493390CB5A591FC4756EF0439ADA08457F98FA7D051045344116D62CFDD61C9BABDF716D0485A52A24F021225D24682132673F4A8ADAFB59381C217207D24BE74239E55F3D61EE130FBF346B4E01F2AF0C88EA23E367F8C3EEF77F5FC42FDA8706DC2EEA2EEF2DB775B1572A6315BAB75DCA6C6E5388B4D3AE788B6789A5F84B43807101C24419AF2EF8CFE24CBC0CE9FBD3095249F96970519BEF54D9B22CF7B18E9BB025FC94277F777BFDEAFF713715CD99983F988D9AF63EFE047ECE7B90C1B0FBFDE660ADEF076990CB2F5E5A6256F6D8A61697D438C8436F36160024F1839C8AE05B57E2999C66113882778108564697269525F3F38BD7F9094C94EEAD237B2984351ACE5BB3D63B05B19ECE9B98DDC61CD33B2DBBBD93D9BB665294B16B85E176F68F909802108004981A6624F3135C43C4BE3138A54C57CC7DE2436F56A4F17A5CEBCE23B153C4C56E041537FF1121D2332C6C34F4148CB78761B6966E8559D93F6481012C7861B291119240301433F2D35AA12F18668F9EA2CF5AF0D78039641B3A4252E6808604115078F0A173C34D5A24317167736E59BE65C711C2414AC05020F9E5E5CF2E734BE0FC512B09352952EC46741AD29AF730EF67CE5CB9A3E42D285121EE120D09B7534C985E38F7FC473D89374BBF1DD4EDA6D3B3B38D61BB6384D91BB671CB7B4659B8B95B2953A0AAE024AD45296C2046931AD778F03F8BE4CF99282144311BCE456A2DABD6B9DF9741C16D4C42657C9C42E5B28109DD35B5779ED95ABF7B3FF00F4F9EEA319D90DD0EDC63D8922E16EED0DF8B5B75BE1456EA307BFB8B702559ABDC4011F488AF68782270C6C894A0E4A8249734B86BBFEBCE39478DF1BBF3378A80037C12E1C3D1F5173D6B58FA6FC25C53962CA94C9B739A7C2524A48E131307918915DFF00662372424337D3F88E233CBCD59077812483CEBC35FB448D4942505104144105104144105104144105104144105104144105104144105104144105104144105104144108AFF31F4FA0A208A68820A20828821647E51EBF53441155104144105104144105104144105104144109ADD4B7A83F7FEC51045958D5E3172EBD69E25CA1600109308CFA798FB148ABF91F77AC109605B396885975E6C5C2559C3E0288E7CF2E9DFA56B043EC6B6770BBCB77FC4B0687829E2654CB490E056B918EA069C851046161B6DB43B3B72E30AC3EE6EF0F61442129694B5F082604640E9CBFD10465CD8DDB6B2DA6C383E8B67AC9F6F272D1E4043A0CF240CF3D7BF6AD3E60058127562D5CBBEBEB045EA8B84ADA0E942900980958856B12474E7E559F9BC55EFAC11EA882B81993F2C86BD3E7419841673C6BD7FBB41082EE1A6D6B438A08298CD4400644E46B066D0D5563EEF19170FAC6B27B4DEF217BBFDDE6337B68BF1B14BE43769855B33EF3CE1BA5FE1DD52500F11084B9C448D0024E715C8FC7BB653230D3D1F308514AB76BFC6878E7DB57AC59F64618CD505252C10DF31EE4AACC1ABAD79651AAFB8ADD4586CBECB8C7EE6DED95B7D8FAD7758962A1224B6EBAA759487A3C42B6D973848568A112057CEFF89BB7277CE9FBB354594AA856A5D99F8E94B333C5FF00012CA081421830565A1F4A371E7B09636C6C4ADB45D5CBE98042DE5F12CAB55051FF00A857E5E511E47CF3376B6297356D316CFAB539D5B36F3AC4F7D6A4212B4CB3BAE086A0193529D33AC797AAC42ED4DA0A2CF810A9F1784F8E04823DECF3FBD29862264F9A1D44DEAD7BE7C6FE56B0D44909720A9943F893F4B8B3701A449B988ADBF75B425C504A4788E895929039F6323F5A55789F978420ACB806A491E76A0E19650C66CA284155537648A015CBC9F9B690DBF1A5FF0076EADD95248E4993DB5E9DC4F5E75CD7696D5988C428254582C3E6CE79B71FCC35953D52D745117A83DFEFEEF8A37C96F60FEEFB1F6EE2D9B364E5B969D4292381497429052444199C875AED1F0C36B4F9B8BC3A43B1525EFADF4EE474CAC92316A423E62D64A88A026D4AF916D3A45C3EC57B23826C66E3367ED365F09B5C3106EB1277FA4C21A5A94F5FB8E294BE0E64A8C1EE3AD7D51F84A93370787047D44249241E3566E57E4358E61E2A9E664C9CA2B5105BE924103CF37A664C6F95AF1F80DF88657C2388832248072F8D7A525A021200D07908E7A15BCFC0FBE5CA1C5291B414410510414410510414410510414410510414410510414410510414410510414410510414410510422BFCC7D3E944114FBBFF0064FCFF006A208A8249008220FDF4A208F780F51F3FDA88214488007DEB4411ED1041441051041441051041441051047848027E5D688222DF773E7EA72E5AE7F64FC48220578797AE4BFC392C8CCEA741E7AD22AFE4608B86C5AF0841CBAFC3B9ED5AC10929775F89B801014C80380998329CE3B7DE74410CADAD6C9DF1BF1366CA8CC9E3427424E79F59E9441186DD79EC1F780EB966DF87875C2D03C240842211072190939F39FAB259AB07073228FEFF0030466C2E2AE5F6024FF4D29E254130AE2483D391F856AE753DCC10A5C5C1B40FBEA9E11C013AF3CBEFEE300AB3513C6D04446216CEDFAEDDC4ACB49852DD5494C2520193D3219498AC2D442165CD12A373A18C8B86BB86E71CE5DE862973BC6DFEFF00212E7E236536023F1E12A2AB77DCBFB70A678A4F028A1D1CF307A9915E2DF8C1E334ECEDA33F0666B315021F813DC7987E71D4FC39840BC1A5652904E6CD6377A0F74BC66FB36DBB4C2587D88E06F8901034080AE14E404649033E990EDE20F16EDC4ED09B30EF05051373435B8C87DEF16642129510033588018937ADE95EDC22590A0E202D26028498D67CFF00DD51654B0BFA88CCDC31CFAD72D1ABA43C4AC001EA78DBAF0D0BFDD839289199E83D358E5D3AF5A6D8C9D2E425449A797E32CB9D32541053BB40C439D1CE5C7335147610D56E24B9075E632EFF007DF99CCD57B158EDF96B093420D34D2D5F778D9787DE946809AD49176F74E59BC535503825E2A7B004EF2AE7526A0B7E7ED158992CA66804B549616EADEF84620F68571D4EE9F1566D64DD5CDDE1AD3694FE6295DEB685E999C952794666BD1FF0AB602D38AC3929FF00720B805AE3D7EE7A494B5A84BC8848BF3D03E9D78D236AF725B3AD6CE6C060384840496ED10EA931C2429E4A5D5748F789CFE35F55BE1360BE460E43803E8431B56DC78646B58E6FE235154D9ADFC722F4F747AF2CA33D5BBA3C24F1647A65CB21CFA0AEF4A67A5987A7BE778A6243121C1E5D6FFDD216F151D7E63F7AD6378AC104023434411ED104144105104144105104144105104144105104144105104144105104505694983AFA7EF4411E78A8EBF31FBD1041E2A3AFCC7EF441078A8EBF31FBD1045054D289F7E09E522474D3CA882105DBA97F957944E4743CBEF9E74410E59429B6D295192264D1042B44105104144105104144105104144105104144109389242BDE0001CCE9FB4D1045B57B74865478B88C4CC73FF1209F5D288225B0E75B7ED1B7384E723319E47BFC7D6932824921BDFEE32013610B2D694C8022798EC7B47C72ED4990C723CA164CA0AAD85BAB642FDCF78667124A16EB5C6DFF004C0993EF264492AEDDB23DE88DFE466DD03EB9790C83968B3711DACB1C39C2D2EEED9F79F3C286587029D0498F7933AC91F5A23030E4BBB86E5EDF87E229C130379EC42EB13C490DA997FC35DA367FE46C47BC5615A7148E1035ED35ACDC12B70AF79AD406A59DDFECDC21BCC1F2D401B17E3EF236B18BEC2036DF0B412956504F200E9941D341A77E906711FEB7C904EFBB1739F063EB0A84A481561A8F67B656A44462D78D7862DDC9487149F7E3DD94107CF5C865AE50273B1E1B63CD9F2FE605BB07202AB5C855B8D78F08748C0AE60DE410DA532D6F56EFA462FDEFEF230DDDFEC5E278D5E5C22D12AB376DED7C4586C97DE41619E19227FAAA4E633CFCAA8FE2ADB523C3B266AA7AFF008CB5B82A1FF13C5A8C73CB38525ECE5CC514A6AA494BEE976E63D75EEFA05B91B0C75DD9DBCC5B1C478DB41B497770FE2D7484AD41DB745CB8BC3F816A1C4A86149078B2E432815F24FE39F8E93B43C518932261DDDF50001D2F47A5ADEC760F0F608CBC000A71F4FF00B8D0737A57FB8D87B5BFF0D3FCB1E65E408010B526100E5993CB3CE73E95E795ED799356E54482753AB96E678826260E11EA92E03B101FB51DCE629F68B92D0165A4B4B3C4A124A939A7324C4E50454B48DAA809DD20BB5E8C7F5EB09893AB5CDC90694AB7AFE21DA4CE71A9CBBE83EB95426D19D3315BC104806C051EF42C076D7ABE486247BF6D10B70EA19B8216415023DD1911F1D7FCF6A811F3503E52F7897E94AB74A7BBBF96B4AA5697BDEEF5E9D876878D02E20B8AFE93600256E7BA8CFBFA67DF49AB16C7C3854E4AA60012487F2B3D9ED71C6ED1058993BD314A4B3E82FA656E1D58C618DE4E3981DCE2182ECE5C62568E8BBBA415B61E49092CBA858E313919194E875CB4F587C3618695370E5D0900A6EC0BFDEF566A5A12FE32D60A4BEE9A0772CEC35A8B746168DD2D9CC5ACAD3F0564CBCD5D7896D6E96FF0EA0B0809653F9A208D07F800CFD0AF00ED5C14991210264BFE2960142EC2FD0DB5E158A26D2C24CC4C954E52552824A89F9819C12599E873CED1909CC52DDB70B706404E4223300F977F9D77594B913E58989C44A0E0382A0EEC38FE69DA2AD2F662948DE4A98126A74761D34E70A22FDA5E8950F3F5FDAB55AE52003F3659A904850CBDE709CCC1290F576CEDD6D6E6444A34F23813C326674923BCEB07C865A5335E325A4B0208D41E5D3386AA96A45F26E07D8CCC0AB9099046604F0C67E5AD23331E94644962C067FF00DB6F65A1B99890ADD37E7EF5B3C788BB4A92094A927A1107EFCF3ED5A2768EF16DD20D1DC0CF8D7D2174A0AC021AB50FFD7AC565FF00FA89F3CBE84D4A4A0A58DE2CC6DEC0F7D9F3F2D4ED4ADAB4E5CFFABC79E39FFA8F89A5770EA3CFF119F92BE1DE2B4BB2341E99451B8751E7F88D770F0F7D2140A07B1FBD3AD6A43163946A43163945548AD6524D0306E756E3188A0AC0EA7CBFDD227120121879FEE0838C743F2FDEB231209018579C1092AE1093041FBFF34F512D6B48506AF4848CC67666E37F231EFE21249804C7435932D42EC1F9FE23433C26EDCF2FFF002848DE278CA122549891CC489F877A426A8CB2D4347A024D9CE7FBBD28635389A80002F9BFE3D87EB09AF1065B5842D412546005644F909FD67E94C958F4255BAA0D56AD3ADF8C60E2802C401DFB33C7AE2D2525D198ED9CE5AEA7FC548C9DD9A84ADE8A7A8346F7C6F02A7ADDC27E9362DDF87115ADA1AFE2D80095389491FDA489F818A658BC6C9C3024AD34A9721DBDF0D03830E657CC9A5820BD1A9ADBFBB738B4368F78BB23B24C2EEB68F19B1C1ED500A8DCDFDC22DD8000CC95ACE83E755D9FE2BC2C956EA88E7A51DCFBCE26B0DB1717894BA10A3C0073D83FAE91A6BBD8FE257ECB5BA7656E621BC1C171E75BE20BB3C0713B3B9B90A4EA0A14AD7B76A64BF1C60104825D9EA18DBF7C62CF80F87DB631D284C4A02378D1330282868E32D7567D239FBB45FC797D98ED31FBD6AD30ADB7B9B7B72800DBB366B4AF2FED21C00F383A66075A8099F14B672715FE36ED49005BAE74EB6E313137E16ED3C3E1FE74E22953BBBCDAE9D39C7537D943DAB3653DA8F77184EF2F636C318B3C1B17F185B5BE2CDB68BB3E03A5959525B5149F7812209C88E8455EB656DC95B51095CAA6F65C3D7AE6C639FED4D953366A9495D4A0B1777ED973D637090EF124129209131D3E3156058280F43C8F2E1C620D13378B311A93D721CA2AE31D0FCBF7A13F53366FE4FF0088557F43BE515020891410D431AA54141C47B446D051041441051041441051041441142E214329313D4FEBA510441DD61FE31396B3A67F5FBE7144116EDC58E2ED38A45BBFE1B00FBA9E25089CCCC69D75FA524B51721E9EEFEF9DA1E61D28287500E4E6389F7588F5D9ED01822E675CF8D47D7335A43A094E4057AFAFB31430E5C38DDED93E034FA1290BBB57BA973881885E731FBF9D101166715CBFA3D85333990D706D8FC2BDDBEB809BABB0A2A4B8785680AE23A1226040D3A40E704614486622D576F6E7215B68F1925A49084050485240108D0002123E1197A695AE331625C929CCD88E4D41C751DA18CD413535009B8F3F261AF011497614467AFA76EBEB1FE6AA5225AE662F780533DCD337FA587BB57368AC48954CC137F74A9A30A5E18E236D6D76DF84B212E6AD9D0A888309D27400E7CE3A55F25E32660A56F95B0082F91A248CFC9F4E912180C7294A00541B8CDB3CCB665EA0718E597B6FBB8CEF0369B61B73F845CB96CFE2578B7AE54CAD4996EC1D6AEA1C89905082065067400D78CFE37F8C4A7FC994164B058A13620F117BBD0718E9BB0F65CA9F2862124013189529A841D73FBD3AE68C1997B05B7B2B266D90CDADAD95A5B97B87852A71A61B69C515692541473CABE5CF8C14ADA3B5E762007056A2146B43E77A791D22FF00224A30F2848241DD01F7454BD6A1D988E2ED17336DA5E22E3C443EB4E7C2D90A333066333D32CE67CAAB08D9EA2E40A92CCDCAD46EFC808C198949284A4A121C1DEE232F4EBAC4DDBCBCDA5650A6C1905247BC08CB31F4CCCF5A7A8C1AA8198B54E8F95B8356D0D17300A3D4E6FF007FEB38916DAFFAC18D32FD33F5FF0074E656CF35A10491522CFE8D5E5943698BDEFF00711A9B69FD311C231A6F0F0ADA2C5ECD769B397D84D95E70C071E756DDD024E454532476CF41CB28901B004C4098CE74B922D50DEEA79624CC095AC12B3BCC5CD5218656E02B7C8EB801BDC96F571869C631BDBCC5ED5974903F95624F200049309E21D08E5CA9038656115BCCDBACC2D6ADBCBED1BAD6925560750CF4008E397DE2DC77D8FF000A7AF6CEEEEF6EB789738C30B5AFC7388A576FC64CA4A5447140F9721573D81E2B56CD5A1456A1BA430701BCF26A1E1A1AC7CC595294459C5412E4B74D2FECE44C1F731BCDD97BD373856DF628B602006138B624F129012520980069198CF5EF5DCB60FC619D8308099EB1BBA28F0E34F40618CF4A672548504AD2F621C3F1D4E5700DE2FDC3B6977D9B1CD2157ED5BED132C294A5DD3097EE94F02660AC91309CBB1CB4ABCC8FFA81DA4852509C5CD01C0AACB3578E435111337092C277004A5811BA96043BD59BF558C93B37ED2EC17136DB4BB3D88583A212A58B50D3614041CD674CE672EF5D0B617C73C562952D33F124A54D5DE27CCAABA1CF38839FB28B1DC52C924B6F3B6B4D2FAE7D6335601BD0D8DC7941FB6C79AB37DC88B4B9B94204CE49080499EBD08EE4D773F0F7C42C163928F99392EA6FE4A0D5B9A97B674BE510D88C0CD4072016D3F96879F6ABF01191BC67EF5B4B8976DD76CE094BF6EA2551CD5C432939673E75D7765EDAD91884A54B992882D5DE490F9558F971A8688C560D2545D2CACF7A84B016CE8C5BD6CF5B6E069210DBA5D4670E2D4173D4714C64646556F9123093A5A66A11294156290922F46A3380CED9C2C896508B330ADC96FC5AD9C48B6E92331946503AFAC79D23895A70E92D714DD1DA83DDE82125ACB543317E3C21D0526341E801FAD468DA254A6097E3EC7BEF0D97308B5341FD7E5BEF5A4A4E994F2FF1A7C3D69F4A9E99A2B43D9E9E46F639776EA9CB0ECAAD3A67D7CEF0BA220693F3D4D616A4A5443B935157E37FECEB0A4B51525D5724FDA2BA44A4ADFF00AE83DF38DE102412634FDB2AD7FC71C3CBFF00D608F2B230E9F607EA086EE708566067CC810329FBEF4BFCEF94022CD4B1AB572311B389DF60F6C8FD87BBC15A1C600F9B5873BD1F58525CBF983EA4D746A5CEA0E82185F3B656ADA5E7DC5214A39F86614A8319CC4C1C8672396B934993D0B503BC1D4ED5CBA16032275A43D95B3D730EE84D732065760CF907A88B3B6AB6DF65765B0F5631B478BE1985E18D214A55C620FA185A40199E224267BEBEA29B4C9725492A2536A03F661EEB4687B2B62CC98BDD32D4496FA98EEE84BF06FEE3955BFDFE30BECABB8BBCC5B0D6B68713DB3C5EC12529B2D9BBAB3BF4F8A50A29496F8C2A01D408CB903542DB3E3093B2E62B0C998A0A4B8A1A6BA81AFA3DA3A36C5F00E37192913552A57C823EA0C77EA28D6F4E85A388DBECFE3CBBECDBBBEBAB7DD3ECF613B3D8195AD2D398EDB3F6D8B96E4F0AB89973878C8CE4643280245738DA9E3D54C27FD4357ABE5C6B9D2F46D6B16AC3FC3D129BFD206B761992DCACDDDDDA39D3B6FED7FED39BF5C5311B8DA3DE66276F86DD70F16096D8B5DA18680490B4B76EB51090A1DF3CA6A8B8CF15AE62C8DF24AAF527EFE4CDCDA2EDB23C1C990A4112D346B8C9EE28FE51AE78DE39676ADDDA71AFC6DFE22B0A3F88BA8778972493C4A20E67BF3CA342C7FEFAB50BDE97AD69E9E51D4B65EC544B4005291BA34A59CF6EFC811185B0E606278AF05B3AB37B8B62D85DA35689325297EF1A60C379900A57396A290C0C85E2F69267392EA15A117EFADC6B5884F154E461A42E582032482006B7E473CB468FD14FF8766E72DF72BECB3BB4C19C6CA2EEDB0D174F248851388F8770272CC8F167EF2F5578370DB9869273600EB517E793B5695BC7913C598BF9B8BC44B3FED53825994F577E047D9AE23A1A93C494ABA807E226AFF882529000A65C6CFE6DECC52B0F55BDCB9278302DE7CFD60041CC5664972068FE6F0E27D52DA8EB710B2343E7FA0AD95FC8F3F4A42328302346FBC57588560A20828820A20828820A2082882122851513208310348A208560741969DA8821A3D6C1C515152B38C81D0F68A457FC8FBFBE9CB942B2E66ED353E5EDF586CAB04ABFB9D1EA63F4CFBD6B0B7CEA30207FFEA9F6880C6F6751895A1B66DE76DD6A20975A5702D4279A867A081D46BD0119130D492492D9E598EDCF8C2D85E088C330F45936FBCE2923375C502B3273CF4D39FA5119F99CDBEF639B5BEF12008B5050AF154948F796BCC99EA7A74E7F5A467618CF0031700B3FE3DF2816A0A41248B331390B505B87DEB152805A4B8D9E21049CE4E43B4F4FBD4AB84C0224A82D4056B517A93C3AF663157C6EF952B75EFA114390A7363722ED68B7AFEE12DADBBEB8712D34C3370E34851E152FC36D456540C03F964768CC542F8A368CAC360E67D607D2A6FA99AE3CECF9D4D6253634A9C54860E094B8625DCB1CB4C9BCAFC45DB7F691D911ED23B53798B0BA7F15C11E6ADF675868A14AE37982D5C00951E3954641199244D7CE8F8C38D9D8A9F88521649758BD0D59A8C19B2B47A5BC298290AC1CB92B037581340E480F9687BE5568CBB84E39BDDDBE71972C1BB6C1B01BA585316F8925E63134B6A5492EA40291C5AA0E85275E55E47C46CE54D9A4A85779553EEAF52D121B5548978829960519D839A00D5152D4BF03C636D763765EFB02C350BC42E7F1576A4F12E1456DF144C0E283049F5035AC4BD937FA43BB00C41E449B0CBCEEF15F9B8A2A59417E2A0EDA70635ED98117AB16AFDC3697941A41512385220009240D27BCF7A7C8D904B7D15F27F2D7422838C3533C2014825441B90E7BBB43D459B89E69D3BCFDFCB4D29C276492A622DC1802296B1E6FCDE105621F3B59957E6FF88A6E703B2B8683A96909BC2656EC09510444919E42227A6B06A625E125CA921012A2B63BD620F07F7D2F088C5CC44C505281416DDB922D723956A5853587B6B87B4D33C0F296A580608323CB965AC79F28A86C5ECD4CEDE0DF5170187BFED9A8F189B899A4FD0CC4DCDDB872D3CE133873438D456E05E5C1044089D3991D79C54327C3938A8B254483F4BDABC72A5A03314A29DD2376CAD6DCB3E6C6D94242DDF7521170195849212482441EB3D80F86752786F0E63A852086B81A5FD321F78DBE9DD26CAE19F3A738F51645B5296979CE1207FF001B8A2D8408C91DF9FC69E0D97324ABFD451749FE24E79F115AB7A65A6EA492E91FFCC456B98BDBADE2DCC67671389A148FE578392ACBC47191C7E64C6BDC472EE2A57098F5E09492950013A65DAB95C1343586EAC3862417E7DA8C29EF40D8C712DCEE1D8CAD6CAEFD5835E364290E614E861614731275FDEAD381F8838BC090113961233DE37EED969DEB0CE6E0D2B2494D6AECDE85F864F9E822350FEF4F7560376589BB8FE12DCC26F9E7AE6E3806790100E444E9A4559F0DF1AF6AC8094A71539280400CB56B5CC0E43BC319BB39054E101CEA32BE84B7F6D431943607DA57673137D9C07692CAF301C552AE05DCDF368B6B0796A248F016A32ACC00ACBF3111DFD31E02FF00A81F9B80932313892576FAD7516E24F13DEAF1058BC1A82D4121806B51DF2F57A74A46D2DA6236D72C22E18790EB0B48521E4AB89B5057BC08568723967CF4CEBD0FB07C6B276F041F9A0EFB31DE70FA82E5F87488C9B2181A392E0822BCDAFCC5697687CBC4ADEDDA6D450B794A2470B602940CEA474CB289D0E95D43038144E4158DD60017C8BE64B1D73636BDE21E6A56926967C891CBD3BD9E1F255C680E04A803FDA47BC34D47DFC6955484CA528A4BB1CAC4559BBDA90C26129C8F4BBBD843A654481FF975D79C5472D6EB22AE0DC9B30CBB7087D20BCB079FDA14592001D67EFF004A7A9237732D702F5261588EB8BC0C29280CBAE951CFC34C84CF33F7D69CA64EF237F7D22B626A5DEDC9ABFAAE5AD6AF71CE2BB8B945BB5E32C1298931A8F3F2CE7A4674829494920A998B7AFE3DD1F1112DE356F72B73C169D5A1A897801C19CFF74F633D0014B8952E6A77C9497147A9A3BF2F4F386C70AA98A4B7FB89B7DF367E50C76876B304D9AC02F369318C42DAC308B0656F5D5E5C3A96D96508924ADC3EEA6025524FC63484C7997252A5EF064BB817BD1AAC28EE747B9896C1E109989941277CEB6D79E8DA18E0A7B647F1CEF672DCD59639836EF71DC376DF6B6C92F31F87B4B9B5C46D9BB8014801286DC0B052A1EF4E7293A72A26D3DBF2F0FBDBA40A666CC2E3D0E61FBDE3666C45AD43E67D24336E50915BE7406C3A068F93CF690FE27DED2DED3D8CE22FBDB71896CA6CB3AEB9E1E0985E217564A530A51848B7E2289E18303204F3CEA958CF1B1438334B00400154CF5E83BC5E70BB092129FA0BB8A33E62BC41D7D19E352F655AC731FC4978B5C620ABB2FAB897738B3CA73117540FBE5F5E739E692732233E75CAF6FED39FB4710A9A851AB9727D2B5E14A748EDFE1CC148938044B28E7415E56B1E3EB4CDE19526DA54DD895369F79C00F1E594827B0FBE74E9F2F12A7FA946A6AEFEC657CF8C4E2A4E140277464C186B5CFDD1A14C3F6999B26CA584DB32FE61C7D43856E6A004A844C4C08EDD2929180C44D58241041CDF3CE95EC38E51A7CF91203A4806BCCB52C33AE6D912F18537938DCADEC41CBCC482585202DA65CCD7C6A480509332003249D055830BB1672EAAE14A6BD73CB8D5E31FF7C932412E2C74A30CEB95697A56CD1D0DFE14FECC175ED3FBFCC3EE2DEDAE2F3677642F70FBCC5D7768E34BC55C0FB019500524A16DFBFC530418ED7CF0F6C55267CB74BD45817A5DB8654D699C722F1A6DE42BE6913004905892181A80E6CD501AEF5CA3F431D9BB0B7C1306C2B08B56C2AC6DAC2CAD136CD2415B26D5869A1EE400904A24EA20798AF49F8730624C8410186EB579598F1F5B078F2FEDCC519939656A054544BA5D98BEEB74A3BDB52232234A3E1254A82607E5F8019F3EB53D8B6000E7EA3F0623F0409054482C00A5AAEDE5F8E752223D73AD30EFBC092F42DFDFB6873882C87F7710E11A1F3FD052CAFE479FAD611945C13AB7DE2BAC42B0510414410510414410510414410510414410520A0CA3EF8FDE082B10422AFCC7EF9511973A9EF14D106F1D4F7860DF8CAB8BA4BE10AB684F8204951CA4F148826748F2E735A9C5A650751B02CEE7EF4E7A16778C09BBC580AE84063EEC6A6F9443629B4786601875DDF62453656B6E852CADD86D30013CFDDE5CCF6D74AE6D7F1548C14A51DE09DD06AFA5433177763D69430FB0FB3158B50F9680ADE672059B57CCD581E2F1CDFDE56FCB787BC1C6F12D9DDCD5ADB5CD98E3B5BDC5313438BB669B7125B51C35E6090161255C53202C0D6BCD7E36F89328A66CB137250A9B5C3DF507A3F38B860362FF008DB8A5218674B659B50DC509AE9168EEABD92F6236318BDDB2DA2B21B57B758E3CDBF7CFED0A1ABDFC1BC1D24FF2F2A4F88D8014A8933091E9E5CF106D795B5A6AD5BDBEE54595506E0E64D281B325A2ED85DA3FE1CB32FE61960060A0A62E1A879E7964CF1B9B63B1D86E1B6ACB8C3447B89290E2471A724FBA3A246881D001CEB9D62B664B52F7D018073614CAA3EEF4E108AB6B4DC54D50984153B1527302C78DB8005DC9891B64F128B440E10787CA63491A7AD272F67241FE2031B8041200E55E34EC0C6AB98A0EA2C5DCDC9E1C3BF9522585B86FDC48303CB9E7AE9F3A792F673D5A8C031D682DD1BF30C264E5283871AB0A9B0B547BEE785D95F0FF0014ED1B2C33EEB16CC1AF260DD4F7D10F9A599D479B7A8CA3D09E1CB3F5D6994EC0284C6018756BFBB423F3EBE66833D6BEF8C7B4A48D9C1C2D6064F47BD6AFAE5C7BC3844DDE00062D71E9D385E8D14139E5F993981C8CC4FCBECD4EC8D9F86491BC9191B015E7D87EACE12A041191BEB476EFCA1322091D3F6A974C9C24B05928A248A00F6CBEF0B82E1EC4E9CCC56940201CF3CBD7A695CBFC452A69C72CE1DFE5BB0DD2D95CF3F57845530A0EED2F753D7367D6A2CF9F5ABC2ECAF87F8A869783C44C0CA4AAA2D56E1771F9B88D7E6162412599EA73D397210C8E0F6C1F55F2DD5071504A240D073CA7A7E9DDEA36229406FA40725BE9E37CB3BB346BF31CB6EA8F162C6D639F56D213B976D5D4969DB64BE902389490A1D33F3D3F4CA96FFD3A08344922D720F4AD9C3F93C6C4004A98BF07E568B2368762764F69EC97677383376D7290A2DE24DB084396EB2642D0F1CD241CE6397A544213B4B66E387C952D3292A0480481A5851E95D7267845782DF3BE405050240CCE7A54B861E4D5318B707B4DE4EEAEF14EE0B8CBDB5FB3A544B96F7AFBB7CE5AB4924F0A12004208048E7A67CABD2BF0F7E224ED9864A67E216D2F75C1516AF33F8FC4362B6703FC5212EE2A08347B7EFD2367776BBE2D99DB05A70D52D16F8C3502E2D5CE04A90E1904044950CC73123E75ED1F097C58C163254A926783BC00502A1C19EAD6627D728ADE3302B1FC523743B8CEB9E56CE8391158CEC16A2DAA0057BA4A38648D32E5F0D632CABB16076A4ADA32C2A52810A17497EB47CFF262066E1EA686DA6432D0713C4F111E58ADCF0506E3DD72552279126358E47965D28988DD9B7725C9D052312D3BA902DC0C3C52D2A882329D48EDDE9FCB4921C0BFB17FB7DE3788F7D01FE34F8A5942735ADB3C2B3D33CF29D7D7AE44E9A99128953BB6593E5EEEEF187AFA9C873310B718B58D95A3A1E778AD5A0A2EDD5C94964093C456BD00027B0EF3548DA9B6C4B593BE46ED6FD43D6B5D736BB53748ABDF22E282A19B9F7BE4CDC7DF6F5FE2F5ECE3EC4D86E202E2FAEB6C36B196969B6D9ED9272D2FCA6E4A6129BEB6E30B0952C8200CE388C659D77FF5FE1E4A861953909995AA94C2E5DFCEE6D5368B56CED96AC44B44C4A014577C815625830B39B13C0B111F15FEDC3FC6A3DA8BDAF710BDC3F0AC7F1DDD06C3DE3AEB565846097379818BDB75A8A529C4184AD4DB9C42240CB356550FB43C609C4AD72E4CC1398FD664AB791517D0EA7AE6C22D5B3F634A97BBF4925FF92C7D4FABF0A7ADA395F84E078DDE622EE33893ABC531ABA597AF2EC294F5ABE552A0E070C2D4B20F12C9D5649E66A83B4F689C5297F2D4ADD36DEFE56620E82EDCFA8BF6CDD9E12120A4134AD08EA7FAD38C648C31FB5FC4A18BF47E19F1C291E100949E44C9CF21F03C8553B1180C5CF5B82ADD7767367D2FEA783C5BB0F864A775EC187D5567B90E07F4C4466CD96B816F72B6997896C04F01E29CF84731D3C8FD625709B2CA640F989753177048F57B171CF361163C2E21725210927746552D7FEE9F78C86E5F3C2D5E01D3F96667E1AC1EFA7956B330528120A6A08CA9D72E17ABD61EAB10B2C9049CCD781E6F4BDDCE6498C4B88E32BB40E3B7971E1B685136E4AA38D45449199CFDECB2F8D2B230B2CCC0C81CC0A3D05B3BD39C44E3A74C092A06CEC3837524FEA31DE39B4F717EB16CB42DFBABC7ED6CEC6D900A94FB974EA18494A355105C4E911CB4AB56170B2804B804532041AFDF2EFC22998EC64E439DE51BBD4B0FEAF957B1FBF2FE04FEC896DB81F662C136DB1FC33836D36C6D85D622A5B205D34D78CA72D64A93E20059746BC87202AFFB0B67A4AD13129B33306BD1B3399A76BC71DF166D19931464A95F4AB789075150D503DF48EEFD95BDBB3C4A67371E990A8CB52223489CF90E935D87038712B0E80C599C96BB0CDA81B839EB1C7F1B89F9B3D8549D7514AFB01CDA25D8694D3010A571112A999D4F144F3A6D8E98CB1734A0FBD876BB44A6046ECB2090E58D0713FAF6F0A224054093965EA6B6C2972391F407EF0A62BF80E7F88748D0F9FE829C29DCB97E36CA1293FC7B7A98AEB585A0A20828820A20828820A20828820A208283404E90426A58989223A18EDA73CF2D4532F9DF327096902B4734F7CCFEA36092438F7EEDFA8A38D3A052893DFA7953B54ADD04BDBDE43DE51A2F7902A070ABF93088C77114A2E0B1E138B331C604A64C6A67BC9903F5AAE62B6D4AC24C3294952C82CFCDDB3CF2BF384C6F28D378F04F36F7ECC2AE5DB698E24AF212A29CF834FCC7ECF6A98D9D306D097BE92CE1C0A7637F6F0BA70EB51DDDE21C3B17B67A03FDDE2DEC5B1FB3C3ADAE31572ED962C2C5B5B972FBEB096CA5292612AD388C10419CFA662A9DE2CC6AF65AD692ADD090A2429B9D5FCBABB185E56CC9BF3A51049269BA5DDBB5732281E39D9B7BBC0DADF687DA0B8D99D8470586C8D83AA6713C56E54B698B86C9215E0BED92DAA0A5691235307531E55F1E7C424C84CE97BE428053170C2F6FC9B9E317DD9721184402A439A1500DBC454D985B36343934664DDE6EC300D8AC0DAC330C75C200972FDA523F10F3AA3C4E9538912A4F19504C9FCA44F39F246DEF16CFDA78B5844C56E952AA0F13C69976062C93B169284FCA4A0518850147A061C5F57A5728C9E30D65B4B4D332EA1325C5BF9BB394709D067DE72CA29FEC3D978AC6292BDF25370E4BD6EFC2B50D4E358AFE2FE6CC7650E0C580CDECF7A1C83EB0ED4DDC7861A4B9C484880567DE8E84F6E5F0EF52F8AD97364CCDC25E81C1BBD6C19A86F0E30A7E5206F01BCEE5FF007EF46786ECD9B8DAB889124C920F3EBA09FF0011148A700C5C8F2ADED63966E4DEA61D2A7053B9150D70C29CF5FCF08921319EB4ED18548CB93DFD0FBE10D94B2682803DA84F33EC426A7529E44CF97EF4B09433096E03F50814A8DC8E4E5BD228E20A923E741C3CA374BF36FC424A9449AEF1E469D29482B53874D40602CD6B743E50B4A0524124B747A0A353D6E1F8414DE648985B74D9E9563A519BD5A1E226240AB5793F23584CA0924E59F9D47CEC1E35544CD2903FF2229470DC7CFAC2E89D2C2402AB727EB0BA084240CCFC2B28C3C84A00C44BDE99A90E686B535F2E1C6194F52A62DC1000E3F703EE62AE31D0FCBF7A5449C2972896906C1C0A33F0A75E9946A14A600914CC67A450596DC254B52E0C6423C8EBCFE548AB0C924EEFF10EDD790A6679E90A198A09A11BC727A0E2457850FEA02C3491FD3409FF00CB9F63CB23CFE1DD33849AFF004EF30E0587DE83EF78513369F536562D6A171DC8E6D10EFD95C5C38A0F381A6103DC4B248F132829781FCC397918D66965E0F0870FBB3100CD62E480E789CDAB6E22F487D2F1084A494BA89762AB26AC4A4D18B1B0CF85DAB9625F49B77382CAD888526C00429D11FF00ED1A2A7B81A9EB3542DA88C5E1967FC75196905C6E929B170E539DB33D2D0D66265B28A54A528D5D4D47B80EEC0BF105DAA5846BD6DF6EFF0013B1C5DCC6F76C9561F8F2B85C78DC4B56F745B0090C168712D5C20F10CFDE396822C7E11F1963F6762A4A66E21659401FA8B1008096CC9D72D6EF11388C2198414335406E3776D0D99B3E117EEE67DA770EBCC753BACDB65BB85EDCB29F089BC29658B85841582C970F88B052019E73CF9FD00F85FF001230F3244846217BCA5000B9A1714BD620315B266B19A94B807EA09FE4C7986A3871F88DCAB3BE57876C8BA520BCFF00190B41FE9848CD3AF2298CF31CE73AF4361F684ADA4533A5325243E42841E26BD74CAB159C4A55266143021E87D5DBD323A3C4938BE00550549001E2198331A7589135609612100EF2599C97146615BF6CEB1B4997F3684B1CF2D5A87F3EA230E6F3B7C5B2BBA7C32E718DA3BD69087504B5685C407AE1491010CA164712B888100EA467A550BC5BE26C26C991314B9A93BA0E632E9A8BC4A61F644D99BA405104DF235BF12CD4EACD6E6E6DB6F5F7E5ED28B7F01DDFE16BD87D81794B6EE318BF62E30EBEB8609502BB47DA25B59D609C80226BC87E34F8E7B3F674C9C962A3501B758F98EED46A71964786310A620B39760F605F95A3125A7F0C1F673C69C462FBC5C2DEDBFDA0716A7AEF10DA466D71271F7D47895C4E3A9E25210A242330427872E9C2B1DF154ED19AAC6C898B421C90016A0241602D6F4A5CC741D8FB31586C3225A92193725EBE55E74FCE16F685FE0B9ECADBE0D9C7ED304D9AB6D95C69B6949B17B0AB4B3B2610B2212A5292D9500204C09E94B6CBF8B0654C08F9AB05446F1DEB9763636A1AF4CA9328F9685329296A1147B54BD28F947C9E7B6CFF000F9DE87B186DE5CE0B7B762EF615E717FCA719B65BAE043613C4A4DD5C1425B1EF282120089D6BB3F87BC6183DA625283998AAAC16297C99ECF9F6033899C16365A5410C2AD6CA8D90FBDED1A02EB88B0B979448BC55B94153AB1C725794A5594C48E233D72E47AE6CE99849884A952D2491A034EA4F5A18B4E16626687B0CDC50F56C88CCD416ADA2ECC27690D9DDAD65695A161247826502139807491306329EB90AD316100ABE52581B5393861CE1D89E25CCE160722E2D5BD74EF172DCEF01BB7B7712B0F12A040800807389CF4FF0476859A852890189CAB53517BFBBE50E918E949014402CF7FC57BB4611DAADA6B9C6826C9A2E361A2B5B4B54849CF8B32390233D2233E54F307B3E6CC50AD1FB1F5AFDDF9C56D1DAD21285380287477ADC5AF9DA3AA7FC1DFD86B6EFDB13DA576371EC730A69EDD76C2DE1BADA2BDB961C55B5F29482E590B470A4B2E16DF6929702A20E99D5CB67F87F1535490154A67F4B1E5996A5F80731CDB6B788B0F21330A81234003F02DA0ED4BC7E93FB01B1D65B21B278760382DA37656F63676F66D5B9406DB422D9B43321090350991020FAD752D8BB25785968DE7269BD5156F2E39FDA38C6DDC71C74F5A83115DD29A5C017D403C8DE2EE4E1A5B750B4A885092449E193398112739CFD7CAEE89E94CB32C83BA02402C09D58EB9FF4E6291330330CD0B05AEF52280B0E41FCF8C4A21B73800594F144652447EFE597D2A33152CCC5BA012D6BF12D5FDB651338649948017FC99A99313CAF7AD7BC7A968A673067EFF7ACC80659FA816B5AB61A429387CC4B0A177ADBCBF10AA41020F5FDA9C13BC49D75ED09CB414062DD3A9FBC55588520A20828820A20828820A20828820A2082B06C73A1A6B04357092A910620C73F874D29B09252AF9C4589ED773A7E381261647F11D7D63DE11911023CB39FF13E5F0A5D33E5CC05233A000F31521EA74E7570F084EDEAB351AEF4B5BEF0D9684A5D04244281E3312721967F4CBD73A85C76C413D66600924D4D3215AD037BAB08DA4122C0F3AB7E351AF1CA20EEAE59B017F7D7AF34D61E96C952D6A00200499CC809198EDE672A8A3B5E46C1428CD584A520D5C0667E79BFA8689297294A28009330FF001EBAF0229F6BC6816DDE37B53BE6DA4BCD8DD8CBA5586C660EF70E23888716DA71343A78D6961D6E5B7BC35052083A695E6AF88BF12E562F1D3A5A673B3815A160455F419F48B860F0DBA8131613F31817D1A819EA1F3F3E394763B63B03D89C359C23006529B27004DF82948B953B3EF28F04020B854A93CB3CEBCAFE2BDA29DA6B9A42C2829F37B917B8E033B7030FC214CE48278753F8148C8ED5A316484DBDB28ADA4E609226559A81390C8935CC8ECCF95882A6DE0083BC03839973D79035B4094A941C8097CB870A690FDBE7E93F7F1E9F3CBA06C4C6A70410924815AD038617FB76D633B8751E7F8852A4F138BFF2166685120B541AE9C1ABEE820DC3A8F3FC414D44D39953F03FB8370EA3CFF108B8E70923E9AF2EF59F9BC55DFF0070141CABEF8C3271D83E5FE34CFE347CDFFE6E35FDF383715C3BDFDF1685DA3C4DA4F6F8E7AD1F37FF009BBFEE0DC5708528F9BC55DFF706E1D479FE20A3E6F1577FDC1B8751E7F8828F9BC55EFAC1B8751E7F88294FF10CE0666EBD9BD34A59E33F2D46CC7BFE20AD0E1021C6E8074A7DC463E5A8E9E7F88A82E0465975EF9F5A6EBFA32A644501F7CA32259259C41E2F74FC7FCD22AC484D013C2B4E8CFDED18F96751EB0D1D77357D807383DF5FA0CE9A2A7059D586AF5E27DFE5D252C18A401714D5DFA8B70866E3A0F383CE35D3CCFE9F3AACED762853598DF3A12FFA6D2B19DC4B73E6F4E74AF0885C55FB8B1B471F48438FDC148C3CAA55E004901DE23FD9C40F2CA35E754A933D3227A565552A1BB57DD635DE177E0F58D0A415802C9BB1707EE465FD574CB7FBB977B6B311B0DE56C95D2F0FDBBD970ABFBD5DAB85A4DE21094B81B940F11CFE8B452412012632D0FA3BE1EF88132848054CC520DAC14053A1F79EDBA4EF02DBA5D801A86AF2BFDF4CA7ECA3ED9580EF81DC4365B1B4230BDACC0128B4C42D710E06431F854A9B2E942945690E2195384919EBA1AF7DF8476DE1BFEC72F10A9B2C112E84A9896B76AD3D9A86D2D8E573153132D4402EC915AB87000635ADE9D1E28DF57B746CDE07B46E6ED776CEB7B59B5C54AB774618A45EB36CEA9328F13C1571A0093AE723C85517C63F1651B2513512E781BBBC1D2AF3BF00F916BDA37C16C73F4AD482294045B982F4EAD666B0C3381EEA76FB7938B33B59BE4BC7EED9B858B8B4D9F4ADD5DB59A490A48FC2BE084710E052A3533E55E57F15FC6156D33364AA7A95BCE03ADF5E3DC5338B461309B80580160010389CB8D73E31B8786E0D6186616C5934A4D859DAB6136D676E435200192DB040CE01CB339EB9D712DA32D1B794B9AB65397AD49AFF006FD2A1844DA48410000F99E7906F74D6B0AA5CF1471F006C49012040001C8C752209EB3355AC561938196A909002402E05B33E67DDE25E52B725303900C59DBF157CBA45550D253B93D243B3827A0E99FE61B2D2E4B8A5DFDE6FEDA39EFF00C4A7D97704F692F672DA8C1C5AB08DA0C3B0DB8BDB1BB0848B91F850BBA7385C82B1286B87DD1A6B3CFBD7823692652A424A9882C43B5A9A9B74C83DA16C0CB22728B9214CDA0028D90ADCF334D7F3D2DA1B16B66715BAC19E654F39657F8A58DDF12415715A3EEB08E2D39B79157975AF56F87B1699F2905C10522CF980DE6743ADDE2EB83514802AC59C727AF95A95B8D71F5962096C9466985AE12A1060A89032D321979CCD58A724A8D29C6CF4D58F935844899617F5172DDBDE66FDA14C4F1305B3067DD33DFD674CBFDCE68230CEA0A22B5BE872A0ABD33E30D27912D0541419BF8E46BA017E59579C3EC5ECD637BC4DB7C1361F044ADEC5F6A313B2B2C25A6B894A2872E1A6AE8F0A7DEF75B70A8C010019D60D8F676155BE9A549C85068F6E428FC294A36D9C7A50140920006FCBEFA77148FD383F8597B1BE13EC77ECE9B05B0C8B060ED462F8622FB687130DA7F101C7D28BC612E3BC216327783DFE4234AE95B2E514A529003D1DF2FD373BD9C57906D6DA2899355F52884BD07F153BBB9CC69CDA3AE167C66DDBF10242C0293C208100C0D7392209E5D2AE5202826B66D69937DF93C5594ADF2540B82491571D21D4099813D79D388D60A20828820A20828820A20828820A20828820A20828820263A9F2D68820A208681242C922049F9CFCFEF9D656DF254FA1EEE47DE164FF0011D7D4C567E3E550924B4D014480E737E3DDBBC22BFA9DB36F2688176E1F55EBD6ADA92D9F7787C6301C912A2D811300E7940F2CEAC7326E1E561D3316A0FB8A26A0E54DE7ECFAE90E64A52900A92E4359F8B3DE8DD41D234AFDA1B6F71CC5F6AF07DD46C4DD326E6E14E8DA4BAE35163096F843ADA6F548CD83728E24B1C63DF30398AF1E7C61F180C11C4A24CE228AA24B53BBFF0064F3B3ECBC3A66A1334A46F1D722096637D3B9CE2736476551B35875AE1F62B0CB366994BAD9097EF1E7614F9BB23FE44870A8B71A24E7CABE7EF883C6B88C4ED25FFAAA037D55735726E5FCE9468B44A9094824951DE1549341C86BC7F4D7BDBDA9171F8D7084BCAC94D23FE088E1E2819F16A74D49CA9CECFDA7FE531592A7D59BAFDC5BB88544B480C09E04D48FB7944BF0210785B2A299C8AE264EBA72074ED560DD9653BC012E1CE84578D630941DD01443825C8170F4F7E50F112013AF413D35CBE039D454FC52A52BE82522CC29AE9A91ED8C6CA4A697D037BE66292F2418827AE83FC7C2A57058B2A940A8DF2068393D89CF3F383743DBCB9D9F9E547F2F3C71FF0053F114F3FCA1A9FF00EA1F98CB0D07610D5E738946011A73CF4E51F7AD63FC9FFC8F71F9BF970818683B0868A4A892441E809F43C88158189FFCBCC77B8F7DE061A0EC21E30785B4854939CC79D60E24E4AF31FB818683B08578C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDE8FF00255FF2FF00EE1F8818683B0838C743F2FDEB2312A71F5663307C9AB06E8D076838C743F2FDEADB809C9387493BA685F9F11ECB528C6022C0123967941C63A1F97EF49E216835052189766AF36CEF7FEF0520906CC5E99F384D464935018A9EC0A4101AC469F7AFE348374053F0B69C63CA839B88DDB9AE8F977AFBA5E009038F3860FBC12E2926728CB91CBCFB7DE74CD38B4998C0DC970FC082E01F3B5DCE65D210E12EC4077198734CA9C61929C2A39653AF2F84534C7A3E64B531269C686BAE66F67E758DCCA4BBE438777A57852FE69BC8B552136F745D26F012DAD59A590DE64B44FE52ACE48D4F3E55CE31E172E7024167B8B38201E1957D18423F2C6FB8FF0069B0A9BFFB9BA37DE2DABA4E1D86B57CFADD0E61CCB4BFC5BBC414E94290A1FD654C70415083309ABEF8576A2E4197F591BAC6F6CEE39726B17221432986E9DD0A361CAA47366CC671C32DB0DD66DAEF1FDADF15B9DC762EC6CAECD38FA5ADAAC4F0E7DCB26EF90E5B1427F00F5B8E071C6E5C4BBC792579098AF42E07E2A1C0ECC18233C83BAC06F3573ADF2D39BD225A4E065AA4EF280B5185DEEE286ECC0F6CE3A59B89F642DDFEE52EF15DA0B172EB6A76BF1816EEDE62DB49E15E3EC3C904BAAB67C00E264A9404C9223A5722F1778AB13B5D530A6728EF12CCA26F77AB7A733708CCC2A0252120005DC9A10D5191CEF9F1AD36DF8906D92C3656B0911E33F9BE0F31C407E549C9234E181A571BC527186715EFAF77789724EAE6E5A909A30CA4555BAE1FE94BB372233B9191B3188F71588A53E0B2CD93CD2A789DB9054F0067349D01CE0796719558F666D91839604C249CCE766677B758D172AA9980A86E9A007E93615705EBC7F6DD09FC3FF4497164192B3EF66ACE275806009E5E54DF17B4938CC4BA4BA4F4FB56BDE967021D4B5A94002430CB53FAAF46BBC2C0CCE4479D26A414B4C71676177A9AB5A1DCB4B800B91C74C872A7E22036A70D6B1EC1311C34AD4D97309C52D9C4A8C21C17166F37A664E4A8F3D62AD1E1CDB22462A5277C065005CD4641B9F57ED0FA56F61953269495209484253553D89577E62968FCE1FDBFF76D71B9BF68BDE16CFB1641AB45627717569E2B640578CA76E1D288024CAA7202799EBEC8F877B4062E549ABB800BB31CDD9F9FE22C52567752A0E1C02791AE5A3E59BC73C6C31238978778AE161370B7810A3C21AF09453EF8D13C6734C6B945762992525767A03C2DAD4D5B83C4E4B989F92096E2EC4F1035AFDE9085E622CBEF1B62F21840506D574EAB8584B8A84B4852F40A757086C7F728800666A470780F98A480379449167A0FE9FD3855F6B6304B0ADD20000876008F4AFBD5BE9CBF8057F0C3DA1DE9EF2309F68EDE9604E5A6C86CC3EDDDECDB57D6EA43B71E282DADD425D470293C694AD2A428120826ADF80D9AC5F70D19E99D074AFE9E3906DFDA43EA4EF92B3BDBA1D817E14F76A47DEC5B60F6966194DA39C2CFE1D86322250DDAB4969A4B519084A52083CB402AE184C304904023785CD05079380DDACC1F97E371049672497A641C9AD34FC708BAAD0CDBA0CF16A27AC18CFBF5A9C9619091A08D64282A586CBEE4C39ADAAE2CD9EBC1A1682B30414410510414410510414410510414410510414410510414410D1C5F0AC891AF3EFEA3FDCD65C2D1B82E72A645EB58DB786EEEE7FB78A3C5EE9F8FF9A8AC6CAF912CCDCC027B5ECD93FB35D635DB7FFBD7C3775BB3AAC75E702B1828718C1EC10525DBD7AE3FA1C48689973C25AD2A907DD1279E7C4FC69E3D3B2B0F365998A4965004A99E95B1BD7B7689AC1E1C4C60A70090F43AFA5188AE547B6ADEE7766718B5B0C5B793B5FC573B47B6AE21EC6D2E7129766D30E2861C1A0B1C6D9532A471956B1EE98AF0CFC42F162B6D4D9E04C2A0EA04825EAEDCB2C9BBC5E70125084A120252080523DF0BD5DEACD48D85B17416112A99923FFA926075C84039FCABCCB8DC2CC38B54C20D54E1F2AE629476353689854A19003570C7D2255B74189D0F2E533944FF008CEAC3B331064EE87634B919599A9D4D78D2032D346038D05BDF778ACDC42A24F91D7E67F71156D97B437D206F0B35EB600D34D73A5E0328640371BF90872DDCEB9EB1CF3FA8D7B99CBE0DA7054E2FBD7B1CEEFA311EF211A992ED60DA7F5142DEE2513273E93E5D7B67E7CE9FE154508DD2E1ACC7524BE46BFDB9AC6532D21C100B379BF28A7C5EEAF8FF009A75F378ABBFEE37F968FF00888A819CFAD1F378ABBFEE0F968FF88828F9BC55DFF707CB47FC447857C2624FA7FBA3E6F1577FDC1F2D1FF111E78BDD5F1FF347CDE2AEFF00B83E5A3FE220F17BABE3FE68F9BC55DFF707CB47FC441E2F757C7FCD1F378ABBFEE0F968FF00888F3C5EB3DF3FB9E7525276B7C997B80B76EAF6AE59346BF283D83720FE8D1EF8BDD5F1FF0035A4DDADBC18967766F7C6B7318F95C13DBF5078BDD5F7EB51B3717F308DD51CE8E1ABA0FB40658C92FA9200E4D9FB7178F3C533CFCE73FBF5A66B24A492493C4EA7EF1B09696A80FEFA53AC47BE789C51CFD7EFD2A00E20A71052E5277B2350DEEC05B5685E52185817EA5EAF97B109559D28F9D87A312D5269AF6A690AEE876DD0FA35619E2171EEDBD838827F16974B57490786CD2D82A70B8BD1B0A00E63588D73AA76D4C12B7882D7A70E5616393F1840A1017F31949DDBB00CA761AD5B96B1A75BD1DBABCDB0BC7773BBBA7DC7B115BC96B1FC6DB59534DB2A5074A7F10D9E20435C6885039E54B6CB92B97BA0687AB545B8BFBAC6FBA972B20BE5BD91AD9ED761FB78CD3BADDCE6C6EEBF0A69BC30B5797EA6C38FDF39E1B8F3B70E8E3789740055C2E1508E5E750FB57138B958F212A59008A034ED5039106B68728C5A952C2024A124B7D4E0E840AB7BA59865AB14F0979F5C80B981CB2072CF969E8672D2A6366CC1380F9C5DEEEDC0D457EFAF11BCD595EE84814A123B822BA8B9F2314820C919093F5A90C64AC39964A521C0B518BF072EDD2372779B80CEE48BB0FEB8E4C551F68485851129C81A3FDBAB7611A2A56F26A2952458B67D73F4A9A380C345A0E1002889E84C1E672FAFED4C367A9631010B777CF2B75A8E5AF2604AA5CDDD043037CD8543F1A1FDC435DDC30C922520C99394F6FBC855D6724270BBDA26ED4B015F6EE468F13D8594A98000EC4DF4FC9E432A45818FE36AB76EE5F6B34B4A6D2A03FB83A4214394829267B738154995B53E56D0090B23EB19DC38AFEBA0D0582448489441009ABEF0700E4D42DA6BE71F187FFA81B65B08C037E5B0D8F61CC36C0DA56F1255D38848485A99B46C09226482A233F809AF777C12C48C56137DCA8A44B097399A171CB5E22968D1531686046E9259920330B061CF2CA8098F9AFC6F16C3F01B753EA32CB6A507594C12A2EA88494A4E47878B889E5F2AF50A2415CE09A0700D4DFE9E5635A67D5A155E384B90EF522C1A94CC6A3871615AF4A7F8567F0FFDA8F6FADF5607B3C6CAE99DDB60988DADEED1634A6D69B7BB4A568BBB66937052A65C0975A2D2C2B39C84E756CD95842A29DDA1166B9BD68294F6F1CFF6E6D51BB30EF1000CCD0BB017273A796B1FA6EEE1B72783EE3776F816EE764F0DB2B0C2706B0B5B44AED594B4B70B0D3695AD65109254A44CF73ACD5E7098408028038161439FE4E669D0F25DA78AF9CB2B2A721D8136F6E3F119BDBBA6D572D59356EB86C1F15D08FE9A4C1391CF5333D0CFACAFC94A4DB26A5037403D88ADA91BE52A193820F1EFEDA272C8116E906322AD34D67D35D0D6C030034871292120A4351AD9DFDD6BAC3BACC2B051041441051041441051041441051041441092DC28272C873E9973CC51190926D5EB088BA9310358E79F97F98AD54ADDC8C2BF256CFF004F272FE622B55C25313AF6CC72FDFAF23956A99814486208B8BB7BE0EF0CA7CE124805DDF2EBA8E51EF8E989391E5D23E3FA8A5189200773661EC778DE42FE6B310E6DC39E5A373D18C44BD769F1C85B6B6D103FACA10D679895729981DE7589A692A72A5E2F70B14DB4B86D4FECF3A3954B09CC96B817E94108BF74DDBDB3B74A5071A6D0A7096C923810095A87284804AB3119926293F104E4CBD9F3959EE1672327CADC6FCA1597237949033A17CB9D9A85B4B738E66EF0312B5F684DF658E1F863C87704DDABEE1714EA81B2C4977AD85280E194BAA61C411C8A142BE76FC62DB13C4FC42113084EF29802697B6597A728B66CFD9EA202897766EE351CA9AC6CB216C5B617716EA6E5B52186B86253FD101032D2047BBA488E535E503B4953274C1314E5C80F9B12736CAEF61C62F385D9AADF9403020135BB90FA66F5F2E3E32E301094B4AE28049464548E70A1CBB4F2A8FC62A52D5BE12695B720D7BB77AB878DF120C89850BAA8163BBAB73CE9D4C4BD9A177297148040409F7A73D724F726047523D22D78B4CBA80435DAFECBD7D61B7CF4DC8507B53F2DC871E8ED4871C9250E36648287010A1048981391891FAE54AE1B6AA779AC468CF7E9D69C236131EA283DBF6AB5BB42C8511014A1EF0CF3CC40CC1CFE3C888AB361B1E998016A0E1AF31F717BD046DBE38FBCA02F804C127A9075FDFEFBC2F33692504B120E675D33FBB508D21C4B96575AFEFCFCBFBF3F11D95F1AD7FEE5FF00946FF238F9FEA1637ADB2C29D5C908CCA47E6CC9D073F39AD86D548A10934B92470EF1A192BDE0901DEC6ADD69FB8A9ABF6DEB537694381BCFDD508518E83E1FAC56DFF764FF00C5376B9F7CB58D7E590B0870E7476F4849171E3B62E129712DA89038801106338319F5A708C57CC1BC081D5BEFEF58D5437494921C33F0F7EF48F5B790EAC368701513192B2FAD6FF38FFC8773F98D49090E6D0E5C696DACA0AC122261479FCEB266A8162A1DCFE6308585A428380758F034E75CBFFB4FC2B1F38FFC8773F98D89604E91E96D43FBC7C48D7CA4FCA9BAD13261041735B1F5367A7BA460170E338F3C357FDFE07F723E9594CB980015F38CC78A42BFEC08F3FD33FA52884AF371A3BD3AFE3F3047810A9C881DE48FD294620124B8639935CBCE084D6CA8AA6419EF303F7EDF6602660662B1466B9625D2EE4039BEBA52B6BC2889BB818B56CF7F56F3D2F08A93C399223D7EFB0EB564918B461A5042EAC2EC3F67D3362F0B09C86722BD1FDF0AB6710B7D6B7AF337EC34E20377CD29AF1164F8B6E1485364B247E59073EB94F3A88C66364CC0A1BA93BCC5C8167A65D385EB684D6A96A5A16EA1BAEE9C94FA8A8A1BF522AD18CB77DBA7C0F60938B5D3015718B62AE788F622EF0AAEA38D4A203A3DE02145226721F0672368C9C3972C0E428001CB5F3E548D8A92A2086DDCD3404DC8D7AD3B168C9565656968CB6DCBAE25256A2550A24A8F119E5A939F6D2A1F1DB4708B9EA56EB92694A3F91D47E21352492E0539D7ABB76E668F14DFB8EAD4916BFD36D260A55209197E58CA72E7A914D65ED24053CB05366E87AB0C8DD898565CB5937625AEE3FBB5790A98A537896C04290E123290099394E67BD3A1B494AB971A1A5F32286D0FD1254F5151D5C6B407ED96B0A8BB6C988503DF2FBFDB3A5D18CC29ACC48720DC03916ADAF6D0E7A29F256C4D2D4D7B1F7EB0CAEF186DA429B1C5291C898CE35FF03E154AC66D49387DA7BC94B277B40C187B03288B9B839A6782092E680660D0FEF219877318EB17C5D6A51E02A19926662750797293FA54D4CF14E1A6618C929014450903833D726ED16AD9B86504A41760039CA8DC75CF964D1108E0C4ECAE0282B85BE05BEA50F7441E240933055103AAA0D57F01B326ED4DA09992CD0A9269A13C34EB4E6626CEE4B60A20153900B396E17A718F91BFFD484965388EE56F30F69C4DFDC1C7D29B72902E5496BC24A961033E10905733F973AFA0BF03B616270D22482BFA1613BCE7316C9FC9C6B1158A989492A72082F5BB68F6E6EDE91F3C7ECDDECBDB7DED69BD9C27775B05862F1ABBBBBEB165F79B69DB8B1B265C71B3726F94DA54507C2F10A0C47109D04D7B1F0BE1DC44D289A934212C43E8D96AC18778E7FB5BC4F270D315209D453859EC7EFCF2FD38FF00868FF0F9D8BF61EDC9ECD6C761163871DA4561ECBF8F6256ED37F8979F7909B8E15BA948510DA96B400A04A408EA6ADDB3F64CCC3EEEF176E39E7EE833CD850F69EDC978A0A42412FC3E927537272EB6A474F2D597C2C2CAA19CC04926739991E64558A58DD46E9150C05F2BF7FDF3AACE5198A26956FB7A0F4859D65F449B54B0952BF3150890489CC769FF0035B924E64F38412863514D29EFDD61DA13C0909D32CE349E7F3AC428000ED9C5744660A20828820A20828820A20828820A2082880D013A434715C4A52635D0733E63CBD27E49AC29DDCB7334F661295881F3B70B57A31032CDA95AF11C23D44A567581CB2D3E87CFCC4D2A847CCA6A1FC9FF00A76CE25D202D0CD5D6B9E99F4F285B252028721A4FD7EFCE68124A54EE1B4ABB6869E4FD62176949DD0140125EA720DAF13E7CCC789546474F8C44E9EB4B8486DE1BBD2F76F7C222F0D8A549582350F4A1F6E69AE90C71071E470A1D6C2ECDD3C2B28054B4E907A0F78FE99738A9C532E6198A6A55DECFCC9E6FF889F94BF9A37C66327ADEE3323DE51803DA237888DD8EEEB1272C9F6158ADF866CB04B15287E2AE1378E8B6BA286C4159690EC98D009CF3AE67E39F13CAC2E0E623E601BA82010781672FD68FCE24F0682A5070E5CEF3B90F6193D34CDAAD47C05B97DD6A760701FE6AA529DC471A3F8DB975C1C4E9372A2FF0A9591211E2409D220738F9C5F1476FA7178B9E12B25D4A72F7E5FACED9C5E36728CBDC2588D054BEB6FBBB068CD178DA3F97A51038D4412233FCD267ECE42473AE19860A9D341BD4B9A72E943C2B4CEB65C3633E5CDF9854E08615043D079794610DB6DF7EECB7758DE17B35B518BB785E278EAD4CB4E3AFB4CA029212139AC82278801AF4ED5633B344D96E949721CBB11E57E2E0EA75852626662262E6B2776E2953472E006E4E32A9D7256098D26CEF5AB36EE957B87620DA5DB3C410AF11A295B7E283E2881FDE008CA4D57B19B254146840BB8CF5CBD34AB648FC9332525425EE924FD2A152D43973B753175AEED0D82DB8E871D924A8281267302626239F41AE7510306A9531B74E795B9716A126CFC2BBCBC39502774803FDA6F4A50573D5F36A3C453CFAD6496C92274FD7B0CCFC226A670CAF96C19890720E0F6AF5E91B1C329C1602AE685ABC4D78BB13DE1CDBF1169257F98C935B4D2E413435FB43C929DD491CBEF0B5250B430712B2B7828C2145303EB94E7FECF6A208B6B6CF6C98D97C2D965281C4E880207500FEBF648ACBFD2DC5FDD29DF5D6114CA4998A9AA776FA41CB870E3F710AE17B533B396B88DDF0B4C5C8570717BA4C2883ACC796B3152F879BBA801A96EDEF586B3128528907EAB299A94A3FBCE25F0DBFB57D837364E05BABFCA2665427403F4A5FE71CC6990FD5FF00A68D4A524314823944ADADE5CADB0ABB1C2F999049100481127204474F5ACFCF3CF9FF007A7B178025200601B26B4493572404F1106796647CF39CFBF9C1AC89E331F6FB98C14036A1F2F7CA152F24924C4798FDFF005FF0E25CE4B5090323637E7194A400C403D3CA0F151D7E63F7A53E70FF0091EE3F31961A0EC20F151D7E63F7A3E70FF91EE3F3030D0761078A8EBF31FBD1F3926E49EA3F3030D07611429C041CC47CCFDFD9E75AAA62425DC87B1A558D58BF4841490EC6AC5F9FB7868E3A0CC68222749E7CFE1F731F889A14336ADEF6BE64B74EF0572BE5EC4365391C51FE32F5981CAA1672C31006B5A3716AD1F9B51AA21D224A99D4286E2F6B647DF286AE3C24E6679C0E5DBFCC1A8A98B735CAF7A353FBCAB0BCBC33D774F014739F3EEF9D042887DB0D80BE119F389CB2CE7E597EB4DD5212B75352EF7EB5BF1BF3192E641DE2C0B51D837273AE75FDC20E5CB1DA4E5060E5E597D99E54894A6596ED41E4DCE164619776A0AEF55FBB53DE70CDEBCB4420F1293C6359E1E7E6723DFF006A497884A33D5EB422C3D7A7AAF2E4CEDE66514D2A5C9A37936472AB6B6ADF630D209085091D3AF7CFBFCE9AAB1E0160CCF7AF2E3A694A3F19346154523E9BEB9B574BB7DDA2D6B8C67C452A55AE5DC7ACF61F66699CDC3CAC42CCD252E58BE619BB0FCEB69393B14CD4A66D068E0B93A00DC7A677788A7961F920C939907AAA32D675EDFB5446325FCA0C94801C55ACD666D6B5A6594487F8270C91705AA32FEA8E1C0AC050DD859397574F1651C2A36ECA54128BA201E22F24FE74B27DE911C31564F0862A6A3192C0DE62A02F4B8AF0A8B9D3AC41E3B152D0E4941520177FE497161A7106F78F928FE2DBB15B6DED89ED59BAADC4EE6AD2E76BB6DF0EBFC42DF197EC50E5F611815A5EA195B8A754C4B96EA5DA1599508E341E409AFA47F05C4E9D8594B52F744B0874070B99BC5BE815762CEFABF3A16D3DB484298AEEFF0053D05C39D1F27ED1F4C9FC2EFF008576E6BD89376782DD5861D698B6F62F2C5BB8C7B17BF69879D178E23C52869FE04BFF00D22E2DB857E588AF6E6C4DEFF111BEEFBBE807E7988E4BB6A789F8A5AC6B95ABEE83ED1D6FB662FEE9A530CBE2DEFEDD69FC482A29494F14A4240CE38040E511153310F17E3265A46609090091A1500028FA99A208528820A20828820A20828820A20828820A20828820A208288C1B1E4622C8517CE7209233E5D87C7EE056AA0E1A970EEFE5E5FDC4392BFF002D3A035367FB716BD5A1B5CA0859D60E606B3A0EBCB5D29EE1C2001FC5AAEF91033EFE9778B5C82F2D23302BD5CF7FEE1BDBDFA4DD2AC432F95A48E27787FA425322546234CCF5A6F3F109966AD9E57EAE1EDC84218C47CC96C0820E952E2DEF4E514DF620D589425495BAA5988687114E99ABA6BEB50988DB52643FD429FF001B80E72A07A57CD9A2125ECB9AB5021248268CEC2BCB437C8D0461ADE5EF9F03DDF2B8AE14BC556EA08770CB321EBC656530D7F48C14FBC413968272AA76DDF1548C3C8528CD48DE0AA0354B0A3D476761A45F3647867118A904A5135250DF510C95BDD8B55AC7DBE9F5AE0D8FEF976F6CF6D76C0BCC6CA60AB75DC0B07B8E24BA4BC8857E29872504A5CE152383311E83C75F123C72667CF9689C4825565790639D29DC45B65F870C94B6E80B2C58DE99915D7DE7B316172E26DDAB77D216DB01484A19023C31EEB6003CC2409EB90EF5E36DBD8CC4ED0C4CC53A8A4A8B3127339BDADC8BC492B64894031008CF98E356CB84463F77C57DC2E7134C9FC81DCA32F28F879F9A7B32419652542CC4D3AF535E43843799869B292087292E01E5A535CE9E51A4FED97ECB167BF1D8EB8C4301BA4DB6DEE1A855D6CE3ED2C2429D6541E752B5A4170921B4A404F3D6AFD864A1526803B51AE5FD2CD4D5B5899C24C0996D34EEB00EA55AA4B579D3AB523597D8B7DA8719B1B8B8F673DF42DBC33799B38EAAD6CEEF142A65ABC6C296E23F0EB7CF8AE2BF0E84010224E90669962B0B2D414126A75671A8F47BF1B43B5253499BCA56E7FB52685C67A8FC36B1BD7B41BDAB6D9FDA3C3B08C430EC542B14586D8B84B405B8881C4A5A8FE43C52939E5C849AAD62708122D517A7DBF1C758587CB6E62805DFF7CEA7331B1764D86D16CB788507DA43A8291301480B00FF00E50623AFCE2E62371553714DD2DC3CF843654D1310A084EE94962141B36714E1ED843E514A8952125291020E47A4C773A4524E4DDFAC0874B254C546A48B70D3F5CDE282A09899CE88521BBA871C2929809044CEA403FEFF00CD10459FB5FB228DA572C8FB810C281742F22A00A4FBA331263AD64D4B8EC32F79F18C25C0637D6FD7F4F16AEDC6CE62D88B186E0D8238CDB61F62521C0B5142D4094295C213910485418F3EB4E5134331240C9EDC73F6FA4202490EA212497B73B07CF5CEDC22F7C36CADF0EC36CD8B54B9F8A6529F156BFCAA3A9208CC89F803E55933D0003BCC4F4A060DC283AD235095BA814009664B03BC5EEED4D3DDAE125DBA5078C20A8004742911DE0F90D6B6F9C923F9163C47E632997BA18249BD48735E90B250E2755031A664FE9F7D7A644C49B1B71FC1F28CEE81FED6E8D0BA5C310449E79E9F5A5A54E00665F2714BB3706FD46DF2F827B7EA2AF13B7CFF00C52BF3C7FC4F7107CAE09EDFA83C4EDF3FF147CF1FF13DC41F2B827B7EA0F13B7CFF00C560CF190238D0C06550D13D2FE91515C266333C8EA343F7D41EF48AE79A249715619F1CF8BC3298965301CB534CF96AD488F75E0924198E5CA74D7E51E7CB5A653A7F501E86AFF7CEBA7185E4497FA8D746B821F877B886EA7651C5233981A4C1E7FA7975A899F39F9370AD0D33BFEF94A22582580D2B4E4C32CBCF4884BAC4D0D4950CA4C81D0643EF4D2A29588625DD8E4EDDDE9D00FDCA4AC1A942960010FE6FEBF9702206E31795A9495108E40C65027AFC32E7999D1EC99C9F95957BB8D3BDEFC1EF232B03BA03A4139DAE68CD4F588A7B1A09513C66675D63CBA4C72F2A61899A9A8D3A3D457B8ED0E65E042812D7E078FF005C8365160E2FB50F357CEA52B70A7DD1C20E60C673A7D2A071588704037666E1986249A9B0A521DCAC03390976BE560180ED7A8F588E671D174616A5372732E401EB398D2674FAD41CCC4A92E1F5A82DC3334AD8B748768C1512424BB8A351890D95799B3EB1E3F752E05347C74082E2992541A1C8ACF29F9812749A4A4ED598957CA724921D892D56A8A5F4CF2CA2C986972FE4849025A92974B800A8E6D77A74899B5B96C302E3882D8FEFB8041691060F88BD131D73CC559B09B3713B4C2404ACB8191B16E1EF566783DA98997265A9C804B8634373AB30F3F58D66DF56F5B69F69AEBFF66F73986AB1DDB3C4D4DDA5C62A965773678234F14F8AB2F307C4B7529852F84C66B4E7005764F027803153F1524FC951FA93FED26AF7B5BD968E3BB7F6AA10A98C4077FA8667D8143CB81DAAF63BF61FD85F67AB8BADACC630EB4DA2DEE6D1A1ABBC5F6BEF5A6EE6FECDDE12E169ABE290FA121B714C90A27DC0139E95F4D7E117810E0B092553A5B6EA5156FE2585B3CDB83306B4723DA9B495316A0EA00B80067CEA4657FD3746EDEC997DA4BF66861A751925C6212952A6145440CF31A7527A8AF470C327084C90929DC09A10D421C79373A1BC41151554925F587F6987F86E1BA7F87F14E7FCA5BC90A8109CF5303AFD2B68C449252103852207EF441155104144105104144105104144105104144105104144105101A823586FE1A788A89023B89F4039F9F3CE26886A24BAF7DABC5C79FDBF709388490547967E5CA474F9D2AE5292C0B80E73AB07D7D1A1EAB109901945A81C74ADAF6B4312EB09539E18487140F12801940804911A012263A8D045336E6D0F912D41D5BC012F663A70F31F7470F8A4CF98108FAAB6ED6E27D5852F1A87BFBF687D96DD558DC5A1BE6AE31A752A0D329710A712B33038642A012274F21AD714DBBE2A4E1CAC0987783B906CD7B33776AD23B4782BC173F6DAE4CD5CB2892E08431DE50E34ED9F131CB8C537B98C6D5638ADA27DD7957F78F151B774A8B484A15C2DC209E2128E139F5F879E3C63F10D7284F4FCF25E8DBDAB59EADABD69DFD2DB23E1EA30F2512C48012025BE8E21EE199DCF5BC5E789EF677876564CAAD2E5869B4A470B4DADD060680A4440813DF58AF2B7893C5B371F88581394CA51600D2B980FC5F56CE2CD27E1FE1A63138696A531BA4123967C7F30D6C3DA0F78B83B8CDF5F8F12D9C2014FF54C0490939129039AA7D7CD0D95819B8B48592A20D781E39FA7770F11B4FC07874214061900814012033E46C6BC34E11B87BB5DE7D9EDB58B5737A017E0150000209D75248E9DE222A57158718445824839DDF80D0802E2C738E59B6FC32BC30509481BA92E428304F26F5EB19B6D5D6195171284A9E792461C56250D650E8569C2160C403999ED4DB0BB5BE58352F61A5D8FE78D6958A062E5AA5CC4C956EEE827E62452D66A70E995A39E9ED2DEC6786EF431B5EF67636E0605BD2D9B52AFDCB8B250B66EFCA3DF4B7C6DA4BCE1F09B2889993C22662A465E2C4E0E2F9BBDCB585EBD7A460630A1411BA4A55449193382E7CB2D1B28BB372B7B8D6FA766F08C3B6C30C361B5FB2AB5DB5EA9D694D38A2C381A69C95CACF88DB3C5240041D291C420292A25CA8E99F40D419E798A88DFFCA4A52A2A2129E3463E8C7CBCE375DB43D6D8759B0E125DB5E16C99954248488D0E806A3E555AC5A4A4D18D7B9FE9EC7864C013D2EB3425405072F6DDCC4DB8506548238541111CC8038BE73F4A6B785641242492E6AFE6DE4D0D5CE5EBFA510E6112BE12467E9FEE8820F17BABE3FE683404E9041E0B4E1E356AACC8273F89EDFEF2A6CA5D6B53C3280AC8A04BB66DF7FD73AC38430D11904E7D333EB98FDAB099A967292E75CBBEBD21352C87A5B2B9F510938436A281200E9A67EBF1D73A4D53D8900103A8AF7F7CA14402B485503E45FF0071478BDD5F1FF358FF0020F1F3FF00F68DF70EA3CFF114071434FF003F28A7D2A712090790059BCCDFF0636DC1C7A7EDE3DF157D7E67F7A5BE69E3FF00D47F106E0D4F97E2144A8900C9F89AD0CE2FFC88E153DEF5F6D09A831223D93D4FC4D63E71FF0099F7D23115AD7C29224C88033F2E7DC7D2939B30DDDCD4D2BE432AE7C2B0C268DD981C8CEBD0444DC3D3232D79F4CBBE71D728F5A8E9F3CB5ECFAD4D9AAFDFA448E1D02990BB0E23CBF77888BABE0DA549900A41E7D758FA1FD8D45CE9E374B1249B575EE05ABC3289D9186DF214C58E57F7C8F908B1B11C4614A3C4009D391EE467A7F9F3889F3D89255C6940E791F79E462C984C216140DEEC7AF01C323665EE28E1716105412065073E7F2EB90EF49A71C65B0259DEFF006ADF477AC4BCBC206629760323EADDEA784405C62AF1260939F39FAF2E5F62939B8B13050826AE4F32F47A9BF43A98712F0AD641AD2DCB830F53EAD416543F1AF9E22B994920E9968ACCFF00AA8C98B7CEBC3EF5F57FC48A3083737774D83B8E7C2B57EB11CFE396A494B162E2D5D4340CE9A46BDBE798A68B93F309DDCF8350B0AB707D2164E082412EEE1BF0282A5871ADA18AB6A1385B4F5DA9567676F6A92BC47F19EE36DB7F9878F9C02A483E1CF3F3AB17873C2188DA78B96B420A92A21C106B66C98B65D6D68ABED6DA88C1A8CB538525D88B82D96601EF7A59F1AD86D2ED36FF00F1C5EC86E4038C5885F818EE3376169C11B4190A558DCB1202800E0055978804F3AF6AFC39F83537188905521CFD25F7356FFC7F0E5C8B98E5BB7FC48196EB7002B30E05988D5F2BB9063A21ECEFECBBB2BB93B3B8BBB5BC563DB6989250E5F6338B2D171705E00952597C2439C08952120E890065CBD75E15F84F2B650953178748524057F0FA49A1BD78FE35E3DB4F6BAF12A539210B25812EA0C6AE1DAB4ADBBC6D43185DC22D941453F8F70FF59CCE0A672E13993EE9220CC6990AF47F87A461F66E1D329490964D52D57028CCD9D49BBF68ACCC2A98492470CF9D7B0A51B2B35C7616EDDB5BA5B6C242049F774E227DE3EA7CBCAA466CE33E62E612E49D5D8643B40CD4666CA1E52704144105104144105104144105104144105104144105104144105104365082260013AF327A4E9D7BD6C775282A3C7A37BB5CF2B64A9094B921CBE76BB53F37D612582E2480600D3BE475FF005D73CAB28589A93BA6B9FBD3A5B37AC46E210BC492104824B66396BC6E7A4620DE56D55BEC16CC6D1ED0E23728658B7B7E161457C30E3885211993AF194819F481CEB8D7C45DA276561F13356580048F79FBB6564F0AF86E762B684A96141467281005427759DEECF46D7331C0FDBDFE6BB61B4571B5FB557173756B7F7370AC2D84A94B2D25B5A9214EA579252612531CB9578D36DF8D24637113A52544289500C4644834D19CF7BD63E807C2FF000A0C2C99026049A26A43DB9FBAD2916E365D0865C60B28790A21453207003088CCE7C3A939033D6BCD5E35DA3889D8D9B2D2B5339CF50F4CBEF933347A464EC69094A54100D01A0A71D1B3BDEB6CA6977F72EA5B2E5D3CA527229E33C1972CE72EFA6623957309784C41C4FCC9AB5105540496E2D417ADAACF5858E124C807FD2481FF002090E72BDBA0E377876FE266F2DD36AFC847090824C09F5EA73E73E55D4F61ED5C3E124A11312E406A3353AF6D38C5776861244D0B4A659753B9201EA7B5B367B88B9375BB7F77B31B516D8638EA4DB3CEA42425478632C8E91AE703CF3AC6D8C7A31AE24DCD0352967A1CFF0021A39BED8F089C5A26EE86742D42F5604D4FBF38EAD6CD6256F8B612D38F2212B6905975B03C46E5238B80F2E23AE432F855657839F25615BC4A545DAB48F29788B64AF0F8F9B292485A56A0A3504B1239D8370CE1CA2D14029B0E14A493FD50AFEBBA0FF6BC7FB872CB9181DA4B0F315258A9CE9A1AD73AB68E00F5833805FF00C88B905CD38D39661F942186E0F8260388DF63187D9376D8BE221B176586D286145B4F0A5498E124A84C93FDC4EBA177331E9615655883F6B97CCF1E9097FDB6729D2B585CA268332D5A86A5453BD22E86FC37ED1C2E03E33924F9C9397393CF9795454E5A66390E730C055DBAF5AD2038652549485303425ECDE5F8EB0D2DF883294AC10A05591CB9C0FA5317093BA1F2F3D3D817EAF50A12992A356229C33F2851492A888CA75F4AD9EAD5B3DBDB7585C2D2598DEDE9EB1157AE8B595AC920E813AC69D81CE39F6ED5B8965445C33E5771A671B0FA8B023BC376AE43A92A85B60735989F2CF3A57E41FF0090EC6141294A2C18F27FC4542EB3949246706411DCF3D72F2F5351B3F0E42CB114A3D72B7285912D2C413517D28FC0BF67B52D0ED17262012083A8FF007FBFD2992C949FA95FC72BBEB7E9E6F48D7E52544B3685E80B727B7317E31529B71490EC9E15732639C72D73F865DAB51302C920D7969A6B1A24A524CB7FA93957CB87BBC22E079082B0DB8E0027DC93D7F6F8674E65C852C12C726B7BFDD396E152DC852C06C9C0F7EF486A9B97145005BDC02B244149F7639ABA4EA3B53D97845EE0217D01B57F27F30A6F4B01DD2D5B90E5B9C3E7D06DD29538EA53C5CB8B31E734AFF84B607E65F2DEAF60FF00DB884D1350B24043366580E858BC2A56866DD0F29C4292AD384C91A6BF326B6FF0D4120EFA4DA999E37AF956ED0893F3262920335C9603A5AD6FC4541C6CB45E0B1C004EB9C67397C3E347F88B037B7837AEA066F76A4608216106E73CBBFBC8670D7F148B84788D9201919E625391883DB979646A3A782951483F57FB790BE9F6CC69094C904AC28D4532714A023AF9F5311CF0528CE507F4E5F7DBBD35549529998EA2FD6DC214978A97295F5659528ED5ED668B471552D0B7110490066273CB965E79F39075A8DC4615402B8580C9F2361D3F713985DAB2414A4025DADC756BFDC5DE8F60E245D528E444C9CE7E072E5AE7D3BC557B1095209DEA905B85E9663F8E0C22DB83C7CB580024DAE037126B5886280532A492ACF9778D39C7D00E5511377F78BD1AB47160EDC395AB13D2E727E5EF121FB3E43DD07578897DB46797CA39FF009E9AC79080C46DB1859C6493551604D47014AF58712714852824062726CBAEB51C4D189AC5B58ADD7816EFF085FF004009047BAA2AD3863948D39FAD58306BFF0026426730DDA9F36AE44D844E26592905354B5FDF9E9A4686EFE7DAAD5B9D71D63FF8D75888504DBE18CCB97F72A5100218641054ACC683CB3AE8BE0FF05E23C558B9385C390153160382C5C9039350B3B5A22B1FB6246CF4933121F74D28E5875FBD8F28BA7D987747BE4F6D8BF5ED96D7AF1ED80D85696CBBFCB1B2FE19758AB00E69BE65614DBED909F7338E05F306BDF3F0E3FE9D71B82C3E1E7E25285164A8920F3A022FAC79CBC5FE2F96BC6CCDD2456C0DC654A135D4BE71DDFDD46E8B77FBABD9DB7C236570DB2C20B084B770EDBB4D30F5DB89305CB852238D4544924E664F2AF6A7833C2383D858542264997F312901CA5390B03AD0371F3E5B8EDACBC4AAFF0042AB515001A5327E757B5632F33832DE74B8B5B6CB2D41B55DB1871523DF2E9D0C91A7C66AFB35723700932C390CB7008045B77C9F3ED58198B54C2EED983E808F76B44D38C5C298E149487B21C44E4403064E6648D6ABB8AC3E296A2652F72AF4240E541D188FCC6C929DD0142B9B01EB43F8878D24A1B4A5512358D279C4F539D4860E5CD44B1F34BAB5CCFB6F7531AA8824910A53C8C41441051041441051041441051041441051041441051041441051043777FBBD3F4A471333E5C93DEDD35B5B27BC20B964AB3ABB31A665AD7F7942493A8FFB65F234D3098848739004FAFE5F2D05EB99402660268F70C2946E9EAF4CE39FBED86FDFED726C375387BCB61FDA0B865DE3428A54A6EC5E6EE5D120660A010759935E74F8DBB4C7F8589054582486735E5D3CAA6F1D5FC133E5C89C99BBA3E63D145A84598B86278F9135D0ADFF006CCDF6CA33688C3ED54BC3F0FB661B5AD282471969B4B8A94C0CD609E526329CABE7AE236A23FEE93025542A56772E736D7879C7B1FC11E235270F23E61DD550148A067D29DC51DDE359AD31242EDD2A194F16B99993224E5967D3A41D4D3F6E2C4EC6296E0839641C3E76A35BFBF4F6C1C54AC761659DE0E52F767CB98EB9E90A9C5B8753F319F3E833E59546CB90952B402F6FC5A2C5FF006E4CD1FC778351DCDDB43F704520FE65F8B2D34DAB83C3E2E220C1CC488CF3D7FD53B4CA4A40001BD855EB4E3CFADE18E2763225A553141212C487A373BF067B1E622DEC39DC4EE36F70C66C1B71C487D216B40240D33919CEB9F78D32A732E554580A13AD3A5FAF58E7DB57132B0626B94064AEECF50410EF9F9DC651DB5DD95BBADECA61887C12EF809E30666613F219FF00AA7330BA500D4805EDC32E0DEB1E2CF19CF44CDB98B54A6092B70D620E7A3E5AD5AF1929B679F08E51F31D33F9D20A4B80D4BB69C62A0A98CEE49D74FC7E22972D87171AB28898CA3E3113FBD24A940BD95EAF6E367F6D194CEA6E834269EC1D79E4FC3CF1DB68788540348CD664447727E79FCEB41280C94C387EA1252014A812378BD694B6B4CB4F410A8BBB6BE1F88B45256C2B24A92414929C95047FE535B9C1EF10A09D34D33A1E77A9A9BC47A42925295AB7940A9CF3B4149AA46EB500E63F43DF287096DE0CEDC6F68C31BD5DE2DD6C5A2D0B1B378A63085A8A54BB3B42FA07BC9008339C4E67AD247E972F67A8AF63D7A670EA4286F900B917032A1BF7F6C627367B1356D7E15698A7E0313C33893C4AB475A2CAF3CA382627EE69B4CC490A0056D41571A3D05FABF287895251552F77424DEF7D5BA45CCE2508570A1B75A4803DC7870AE6332477EB4D274F0E58A8035367045E819BEF1AA5616905D2A2E7EA4D8D7DDFEF0E5BCA472CBF5A899D33E616666CF539C6628657893D70EB508166CE683EF051912648CB590279EBA56F86016424DC640DEF5A8D5A9F68D0EE20EF3328D1F32FA7BA6B568C07BD0DF0DEEC93AAB1C3EC2FAE569047130D1704FA1EA4CD5930F24EE86E3F8B53F19B98C942557482DAC5B9BA1DEC63DB518DDC318A61F8930DCA4A03AD29281209D09EFCA9862538B44C2995BFBAF42976156C99ECDC4DA1D8C2EFCA7615663A5855F95B2A38D365D65FBCB9F7D32DFBBC2179F207E3FB522DB43559EAAF3AE8F5A3660B884F7112D164B7035D7227CB2ED0FF00C1B77C26D9D5F0AD04F12504011CA06BA77C8D6A46D014066139DEB614A572CCB7A335A8804A7743E79D32A1B93DE97CA558B1B52D1638CE70224139EA3CF38FAEB9E5231E4FD456DAFD458E7A310465A90E619AF10B490FBA4F5719DFF1EB68E76D1162E2AD90494A0E5399F7B333F7A5650898EF33F95DD9DAE731A30CF8BC2E8C52264B0E589B870C18D4B1635E511EE72F5FBFBFDE9E2774074A6A28DF8CB9901F856135A50B2295D29D295E3083D60D3ADA9E54C919E9CBA48F872E71A532C5A0EE9A00F73E8DC287AE8D0F30B212952737D398B33726A7A8367E2187B526129F2CB967E5DC728806AA98D949FAB334AE479EB5ABF38B8604A52C1A8C38D455EBA3FEA2CBBCB54A5C5A529C8691A67A74D34CF3E9AD414F94A09533391424F034E15E00671654282A4834B57817CFA4415C5B44E51AF2F872D23E1D39572BDB00FF009C5245942A347AD5B964D951A35C2A93F3455CB8AB5BAD3BD62DFBB5B12BB77ED0108523FA8B6F27648260F381C8E42BA3EC89811B2901490E00AB0FF90BEAE34F58B6C80A520AD330B043143D03A481422D60733A473FBDAA775DB118DEF977418E5F60AA4A1DC45D379C56EDFE19D297184B61634502749D7313D3D3DF01673F8830AC187CC40614D1DC176B9F28E75E25DF1266098BDE9890BA82E03BDDF46F4A47D0FEEEB0AC3767B66F67B0AD9CC22CF0CB57B0CB30E8B660328E14DB3441844093339819F9D7D8AF0B2B7B66480C0112D16E43D3DF0F2A6DF2A38D98A52B79D4ACDC062437BBDC878C849C3B0B5BCB471053CDC2968041CE388C8F31F1CEACA43EBCB23CF588389CB55214CA4B69284094849C88831A72ACB0160D0438A20828820A20828820A20828820A20828820A20828820A20828820A20828820A2086EEFF0077A7E94D31DFFF00CE585AA4E7937BB46410A4E8439639FEE8CD0D3C4E151C8CA4F3C81F5FF15052A6142580513F5540EBC3C8BD21171BEE6CF9F2F7EB1CF0DE75F398E7B4961966C1877000F02173C31776A348CF4274D33E599F2A7C75C699782C48CB74B00399A9E1E5C4C5E3C3D3D52D52C8240075E3A75B679DE24B6F360ED76A2CDFC2AE116EE256DACB8A700519E12A1C24EB072F87A7CE39FB489DAA402C42D65CDB3F75B1E11DDF61EDD560C4B5952D40148FA4E64B59F5ABF2CE91CD4DBCDC56D2E09757D7B8532877094AD45843416A772278F2480089074D75D4452D3B1226282D4C6EEAA64295A67D5ED1E92F09F8DD1264CB96A9A02801F49559FAB80C476E91AF8F5AE2EDDD2AD5EC2AFDB5A55C256A6149464489072CBD339ED584CE483BC9E058795C9E7EDA3BB6C5F19E1674A1F3160D01AD43D5B3CF85F4192F6D84ED0BD76BB6B2C23115AD6501372185FE1CF10E4B1AC139F965953C97884A98960D7CB2F75AD6B9C6BB77C5B874E1D7B8B48FA496040A8CEEDC5B91D2374BD9FB73AFA1D4E25B43689376B5256D29683293075E2CC6A34FA654F113921F788B6445EACD5F5EF1E62F1978C49337E54CAD6E68CF5CF896FC88E8561086B09B166CD49953408940F7784FE5D633032397A9A693B1A90A670CF4663D4971F71A479EB6A62958DC52E7BB1597BE97A07A3FDE26D18A5BA6650AED034EBCB2F49AC231214097A86A1258BF3CB8FA188DDC59A3B8EBF8E10B3D78D299012485DCA541A3FDC9294E8BE62797A7ABB42D24124D4E941D7A3716A1B46802CAC245377B17A86A7ECD9A916CDEB372E6CCE296616945FBB6F70B616A24240690E2CC9D46432F2EA327294A72A9A367FD1B65DA30B44C0B0A25935DE7CEFC2CCFEC4637DC3ED1398B6C9B5875F2D6AC46C6EAF9370FA892D287E25DE0E151CF2488CEA570F286E0373A914AE5DB816E75289511308DD25DB2A8A1CF2B7171190F15DBAD92C11CF0B15C770EB120C13717286C083067888A6B899692E02439CDB917E3D7808708FE40B3F0E9CFEF0C13BC0D80C6DD6EC6CB68302C75E91C16B6F72D5CAC139C040CC2B39E711509884EEB860746AE5C6AEE3C99E1C4B4266391BF2DEE41670072A80D9DBBC4B3D8707407ECDDBBB22DA789BB76C86D939716481D7288D66634A819C95256480A15E34CC0B55AB778709292A017B8B4B67535D6835CEDA8362DC5CDD5BA6E2E140BE4A92A6C93E20083C2091DC099A69353354951357676BFE6D7785B79091F2D09DD4A6B664D5EDCC9FB3522A6EE21C2DA9A71074952606463F7C874A60A42F78D77781241B7DC8EBC60157D058EB6B7786D89DD3785A9973C4BA5AEE891E1B4A05ACA06635CFEF2A7D8374919BDCDF86553CFCA130779F7923E934A026AFD69C6DE9AA3ED21BDFC4F7718687F03DD5E25B5F893E825955AE0CABE4F1651C45242B98D34D672156FC2A920241602973AFDFF00340D19001208592C482E5C69F9AD7368E79621ED19ED878A20DDEC6EE5DBC0DE7CA821177805F5BBA8014784A92D92448CF29EDD2AE183C260A74A0A5896F9EF370CEBD34D22630FBA258DE3967E6F522E29C69711682F6EFF00891635748786CDB564D13252C5AE28DC2409C872CB97E94EBFC1D9E5D928366603ABF3E873BC258854A0E00481A1142EC3A9A1F748F1BDB9FE237638D3CD8D9D6DD6121BE071EB5C514E12539F11919493CB410234ADCE03670500D2F3776A534B3DBEE2B10D3C7D5F4D53C1FCF97F778BD6C36C7F88F39709B8FE478606A4152556D8A710C84889E5AE5131F04CE07679144A1C02723971A6A2A223662544BB727F5C8768EACEE131CDE3627BB6C05DDE961AE31B6AA1703154B0D3A8B710E90C94F8DFD4CDBCCCCE7A64455136AC8969C4912F76A5D85880F6B53FACA236619A85B07A16A3354D838BF2AD6335A995940594940E8A107C88CE0E597F9A6C25B07B3666FE9DADC2E61D4A9B368EE793BF07AFE1B9BC205D053E085A4AA0FBB3A6A6239CE910640E951F8C40DDCEDDAB9532EB9E8625F0F88989FAAA00C8DE872EE7A72882BFB27735171A42359528803EB1D7E3D22AA98B96778F603DDC8AFE6B12B276B0412198B86701F8B7F62869AC5917C508756994B9C310B6C820F69C87A89D2A2572F7D2A49B31AF2E4FD43EB174C0E24CE91BE48622A03925E9EB977362602E16933EE91A6BFB7F9CA7CAB93EDD93BBB4142C4285EEDD43D3A73AC2F869844C046ADC5AAC74FEA2031369BB96D0B295A45B927FA6002B9CC4CEBA4C8D055E36691FF6B4822A1AE38DB5CFDB45AF0CA280B62499A1C0A9DD2054707E6F68D62F6862D5FE19B378A5D34D24E1D8B5826D1C4262E1017885BA1C927498E434D729AF487C059BBBE21C2906826247BA35685B57CE285E28584A26805C90AE21C8F304BD357B523B89B076E977663671F42DC8FE51619AC82A8366CF3191EB98F9E55F657C1EADFD932142C65A07601F33AC79636F157F9B3028241049648A317AF5D22F46F0F6DA7D572CE6EAC0E32B882448AB5D5CD9B2D78BC41D5F867FAE3D624D09E148100750349E7598CC5544105104144105104265C4804C1CBCBF7A208A92A0A008FB34411556017D473BC105660828820A20828820A20828820A20828821B9CD6A9CC6500FAFEA3E95B2D01728A48B83D59E8F08AD7621C31FD3FEB8B4337340498FD74FF3F66ABE642C6FB07A1619B077B81DB410BE1E5A66104BAB3A75BDEB4CF5B4738769DD461DED4D7AEDD9E14624122DF8B20AF0ACE17C33E7CB96A6BC73F1FD1B983C5354EE2AA78D7AD79522F1B170EFB840A5AAFAFF006D4E45E325DF5CAD372EA8FF00D8883A94A89000D728C88D39659D7CC7C74E5276BCC00D02D4FA5CF76FD17CBAA6CE947712086A0F263C01E34CA978B6EFB0F6D68530E34CB96C4150428711CE54796799E7A0D69D4DC7A81DC2A2DA13437E5E5C1C459B0D8C9921695A54A4B3074D0D29F8A7ABC630C5360B66AF5D5ABF9532A70AA494B29CD47EC69AE62954ED0144B816D18FBAB3D5F9BC5D367F89F1D2032671090D42A3F917E7E861E615B2983E1A84348C1D91E19399613399EBF4CA220E5269ECADA29B10096AF1EDE5C1EC6338FDBD8FC5952CE32690A006E8592035D867F9B0353191F0B7F0FB3424218433000C921307A65E596A2333CC56CADA2EB3F532438A13C46BCCBF168A1ED44E2B144FD6A5139972FDB950EB43130ABE4B878D2A949D0C920C7791E5E9D6A2313B4089CDBC40A31A01D736D0657E310E9C1AE582142BFF0090FBF3A57411E7E2BBFCFA4FFE54BC8C7B8037C971AD2FE7A0E1CA364E15C394D4E8187663A738F1AC4494DD28A813645AE1139FF508E28813CBA7AF598C3E31D2FBD40CFC3CF2A071EB18548DD5210515980B280D3A6A6D719E70FF0013C45855962188A9C436D5AE1B76209E1054E5AB894CCC892AD273FA54CCBC5216410A601B3FB72F6F084DC229081288256B25414452EE413536A7E99F9A9BAADD46F776DDEC6319B7DAFC4300D97BFBEBCFC33585DF3F6D78DA1372F2547840E01C473491320D4EE1B10552DDCD05CE63CABEB11B88409738241B268466C1AFE7FB8D82C07D923661929C4368F6CB6E7682E78F89C6B18BF4DD5B13C52470A84F01E8796998CC5CF0B046E9AF6FCC6A824281A1E7EECCFE90DB6EBD9D6DB04B91B5FBB0BB7EDB14C3CB6EDD5936B0965696C26006DA01454A4A4954F5EB4C572828300F7A69E96BDDE838C3B94A00B29802FBBC75CAB57B7EA3316C0EF5AC31DC22D70FDA6BB6706C7ECC06556D72E25872E5685704210B3C4B242499FF00CBBE6CD783DF0429E868C2879963C837385A5CB085A949AA660FA83580058A5ED72FC6B6B65DB8BA61EB6FC438461F2907C673FA485240C9415CF88099E73CB96666CE64394B1ED91EBCF4AE51A00259500A33534A3EF10E73E3D22D6676A2D97722C6DF86F94494F8EDC3A91DCA81073CA0EB977A80C5E1771C94BB3D4873CB85BEF710E08702A43642DEFA45E2186EE59699B8653C4C7BC97169120A8F16455D34D3BD452677CB5005E97229FDE79757786DBDBAB528289DE23E97766A503DF9430C45AB5B80953A8B7B82CE6943802A39E999E5DB3D3AD4A49DA3BAC1EB70097176B3F47CEBC6164EE8496078D03D73D0B0ABE4211670966F909BD0D2592E65C0D27850383DDCA3213FAEB066B49DB7F13294532D4B6B80096F2F2F586FFE62649F9656481404B392F6AD1AFC9AC21E7E1DCB51EE072120444FC2639469DB3CB44BFF0052634577D63AAB97DE364E2933AE4115BDB4E3CCD0E9A3B806D968E271A74BE7252B8667391993CBBF291DEB7FFD478C5172B9A49A9A9E5EFBC2A12B2B2C65EE64FAB572BDADF984D572D5B49517929EF97DE9D67B01347FEA1C633954D1CC9D5BDE5C6154E1173582370ABBB926AF9BE94072AD22D1C6378585618E38CFE29849464438B01C075CC4C8F3D4CD4D60E79C523E62CEF28805CBB8E64FAF03689FC0783F138C489C6429454CEC974364CDABE678674B5BFF00763669C70A2EB16B76C4E85F48F3CA7598F2E5CEA4E54B4AD3F5915E7951B8D5BEF944B2FC118C949DE95852A2057E93E54248A8E59B52166B6B366B10B8371618DDB38B7238509B84418906409F2D7BD34C6E191BA4A5493CEE08BDBF711B33C338B961A661A605077210775F51A30ED487779883CFB7325F6CE60A254387288EC00E474CE7AD371A8DD51AEA2869A55E9534CAA5EF1098CD8F3A5AAC6EC41151A7DC1B8E516FAD0149242383FF00150F7A679888CFCE2A384A065920558DC3D2AEE6BF8CA2CBB35065604A4E8589C9AF7AF1B54D2B7888B86CE720F68F9F7E5A7948AE41E221FF00F60A615DE1956E1C76875865BCD038977A55F3D03D7CB586B7486936E841C94E8565CF2E994E93D7E02AD580504ECA4B962400E4B661AAFC34CDA2D38652F789BEE07A1B02C34CFBDAF58D58F680B05B981E156ED82A0317C39413131FFF0020C2A600EF3CC65F1F40FC079C3FF51E140723E627D79D85F93C50FC533184DD6B6072E55AF677CE91DBCDDC2148D8FD9D4AE4286156120EA3FF0088D083F7A57DA1F042F7B6361C1B89693E498F31EDE2FB426E5C0E51901BE7E9FAD5CA21A14A20828820A20828820A2086ABFCA7EF98A208A9B5A528009CE4F4FDE88214F151D7E63F7A208AC104023434411ED1041441051041441051041441051043424176648198C86B33AE7D4F2E9CEB72B0894544380FDAAF9D73F758D0C82A0082C9258BF0E9EFBB3779B511023EFAE63A547CB5267853101DED7CC00435BCA1DC8099742483C34E141C9F9DDA39BFED41835E607BE3DDA6D6B4EB6C61C1DC4538A3CA5148056DA1A652B50112A260126BC81FF509B3969C162D6038DD57A6597B7A068BF787A6A0A65A7526FCCB11D0F1F31190F12B9B775A17691EE2DA69606449F701927A1C88D2457CB9C760D5336C4C0DBBF5AAEF5B923F27CF5EB3B26515A5082012C4D4519B2AE9606B70D9C5A0AC45374B2E953C8493010080070E472D0091CA399EF50DB492A918829776A1BE8E34CB5B6978B0AB6792948CF403882E4DC71E368F5174EB47FA086951A07733E797AE82A3D33560BBBF7E99F2EDCDD05E12623F8A95517724654E068E3D6137311BC5288710C0573E10A803947783D065DE9D2316A0C5EF7735D5B2EA75ED04942D0485134E3CF2F7A9AD2103E2BDF9A00EA24651DB3F4FF30B7F9A3FE4D4362FDDCF4A3FA187E89D2401BC0122D6A7BB74891B674B6D21B3991327E7D4741F604B398264E9856282B9D6D6D5F5E995984F54A2B200FA4D8162EDF872C7D21E25D52A20FCCE5F3E54EB0F2660A9272A039D2E3803ADFA4372B969A048ADC365DFDE9155BB6A40BF796B4A9A5A99F1500CAF2309CBF42721CF3CE730C85B5DB9870C2CFAE9979D5099889614974D43B1614F3D784629DF6E3589E15B2D6B86E08D3EE3F8DDC30D071A0541B6C5C212E874A4C89415012623BCD4D4B0A29156398A86E9F9BEB099C54A24EF2052C5AD950B9CEFE958CE7B01B396FB31B3369875BA43695DB34E909007F51E425C72748256A56B9F51315352710508092EE00CD83E79F768AEE38A553B7921C39627B53F079D69177780855A29859515924833A664FCE69C22782C5CB96BE7CC72D1FA43505887EBEC7DB9437B4B336CD3ECA5280E5D0212A0202A27883A4EB0321D01D29F4B9C802D7B161C2EFEEF6CF72B0552D4C92106A186F558E5E75ED5235577DBB97631B617B4F845CBF8663F8105DEF0DAAFC2B4B82DFF0054A5600E257BA888E67999A5C4C964592E320C395AA29A3BC3B46252E096034F646BD838D2301EE877C9BC0DF862F7FB2B8AD85D61786600B4DA397A869D67F121AE26F890E1252AFF008B33949351D89DAF2252BE4A83D2854C683D7ED0FE561C4C47CC012806A4B004B9A51BA7946EBEC761385600828B6538F2930971DBE292BE29CCA5423E27B557315B4254E2C96009B5B56EEC6E358557825B10028D1DC697D3A68D9BBB5ED717816E908754A49009F0CFB9CB4CC75F2F4AAF4E214A56E9A1B75AFBBF0D2139781536F14B1D0B057BB71BE70DD6F2D078ADDB6564EBF884C83CA323CF3A4521492E083ABBD7CB9C657842A052EC750A63CEA29A5B5E061DB6FADC424BAE1B75FF007376CAE06939EA94F53CC9FF0034F913A40401365A49D583DF577CBAF48899FB216A5EF6FB816AB13AD73EF7CAD15A956FFDCFDD93CFDE1CF5E7CFEF9D6462304A1FFBA1FF00D21F857A5DFCE1B8C3AF0EC93522F99F3619F9DF449DBD62C9B539E2385B482417152729249CB972CB2E5DA4B0B2B0B394375294EB4039796A7CA27707865E2421294A4A945AD5B81CF51EB9BE9F6FB77D69C14AACB0CB974DC12A48F097212447E6820C67CB908CEA613B224CD62025AE73D2D567B768EC7E1AF8798DC7C895304B092A624B149BBD69516F2E31A5F7DB73B418B5CB97577885C7F5CCAB85D564341A9CA408333967CEA4A5600490C94848E54AEBE5FD8AFA07C3BE07183C32244E40DF005C71073BF967A88B2F16BAB9BB928C52F50A339F8D1107CB9E5D35A7024EE8259C0EA3A53DE516E1E0A9332A10914190CC64F5BBFB7885636AB1ED9CE1559629882DE6CC92B7945A235CA35CBEB03AD31C44BDFDEB56874193D1CD731ADCE510DB4FE1E7CC967712900E5EB460FE6EEF6BEC76E6BDA4715B9C598C131A7D0E71A90D85BAA247432547F49CF5EB5E9FB326CD5B83726EFA3035B37E291C9F6E7C369A9139611500ABE905FE90EC32A8B657B88DFD62F59C518372CB8D28702567C320A0F1267239E7F669AED7D98BD91B3D78C98A1BA12E4039364E19EB4EF58E358AC0CCC22BFC7285A194B1F58666398A366DC18EA623DE09530A7828702499139C831A1D73FA9E506B814EC4276CED4299043EF3026E58F0EB7616EB17295F2A682A0487BF7E0DDA2D8BB4BD78F5BB8CAC25A649E34A8905526047A83AE9E622AE188C1AF66ECE0998090006A386A3E6D5E80D1DA2DF859E9F944D015062F7E5D88B91768C67BD2C1BF98BFB3D874B7E2E25885AAEDF889294FE1AE995AF8F2241201881DF38AEEBFF004F928E2F6FE0D69240F9A1C500351C6AC337E51CF7C52779334BDC28E55615CBDE79C760F64C26DB01C2590326B0FB341F34DB360FCE4CF5EB5F68FC264E1B64C8704FFA48B0B505A8DA0D34A5BCD7B4D0A998A98A51FA8A8E766367ABFAC5D68706700998CF97EB5615ED1DCBA559D0073F6EF118A94CCC4679F2E1CE29FC5B61C2D190A1033D331220FDC73A25ED0130B00DA960D76BFEA115324B13DE9EEF15A9F4A53C460F9199F21F3D6A4E52D3303EF2453335B69EFB422B9BBB6AF1FEED9E45DA1A7F32689E11055CD23F30E922644F2A6B371699733E581BC750FEEB52D0D958E420EE962AD054F5B0EDF6857F1CCA44AD40189099851F2075CB3E54E64A8CDD136BD39E7942A9C4A5428CFA77E3EF431E26FDB5202E14892442C7BDF09EDCFF00DED35489555CC401997B35DFDF9D21ECA96B9A010186B966D0D5DBF69394923E9CF3D62753032F8D42E2F6E60B0C4838896FA6F0A7E7BF0E21DA706A2CF4A805ED5EDEB163E37BCFD8AD9E5BAC6278F61CC5F311E2D82AE5B4DD278B3482D28C891046B919D2ABDB53C73B3B6661158A993659003B05269A67CFCA1D4BD933A6A884A084E4A214C75620D5B3A44161BBE9D8DC52E536F6F72A1C4603AB52037F107F59F94D3B67FC65D918FC60C2A14872ADD774EADAF06FC52313364CE96E4D8396D00E95F7C5B2A5AE316370DDBAADDD43CD5C025B79B50534A2333EF75D0475AEAB86DAD2715864E225AD242802038CC75E76E05A23CE1D61DBFDB70D51CFDE9AC488B8495A91C2A1C312AFED33D0F3FBE944BDA895CC0862E6D415FD18D3E529897142C469ECD2D9650AA161C4852743313DAA550ADF4856BCFEF1AA925258DE2BADE35828820A20828820A2086123C4E1EE0FCCFD8F5ACCE1FF00F156AC8053F2F64FA43A425E50E6A3D89A428540850E9233E7F647D399AAF6CC9CF8B32ED555FA9E1A8E35D1A358D3FF006C4D89BADABDD4E309C212A38EDAAAD6F6C5C6C1F150DDADC26E2E380A4710E26DB2150340796BCDBE30F860ED6D8B895A51BE4CB2ED930A8B708B46C09AA1302033259DF4539FEFBC6B3EED36C5DDB5D82C3F145A8A6E380D9BCDA8C14AEC57F8658209247116C9CE67B57C89F887B2E6787B6B4F985051B8B5D5980ADCF3E9A976A76FD893D9090E1DA8721916CF83BEA06513CBBA0D2CA262232D27FC6A3E72753C6315B4FF00C99A5649356BD78B67A533F4BBCAFAD00D19AE6C47BA7AD6176EF4883C5A77E5A473D24F61CAB444D2A65025F424F2E1FDF9EAB97BB4BB54BDBB55BBBB370878973C44858D0E99F2FD29E4B9656C5C1D4E9FDFEDA192D3BC4901ABCADAB663FB7BC3E6F9FA73CF2F59E7AFCE9CA70FBC452D5200BBDB27D32F586CB96C5C9BE41C9F4A768593F986BDFF00CF6A7689252057A1EB70DDA13521245125CBB96AD3DD38087CD7F6FAFEB4FE4A294E14CEE7F64F610DD520B12417E0FE6E3216D6247F061865370A59E1BC30533A701811A46672CF974A9995294102A0939569D1BDF488D5813173129FE528FD593BE6D9BE79C4D3780E137D6ADA714690FF0081EFB256124833C530A079C69965E712B225050AB06A56B57CCE6D9BF9B888EC42E682844A40512FBC482586AF67A9D6D71130CDDA14D27C3F7509F71232FCA9012072C801FB73AC295B8B24F2D1E9E8F73FD420B94490141DAA684D4FA7AF2857F140F3E7CE72EFAFD3D2964CC0082F4C8034D6C4FAE67A468A934A22B4CAA7DFE8DE28BAB852916C5A265B52B8C89CB88C0075EB3AE7C8D3D44D06A08E5956C7B674849324EFA8A92C0E4CD6E6EF6B8A33C597BCCC758C0B6471DBF7D21C1E034D2F9FFCF2D899CB32AD3BF5A5FE6EEEF68D972D5FB3539C6C892920100DFA5FD9ABC61CDCDD8E0D856CDDBBF86E1CD337B89BB72E3CEA1A4A16B2A794A0544004C71644C6B3E74EDA7337B12480CFF6D3DDB47A58F092C19037CEE8171950E63A17E4632D3ED356CD169D584BAE0924182273E79F3CA7A79C45C3E94B2B53A58CB1404B105867F76B71315D9AD2865012E7880490BE2E23A9E7CFA72E9446CA439706BC7DFE624D2BE21A8FB3CB5F58F5A21BAD172C5F30D78F7C4299CE008D4F5F3CB2FBD6929A58022E3F223558019B378497759812353399CC7C40FACE79F3A6C92C41766F7E578869D27E6CE600D081ABBB0E6F7D2CCD420617DEFEDD1D98C02E4B6AE15B8DAC20E801823B733CBA4198CE7F674D4EF07BD1DB8364F6CC9EFC3A5F83B63267E224A948DEDD62011435A3DCFBAB54471EF6A77818A5EED0DC397CF2DE6DD795C3C4A24264E838A6047FBABC60A6A77413502835E75BB79B5338F69F823610F91246E00E91D18662B619674CAB139698A85DAB6A27358EBE5940048CBB4CE841069FAE68D69975D72FBD62F58BD9CB9135920D05486D1FD8D6DA9A1CC450264881CA673ED32232C865E7A4B45CF21C034550B5A8DC79EAF0909CB9640215A501A375F4FC442DF620C2D21B5000AC11CA67965D73924D3499358904BE6E3F2EDDB48C7CF5CCFA06F1D3CFDF73CB155F3B89E0D8EB18861EEADB8702814A8A465E519C1E7AF3EED953774850259E9A65C73CBCAB0CA6EC59D892B265A88502EE1F5B5EF9F28EA0FB3DEF06F719D9962DEF1F5BB7496F85C2A5126048124E790D0CF3ED3517E319FF0033C3F32593BC4A1541A3E94F6ED78F32F8F7C3E246D09BFE9EE904D8354BBB5FA9D2F58D8672FDE369E0824159EB1A9E59F9F502673AF37787E4997B5F79882262A9D7DDC8E2238FCDD9C5134FD2D66A3356F5D21F5836AE04A543DE57BDDF298F9199FAD74DDBDBD3F05BA1DC8038E55E3FAB343E4C8F9729E808157A0FEBD8BC634DAFBCF1F7A3BACC178A4DE5D5EC26419F08A17CB98CF96401F5EFDFF4E3B3CCADAF84514D3E62090464F5AB797A1A8E6FE279A1299AE4FF0015371A1717EF7FCF607086FC0C36C520C14DB30982607BAD2464272F8EBDEBECEF8551255B2E402104FCB450B3FF0011CB4FEAC3CCBB571E99589526BFC959B677D726B696313CDAF23319C4472E994F3A9C9B8390A2019690CF50900F2D0B7AE511A31C998FBA4022A75AE753AE55EB0CEE6CCB8A53ED28A5460C1ED965EBEBF1A6337032D03FD30D43EE9E63918CA4AE654B9734EBFBCCDF934276A9712541E54C64028F2CC69F0EFF00AD7F1188998759FA983EA476D457DE4BA2402FBC2FA5DC7EB514E358A14CDBB6FBCF209F117054A5C78420671CC77CF9F7353B85C6603FC713710B921412E4A88DF06AD77AD3FAB16EBD9614B2B4A4BB50354B9C83036AE7D59C595B51B6FB29B3D6EE3D8CE2D66CBCD4C34CBE80EE5FF8AB9E407EB54BF1178FB66EC996BDC9F2C14BD4292EE1F9578E6D9C49613642D44028209BBA73A3DBCEDE51AC5B43ED3570FDC5E615B01B3D8BDEDFA484B18B6296BE2604E28C66879B54A929D164686BCD9E2FF8ED2B0DBE9918A7237836FD2828CC781351168C2EC898AFA0B849008DD05E9AE8C6313E26D7B42EF0093B5FB59806CC60EE199D8EBDB9B3C4D0D13201E3F74382418D2418CABCD3E20F8F78F5CE9865E2E6B026D315BB7E05BD2968B061B6484A424A3798DC8ABDC3D9DDF99A42DB3BB9DD9AB4B858C471DDA3DA8B84C156258EDC22F2FAE179921D78895250470A33C911AD72FDB1FF005098AC4C95E0A662E66F12410566B51C74CADC749D93B31A57F1019E940DCBAE9190118260B875BBA9B6B271AF0D24216A692932260830232D620F3E951BE17F8AEB95B4E54E54F213BE2A554BB3DF4634CF9445E376728021208CCB8F5A1A643A4671DD163CCE2B84AF062E14DC614A511240510E2CA877D079F202BE85FC29F8928DBD230D86F9FBFBC121B7B80A55EDC8966B068A7E330E641528A497BD1DDADCFB53A1319B5DBB52ED0B4DF10B9040274300C1EF981F3F87ACB666CE44E948C4160E01AD19C6B6CF47E0D7AECD5942DD2D5720356D502CF7D2272C12B45AB6173C512675939E7FA768A94284CB2509B0B7BF7CE1B6FEF926BEEC07010F2B119828820A20828820A20861C12E13A1E674CA75EB39E5E75B4D27FC75268CC4D79B81C896A71870957FA613C4F2677EFF00685384F14E5DE3AF38F3EBE7EB5AC14A54AC5FCC66FA89D2845001DB2F2A425314C014914BD788BF9F3D0C59BB4B602E59BC66E528751736D716EC323DE243CCADA59E13A81C5273981D00AB26D1C148DA5B2E6C854BDE3B8ADF252E1CBB0E4F7B75B895D9F89DD5A595BA1D2E41B91A17AF2B7511CAFC2D86375FB7D8E6EFDF4A9168E5CAAE30B5A0016CE97D4ABAB84B44E4A502A85009FCD97535F26FFEA63C1ABC34FC6CE91288AA88094B50BE5C3981CB3EC1B0F1EF2A5A8029A0606ED9160FA96BB01D22FDBC68DDB8BBB62196571C2DBBEE39EEF320693A8D6441E95E024E166C8529131C292A21B2FE5C6B4BD348EB3B397F370E8A3EF5C9CB3BE74E34B81110C5D715C7E1C1293A059C9073F4CB4CF28A792533010E6CF42723CF89E7120A97424B74773CA95E462EC6141A425A52D2B52466A4990673CA796639D4D6186E9AB16CB5B96F3F2A888F54B5281205C921DDEFD7F30FD1708E60E71A67F4D73CBE93528898803439BB71F6DA57386E517240BB54549E14ADA1C25F4710C8C7A7FAF9F4F4DBE6A29F50739387F5F48DBE48527F890780D0F2CE1EB770811AE5DBAD3C9335096AD7C9BED7FD6A92A4960DC7A5EB4B509D4758A96F5DBE0A78D0184478024C833EF710E5273CA321E553322685331D5AD4BF13DAB5D3364BC3A0951090952BF9716B1A72B73AE9376AFDCFE1C21F7029432053311A419E80F3F9549CA98C28AA6A48ED66EB7AE70C57242545D00306A0727F35F28789B84B00340CC6A44C7BD04E874D35CF2A8F9F39A6286F501B8208B7F41AD0CA6E1C95380467D3806D5F8985C5C9390933D24FEB23E535AA278554AC86B0767BDC7F40469F208B247507F07D61CB2E10D5C051953BC3E11CC84C6B33A03EB4F25CF600DF4E1ABDFCBA36692A428A907E9003EF0CEA29C3C8C5A1B65B3EEED5ECAE2F81AD683717EE5A2995289F0D2961E0B7028E664A410235269E23140A4835245079675E3E5C630A9133E6CA28291283FCC16274A5AEFF007BC31C1F046367916366C2521BB26C2484819A9491C4469CC4CEBFA56B1CBDE9E55A9763C35F7E64C4C4840548521CB960F6039F9EBD225AE116F7772E3CFF0019414C2008907860C8D333D34F9533A126E3CFD4F9F942A842A5CA084B120E76A9AB7AD7AD629B3B12CB094215EEA492924E704CE7F1EDEB58850A80A1BE6D6F387801403C5CB90CE33A234242886A1ADFF4FA43776E005409D739D065A9E7C8F5CFCE91981CD5D8B5B87F5E70DA6A4EF312472D381E7D793C473B720716A75D20E639E5F12338D7B068A705B8B3FB7A9C9FD690A6170E14B0AFE4A7140F4FC5AFCA35ABDA06C9EC4765AE54D254B752D2CA12904A879C67CA7AC75A96C34D4A1282097CF362F9DDCE56E2C2D1D8FC0625A315BAA01814B3D32A803BEA79C7212E12E5BE2B72DE2E859525D5786003900A233E2D3CFE11955B30389010904D40E5CB91CF933691ED3F086270E8C3CB48DDDEDD00136AE65EAD66FDD66EDF1342521014AE119252341DA35D0C1ED9F39A915E212A1722B4C9FB9FBDBB474199814CE4FCC74AF785C5F2FBEBC3524BA5DFCA09D673C8E7AF5D3D3E3CA9A2E6E76BB1CB4BBD7A74AC4362364EF1748CCFE3B353AD4DA2DBC6F114B4D32E369754B24CF081C880200A69367B8209ADBE92FA5DFDE8E23383D8A4CC054906BD0374E56D7998B5B10C51779E1212E21B724407494F4D633D20F6CE9B99C4B24292C3F8BE45A963AE917BC26C992894EA4151DD3FC402598DCDAF993FBDEDF65D45DB2CAFF10B4389584F096C92233EA0E7A03976279D43EDB9DF3B04B94A2E7748615A1D070F4AC7923E2F61654AC76254801201A0CC6A1B91E0D1BBC9BB63C4432A42F8D24498CB91CFE73D74AE4B84C38918FDF0199449360DAD6ED5A37DA3CED89967F9298BB8059F9D4E608EE0C5CF66A0FDC80D25442000531AF126065CC08EF19F6ABC0969C604A12E4121F3BB120307F4BF3888C57D3208240556A6C1C66467A6BDA30A5DB2BC63DA7F74F84DBAD017833B8AB97E09C921DB74B8D822352065C519E5A44FAFFE026C6323178599BA2AA15E3439F3ADFCCC71DF15CEDD4CD17A299893ABB5A9AEBAD44764AC5D53EC5B0692B090DA119CFF0062129303331918EC62BE9C787538A4E1A4EE9DD0501ABF4D0545FDF91F2FEDB96B56354966FA8B1ED9BEBF6CE9131E21B74A54EA5652A895019274CC9390113FB55C7FCC44A40F9EADD201724D389EB7F4D21BC8C2CEA50D6E75F77E19EB0D6F7136ED185DD29E6D16A94951714A809004AA4E8204C98CAA0369F8BB65ECF96A5AE6A0EE8352A4B5B57F2BF78B260B08A528259D4726BDF5B0CDBF6DA81BCEF6B2DDFEC7DC3D63678BA31DC59BE248C2B067DBB8BF5AD23F2A590A0A2A9CA23E735C47C47F15F634854D1F3E51500AFF00724316A06CBDD2D16791B2B78A7E8AE6E2F67FBE5525AED18A99DF26F8F78D85A2F706C39AD98D9FBFE34B0C630D5C59ED1B484129529F4A4F08E28E264FFD08EB5E58F1A7C7FC461715324E1314532D2540042C806962C4D19A99F38B1613C3E850F98505D4CC08A060D4E3A33F286F83EEBD8BEBAFE67B578E6378A5D9505AEDDEB90FDA49CD4025C1307CB3115E72F14FC72DA38D331271733EA7702629EAF70F6D74E959895B11200013F50CC870391616D7F35C9EC5AE0B8484DBD85A069A68421A4B690D891AC72922550333F1AE3D8CF1EE2B684C56FCF242890C55EA0BE60B3F9089CC36C800074017CAFCAAEE39D3562F0E9788DB110AB5682644C204FCCC44763F2A7123112F1A9798A1BC41CC568F6F7DA2451B2806DDA13572EC73AE75D1E0172C3612E59B4842B4571244667B69ACCFC2B8D6DAD9D8A5F889A4AD46515644B014E9DDBA64B0C1A93BC998DF5301BB6A5C97F4F2CA29BB5BB7C10D9E042345F0E47399024F3E53AE5E553F324E2767CB4CC0A208DDB38146D19FF3A986B88D9E8520B3922FBCCEF6D2FF009B45AD866D07FF00816D93174DAD630EBC75B4DCA947DD4121284F88720389648483AC7781EB3FFA7AF1BCDC36D4C24B9D38A46FA036F367673A80C2BD328A16D9D9EA017F48200A86AD7FBAF08DE3B2B862F059E20CA7DC71A42DC1A95788D8292206866467E55F62BC27E24C3E3763C9226254F2D1621DE96ADFBD41BD0C72CC7CA5CA5949AB6F55249B96E1A75EC22EB654168E21224CC1D469AD5A02D333EA4D8D5A1ACA0426AF7CEF427DDCC2B598560A20828820A2082B06C791821B05242B965ACC41EDE79D42A3682A6633FC32490F548371715360F7E02F585424945297AF5CFA450B751060C1E922467FE321E952EB929952D5319886AE43573473AE7CDE184E594AB749607372DF80FF009EB6E5EDB3D77885BDDA4AB82C82D2100E4E0793C264660F083F426743A61B694B5A6648762BA298DC07760CF5F22F9C3BC1CDA906C0E5AF63C99FD446897B5AEEC2E7F96DB6F0F0041FC7ECC3BE290D025DB945CBA90E8570895042279E4267515E6BF8D3E0346DEC2E2A7225050285127774196AD47C9E8D78E8FB0F68D65214C145986603DC8A548B1A1D230CE01B5B6FB5383DA5EB2A0DBEB425B76DE785495B4036B0539C4A924C11A57C9CF1F7857FECFB6A761F7373756A04377CAED6CFBBC7A2FC3A913300958AD03837A8E0EC4B6B571138DD9A5E1C208438661472332799CFBF6F49AA22B06A975673477C8E6DF819923368975A0272040AD9DA81DD837F50FD9F12CC780EAF8968CF8A7AC75EDDA0E99CD3698B12AE403CFDBD5A90D16029F75B81ECFE90F9AB9194E7AE720F5CA333EB34DD5B458DDC73FBD9F4E8E2F0D148214D523337E8E58439173A67D39C65F1CBE1E95A0C7392A05EB4A870D539E661DA255052ED762C391AF3878DDD6B9FCFFCFEBFAD3E958E342540D01A9B599BB1B5A34561F41DBF43D44495BDC7BA9274CE7BFAFEB9F99A9AC3635C02145F47CC11F8A54654786536433D393367E9E96A65128DDD8C803E7A09CF31A7C797954AA31E4A4EEAAE2D4EAFCF817A3F0862B906A4D6CC19ED7EBD61D78B2AD411E93F2314DA6620A94589B9A3F3C837B7864B94E5ACDC7F47CE1CB6F0C88C8C41981F4394F6F2ACA67106E7AFE7BDE8D7D234F95BA2C0F9935E5587497A10003ACC91E7E83EBE95212A783572096EFE9A793BC226555C01D6E3CBCEFDA00F1D38943D4FE84D3A4CE049A654D7DFB6307CA1C3853DB432753C6E295EF13F1F8EB51B893BD3093776603261EF8BC399602502A2BD2C4DB9427E17657C3FC5378DDC6A3B887CC8E16D23CF5F3FDA8845441510F0939A2BCFF5A05481AC651FC875F4310376E70BAB13A46435FAF7AC4C04023DB3DF85A1E270E26241677AD785743DA2356E8D4188F3F8CFEC7D4D47CE21CD0E556A5B8F07F511ACB0252EC03721E963CFFBB5F1FC1DAC5AD5D6AE1295B6E2542089047DE9F104D29869E1EB514A71CAE0B71EE0D62DDB1B69AB0D325AE5962935D4E7DAFC1A39E7BEBDC83AD3AFE2B86DB10254A8424C19F200CF4CC7A4D5870D88DDF50E73E5CEF46E3468EFFE1BF1B7CB952C7CD3BC00DE0FDEFA79E6F411A717D8662B862541D6821482AE20B0A0A80729D397C2454989E4DCB9CF3FB8D3FBCBBE6C0F19C99D8742553379D981555B817F2E76A45BCDE3AF070B6E96C198304E506273396791F5CE915CF228E69535A7077E1F9E57EC26D2958A1BC374B805C31E9F887AAC6F0F527C2B9E052849311CC4E527EB4DD53C005CD4D8BFEFEEF6A343D9B889724198161219F260D42D4F7E96D59E10F6D26D35ADB5921D4B2A74090232C8F29190397C2A3CCF24FF002163AB654CE8787E220F15E38918013126686014012AD417A3F316EBAF55F727B14BD9BC36DDB525521B4A8920EA44EA40F3CE464072A87C5E20A94506A05186B9B823A37121A8D1E56F88FE2197B5B15366214FBC7573F80FD684E95D86B5B22FDCADC1C86B1D3F688F8E7CAAAF3E4EE2FE6002B91777EB98CAA3AC713C5E2D23FD304BD180234A9EB7CE2E54307C36DEB7716D2D869F72E14150901B42949923B2753F2AB3F8687F938B932C1FF700AA0A694EAE699935BC436227ACA666FB1410C9003A8DDE8F95BB691AE5EC70FA7783ED65BDCC72F9D7B10B6D947B086F0C57178ADA0BF6CB6DFF000E4103310A098D3CCD7D0AF835B351253859850E06E9A0B97D2C45B331C5FC64A56E4E29504BD89341C0F3B6763CA3B5789ED2E0DB3B64A7AFAF2CB0D65A4125574E2590001275204C011E9E75EE3C3789365ECED9D2D33A6CB42D08662520EA796AED1C706CA5E2A66FAA5AE639A2921D357CFF005ADA91A3FBD2F6EAD8FD97B97F66B63ADEEB6AB691D516996ED128BDB52E8C802942828827A6BAF9F16F1C7C5FD9F804CE12A7241485070A00F30694D6B9F289DC2786A615552425814900D35DEA368D4EED1AD8EE31ED33BE7BA2BDA67D7B15B2B78AE26ACB0455DE1F88A1854487DB54A01524F4820FC3C57E3BF8E789599F2B0F8A5D94C02C80C5F27CB3EE6B16BC16C192809594A41A312056ACC33A722DCE329ECBEE5B77FB20DA6E1786B78E63EA016BC571665BB8C483BA9525F8E3E29933E43BD79536FF00C4EDB98C9CB32F1338A544827E628EA00ECED7358B3E1F62860771CF10F40039A01F7E228D1976CAF2DAD2CDB65D0AE36C11FD503C4009F7475E102027B0C88AAEA36D6231C8F998A9855354FBC564953D75A677CBC8CC49C0001212C4021BEFD4371A5C0842E3681B40842608F42627A6BE7A6994655178BC22B100A92C49773D684D6A5C7A7187C8C0A52E48734A016167A5AC1D8171D61A0C40DC8F149E12A9CB498819C93AE5FE62A167603112BEA028330FDB27B96F505E1F4B90909DD0C40347B8A934CFD34D63C37103527B020F61F5E9972D2914ED5C66114005AE94352CCFA5FD87857E50C9B3FF006FBEB0ED9BA1C31391981D0CF4CF4927A6B9F4B56CC54A992C63A78057724EA1B335F3CAF1133E6A513B74F604E63306F6CA9A0AB8768BAE1E124E5A723D758F803CBE34DB6C6D2C2CF96654B6DEABB52C5B57FD8D03467E599A9DE48398A3BD19B91FE8E4F696DEE12BC6B66F116AD65376B4B772DBA9C96855A10F40234E22800E42454C78076FAB63ED492B0A665A58823506B466F7A9883DAB800B0A7191737AB68F97172348CEBECD9BC73B6BB0D87AAF9D42715C2D4FDAE2ACAD50B6C36EA99B62B495482A4360898CF3026057D6FF0081BE2F5EDBC1E0E4098A51DD4821DC0343C1C1ABBDF2668E3BB6B67FCB9AB601D4AFA435581ABF106D71A3398DADB6585B414233E9D394768FF55EC9C34B32E5A42AA77479811525A0CB5141B8F7EC8A438A711A414410510414410560D41E460862B695C648227F7FDA7FC72AADC9D958846D6FF309FF0049CD896A0CC7EF3E30E12AFF004F745EB539177B7A77E109780A05464124CF9F3E9973F972922CD8B989561D72C36F100303D5FDEBADE3A7C92B5022BCBF40DE1838CDE36FB6B6548F0D321C4A89CC1CB2F39EFD472269D230389978BF9A15F4B92439AD6BEE96EB1B4A1F2D41CD012E06B959DF96A6F169E3BB3CF63AFBB657A8B6770479A710F5BAC152965C6C89283EE9851907D6A5F68E0656D0C22E44C46F132D40821F22053ABFF6F162C26D64480192833014FD4431605DB514B59F5D390BBCED96C7370FBE1BBBEC45A5B3BB4C5EE9B187DEB69526CF0E52C00B4DEB86196FC57DC096C8D4E4649AF9B7F1B7E10E315B5F13B4E525A4EF2D4285B95B864D51DBD11E10F14C8998144B0C16000A4E85C5F893972BC64EC531469DBC63F95BA8711E1B4ECB64282D2EA12B49491120A4F5F3AF0FF89E51D8D889926602E85148E2DD069DFAC742C1E2062929B97772CEE0D998E86F5E10F7F18AB85788E4A565290A072208196BD62738EDA455490938D4EF21C82F703D1F2A67931D2243FEDFF4FD36353A0A03C0E674CC712E1A749C81CB399E594E79FCFA73AAD6D952F0153BCE34FB0EEFDE911F3B0C50A2925CD9CF0CC77AE5CCBC3A0F1CB3CE791CBACF3EB9EBFA536C0CF5626589801A9B171CCF2B5A9C328752253201567964039A5A1E36F19D4E99F7CB223EFAEB52B2D6A04006835B06AFB6AE42B4817298D183BFBB5FDF37CCDC840824C8CC4E9EBD4F6E644CD4AC9C49481EB6B65DFA529C58CE4D1C0BDE9F7F3EF126CDEB41241041904401033F97CA633315228C61490C6EC286CD6A397D79B5CDA3A6A1CD081C39B69516D224117CDAA08E20349CB5119CC79CE7EB4E3FCE4B80F56B92C6DC0E9CB943338770E01A92EF7AE7D3434E90E91760F2313D33D3B0FF0073DA9DC9C5A580A1275E15A55CB54EBA3011AAF0E4243379F637FC3F387ED3A1690648D753F7CA3BD49499C0B35CE6EC03396CF2E875A886A431208AE60C384852B457C499F9FEF520858A3B1247507367E7EDA34514A6E9F20DEFCE1276E034E14C4981A673D3EF29A426252A39823F5ECD23644BDF4024917E63837B2F0A25D2A12065E47F7A4FE582F7A5EDF88C19605DC3F11F8F75D0C2A1E200100C7A79567712C2A789F6FE4234F941DFB1B9FB7F51E195273D4E7F3AD0A085820D01D687DE543181F4AAB56D3945B778DA8DC2C83CF4E5EA0919F5A4A6CE480451C6B7B3BE6C226F0CA48949A3DEA00AF57AC462D0B920900721CC91D79FED51F35495367EF30E4728426618AD6A21EB5A1ABF7B71F286E0381D25C292DC0084A7946B97DE51AE7484B1B84B92CE2DC1D9E093226C92FBC79B906F4FBF631058DE1F638A214CBEC8532A10414827969397D3D0549C9C60401BC016A55ADCBD5BA67160C163A7482085356A145B36E35A07E3A55F5976EF719B338E3B746D5BB965C7408E04A12DA55C3CA0729EBF1A79FF00714121BE9A56C071E4F4E6747A742D89E319D83DD1366380DFC4D5C3F37F77A46B2621EC8370EDDADD62F8A5B5289095384119CE7EEC4F5E99D657B450522A2BDF3357AB7BE7D6763FC59C2E0D094CC51A001DEFA3D7BE94E30F2C7D929C438CF8D736EB4A0FBE56A25644F972D23E191A6AAC6855986957E1C39E5EA0C9E3BE32E0A7CA32E5BD410F41DAA4F3CEDC6362B633D9EB65F035DBDC780DAEE5B852961283EF01391039C6667B742115CF46E9622C5F869FBA1E51C9B6E78E66638CC32A6A92953B1DE6353570FCCFEA873E3569658682C30829E0425290008C9207FAE9D6A03138B44B9A4A8B819BD6B5AD0F3CDB368A64CC5E231690B98B2AE65D4C4E7534FEAC21EE1AFB6C073C549515FE58823312013991969FB53156225E2C89680429D83655B3D7D2AD4D0D7F152A615956F11C9C963A83C7DEB61EF676F86C86ECF6BB1568B366E61F62B4FE22E3DC2E9B86DC6D3E12841570A8C1D62BA3782F62AE5E225CF56E9485051B937D326D29E71133C94975294F50340E35F7DEFCFEF629F6ABC3F753B27B6F8A61FB3B88ED0EF1768EF880ED9DA8BAB7716DDE3C18F1085070A5285A44E6400790AF69F82BC6F81F0E61A5A6784BA11761906A3915E2FEB5E7BB7F64AF6829C12525DC3BA4E8E3576EA6368D9C2FDA37DA2F13FE77BC8C69DD8ED9FC45616CE0B82DC5D585E30C24884BF6EECA525C4F091C8C9390D281F103E37CE5E3662309885A6539000511FEDC803C433D468F0C703B1918597F2CA522F972D47EDEE1C18DB2D82DCA6C16EEACD0E1C370EC5B106D2957F37C4D969EC4BC4199587C0078A46473AF3178ABE256D2C7159FF226105DC95927851D9EF47EB5112F2F00898A094A149ADDBE9367761620EBD6ED78DCE34965F5B96B7B74A57BA1285B92CC0C824091EE819013CA04E83914FDBB3F1138AE74C5A8135DE24FBEA732F60D3B85D9492005212025DE9AE741DDF3ADA1156D23CE0F7D8B4E28C9C4A7FA82720788C67DA35F854CE071F805247CF92925AEC1C1BBF4D444A4BD88CA13113266ED7E97A11986AD2FC03666B0D5370BB9578AE2CA8AA4EB33197C8683975AAD6D19EA56349C2AB764B80C3EEC776D4CDE99461783F94ADD0000097767D437322FAD6249A6ED9413C62546072CC7D67CFE13562D95890129138953E46CD6E0FDE9E51A2E510E52D56BB9623F2FADC3C78B6C2544344840D04C7E9F0D2AC8B99859B2C83287D4340E3A3BEA1AB9C6C896581FA4645857DE77308159491999FD3EFF007E9558C7E064A945494A5817A8D33A574CEFC214DC2C6B5CB4E2F0A22E0275981D4F799E71150F88C79449560A4D1767B369667BF9718AFE27013264E2A06E5E9F6F60F3B05C5EA0260851D7BCF6F53DA3AD57D5B371F289C44C98A29772378DBAD8B11A3E4CF47F879265202564DAF535D3D8ED9C95A62B6FE33368E5B5C2D170875B52820147BC929053AE401CFA537C3ED9187C74948554298D58B83AD7AE5D03445ED259099891BAE59A976BF96675CA312EEFF1373751BFA7F67710BB6ADB6776E1D4ADB507382DAD956ACF8812B39252A71C54467C4A98CF3AFA77FF004BDE3593825E08E2541481BA0906E3277E2CE6BCAD1CCB6D23E6054C4CB1BE9A25C6B43D1AB5B1A56B1D4EC32E9A36CD80B4A894254983F99244A543A820820F39AFA7F83F1061F1F85978992C10509B35683DDFBC731C5A0FCE59C89A6B76F66CD5E53156186705104144105104144108A8428F9CFC73ADF786E367FB778502C2535CBDDF2D229A6B3524BF166E8DEB942714A913273CF9F2E43A5353F4D48A8EE3BFB31A2D05E82B98B1868E351390F3CE79761A79E9583894804B81467E85AAE6977FDC6A2528107773BB569E768E677F11CDB0C0F07DCC6D1E1D890B773107D36E709B25709BBBCBA43E92836ED932B0CBBC0A5F0E6919F979F3E2C4F9733033904228955DB31968FCBB476BF03E0819067EF2895EE9097A067BF03E7A472EFD94F7E3B59738633B17BD8B7B7C2F1A59745862AB4AD9F16D82CAD84F8CFF00BC4A58F0D10040564328AF953F13766CB99B467AC005D6A3AD09B5BD34B8CBBCEC492C25BEF53270C72A81AE95B51AF1BE7637A875A43ADBE5F6CF170BBC5C41624899C811A11CA32ED541D958444A400774024DEE2ED4BE5FA8BD26480809005402F571A64C694B0B989C6EEC04C0D7427940EB3946703D22AB9E2BD9E89A8580CED7E3477F4B6552222F17860AAB5791A65D2F51FDC546F805646349CC881CFB7FBF5AA7E100C3A0201AB97007134E4DE79BC252E584CBFA921C700FA0E95B707AC3B45F080273D73FD7B7EA741CA45130383E791CB2B7A084A64B241296B8A5B5D2997E9EB0F9ABB0A0924CEBCF9E9A6A7B7FBA7489A1C54B771F815FEE23A6C925C1A0E1EACDEEB687A8BA190904E59C9E646BAFEBA74A7B2D6E1F7806B3963D7D3F55868AC31277999B571CB85EF539DDA241BBA1C2923E1F0C867FBCFA5644C014E1C936A023A5B5E6611128824D9F5D2F461687EDDCE5F9BEFBE79794F5CA9EC99C090D716D43DC53D7F508CC94452A470E9DDBF312B6F78021327AE5273E5A7FBA9A913451E8783E76E3EF50D0D26C81739817BE7C06991E31248BD498D27439E60FA1E7CA2A5513ECCD4B3D1C77D3AC3432C66FD7FA8A16B4B8B9009273CFAC7A74EFD666B2A9E1CD09E34F7D237480031CACDF77E3A43969412224E713DBB4749CFF007AD7E790F4BDE9FB84964166637F7EB0E909073398E5FE7EFE5419CF93721FB86CB98C0B676D7DF1FBC2B5AFCCFF00E6F7D61A9984162F5D2DD33FBF3881BDFF00FB0BF4FA547CE72A249046447DFAFEEF13D842F253C00EAF58897397AFE948C3E979F4FBC377397AFE9442910F73CFEFFEB4411EB6CDB2DA05680A590413009E713F71442A852C00C12D567EBC5E115DB594FE448CB2C81F9E5F4A216DF570F388F73094B8E179A4008511000E913CE338144604C228E09E37AF5F7DA1445BF8060888E7C8F231D873EF44677CB3325B46A5DE195C3216EA960483107D35C872FBCAA1B1D24A86F11ADA84BBDDDBEFC1A24E44D1B9420062E2A03F4C859891D2156ED867967A8E7A89888CF5D341DAA1F08F2E7821AEFA675AB59FEEF0DE74CDE71955CE7C75ABD6343BDBEADF686FB61B67300C21D72D2CB17BFB7B7C49E6D4A6C2DB5DF32D80B52722085100284679F4AECFE1ADA2254B960AB404BD2EE3B72A9882C5A86EA998DB893CB8F95BAEDB6E13D983763BA3D91C1EE5BC399BFC5EE6C2D2F1C75D6997125F7196DE278B841FCEA3CFE3CEDF8DDB72E54B24CC724506F123A720F4D78D22B6B5CE9D34A10909961F7CAA8AAD8A69DCB3F3778CF78A63F6CC214E9B7658B8094A421A484A4250385B006A3DD007D00CCD71BDBF8E189C42A606AD28294B5F53CEB7D21CE1B00508A954D00BBA9CD497356B062FC39B4639BDC7B12C4D6A6DB754941910091F08F2E5DFCEA838E1BE556A963C789E2E6E35B5225A4E0C862D42CC0587BAE6F720521807EE6DE1A714A52D2249CC9839F3FDB23CF5150A6532AC75ABB6AE78FB689AC3E0F7402E920D9854FB2F9BDA3DFC6BA3593F2CBAF3D396835CEA4244BA501B1BE7719FA6A748999787DD4821346E8697B7AC5DB85BA576CD2944E7C53D400A3A0EA0F5EA6293561C99AE1D9C06722AD9E5ABFF00422BB8E4EECD239D0FB6D28E4C5C4C3A32391E93CBE7A8F4CA3BD58307240DDA0B5989D7954B573FB3121C343A99CFAE75341C000E50000504325EA3CBF534CF14CC5ECD5E5F4C6628FBFBF8D5357249C715815715FCF0EBA3EB1B265A58BA5B98D79E7F98F2419CC65AD48ED29DB982292C193471FA61CCBD60549770C082E2CC69D2E215C26FEE9DC41E64320B5625210B293EF78B32674C8FCFCC57199F8829DA454E28B198A07700D5FF004080F5881DA1856A549503571CFBB659D7478C5FED13B2371B41B2831CC19D533B47B3AFDADEA5E68F0BDE125F6DE7405247147828502274E55ED9F81FE269782183056032902A585C020F534FB6747C7E08AB788723EA7A38A70F77B3D6378B707B7B6BBC7DD86CDED8DA5C05B86DFF000772D85494BB645368B2A03FECA6D473CC99F2AFAF5F0EB6AA369787E42C4C0A2A407AD7A8E1D1F23AF24DAB855231AB94414073BA45055CE9D5867AC6CD57A062BD05104144105104141A0274821051924FD690DFFA9812E6AD90CD8FDBBD2352A0FBA7CEDAC794BA405B0362EFD1FF0010A01F533F51C9E1A2AFDA4AD6C702CA9B8E22008CF3C8CE7F7DE9962C7CB04873EE8F5E1E6D95551294B248200701EB9D3F1EE90DD58836A4DC1085245BA14E28AB294A50546328D07330488AAA62B13B8953920A4289198B97BF3D3CD8AE65A9050ECADE20063992DE5DF83C70DFDA0308C53DA3BDA57F97DEBAB6363B6096EA2C6D41294DF2EFADA1C55D20CB6B2CBC9E268A47BA60EBAF8E7E2DF8C932F1589C31994015F4EF3B1008B3DB5FB08EF5E0AC37C8D9F2F7C0DE6AD8BB97626E6A6A1F8F18C3FB47ECDD6D87ED134AB8C47107459B9386BAD3A14E24982A43AA2326C1848098F7644D7807C73B6133B1335654F551777ADC1BF0FD523AF6CC98997BB5A8636A6552CD9B9C890CFC364366F07BFC2708B4B2BB536A7D8441282A28293920E9255C31C5AE7AD72E46DE4CA252179977229DEBCB99D62E122724A4070C33353C1F5EB5E81A2E24F1A44127976FD07EDA74A8DDA1B6538896AFAD2487A3BBD5AC09CA8D946D37FD4FFC7461EFB3B738F0B2E2A1D0A002B91999F211AFD67388AAB9C4BA94AA33DFC9CB1A3C315000D81072FCFA884D771E0E4A24C69C267FC73D7B1E74A2279A90A26D6B31F75AC69B81BF8D356E3AE55890B6BE416D27333ACEBE7039FD9A7A8C4501053C43FB670D952BC631FE3A540BB31E845F36ABC48B77A88E6077313F3F874F853A4CE71424BDD89667FD7B1091C0D281C7176E7D1BCF263128CDD254849139839120C41F879473E94A267310C4BDEB979E6DC5E194CC2906D6E4FD2943AB5B330F9BB94C6B19794FFBE733DCD3C953C13A72B1CAFC1C5FCB268A95914039DBF421F35789809F78F48EBF796524E7533879EC0390DA3F3F400E6C0D2F0D26C87FA5A9C8BE5E63D6B9C48B5700C448EBE7E7F1F873135288C40342486BB1A7BFEA1B2B0DBA93F4853DB5F327F5CE1E22ED2980788EA2674E739E5AF3CEB2B9EC7F950330259ED5E37E1AD2F0CA64920B817C9A9D19FBE6F0EDABC40000E2275D75ED964639FAEB5A0C439FE56737166AE74B65DF46EB9248219AEC452CFA57F6CFA44BB174D142409CE7F365D7B76F8D6558A2C18B1A66D72F91FD00781762B94A62E03E5FAA7A4394BC8509063EFF005F856AA9F675543D01704F17CA9701AF0D8CA5120EEA8B543547A5CF768B7EFDF425F58E6408EF20E7A9D23EF3AD8AF7EC4E4EC4B70A74ADE2C1844BC9045F3ADFDF488972E10391CA7E197DC510F100877CDBDFBF3868BBA41204191FAC511BC34710A767872F3F4FDBD28821C356E80DA78BF3738CBE7F7E7440E0355B480E1E16A8C8039F2D75FBCE32F2A23054407A9CEFE7124C36DB2C2595092999F5D2328D3EC5109B2D4ADE0A2125E84FE2BEF8C475C59A9D27878403D49FF7A7C0E9D688583EBFB6B5BCB288E368A6D5C2AE1319C8F975EBD49CB91ADB13212AC31555DAEC694CDEC4DFCAAF0B0C46EA00722B716377E197DA164A1291A09E754F520CB9C9235AF0D1C3F2E0E2958426621C3024358D3F7C757C9A310FB40EEE0EDE6EDAE1092D0BBB2BAB1BAB22278D28B7BC6DF7818132A4A2044F43578D97354896921541DBEFA6BC223664DDF514545CEF1700F7C99835ABCA32EEC86D17F37D8DC1136CD949366DDB25C7C43893628432EF11131250784822728A4B6A6D39A842920B8B67AF46E8C2199900CC0B0A502FFC41649B0A8F4CBD623B107AD6E5C5E6E2F382A519929C95E920FCAA9B331866A89726E35CEF7E5167C0615E50243F1CEBC8699E67388A6908615C4D0CE79F4FBEB1E94DD52CCE340EF4A5D9CDE85BA5A25E5C80C10121BFF217F6D5ABC2CA40721C580547398CC41E607D018EDD7518204EF29245F8335B2A55DBD1CD17004BFA40492D9FAE7E86AFC63CF01BE9F4F2E9D2B7124203311C68077B6B9C29F315C29CFAE79E7133689E06D0907213CCF53F79C69CB2ADD321D4E41A376CC598D73115DDA65E6D1201AF2341DBDB9A44F5B93A8F21D0CF3F9FD6A670B26A29A92C3D3BDFCA23A24D1A791A7AA4800D1886FC7BEF7821AB90083A0EFF00BFAD4562177702C79585FCA99C108ACC0D0CF2EB974EFD2A0D52809A565BD2B933166CF9C3A4A5CBE432D6FF00DC362E01208206533239FC39F5F86B50BB63103E5290E5D8D7CA96BF1E42D0BA50A5073BA34D7EF15B37EE5AAD2B65290858578E63DF24084441CF339CF2E432AE458C49FF0024AD2186F397B9ADF46074D4E50CF15864A812A033624DB50347B5B2D6B14D9B571892B106AF54971AC4187985A3320A5C6D4DA723AC050991EB39575EF03F88666CD5E1C15EEFD686A961F50F4AB7E1E2AD8CC227EAFA458D8703A52AF90CF568B0FD9331EBCDDA6F276F373B8A5D04E0E8B9B67F669BF10F02BF13C77777E18510930A589E0CC1F39AFAFF00F00BC668C56C0C24B54D752928497232C8BE742F71DDE394EDDC0033D4B523EA0EC5BFAF2D63AEF5F41A394C144105104144105609604E81E086C5414A206467A743A799EDDCD343FF00BC6A0FB8673F878457FC8E56FCFEA3C518498FBCE9F4914E9EA4FE217921C025E9F9311EA6D2975C75510A02644CC40EBF1FD269AE3801289CAA48FC1D783BE74021F8A25290EE6F7677A76E2CE6DC2CFDB4BF1856018D5EB64A549B37CE52238585F4E7979EBD66B98EDC9E5089CC48FA1449E878E59F0A350BC8E090662E525601DD26B424B90731AB5F83691CCCDD4356588AB17DAC712955F5F5E5CA5D5C02A2597DD6D3EF6A0C0CB58E5957CD5F8CBB4272FC47899695AB777D4C0167A1CAE6AF4E7725E3B8787E684609296C870ABD331703A8222F5C470DB7C495F895B214E2566094CC4188EBF4CA72EBE57F11E1E74F4AD6497A972795EADA67D62E586C604B7D4CCD98AB57ED61ABEB0DDFC1028173878652204690398CBEFB5719DA089D2A6299C313AB54F1274C998F08B2E17690A00A532A8EED40D634FD45B17964193040100F4E5DFEBA76EED70F2E6CE35A825F8FB2F406DCA827E562C2C0726BC7866FEDAA62354BE06C27A75F4CC0EBE7DB3E55ACF0A92B292F562C03D40ECE33F485400B5125C0A7A33F4881BC7413CA679F4FBE7977CE45665CD63987B81E4783F1D0BDA1CCB96EA029BBA9B5AFF9FBC356AF3812124E63F7D4F5F334F11345DD8E9996F5E196A61DA70E0B101DF3D32CADDC3DE8F0FDBBD0AFCCA811A93F300E59C098CFB9D69DCB98406714B17FD8B37BCDC9C28091BA05726FB5B958359A82262DAF416D2388F38CF3991C81EB3F38EA326794B3392EC4EBC49776E3DE223172B72636E8A52835F4E36E3122DDF640A8E5A139E44C67CBEE29FC99CC41C8DA9CC6AD5E1E511D324850702A323FD39E50E917C018E2CB9EB23319EA6A630F3892C72ABE5CF5F6EEF0CD72B781A116C980CA262DEFB2199E5AF78FA8CA474A939739E9F503E6071AEACCF943654B20B338399B7A7DA1637C028C100E53999F4C8C4E7D7AD0B985C392F5B7DEBEFBC64E0C285535EBA51EEF91BBF1061D377C081EF721A93FA7D6739D2693336F550A8ABF2BD7A7286D3304E480917A86B7603D4D75CA45AC440481C5A6B9E539763F31FE76F9F5B06F3ECFF7867336706074ECDCFCBD987EDE240089F8931E79447DEBCB22702CD57FF8F0C8DFF3C4086EAC00161D48A7EBAD32CE185D3E1C714BE67498CBAF79CFE7CF9C8C82E9F7DB4CF81E79292E58969DD1D6235C744E7F7E67A9FBEEBC291EB69E3015966796BE9E7E74410ED0D1CB98FB39988CBEFB9042A4418A21BA955739F97EA1CA3F30F5FA1A235F9838D32F6605FE63E9F4144642C6448F2FD4534463E6F151F7CE105B3C6A2A024E4797974D7F7E666A41697C29A3B8A9D397E6ACCD0D5734905CB0CAAD4BB77F79C79F86FF00C7D23FC7DF5AA74D40F9E684D49715E9F807C9E35130A894B8C9ABCADA583FE690A8B14DEDBBF6AECA982CB8953660825685465A183F09CAAD1B3641296C886E4DEDCDEAF7AC6AE5F526952EF97703CE30CEC4E38DD95EED1EC6A8F05C6CF3ADF829D14A17CB53878473C959F6A63B5F0CB014F6BD3DE95A178D92927871EB945E7F855B1FD3590A503C52733EFF00BDDF406A80B5FCB9C47F17E87DFB348B66CEFA64241CA84B71A574D32E791E1764FC3FC54CE1415B31622A479BE61AB4CFD0C86F8073705A90A04802201F4A9712A868321F904B5FAC60CC466A0F7ADFCE00848E533D62994D9612FA1D453D83EC504682725CEF100017CBD7D9F29063F2A2639C41C8EBAFD08EB4EB0F237D20DDD89A56BF815B31ED1018C98664E5682DD7A0313D6DCBCB4E833E8627976D2A664C90801C574EE0D087AF38690F0B9C23873D351D67F6CBE149E24356CFE6037DCBC10C9C7323973FD797A49FF5355EC49604D33FB7BFC410DD4E8EA66633F8F7FDAA2A79694559B2892D9BD2DC5A0FF2025410E6F52E5FB701C74EAD5C7233275EF33AE79C7D39552368CE2A252EE1CF50ED7ABE46F0FE54F490C7DD6F7B71B7DA85105B047AF4D4663AFD63D2ABCAD9C66FD6CF9E55604E4281D9CB5E9CB49CB1BA4920BB3035035234D49BD32CA6F04FF953E71F08F9FF00AE5580A5E0D48209494A833508ABE5E5C1AD15DC496DE21D4E7E902E336D3AF9346A6FB495CE2BBB9DE26C0EF5F034ADBB7C26FC338F968101D45EBACDAB25DE18E2090B2654401A7427E82FFD3DF8C97270D8390A9845500D7FF21DFD98A2ED8C37CCDF3A822D62416D73D1F32F947786BEDF479FE0A20828820A2082B04382350D0423E17BD20FC7BFA521F24EFEFBEA18FAD3DEB09A90492411580B64822467E7FB5390BDDDE24528CDC183DF8F0B7185659DD0C47B73F6310F7E16A6DD436616D14024E878950207FAD79C0A678D5FCC945097048CE8CE5B2357FB71877267A10BDE5B9B51BD72A458DB75875C5DECB6376DC4853AE61D74A46A724DBB8A39C4FA0F2F3E79B5F63E23132E7310C50B26A43063D4D1A85A99449E1F1D2654C4AD2183B119124B0E0E0F91E71CC7DC03CDB78662D6B700B86CB10BB45C30982E33E2DE3A10A713FDA15C8F31074135F32FE366097B3FC49893313BC42D5E635AB3EBE6CE4759D838C97330882924067EBF8E71B14E58DAB0FA2DB80C3852A4AC0050A044FBB9004A4644472CC579A76A6D5C2CC2A925237AA0D85EDF7BDEC0DA2D322715A4A81293902F6B56D434A5BCC45388336E0A9B42488033CBA7F831975CBAD4713E1DFF00B8952E58649ABB55BDFE844CE0D730A52B529DC9601C677FCB77D31BE3764A3C4A052224C73044E9F5D7302321155BC4E1E4EC452BE724109D450BD0655AF0D38C5C301342C01F507FF769970D39B73118DEF1F0CAD6D282894C024091FEB9FE99CD53F1B8A463310664A1BA1CB3160CC464387BB0B4C895BE9DE01C3E59F3E16CF567310370AE324E639E7E83989E5FA69AA2896A772483AD7D93E50F25C95381666636B0AFBCF867185B738894A81132333EA0F7FA75269E4A965C1736CED5CF3BD80FD987F2A5D1B93D7304DB8BF68593C7FDC72E93CFB7CFF6A7299643D546B93FBF5F387E84B07D4797BE9A4485BDC708824FBA3B9D7D7EFAD2C990A507DF23AF5D38F11D1A22717277E61666B55F83D439F489469D2B88240E84FEDE5CF97C9E4A429000FE4033387CEB71AFBBC46AF0E6AC017D0575191BEB0F1B5AE75240EE7FCF4F49EC2A4A4952581CF9BB072D7F2CBD192F0C5D8BA6DAD7DD0F0C8E92F6EA591AFC7FC6911D27D2A5252C30A87A3D6FC03D6D4B521AAE42F7EC00193776B663B8BC39257248574CA4FCFCBCE7E94AB2D44AFD1DC9D7A37EF285D32C0480454660DEA2FE74ED0B0714343F7DF38AD0DAC08CC1F7F68D572C2ACC3EDCA86164DCAC0E73D79FD72F81D3CE912B50140E732F5EE7EDFDE9FE383763CCFE0085917BC3C8F2FBC8E83CBBF334899DBAC2C43BEB93035D350D784578601CD0835A0FD71E10F5ABB42D299E2988D3A73CF954DE17100A035F314278BD7D1A9D622E761F754D501DDCB8BE56BB5FA457E1970FBAA10399C819FD75FB9A72678D5BB76BFEF8C246436BE9DA9F8891B76F85213AA87EBD33FF005F183FC814FBB57CC7BBBC24A400D56E7D7417A5A251A64902018E53E7F4CFB0AC89FA8FD757D783C375CC4A417E36FB711083EDA90E28149F203B0CBA65F79E547CF72CCDCF2E758899D8D42565390D6F09FE2380C9428913901E87AF5A772D3BE01D74CB57F7EA23418C41661424F1FBFE383C02E02D51C0A493FF006FF5DBA7952FFE31DD7ABE999F2BB369F78748585B0B12F7B7DE1DA1A52E22339F9524A94437DF3E4C215DD6FE4F5B337DFDFD9EA1809480A20913A41E87FD7FB9DD58A4A257CB2EC5DC5B577EF91A68623E7255BCC0B0F798E87DD28586D133FA75EB3CB9F2390CAA1BE519B38A85002087676E2C3FA2337AEA90C039248776F2A97CF3F21482CA6CAE8DEDC00BB27213E1A3374920A678498804C933A0F302D3B3D69414A480C5C16C88033073CEFD291A4D5AD52CA65969818825DEEFE63B738D24DBEDB9C0377DED43B33835F3FC09DE2FE2835C0A486D2AC3ED429297E620CA804EB988E8697C66CF998B973264B49284B6F100D09B7986AF28565624EE21DC29EC431A5E9CF8756AC6D25DAD0D043AEBAD2D4E0E24A50A95709CD32239A4F7CF9F3AE678FD913118A2681CB90470CACCFDEDC4C5A701894996135B0EAEECD5A8EFC018669BA64F17BA470827DE033D7439CFE952182C27CB29DE5001AE4B00D6AE9A30E62D12C10660040234CAF47D1B5D3BC3138A32501C436EAE54470240E210634FBEF15253664B427743161C0F2AFBE1902A9C028D4A9406AEDD731D61C33749791C7E1B8D8E8E260EBDA6A0F138A4A7FDAEC6C050F0B5ADF624C36560940D161455672EC03D7AFBA449D9BA16522149CF22AD3C869DFCB4D69FE071682907779BF17FCF688D9F832164A957B36A19F5A56F9F289F69D6DB4F115A4F380738CE7EB91F954F4B99BC90ADD773A39F57F7C5A18AA510696199B7714FDEB0E53C2FB7E236EA013AB64FF504728F4FF3AD23889732623E942BE907CDAE2BA5883CA90D953128594281E7979B7BEACD16D393EF24A0680AF248D39E9F7D6ABB8AC36254584A5B1E05AE19F8D3B5612389402DBC003627D7FB0DE6611530A0A212B43875F70CE7AFCB9C7A659D456270D8A5A0A132261CA8836CEFC1AE7CE3230867B4C133753715A7076E5E9788FB9429912E10913A9C819E7E9CFA4D55A7EC4C74C98E30F38392EE93577B8A802DE54021CA6589742B0C9E3A59A9EF9C38B6426E5A406DD6C83202A72272E7E9EBF0A5E56C6C52505270D3778D2893DB8BFBAC213E724024AC07C89146D3A8725F95E2EDC1F09750B0A2EB5CA73EDF64FAC9CAA2B1DE1BC7E20B891343116496350CD42F5D7FA82C4E20027EA0A73FED6D5A96D4D3FB8B6F7C1BBFB4DB6D8AC5B087956A0AAD977AE2EE2238AC10AB96F8091AF13606712623335DEBE11A71FB1F13864CC9733712B41208E233CA95D32A8885C60F99254776956A57335B90CD901DE3A7F5FA248F3641441051041441051041441056ABFE27A7A882193EDA65797FC8524C8FFAC1EBD7A7AC9A6337FDCFC3D4379460F0152439FCDB2E3C9A22311B5172EA6DD79B2FB2FB6E03D16D9466398F7B3EB4CA700A95301762936E51906BC88E5F9F28E4818DCFFB4D6D5EC662292D605B7EF32BC1D6E7BACA1766C179DF0C9F7412E2B329933A8D4D7CFDF8EDE145E336962B13B942546D900C2BC29C9BB751F0F4E57F8682972D47009CDF96B4A5D9E3688DC5AA516CDA96953B61C456B541E20F105B20F4E129D7B467957CF4F15ECF3B3F1CBFA4277546ACCF5E6E5AEDA5EF5B8E1674C04925442B22FCA9CD8BB80DAC33B94A16F39CD27848F513F0A4F66ED02256EEF55B95B8BFA16D22CF849E7752924B55B2A1E2EFF63DA2C8DA048085102241FBFDFAD527C5A83890B533F27AF17B39E5578B161B1664EEDCE64E57D491E6F4D2310DF31C6FAD406A731969DF239CF49CFBD50F0F8764B171C7F5EFD04742D9988F99870ADE3567626E5B566A56E395A229CB52675075CF2F49EF3F5CA9F210ED635A119717A3F5E59C4BA660480A772FC185756FBF0A0864A678544427D7A67D2453C9729DB2CEF7A57D294E5AC3B97352D40C0B683576D7CA29F0BB27EFD29EA25B5198E65ADE97872165550A3DFDFE22B4359E83D34F5CA94F9645037BE548673D637D8DC69C75B57FACA262DDACB4F86BCF4D7F7D4F3A70843007B7ABFBF5864B5B3EA7ECD7AC390214B1D08D3D69CA406043977A8A80C7EEDEA1E192CBA8D5F4CF2896B6E5F7FF006A7D2D0C904DEEC3BD61AAD63789A97F76C9EF0F29E243243FBAC60170F0526BFE47DE519829B1A13CCC1053199FCD5CE0855B742541249044E7CB49FDBE039E54B4B9E515A002F5AF419817BEBD5BCD92958AD40A8D47937189961C491131FBCF5D233CFF004A9097377F3A6751A52BD3CE2371092806AED6E00E67ED6E222E9B0B42EB285C4CF4E601EBDE239FEF272249981296724D1F2A9AF3FC1C8C40E2715B856E5865ABB726157AF9C4FB162604A7A1CA472063D7EA7BD490C0934DD069907CB835B5D2B77020E763807482EEED50E2AEEE69C69AD844B23096D684AD60151C8F5CB9E79FC63BE7AC7CD93F2E69435F30DA3B7E3AB06110F366898B726996ACCFE8CE7AF086AE60CCE5EEF6E5D27D0CE5FEAA5B0E96003529EA6BF9E3485253D1C9AB9ABE9FA7885B8C3421F52909F76004C0EDDE7A7CE9FABE9431CDF7BD6E3366F3D22770F301483C18EB9559BBB79C3450F0647965988C867F4E9CA34A8A9F340A02ECE031AE4FCABF7BBC48865243D7F3CFEFA455E3712667D0647EFCBA9E548FC9F992CCC203F70C3BDC7A738653D20ABE9CB8BDDB9FB162EF0D9C741CB2806013A1FDF4A889D3C492524B35F76FF8E57A563544A2A06EFD5AFC32D7A5A1CB0B6EE91E0A9400642811944AA639E7C8C771CAAC9B1569C64C4246EDEB93B8E635E3530AAE40975DD2EB66A529D01CB8C7CC77F14CDF9E27BB9F69CD81BFC2EFD617B118B205CF86E194B589AEDD242A22006E467CA7B477DF0B786938FC0E2F086582B9E84AA5AC8000DC054412C58E90EA5ECDF981134A084E8433F3C9DED51C23BADBABDAAB6DE8EEBB65F783865DA2E19C470AB452836BE21E236C32873249227881273D7BEBC3FC73B226ECBDA139003142883A79778929527E54C1282482681EC5B4E2332D4E4F192090EE182E90402252AD44C1E13D3420FC338AE4D8EDB0AC3120120A6843BBE4FABBE5DA26A44D32D5BAA72E29720357F41B37B88696D6A9504BCB2A434A909520C75060F98EF9FC9BE0B6A2B1AB4A12B2497CC16E9E553D21CCDC6EE4B2CA049B05337170F4F2B4480B1B8B53F8AB4745C253EF78774A2B4FC04F5F98EE2BA1ECAF0CCEDA094CC082ACD88705CE74EFAE4E5A20B15B551BAA4EF096A3729A372CABDCD6E6E9BFB5FB376AD78B8E5F5AE10FA5243BC4EA18B64C12014851CA4013AC98EF13E9F066293382132949723F8A481E9C34E4F1569BB6D3281419AA5EE9242965D44939B73A35338B77FF0077B77CD2D4D5AE28DE3CE03019C1DE6AE5E39CC7083A9CC0D64D744D85F0FB153F70190A24B0FE3DB9F3E111D37C409208DF14ADF5D756FB5ACD01886F796BB95A3677775BC3BB7CF086DDFE55C76AB3191050734FCA39E75D5F66FC1D9D88097C37F201C14126B6A31A0EA5A910F88DBE92A7DF0791C8D296CFECD488C5ED17B4A6D09E1C03774FDB30ACD0717C2AE90424E93C32272CFAE7356D93FF004FD3310949FF0012EC7F8137E9D9C6778889DE25912D442E72535A396B86A9A5BD9AD5EA775DED7F8BDAA2FD8676570E75F9E2B47137CD38D41812D819150CC6798AB76CFF00FA6DC2CC94F370690B0CE4A0022D67193B75B8A3B997E324225309A9292285DC16E2F51D351530DEDBD987DAF76956538A6D36CCE1ED4C7B9777AD40503966201D34D7AD3FFF00D9AB03BC01C1CB482D532C7FFAD5C3F5F26589F1B2508514ACAC8FF6A4BBF4773C47DC45FF0084FB126FC5BB768DDEF0E2E332E0B3C56E3F0F9CC16E53232D7F5CAB63FF004CF8100B616496ABEE25B90FA6BA655D33819BE37132BBD3522B42C08D2E696B5ACF998BBED7D8EB7CCC883BC6BA911A628FE79C83F9479721DF5AC7FECD18225BFC29433ACB19016A1AE79E5C1E317E2E249AA8825EFF0082CFF9EA6D6C4BD8B77DF89626F0777A37EDD884F86EB2318B808536EA7856387860852499D35E82ACBB13FE9B64C85A66A30B2928490412802D95B80FC55A1F7FEAC4AB0E874CC515BD80B87BFEB9DDE3AFB5EEA8E530510414410510414410510415AAFF0089E9EA2086B7124122252329EFF3FBF8B19BFEEE9F682231C5388B76C28053CA2785799004F3233CC72E94CE6BEE299AC6FEF568C8B87D6388FF00C52F7ABB3BBBEDAADD6B96AC5D39B6CBBDBAFC2BD6012432D8758FC42AE543FA890599E18E8794D79B3E2CE1B0AAC3CFDF03E66EA892C1F5CF4E9D5ABD9FC15B2E6E2704A9CC0C93BBF281077854EF026D5398E7AC65CDDEEF16C36EB6630CC6F0AB8FC4A95676DFCCD09585B81C4B484E406842C2B881CC19915F2DBE2761D29C7CF12C06DF351C4D45299E95BE51D065EC6DD5268F7BDEADE7622DADAD95FF009EB0D5B25F752E7094E6A104242722147411967AEA7ACF32D9B2267D34AB9CAEFF006F47B189991B294E027701A3839F6E3EB5D22C8C476B306C41F559DBDD34B7F4E04AD255C51A44833F18D09A4F6CE0B7904A810C0966A1FC37BD625E46CC57FBC2695041E5ED985E2DFB9B55A417142352126263B8E91A76D73C8D2578620B252284D142A75B8E00F23163C12C4A40402C2C374D388ABF0AFB10E4B6E15240854C72CF3F972EDCAB797870186EF30453830E1C1F8C49A2752A5F997E3C85EDAD6193D6F0E2840032D4769FAF96BE74F65C9DE4D1249A01981CE8DC8F387889E08A966E37AB52A1FA7F690B73CF847A034E938726C03EA5DCF973B08748C4351C97CEA416D0B8E7A7185516AB1052011DB9FEB97C8D60CB656E903B38AFE5B85A109CB04EF6F73D5FA72F6D4906D250334EBD35C8E91918EDDB48AD9282E1D8F0BBFBA43652BE92A0687337E9E77E25E160C29C25620054403AE5391D3CA9FC990017501C9A834CAFD290C674DDD0C286CD9BF11A0D3D6D0F5A49447167D87AF5E84D3A4A2B5AE9FD4332B2471CCFA43D4A4A9214220FC72CAB785E5AC04805DF5EBDE91413026915FF0023D3D042D14F18EFF7EB4D8DF3772FDF2820E34F7A6333F9AB9C10DCAD5F886D0028F8AA30672000CF8BA65E9F11496EA8AC685CDE9419F514EF1B9004B51A029A134715F3D22E8B0B65BE0F014FBA7324E5EF699F3FBCF5A90C2A14A50487617239BF60F5EED15ADA53D32D248CC540671CE8733195306C25E6EC99E25227DE397427AC7FAEA60D5BF67CA2C97A91600D07EDC76D68DCFB1D8F24AAAD90E19BB7A718B81AB55208E2E123E711967AEBF4AB3C99296714D5A9A8F36AD44434CC4A8B3E6ECC752097FEA1E1B67D49050501267224E711F7CB954262E48FF20B00C097A0CC163E8FAD6B09A66282805D9D8101F5CEFA72CE18BCCBC38812920EB1DF58F2E7D0C75C95932E9A6BAE7EB125266924390C2D50F415E86D119728096CF101C40667D632CA7BF3F5ADB10B094901ECFE97E0C6BC0F0892933095259C02406B5BCF5E5C1A2CEC4042A412069976C81D33F3FD0D5771130826CCF400D6FAB53A69C226654C06854406E9C8F319D43C44A6FDA6DF6AC940F88E85A92A3F97DC049063AC65F5D6A730E12AC0B9DD7637A9E47953D3842CB93BDF58766CBA926AE7DB5EED98C41ABB75E690140B0A09254323248047C33D34AE6FB5E62C4F5A52400F91625EFDAA2D47AC3B9528001D2406CDB4A75CBD28C621F1EC64E03678BE24B2536F8759BCF5C70FE672195AD01BD24A4A7DE274F4136AF07625B132C2D4FF005076342E685FB6BC8343D421139280DF5289DD24000006B5C9DB99CB26F8AAF6EBDB4BCDF06FFF007838A9755F84FC420308B852BC40BB36D4942923300F1B6082328AF6EF808C8FF1E4AD4582836F5890C7798926E07763589D932E504EEB0A52845D801CEB7CEBD23B37FC15F7CB8CED86E6AFB777B417EAB9BBD902B656971D52816EEAE1D2C8682C9221B48072E523491CE7E29EC1C2E2B6962276113FE8A80202D8A8A825CBF026C29C4B52313E5032BE61037D2A0CC03873EFD873D8B6AE1413738580A0A6D633232214A2A11A99EC34AF17F8B3654CC3CE58DD206F1A686D53AFEAF0AAE58090B60481FEDCF5D1EE6BDE13C5EFF196703C51BC0ACDBFE6584301C4A31042BC2BB2B495816BC32A594C7BC32CC8D75A6DE12D98B998B96ECCE9705DEB40D6D056D4269159DA139482400A21408DE4B306C89FBC6BCEEB5BDFAEFD715C4B0D5DF60BB2F6D62F29B76CD2EDC59E24B4F12802DB79CE499131911CABDE5F0D7C2523132646F212B2424071C017ADB3E0383C5036BE38E1A5AE62C929059DEBF51005C9CF8E71B8BB27EC2FB3B89B76F8A6D9ED7ED1E297AE2C9B9B07AF90F5982930021A7133C2A2339D743AD7A67667C1D938D08C40908292C689B934E3C3DB18E6BB4F6EA913968485D0515FED2E1D835CD6B9BD2367765FD99F74DB1CEB16D866C761EBB929917AED833C4484CCA9C0264E7399931D44753D83F086448521F0EE035D2185726D397EABE76F621614B52D2056809DE1C6ED52FC79659CF0CD8AC0B0D65B0C61564D38DE9E1B290948E5A0CBD79FC2BAEEC9F0260F0A9015252E007DE48C8532E178869DB56729759C5292ECCAC83BB87B7AF089D18724A4B72584447F408491D00D3BFA73AB6C9D818294001290198064836CEDAE54D4B988C9BB4C12CA56F914FA9CF5D32C8D3BC7AC614CDBA83BE33CEA89FF00F6AA67CC67E5FEE2909B83968594CA410336D45AB972FC42C3173152C268126A00C859868E21FA909223810465A8F39E823427CA915E1C9AFCB7A55DB203ABD3DB984CAD4EE951A8ABFA694EBCE17693C08E1002626001909E9FA8EB5812D219D0464E406A6B7E9AF184D454413FEE3ECFBBF584D4DB866081D3F5FB3D7E3B7CB4A88FA7300903234A9E3DE19AA54D2E778EE8AB3B1A7BA65DA18BD64B716D289013EF78C53F98FF00D6391E433E5E662D1853265482C9A32775C060D77F366D7842D2F18A928092E487A1B8E219D896E55346789EA46310510414410510414410510415AAFF0089E9EA2086970471251FF79F8A472FBFDA98CDFF00774F3682239E50532FCC715BB657DC0009FF007F6299CD2D2D674493025DC3B5C5B9F1EC3F6C3807BCFDDF2F7D7EDB7B518DE3A97719D98D83532D7F2CB9FEBD9B6AC4AC4B40B6CAA5293E280A3FF909D419F137C6AF14A70B8AC4614AC823783386B1D1ECCDFBBFA3FC1189972363CB4B805AD402EE4906ADA64FA3455B57BA8DE46C0E23885C6EA4AD9B7B3522E1581A83C1A7D025C0D22D99038E402003919F8FCF2F1763063F1F34BEF6F2CD2F57A357F74ABB45E13B430CC085A083BC1DC528D4E2FC5FCDA9D99DA9F69EDF0D862F82DC6C4B7B1F6CD2516E9BD770FBBB274F00285B8870120F1147171644C8275AD363EC733A585897401E81AF9FE6BA662A61F68E0F07BA9993F794B2774CD507357A13CF2E91963769B92C6B6230C38A6D3631758AE36A70AD4871F53CDA55E21C805C2C08239CF789A8BF116004996BB16A65462D7C9BBDE8F58954ED992A2109A519E8C5C6473F224114CCE60BF4BAEDBF1BE84B6E70C14A072190813398D67227E7CC66A01986F760070A6638E5911AC3DC34E48427754A50A9BBD0F1B3D6E3F5169B6D7F54C8124E51209D7A99EC738AD928208FA41E14CE9FBA7AC3D97354A2EF50C5BF23B7A8872F5B4AC98D6232FD60FDCD3F9325C5807A923ADF2F7CE1E89EC5BEAB5C56B736FB0A425F85EDF2FF00FE4D3912C3B96E82ADCF28792E6D01766C9DAE3C8F0CA1C22D55C2397CBA763D64F4D05349D2885BD0699655E7DBAC60CC4851049232A8CEF7F64E96854DA280399F847E95B4B95BA5CDF2ABB72F7A9A420B9A6C1BA1F5D7CA1C36C10800EA3969FA7ED34F522828C746FB4315A8B924BF2FEFEF48AFC0EFF3FF0014E25A094824004703EACFFA221BAA687D1AD7CF979D042C84F0A427A4FCC93492BF91F7943D45520FBBC375FE53E9F514DD7FC8F4F410EA11A6CAB9E67D608298CCFE6AE704327314B4B7B945B38A48B8585A5906388983300E663B4763AC4961F0A66201670D76E26E5A8789A0E2F0DF133D32D0A1BC58EA6EDC3EF78BDB656DEE4DAB9E28595A9692041260AC11944E635CE0F6A929185DD50200BE966C8356C598B5E968E79B6B68B0500482C43F77E347A072285DE33BDAB45AB76904442465A119099F53CAA7E47D1BA416CB466B79DF2ED1CF66628AE6106A4A9989E3ECD4085C9813F2EB53327115634D06BC2F56A97F4891932B7C0DE0FA021FEFC3830B887CDE6CA08C8906077EBF1FD32A6F352262C9157B51F953BBE9084E64CD2906CC468EC096F271CF488EB911247F8CE073EA273D73ED584A08A873AB0A67F91ECD1590B3BD514E1AB54FBEB10576725CCC4465CC41FBF3F8534C67D20BE6E3D07A889A90BAA493FC5E838EBC05F5AC59D7C499E433CB94683D4E507FD554B1AA62483C4D6C497FC8112B2945D24D5CD46B58C15BD0DA74ECA2B09BF52F8038E96A6624BAE25B83A4FE61CF3CA7954A61B1891830924D4103880F56B0CF21CE2D9819489B2DF7492DD32F315B74317BE1CEA5B63F1474B86EDDD0A3FF009A52AD4CEB320E939F9543694933662940E74E3C0F4C83D21499282544E45DBD1D9BB5F5E30AE2CCE138D377982E22A5A19C4592CB8B948042D0A4E5C4623DE396B9EBD5DEC7C47F87392B3A82E2F43ADFBD7BC3254D9921237777792E6BCEC39DFDB8E72ED4FF000B7DD16D66D5E298E0B92A77135ADD5A7899D5695183EE480788EB333A4E55DF7C39E3C184972E509E400000EAA076167F4FC46A36B848DE2EE0B1029997A598D6B9000B0CF9AF87DCE0DFC3CBDA9B6B764307BA2F6178F5CE18866C50B4A8FBACA4A816925293EF3B23203E157FC76D71B63672B1213F313291F5CC4FD5FC9DB78F90CF3E1166D9D3938C9414A3F4AC58B034D327AEA03738EEA6C5ED939B7F81E17B476166BB4188B2DB854A6FC39F7539C82275D395797BC6EA94A9D34B3073609A5E8CDA9BF7687DF291293BA15605B78FD5516EC4339E7AC648462372D5E165F6C2DCB64A4359122EBC44C2C1FF00BF00C8467E99554BC398E9585C6CB4A887DFC9812E68EF5A7BA44162F0895A14B4A4B170C4684D40B7DAFCA2C3C69FC736336A6C76D764AD0B4FA9D4AB14B1610A090D88412A691D51C4A12635F4F6CFC39F1961F0A8C3A77C02371AAD987E15FD8E341DA9B344D1312B4A54820D161C1BB16ABB1AE7C23A61BACDBAC076FF006558C5F0FB86BF98786D0BAB60B4788DBC984AC29092482A5856A79F6AFA6BF0CB6B6CFDA1B0A4E20EE1514A5CD08AB371CB36B5737E09E20913B0D8F3200795F5329AA033B1C8B74A335A336D9BD70F34D2DC6D293C2A0490414F0E4338E63EB1CABADE1E7618A3E86049B00199FD05FA031569A908DE0E09241BD6EFF9F6D1236E14B68294482641CF9490397A7CBAD3933124FD3514B446E2012694F633E3F68F1693A491DFAFDF9D369AB510C0916B58DB8D5B8F7A088E54B2E6BDCD7D214524FBA00CE0FE9D7CE95972D3BA3786F1D4D49CBD479F3894C3CC9611BAA351976E514F0A872FD7E95BFCB47FC476873F32528DEBCC57B9F48F0156A01E9A4E9F1158F952BFE09EC232F2FF00E447323ECF154AFF00F2F851F265FF00C13DA31FE987216FA073F7A7A47A41E11A73264FAE7F1E7CFC8D44E30CF4129964849B0141C853AFA110D664A04BB528F4A060D4E3CF5EEF2A4A330510414410510414410525F346F6EB1F7F76AE9C608F098127956E7EA4D33D79C10CEE13EFB5713EE3721439FBD9081E7AD359B294C585FECDEFD3382216F3FA0CE30EA892916370E003586EDD6A503DF281DFA5466255BB2A627FDC50BF43D2364075241B150B73A5FA472A372F7D69B4DBC6DEB5F1B0368CDDDEDA072F52D06EEDD368B7529F19CCF8A0A21327F29AF9A7F1E70B8A9FB7F13B8B213BCA60E6943F7D28C23B278713393B39265A8540606BDC7B6EE23653F9433785CC58B858B8414A0149E12E04C2071E5272034823977F1C6D0C1CC93882B9877B7555AB9BF2D687ED5116057CD9450877DE04B582732696E022B76C2F1A2A53178F31C6078ADB4E292DA80038613CF5939913234322CFB276C48C3C912E83E96233F3CE9CEB1B842A784AD602CCB3F4BD59E9467FC660BC327180E366DEE5A696D907FADC32F4F33C46739D7CB2CE6AB5E23DA32F13F3371218D2D4E24B52A6BD75787A84E2490A0B395892C45079675CE8E231DE3584C3AEB76EB25B0014970FBFEA4469CB98CAB9FA702A9BF586152C34737E072EF170D9B8A526484CC724D88A695E009F6CF161BB62E5BB854E70100C426675331D065AF6D7232A0C0947D4A0EF974C9FA92FCB48B0C89A16414921C3DF81197BD0985525B500A854C4729ED9F91F2F9D2BF2CA064C3BFA0896952C901414F7BD7CC73FB410DF43F015B25612DF4B9AD6872A3FB685144A033960D416E0D685836952530400064244FAE46905CBDE53D1858396F4B7B31877ABBF1850201D483E46B2943172DC2355390C3AF28A0A903224C8D634F4A581000A026BCC0E3EED0D56EFBB964D9B7AFF0051E05A39854FA476EFE797A56E2790C1879F330D57FC8FBC8452563903EBF7F7D4F30A029D4FA7E3FBAC494921494A7302BD3DF0786EB39475FD08A67301770D5D780FEBCE1E478D34B796A6D00929FCC6321D3BE7A691396B48250A5D69535FBFB2D094D9A9942B736E9091212EA9B70F841295A94E2F242781254428F2240CBAD653B3A64D5E75209ECE40FBD435E9947CDDA6896EE199DDC76ABF38C0EC398C6DBEF430C6B016DD461D83DC2C5EBCE85062E02C40F00A642A083C53CF95593058612E504AB87F63234198B1BC57F1FB553312A4A6EC5B8532AD33BDB578DFCC330765BBA60A4250D969B0B6FF00B8A92D804C72958273C8EB5226407253FEE6F629EEA1A2878D54C9B2D4564935B59AADD80BD2FC22EB7D3C2E148C8240CBD3CFE3D6B7F94B0C1A9CC96D32310B2B045453343DF4D0DF23EF330CDC4A95319CC46B94452E994A4B39A6A1C1CF3FEA9133280400E0E6F4AE62D7E3D6251949F051A640CE7D634EFF00AD3A4495302492F9BD8E61EFDB5BC47CF46F4D2CE0EA3F35D1A22EE96912241CE08E7E9A1E5DBB8AC4C589798A3DAB6D2DF885A4A0A540105DDED4D0FEBF316FE26F22D98F19638D2B07DD466A11AFD75EFCB2150D8C9A54F50F561E879BD4F0CA25A44B24A83170DC882F6D695CAD163DE5EB0B4832532600244F2898F2922797C6A78B49528872378DEA1AA0E6FD386994BCA410AA82D421813A9FDE87AC692FB5D6309B6B5D8EC259722F716BF49B6208E1E162ED953BC4467F9721DFD6A5A5ECF9A8C1266BFD206F1BEB47A53339DAE22E1B2E7265A260291F500C4F3B3836AF1ED7D9CB6291B3D67C4485B56160544FE551F05A2634E608131CA44D57A74C0B5996DF55452F9BDEBD472AC667ACB9600825C11C6AD9674666A56977C87DBBA6987FC2B6E063842CAC0F155C442473839CFA18D4D4263F19FE1B38600936626BAB0F5883C4052D4A3BC72A3D052B5BE7179A509C3D1F8F425A9F08AF879A5294492A19408CFCA62622A5BC3A9C5EDA9D2E561D4A495AC0A920D1474A1E5F7262255226294523799E86AD7CB857EDC63E5EFDA3C6C46F5FF8945ED85EE2B6D8B2EC6E6DD6EE1D66FB6FF82A670F4AC05347F292519E998E5AD7AE767F85B6DECDF074C33004C9C4CB054B5056F9DC538DD2455B3AD8D23A6F86B66A9787960A8EF245413624D7F5C4E423B41BB6DB1699B3C2F67B09B54DAE1F66C8650852381D012809C827DDD4035E5CF14E07153F18BC3209DE2A50705EDD6BD1F37D22E6BD82B9725539442830B9A8F20039EF6AD4C677B5C4829696C32EDCDF5AC96148405FFC827FAA75809C81D469558C2F84B6A22709A12B2C527783B1AEB99B695B88A76D532F09BC4A9225A87D6972E96A3A45B8FA69101B49BD4D8FD8FB7B9736871EC159C5EE9050BC29DB96D372A1051C0D30A3C45C283A7581CB2EEBE0AF0F6DB9D3244B419C3EA43BEF80CE3B5BD961144C5E3B0B30A93BC9176B3D439E6DD48A868CE9EC4EB6F1BC4F69F15C2ADF11B7C06F956EBC351788E148238FC75003DCE1528CA4A41F7609D32FAB9F077C37B5A4786B0C95CC50225A6E540D783717E46D48F3C78BF1D286D198037F22CCCF6A9D0F2E1DFA34DBF72B7D564D16C2D9FF00954660A48900467200CC4448E46BBB60F6763E4801531AC6E69C81D5F818A42A74A24CC6249C95566D07EF3E7170DB0FE8A40293DF3826615D32E9F3AB14842D29014A7A5483FD9075FDC339877944DC7BA7BF48A94839E52272E7F2D69D5086207322BEFA43428AEF1079353957EE6F09A9B5932263A67972D07DE758750A034CAA47D8FDB8C26A94A2CA49DD15BD6F971B7B68F381CEA7E7FA8AC12B218100EA493E4C2309973011F50E4CCFE515065CFF00B01DA4FED5A7FAAEFBE1DB43F985BE5CDFF926DA9F4DD68AC36A004904FAFED434D37507A56B956DFBE7A0DC2161AA1C73FC74E3092DB5CE4091CA34F9FDF2E54B0DD23EB1BC75F67DD21CA160065024EA0DBBDFAC3BAD613828820A20828820A208299FFF0013DFFC608A57F94FA7D453A47F11D7D4C10DDF8F060F323E4AAD5740A26D422BA0AB0FEA088CBB48B8B7C4D09125766F3601E7C6C2D1CB3F4F4EF5078D6DC5EBB8AFFF0012CF96BFD46E8A282B20473D3EF1CA8DD0DE59E13BDBDEEEEFDC4A2DF11B7BCC3DCB79012A712FA9CB85708D4FBAAD3FC47CF8F8D5289DAF8A2C1DD437855A86E74B3DF9D5E3AF787676EE0E4AB7C2420170F7E0D9FE6F48D9FB860F8E70F6D6129414124640C00A39F3333023ACE75E2BF10A77710B0E5B7A9A71E8DC6EEF16613F7C024558DF3F3152CD5E54115DEAC2565214141294891D426398D41CA399A819001994766CC039676D21C61C28252E0877B86A0A0FB7BBC03EEE7CBD3C865D796BA79CD36C7C8242980AB3B7953B0D29D21F4B99B94670E3B67EBA18B5F1148515AB2931A73119F7190F5F9D454A4196189001B83F6D6BFD44EE08EF252470BE57B83CC748C7F89B79AA67231979E7D7282477CF9450A5B549059D865D3F35C9E2D582965C51EDA3369E62FD2AF10215C038721CF3D73F514D262C176CDBC9AFDA2C9291F487A0F3E0DD83BC7BE2F74FDFAFD29AAD443005B3FEFDFDA139D2CD58B92DEA3200E86154BC024684E73198D7CC7D4FA51F30015F2B7AC611299357A7DCFE72FDB2A1D498EFE5FBD67E624D8BF01EDBCE02821CD0B778A090492343FB50169363D7286A45C5473A18F2B1F3124EAD9D0B79BC325214E49CF32EFE9053C97FFBB3D3FF00C8C3E904248245DEDD7DF48A1424A472CE7E54CE665D7ED0F45B2E968AADB1145ADF3768B489BC0BE124681A4C9CE39FAE47B56924172055FD06776FC5DDA23B184298B91B8ECD6CBBDDF3AF9E2FDEAED03F68DE178261DC49C476A9C5B36A10616916EE252EC419CD249C8491153F8697BC037F2B8E44E7F76F3CAAF8D55C062C1CBD45BB0F75148D98DCF6C261BB2781DB317ECB6AC64341DB979491E2294FFF005132A2388C255913A659F3A9995242432DE80114CEF6BE74ADDB8C5231F8A593FE92D3BA4B1292F66703B7AF33911A65E17EE3A82434954889394738E63C84F5D2B64A4A560D48EE0303964F0899E160214A0C457B5DD87BA50DA57C5F18970EA7231D801FA67DE69625CBFA70A46A1625A025352E74A76FC7482B216406A7BEB07CF660C4BBD5BD6B0A17B81A827A83DBA4651A7C7CE905E328500B3676E2D99BF3CA3225A96A7E447137AFAF017881BBB9009EA0664F7FA93DB4A6D327EF87D6E33A65C07AE50FE46195BD7714ED5F77F4316A5D5DF8CEDC34B3EE3404011C24913D73FD35CB3A63392A99517ADCD00C8367E5CE26E4481402E68E34177A587B61164A8B2EADE79F70356ECC9E251E1481AE73CA44E83A8EB4C7FC3330871987CB3A1E397DF211232A45992546C031A353DD7D639EBBD67D7BD2F686D8ED99C39E4DC613B26F5D3976E36AE26D25E652EA388891F99394F7E75318A5093B30CB269BA7D9CA83A71BB58F0D861F29D41880D6A662E4E678F2D63720E265F09C1DA02586DA68919710690903DEE7F96464749AA061C0998A2D72A24127BD85F2ABD68F0BAB084A416372D471C0B1B0D7FB89862CDD5A5B6C2C84AC852C4C0FE99E2D07FF0058F5D4532DB98054D4D03DADCE9906EE486B58C309D8437200A97A53B37AF36A4618F6AFDFD617B8CDCC6D1EDA5E5E21ABA187BD6F66CADC016A71C42ED814A4C12429409E1E7DEBA97C27D80A5E330EADD72E0B0150C7D915A986C30DF5292A0404B17670496B393668F92CF61ADACC5778DEDABB61B778FDCE1AE5C5DDE5C3DF8ABA5137696DCB77FC3971449108238794089022BDA7E295FF0087E0ED9F8647CEDE5CB9817BDFC28437CBCCD039E56BC593646397855A92E404B3659676E22DE71DC63BEDD9BDDA63785DA5B3D8A6D1ED0E2AF3E8B4C3B0F28BB0B712AE14B686810A3F98447EE2BCD5B3FC21336C6D641F96565732859DDF8FDAA6BCE2D98AF10FCBC210A5D02490E4B0605DEB90AD5C0B3E51BB7B0DB01ED2DBEAC3ACDCB2B3B0DDC6177A125C7F1B6EEB0AC7576EB208532A48292B2D994F2823BD7A63C3FF0003A66270B295330CC5490A7523AE61F87615A479EFC5FE33960CE32A689894A98896A06A49F537E2D6A08DE0DD77B0D6EE36510DE23B6C85EDCED428216F5D6D986B11B7F189926C94E242F873FEEE5C23CBBBF817E0A4AC362251561D0374B90A486A31D3A6768E398AF16CD52D43E6292836282CB15A3B71D33D408DE9D8ED91D9ED8FC391618261587616BE1E1FC3D830965A427904A52343EB9D7AD761EC846C6C1A30B2C04A4240205A8CCD4B0FC52299B5315FE5E21530A8A80620A8FD5C4E557A1034AE917531861656E3A552E3BA9CC9D343CF29FF007532E3511191276AC96194B64C90499F333400C19DF89821C5660828820A20828820A20828820A20828820A20828820A208299FF00F13DFF00C608A57F94FA7D453A47F11D7D4C10D5F696E363848100CCF998F9C7F8AC2E893EFDEB0432B5656D25E0EA924B808CB311075E472311E95078C1F4A8FF00E25FB1B7711BA54032732A04770FE91C96DFFE0EFEE7FDA7B01DE7BEA4DB6CEED638F358938825202D8B616F6FE31C91FF0022870CC939011957883E2FEC75CFDA1889A949DD724122E19CB71CEEFD63A3F87E624E1D290A04A5810E433D2CF99D286E7439AF13DAE690966F6D1C172E3C8438A6D83C6E04BC9050A201C804AA5463313A45786FC5D81323133090D53C29506F9B7957845FB0528CD6A64F517BBB6B4391EB4312D698BB6BB76CBCE78AE11C4A5A0F124CE704F54E87A10455264A82166A58DDED4A6BA1A166BEA5AC12F04B290A20D03B35BA70E459F9452E3E8733492274931965E5E5DF9E959C4CD4A839209019870E1C58E56E158D178662000CC6BAE64FE053B3C46DE2D01044891A9FA77AAFCC50249A804D2F6E96D5B9DE25F674B526EE4351EA471D453D78463EC56E5B0B5403AAB2006599E874CF974CF4A66B5BB8D7434CBCE8C7D88BAE0124848CDBB706777E9D9E2D371E0A515007BCE5A08EFD3F51AD3598B2976C98E8F6BFE338B0A65D057CBDF4BC781C49CC4C7A7EF4D973BEA05A87F593FDFD6135A0BB38A7DF8F6CA2A0F84E59769D7EA2B099848CB3BDEE6F58DD082C069ABD5EB483F129E7A7689FA9AC85105F5B8C8C6AB946FAF6F4A43943E8E111244EBD0796BCF4D7E228DF21C814BB54F6E6619CC940925883981D1B23C7FA8582B8A72D22B50A20867AF0A7584552D2A0D6EE59B3F7D697A4BA90A2933232F3A7D256A32C9B31BB90CC7DF484012956E0C9EAF5D7AF68590952F4103A9D3E5349AFF91E9E82174CC648FA8F427DE70DAE2DD01E6545A5AAE42FFA0E04CA120C05C9D47126440D29E61653A8646C0581777A59C5002C6ADC218E296774800126FC1DDA9F739906315ED8DBB877BDBBDBF7F0DBCB8C2F0372EC2D2D34572BB96D2949483EE901C92A3D3A9AB6E0F0C9012C32CF3C83EB91E19D22A58D9AC561C824170FA8B59AD4195728DEC43F6649716871370A6580A00001292DA7802A73900E731CC015349C2950752686D72D6E05BFB0E050D0312A4A17BA8AA5C977A5DCD8000BBF1AD9A1D7E2AD30EB72B79F6DD53D9210D2829633FEE1946B947CB2A49586A12D5D1980CAED4F2E1942682564862199C91F4D43D0C37174CB5EE292B4EAA055119FBD999E9E5E54CD69081BBBB9D0D39E5E94CF8C3C4CA5101ADA9D3B01F98A17895B2464B4ACFF00D5264FD3FDD24A2C0D5A85A1CA70EADDFE2E722D7AD5E8FEEB11CE62D6EB511C7C2AFF00A28C1196597CF49E7CAA1A7A8FCC56E96395487FCD3311272708B094967A685EE323CAC6910189620A6415FE1DF753AF1368919F33DB4131972CF5D10951D4826A732D5B86E54C9F4893912536DE4EF13FC49FAB27719EBA3748B22E71A4B2E29E55B5CBA2EA652DA24B013A97C4FBA2093DC024C53996904A5F3C856D77F22F1332F0C58170929AFD428AE01AE72FEE347BDA7BDA2B05D99B17B617642E5DC576BB14429969AC2D697BF04EAB206EC3678D0005C9C8C70ABA5384A10087506704B102859DBA44BE1F0EA5201DD6A5998E41F969AE9AE2BF65CD92DAED986714C6B6E6E2DAFB6AF1A71A798BA654B7434D15A95C2E2DCF7D2B0CAC2607F703CB2A8EF10CE929C3CC4E1BE67CB0004EFDC16FA9DAD5B3338E158B361B0FFE8A42B74BFF002045D886CB2E7EB1BCED5A06169BD1FF0022932B3A12633F9F3CB21D32AA16CD56F62DDDDCB8CCF16CF874348D9694B948CA8D91D1AEDA8F289CB472E9C4ADD688525F292C273E24041FEA8580722A12131AC8D79DBA7E193325870093BAC746350EF5A3B74AC46E211BAA2EC0203A9EC7787D246AC4579B8B3C7CF67F197DA3DE4E2988609B2F82E078FB9B16DB776E62AF5BDBBC6D4786DA5D4A9653FD3E10E26655D2626BD15F06F64E156B54D24A674BDCF928240DE2AFE54B939BB539C35972945082B295124B949A370EF6C8F111C3BF62BDFBEC56E9F7DB8BE33B4ECBB74C5E38DB4E2D80DAD2C061A5B4E0794B50093A83DC1ED3E93F15EC3C462F64E0E59412890956E8DD3FEF634147AFAEA61E61B08F34AD2D5ABE82C1E9DB4D1E3B84E6F77723B578BEEEF7B1B15895A3AE6CE623E2E2B62875855C137172CA130DB64E498515711194D33F875E0E48DAF2BE74820A56090A48D5C30B39E19B35210DB52CFF0089312E2A8527E922C4350D0BD69561CE3EBAF70DB7DB3BBD5DD7ECB6D8E149B276DEF70E61B6CAF855C0AB765B655C1C2602814E647388E95EFED93B1B052364CA5AA523784B00D038602D6637BDDB998F21F8A70937098DC44942E7195BE548517624B921474766190193C671B1B1612F2D2F22E2E9700B6ABA85B2D889FE9481034F38E74EF038CC1E1E794206E92CCCC18E6DCF955ED1CFF7267CC2A25543406DD0519B5FB44FB16A8528DC84F0B8AC80E402728E67B0CFE5562F9A99B5497196B5BF9E94EF1BA8104BDFDF285822E94A2A2A401C86632CE86CF4FBC6B0ED1C7C23C4E1E2E7C3A7CE8822AA20828820A20828820A20828820A20828820A20828820A2082738CF499E5FEE993FFA963DB837EF95608A57F94FA7D453B47F11D7D4C1142085028E9FBCFD7F5A260FA6B627DF2BDFA406BFA888C52E45937E202233EC3213CBEF5F481C6D88176367AB81FB1F6AC640048700D45F9C73BBDB4ED2D76F361312B25A02AE70961DBBB479A00BCD3AC82FB6904E69E371091035903BD79EFE20EC438944E9A52080959A8B9A8BEBD2DE7D23C37210501690EA5338B545DB3B3BF5E11CF0F65CDF33BBC0D8E7303BFC4D08DE661576F5A5DE0B70E91722D98BB5B2C28B0545DCED11C7310419D32AF9FF00F10F667CA9F3CEED5D54B70007DB3716B4762D8D854B254BFA521AAAB559AFA9B10E46A1A37AEDF13FC234DDBA894A9284F10320F1912A93D02A63E51A57009D30C85900589BDC70E8ECC43C5EE56CA0A961696622FA3B56F63DAA4C3F6F1B03FBB9EB3FB18E93A475A88C663C00CFFCAF534EE78548C9D9E911989D9E12545B30F6737E163C352D0CEEB1A4F1292173DE40F3E47BC6BF4A8F4CEF9A1C1770F7C8FBCFCE34C3CADD56EF2D72B657D0708B6EEEE7C624E5FAEB98F4F4E9A655A2945D81A70378B460259041160CF6FB50535AB3E7588570FBC40D01E53D8E7D629ACD986EE082FAB9E7C88EC45A2793603DE7F77FEE2A49040D3CBA5335ACB105DDE872CBED90A40A43D6C72391841C71295904E7974E9E63CAB644D094D5C9A75A9D7BFA438972FE9059DF5E19D6AC7AC51E2A3AFD3F7A0CD0C18ADF3ADBFB8C2E580E2E74BF937BE50FD820B608D0FAF4FBED419D57AF26A767AFAC32584B97EE687BF38916F9FA7EB58F9B5BAB3AE96D3DD28346AB4328B1E795C70F385916FE2282A241E71D32D63B659E5CEA4E4A8FCB0F6604F1D399D34615AD2227ACA66001F7AA4E8FE5EED12ECDB42047088D35FD8C759EFDAB604296F91D796919F9A1850726A8F3E5CFA43830DADA538DFB88564B23212759D6331FA8EB378196EA4B338F322F9E9C75CCC30C42C1DE2145D8167E1D6E1FAEB688DDE46CCE358A6CE9C5B654B4AC52D9A2B67F371F191970F067A8E46AF78291BC90401950799CB872BC5431B38296524907EAAD82AF50D7CDFF004D1687B3EEF2AEB11BCBBD97DE45EAF0FDA4B05F8776EDD385AB65A5454A60254EFBE47860033A9F4A9A4E1C10067AB301C1F83EADC338A96310A415AE5A4AC82084A43EF7D81E2236BAFC60CA6DB6ED1DB7BF4C8297ED141D20CCCF109D3B1FA5359F204B191E4C417B64DA9EA2F785306954E482A96B96CEE169637A900FA7586D70E36C8287997D694A07BEA124822609CE6328F86794C362250756F05240B1B71A5B2BE8EEFA4C61E46F91F2D52DC64554E1974CF4A345A78862D60C13E030F29CCFFB5249F841CFBC729E42A2672909A872D42FABB06E1C866F13987D9D38B29625EE8018241721858E8796BD2CF771F75DB85F8B6E80CC8CDB49FC5360092A76623ACF20338A40E18AD214452E08AE6F7AE7601F311292F03BAEADE50B50FF001391CDC83634F26318E76BF7B3B2DB2695AEE76C30D5BADE6AC1CDF2157EA3FF00F8D2C1CCAB4CBB839D6ABC3942410A1C52FEC53F1CE1DE170D28CC2932085021E62922B4A6E9CDBC9818D42DB3DFFED66F2EFAF365761AC6EF66F0F30DDCE2D7AD2ED6F2E90B0655873CD9217971054820020999CDB297B82A1AC090EEC5BFBD72A0113F87C1209AB2C38A1A80C459F8DF5F4B4367B7236585DDA717BC69FC6B14795E2DC6217094DC62EDB84F1152DC202928049009FEC1234A6EAC60466E32B3DABA9A1E1CC5DA611874A52280301A07D1A9973EB9C6CDECCE002D50C3885A5E48193A832328F74AB4949C95AC28543ED99BBF835281350DF8772C7B985C2D2964B860EE721A71EED1950A816020EA040FA4F2F38EDDEA9FB266286281BB28DCD454737ADDF8EB0D96B01C8AB8C83935E2DC2BF731459BB76A6DCB603F0ECB6A4C5C0949826550AE51A65196B15799939909FA98060EE003D79387EBC6184E5209DF512A77649AB90294A694BF3CE354BDB797816CFEE17783B4589E1D85E35F87C21C16CF620D26E0A16B6968570A9511EF473E5E95E8CF83B881FE66180A82A4872F67F66BF686A89DBC80427E58ABA2C29C2F6A9CCBC7E7F8AC6AD1EC4F69B1A699B7C314FE2B7B9211E0B251F8C7920339E7EECC8313957BE676C74E236326629D6528428331624034CEF4B5380A43A91B4A54A3BA4849CEC32E0C18937FB18CA1B078EED65FB89D9DD85B8C7D6BB94A9C5358629654E2DB05D48692DC924A802246B9F4A6FE1190946D64A9406F6FA5FA503FA35F94436DDDAF2BFC7584B541B1A73AE7ADAE35A7DC9FF00ADBEDEEE33B8CB0D89DE760BB45636D80A9E4E1F79B40C3EDBEF876E5C59E35BB214042424A63223AD7A802D6BD98128A3A0333F2E9E4794798BC61B411326CD015F5025CBB8EBC03F4BF3FA3AE1B90095A9B4A523DCE1273026049D328F2E5CE6A387C1E326E306EEF1651AF992E0706E79E714594A41BA779F2D3AFEAD5E5258738B72D92A7014AA4E4441D48CFE15D0F052E64B94913410B6ABBEBC7AC37C5A5299CA092E29D283F70FA9EC35828820A20828820A20828820A20828820A20828820A20828820A2084CAC82440807BFDFCBE349264952DF4B9CAD953D9E461354D4A5A84FAF4E5D22A90A919FDFC694002433DB33190B72CCD0D5B205C3A24C2635EE272F3A4674E64B641CBF5EDCB90B429761FD9FCC5ABB605430B79F4E41B4924692049CBEFAF3D61F1002D254E33E341CB4F5BDE8A22592450BB8B57BD3EF1CEDDEE5EBB77846D23B6D2E855A3C5E6DDCC02D34B29E103FB721C4491974CEB8F78C76A61F766E14A7EA00A5D403BEBEEC63AF7857045587429EA5AEEFA51C69C8691F3C9B1382EF176237B1B5DED03B349B9B809C4102E70BB1F11568A61A7576CE16D94C7BC1BE252A4FE6D6BC61E3FF000C2B68AA72E4AF7492A2082CF5E0E0F91CB9F6ED838340094CC01480CE15504BD3414636CF8C759F76BBFDD97DE66048C5EDEF9BB5C4DB4368BCC22E1C422F9A7A78172C0515005614AE7EE8122457963C43E119D83F9AA54D1F4924806B716B67714E0D48BFCA969420237286C52030622EF67A65967966BB0BF37C62D945D4A512A5A33427DD98528686328EBDB3AE2BB64CEC32D49DD2589A81C59B2A8BB67E51198E9297A86166199B1CF26F748A54F38B5A97242742093323DDD3BC1D33D33A4B03895995549078821C1BBBFA8E1C618CAD9E662B7D2C00A97762723CDAF5F48A937FC1F99975644E89D667CA7BFD73152482A591603B5C53DFAD22670F8732CEE82EFF006DEB30E3A08F42FC585A5B5A02B92844465E9DBAF2CA96183F98C4A921C9600B538E7F8E01E24501207D44150CB5E747CF4A1A9BC29C4842415109EC624EBE53DA951B18ACB99A91A024E94D05C545E8748092737F4E828DDA239E5A54EAA0C8E4797E9CF2E79D466270870E482A496D0BF7E2C7979C6C9C4EE108524B3163AB0E7AE659EB68F024AB3047DFDFDE751AB9A11A77A77F5FBC6DF337FEA0925F874E3A44B5A7FC694F3060FC7E3F4AD133F7D411BADAE473B1ECDCE8D9339EAFE4A6140ECDCAFA9F7AC4FDBD9B8E890A4671A98F3D7E35272B0A66241DE009C9C3679F6D6F58899D8E4A09705C8B916C867CB56CDE24D9B752141A50E229FEE198D0739F8FC0F3A723FD3FA0924E82C5B4B3FBCDE22E6CF4CC5EFB64398A7DFDBC4DB164E2C26074EDF1D79E87A9F83B9127E62812EC0E4FE6D97A437998842695D5EC73B71A44EB5847E2994B6F04F87A029FCD139E664663EE6ADBB3F0CC52EED537771C05F3047A8887C462D0EADD249346366E0D973CF4CA5B0FC25FB058432F2CDBA89E26D6A24C7602AE5833F2C00C28D931A67C7AF18839F342CA8AB76954DA8E00F32D66A8886DABDCF6C9ED9B4FBEE34BC2311B8482EE278725B62F5C291014E3B1C4AE180019D32E74F95B424CB05252E450167EE4DF4E0CE620A64DDC5804037DE0CD7B1B79E8D7731AFD8BEEEB7A7BB8E0FF00F02DA36F1465B595706D25D3CF4A78A4001B006432F9654CA66325CC2490CF9022957CF8FBCE1F499B2D49092CE4977E3A96D1F3D2CF0C93BC3F6810FA8E3183E0570C242415E1EC5CAD0B84804A4930731E951B3D6A9B41D2ED4356E9A6B5D626B048C3211BA120977DE663772C7ADAB4D22C4DB4DE3EF70B0B182ECF30D5C807DE7ED5E08E239CFBB2489988CA39D464CC395134B9C9DB5D072A7E62CB2264B003173CF875A575A4609BDC3FDA2B6F1A8C5F17B4D9AB57894A9CC11EBAB4C40A78A21C2A904C6424E4093AEB90B4C90CAE9DAB9B1A534787416822961951EFA7BD625365BD9C7F0D709BCDA0BBB8DA0BB510A55E62AB17373275295AC4CE7F28E8698E227CBB0FB70360DA5AAFA98732E720067D19D9FB0F76D699FB08DDE6138516D2CD9B4A2D8050EB8DA7C46CE521063204E59C6550F8898E5F4D73ED5341EEB12B271728252D7CC585697B3FBD62F746CC593A80A4ADDB77844AD82105E11925C3FDC00CBA807A45442D678BE4F6F51FBA1D0C3B5E3DE8908296FA8915D2963A69DE1FB762CDB302DD2CB4C944C2191C2DC927DE8EA7F32BA9EF4DF14AFF00230EB9207D6CCD9307C81EBC223D58E44B5EE83BC2EE6A4B9B7E05B5E292587418253C33966491FEF2E5FBD5691255B3E6FCE58700BBD09E5DF40FCE1413153599DCF1605F9B59BFAB4561DB8B45A96521FB55A7FA8D89516C9109244C244E797298CE9F61F6B1DA1351874214E54002DC6E3D96CE80422B94A2E09AE47DD072D0D59E386DFC4F76F36B37A5896CEFB2DEEDF137862FB4EEBF6F8E3985BCE78762CF1377091745A254D9532A504050FCDDB2AF6E7C06F076D09F3F0B8C4A52A09295044D7293CC58B33F2E05CC5E217B8E0A9DBEDAD1DF2A519E30C7B3C7F02DDCDECCBB61B4BBCFDA6DA8C79C7FC1BC7F0655DDBDD61E5E570BAE2576EEB67DC5384C89CC124E75EF79C572B00304B4A65CE284A775144D0370AF5376D229F8EDA0B913944294D56AD752D4E36CEEE5A3B3BBA7F635F65CD91C53086F03DD2ECA5B5C58F036D5E0C12CD172E848482A79C48F79440CF2CE67AC34F0FEC49F2F1E99EACD4EE4EB9171CB4B1AC53F6CEDB2A92A00AAC4104FE38971A67668ED0EEBF63F65F66F00B5B0D99D9DC1F03B4286FC3FE5D6A8B67084C157104E473F5835E88D9C52AC2225101F75A9996CFD4EB4B51F8A6D913311326CC0A356706C2AE19F8B8CF8465F72D564A0F88B2129FCA1592A00FCD3A904476FACB6130B2652B7CA06F5C1233D1C7B073886C295214525CB6649D2CDEFCA246C82C329E3E1933F97439EB9E7D7A5389C5256775F893C87BFBE9B4F52553094E801ED0F2928460A20828820A20828820A20828820A20828820A20828820A20828821056A7CCFD694979F4FBC3399975FB4548D4F97EA2915FF13D3D442C8FE43AFA1847861D7951AC69AE5D7F4A633BFDD425DB27A37EA16171971D22D9DB04716097794C20E5E87E3E54CA60FA59A8CAB0D787B787B21492A507AFD239D5E9E75CAFA472EB7B6BBE385ED5B587AC2568C3AFFC4CD420AAD9EE09033C8C46933A19AE35E35D94162762022A012EC3425FA51A3B078627844896934219A9EFC99AB1CC8F676DA96362771B8E63BB5364C62BC18BDE5A5F5B38DF8CE94DEE2EFDB347857D0382267B682BC51F11B6EE23662E7A5256129DE176D6B43D7A5C10F1D8B63E24290900B12DC496E1AD3D6CF0E778DB8CC1300C291BC4D86DA156C762375E15CDC5AE27749B1C3AE9774525A43086C4AF3720A4CFBC40D4D795F69788317B4F12A940AD414A20DCDDED56D795ED176978BDD4B29C8206EB64DABB172386958C6569ED8988EE871CC3776BBC9C3F16B5771542B87692C9A28B171B6DB0E871376EAB3494119E9D349A9BD8FF000E311E2097F35525DEBBA524294EF402C7CFEF11B8BC4826F40ED63CCB0D5E835E51B3FB31ED35BA5C4F0AB6759DE560092EF11F0B10C559178933987532633C93CB21DEB5C7FC1FC7E16614CB90A005BE9200A3E94E361A18464ED34246EEF3330A1153F67AD5BA5232059EF9362EFC8559EDAE07700E858C41B50D01E44E4476CFE134EDA3E01DAB8376953A8F6490E43816FEBBC48C8DA2852AA439156F215FDB9D1AB78611B4985E2EB439678CBF76E3874B57D2B615063DC00C9D33E53CCD50B696CDDB382DE644EFA49228A661CAE683AB718939535332C5ECC4D0FE7F65B38BC6E6CDE5301C7AE2E186C8FCEEAB875EA488FAE5F1AA4E2B696DB90B2DF3C373671A0ADF5A01D2AF658429802951B109A90E730DF6B68F0CEDDE436DA52DBFF8842491E2F105CE706543A69A11232AC61F6963A78FF5FE6151615243EAE3CF3F485BFC32A62D4C81E37F2CC919DA245BBAEE4E9CE09F5EB0465D674A9EC2A04D00AE845F79A94CC1737E40E9AB84E10243333D8E5F625FD4F794B5B900A3B4FC01FB8FAE469DCC952A5A77814BD2BA7B6B0A528D688EC561D92A2D4670DFBAF0F4BC5E36174084EBDFD7EFAE91D05444EDA8B904849342C188D3F54AE7567AD3F1D288DE167E67F75356191AD691775921B79285989333A671CBEFA73CEA5B073D7894256A241CCD8F3AF4BF9443952852C479FBD738BB6C996C464339EFDB3FAEBD39558F06A4A4D4D465626B4ABBE9F9CA22B153164DCB0A96E56ADCD7D22E4610D04241E181F18D403E67D0FA656BC1CE09DDBDBB3FE69CB8C424D52C28FF003FAADC3BDAFAFAD651A4B320C8111AE8341A8D3F69E756191884EE9750B52CEF9BB1B574E10C56A5870778B7FB8DEAC6F415B5DBBC392B4B44919B640D73072198ED9FF98A8FC56206FBBD0DD9AB4D7AD75A50445CD2A54C04B5097E595EAF5AFB30C2EACAD710052BE132208CBB46BF0133CFA014DD3880A7751072AF4D791BEBC21CC85949FAADC457DF4AD9D9E229DC26D6DDA36E8F0804CE47501464E5DC9903ECE4CF2186F31ADC9EBE599EF4898C3E24029290ABE55CF4FBF18B2F11D9DB77D4726733DA3BEB1ACFF9CE813C1A953E95D1F537D183DD844D49C45C8DECB831D73D2B9768861B3987B29085B6D29C4CCC0067B826397A10353A963397BEAF7DBA655A5A1F2318C0024B97AFB6A37EA1B39845B2092DB423B247307EF99CB28A6335EA2A79E97CAD5CB4AB34394625D4050BEB56E373DA1839837192EA5B0907310348EA0FEC7E951F312E906A497A135D0E55E5487D2F12919E54073E601CBDBC47396FE04C1397FDA728F5CC69CBD3234CD5289C800E5AEF77CC77870310F7722C5BCF33DA235D471B8489F41F03FBF79A48A04A49530E3A9F21D6374C833485901813C9C9662C1EBEEA4C51E17FF6EF97DC5203069DA0B1299CA8814142E6D636CF31CDDA464832C0A800543D2ADED87DAF83B7FF00BD5C3774BBBAC7B1CB87026FD4CA6D70EB30522EAFEEAEC9B767F0ADC85381A75C429C23348CF235D93C05F0A4E3B112270C3B82524326CC41AFBF3610DB178C4A105EE1D99FFA1F637223497D93F702E5AE258A6F877ACDAB13DE06DCBFF8CB87AE41791B34C30B51C3D36EA7878B686EED56DA5609FEA1194F3FA23F0C7C2C3C3F8792A52370212059AC2971426FEE951C76D015FA99DFB54D39C74556D2BF0EC052022324A522070A7241CCC6691396B3975AE9B8D299D8B0B4DB53A5AEFAEAF9DF3A76D09E263A81241A35C9C9DAFE77AB9CEECD8E6BFF00E6ECE468E0D27A8CB2E79FCC9CEAD3B2100292482F4AD0E9735D08E3D4C50F6AAC90A25D8851F7D2F4A9B523A5FB12230CB11C837A8CF90CBE1F1F4AE95B3EC19C30CE85EBE9AC51316B652C3D1ADAF21958916BC64958800F248F5FBFBF2B0A1B74019522292A1BCFA1A8E632852D7FE14FAFD6933736E96E9082FF0091E9E821C56235828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE863D52638CC0CE3CF2EB4CA6921EB666E0ED0B45B1B440DD61D7368810B75042547F28273127E1CE99CC202483983E4CF0E2424858551A94ABD639E5B7FB2EE5AE2D8E5AE22522CDF4F8772A689CD0F20A722A81A28820CF58D6A87E244A67E1E6CA672A0459FA51F3D2F5238F43D858AF96948DE619134CEDFB23CA3827ED7B816F1B703B67865DECC5AAF1ADCE63B89B3738A58D925DB8BA67C1B969D256DA21848F1D4A32AE93135E40F1F7C3CC46D9993B76593BE4D4268D5CF4EB7E21E3ABEC6C76E9402A3955CD6FC38BFEAD6D7B69FB55619B63B05B0581EEE302C7717C6DF5E181EC2F0BB64BE2D976CF5A150BA65A3C48E20954C89C89E55C9367FC12C4271816BC3D029C9DDAE76A5B2E758BCA71DF403BC59867C087F3F2A868DA1D97DC15EEFAB0CD99DE76F4367DA699B2B0B3186E0AF5A94AC45B32CBE9BD61E04428A791191322BD25E0DF87B87D9E895F3248FA4016AF1CB8B7F548DC563F75249512E0D9B8919BF71C5818C9B8B7B296E5F1B2BBB1B178260EFAD08416F09B0B761A4290908E3402990E28895AB9A89922BA54EF046C89E9DE992251240A1482C4B5DE9E561C43D7266D35A6690925B30D46B57DD39C623C6FD88B622ECACE1BB47B4F8324CC270DBB6984A7A00026321EBD339AA5ED7F865B271214061E4D41B203D7855DFDE913184DA0490E4D6FD18F43AF78C4989FB136F1709BB7AE7767BEADB5C3EED9016C338FED03AD614A58121280CA41827256999EE2B926DBF82DB3F129294E1651A963B81F3BD2A38D7C8BDB3058F620EF03931CDC67D2D50DD22DE6F799ED7FECF771C1BC7C393BC6D9DB7242AE7056AFB15716D27995BC420A881993D0F399E5FB4BFE9EF0F396B50C2A2D40101ADA6EBBD0B70B459B0D8A964B8201615058D879DFB50B5636DB735ED6FBBEDEB5BB0C3C95EC863A6517382E301BB1B86169240058E22A495C710CB30418AE29E27F8313365CD98518764A49A25059874ABBBF37E0D60C2CF46EA4156FB13FC8826B9BBBBFE9E3692C71766F57C2CF8859569723FE050D4292B920883D79FA8E11E22D9188D8AA9837149092C0976001ABD9F5AF9801DF2A64B525C0045C01573DBCB2A6B5996F14B761E0CF18700221C410A6D5397BA474D3B9D473AE74BDB334CEF92545AD7FB3DDF952D686388489B294424A5C588EBD2AFA54D327BE30ABD6DEE11C611A415981F1CB9EBCF2CF5A9FD9FB317B4589058FD5514399E2E48B53F351C7E15552524EACEE6F61C2FA3B6822F9B47168E101E41E8127AF31F2CC48F2E73E30A7027E530200C8D2B5D3F37D1A2AF3E490B2C9525EAC47BE1EC345D56778E048F789D34267F5D3B4C65E54F30F34EF3B86A3DA94E957074D2D11B3A4B92E90C5AEEDA65ADB43CDE25D1882A47BC124E441CA23D7591AF79ED53D87C504DCF177FDBF0639758879F214092C487C85B43C3F1E724DDEAD4212B132273F2CC73F3CA338A94958C02E68D9E8C0E9E54600C464C96A3BCC09CB80A6B4E1971B44AAF106CDAA5A85174482A0070FA199F3CF5E8669ACEC63AC8717CECDD48BEBC4F3860708B528A98805D8313D5C0F2FB4465BDCDC34E95A9529998075F4E5F2A47FCCD19C35496EDECB768593875020949A7FE26BCE9FD4387EF90E38A570E662720740074FAFCA8FF2CD5CD7A7A5CF06E7587D26514A47D2435836AEEF4E3C3B34352FB2AD5B9F41F3F8655918C04583E7FA76F46CA1D252B702A3913E4DE7C2211F682EE56BE121063DD034CB9448F43D474A513337C02146B93FB7F487282ACC1E7CB81FB6799BC2CDAAC513E234E11CE123303CC83F5D73E95BFD2D577CD9ADF9FEF846CA3382BE921F8BD2DCEED71F8641E530EF1065B2949D0A840F5EBAF98AD7E48517B067EA74BF11C98B6AF6419C024AC826B6726E496F2ED945A18A5A49E3F11B4E44813CCF58CC72E9D6B070C9AD3CF37D1B23AF0AE920998B7018876EBC98D47166BF216AB64ADE79A8E14B31C4F1C9A3C59A615CCFEB505B424CCAA520B0D38B66D9E9956D13D879A99720155D87D39E76F77EF1686DAEDBE05B01805EED1ED2DC270FC3ECDB538953EB4B46E826470DB9564B512008EA40A9FF0006EC79F8AC7C92A42F777C646B517FDF0E2219E231E84950DF7DD150F6719F6AE9A8CF99780BBB4BED81BF2B0DAF7AD9DB6DD2EC7DC3BFFE3F8462485A138AF8882DDCBB88319B0F165F6FC5B4524E47849AFA4DF09FC3587978590A99280FA126A90F4029E85B2F28AA63F6928957D74AD03FEC6BA1CDEF1D14B6C26D10B7B05C3385AC3184B097DFBD01372F78094942429320A1A52785B06084848CF5AEDFB4D48C048DD943758300037B033F5CA2AD89C5AA6A8BABB1E7D746E05E913CFB8D396AD3AC92B687B80EA4F8709398E597EC2B5D91BD8A4852C0E04DCD79B53F0E2A223D73094A9E8189B9F6FD9FAC5F3BBEC31FC4715B6798294A50B1C5C5209CC1E5AE433D4E626BA36CAC391BA7938E0F677E40DABC6299B594EA5358D40AD181E1EC115B08E92EC8D83ACE1966B52870844473919139FDF99ABDE0E584A4166E038801AEC6D4D2DC2287895A4A94337A12ECCF97AD59B8C5F0A525488FEE20CF4D7CFE952454539D2AE333A74D7D888D0A2093AE4D4F7EF575ADC10D007A9D3CEB20B807580972E7385AB318828820A20828820A20828820A20828820A20828820A20828820A208415A9F33F5A525E7D3EF0CE665D7ED152353E5FA8A457FC4F4F510B23F90EBE862971D482519CFC3F63EB4C66FF00BA9A7DABEF585D201501AD7A0BC473F6A5E049E9CF33F7F4F432CE6074B9205C578C3A42802C680B5B87BBEB1AEBBD3D8543E9BEBF21C7137A905411986BC311247298D67F4AAB63702B9B38923E9341D8DE97E97A50B189AC0E33717BA19810D4E5A3BD4D7F348D16DA5D90C1F16B6BBD9FDA2C16C31CC31055EEDDDBA6E5C4024A8F0858E1064444E446424547AB64E15559A849A33103D68C7EDD0C74DD8D8B2A4A54E7A1E77007DAE6312ECE6E8F74183624F5CE1BBBAC35772957126F2E30B6086D59E6870094F0E83908D795339FB3B65C9FA932D00B6807F4E7C9B48BC4AC613280DE34B826C3977CB5B464271F7025586E1E52A62021BB56B3619198090819240CB4D48911A88F5AA44B27E5002E404B060D60DCB534AD5DC4663316A7FE4C2AC41B5E9CF216111CAC39FB64969F480E0FCC120C0E2322273D0E63581E555BC66D0C50584A0AC26AF520355BBD7CC4478529642AA756CEDF7CEBC6E5A21FB6F7A232CFD3E47D3A7C61B2319895FF0032B2FCEE6F4E27A7189492B54B00B9CEF7716EB51E9AC4270076E96CDD24861A23C328D64E66493D73F29E722B6F98A5B15A49702E0DA9CE822670B8FDCFF71F3670CC2D473EAF156321BBCB33875CD9E1D7387A870A85CA389CE1E73CBAE67D295DC94B4D51C983BBE5D470E71352B6CEE007798F0E81A97CAC5F9C68B6FBBD92361B6FD6BC4F64F13BFD92DAA92EB177B36F3763FD64C293F8F5A015F04800091913A646A8FE23F0DE13684B984CB495149674826D6B711C6F13185DBF91517CB30CD5D0F1B75AB4604C037DFBE5F664BE636237A9855F6D8ECB29618636970365FBE5DB320E4E62376EC368805324468ACA6BC7BF113E144CC67CF5489143BCCC9E6E5EB4AC59F05B5B7C004BBD5C105DEBDDF5E79D3A49B9FDE0EC4EF4B08B6BDC03686C3104B88E316F6F72DB974DA880A5B6E25130B42A52A1C8823B5793F6CFC2BC5E027AA6192432892774E5C481C75AB919C4F8C4054A71A33F6D3F7CB5CC76EFDBB37AA6D97DEF1983932FAB2544689D4E4397999CA9AE0D32B633226B0DDA1DE6D08FC30343965092F0C569214012450E8E28D90A0BBEB58B818DA3BB5DC00FA030B100B69052948190201D02B224EBDE69AE37152F1538AD0CC49B72F6FAD2948ACE236780ADD04AC027EA2C7D916AF570232560D8C21C424A97079927FD03D23CA3A53742B749AB3E7EFDBC4462B6791FC53958D5F4F36BF578B9D2EB6F283895E47BC67E59F6C892234D69EA66669533DEB7F38879B8577494D4065532E596773969126C148CC39E8159E9D20C680FFAA709C492C0A83F7EAEEF9F4B8B4464CC1A41FE1C5EC2FC73E34AE50AAEF434A28E398CCE7073EF041A426E21492594FF00D0A7BF468DD18305208043EA1FEDA367D228FE663A9FFF00D87ED487F94BD4F61F98DBFC2F7BBFA8ABF19C598224EA0AA08F9FC7215B7F9254010A19BBB7979F58CFF86902A97D4D07D87BBC1F8A13AE7A73FACE959FF2A9BA5EA6E0866F2039D5B9C63FC66760903437F207D4748709B849410A201391279687F5FF00753585585CBE2337F64E55D73C86BFE3A82AD4C9AA3ADCBE7C21A3972D0D60CF5F58D481F5E5D2A4A4A42981E6065D69AFAE90AA30EA51277496CDAE03707CDA20EF318650A5B08202D319E5CC48CB3CFF005D69F252281B8659F67F2A5290FA561CA40510CF4622D5CADA58D62D5BCBC6A49B8B94A1339852C800753F0EB9D394480B60A0CDFEE6615B548ABF67A43F461CD4B127219EBA7A03C1EB18C76DF791B21B1F85DE6338AE316D6CCE0CD974599B8421EC51C5025B6DA41203C50B0124488E2EF3574D89E085ED7095097BC090FF004B923B7DBCA19E2B1424A424BBFD5AB27CF2BD29EB1CFF0052F6E3DB476A8DFE32DDE6CC6EB706B8219B05872D177ED255C33E1AA597015B61407454F6AEFDE0EF849364AE54F121AC689FA4336A38393E6CF153C5E3021240512493BCA37CDB78FE7AC6F66CCECDECB6C16CF58601B1986B768D59365B2E25A4216B5180A52CA009E23267299AF54F86F672F644A952CA5B7404D29976E1DDC18AE4DC495AEAA2CF99ABB73FD680677731656D7366B75C3E0BCA12E1C84EA79E672D663F5AB6CFD9EBDA83751BCA243E6F9643C867935A044A2B2491AB7B66B0605EFC8C37B5B668B0DDA30A2B6D2A30A104925524C9EB9919FD26A5766ECB3834A65AD0410F96BA599EC2FE6D0C718D2DD35000A92EFF0070FC5B5A0631B29BA6D9C21E65C08C8A92743D729F203F6ABCECD96C94D2A72CC8143CFDD6B145DAAB7DE2E5FA7A5FCAFC6379F0867F0F87B0D10470A743DE0F3E5570C3A5887B1D2F62FC2F147C5CC725AEECF7D0FA5B2CB9C9D2B3087352DC72F3E5EE911BF32AC547B96F7AE435876CFE41E66B32CDEB4A379C2E92E906FC7AC2B4A46D0510414410510414410510414410510414410510414410510414410929064C6739D6E9504BBBD5BEF0D972D459859F5E1C22A4248249F2A4D41C11EEF0A24177666D61B2D8714E958238491A93947DE7F72D664A529D9FFAB37BFD2C181048B438E0CB5CFE5FBD22AC312962F93D3AE61BCE3255F56F0E8FDA2D3C76DEE31143F60865A29527878DD4CFE607F29194C76CA0674CE7210414EE90A66A8B355DFF00BABE4D0F30E374098A5115B3DF2B75B3DF48D29DE7EE81EC25F7313B2BDBC05C5296FB2870F8644CC25206801391CF3CEAA3B4B0F88FAF71442AC0825DAE486D1DB3B6B7BEEC9DA0896849B80CE3CA9FAE51AF97187B56F76B45BBD7EC37925C4BEAE149207BD09034267A73354DC4E0F686FD56A524E44927370030E2ED7ED17295B5D0B48029C2DBDA1E35E0DC6AF093682CBC1AC398694167FAAFF0FF0057A92950E799D40A4D3266A48DFD5944F503476E35BC626CF135254D52CEF6B86D5FBD7842F7987AC2D50A5A814A4F13C6564902412390CE04E4075A96C3E0B0CB4BAD0144DAC7B07FBE79D214958A44A001EF7B5455F9BE82916EDCD9A9274D394FFACB9E91D795666E1306827FD31FFD23ECF9D3DD1C231C951228C0F56767F23DDD806868E58DB78056DA26E553C5C63DC1D2329D2751F2A8D9D2A42086450568056CC2EFDFC9E1EA26850749619B96ECC6BCFCAB4B3EFF000643CA2A76E6E1067F2B4A1C1E5A1F8CEA08A62B54AC9200B3066B655A7439584384A966DDEAFE54F2D22199C2D9B275D5B4DA145407BEB48F117023DF235E824F59E95193247CD984DD2694B75F36CB430FB0F2E71008530D41208FB65E94D6CFDB0D93C236B70CB8C2717C2AC1FB6B84942C964294A4AA66788473F3C8F794311B0B098992A1364824E7BA33E80B3EA79E462D380C61925017500D49B65573FA191168D19DB3F664DBFDD29736E7D9B719698C5D6A5DCDF6CCE22FB89C2D0106786D2CED42540B89E22A0755281CF2AE29E32F86F83C7CB9BB92424A829B71201CFB777148B8E1F6E484240500695736CC5DBB6515EEC3DB771CB1C5D8D94DFCEC662FB2DB40DAC30EED13160BB2C0F891092EAAEAE55C45110AE2CCF9675E33F1B7C0ADB7899D357835AD287247F3720540A03A6B1292FC418520B8B86000147A1CECCFA3BDF4E87ECB6F036476B9B6DFD9CDA2B1DA16D684B89BBC3EE9174DBB29E2284AD33C4A6F342C7250E935C3319E12DABB0712AC0E2513173525B7D94451FD68DCDB81504F933C6FA0009360CDC0F2AF5CF9647C331B5292A952AD4A084FFF0022513248919E607603CF952A36362C23795296903FE40D7859FA13F686CB4058CB872396777E2F1778C6EF2D582B0A53EDA38214DF110BE331EEE70424913032F95436254BC2A94952542D71A6648E1D6D9444CDC1A4A8FD22AE48D3BB68F9B70222455B4D756C9694B0E2D4E09094495088D472F21D472AD64CD334B82C4317D35AB9B4305ECF0A2E052EF60EE7DDFBC4BDBED236FB4DADD65EF19C305B09F78198CC6713FE69962B1E64CD2820AAA6B46F7A9D78C339929129450A42891983FB1A8A5EF12C9BE44A78DB75949FEE713C20749E629346D12A3541166B55FA1B76E302512D401092736724F6730E1FBE6ED9A0E825E4A808F07DE27CCCFF00A83953C9334AD8258BDA9DEC5DE3099466160821B23CEC18D73FCC26CE32DBA9E2216D000E4E0E1518EC7F61F0A9093835CC75070EE4795EB5E59F3853FC298EC03926A2EC28ED5157340417F2886BBDA74A2E0B6DA1F7018014D00A403CE6397FB3AD49499A70E7E5EE289CC81D3BF377A55E1F4AD90552C15EE8A5CDFABE61F9579C20F63C86C02E3E1B075E3504F0889CE63A7CBD44D6096B9AB4B2147A6668E7FAA1CA30766194EE46EB3029A3D5BCEB9FDE31DED7EF0B67F6612710C4710694CB82438DBA928102082547AC0D27D6AF9B23C3789C79425093BCA6BF16CAFC0FE03422BDC94EF5E7FD30CEBEC6986F43DA1DAC5AF11846C65CBD7F7B70781A4D9AFC585188E2E054E848FBCBA76CCF851B4F18942805004A49B8A38B822A1E1B2B69C9942A0588BB3B38BE64F4BDF45F6437138D6F1D386637BDABEBC6ED2CD65FB0C2AD5C5254F052B8E31261E1EF24C24B607F6933CABD3DE01F86E76761651C4A0129097701E9AB8AD341776CC45076C6DB96310A4805AAC435DAEF903C637170BC1B07C22D6DACF0CB0670CB5B3425B6AD6C5B4B2C3C94A42429E424C29440E23A1E23AC57A2B65E070182C3A50A949DE48000DD1F8C9F26EB157C4635539F7598DFBF3E4FAC5C4EB4979A42AC98436B392894F0A0C18CA3393CCE93DA92C64844D98552C6E8B06B3741DBEC6B08494294A05F788B3126EEC39D756BC0F5BA516E52B0B0A508514446B999CFB919139CE862AC7B0F1387C26EFCF402F4767A5466D6FC67589CC3A928B9761504D6DC789CB8D5CD54D9FB12ABB6DA652B5238F20449CC826791F9F7CAAD8AC08DA2A4CF900250A62C030B72F75393C5736B632589AABD99BA72A37168DE9DD6E0AB432C2D480880932444E5241FDF3ED52985D9AB92A00D599F5176D03DCF1245EF147DA0B4A8296429839005CBD3D7CB2358D9069B21090001023A72FF00433A99972F728A72DA9AFA51F93DF58A5E2120BA83821C56BAF2A7B1A429C0AEC3EFB4D0B46F5B30C7DD623D72F7AD9DEBC5E1CB7926398D7F4F80115B253B800E17D7DFEF38712C86DD1FED1EFC88852B68520A20828820A20828820A20828820A20828820A20828820A20828820A20828820A20828821A3EE34D92A2015467D48F989F81A6B324EF0248008CF5EDA5EB61942885FF00B4AA8198136BF6EBD22D6C5B0BB5C6D05B7DA42873E248394F2907A673FA9062713852A72433D2999B657F76A9895C262BE4021C90C0DECF90CDB80F28D76DE1EE5517CCDC5CE16D842CA491C020C81D00EBD0EB2222A0F13B394E0B2800EF43404D9F2B795227F09B5104805401C876A5EDCDB5AC6B35AECF5EECFDF2ED2F6DD6485405291F3CC8F3923E7509336792A50DD37BB54BE4697E7A44E236900032AFFED2E74ADAB9D9B5176892BFC33C5714B4A40040CA34C88F4F88CF5CE95460FE5A40666A3B1EA3856E087B16A557FF00304C6DD37CC963636AD9F969AC5AB79849930939EB9798CBAC4D369D215BA4B07197AB73EC61DC89C01363625EF4A9A9A38D74B59C413F61C1C49888EB9779EDDB3EF50F89C392E4675E56B7323C985E26E4CF70327B686EFF00AE15E56D5E589E239489CB43CF97AF3FD62A24C9625C647A6B968CCF7E31252A7848157D2A19C5387463E8D10AEE1DC4147864C667E323423EF2D49A66A5EE2C0341A350DA8783FDEB133879E0241DE07870B3533FC86CA21DFC3553A13E59FC2048CFFCE993B4AF7D208343D9F90F7A43D4625259E95701E8E3813A674842D2D9D6DF5B686020019BCB494A5723FEDA98CBAC75E9178DC399885101DC663EC6E3FA6178749C502A636C8022A5AAFEA22C5DB5DD5EC06D9A56CED7ECD5AE22873253CDD9B6EB99F3E258D4E93D7AE7547C76C654D52814BBB801A95A58FBEB50EC62B46073770C39E7C9B5D2358769BD8D5FC18DEED1EE5B6E719D92D176381BF889B2C2D970020A516D6E9C92E2C4AA224CE872AE7F8DF84382DAF89562A74894B98A2FF5A6A5854971D6834ADA2C982C7A53280DE6200706C5ED9F5357E04C60C637ABEDA5B98C69CC3F783B1B866D6EC55BF1A9CC6707B0BEBEBF36EDA54BF13C77086F88849CC889CF28AAEEDDF83982C3E194538745029BE9E1614AD39D2B7A449C9C626630B3B333E75FC3FDE919A775DFC477737B73776DB34E626E6038A61EA71AC52C318798B7B9B67944801D6B8A5292B04A246600033AF2A78F3E1A623040E213865224CC2AF953770842F74B16362D6247F6FE5044C53392736233B5FF0059E85B6C70DDFE6EE31265E36BB6DB3EAB87024DAA1EC41A0662600067211315C50F8731B266EE2028024D81D73A73CFCEB1228C0254086C9ACE03F215EF9D844B61BBD1C2AF8AD4D63D87B970DE65DB7B90A61433238153C80131A6A3A53F95E1433803350EB3A8E3FDD2EE6174F86D33C0594824D4E9E60FBB6717261BBCC43C1DF1F1266EDB6B3E169E0BC87627B453A1E0EA809964D724BB771EEB01F0DA10092814B960FED8449FFEE8E10E5AB6E1BB2C34A2A002969470C18248073CFBE94FA4783E72082892A615FE2FDAD715E26819A103B225A0BEE80012C5AEC73B8D323CA23717DEAECDD8E1EBB84E2C2E16904F84D3E9528F6893AE63B7ACD494BF0D62890912D49721C37767EF9706784FFC244B56FB208A31A6F646BE74AF58C4B79ED47B2B84D8285CA5EF1D5E22521213E285490264F32411D6262BA56C6F86EBC6E1D334C92544554525CB90F56EA78E60444E2F172A42C85123402A939D6AD4CF2B5B2C2D896FF76C31E7DC6B64306C43145BE48652F30B7904AA40808327CBE9575D9BF0B5689809901A87F8E8796A2B1098BDA89DD2029935B1F79BD9DF5156A309DC7EF7F7C0EA5FDE25F39B2981CF1A2DEDDC7ACDC08992149765209232EB273CCD764F0D7C3F32572CFC948008B2780D00C868DEB157C5ED10EE54C0BBD682E00CAF616A9E91B47BBADC2EEFF621808C3B0CFE6F7AC0138BDD32D3EB0B4C92B0FA6089339E672CC577ED87E14F952D2E9600682ACD4B5816FB457311B40289216F53C5891EDB96869995A64786385C0B0320419000C824764881A888F4AB72657F88D2AC2D4A12C3A31A55FF005159C54BF9EB52C3D3B8D6A59EDCA14F00F5F4E7F18229CA092A152473A5453843032FE5922BD7F1D7F1136D5E356B668429292A1324F39396BAEA0F202A4E4E154B1715A37AB5383119D3284FFCA1243B81773A5FCECFFDB1685CC4D7C2DB5C5240809D2644EBA9E43A72815252B66294A02C4B1A5AF5E43A8A645E3076ACBFF9E55AF36CAC3A3F08D8CDDB6EE55768B5BC799E10A2492A4F43DFF4CEBA1EC89224E1820DC5B4BD5C9D39E715CC6E3133662D64B019937BB8A3DCF1E91B8582E0B6D84DA2128400A4A7A69FAE675F96553491BA092CEDD3DDACFC0D62A98BC52A7ACA45100B30CF9F0F662E2617C6DF144493F414992E49D622E7A774A83BD8F7685AB10C141945BDD21540CBCCFDFEB446C8CFA7BF48AE88520A20828820A20828820A20828820A208FFD9, '1', '2021-10-06 01:13:41', '1', '2021-10-06 01:13:41', b'0', 0); +INSERT INTO `infra_file` VALUES ('7e7ed694-2242-46cf-9ac9-0709debcc22f', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F00010000060301010000000000000000000001020308090A040607050BFFC40045100001020404040403060503030401050101020300040511060712210813314109225161147181233291A1B1F00A1542C1D116E1F1175262243363723443538292A3D3FFC4001E0101000006030100000000000000000000000203040506080107090AFFC4004A1100010204040306040405030304000309010211000304210512314106516107132271819108A1B1F01432C1D1234252E1F1091516243362435372923482A23654636473B2C2D2E2FFDA000C03010002110311003F00DB823E07E37221084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210844495A905D25BFB690844CEFE6FF54210EFE6FF00542112497249D4DCC2108421084210842108421084210842113E5CA72E5EDA37F8E5FDF584409B0BEFF48A832DD291CEC0EBEFCDF5EBBF28640BB163C9FEF589085292544591EA6D6BF4B5FDCFAC56D3E0CA9E9CC27213C81D4F958F9F571A341E5CB3721C380059B673BDD8731CDE2A458E1084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084211508960904681AF7BF95B5F4B1E5084574B4598062DBF27FBFD6112AB569240240DD76363A07DE20FE115B2A91552AEEE525D4740399D2DCBF6688173132C6656D70DCF9F266FB31F22AD52A5C8539D9BA9D45BA4531A429C5CDD4679A9461B084A965C3CE7921494252547D85ADB98EC7E10EC7B8DF896A648A0A3A899296B4F892859195D9EC92E6D6203EBD40B1565707565CA14A172C3C5E659F91DEEEC39FD98E958C8210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108472091A184239CEAE7F21FB4210CEAE7F21FB42110EB08421088E5E5CC3300431B1BFCB78437F97CADFDC7E9134CB0A3E005BA581FBF7F46844FE403CC77F99B6FBED6FDF5ED15D4B4D2759E82C7F5D3CB99312D4B63A86EBCDD9BEDA2522C76B588B8B7FBDE2EABC0E9EA249A893574F2128194CA5A996A624B817377673A989130CF529265964EF672FECDF4FDC0A13BAFEE807DB7EDD3DE28A51A1A75777328E6D5312EA96090AF23981B36DFB444813ED995ABB9B586CFAFD3D1E38DCF4955924F5B76DFEBDC7CBB7CE2399F839A3F8586D424AB474A8B7CCE9BBDB57D22AD92078943477D80E6E186D6FA189984B85603EA521A58F23F76CA49F42D825EB74370DF4E9DE2AE9F06A994B428D24FA94AD8A51282944B9B067B1DB4167E514B595D4D210E148CC0789209043EE087048D8027778F8188F155030AD2E72B38A71261DC3148A7A14E3F57AA54E5E9926B6D00A9612AAC392E5E7DB4A6EE352A9715E64D93B8BF7AF0376478971B4D954D478355C85CDCA04C9925612E6C1C91A97B73E4631556373D738A10A704E50C3AE8ED71D4FAF4C39713FE377C39E4E551FC17936AA8E7D63D712B97629F83A9D35352289A1E5287D6E332CE3AC078A10A7257982E53A5442AE77BBB25F80DA8C3ABD18F7194EA5460DDDA54135933F0E896B70439577799446621292A2ACB605A23AD99895553A134A16A5B87094662C5DCB316F3B6DA8D719189A77C48FC465A54DE65E269BE1B328DF70392385A96890A4D626245C3A4214B956CE255AD72CA50B3CAE595101C36B93B99832FB1CEC9E49A5C369B0EC42A24200354ACC24A272032932A5CDCBDE202B79A82EC08B1262EF81F0AE29882906AD0B0951B86B94B81A8D3676208763CA36E98F9A48BC42108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084220ABD8DAF7F6EBD601F6F942223EE8BDF57E5FEE7FE7AC5DB0E97DECC424B124E8767D2FA683CDFE72E62F20F9F3E71F16AF5594A6A983393723241D9E6245A13B50919353CB783250B65132FB4A7802EE9D0C852D4A0404F48ED2C1781AB3184A7F0D254B2AE492439DBCAD168A8AC6258F5D85AE370C6FD1C87F38FACCB9CFD2194F32CAD0A285254026FB39706CA041B84A4951162010445B389BB38C7B08AF932BF0B51967202F284A9D9CE819B661F48952F19932C142AEA0EC437E96D45D9FD220EA994874CC3C9939669402A6A710B956FA9B9097C36B2D8FEA780E5207996B4A45E333E12E08C4AB952E427876BA6A94C9EF3B898AD6DAB1F3E5789533192A0720241D033160CEFE4FE66DAC5A3673F1C1C2D70FB2B393398F9C182A4E6A4C2AF49A657A9D5BAB3853736453E93313D361574E9D2590ABED6E91B25C33F0ADC67C52BA7551E11554F256B96164D2AB280E09CCA32C8486DC9B5EFCA8D58954CCB0CE33F84000B6BF3D6FA90DAB5A30DB9A5E3998DB332A33185B820E1F31563DA8B5AE5CE39C4F4F7A428A92B5684BD2F2D507241364D8AC1725C822DB7511BCBC1FF00073C17C272696AF8CF15C32494A10A992066AA9CA5243AC034E998841D001372DF5D0C5C11C3788D600A4CA9AA0A4821C9D4FF00F262413BFB88B53ACF0A5C6D718B5194C49C5F67CD4F0FE1C9D77E28E5960B9B5C9372D2AA21486DF320C8A682E216B6D6A6DDF883A41755F723B0AAF8EBB24ECAA9552B85B04A2995F2E5A909ACAD44A9EB4AC064AA5497325C1018AE5121FCDB28C2BB37AA9EA419C9233105920816D9DF30DF768BF0C8EE0BF20F8799368605C074772A9A5297B11D7E5FF9DE2075570A594CFD50CE3AC05AD216A32EB6D414949490018D6CE39F8A3C7F1C136827D49FC1296549968968952F30709509729284000288484A40625AD68ED9C13812550E55CC940A7280330727A9D49767BBBF9978BA179B43EE36E3A5C77960250DA96A406D23601B79B29984240E890E04F416D3B46B571071662FC43316B935535282E4E559763B6A412F6BDC876BC671498452D390532D296DC02038D7A9F5043EA2D196B8F39A359E10842108472C59D8B736B4211C42108E1C0D481EB08E424A8B00E758383A107D6111776BFE931CC221208B1041E4434211C421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210844FA64A1535216404B13736D3CC6CF68422EB488EEEB652DC89799249B652971FCCDA33D9C68363149521652A604EA18027CB47EAFD4C625BC5C723736F34723E9B8F3237165728998792932D6366E9347985A65F12B5499D1565C8CC36DA4F3C99664B6B6C282F962CAB01B7AB3F06F3F82D788AA931B46175B2314A29B874F4D57773275209F2D72D3574B98B267C852FBC43A54E5094B125A30AC5513D63324AE5996B4A859401662525C12411B0EBCA30FF971E355C7267261D96C0D923C35E1EC458FB0B48B185F16E209F76B084532B72290C3D3EEF2AB92D4F4321A532A53B32CA91F109790547416D3E8AE3FD8076514C8A7C671E453FE025C84CC975264CC5A97241514B8949695308BF8C0D4280CACF434D4D555F34264CB54D597040D417DAF717F4D1C398E3629CBDF168E294A3FEAFF001308CAFC3D308D350C3F8585065FE124661453CB96769B2AE551D23ED1A438265C46A410E950044758278E3B01E0D99512704E15A4C5AA24A9A5CD9D3545495CBD1D14F325F81447882939D9F48EC8C2B81714A8085CEA69D2D0C03E420176772A04380C5DEFBC7A4657F850E436199D93ABE6AD471667463169497E4EA789EBCFCDD2A6A6894AD7F1EC535C937DA6CB801B3EB6FCAA56E77B6198F7C54CC41A9918149A6C1E42D16A4A7A7932D29CB982405AD0A9C40D0BCD2ED7711D9185F673256941328A9682E4A9C9DB51A1E5616776D6322984F2FF000565F4A269383F0A50B0E372C005FF002FA7CB043A027484879A4A94AB04DBFF0070A8DEE4C6AD711FC41714E25327A27D5CD9C95AD6C01CB636E439FD3AB763D260326484215283CB64B650C7EF41B8BBEC63B8216B492541B0A2AB8E5EA29D2474F3A945245B74936171B474A62DC5F598B2D73271984A8A9F34C2F76D03F5DB5BF98CA6969A9E404E5969040B823CDC8DC17D0F2F5894BAF29C21441458FA1DEFB1EFEFFAFA88C726AD53D254A5BEAC1459B721CB3916BBF9022D1799425D4112C808BBB1D1B40C771EBD62205FB81F389B49884CA4494A40507E6003EFAFDDEF1CAE86503AA6E4DAD66B336A2FADFDEC632CF1A4B1A6708E589D013E9084710844495149D6DA11B31D7EC5E114352AF72771D08FF1FF003138CC9440694C7CCEDD0F3D75D5E2320100A41F262DEFF7D22AA557B5ED7F98DFF3FF001F8440552BFF006CEFB9F931F38965209B8BEFB7BFDBFD22722D6DC6FD81BFE5FDC7D7B47227207E49794F32EC47BEBED10A501249737B31D9BF7D6211C9A8984310961D0FEF11C220F14D50B5DAE76B6E790FBBC21101052483A88423884210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210881DC1B6C6108A69D8D8DC9D477DEDB03E9DCFBF51192D34AEFA95CD94948B96723A73DBD75E9C10E18EF1C09E93969C42E548626989B4028947920B73AABF2A6E9F300A86A4CC3295A2D704A5D0047737635C62384F1F913D73D484A26A4FF00DC22C08D7C4346BBBBC63D88CA5942B32772E4E87FA4860DA37507D23536E2E328EA5E183C7949E7E61C6A651C387129539695C6549916D69A7E0FAD545628F55176C28309698E4D49B2EDFED5E51B9B587BA7D9DF68749DB5765D3B8724D449FF0075C2E8E6990AEF1E655D2212A9AB92015052E7CB26628285F294218B5ED78056270DC6A48984649B352EE2C9512003C8025BD5DE32C9469A97AA5269F52909895A8CBD49845429D392CB438DBD2334C34EB485290A29296DA216371F68B73BDC0D02ED3785EAFB3DC4AA27CC1353DECC5AC851533936D49362082C6C760E6377B87E6C8ACC2E5652851EED2EC13FD20B160E0B333FEB1F40A9B6946E4B6E7F572FF4D81E87A743D7AC74C1AC388054FCC6EE3522E5DBE5CFA5B78989989A39A52964DD8369736BB30D85C72BEA623D62C539CA9D4DA93A726BDC9DB7B4579493E2045C3FCBD8BF3B42282697BF33FA1FB31104060EEFBE9FB4224C4FA74B2887760E3DC06DED08456465A234DE34BE11594E9CC85076F11DB98108828E917B5F7B4552684CE3605F4F08E6D7207203F71BC20B75252404807D77B7B837B6DFDEDBDA27A7079997BCC8A294DC862E5AE47DF58840626E4F20768E2B6F357F3B8DB9D7642C3205ADB12BE67E37EA378ACA31214BCA680962416D75DDC1F2160C3AC40BAA484B25402858E6208F326DBDADF28E40765C2482D2D02F70EFC730B491DEE0320DC74B5FF48BA4FA7A612DD386AB3358EEFB91E1161BFE9146AAC5851CCB9447FE285076D812A53F9DEDD6D12A17AD4742D2B6EDB1093A811616D7A8A4FAEC05FAFCACC8A34572E64B974A65292097B9075DD868FA8D34F3994F52272D412DA17DF4D0FCF660DCA2AC5AEB30F9B4AB21414403CAE3F7DED63E7BD6C220A340528BEAE1873637BFDBB421126A401396DD3E8DFA4211221084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084211C80E586F1C12C09E512936FF001D6FBF61EBEF7DFD3A45DA9EBD32A5E460469B8366BFB0F6E45C4722EDD79DA264A1B5202B40D41E4CC03DC3CD690DB80FAA4211B7DD36F3024989332AEA25CC13A4A88162081A39BE9766362F147572028124396B7273762795DF4BEC748B3EE3A3860A2F17FC38E60E5454E4E51EAE4C51EAB55C2F54994053F4DC452322A9AA10957016F4AA76A8C312EE137BA0D9206E637EFE0CFB61A9E15E21A5A6ACAA250AA900852D82D07205A0B9365A5D2A61B9F21865652AA4D4A6A00395252EC086209BBF4B68469CA3009E19D9C589A66878DF871CCD7669BCD3C8D9C5D326252A0A29A84FD05B9A9812DF64B09594B6865F20A517E529B2491631E8DFC4B703CBE34C06471060B244CA3AEA54D4489B2D04A338493325E6BF892A752AE2CA1A3DFBDFB39E374A932A8A64C7520996B054091A0B0DADBF327CE32B096103CF2EB53CA7505EB38012D1171CB02DEA075F5F5BC799C696661B513A8677826233272F54921DB727A359F431DED329FF00192913A5BA92482481CDB71D074D0ECD14FF007E91669EE165DF5DEF7DEE0795CDA2ED2E532120A4B8006FB795A114131DAFABDECDB188FBB1FD27E708931325A7293621C75E639C2113632D2B1A5370413E96DBF1BFB88D384256BBA50A239B758D2D4AB3683F57F28A682A735E84EB2D8D4E2527CE11DB968DCB8A363E5041E9BEF715B48898A5096949CCA25831726CEE1EDB35BFBF330F760155B35927519B928FF2EA39BED12BB32CCAB5CE7D4DB6DA81239CE064A103EF178A81E4B82D7436AB972CA008D378EE7E0EECF719C7A6CA44AA49A3BC20056451FCCD7D3AF97D0582B71C452139924B1E6D71A8EBCF5F4D231CBC50F8AC7063C27CD2E8B8F332256AD8D2CBD18270FAA5E72B6A52076652FAD691AB62A2C900EFA760237D7B32F817E23E32A597884C9B364D2CAEECCE3DC152121434592A4B3E52CFA81E71609DC6D2659CA24B920B0CCC6DAD9AF7B4611334FF008A23084AD4E764329F878AC56E5A5E6552AC54EB98A996913001584BC8926B0EA14A4D93A8A7E26E01EA7AC6E6F0E7FA75F0E144935D3A9E44C54A4AC04D389AB52AD69802D3DD12FBB8D7CCD895C6414559242AC4B1D12CFB162F76622C5CE81E3CBF0AFF0014762C72AC246BDC39526ACD36FAD335274AC4AA93A832C972C95042E933A5C7143709084D8EDDE332AEFF004E6E11452A946A6466C80A40A6042944071FF70650347F10205AF6347338C5811DCB925FF36E6FAB3BB746F28CA670E9E3F5C256714FD3E898FA9988724AAD3BCB495E2E986D74665C71C4B60B93EE485312DA14B58B38524588DAC45B5B7B4CF808FF006AA2993387A4A664E965456BA593DE3A4256A2494D982439E57B98ADC2B8D25A66ABBC9590286AB55F5661E762CFA9D088CDCE1BC5748C6147A7622C2F3B255FC395B61A9AA1E20A54E373B47AA4B3E90E34E313CC853575A085048D66FB5FBC799DDAA7633C41C233A6A6652CE5A25A94EB32D490C017B5C90C2DD3CA337A5E219152C026E58BBD86E0DACDA797D3B1A545574E85A5C6D650F21692808B7F521476753EE026DF2DE35C44A5D34D299A322C29563AEA41243588B5BF7117E95384D19980490E920E672CECC006F47BDA220DFD3A91B1B8D891D47EC748B7549067288B8B7D2277F6D6D11891084459490FF6DBFDFD94221842108421084210842108421084210842108421084210842108421084210842108421084211C80352E12F72DA08440DC7417B75EDFDBE71528954EA01E7804BDADA738020BDFEFAEE3D8BC4BACF4D26FE9FB1F388674B9281E09BDE13C886FA7ED1CB00097B8D86FAE9E81FD62A00A209234DBD4C5366161ABF2BC40A5650E0666B16DA21B800916045F7FDFEF6F58AA912E44C0AEF270411602DAFAEBC8F2F680513B36FAFF6F6E6D10B82091BDBF7F389ABA7A64FE5A90BF261F7F41CE228883700FA8BC51A800A20170343F7CB47DE10886108E41620F28E08704738811716FD88E23901801C834453E516EB7D8F6FDFE715D22AA5CB9650B979B563EAE03EBD3CA38580B7CD7E56D2CCFF00AEDB44A90D05A12FA8995E6954DA124256439A532802883D6606D706DD6C40B9CE7B3AC46752F12D2CEA72A90942D2B241B780E620DC3381E57B03A45A311A54CC90B940A42969396EC6D7530BE83DC0D63555F13BCB9A8F05FC7565171858692AA560ECE7AA230C660265D854BC8A669130CCA3CF3EEA565A587E42725D2942D092DB8971C2A5870253EF5FC3A71E5376A1D9AE29C3F52906AB09A7993A95130E72B08927F1465B870D2E5A5459C17EB18FF0E53CEC271697384E2B42960283B017748373A9376219A32734CA9355191A555D975B5C954D69AB4ABCCAB5A6764DB969579F690011A0252E03CCBAD24AFEE009223CFDED2307550714E27396932E5A674E4A506DFCC599B61CF56F68DD4E15C7D153432E52A51CC94B024B87CA003A0D5F9DAD1CC26E49F537FC7F0FD23A926D4BA8802C145B968DABBF4FDCC6582A125D927DEFF40CFB6BF2884532A666770CEDBF289A8585E9089711C2108CB24D3A86D2A2A5001B5A5B593BE97156D293B920AB526DEB7B5EF1AC7493A9414C9080E47874D09D7401DEDFE234991532D049D589BE9A5AFAD8730F770C23A0E3CCCAC1D957862B18CB306B9218630A61E61C9EAD5627A6512CECB32D214E284AA9CB25C7D484A8A504A4FDDDCDE364BB1BEC5EB38E712A6AC9348B5C83350804214A49398170183BB80C5F6E822C18D6372E428212A00643A96D6DCBCEECFF0048D287C517C77B32B36F13E23CA4E186AD3B82B2BDA5AA9950C4CC3CA35AC46C6B799717A99E52132AF3772B297147CC9DF68F78BE1FFE10B02C370EA2AFC630F973EA3BB44C452F761225901242A728A4B31FFD3CB71A2E3AAF16C5D73A6108532492EA7B9F27F2F97531AD6572BB5BAF4F38FD42B5529A54C3AB989B9D9A79C9E9A989859D44E9756149495137FB5B017D8F7F41F06E0AC1B094211365C9414CB44B4CB9684CB9694A410004BDB61BFD41C745490080E6CDAD9F7D9C3EFCFD8C64C7C2FF00C32737FC47F3819C1D8710FC8E5D61F769CF66AE36984AD12B457E78AD729234A7D29E5A9D9E665AA0B652B582532AA246D1912B06A1A2654B4A4380583311ABBF2B0F668B6CCAA5DD24DD8EA5AD6B336FB10469611FA207099E0C7C0AF0A78768F4BA264AE15C6F8A25D86DB9CC5F8C2892D51A9BB34020BB3A667524596EA0A994149D29510567A981A9EA3C0A0188003B68DEBCF47DAED78A29B52A21C96670A00DBABDBA5AD7D7CEF8B197063C3363CA42A8F8B72672EEBD4D6DB29665E670DC9B4C36396A67C8940D63430B712DAF59D2A29558DAD1455FC17836292BBBA992950591A01770437270090DE9CE29C622BA72E9043DDC9361CCB0B7EB189CCD2E0F717702B3F53CD7E0D8D6AB593F3532F4E664F0F9539C76A529274D0E17EB55BC245B69B14F4D325D0FD46525CCA3C34B4941753BAA34DBE24FE18B87F17E1FAEADA6A296A9A69D6A49125254C997E101BFA58061B87F2CAF05E21525694A97A91A1606E0EE4F91B7CB4BB9CB4CC7C379BF822838EF05D55550A35728A5CA712A4A8D2A6A554B979EA6D54A55F673D28FB0FCB4C3640521D42C5B68F9B5ED93B25AEE19E24AC948A65CA9299EB0C94948090ABE83567E77B98EE9C0B1513D092EEEC1405C90D62EFCF53C847A2304F29A0A012BD09D601B8D7A415A8136BA54A2549FFC4FB46B857D02A454AE5A81494923996D6EE05F5F96968CC01CC01777BBE9AFEDA457208EA2D16F992B2E8180B33FDDF7E4768E621122108421084210842108421084210842108421084210842108421084210842108421084211015804DB4DDDBF4845449959C82438D4BFDDF9F26D621EF433B5BCFF00B3C2F6DFD378AF142A9A932D232BB31DB9E9E8C4BB9DA057983331569763F7CE097D2A04A54921240277D89F5E9126660F3901F338BBB0D1B5D7EFAC4B34AB07F3A8137607D76F9444DCDEE3AEFF0043FDBB44CA7C34158135795208DB5F5058F5F5D221EEE60F0855FAFCC92FF43AC4AB0A08240569FEA3DADFBF6B6FEF179381D34F4BC9580503C4C41E7E5AB723689D27F332C872EC34274E5CB71D6FA344A9D66E6C6D6BDCF44F7BF7B0DFFB768A19D82A500E59C333B070E3DDC7E9CC44E3945B3026D6D1F5B0E677F28AC90B02E1371DCDBAEC3F7F58903029F32E9989200D5881D776BFE9AC40540753CBF7E51245AA74A54898B94BFCC82527AB59E2205C03CC3C225C21084210842114B58F886DB5A0A9B1CB5382D70E05B9A1BDEFB09758E728906C937B0EF97F0E4DFC1257581B3A7300C6F74FCC870E1F66D629AA4781F2924050059C0B5DCB86CCE0462C3C65724D19D3C0DE67CB3A944DD5F01CB3D8BF0E16D1AE624DCA234AA8CCBCD28F9D097D0C34D5D3FD4C9DCEC23D36FF004F9E3A9838A1587CE9AC99B3E63A0A892B42800A4905DD2A4B823A9058968C76988154DE27705FCCEBA16BF4B74044590F87B6613B995C2565156A69D5CD56E8B26F618AA4E3CBD69667245D409D0FA89BA54A957A502924DEC81DAD6EC8F8BCE19A7E1DC76AA6524B299752B339194312263A880CDB96E6D62F1B1FC1554D22592C090010DCB53A33F2EB7D418BCB3D4F4EA7A74FA7B7A468F041201259C3DC73F58ED244D3AE80805CEFD086B7BF3E5108777D7E5FDE2B654C09DC17DFA9E8F6D3D37E88E148CA1DF5E8DCFF0068AB4AC2B4E57F97EF0882228CABCE16DBFF00D73B32DC8B0861C616F4C2ACCC9A582B7A66A13248F2A1965C4AF5764B67CC3B751F643D9D5671A6334F462495A7BF77082A073252004B0D2CF73AB9D75D0AAF9A64B9CCE6F62430040D36EBD75F2D0FFC707C52710F10398F5CE1D7292BAE7FD1BC1B55758C413B4F9A534711D592A0C541F438D2B42E496DCB32C2028AACB43BB0EDF46DF08DF0E949C13C35455F5F448556CD22A2953364248944A53926AB33292A494920338B17731D57C4156A9B50A4A56486655C39E637B0E6E5892DD75CC0E294DA92A6FE1895950972BE6ACA36D2B71CB24DF75586937F58F4CB0BA69384D025084244C291994078896F5F5FD230D9CA52CB3800D85AC06970FB7DE9695282E292817256A0800752544016F7DE2D53A8AB2BA699A952B2A1454C1F4776B72DFEB13A54ACC924DB28E409FF001E47773BC7EA6FFC3FDC2C61CE1DBC39B256A32B20C3788B38B0C51334B115614CA5152985D769A99DA7D39F5DB5AC53933B34DA35AFC9CC20246A317112A655242092484949BE9B6B7E5BF5D358B74D925CAB53C8727D75E6436FADA339127284B2D2DC74AD6A4056E9B286C2C93B9B691B5FEB6BC4B4E16A924AC28050D6E46F716B9BD87DB514C96924D806E8DB96BFDDA3E838D5D011AF4EAB017EFB5ED6BF5B7CE26A8D42C77685293DDDC90ECC39DC587CA28A653898921EE3700797A8766FDA3AF54687233327372932CB532998977DB5CB3E84A99984BADA92A65D06E9E5BA096D7706E851041E865D7D18C7B0E9D87D534C4290A490A16636D0BF9D8BB599C08829C2A9E6A402480C4598F4B8361766FA6B1ADFE526246F86BF10FCF8E0ED15112B8533265A5738B2BA9732AD2891AFD525A9F51C534BA7B57D09A73530E56E6101AD23426E509DC8F1AFE377B12A2E1FA2ACC6D146801A62FBC44A17CC933029652FCEC4E9A79F7070C5794776E45D817360469D75B1F6DE32B1A349B9042AE42EE2C39A9252E948EC953816A47FE047BC7815C47290BC4AA9494B253354966FE82DA1BD88F23CDE3B9E8661994E8512E4871B3FB6DB73F9435EAF2FFDBEDD7EBEDFBBC6213D000D1ED63A9163FAE9156033F5DB61E508B54730842108421084210842108421084210842108421084210842108421084210842108422242731676FF00205BADFDA28272C8594B5B5F573D2117DA296094B00A1A03A03BBB31DF9BF5E465779D3E7FDA20A525092A528A529054A501A8A401724276D440DC0B8B9DA332C3B099B5F36548A74A95327282101092A24A8848B80589275D1E38554A6482B53654392E761ABDADA6BB34790668678E5464DD25755CD2C7587308D292D17C3F55A9B01F521214A24C89525C3B0FBBACFE368D91E03F869E28E2B5CB4A696A5417909FE12D4121577D183F561637D445B26F13D32092932C120A5C3055AD6BE9D6DC9C02D18FAC4BE365E1DF85A6DD929CCE2929F536E9639D214A6D52C4A7FA9A26747937201B0B9BED1B172BFD3DF8D2BA9C4CA6C3EA56A290ACA896DB6CEDE7CAF7D18D9AA78BA9E5803BD272BB15A9CBBBB390E481ABD847AB65478A670339C35993A5611CF5C38AAB4D8024E4EAE19A6A02DD2004A9F334E849510906E9EDE9B46118CFC0EF1CF0DCA9AA9D4159E2709CB256A2181D9398BDEFCF48974DC5F2EA4AC256924725358D8824DC686ECCFE76BF192AED32A94F6EB3489DA3D425E7480CCE532A08AA3136950D490C3CD2121BD5D6E76B6C235478FBB18E29E1A9B34CEA6AA09959BF32169208BB9B3B80EE0B737D1AF94D8BF7A52010F66BF26B31D5DF979B3C7D7438B99681374150DEE6DBEFD0EDFEFEB1D1B35389504C5217F884149218BBB827672C0B5CB73EB17D94B331399811D2EFA6C3CFD3AC5609D2026E55A45AE7A9B77FAC5B264C5CD5AA62C92A5172FAFAF5E71562C03F288C411CC21084210842291F2BE8737B04DBF32477BFE47F18BB505412052B3898A6D1EC4DF96D667F944339FB85B6CE4DFA06D8E8770DEB1E3BC43D065B15E48E6F50E698130DD572E317C886880A05D98A34DB4DAAC76D94B041B5C6FDAF1BB5F09956BE17ED270BCAA2913932D44681D6A20821FF005E83A61C89853582C7F3366EAF7DDC020BBEFBD846B2DE11D5C99392398B84C927FD2B99B5861A6093E444E38C35603A0FFF0017A7B778DF8F8C897F8FC428122FDF6134D5414392FBC1AF4CAEFB9B35ADDF1C17519A4CBD1DC020EFE5D5F43CF668CB4479E4A9241286163940276E96376DADE71DC32A6121373A0F22390F4D2DD6110F766E19C0E7A6FA3F9B721A5A2BA5AF301AEE41DF58449A84B240218A4E80D8DD9E2E14CA398A6CECC4F36DC422922B23E178D9F17935C2AF0818965F0AD4E624B32B3464A6B0BE1D98979A32CFB54D9D6BE0AAF5261E4283A8765A5A65443890157652014E916DDEFF004FBECE287159B49595F432E69CC95998B9799921293943A48CC6E120903335DDE3CD9C72B6727334C22E580243EA6FC9831BF9911F9C25467266A939393530753930B5A5D55C90E85BAECC28F4DD0A7E61E5D8F55AD67A9263E82387B0D451514B19085327C4ABAD59400092752C00E6C00168EB4AC9EB5CD27312391F7D01EA5FE778E1A1050A51161AEC16475568BE9076DF4DCD876B9F58C8CA94AB124DB4276F2DE284924B9F362E7EA7CFDF68E632E8967E56634EAE4BCD3A53FF00772DC42C8FADAC2262274C96190ACA34616F3D1BEC472662C2540288041702C0EBA8DE3F5C8F081CD2C3B9ADE1DBC2862DA14CA1128CE51E13A0D4E4C283C69F896528F248AAD397A2FC84C93E80D213B69D4404A7A454CB190029B12351D768B4AA6ADD5E32C4DC3D8B738C9FCB1525B4A1D480E2494AACABEB29362A27ADD46E6C45C5E261512083BFEEF1095920825C6CFA81B0D741CB6D2394E1BA536483E636EBE5D8D8FB1DEC7F5B4429480261DCA093D5AEC59B4D6FCA244D52865092C5C6DE7AF43F6FA470E614BD0BB69B86D5E43B6A2524E920F5076041DBAC51519589732623F302AF1004E5653A481B335BA81D627A91FC30A03C4DAB39E66E072258C6893E22DC4BD3E5BC7F32127B0756D2FA7071C3D80B10BAC39CB765CD7692D48CFD2F9A8513C83FCC9D65E6494A4A4AD2A4D898D69F89CC1A8B17ECDB1E56272454A95433D402C02954C492467CCE6CCE1DEE1ACD19370B4C9A6A129CCE01F26736B3D83FE84738DAC03A5EE9A8730735209B90DB9F68D26F73E54B6A4848EC9000B585BE4DFB56C29143C438AA6911DD4B1513825080C01EF09D9ACCC06DBC6C3E1CA50A79409D833ED67B68DD03EE2C2D11D3A763D7B9F5F7BF58E97A70B54C2959516D5CBB312ECFF4DC6D175413B926DF3FD37B44A2F7B7604837EB6B6DFAFF009EF795501215E1003BBD80BB9F7F3E7E7132268A7842108421084210842108421084210842108421084210842108421084210842108124036F436DBDBF7FDA2A6453CCA929972802A7B9DEE6DA5CF5897952661240717DB90D7F7DA292DCE5A52544DD6A0D25294DCEB7886DB51B90129694A0B593D12937BF7ED0E19E12ACC6572282992A3513141072824E626C2C2E58B7937A52D6AE5CB92A3605AECCFB0FAFB07D630B9C78788DE37C298EE83C25F071456F3138A9C7336DD2AF28E0345C16C3EFF21BAACF3AD3730A945CB235CCCCB818D61B45F736B7B05F08FF0009F22A25D1E37C5583CB9D4D29529495D4484CC99316485044A42C329B3254B24A4049719882074F71062D52852E5CB9EB009219C84D9FF31E476B5CED1E8FC3F780DE12C72993CD7F119C7D8A7890CD4AD25BAC4E526AD589D7B07E149878077F94CACAD41E7D13ACB0B245BE0D841BE92848DE3D8BE0DECC3867014A1386E0D4D440C944A5FE1E54B946621398B4D08480B3E220E627D8475CCDAEAA512553944B96BA8E537FCBEC2F6B6B17F156F042F0CEABE1F3499AE16B2F9B61682D2E72430ED1A995DD3A059C62A6CCA1782ECAF2AB5A4DF73EDDC48C170F93232269A58480080122DB36835636B3FCE286655D428879AA2483B9361AB07EB76D635CFF0013EFE196A4E12C27883383821AAD453354677E2EA1957594AE75C7295A1E79EFE52F075E6FE2590D14A161B68A750B1DE2D8BE1AC2E7A66AD54A0651FCBE1777D1872D47BEED558755AA5F7854B2F6377363FCBBF93927D235DFE12FC4FF008C2E04B158C2B278B6BB3384A97555CB55B2DB16CECEA69B28CCABA1A7E45EA7BC5F625665F4EA4B2032A2C7248DB546B4769DF0E5C1FC7D4F5B2D180C89752B4AC99F269E5AD73164165CC0420BBB9529C936B168BCD3633552E7272D428070C92A622FFCAC6EEFD00667777DE63808F124C92E3BB2F64EA981E6DDC3F99547916062DCB9ABBAC2E66993250034F353C5F52E7DA9CD330B963F0E8E6A1A5393225DC4B4DB9E15FC547C22E39D9F55D5575350934C5739525726593296259F180C12465702E901EE1EF1DBDC3F8D2A621089939401482A25442812465601F5DFC5D37719109399334842D29284A9295241595948236054A082AB0EAA2013D6DBD879BF5342AA3993A4CF9051325A8A541408292090400C7FB1E519FA2A25AE5856619983920024D9C8D407F38FAA84690751D5F3DEC07B9FCCC6315292262B224848D407B12778E33B90C6C5B6D5F96BFA7478A04DDC3626D73B76E9E90414849CC1D4D62FADAFFB83ABE913C0F0126E5DDF95D9A2788220842110006B0A201005AC7FC743FBE9175C2552D3500A920A8174A88D2DFBB1F488165C141FCA41717EA7C88B79C7C5C4F229A961DC432602344CD0EA4C2D0A48295A5C96712A4AD3B85055EC41DADB5A3643B1EC4AAD3C65844E97394858ABA6961492CC9135362D77B9E5AC6258A23BA9AE9606C5C58EA7705F560DB316D63524F0A843D2353E25E981C586E433567D4A6428F2D094CD3C52023A0D3BE9DB627DF7F5B3E26A8915381F0DD62E5833D5C39440CD6B96EF8DCF477B9B5DAF78EDCECF14A5E40A512925995B9E9AF4BF94663BAEFEBF48F34B12795316124BE6587D086FBF48EFE4212508B3002C3E9D1C7368459BBC5FF51E7AFDFB6917196125CB0D06C377844D98B52A5241BDF5E419FF005DF94562404FE5B6DA98453C45994773CB58D74FF89873BA7313711F95D935293EAFE4981B2F25E6A765D0E12A454AB55AAEA6610EB62C017251B9548513AB4E9DB611EE47FA7C70148A3E0D935EB97E2A89F2E524140007712E54E5282B7244D01B4D0F48F30B8867113160100A42947AE674BF2D9B5B1B6ED1AC53056865AE6274152494B5727949D6A4A51A8EEAD93AEE6C6EA23B47A8D3A522494CB400025212C2CCDCF4BDFF00BC6066667274606FE77789D4AD42D6B6F7EBFED126110510A001B8006F63BDB6BFE90810E08E61A36B4FE1E1F18AC39C25D55FE13B3E2BAE48651632A99AA612C513CF38E53F0954A69E48765E70ACFD8A2643E82A08D69499717E80C578D07908B71483A8DEFB7BEF1FA0EE12C7D84F18D1E5712612AD5371361FAB2133F2558A14FB351927E5E6ECEB4FA48712FA50B4282820B29D17D361DB9F46FBD638CBAB004B921C580FECD1DAA6EB52D28CA9D7961080DA9E0E00E14F293F7493A079964A4580B00A3BED1CB7F0E6916210A62CE1F7F97D625CD466CA00D54010031DCB8BFDDBA88C417895F8B1E49702593788ABF5CC4B213F9A73F4FA9C960EC094F9F969AABBF539995986693507D8967DC7A5E5197D4CCCBCB7101686C28F2CD8034D87247E126A9475CEE79DCE836E7EFE95C6514CA7B3117D7C9BD4307E863F39EE1AF31F317895F11ACBBCCBC635176BB8BF3033BA8B8B6649042993395965C769CD383CCE4B53244A9D6DD524297F0C905B48248D70F893C424C8ECD3880949294E1B5054B0CE8374A4B13FCEB64D8D8289170D17EE1796915492080730B36A4060E4793E81F9EB1FA7053D85CB25942D5AD6D4ACAB2AD5BF99A966907724DC8D36B9E9E91F29BDA75548A9C57129BE1635338D88DA6AC3316E5B01D3731B05463F832C0B30FE57BDBCC3E9FB5AD1CE70DD57B761F8EFFAC74225483357959DF6D72937D1F6E9E80697397A9D45B7F3DFE71407DE55B6E9DBE57FC7F3EBE916CAAFFBA5B460DCB53136278A6842108421084210842108421084210842108421084210842108421084210842108993A54AD0490AE52962C2F7D24DEFEC122F7F6B7A45CB099FF87AB44C37495841D6CE017D3CFDE244D59439B245AFCC373B6F6D74E66D1615E23DC5B49F075C2AE3FCD6626A5DBC4F3126E61FC172B30A08F8DACD50269C9750E00A71B5C999BF89416D0A512D0074DEE3D20F841ECC6A38DB8D30C5FE1953A9BF152664C640565928295CD5B16072A12B56AE74E4630BC771212A5AD94C729CA3472CC2CC2CEDE641F38C7F7F0CA70E4ACC9C2F9BBC7B66DCBAF10E6766B63FAFD1B0DD62B0CFC43F254095A748FC5B94F997F5BA96DD7662A124129D0121AD43CC6C3E9C383781306E1EE1FC2E9A4D3CB94A972501084A06601878CF86EB5125CDF4CB7023A6715AEEF262813E2510E59C5CED72036B6BB5D89D36E51470E34D32FAD33086957487D943AD6806E94A585DDB4A80000700BF4BF6B67E8912245929003B8B00A7F30FD3CA31E5E562029C10406705C6A1FD9F48FAA25006424E97AC494F38056956C2E8041081600694D8003A5A2298A0B0A01094B800336BD6DF3B9FAC52CC3A1F3D874DB48F873F467E698790660B4B7016398D80AD32CF022612126C2EA096C2556051BE9EA6244A94405CB2582C8DCDD9C33076D7D7CF5972CAD2E017059BAB3907D3AFD05BF372FE270E0AF0EF0F5C624866EE10A44BD270867A4A556BD59A636D2053958B6526251C9FA8CBB2072922ABFCC82CCA0436D491964F2357315A66CBA9A5C1A5F7EA405E662A0525F7B1046A092CEF1512D531335C9B6847EC6FE567D3578C0C70D3C48663F0A79A18533432D310D5E9556A3CFA5CA9309A84D2E4EB34D0B42BE0AACD15944DB2A4A2CA2F36E95AACB502A488E9CED13B3BC17B5DA2ADA1AAC3E9A689D22684AE64A4AA64B59493990A5A5C3DC162C4B1D4465F87629324196D30A7291BD95B31BB68CDEB60E1BF4A5E0238CDC0DC6A70F58433770CCC49B35B72972F2D8EA84CB9E7A262465A422A32F2A8202DC9144D22650D3CB432484B7F6635587CDB7C4FFC35D7701F18712F7744A95492EAE72E4A8206554952D6A429243A4023290E5D88700C76A6118D77E99633853B0D6C08DB9E85DDB5B45EECB3E5D970FDFECDE515360D82C364F90AD276495274A8004FB6DBC79E35F469A7A99B2169CAA4A8820F47BF3BB68DA18CF698F789045ADA6CE43BDBDAE2FAF58AA079B55F7DFF000E83FB7CE31FA8484CC2069EDA74FBF95EA492C0727F7789E2447108420ADDB206C6E77FA7EFDBD62AA842BF152C8D2CFEE7EFCDB918814EFD0254FD1C16F7FD23E7D4965BA3D4544836937CA947FED2D2811F203A8B7AF5DC1D8AEC61C7166119BFFDF69F7FFF008A1CFB35F95B68C4F15FFBC860C1DC3EACE34E572F668D487C2E2FFEBBE2CD03CECCC667CF00BE9A15F113009481B13BF7E84C7B2DF11CA95FF15E1B040FFF0067A8D86A481DE9773CEC0E9666BC76BF6761CA741767035D1FA79FF88CC3A93A075BD81ED6E9FBF48F2EB1663394DA15ADADD7972E9CA36165FE44F94489248B9F5FF11645000B0E5FBC57CBDFD3F589A2357FDB479FFF00E222B2112A11A86F8FA2A61EF116CD7F8A4287C3D3F0DCAB416A0A0CB7F0DAE5C36029574BAFB8E005174A557D453631F461F01E8454766B87CEA719A4CA9B366A94001734D4EFB87B252EDD23CB4E270B4CC9A4921C33E8D73AB585F5D4FEB852056E152C8D94ABA45C6C90026C37E9704FB5ED1B9F2ABA4D5CC9DDDAF3144C2820BB82ECDA6DE7BC60F48ACC955DCE67F4D3EC40A48DC88AC4CB5AEE90F157108196A4EA3DBEFE908A8A5A9296594A9B5CBAD84A9F66CA423E2125252B52C23587507514A9BD4012AF36E22789C860EF61CA38EE147407E4797DFB7AE453859F156E37B84593628F94B9E98B9BC3AC329699C338994C5768B26DA7492CC90A8AE7D68641012D37CA6D2DA0694A520DA1DF23AFCFF687E1D77B1E9616F9FDFCA2EDF31BF889FC4C330A82F501DCD795C3D24F4B99375541A0D1A4279D4A9050B509F95916266512412B4BB2CEA5E4B81200092A22A64A84C4CE4A43954B20381AB8DCE9AC4999216921405C313B3A6FAED63BEBEF186ECC2CCBC7D9AD89A7319665E2FAE63DC415175C7DFAEE21AD54EAB5F9571D24AE5E4AA35079D7DB92255CB54BA6650DFC39E572CA7CB16B33E5D052CD97395956A0B012937054AB5C7D91CAD1397365AA5F77FCC5218368C2EDA5BDB95E3315FC3FF9033F9C7C79615C58F49BCEE1FCAEA05671954A6CA52A949279B949FA5D34BA4AAC56E4EBF2A86DB692E3A0AD2EA921B05C4E8AFC61717D3E07D95E3A99F552E5FE2A44F904120AD484CB54D4A5201CC06748753072E1F6395F0B51CCFC44B594380336D72E3D1C0E6413D748FD0EA58ABEFA9455A8ABCD7D942FB6DF976B5AC7A6DF2C3C538DFF00B955D6AE4954C0AA9A8208D6F315CEFF00DFA391DE7492D4254BF0B0B72D585BD79FED1C85904EDE96FCCC6094C99A998553028073A91A72B16317048235163F5FBFBD629D8EABF6B9BFE000FCE21A90E429F98F3B9D3C837CCC4713452C2108421084210842108440903A9B4210041E97FC0FEB68316762DCF6844610888049B08E0902E610208EB0041D21108E610842108421084210842108440AD4D942D2D9513CE6B620795C975807A816D6A03CD6DF71B6E2FF004B228A68A144A98F55327212B961C162A606E189361AF40F1435CB08965FF294E63B1CC0B01EC1DF6F38D3C3F8A0F3927D998C94C91929C537212B2A8C5351924A9612F4F4FD46724980F1166CFC3A5B6267515142529BDEE081F473FE9C3C0387D3E094B8A55CA972EA57202BBC29752410A0438048EF12E92E7425CB061D41C4756095B1163A6BA69736D6E4BD86CF1B007F0D366050719786565452688B9555430756F1461BAFCBCA2521F91ADB7569BAB3827084A4EB7E9751905A57A94DADB75094A8A8148F5F2A27833E549A7F14B9210124386012FA300C19F9FD63AAAAA62953924E85403826C1F90BDF9799D4131B0C34FA145B0370B0AD2373AB47DE3D3600DC6FD77B036B45610B37CA03B3B9DC8DEDCCF96D6DA5AB29D1F9F4275DCFE91C852D035592A2ABDEC3E5EE40E9EFF58890145EE9037D4F3D989FDFE929692A660ED7D5B9347CC7275925C0B250A6D362DAD41255AAF7500090426C2E6F617173B8B4D989C892B749510E3A14870C4B6BC816717244474F2AE41B01A1E7A92CE03B5BA1EAD7D18FF8BBB1961D5D5786FC0CEADB7EB32CCE259D532563E2A5D970D092DBCB4121C2CA88202C02D9B1B288B18B752CA975B5193123DD49CDA90F606EE2FD18EFE6F15F2E5CB6770FA12D6035D1B5F73A794693201698E7B6EA14F3CAE5AE59492A536D9FEB2549D1B586C95157A6D1578CAB0FC16405E05304E9A43148046BAB93E77B9D40F3E16E2E0D9DBFBF97F8BDE33AFE045C6D4E70DDC51D172971254D3FF4D7399E56139E71F7969A66199E9971BA849559C973E65393B35229930B9665E712A9DBBA10DEB58D0BF8BAECB29F8AB822BF1AA697295898C3D73E7CB5A56A99316A081DDA08429399398B66284324DC1201CBB87B114226CA4155F380AB8649626E753A36E5D88B1263F429712C89979A61485A109974256DA8299529B68257CA522E85252A05374F955D52542C63E587B4BC1EBF01E2BAEA3A89264A935335013A394AD419AE188040E40477DE1539132421492E08076E5B0D869CB7B36B505C24156D6B0BFE9D3DAD1D775685A56952C315005BF5F5E5B45C0AAE07325FE67E67EF9453E6E9BFE5FAC524090358748473AC414404D8F53AADF808BCE132D3DE77930003F95D892DBB7420EACF66EB094952AC1CE520F47763F51BC7C1C4EFA65F0CD79C2A09535489E741BD800DCBB8A2A247A0DEC0827B46C376254D3311E36C26928D39E68AA9134A458E513439B1E874E42313C70192B0B5B0043004E97BBF262395F58D4B7C2957F113FC4D546C541FCD09E710E69235B6B9B994B6A04F40A536B1BEFE5DC0045FD71F89AAA12304E1DA252DA7CBE1DA24AD1C940CD7D35235B58FA34769F6673133CA3BA72CA0E0EDA077E4E35D6CC63316B3A80037363EDB903E91E6AE2293366A8A468B53FA98D8947E50FAFF0078A69040DFD7FC459A62160DD26C1B6D6F15C8DFD3EFE713417F9123706FEC3F68AD009D2112A39C8AE5F31FBC6B5BFC4959293D8578B9C0D9A4C53DD670FE62606A731519C505043B59A1D5AB2E3CA2A2AB95094764C7C82447BD9FE9C5C6D4B51D9DC8C297350152D4165C87509B2254B091AB5D0E7A5F58F3278BE95CACB06208D18D8A8D980F61FB46B57CEE5A83695EB4A755943B8E62BE43F1FD23D0B451A28A7CEC8434D98A592E2E4DDFCAC1BD6DA475A53CBC8953867516E7EEE77FF11CA26E807D6DFBFC445F29D7952E1BCDF99E9F7789F14E219AB37D1DFE675F6E5A73D842114D1CFE2903FA8741A7D6F0843F168E6BF6FEF1239D07CFFB18953A6AE5CB59964F785242403725C37CFEF588913133C94A7313637E4FE71C995A6CF4F3CCB124C97DF9871B6589746EB79E7561B69A4FA95AD4948EF73D7BC627553A6D252555762CB32A54B94B5669849484A743A9D0072C09DFCA3958795CD0A4A4963A1536AF63A077B6BD5A3F41CF012E08A7F864E1B99CC6C6545FE538E739C1AC4C2669A099C93A126589A7C8254429486A69A95969CD09504A8BBA88B931E0CFC7976F52B12C46AF86E96A52BA294A54840490C52A27328B7E6CC492333A8021240668ED7E1AA254B420E5736B5AD70C2F63943FA69B88CF280802C84942412024DEE3737EBBD89B91EC4478D756A93DF4C54850295A94B600B3A9449FAF93EF1D9D252532D20F9FD3E87D62316F9AAB126CFAB72FB689B08A098B0A7DF603975FF10844984210842108421084535024FDDBFBEAF4EFD47E1EF1588952B2A54A372013AB071F7FA4226009B5D23F1B9FD0FEB102BB80E01162C0B39FA5C75F9BC227D27FED3F844A3325B6A0F4FBB420411D411F3820CA53955883B39047A3B75D3A6F088454265D3AC7B86757D0DF4842E4F5378A79A84CB5654B33025B997FD1A108970842108421084210842108422520907D01246FE88BDFD8DFFE7AC5DF0341FF0075C396C1BF132EE6F70AFF00163E6D141884B0A92A24EC4F930219FADB6D4346887FC4CAFCEAF8AEC0ACAD0F3E0E07A5069B48251C81569CF8ED7E84CA73436AB850558820EF1F50FF00008B4FFC0E926BA33212942C921C20CB4E501CBB39BB753B3C748F1120898B4904D981D77E5D430058ED73AC73FF00877BC50F0FF0499C95BC98CE1AFBD49C96CE6A8D3A625EB69716E5170C632D4CD365E726DC1AD1292932CC9D2A56717A741E5BA5C17D4A3E97D1A02E6A948B8CAEE1DC11772FB696D35F4EBA9D2CE77BB82EDB10496F3DC1BFCAF1FA44E18C6341C634762B3862A74FA9D067A465A6E995B9175B7A5E7989C4F312A977104821614149D2075F58BA051D4BEBA13A91B9BF9368FE912F22B97CC7EF1D9DAA830F21B080A4AAC752549F30B6C4281DF7EBEB623D601B7246F6E63471BF9432AB97D22DD3886E21F2A7874CBEC519A19B18A6898530AE19A7CC4D4F4D55A65B61E9D421B71C3234F0ABA9C987F9605900281D3BEFBF1356E05D8DEDCF466DF6B368DEB13A58660D7724DFC98F46F9C7E54FE2ABC74563C4178B8C5B9CAE4C4E1C2F4F666F0F604919A52912B4DC274F9A3F04B6D92797F15556D4DA92BB29C713284956D78A39A3327762E0B6CEDABE8F7EB6E6D13D80B0167D99BCFEEF18D98B7AE4289203100D8E96F93F56F9168E79F97DEB1DB702E239CC278AB0EE2191506EA940AE48D4E5A6E59CD0F32A62690FB3A948526CA4B2850513E9B82230FE3AC1C62DC3B5D4EA405A0D3CC95312D981CD2D41208B970BCA459EDAC5561072553B16CCE1DEEC6DD3426F1FA9670479B433BB85CC94CC433089B7EB781E88A9E792A0B71CA8374E956E78BAA1725C3321C2A5124924F61B7CB97C597670AC1F8EB1298B9441975B54E5807095AC39B6B6B0DFD9F60700A90A9090EF9909239BEA396D6B72D62EC9E074FB0EBF88B468662E3255996E5921803B36B19425CA8747FBF7312B3D07C8FEB16B8897A0F3FD0C15D4FCCFEB08893A0F21F48A6BE83E7FBFDFB45DA816020A7FF26EBCFDAFF3B17885133F8D979DB7D4027C8EBF28F38CD99844965C63A9D53A5A12583710CD05DED65314F98706E3A5C8F7B7422F1B65F0B346A99DA9614B667EEBAFF391B06BFCF5D34C538AAE84BF2D1CF3BDC7A9E46FCE3564F08C6D7319759C5592D8D355CD5AC4B7340009129301D1BDAE47FEAEFEA3574F5F4DBE2CD229EBF0B4920146074A0BB6A0CD2DE77F33B4769763F2DF2962F98DDDCB59DF51D7E96B465F7A479C33D6A54E98C4B672D761AEB72DE87CA362C060072845BA6AD4545F4FD9C7BC57A3F2F9FF008FD21125C91724FADB7FBF78AD46A7CBF5108E226C7C1F19DE0B4F18BC29D79FC3B26A99CC0CA8969FC4185A4DA6C7C74EAE5A5933B51969274243F3C27A5D86E5D896438EA4BFCC096C294ABEE1FC0D76D5FF0012C5E870C9F53929E64C44B9C1D4A025AB2A145AE73252E52C1C1D2E43F9CDC4F499D2BD0EA43D8EBA1716723A0D06B1F9C756E9351A2562A547A94B38C4DD2661EE636F4B19679A75A714C3B2B30D290D943CDB8C28A9B52526CB0A293AAE7E8338771F18DD248A90B42C1968216852568525690A0A4A92485020D8E8085070416EA1AA94254D291D4EE2DB38B7A7468F9BAD164137E6BE0ACA7A048476D3DAFABD3AFC84675217E1D5BCF4D8EA7D3974114D118826ADCB69B39B020BB5CDAF77E50D611144A34A765003910EDD1DE293854748483E5209B5B7BFEBD7A7D7B4239FC29FEBF94576D066661A4061B702BC802DE2CA12A282038541C6C158EA946A3AD5646837D3168C571397858913E6A4A922602A00151290E48600DB726CC05CB457E1F4C04E2E41195EE05AE2FB7DED1B217826F852D57883C6949E2033A69150A6654E079E6E76834DABC9AE5063AA8CA4C85CA2D2C3ED365C939598487C2ACDB534D4B00A53C976CBD09F8C6F8A6C1386B876AF0AC26B244BAD4C832E68913524A49967C2A54B252E34201707C2A014E233AC2F0E4CCC85B706E350DABB3EDD5F7DA37B6A733234A97A653A932865A974F9344B4AB01BD12F2ADB4D169A6A598B06996DA42434DA1A4A52840094009000F99DED47B40A8E38C5EAEAE6CF54D98B9F3157249578CB00EEE436D6DA3B3F0CA04CB976172035C83622F6B8B73D343ABC72DB37403A8AAE546E7DD6A36DFD2F6FA475685AD28F182936B10C6C00B69A90EDD7945F48CB6E407D044F14D3261248D411BFCBD5BEBCA38844984210842108421084210844D4C89AABA65A8BF263FAC482AB9015BD839DEFA74FF0F103A7FA9447A5B56FF86DB7E31552F0CAC9BF92513CB5BF93031095582893AB0777B7CC40AD29BA82D4A237B1D76E9EE7FCEF157FF1DC448FFB0CFD2EDCF43B7AC449582A00A89726D7EBE8D1444E952F416C01EB6FC2FF00BEA773D224AF01AE95732D7A12E34F7D74E6044C0800B827CB6DFF00B7B47209BF603E5B451AE8EA2590152D449BFDD8446CDCFD4BFD62112549524B28107AC2110C210842108421084210842108A0F95843AA4B6A559971B4DBA5D6855D42DBDD3AB6575DAC3A45D30EA8EE6B284BB659F2D4DB125635B7D878A7AB4A4C85DC151492C5EC0386E4C777E76BC69B1FC509960ED371AE46E67C934EA64AA987BFD34FCDE93A04E07A7D7A1C73BA87392121449E9DA3E913E0031C54EE13FC30983FFC24B9A849672651CD30870EFDDA4826D61B474BF11A1A6662C0BA92E0B7E6240172DA9BB967363A46A4295292CA5B6DD1F60F1967E592E061B525243EA7004A9096DC1CC2B4BA08536AF3852542F1EB360159DF216730FF00B761ADDBAF37FEF1D753D0339F50390626C3561A12DE4F1980E0BFC7038EBE09E52570F609CC16730B064AF290CE0CC7D2D51C45252D2ACE94A25E5AA3CA7A6E59B4A404A3913C8E5DBCA5317DCE797F9FF3B3696BC53F76798E9F7B7CE32A158FE2DBE2DA7B0F3F4AA4E45E50D0F104D36A73FD4F21FEAE985D39E29D3732957AC4D49385253CCD2655C45CD88B6C78CEAE9ED1CF7679C60AB8BEF123E2C78DDABBF53CEECC7A857686E2E615298629B309A761A6CBE525E0F50E404B493E404B496D5372CEA9002B96A054BD52E62CB82C1DBEF7B7EBE91125395F7FBFBF68B0848242B5F976404A13B22CDEA0D809161A5B0B5040B79352B4D813112015B01FCCCFAB72EACCEC62284550A64B1B3900DEC03B1D3FC984519770B538D36CB652E38A75C538AD92B215B7FF0061BD937B800D858136B1932E761F8BCB9803242C39E63333685C73F23D62A685C4E770CFCBAB17B6ADE6F1FA2C7804623A9E20F0EEC0E8A8AD6E2A8789314484B2944A9425FF009ED40B6D82493CB69284A1A47DC6D090940005A3E75FE3EA5D1D0718574B960054C4A66B96752A6CACEA249BB924EB772EE63B77872A9D0904B949200B80CE40D98581DFDA336C5DE6300AB651036B5AFBFF00C9B5FDFAC78F58DCB51AC3340F0177D2CF73F63AEDAF66493992140100A47B80C47AEADB72788B3D07C8FEB16688D7A0F3FD0C15D4FCCFEB08893A0F21F488100F500FCE2A695653350068542DD4106FBE8229262F254A03B38B0EB71F53AF9DE2DC78BBAF35863863CF4ADB8B4B224B2C7182D2E93A0A15FC9274A4A542C52AB8D88208EA237BBE12E93BCED27095650A51128804ED98ECFC8FCF4DE31AE23567C8356171D4960EFADF7D9F5168D797C2429625385F9FAF21BF357331F13CFB64A767105BA579F71650BEE09B9BEFD0C6FF007C60854AC4E8C2CBB61D212E48B001561FFC4BB0BEBC8BC774763D2925034040BF9B06D762CCC341B464F96D940D4E5C4ADEE1409D7A8F6B83ABFCFE51E7F4CA0CE55307F3171AB17F3BD83F9F222D1DF4410483CFCADB6F04951173D2FE53B6E9EC76EA4F7277F58A199879672837D1F5E5CADCCBBEDB3456205B5BEEC5DBD34F567FA09A2827D1F732F3170A1ABE87C86DD7945721DF6D3E4E3D8C228226C656D72C971B5B4E279894AD2B94D684AC4994D890842925B98429775A913699842B5149051E58E9EECF38EF12E13C564E274C90264A525410EA09749CCE7C43981AB5AF1A1F5D86CBAEFCE5409724872E79B696E8DA078D5BFC5D7C0FDCCE198C499F1C29521893C67301754C5196B2A24E4E4AB0EB616F3D37410F250F9A8CE9D4876584CBADEA4325A9649592BF71FE167E35E92AB06A4C2B8AE64BA6026A2409A939D7265B240999495A94847894A968198870963AF5963DC348913C99254A195C0F2727A924EDA731BC69B79959499899495B9EC3D989846B784ABB26E29B76955BA45464A765032A521C4BAE3ECB4CBC1D5001A7194E83A092557047ACBC0BDA3708F14534B9B271591512D60144E92B4B292A1E152904954B2774CC0141AE2E63119D86CC960F8482350AB106FA73F47EBD3CD94A2969978B6B6D95FDE71652BF9E94A3CC3BECABC65B8AD5D32539B0F9F26706F0E69A87E8E1C5BA86D6E7959A626A50E421EE6CD701C5FE7FAC5343E975CD0DA54A07A1510DABD0F917659DC8D80FCE2D5438AD4075622AA7952C6AA0B48B737CC76BE9AC4E96BAB5003BA6B13A3EFD2FE5E7EB1EB796B9399A19AB5B630FE5E607C438C6A736FB12C893A2D16A53AEA153074A16EBB2EC38D4B361446A71FD2D907EF01BC63DC5BDA870870CD2AE7D562D4B4E10852D4B9F3A5A41081E2EED24854D2F6640262E12A4CE59F12147664A6F7BBBB3245AEFCB9C6D27E1C5FC3CF8A5AAE61CCDAE31E5D990A7D3DC62B74ACAA6A6A5549AA21452A63FD4EF4BADC9944AB4DB81D725A56664A67E2D2CA564B21E6D5E697C47FC71D151E0B3F0FE0D9D22AEA565520D4294A44C424B85CC9212A4292E4300B05412A215768CB700C113573C89E0A424666001DC1651BF319ACCE1D9AD1B75618C1786B085028F84306D26468986282869990A4D2A59A96939697611A589546848714DB36400E2D6A7DCD00BCEBAA52CABC38ED67B4CC738CABEAEAB10AEA851A852D4A4898A520151777255D45C926F1D8B478549A420A545446CD61AB5F5B0D198748EEC6E41049B137B580B77B0DBA6DDEF1AEB242535499A19665CC0A214FE23989F2D4B10DA7CAF92E7996059D830F2F705FEF7B40000580007A0E9BEE7F3DE2662154AA8A954CC89960B78123C36003B6DA3DB9C56CB59989CC753F7B5A2316F25EE6238421084210842108828D813FBEB08453D67D07E7FE610370473895D984B496DCD2A754EB886D1288F2CD285F438E8D434F2839BA55A6DA48B92482737E1DA2ABAD9F224A64A0A56A4A4A9419C1DC5C10DBB8726EFB45B27AA6A3358101D947460AB037D483AE8FE60463EF8B5F13AE153835A8AF0DE6A62C9D99C70C3466DEC1F44A3D526E78CABA9E6CA244F33293324CCC2D97192B43CAF315A9484845ADE84F62DF09D89768D488AD934ABEE1D295CE05089409DB3AFC36D0906C436B18AE23C41328D5972A09B96D4B790FD7CDF718A299FE270E1755509C9597C9FCCA6E9EDCCB8C4BCE3FA01525B274B8F5A4529425D2362528B056E7BC6D9A3FD3831A5D30994C844E51979D91514F30B11A242145CD81B5C69B30C7BFE71588999532527501D2751D490C1DEFCDB945E2F0E1E39FC1671158970F608957B16E0EC5F89A759A3D1A8D55A44F4E2AA15498712CB01AA84AD3448B52CA7149054F39E54855D63631D15DA5FC10716F06E1B5B8A4CA296BA3A09626542D351216A92145921684ACA8172032803BC5DE8B8C2AAA16997324A1256AF0B2560DB5B92D762DA8EAE1E333C8750B65B75B55C38D21C483D6CB485209037DC11D3DFE51E747196152B87AA66D3D4251992A524D8120E80009BB3B73E42FA677433D7529CCB0DB962086B3DF66F4BC4CDA8A9373D6FE96FED1D4B5D3A54E980CA0C2E5FCFD2DE515CB00161CBDF5BC4F14510C2108421084210842108421100A5A15AC28D82569D040D275A0A2E76B929D5A86FD40BDC6D173C364A674E419812132CA54145C174DC5C96B90367B96DE2867294B0A9792FFD43467B0D6F76B1F48C1F78F5F0EF3B9DFC06E28ADD225BE3ABF93B5293C692879497669FA722A52A6AADD929E616E5A41334F0E4849484DDC2537BFB3BF00BDAB228F1AC3B87A764FC3CDFFA2CC1694AD26A11DC8512A2C120AC28822E1F78C131FC1E5CC96B9854429F336E18B91A1366DB4F211F9DCBAC242E612A09979D9598026549492DB93330CB40B684B8569525B975B24A55AACFF302AE9F20F7DE9D72B0EA5A09D44BEFA5D4651395981091676236D4BF50C747EA1C425A244E0906D99CBED7F204B69BFED1B9E625CB90A08D04364B49575DCA5BD29BEE7A01197C9553CE9456898ACCC6C49D586BEADC9FD2F4E0CBBF8AFB6972C3CDDEDECD122920B61B0549B1F2AC13A80B92527512160DFF00AC28FBC5A26D55489FDCCB4B8248CDEAD7BBFAEFCE39083C99CFCF77E5BFB7510D3A55ADB3CB2400BD0000BB5EC4A6DA41DCDCA40BF7BC5C66CAA944B96BCA08502544DEC1BAF2EBF38854876771CA2A95950B102FFF00777F7DBA0FA0113A9E7A12DDE1CAC43BB59B4170DEEF10641CCC4915E2BA9588497B101D880E376D7D7EB0C82FAE85B4D768AB2D2F35373B66D242255B6420E9014E3AFA9012C8240BA8F994948DF42557B9DE302C4EB2761B4F88CC9A909935256524D9D25CBDCB3B746773A3C4FA04E79AC4DED61700F98040F2D79E91FA49F823E5954B2BFC3F32A29959977A5EA388BF9A62979B79010932B5B9F7EA54E7191A52A2DBB2738DAC296544820831F389FEA0F8C48ACE28AEACA69C954D44C327202480992F2D25401B2B2A466BB66D0691DB3C3F4BDDA50D7719893CF52C5F9D9AEDB978CB7BC84EA42526C13E9FD574926F7EFBFF009B9E9E541AB9955493953929CE836B3120B7CB571EB1D8D4F3660484148621DCEB6D0EDAE9EA2228251D3DC0BFA1B1FD62D315840218C0EE49F584722C00E501BAAD6DB6DFF5FDDBD62A29C01325AB56580DB17205F7DF6222DB5672CF42F7091F57F2D631DDE2B5881FC33C077105506356B5E0CAA4928A090AE5CE484DB2BB58EC3492493716EA0DE3D1AF833A3FC4769FC3632002754D1CB3624655CD0920F201F5F78C6F1D39D2A51B1082433D9873DBD75D9A30BBC26E63CB70EDE1A985B3326685375896A1D0F106329C969242DC79C2A69B5143896415F2B4C9750028951F30DADE9A76C9C0187768DC65418355D4AA52E7CB954D4E73A1092B2B284E752C654A493724861BDA3B3FB3BC5E6E154FDE225A4E59654429CD807B3107E7A39E8395C39F8B470DB9F330CE1AADCF1CBEC6ABE4BA9A3D7E61B91A24E33A948725E42B73896E9EED41E213C867E35C537A55CD695AD24F4F71B7C1DF1070F522AB30F9532B29C67C93259CEACB2C02573252495C9410A012A5848532B29394B64D23B52A85D59933A5CB969CF95C8617533667B91A101C8B68E2326D4D9D91AAC93753A54EB352A63EB52999B61412C960E92DE9796794E2403FFBC825A58DD048063543887B3FC730054C159453529964824CB2EE97D181049FB78EECE1FC670DC569D33573D285901C0367DDC392D71CC5F4E7CC2928365EAD4BF3B45B42DE60B7DCAA71B0A96E66E9B36161646A201D2AB75657896A4AE5AD25265AC2559ACA7215A03729196E4020167D445FD13654EA85CAA7216424A831770E3EC060E1DB94422D49A5A32F9D6A4F2BB39B5B61BDA296A17884A2ACB252520EFC9DBAF22D73FA1CB602803E9B9B1FD8FA46A6D64D452CB79440531218F4D2DCD83031A7250A7D07BE9D03F94533A4297B208294801C24DAC4EA2C1494943C41B15B85C6EDA6C8D8DF20E14E29ACC347E2115B364290B7C89594E801D0697DCF2BBDE282AF0E4D49CC407367B3867B925DC17D031FA45B2E737077C35F10D28FB39B394584714B9308D2B9FA9C9BA8AB85EFA5D13F497E43594151524381609FBC15B46D8702FC6063BC1A6549958A546594438EF96C72B657014C77D45BD62C955C3F2D600CA0A8001C0B3BE9CFFB0DF58C5E639FE1DFE00714CFFC7D2A4F30F09A9D5A9C72530ED7294892694A37B36D5628D545948EC0B86DEA7BED0E0FFEA498E224A51515899C84801495860C35BA0853F47663CDA2C53B85252941425B39008FA1BEADB802DBB473B017F0F9787EE089A95AACF61BC758EAA52EB4AF4629C414CF82514907ED19A452692B50240B84B80DAFB826E22C73FD4B2BEAA96653535404050621014496046A4957931E479454CAE1496E3F86E43ED6D8900581F36F48CA364FF0AB9059094D12994795183704BA9535CC99A6D3D7333F369B12E73A76A8F4FB892955ADCA2DF4BA6C363A8FDA1FC59F1071AAE6CA4E275094AF3040EF941290A3A32944070C76BEBB45C6470DCB46881A07B0D5EDA7AFF68B802D2FEDD209534FAD243456A3CB1637B2D454A091D02104277164EDB6AF625C4D8ACC9F32AEAABE6CF4CDCC42153338751241035D3A168BB52E168A45664245C312CCEC1B7E6DF3F6AEDA1B6980CB292D0B82AE8A277B904EDB1DFDF7EB7DE310AEC56755921CB1249725F4D413CCECDA5B945C04BD741E9AF589A2D928B2C1FAEFA3F2EA6F0C8798DDFA72F3F942139414B2445520327D6DF21FA4225C47084210842108421105024103F7BC2114B42BD3F31FE61083ACB730565C4A94E725B61050AD0E369BA1C5AD2A208079884F404907E5191617C4157854E91340CA996458A487095066D1DD3A9B802C766A59F2CA9252DE139945408B924F858F42EFA3DB78C50788D7856E54F1F5444D5A6E69583B37A954D759A256E4DC684B54912439524DD590A4296F3AF21B64175B7594A13E45242AE63D45F857F8B64F079A7A2A89C9974CA64CF91312F2D76CA490AFCA46A086F173DFAF71BA0330AD4525D2ECC2EDA9D3E9FB469FD8E7C0AF8F9C258F5FC2329978CD729F3B53989495C4D4F54C2A98242EB4B737373A669E91616E369490970A097141B480B526DEC2601F1DFD99D360495AAA64C89F2E9100CB992BBE54C9A000532CCB0960A21C12E52EE7478C1E561D52AAA00CBCC1C80C72867B6A7ABB0DF4DE3646F0AFF050C37C244DD1F3A73C5F5E31CDC4B0918770D38BA72F0EE169871252DD4DD522594F4CCCCB2DC53C1B44EA14548000B98F3ABE27FE37F0FE25A2ADA0C365CA954F39535FBBCE833DC14A7BD656553302D9585890EE6332C3F0E29521653704036040075037F5DB7E51B0BA5A7D26CE0474B59B1645EE41D092A25290774824D93606F1E2F717F14CFE2CC5275490C17354A4A459DDC8275007A8FD23B0A8101094A5CB300AE570496D76D6F7BC5740201BFAFF0088C4A7D3AE9CA44CD4876E9B7AEAFE91725104DB60DFAFEB13453C43084210842108421084210844149252481B7FBC5DCABB8A24292D9D60070EFB820FD7E7B44195198BBB9171E96FDCF9931D4B17E12A563AC2F88F05D769ED5528D8BA8D52C3352937101D4993AFCA3D4A98982D5895FC1B336B9A510086C37AD5B24DB607E1C78FAA784B8C28EA3BF989949A992ACD988CACA4D9DD9833F4B748B1E37202E4A99394906E45896DCEC1474B74D63F324F11FE103177075C4AE60E02A9D366938597589BA9E0F9F32CA2C55E8F3CF2A68CD4BBC8406DC4C9256ECB39A54794995B28274C7D47F621DA8E1DC75C21413855A274F14E844F42541A52C20250487CCD3192CA2594B2402EE0741E39473133D6A53B0248E44B9D0B5F6075B73DF1FE494B41F5A56860EC1E5A4A5B27D02CD9255EC0DFA6DB8BED0E01202E43953BBD891A37E9ABED7BC63D24ACA838043E8075F7F4D87A4127500AB11717B28107EA0EE3FC6F1C57CF9545519D5600B12A673E7EDA69660F17695977019C00FA91E56B866D1C4462E1271DA5A99252328290407617E9B33F43E711D56564B10E5C103A35C97DDFFB59E204D85C02AF6482547E406E62CB5089B5330094EC5F4EBA7D1F52DCAF14512ADC4A0849D4A511750424ACB63D5D09BF2C0E84AAD6317BC33009D33C539797437394902E6C4FCECDC85E1F7F6378BE2F0FAE183147167C4F658E55D229D3935439EABCBCCE2BA9B2D2BF97D268ACA933E2A53B3A50A979748430991650F2D3CDF8CBA3514DE3A13E297B44C1F81F826AE749ABA693574943313290B502BA8A82912CA72A5416C94A96A54C072A16129241501176C36816A9C8284AC85AC6637602E75D1EC3ADC98FD3DF2EF03D172D303E14C038740146C214692A053BECF9444A52D8664E593A6C9D484B2C2436E81A5D400E2494A847CA476E1DA2CDE32E22AFEFE7F7AF5339CA959B55AB5724BF33A3B1B5E3BAB04A40844BCE360FCB42FA33BEFAF21667EE2A5152C13D0DFB5B7DFF007D7E5B46B55584C9742000958771AE876EA7F5EAD97A5294A48000200039FBDB4601F95A2316E8E610844A080E01DC807E809BFE83E71532A5A8A52BD122624BE80870087FD22DB565A7241D0A43742E6E796C1F67E518E7F16AA62AA9C02710EC042D7A304556642504851F87A74E2EFB5CD811626DD2FF005F4F7E0895295DA0F0FCD74832E752AC28EA32CC05FA806E47B5DE2C38A4BCE93ABE52006D77F3DBC8C629F80EA3D1F327801CBEC2755690BA5E22C195BC355965E097528E66A42404281BA8A660957A022E3711BD3DB9712AF867B48C2F24D3965AA9D454090E0CD2A2C431B696B87B68F1D8BC1D4A55484B0BCAF3FE50E35D4B7AF9C599F864704BC31E786767125E1CFC4FE194D3F15D36AB338DF26F3370EBCE51B1CCA2EA4B9B96A8D3999E78CC5366A59AF83A53B4FD14D002CCC84A965474FA6BD9CF13E17C71C3F830553C9577D4C9919D490A2B992908CF9C29C2923BD162092FD63A2F8F311A9C22A67996149289854A0C6C924DFA3B10F66234DA2E5B357C377C4FFC37AA350C53C36632A871479234775D989AC215895157C40C52412A217214F32F516ECC35A50EA59436A372DA41168B0F695F0D9C318FD1CD51A3972D73659095C84A03ACDCAA6A4A54480ECD2F2EB6BC41C13DAC56534D4CA993D40121242892DD1DEDC9C9D5ADB470387FF151C99CC6AAAF04E6F49CE641665B73424A670963075548A6393E85969D4306B0D30FB331CDD9A69734ABA0B9E4569BA7CE8ED4FE0DD5414B515B83D2CCA9525456A549979B2CA2EEB58427C21C8776CA4DF68DA0E11ED5A9A4D4226D54E43A9012332AE49666D01203BB12D1946959C969F625E6A45D4CE49CDB297E52765487E4E6D95A42D2ECB4CB454CBED9410A0A6D4A0526F78D17E32EC531EC0F391226808249050A60068E1AFE7BEC63BF708E34C1F18400552D456029C1BF2D7770496F72D196F56A005C5813637EA2FEFF002B75E97F78F2FF00BF993484AD5981617B8B9E5D4DBF78D4488800D8A813D3A9B1FAF5FAFCE26FE0EA08FE1E86CEE75D1AD6279743711C15006FF7F7F7A44E48B580B6FF005FDFD7DA241A59E8254BDAC6F61EC7A72F9C4A52C906CFC9F5E8DA37CFCCC4B157227CA9285A095124105859CF2FA17D625162A00A5EC5891A736B7907B4352D3600FCEE3A0DB6FF001140996262980B9DDFE6747FB3157E511BDCF9AE6FD6DB7EFF007BC542A8E721214901B517B8DEE1DC5F43F28E09035DE224240D893F3FF88905537F2CC2583100927D6E7605A380A074E46DBEDE9102A27A988529E43EFD62288421084210842108421084210842108401620F22F08858837DAC45AFB8BEFF0081F9C5DE7D7D3CFA79728CA01684A428817B0E7E8393B728E087B1D220A783435590413A4828FB4EFB2564DD23AF4045C13EC6F5C3D5829495C998B96A076535F9DF62CFCB5EB14D32825D4A8E61B38F5B173AEB76FD045129426CB4B8A652E11A94A75A78EE7A8694DEB27B5C2869EB6DB7CB6571EE2341572CCCAA9CB9290429099854406203A6F616B91ABB6D16D9983D3A1D484AB324DD59084F26CDA0B6FBF48E616C294DB6D15B8950F34CCC6C117EA520040001B91DAC7F1C7788B8B24E34145656493FCCF9B9105246DD46910CBA54A41394EE410356B81A073EFCDB58908D248B836245C743636B8EBB18C2513128585CB05C5C3FD6DA5BD045D25BA40F0B307F7177EBE83D2D1088EA6A1550A0A50660DABBF58A849704B35FF4108A688A10842108421084210842108AA366EE6F7FE9F7215F5BDBAC459D73552E493E104240BFF35AFEF1689954B4D6196904861AF367F70FF62380B4AB5071B5AD971BD7F6C9170DB4B494CC03B0DDD675B6826D65A8102E008ECFA3A218261B2713933009F90AC31F1020B330F1176E9C9CB98AB9D2FBF940292E48FCBB96B821B4BECFB5B48C5FF8A07876E1CE3DF261747A77C251F3430C494F4CE01C5AE30D26EF3685CCB5419F5108E70A94E7325D37710A099B09483617F4BBE0BFE21EA306AC914788554B553852254FA69F34A04D94FE20925432CC00932D45C05105493A475DE3B8289889C424E662A0407BB72BDB63CC0239C7E773C4170E9999C3AE61D7F02666E15AAD0ABB419B5CA06A75975BA655D08511F1D241C69BBA1763A4A5C5825205C902FEF0F673DA4E1D8D5352CFA0C4A454C89E80A5C91302A6D292E04B9A42AF6D159520DEDBC7594DA0992CA82E5292468426CA0D7205B936A19A3C2086C121A56B6C7DD56C6FEBD36D8DC0B6D611DCF5144316969992D59B3872411F2D5AF700DB7E71679EB9921C242AC1CD8F32FAEFB9F4F388458EB7089D864C91E2244E511AF222E46C2FBEBA69789722A0CE2A05DD237DFA8FDB5815251E6585148DCE8FBDF4D8F7FCBD3AC6474F3A451D377F3572D3912E5C806C073D469A6CCDAC5531E47DA2E5F86BE14739F8A6C7D48C0394584676B188AA6F21137596D879EA5536556A4A54ECEF2D3A129495249529D6FEE9EB1D51C69DB4E19C274F3E754D7C8921085F75244C4A66CF0917297242522DE229507291C8C7294CC2B0132D6A63E2212484E9AB0D6FFDC47E82BE17DE1B181B80CCA992A6CECBCBD7339F1253E5959858950CB6A975CF3896E6DFA3D1D612B532CC93C85B49D2FBAAE5336263C06F8AAF8A5AFE3CE22E20C264D514D153CF9D4B4B284C272CA4A949054A7654D504833141294A9574A520B0EE7C07089628A9E6AD394A900ACA92CC54D662F606D72FF58CAACA25E537A9F5A14B5BAF14253FFE8CAF315F08CAF7BEB6A5CA1B513624A6E6C498F27B1FA95AF139D5014A2A5A8A9C97759FCC5F912F66701B522D9CC893DC2084A4F8776B1762E07CAEF7D2E62B9EA7D8F716FAFE7FAC5A14B54E4952B54806C6D72079EFAF95F6888542BBC09205F93B37CEFF007A4224C5642108A4BD9615E89B5BEA7BFE517E95252707993AC1489B6D5D985EDD4DCC59EB0955420000800BB6BA1F36DB945B1F19185D18F3862CF4C26E341D156CB3C5B2EDA0DD5F6AAA2CE2506D6EA952AE36B9ED78DD7F82EC7D5238FB0E42E677413918A8E50E09667F77162FEB141529485241205C063B13E6DBDBAC6BF7E129585CFF000C350C273CE10EE1BCC7C534596BDEED30F4BD21A964007A69710F10361B9B46FF007C53CA988E2DC36BD39CCAFC152CF3318E44925648CDA380906E37D2EC7B6B80A5CA994E5208538524656760030D4D8BB07FF1E3FC7B7FA8784FE27F873E3FF2E82E59DC2D8A6428F986994D4DB550C3689C9479972683646AE6FF00EBAEA5EA074F4EB1B55F08FDA952564B93844E9C094210BA74A882A13A58032203B933C14E66FF00DB1A18EAFED5F84FBE4CE9C99533553A80B105DB316360C598DFADA3786CAEC798573AB2D709668E1826B386F3070CD2711D01A6D697C34C54A5B9BADD61A482E22CA4825D2A6CEE0245C83E9A54572B18A394241CC952100AC1722DB9761724E839EC23557FDBA661F50B57E42144B17177D1B9DAFD4B726B33E2F3C26F84AE32E99333198F9754DA763454B39F0B8F30B4A4AD1B13484E68296C1718967251C6895171C4AE4FE216E36DE99845961568A8E0FA7AA90A156A4AB30BA4D8286FD141C5C69177A0C6AB04D080B5A128B2495101B40731E5BDF7D7531AD966FF00855F89B78794D4FE2CE157164D712591F2CFB9333197F58979C62B52122D953E52E48B9393752AABAD3295A12E538C83257650674A82474871DF6118363B267A974F2DE6053CC4CA493F9491E1486624016008B1360D1D9FC3FDA1D6616B423BF24A4A6C261360402D7B816E81DA36970B0E0BF51736B811F19270C548398A81662C1CDF63E91DAD348A44E6512A0C4F88B9B726B74D479444003A472B98B7001600306DFEFF00789126AC55DF500D9FA0E85B5D79FBC22DF316A50B926ED7DEC7DF58AC47E61D5C1F68A5A95AFA9FBDEBEF1262730E5D3D394558E4122E0907982D0844466CC362B57B984220D75842108421084210842108421084210842108421121413FD47ADEDE9F9C4CEECB02FAF4DF71AFDDE11384A48DEDB6DD3F41BD81EFF00217BED11266AE592125BFF008F87F7D6205120DB46E9ADFA444B681B8293ED6FD05FAFD077809AA9C72292A24B33BEA3A8F5DDB94490A529652AB824020682C35D351CFD22112949292410C444FC89E5F33FBC22296C1697EBF43114226545D6080DE116F530844884210842108421084210842108AD9011950A23C40920DF991E9F2880CB41254521CEA5AFA37D2115C6AA6A91DDAA6ACA013E17253A9DB4BC4712AD295A14DAD3ADB50214DDF485023717EC4F4BDAE3AC5C309C7AB303A9975745553A4194B4A8892A52335C5AC3789532521695664A4B8BB87FBDFD7CCC5947157C0B70E9C6261B98C339D18229F539E2D2DAA4D6E96CB5275CA629C49087199B53531CE71B590B49537D411BDE37D3B07F8B6C5783AB69E6CDC5AAA494E5412A9C4E64064A810A0DA58BEA395E31DC470B953A5A80932D9812C9D3AB83AF9EF68D7133C7F862B11CBD66766320F34DB768CF38E392B48C6549E5CDC9B0BB14B0FD49AA830D4C2D2755DC4C9B234148E5DEE4FAA9C19FEA19814BA4922A6A64A96A48CC944C4A19400723366673720EE491AC75E627C36A9A099681BECE0F506DD5AC40DEC62D5695FC357C5EBF5032F3F8EF02C8529974DE716E19E6DA0A22EAE5227258A0D920F99D5EAFFC74DCE59897FA84F074C4833F3CD50BA422B65200D95632176D34237E6D168A4E0AA89EB51019AF74B3B6BCB5E7BDEC4EB7F7C3B7F0CFE04A55529F50E21333EA38CE5E5E61A79CA260B658A6CA4E2104A972AF3D30BAB1085EC09B0D81D85E3A578DBFD43B095C89F230BA844A2B4A9328998264F4280B14AD265A7375C85AF6D232391C14A9490B9CC1203A89B002D7BE83A1E91B1C70F3C2FE4270C186E5B0BE47E5A5130651E4DB44BCC54694D34E57A7A61A4848555269C654A528D9657A10D0D46F616B0F353B5EF8B3C4F8B6B67CD18AD4CC5CE2B7577A5FC44DD810003C872D498C969B85E44801265A524070E3563AF9680E8CEF7BC5C6151528ACECA512B3616F32AF73F3DC827AC694E298DCFC56AAA2BA64D98A5542CCC2A52892EA24DC9B9D5B5668CC69E9D12252258481912000341603991B442317AB5672E4BBAAC7D0DBADCEBBC544228E21C8905D838D0C21114210882BA1F91FD22ED4931E47764B8CDF94E9721891BD87F78A09C926A90C01F0871FFDAE7CCEF1D76BF4D6EB545ACD21D46B6AA74D9D91712521414899616D2C106E370A3D7EBDE3613B1CAD386F13618A92B5495F7F21D48394B158B588F913A9BE8F8DF1385A120A14126CED622F7BEF6DEDEB1A9578653FFE93CD0E2E326DF0A61CC1D981375644B2C90B0AA83B361D2949B69D2DC9B4761717BF78F667E2150715EC9302C6972D0AA89B83D1AFBF09F190813014855F70097E7E463B03B259C42BBB5ACADA6B10A3700E523FCF4E8E3235C4C64DD233D724F1B65B55A579CDE25A04CBD2EC5925725354C61D32AB4950514EA54DAAC12124E9EA2D78D5BF878E3D9F87713D11A7A8549994D548292936252B48D2DAB1F7023B8F8D30F935186ACF72839A592CA482E00279037D2FAB8023D9BF86DB8A7ABE37C82C67C27E625650732786AC4FFC929F2332B299C730791352CCB2969D70BA532469ED24AB748E700529BEFF00429D976374F896092CA18CBA99089B212ABAD085A5D2E5F662E402778F3D78E69D54789CC514948EF08530213626EC2C1DCB72BF58D9B585256FB847475287594FA200B2EF6FFB4A9209B75247A46535F3A7CCA83292B5654B10D67CBD7AD8F90DA31B54D4D452A132D92A6399ACA72C468C49B9DC0F9888D4A5C4DB0A61690E36A4292B428056A0A4904588293704EC458DC003789B2A9973100AC92EC195A581B9BFBF5E9A71210A96CE49BB927F6B5C96E4FF004B076CA5E965CD4BAD0B96274A5E3E5E5286DA9C479AE0F5FBDB01D63E182AB05C5686B5722B644D4A50A527328283B1B10E069CB9DDE36997562B1211A12CE1F7D6C741BE9F2888BE94EA02FA479926E95FFE69D8581E96DFA137B1116EC464A64CD480CF943B33177E5F63AC4DA5A714E328DC9F4B3B6A403118B1AF4F5FD0C5727F3067DFAEDE4228FF005FFF00CBFBC4A89D15A108421084210842108421084210842108421084210842108A7A4A8DEE46E40DBA5891EBED78BB22585213C9817363A02D673BB7ED088A8816BDC5FB8D81F98BFF00BFBC7270F9934E6426CF7B173FBFC8F5BC4B5EA34D3D7FC72F58980E9B923DFF00E2FF008C4D93854C4AC2D40E5BD98B86E4C7C869F5890807BCBEC41F76B7D81118A7AD9195CB5C5EC3CEDF7D186D15708B60201BE977F50D0844C9AA0A50234CA3EA4C2112A10842108421084210842108422A25AC84001B7FA9EB084479CF21F3FDE1102010411707620C47292674C4CB2400A203DEC5C3177D8DF430D62555D7E5754A7D0149D2DBD65368FF00EA00045B6E87B8115F5186CCA701521613943854B2C4BEA1F427C99BCDA257732C6660C55A9058FA1895652A520A9A41084E90920DADB917DFB5FF006220918AE2F4AA025D54F484801B39CB6E5CB972710FC2CA55C84DF9B38DAC1ADCC0EB11BA9684A3514A5B24B606DA0ABA9474B5EC2F7BDED7EB15753C478BAE5841AC9C366CE4B0EB71F4B9F9F224C9A775A52919C312000E0680EC45CF2239C54712979296DF25F426D6E61BDADD2D603A7FB0DA2CB36BEBEA16262EA271580400144FA6AD7DF5B973B3419E521F225201FCD96C15AEBABEBEF133A43A517480DB62C86922CD8B5AC748FEADBADCFEB79F4B453660FE24CCA48BA8975907F95DAC2D7D5F6222904CEEF314A57997F9892EA517B5DAEDC80163E512C499B33B952A4A194941CA0BEA06966B1B070F170428A92090C5BEC8E86114AA515973E8360222844308421084220AFBAAF91FD227D3AD499A801D8A8023CCC5296FC64B27560DD75FA6BF28E3CB3A96DF4AD490A00F99245C595D491DC5BAFB5F78EDEE09C40D0F12613E260A9D2092E5FF00EE076B80DB38275F58B4713C90BA70A6B80F6DCB9E86FEDF38D49F0A497FD25F199E28B00147C349663B0711D31A02C8996DE666186F4D800521D65CB2424D9448BEE23DE9E2892AE25F878C0E694E6FC3D34CA22C5FC32E449988510DAA8CE501B16706F177ECD6709357F99C152576E65C33B87D074DBAC65E8A88494AD44A5F41679A36581B029D66FB2BA280EA0017006FE73702CA3C37C4AA9D3159128AA605F2E8B24687FCBBD8DE3676B29856503315669563A9663A3DB7D4E818B461D6978D67FC3C7C5DB2CF885651FCAB2A78800FE15CC4665D2A6E8ED4ED5AA14E7DE9E6DA050D4B38858D2C9714F14A5C705CDC98F74FE1ABB48A2C4308A4A254F49992928CA02813908014557BA524240166CDCCC69076B1C36B97553E6041B955C6FAE8E186F7B7CA37D7A4D4246A4D89BA73E89C959A4FC5CBCDB442995313365A1B6CA4904253A415056E2DB5AD1BBD324C99B265D582921400077530FCCEFA93ECF1D0D492264852D2B4948D1B4208D39BFD35E91F7D09558F537B74ED7FD3F3FAC0148486D5BC56B391D1CB5AFE9152B219873279F3D7AF90DB48D6E3C3AFC4630071CB960A9B137274ACDEA138C48634C02B2DCABD6434CA5E9F90610A5A9E6564BCB24B4D1414280D5A6E7E6A7E283E19E7F08D3D6E2B494F28D3FF001264A9B2D0405A43A8149CBAD803C99AE18C6C5E2926AF87B189945552A6A56898525494B243167DBCDC73F5393F9697286D494A91CA0B219B2CA872F4A4D81291D14542D6001BC791B8D19B22AE7A66CB20CA9AA9641703C25AC08F2EA1E2FF002E7898942C5810EC7D5C96D2C75E9A6D0D6359459408EE46DFAFF6DFE862DD2A997532D4B43008B973CBEB6FBE7572C85170E7562DB6E5F944A410A07D4DC5BE7D3E71488495A8247EEC2278F6F38AB109B1239421084440BF703E70BEC09F20F0881B0EA458753DBE7F211514F4CB9EACA011670E1A2052C25DDEDF7CE21A91B9D69B72D2E8373E64A9E0C009DB756B22E3B0DC9BED114EA49923F3149B9006E5839B7400EF76B3C495554B4AB297EA4683CECFADB4D623FD45241491FF0076DEFF00DC7E2220FC34EEE84E12D4A96A240290FA6BECD1CFE210CEC5BFBB7D6D03B5B706F6DC6E37E9FBF7110224CD985932D6EED74900799E510FE290ED9544DF41CA04D813E913C51ACA824A909511A13BF2D45E2722605B3021CB78ADFA449CC1D2C77F688A650CD9775293A39FB7313B2FFE49F788950001DF7892241568A1F61FD3D5A21172438B75B7DF9B44A1D4136DFF000FDFEC426485A081F99F93903FC6FCBDDA5CE9A8920152817D81BFDFF688958092AB1207602E7A81B01F389D228664F4E60A4201D029C12FA6ADA9E4FCE241AD940397F4F5E9D3E6368A80595A1652D2F4EA097080543D82756FF3B4433A8E6C9D4A577605377F2897F8F97FFB737CF28FD4FD22915200090A0B5AD47ECD3BAC77D4A49B59361B9BF4F73191E078362D89CF9326970DAB9C56400A449514B682E35D6F6168986B65306CC4B02CC1DBDF5DBA6F1E119B5C48E45E4A31F1D9A39A584304CAB4921C5D66AAD34A0B0AB72B94C879FE65C5824B605C7511B6DC0FF0ABDA1F16D322AA8E87BB42D29532E54C07C40102C921C1E676F41493F11080FDC4D533E89D87AB1E7E4368F95937C5CF0DD9F8B7E5F28B38B05E399B95514CCC9D1EA61536C116DD6C4C2185906E1434255B107A74BAF187C2CF681C2D46B557E1EA40487CC25CC6209704282198B6C7DB48A1918CCA9B51DD2A44E483FCC410970C5957E5D75F48B8F5A92D9097569694A1A9B4ACF99C49170501214540FAED1AB1C51C198B609DE7E3A59494BB92921C39DC81A7A6FE717C1532CF36E7AB35E27092A1704475A4A90B9D37BA436676009EB688FBD06C2FE45FF4BF908914A09363BED7DB71FDA2A2AE867D3292169FE517BEB7B69F3B47226021D88FBD6201609B6FBC5114A81620BF94460821C40A80BDFB5BF3F489C9A65A939B3253CC13711CC4358F7FCBFCC53C21AC7A1FCBFCC21110A04D85E390092C211340820B184238842272242A60CC086F9EA47E9D6108E554EB4872437AFE80C211241292082411B8D443CA1F97CA2726A67243672407D6FF006F1032F98FBF487CE38993E62C0BB11B8717F3D5BEFCF8567D3A1D016E8E7EA2263A7B037F4F7F5277FDFA77A719FF009883D7A72DBECEF10A12B2FDE17BF859DDBABFDFA4523AF7B7A9F4B91DADFBBC54A26E51762599C8BB1F771CF43134250CC43FB7ABBC4A4ACFAFD0111C2A7CC517CC53D136100948B0000DAC1FEF9C5517205FADB7F9C4225A941C317EBF58E47B7972DA110149496208FBD8E87D2111B6D7B8207F9B74EB1082E598BF97EA2DFDE382583FCB9C2DFF001BDCFE5688995FD27CDBECFCA20EF3FF001F9FF68844689531659293E6C5BDDBA471DE8E5FB7BB31F4BBC414A484906FA88D88E83F7BF6313E9A9672EAE549092159816BDDAFA8D00E85F668851295327A67380940662353AF42FCFF0048E1A11A1C41529210A7129794A3D1951B2EC08B12104D877E9B465F4555F80E22C30CCCC3BB9B20961C96D7F507CACC5F5A0C7DA7D389680EA0EC791BFB8E76D7DE356AF10BA2AF283C5BB85ECCD45A5E473129145C2F539B274A9E9A4D7A743E1C16092D0627D8F31709DC8281604FD09F6555F278CBB0DAAC3A914A33692928E7E55FE41FC35F78A05CDD41091A5D872022DFC31592F0AAB9289D98199359C3F3480E6DD79EA6326E410C32DB83ECC1E65C6CA3AF705293B1DAE7A8B7D63CD7E3B9F36831CAB934CE9992EA9697B06217776D87EF68DC5C08A6AA9255DF3CB04036B116F3DBE6F161DE22F91073A786DC58BA3B1CCC5F80D52D8D30ACD281438B9DA625E51A7879095BAD87B5A1C3A12B376126C4EE36D3E187B48A9E1EC6B0E9589D42FF000B50B97226F7633A84B5A92E5282A4025F29624003E7D39DAA707CEA8933A74B421C02A4BDB62581DB9728CDF78197174EF15DC0D601AA57A795318EF2DD8465F63561F20CF1A9509A6A4533F3092B5384CF2E5A61DD4E04A8E924DF7B7BC5C29553712E189155DEA664B04242C1241CA0DD3B104DC1D08DF63A3BC474FF00EDCB58525941459C31172E34D1F67D5ADAC6695B75B04A350D4908B806E77BDADFDE2E69AD4217DD29F33B7307D6DE44EDE6F18D216A98E54A0580243F366B74F7BEF1F94FE03CC8C61C15E7D619E27B29D0BA67C03D2EF633A54BA94997ADD0D97899F0EB6CA4A1C52D83328216855EDB98D27ED1384697B49E19A9E1CAE9699FF8996B1874C58FFF000F5931391092A374C99CA12D331B448258E91ED076EFD86D2E1B4F538ECAA7485B2A628E4FCC8FCC7A9209B3E86F1BEAF0D59FB84B896C9AC119C782679A9AA4E31A4CBCF3D2ED38852E9F52294A66E9EE21B5AF96E36B0165074AFED41D3BC7CFCFC53760B53C058AD577148509CD326AB2A48055995605838395DEF63A468A4996CB9E803289731480144EDAB8DFEDF68B8043885F4B127A2AFABA7517F5DC5C1E9F58D29A01325CB9D2C5B50A0C76E963BB1B45C25A598DAC1981F9B69EBABC5428242546DB137EE2DB5BAF7FD3DAD16DA63FC7525AE12AE9F5E56D7589D0890AD4F99FAC211C4220A3617F7DA2E1413E9E42D6AA849527296000249F523EDA39177B816DE2620817B5F6D87AEDD36F5E9F5F9C564BC4A5CC9E8972E5E54A9411C8DCB31B93BB5BD768A0AC504249BB9D003C8721AEB7B697F3B4AE2378BACA4E16060D5E6FE205E1F97C5D5C4D2E49D12E5C4308752E3ED38E2CADB096D2EA079890011EBB1DB6EC93E1D6BBB520A551531A9EEA48A89C10CF2E5384296C58901F4014A6DB961B5989F70AF12C872C0DD9DF9FA30D99BAB7BD65FE66605CD6A348D7B01E2EA6E2CA454184CD4A5464A6A59D71D6964DC3CCB4F3AE34A65614CD9CB1B36147B0893DA37C3C718703D55448A4C2E74CA1909052B4C95A836404FF0020BF3BEA7C8C5761D8CCA56444C55CAB52DB917B91D7D74731DE1C69D6D5A53BE9EA46E2C49DF6BEDF306DF4B4740CC55550CC5D1D6619512A68252A2649003B022FEE741D748CBA54CA75A33029BB9D6ECCDFA1F38982B6B037BEDD7724F6B8F9F4FC36DA31F9FC3B533E77E269CA6585282B2AC94906C6C18B1D01D2C6FCE28E7D4CB27B896A0998B60FA0176D411CECFF002D621A80EE0FB77DF6E9D6E3F6224CEC17137399724D9803339D99B21B73F5B4527FB7D5A9DA7A6F67CEAD07A379F99BDE2A2834517DEE36501BEF6EBED6FEFD768912787B1352ECB90CEFF9C93E43C3D753F588461D58EDDF274D7311EC59C6B7FEF1C05841559BB9BDF6EBB03D40173FB1F5BCC9C32AE8D065CF942A153834BEED256C5B42C1C3BF2720F50D39385AC826A2A07966398736243726E76B17B7235043616A5BED824E95CBDB9F71D43375A015DBFF0031B137368BFE07D97F16712D64A14587CF32D6BD04A510012CC400C59F7E45A389A8934A950494CC22CCEE011B12C5B6D8973D5E2D3F884E327874E18A9351C439AD98B43C39332CCAD68A14BCD4BCFE26A8948BE94B0D3C032E9B5C85BE2C7A98DC6ECDBE0AB89F88534CBACA498CB28395485B25CB9BE560EE4396D4F4894719952BC0A913161D92C8B172427C3A10924747BB0600EB2FC5578EEE7FE78D5E7B037065855DC0586029F9098CCDAEA8B3899C924A94D266E412C36F940986C075005410424807DFD53ECA3E12780B83282817C494F26656499328F712A5A14E72273A67CE56432D41CBF76263A983B391D95C1BD9C631C473E4D40A499F86A9505852905803E2052188539637239011884ADE55627CCAC46EE39CF0C7589332F12CF3EB9B9A98ABCECCBB79875456E3DADE987D4C25B59504B6DA5614005122F68D9552F86B862985070ED3C8A0A7CA10B1492A5CB9931219BBD9A8654D2D62542F6B6D1B7BC3FF000D726AE8E5CEABA50B564492148B68E4B1059DFCFDAFCEA765B620CAEC4725991C3F620A9E0FC754371138CCCCB4ECC06E6C349297DA71E4AD9712812BCC4A921A58584941165189D594DC2BC5F81AB06C5129AC33124269E729254826E4CB2A2AC8B05D4E90E6E1C3BC63BC7DF0EF4D86E0D5551434A13549BA4A10012EC18B0F201CF22CCF1B30786AF8CC612CDB99A5645F146FFF00A0B37A4D0DD2A8F8DAA0E215218B396036CB5A9D530B9771E09E56B701170157F4F393E227E128D6D155E23C3F4F2EAA89944F7414A9D4C4964CB9E908604120254852C2925254C49034D388784719C11444D91310A46A329018594A05B97CDEE446C2CC5498530DBF2B3099B959942572F34D2D2E32F36B00B6E21C41536A0A41B801446FD77BC7927C57D8E633C1F884E5D4D24C4225CC56A850B02CEE46C5CFA728C6282B952A61454E600116367FFE409B1B36FF00B7251720A892493737ED7B5877B7CBD63AAF17AE952EA9326620BA5012C0683335C1B816F58BFCCA89534A55254E32DC82E09DDF6D2F7EA6EE22AA3A83EBD0FBF5EBF2FD628D629A6CBCE900167039DB537EAD73EEC226217616EA7F61D6DF3115929D573ABD80EDFF003B75FCA31B9EB698A06E1C807A06D3AFDBF29F14741F51FBFA44308683EA3F3FF10844C94906E6DD3FC42113C21084211C85280B2881D090211314902E7FE3E7013546D98FADDFDFF5844B1304BCC82B7B8737E407BBDA108950842108421084210844CEEA6650B00B588236EBD3CE202B487D6DBD9BEB11B1B5EC6DEBDA2AE44F916133F3331D0DF980C796C1EFD6CCE391F97EF04EE76B1F5DAFF908AEA8552A69F3C800CEB101AE6E0060C587F7BEE5992AB73E7FD8C415A6C6C6FD41BEC2DDF71D3F0FC22D899956AFE43CEC8FD19BCD8D8C71DD21DD9B7B13FA923E510B8F51F888A84D456CA07C0592D7C9E9EBB6D6DE3932D279DAFEBCFCE29AF7371BD8589F4DFA13DBA8DA2B70DC465CBAF44FAB4FE549482DA723CDBE9CF945DE265A72EE5C87FAFBEA3DBA5332E99A28975A8203CB4A028EC12546C1449E8124DC9B802DB98B84CACA7ACC729274BD04C9602816FE7703EF43A6E62D9569050A2CEC0AAF7E6E7993FBFB6B8FE3F9861DA5D03860CFC914F2A7302E64BF2AECC36921C436F3D4232A85AD23CBE765E524288BDCE9BEF1EEBFC20E30AC47846BF0794A4915582D4CB20FF5CA91FC324877014A36F38C726A4CAAAA6984B34F956D0865073AE86D6076768BC5C3F566B1061AC395C6CA4B53D4E91714A053A4F325DA5059502459449B126C6C403B18D33ED870B9B87F11562CA487AA985C8D4859BB3FCDC3BDE3703846ADE9E952083FC2961B5D83F26D76F3E91CC9A944CDB3354A7825E66A1CD6D52EE00A69682DA91A5772414A90E2EF716B81BF48ADECF71D34588512CAC0089B28E6722CE1DBDBCEECFA45C78CE90D650AC241BA083BD883ABF9BB93B92072C69F862E70D47C3E7C5531EF0DD5698765724F8A244F62AC20C2D65A9394C40E4FB5314B69842CA590A549D4E7B99CB56A4A9B4800DE3DFCF879ED065E3DC1D4346A9A950A695229D41ED69644AB3DDD295393D35B18D08ED2387174EA9930A2CA9AB20B1DDDCE8CEFA39F68DE269CA4CB961C51F887DD9653856157BDDD6929055736584A8920EE4037EE6364914885B4D09DC14DB4704F3B7ADF58E95549EE1DF62C4B75D34BB333F3263F2EDAC52DAAD5367A97382F28FB0E52DA4900FD9CDA085A803FD377957F61ED68D2DE1BC72529424CE2953324BB6A0B5DC6F1F4FDDB26088C638766D226582A54A218873F96ED63A0FAB6D7C8F780AF1315ECADCE9CC6E0CB16CF095A362443989F2B1730E00D375B936DC138D344F45CF2534E690123CC5AB6D611AD1F18DD9AD07137085471152C92B992652E5D41284F814539A52C2EE7F88A252C34C849D418F1E78DF8557C378D54524D42529993264C65020142890B0465F168C361CF511B7E30A6B98B6991A5B421B7D361E5D4F8295A47522C5ABDAF6F30DEF1F3CF8B60A9C3F15AE921232A26CE0DCD8B331FDF7D368C28BA45FF0037E52A1A16D0866D8DACE2FA472E3ADE70126A561980CD6F307EFF00BD8D399A01B82C4B3F3DC7B9108A43724F3262AD3A0F21F484711CC408BDBBEFFD8FEFBC5D70B93473A64C4D5A825390E52EDE2B37C9FDBD9056EDA92A27494A82ACB295004106CB362936E8A16D37BDF688CD1D3CBA942E44CCC10B075BBBB87E7CFAFA5E86B102624A5B6E572E2DD0750FB758F08CF1E1DF277890C2F318233A70661CC5B48764D6CD3276B54E62A157A628A0843B4E9F7A59D71A79A3E669487DB2156B2876DB6EC7FB78C5FB385499B41553E9662100154898B94B29DD2A28209041F107218DC308C46B30BEF94ACC84ABA116E840BE9AB7AEF182FC5DE109C4870E15F9EC77E1F9C45E23C30C3536A9A465BE28C4B88A5A973835070C889364D429330C38B2436DCE29968365285694A6C3D1EE16F8BCECF78DF09A4C378EB0EA7A99B3902554D4535352CAAA2A032256579A599AA2027395AC3924DC9BD96AB02AAA69667C85948D424A890CF7DEDBE9A5C691D42BDE291E247C19CA3EAE31785699AFE1DA3A1A62631CE167E8F2D4F99612BD2B987052DE6DB5A94DF9FEDCA54A27CC01E99AD3FC3C761FDAA8975BC3F8AD1F7F5AA7452564B54AA842A616423F8099D2C92A21215DE6B736722DD478CD7226F71312A0C425D24105ED776370DA73EA63D632FBF88DF841C492927FEB0C2D99B822666396FADC670ED16A1268208D65732AAE2660B6920952D0CAD76048415581EBEE2AFF004FB4CC33D383090082528226A42731B0B10F974DB425D9C81D9541825756D37E2A505158014078BD08201723403736D1E2E8289E38FE1D15A9613151CE96686923516AA741AC4ACFA7627755324274820FA397BF43DCF554CFF4ECE3052880B907312C04C397CC1CB9599F70D111C378843E544C21FF00A0866F30E1EEFF003678F8189BC797C39F0DA1E14FCCFABE274A412DB547A3D6D4F4C100D8736A52F2015A8ED77160F5E8378AFA5FF4E5E3072553694004BBCF4BB6F60E5DB90D03DA1FEDBC427495301B90421434DC06F263D2FA88B37CCAFE23ECA490977464BE4A63DC5B3E9E6B32D3156448CA4AAB9800696843554992EA5C29D4BE736829012003A956ED5E0AF8009787CECFC4359878653A3BC339494310EE51214092C00671ADDAD110E0CE37C726253414D52B4CB2D30A10A624B00EC1F477773ADA31A79C3E2F5E235C44373B87F05352992185275B5A5BA8525C4C8E249069C50FB6A6D4A4D869F959A4A6ED975136D2B438B1AECA20EE1F047601D9C705D3CB33254AA9AA94C4897290990B290CC262CA668D3512DCD835E3BAB82BB05E28C5152D388D2AC216C162621449720E8537E834E5160EE64F56B19E217319675E35C4398F8AA6965E9899C475299ABA9C7566EA2B5CDCCCC1515289B951F58ECBA9C469F089229F04A4934B2539411224A12548486F1AD202961BFA8B7AC6DC70B7C24E195B2E54DAD900AC0492163A826C74BB5C0778F69A652A4A8F21F034AA749C8B6D80DA529421212DA3CA12121160024580E805EDD228F19C729F16A2954F48B4A2AD32C2668496505E8A162E2E2FFD9E36C3867B25C1386A96929D34F2C0A642500E44DF2B00E5B50DAFEA23E824A74B6805B2509B2CA0586A2ABDC8207A9F6B7D231FC3F0A44B42D5884D254EA21D4588D9829AD76366F3678ECB952E8A9E4FE1E4A136013648E46C5BA1F944B30B28B10875C2568404B1FF00B835D90542EA48B2028A942FBA41B5ED68B4CDA3A9C3B11978952ACF712C90405288624D8EBCFA5AC378B256F0DC9C4F3A2A25255256E4829052C5DB5D9AE45B53BC79D63ACB3A2E36489879A96A5D769494BD4EC5524909A9CAAD3F688FB44043BA90A3FD2B3DF7B476FE018A5062B48BA7AC29299C8CB352A62998CC405A0B05234705C1E578D75ED3BB17C3710A69D324D2A02B2A99901C1637058BFCFA18BE9E0D7C5EF3FB8339A91CBAE224D6337324D97D9966313CC2D7395DC272C421A6DD69C9C525750F876836EB74FF008A54886C212A712EA9E6DBD78ED9FE1C301ED0A8EA95824AA79388290A12E90A42533E63951EEE6B650E08CA165202814B8178F37BB46ECA2B306A99D3254921014A399208B681C30D35B6CC5DD846D9DC37F14D91DC4E61A91C5D9458F6958A64AAB28977F97313C86AB2C4C68D6EA26A9332B65C6CB495250A4286E50A08D4DE859F1F3B5CF83FE20E1DC5E729747325302A3E1510C14AFCAA01887043A491B0DC474E48A39F400CA9CE083A17058733F7CE2E72E1D4A14E3EC1532A520B68B4B38DEA2059D96484A1C3E8E0D7A4DF7EF1A85C4BC115BC373A6C99C829C9624853F85DDDC793DE2BE52D88B900BA8825C722126EC34B585CB0DA260957DE69608B1DC1276F96D7FF003181FE0913733EA9725D81B6FF005B1D75DE2B92B2C5AD76E7EC7F589E2D2A195447224470E06A40F58471071CC7B8888569DFE90C856424737F4FB311A08CCC082E36302F03B036F7DFFC6D1592689C87F5BDF42DCC8EADFE2665725C9239683EFDA29DBFF941FA9FEE445E2461AECC90469CC93EC2FEBA7388BD0FCBF788A5DD2746A0AF43D7A807E7B13DFDF6B08ABA8C049906604876BEC5B577F3E9FBC70DBB317BF3E5AFB69FA98AE55E5BFAEDFAFEFF00778C426C85499AA41D125C1E8FCA3800051E7B5B6D1ED6BFA1D6D78A515727FECCCF3FDA22845242108421084210842264A5B49D4A22EAB9DCFE3EA2FDB71D62EFDECA5D32100788000E81ED6B6B7727D378A05CC01445CB7C8FBDFF00BC454F25C525B6D4137493CC5ABECD3637D2A46FA89DFB1F9C4CC3B87AB71099924A02B3285C0755EE03B383E5D625158377568CDF6468035CB696D6386ECF312EBD2EB85942012E4C265A5D894B006E56EBAB6BDF7D26EAFADFB4B05EC7B88AB96855353CF9F30A4144B085CC7E76234677F3D5E384CCCAAB3149D4A945C101C3062036EC4167D5E3A6D433372E29AE2DA9EC6D85A45682A0E89EADCA4A149BD8956970EFF80FEFD9941D8171C2807C1AA48673FF004EA22F73AA5C5DD9B9BBBC4FFC500921C3B0660FD3702DF64DA2AD2B3032DEA8A70D2F1DE0FA93AD275866571049CD2946D700214E8FBDD877B822DD224E27D83F1CCA0A2306A9B7FF00CBA98D9F74DC36AF7F3310FE301003283B82AB0DFA1245998802EFCA3BB3132D3D2EDCCB6C25D9479254152AF4B2AEAB901D0965E3A85ADE7B5F6B102D1D6B8F7639C59434F32B2AA8A653CC47842664A524103A1019AD6D9FCCC514DA9FE384A54543F99CA9EFA312D6E81C3B748A4E7297A9BF2A995254A5AD5B38DA77D60936EA2F7DFA1B5AC0C6094FC3389534D4CF9F2CA44A98330482DE1625C300F7D9FCC931744CB0B959CB91A313725B47B91F3B9F6C43F8DBE004634F0FACD0A9B2C29CA8E0376858FD8094DC84D255517E695B0E896A5182A36D811BED1EB27C0BF15E6C6F0DC1973804D54E450AC1538289E44A5803A8D74E718D622324D0A507CB31240D4062E0924F51CC5B4BBC5B6706B8C1CC75C34656560BC1D150C35212335656AD1FCA1B05415DAE3E36C6D6237262E9F139C3A30DC5672C2322C4D529C3862546DEA1B47B680C6C87065566954C972FDDA45FFF0021EBFB39F211754F10E4D2F9674B610E31A8F4E59D3CBEFDECAB6DF2E91AA987D5AE8BB998925253312435EDB7A68E7E71DC73E9455D2310540A7771AE9BE9A8F94623BC5472BAB6DE13C03C4DE5D19893CC8E1F2BF45AD4B4E4B0703CDD1987019F4A14DF9B4BE5997655DB4B8AD5600C7A89F081DA54E4E292F0F9F356A9332480A979C801496099B95DB3A5D49075651BB1BEB076BFC3D2E4613DF6548577A729CA792ADE4790BD83C6DF9C00F14D8778C1E17F28B3C291C966671461CA23F8869ECA90554DC64AA4A5588696EA5BBA52891A819A61247955CB16001DBD8BE1EAF15D852673A41EE926EAE809D3572373F38D2AC6E47E1E64C04B9398860080970C93C8B339B92CF6DFF3CC74A1252E2C5CA08527FEDB83B12916048B0DEDD8479EF427B99B9D04A540BEA6DF5D5CBC7D4CF12A0D4226257E24B33301ADCBEDA5B4E51E4E9C7B3F905C46E4571154575C95730BE2FA7A2A6F3675FF00E96467652696971B59E596DD4BAB4BA9234BA9484B80816195E3D86FFCB382B18C12B65AAA115149395265A6C573654B2509009482A5288CA096BDD81BF9B7F1358052534E562B26584CF96929CCD6009274008F32C7CC98FD0BB01E2796C6186A838969EE21D90AF51A9B559771B092922725D2B5D943AA0904A517D2937D00152A3E6FFE247023C1FC5F59230E9464CA54F9B9810EC4AD4087DD9883CADBC690E17553EAC4FEFCB9429936DAF71B061C87D23BC46B8574894695352524CF5148274170492CF7D6EE3D348A797326CCABC8FE00A729E40117E9B80D7F7877F6DFFB5BFBC5862FE9D0790FA4211CC2F6FF00807F5833FF00923E9081B1EA010762080524770474208D8822C7BC4485AA5A8292482342E4FF007F9C4250953B8D7CE0424941286C86C5908E5A3969EDE545B4823D401FA4578C4EA8060A6B3756F3D7E712BF0E8FA6DCB6B98A48515AFCC014B7FD040E52C2AE4875AFB8E8DC81CC0AB0000B694DABA8B17AE93365CC973E62148650CAB29B8208D1AFD795B4B452E2694A2880097CE4BBDD85C326DE10D764B0CC49372631CDE2AB838636E05B3F68DCB25B6708542A886D9529A2CBD232CF4D36B972D14A98F3B292E06F485A014AEE98F4DFE0AB8EF16A8E2DC264D755AA6C8935D46AEED6B2A49089A85314A89494822E92188DB68B2D3E078714227AA59EF14E4973AF4BEBE7E9B3690F92942C2F88F2BF0CAAA743A54FBF2489F917E69F909671E53C89A79094B8EA9A2E28805362A55FA5FD63DB7E26AC9D874942E95926714AE602C5BBC425619DD8806CC036CDA47A13F0EBD9DF0D712E140D7D3F7A512D252FABB7555F9171F58EF6F64FE5BBEE735784E91CCFFBD126C21571DEE96C1BC6314B8FE26B490AA89A10FF00973AC0DB676B58FE8FA6CD1EC2F82D2A6386A4BED9525AEE4EAEC7EEE447258CACCBB9316670BD2D6E1B5FE225599817EBE50F216136F4481D368AA5E3D5524029587EA735DB997D86BEEDBD653F623C009244EC3413BFF2FAB020302FA16D04768A7E1CA3D21015234BA549A05AC18A7CA34A5586C41434920A77B11BEE7DE2D555C5D8ACD69614022ECC9161D4EBD403EF768C8A87B2BE1BC309FF008FE1F2D092419F9D01648D99C2B997DAFBEDF6EEE2DA52544A9A705ACE28A936241B106E34D8741D361BC5AD5515F5ABCCA59B93A1203901C5AC4F3371E5AC67987E11826152C2AA6553CB5001C14A12CDB9B0E7E6E22B0425D40D2DA5A2D8B731AB27A6DEA371D7D76EB72045C69E9B160190090A4B1252EC0F521C0D362D7EB136A78AB07A0B53CE9290CD6500C363AD8B0BF568E3B885AD449F3D8DB56B686A1B8BAAEBB927AEFB923DC916691C3B5F4B573AAE522609B3661985DC872492C925B7B16D36E74353C53267CB0A18853A7380E0A815005B76B3DBAFCC4412D2812406507A1054028903EF59AD436B6E546E4FB457555062D557989586203E5034DBAF227945AE9F1DA71349FC7D3B937FE2585F7B07B0F2B4456AD249E610AE9F601C2E74B10924246FB8209B1171731CA28B124485489A85992E02BC3770430059C681D881A748CCA8789284809A8ADA632D8582D37605D9802FC8D9C1BEF13210928166CB57DD4B79160BBF5D6370AF7D5788512E7D25E5A66208B8B9E6F70E7CFADE2A6B310C0ABA4AD099B28BA6C92A0766D013A8736FD8470AAB4E91ADB069F5494949CA7A9B5204BCC30D4D4BA42AF7D2CBC853480492AB0401A94A2003D6EB2789313A41E02F9430CE80A7E56502C458FEBCBA3B8BFB39C0F1E2B2B928999DCD80B8366B5F9FBB5F48F24C2983B32F21F169CC8E1BB32711E5F6276A604E2E952D529E97A3545E6D41602DB69E5213CD484B0A6B93CA08424742445D6A1780718616AA4E29A1A6A99880512A6A64CA97532E5BB8099A94A56A014490852B2392E2EA7D4DE3FF00873A75AE6D56174CB0A095164E629700EC1C68DB3C6693866FE203C5585D54EC0BC67E56D459999528904E6461995905234D92DA2727794FCABF320A815B80B2F3C46C94289B46A876A9F079C11C5F4D5557C3D26554D4CC4A94294A972AA41209621792458DC94CD5007C9A34878DBB3DE34C02AA6A64D3CC4494A8F884A246504B5C2496F41AD9E3620C88E32B86AE2128F2B52CA5CE3C15880969B5BF23395372915D4B8B483C9FE5355664A61C58274EA9769D4956C951DA3CB8ED27E0F78D302ACAA46198655D3C894B5E6065288397F3044C4852140001D964024462141575F489527114294A66D082FCD880435EFA1D3AC5D4B6F29C49702DA71C50BA6525D130E246D7F2CD1684B9D8EDADF03BF4BC6B0E29D927116153549AAC3AA54505963BA50B8F200FD9EAD72A3C464AF309E0A1C929529214C01B020BEBCF9831C31353A546F2732DD8EE952E45640F62D4C2C58F604EB1FD401DA287FE12B4CA515E195598027F21046B637DBCFE515A716C2D0C95642AFF00C5EE39B103C881A5B9C7256EBC96C38B69E209094A12658F9EC482E59D2A4A36372904DF600C5B28784AAEB2B26C895455128A104A0AD0C09716724EC766D3568A9955B44B0F29525DAE4939824EE0333F9D9B5DE2AB575B7775D946DD501F620CD234057F538ECC32DB7A503EF1438AEF6BED7BFE13D9471AE275B2A4D0E1959390A580B58924A5B3072181B5CB3B16D6E62CF8862A64664CB58704B28017F41B72040DA2C1B8B8F10DE1CB847A2CFCE634C614DAA62C9469C94A565BE199D15CC4588EA6A05B9708128B758A7B6B7085A91393724E048292DEA3A237E7B20F83CAEE24952558CD04C92E94AA74D9E9549952923F3CC98B2400948F110E4EA12924B1C697C455A92495800961BBF20C4172FA722768F09F0F1E2BF8B3E2AEB38F333334B29BFE9B6443CA43797F25392D28CE27B296C30CCCADA179E9B4BCA2B7D45F71C682147944B6124C3F111D8F7655D9960F2F0DC0EBD38A6392A91733119F21C524A9C4A8225CA5CC285AD61190A884146ACA26C6E1418BD7CF733192927C0E3C4A7DD5661D1EF71AC65E4582020283A9D2DAD0F0B0252B6D24A1D48B043C95156A45B606F7ED1E5A570CF5F3729397BC521B29B82A2414FF00E395AF6F1022F19552CD5CC0EAFE90E3705CB1D1D88D03B5DD9DE25F5F9FE1B0FF009FAC71393DCA425048CD753EFE11CF7B1FA08A95120A5B737F9422922284211037B8B74BEF11272B10412A2D95B63777B8FD6113DD02F706DFBF7FC3FCC44696A8242CCB504B12F95C16E4403FB7A453A7BD3308259235077EA352D7DC8895C42DA046A0B5A85D0803CC01E97B6DE9D7D62BE80D1CCCA89B294B59B060352586E1EDAF5DECF104EAFA6901E610920905CFE66676BBB79B6BD23A8621C5941C2B47A9D7717D6E9D85A874C47C44D566AF34CCA4AA5948D4B4239CA1A5691B153E8434BD24B0B73CB7D82ECF3B16ACE35AAA6974987D4E59CA4B2B22FC44B00C90E18BEC39078B657D7489D207FB79CF38A400004BE63A952B5B1D0077B93CE300DC6478FA651E50D72A980786BC28E679634483292F5261130DE1E909F410D170CD3E584BC12BD4A216DA987083C9538DE951F53FB16F80744C954D88639293494682954D9935330A859CCB084A55333382012909041721DA20E1FE14E35C62A9225C89932529418250D6240D580B0D595CCB4613333B8F4F127E25669C7316E6B4D65AD027895270FE0F5CBE1F5CA4A2C85B52C87A8ADCA09B5B634256B79D52884A964EA11BA3807629D937074E44B9783AA6D6C82512E7CE2522614B8CC519C801C022C1F70ED1B5FC31D82565751A2657D1CC33549495008218B5C936737DDECFCA2D7EBF96998B5E74BD8AB3E73527DD9A56B9A2E627ADCD6B5A8DD4415D455A413D00B0B5B6EA63B329E470B5304A65E1985B200033E1F46B36B788AA512A2DB97BDF611D9141F0C941387F128A71275BCC07AFF330F31FBC51A3E5963CA1BC66B09E7DE6761D9B4D8279D886B8CA1DE58013654BCEB8A015606E6C77E978E67D3F09D524A2A708C2A624F2C3E925A83FFE4896147A0760C06822756FC30D04A4954BA49E0B59D4B51B6AC3391E5BFB5AEC72AB8F6F108E1867242770F661CD66D61B90790EBD43C43308ACBF3ED36425D9044CD792B99964A9948502CB8DA12B74AD2AD6551D65C43D8CF66DC6B30D2D5E152E5AA6864CD401DDCB725F32259761D10A2DF96E008E98E32EC427E0F37FE969673A525403172C0E9B35B9EC7CE3609E073C6C724389E9C6B2FF0037A4939319A336B44A3F46AD3825E9534F25294BA86AA6971D4B4ECD15290C043881AC84829EB1A1BF11BF07ABC130DA8ACE0DC355329B2A97DF5382B0A1AE6C87F8C848DCAD09667360F1AF38E609C51854E5A132972E5A4964AD07406CE4A48BFF00E24DC4646F8C5C0CDE6D70AD9DF81995333CE632CA8AF48D2D128A13087DA9DA7CEB4D2E59D41521E52814941D45C49B900289BF407C38E078C766DC57455189CA99227C8AE92A945492005266022CA0016BEA1BA3458654F417189ABC62C46977F47D6C7F578D7EBC24B13BB5DE19061C7DD52E6F01E35C41409C2AB24CBC8389916E5D9527B2B5CABDF6A46BBDFCC488DBFF008C0C30149AD4A58D44897509527465A1C11CEEF63A5F9BC77676778822A3BA4E77CAC94E8580E7A9240D1BADF9E542725C30A2DDEE0A10A041EA945CA0DF637F31D47FAB6BDED1E78E032D3579D154490851DD8D8B7401835B57BC6C19A99D2E4812CBA5AEE1C37933EBB80F1D4B1DE1CA6E3AC178A309D765A5E6A9588E8B3949A834EB28D2A6A699536DAF64DD2A6E60B2E85A46B1A763B98EF8EC578CEB385F8DA422967897241406597719D162E08B8D459B71A18C1F8C706958E61332555CBCC120A835988046BABDDD83D86F16EFFC3B59E551C84CFBE203C39F30AAAEBB3183E66A989B2DA66716196EB126D56D997986A442B4AE61F986AA089AE72921D2DB2E0D7652C1FA0CEC7B8A24F1170DD3552BBA4AAA643AA5214E94CD48026109FE54A9449969B009D0001C79DFDA260F3A83129B264A5425A1647E50E41360E46A1AF7D6F7D63010E8494D94350B7E207FCFA7B46A3D3338B3B93AED6FDA3EA131A9399040E40F2DF7D35DFDC74F09E22A942A19515C7255239D4E4AE79214095361B46A529045F495684D8FAA77204766F0DCC9444992B3FF00AC951E81C66B5C976B82588D846907C48E062A302AB9D949694BD47306CDEE435EE7A36EFDE1738F9798BC0770F18B1F75D999C7703D3E9B5171C525C7153B201416A2A493B143C80012163492A16B13E15FC73F094BC338BF14CA8044AA898CA218975A94E6CEF7FA72BF993409EE265420021E62CF3BA5C01B9E6DA0DB78C81056A492011B13BD8FF7F4F68F38AB96F4E10FF954DE400B020F91BD8F58868521557354412A48370F7399886F3F7789C1B807D45E2C517B8421084210842108E287036A374A8951005BF01DFE7DBFC45752804DF64EBCAD14389826953BB28017BB9572F2368F15E22B07378FF24336308BCD87515DC0589E450C9495175F7E8F3ADCBA52122FBBAA4F4B1DEC37B46E47C28F10FF00B6F19D123BC293F8991BB1BA92799661F65A24A7F874B2D4C6C92EED6E8D6D7D9C8B1DBF3DDC85BD1D7989825F4AD28C378CAA52ACA15605B5FF003279A08B13A868280A5277D88DAE63E89B139A6BF0CA2A8242C4EA2A69E14096FF00B084B83B8F06FBEF78DFEF855C6325225015B04949209D49B02FAB8DB7B9B08B842AD2AD2411DB576FF36FA461A85642400CC6D7DC59EDEBCF40EF1E8561EA456119C0620172074BB5EDB5C0F4110710DA6CAE6581DCA82566D737B00137236FE906E76EA2262A4CC9C52C09CDA79E8C4681833E97D4DC4565650D2210A5AA64B41F3034D7CBE47503A70AB13D214F91339549D669F4F646A5CF4C2CA1A401651BB2019859B58F91A55BBDAF68AFC3F86EA2AD655DDAD85BF2FCEEC2D71AFE91D6FC43DA2E11C1326677D512734F4AB2A4AC12E06CFC9EEDA45AD63FE2DF06E1B77E070A73F12CCCB9500F30C96A4798905239899C4B0EA91F7BEEA54490362378EC7C0F82D6ACB9E50008B022E4BF20EC741761EB1A55DA77C4BA65CD988A2A8252EB6C8A0CC0D9C86E970FB08B4AC43C56E62D75E996E4A7114A61C52CB4C4AB2EB6EA413B0D6A64377E83659DC8ED1DAD85F034AC89CF28330CC598BB166D0F3F3F58D63AAF88FC66A26ACA674E20122CAD3AEB702CC06BCA3A02B3CF345360713D4AE46E04ECB0B1F4DDC0458ED620456AF81640516942C4B02069E46EFB69186D47C4971A99F311295546585B26CAB279D9FD2FA73D23992B9F39A88F3338B670006EA0E3F20E1B8ED65294AE9FF68B03EE6203C0D20FFE881C88047B38617F4B74823E22B8E124280ACE764286A3958728EC725C4B66ACAB8D97312A9D4A41F23B249285AAC426EF372DA6E5440075D89B24122385F004A9A8EEFB91C8300EFC8F97D22E523E26B8CE9D48FC42AAD32DF749B6BFCDF527AEC5A3BBD378BFCD094F254E5E953AC9FB88703697562C371E54F5B9B5EDB7A6F165ACECC920102597035CA37D1B53C8B3467D807C55E2895A44F9D358104B953DDB571A83CBD7AFAFE1AE34692F34A96AFE1C9E69E4E90E3924A91424036D452B79F426C2CA360AD561B0DA311ADECD569CCC87B924005EC3AFBF2F9C77B605F143267213DF4EBB004A9406A3CC5FA6DABC5C6613CE6CB5C5CD3029189528A94D00D2642A41C69F97709EA0BE84C8AD1E616710B55C8201200B61B8870157D35485CB42932C241206603ABEDA6874FAC76F603DBFE01894B126A66492A51BE628D4EBA9FD36DCC7A55428B42AE492A52B14B91AE32A41E6CD4D7C3BC1095742C2A5D4A652B1D504E9712ADD1624C5CE969E5E1A902A90429296CCECA1EA082C5AEE59B980F19BD4613C1FC6F48569148A5CE4900B21C9201B0B7F516FD23C1E77217F97D43FD419638D311E01AECBACAA566E8956AA5203642B50D53928F3334024D88D0E103D2FBC713712E1DA9229AAA453CF44C390A6A254A9E03900B77C159736F9407B3EC0F41716FC31D26253A64DA1928CAF9FF86185DC8BA40701AFEE06A0DD365871B7E253C3DCAB149C279E752CC0A0CBA92A3298994D57A7E6128160DAA7310CB3EE5940149D33009BF7B4605C6DD82765F8CA26547FB651C99B56D373D390C82A724E42ACA181B0096E4356E88E24F873C4F0F4A932A4AFC2EDE156C6D7624B73B836BBC5DCD17C7978EDC38D3E9C4991D83EAEE4AB52ED29F0DB6C4C4D17028257CAA7B8D498594A16B51165100EBDEC23AA47C1F767D5B97F09916A98095AA62129968B064B0014E6E2C0DF68EA1C57B12C6E925CC9EB92B4A520ECB7B6B76B681CB87F38F50CA1F1ACF102E22710D7304E4BF0D186313E24A52968A8B72532DB4696D25E0C1995BB509E9794490FADB404B8E5BCF7B5818C5F1BF83EECD387D02BB13AB9186CA01C4E01241524BE520824D81B80D6F28E92C5A86BB03A85CBB950514949517E5CEF6BFAB6A045CE4C64EF8E0714EDA6999818D70CF0E18426D2029C94AA619555C4A3A2CB434FE115546A087792A572D4E2D2B0E006E1636C3E67167615D932552E5A2562D53252596A120495286A52C5135C1E801DEC62810AACAA63303025D83A94DD366B86D7F58BA2E1A3C15322F2A31149665674D7AB39FB9AD2EF226DCAEE339D9EACD20CDA55A8BC69D54714C4D2C1174B93926E39AACBB858046B4F6C3F1A61786CFC2B8366270AA6CCA6451CB95256A252A19664D9404D988BDD2B5949DDC08AE97869CD9D4824B7F33D8F406C2F7B01A6D199AA7D2A9549625252914C93A3CAC9A10897629AD89797974B32FC865B62510132A9692129FB3E584A06CD8012911E6871AF6B78DF15CC9E712A9993A6CCCF98B9B872C9B3000DBD185ECD9251519094B8B387491AECEE390D1BA748E5A414048164950529F02C12E3EA75479C06C428B452952459208F28B111D554C65AD7DEA92E58F8945D4D7B33A80009241673B9D4C64B265F760B905D826C1C240162753773E4DBBC5403ADED7ED6EFF3F7DBF48A4AE5E69C024B8018EC06A74DCDF5F7D6DCA9473B316041B9D9B6BEE47F6845244E898A4817DADB7E708842812D77BFCA29856AB80924FADC6DEF6EE7DBA6DBFBC490A0A0A0E42487001BFAEDFABC4A99332CC422E01373CF4B37BFE912252A5072EA03CBE50A36DC7624D80E9D49F9464F33134D552CAA1A7965535404B0C87249605CB6A3FC447553532649502C403770FD3CCFBD85FADBF7127C4B654F0AF96B89B35336312CAD06994D90755489379D49A857E6C254A4CA5325FCCB2F2C20E92F25B6F71E71D236CBE1F3E19718ED0EB29264CA49A65CC992C84996B01944396093A072543401DD8DB045D1D763152A45385AF32AD95CB8277D1F6E67EB1A46715FC7B7119E2338D2A4D3759C41963904CBEE4BD170CB2FAA9F3F5DA136BD34D7EAE698A2CCE3EF4A250E388987DC690E2945A02C0C7BC3D9BF615C1DD92E0B425345435D8C53489495CE500B97296103BC0944CFCF3133129F1E5524B1214418D98ECB7B03C5F169B455357226A64CD285F8926F998B9B75E86FA08F30C138170F6069644A61FA4CA32CF2D0D4CCC4E4BB5393D36B4A4054C99F984BD361CBDF4279E10D83A50024003B465F6A66850BA214E90951214A125001528DD49CA9600BECD7BB47A7FD9BF60F8461541226D4524AEF132D1F990926C90FA8279B1B6BEFDEAFA6ED052DF964DD4C87EC879A5ABEF6971AF369DD400D7D2C0F78C7314ACA2C625AEB10B4A6A49CC10157B9B8606FA97DF6B1B4771FFC7308C39A5A244B01366084B5B4B003E4E6C4BBDA29A523FAB58B74D2F3CAB7FF00DD67FE778C58C99EDF99577DC8B3B6DA74700758BAD2C9C2E580F2A5863A6506CFE4F7366DEC62294A5BBE90A59249D4F28BC45C1E8970AD2074B0000DA0254FE6BD0EEA3A07E77B44CA99585CC040948B8762801FDC7D3A7945441085978A96EBC41400A4A1965A411F79B431A0176E4F9D49B90120A88168BA51624AC2489D349241D49B84EB772FFE1CEF187627C0585710AFBC54997E1052F952ECE5EE436A6FCAD1E5798595987B1B044FB3CCC3D8865D6DAA42B74A5B92532CCD257A9A9D7E6A554DCC9725DCB38820A8123CFE58EC6C1B8A308C7252A96A65C9529485CB5A66CB44C44C42865295CB582852540905D26CF1AEFDA8761D86AA8A7CD974C824214414A0588720BB3D8EFCEC1CC665FC2AFC52F12A2B14CE0A78A3AA99533ADAA9597D9A15971A2E3CC280966E4A7675E2661ED4AE5F2D242C7995722FBF41768BD8161D886232318C0E9E5CA49A997326CA96923BA566CCE3F94A14FE101D4194140067F27FB5AE07C4706AF9C99125484216A2E80C960A3AECE06AC1CBF5BF4CF0CC9B4E08CEDE3532550A5372D4ACC0959FA3CAEB4DDC944CC56D4FCEB090A3F62FA56C94A810494EE00B475F7C4F70AA95C2F8695054C5CAC365D3AD4A0A242E424BA0950CC549CC3310E18863CA6F64F5733F1224920A92B620FE67703FF8EC6E2FEB78CCBB8E2DE4214B275140B057DE40DB4A15FF00926D6245C7707B4793735030AAD9F2C9CAEB5063ADC97B0B58EF61BBC6E24896154E92AB9CAEE06CDCDAEF72F7F91891482A69C4041755A524363A2CA549D940F54804A88FFC45B788B0EC597418B53D64B24293312E46ACE2E79E9F51ADA2555CA973A9D72AC4A9243303B6DF472E7A68230CFC7326B5C27F169C38F1EF800BD2030D63790C298F154B4ADB6E6A8D3AD3B27353152242187582863984BCA279BCB576247B45F089DA9A6BA8E4E1132A539FBB44C9685286799312529EED2F7FC8A5AC8B2591CDA3503B56E110F36A932588529CE5D2CE0E83911B104E8EE4E3C9C20A7637363E87B7B77F9464B4E3C5761E271F41ADC0F6D9E3E8371212D48CC1419B5777D43D8ED7FAD8C797E6EA3565B62F4A6C14BA1D4398576094A112EB29DD5B0372AF73D3D6D92603513D78B2244A42A624655A9280A2C01B9B07E7A6BAECD1AB7DBE53495F09562BC2491300F3CA34776E4C7CC5E36D2F0299C72A1E1C9938B5AC96D8AC629A7F989B16E4A5A80B60A49B5D054FBA1253749B2AC4DA3CA8FF00504453A38A31594A5244F5CE52BBB2597F97FA75F96DE71E422D915D572D2E0254B214C59CA94000742435C0B8717D23314E0425A3A4A6FB0DAC7A03B7FCFEB1E47D7CA32D0A4CC4A90EA240208E5B9D7D35FA718581DE4D2EE49D5B6720FCDB76D209FBA3F7DE2C11733A9034BFC8DA26842108421084211414D8D48F4D5D7D3F771EB1574B62B3A3A0805AC4DF7D39450D72553652512C673DE02000ECD73A740D731338D30EF31A7501E69681CD6F4EB4AD03771040BDD2B4DD36EFD3DA3BC3B0AAD9D86719D0CF9CA32A4FE2A493356E940016904B9606C0B9F5B452D613268529596514A86570EE5ADAF5DB73A388FCF2B3BF2F26F21F8FFE26B29E642D99238D26AB94C4389E525E96A9C8CAD55B725F504971A4BD30E36168D48D6DAD37D48508FA61E06C464F127675C375D453D35AB4617F859F325284C79B255326292ACA480B12E62014D884907420C6E17C2C57C9955D2E966CE4CA33662322545B56167D5CF983A58BC76A0E25F1A0900D8DD4748001EE49B7B7E178A04CB9899C5131241CCC0301ABBF2DAFF663D2EAAC630DC12994B99592652908D54B0901D2EC6FBF9318F10CD6CF5C2B95AC1949A9A6E7B1025B53723232AA1349D400B7C5219E614A82880438526DB91BC763F0E70DD5D700B452AE625B3254104DB90700374E86DAB6A776AFDBFD26088A8452627254B405B251303D9D9803AF2EA7DF1A398B9C98E332AA2E0A94F4E352BADC12D4FA74D225DB6D2EA87D9B92E95A4BCB5D93A1252A234A86C5568EF6E13E0F404CC13A53109BE64B1CDC85BEB71BBC79DBDA176DF8E71956CB934F327CC44852C128528BE62395FF0097968FCAD709C37F0139F3C46AA5A76998666F0CE1C69E417310E26939BA6CA2985DC739A4B8961FA80360409343EB370AB69D463B129F87A453B6596905C1609BEE753A00D6D3E66313C3300C6388D693512E7AC2F52A0A6BDCBF9EFA6B199ECA7F066C96C3F2F273D9A75FC538D6A8A4A0BF49A7CC49D3A85AEC35203CCB327544B60EC0AA642ADD49317D914A89432A52C036A007F205CD887FB11DAB83F62FDEA52B9B24826E428286ACEDCFF47BEF17668F0D2E0DE5E5DB97193D4C5686D0D0E6566BCEB8342401CC70D5D456BDBCEB2A5151B924EE638553B92420B126ED673736D3D3A467345D92612854B97369505401CC480059C392E01E5A75EB1F2E6BC2D78339F4153B95B2B2CA37015275DAE36B4DEFBE9356FBC36DCA7BF4BC71DC16CB90B7908C8D3D94E00101E9E4861CC6BA3B0E77B3B6A2C18479F55FC21383E9F43A24E8F8BA94FAC82DB92588669C6DA37049089F9D7A5943A821C6D440DD365011C042A4B14CB512F6B3EAFD1BAB5BE516AADEC7305AF49A64C9952CAF45D8007567760CDBB9DB78F01C69E08B94B502A770666B627A24FA8DD96AA6C53A7986C760A70539F6F6DAF757B7B0856B5AC5E41EA72F46D00F96F6BEE7AE71BEC2A55085AA9594521BC04923AD89776F41CF58B32CCBF06DCFDC332CECC60EAED0330649AE6A954C2EC9D2669686CA885075D553CA96B4A41294AFA9D29481B4502E94ADC9907723C3BB3E8CFD0B6FF2EB1AAE05C630D98B4C99352A009CB942890D70EE2CE77EB7B698CCCC3C9CCDFC9CABAA471DE0AC5584E6651C28957D74CA84BD33E192AB216D56C32649D1CD0E6FF18B36B1E8413455382A27C9528D382A20B0CAE599998DC5F90373B45BC2F1EC1E7A4FFD44B5D94124281B68EEC3C87EAC0F66CB4E2331BE067FE0A767175AA529D46B94997C3E6D7B25499852C92E27728643A54B36484AA3A7789783E7CF337BB9331249533A54524B59367676BAAC39C772F0476DB8A70FCF932AAEA264A40287EF14C19D8FE7B10DB5EFE91928CB7CE3C1B99D2ECB1213EC8A9A5B1F1143985A24A602AC2FA5B74B0F2D37B8BA49F99237EADACECF27A533679514AA5A4AC02E0E64DF6E6D601FF58DFF00ECD3B6EC231B954D2A75753AD533225454B41605B57B8FD39EB1EA09429E2B4869C25B27981B59496FA8BA885274DAC77558758EA6A8AFC5A9EA552EA67AE54A9530A1E63846549D8AAD71E91B335585E13C432E54CA29726A814254A32C256012C751AB83701CFD23AEE26AAA28744AA5414E252DD2E51CAC3A87969742912EDA98014E12A0752A69361AFCBA76B6F1D8B8157D64EA1CF433BF10C2EA96CB6722E40B59DEC34D43474CF6ADC3D82E0B80D62EA132244E1296425602540E55598DEFE568CEEFF0E5E4C2A4727B367887AC34A1399998B0D3A90FB92CC95990957E7DD9A32C669A3CC964BCD4B8756C6AD2E1681502A00E857C7776A58B70FE072F07C2B1614B574EB909A81DEA4295304A589AE012CEBB91B1B168F16F8AA7AF14E2EAD909967F0C85CD29580027F3B000F95CEBA0631B28AC9B04852260FF00DCDA10D293BF7E72529DBFF0B937D85EC078918EF68F8EE2555306235951521DCAF32C82B7D3C3CEFA5B6D35B850E172D0332C2410400540A8162C1B2927D3C9EDA4028136B11E97FDEDEDEB187D6628BAF9658AE5ACBBE75A89BDDEE4ECDE9EF174551CA67006FB973EEC469AC4D165974E0A9E6AC6BBA85EFA92E75EBE4F09729282592401F3BFB11E43DDE2900A2A1D45CF522DB7D6E361F3FC6209EA32D652953A406195EF6D8D81E8396A22A89194017E67D496E7AF97CE2A902E45EE36FD07A7BC49432828ACB1670E6E4BEEF7761C8BF2668A59A14569CA0B39CC46E001EFFDAE358404B5ABF2A4ABC81FD408A88A848D16BEF61B77ED1C042C9CB94E6E5BF4F7E5FB44AD167D4F2DBFB811C7407374A6C0ACA50906D75ACDF4A137EA5563602E4F6117BA2A450A6A8336594929F095037716F37B30F360E628EB0A84C94B03C28512B3D010E4B359B998F24CE9CD8C2B91196D8BB36B302A3274EC2782E9EFCFD4D7393ACC921F75A6DC5B34F6DD79C6C2A7664A4966552AE7B896DD2DA0842C8D99F86EEC5311ED0789A8C7FB65454D389D2C664CA5A900155CD937B073AEFE716AC52AD754052D203366AADDDCBFCEFA3B00F6D0EBADEEE63447E2BF8A0CCAF120CE5AA663632A9D4E87925862AF312383303A1130CD3AA6D25E52589C12E127E2872591776EB4FDA7DEB2A3E893B30ECDB02EC9B86E96548A6A64E24BA694B9B352077B2BF8779284BB254491DE2C8CC0A404900A9F68BE1EBB29C471CAA913F12C2E7A6515A559A6C92124020B9253A17B03625CB6E38F232125232AD536565DA9495966D0CB2997683494B4D00940012058040000B6DB7A4438862757595B3D6A5A84A5AD65291A24124E56602DCFCC728F5DF87381706C0F09A212A5494CC95252E909402E129D99B51ADDDFDF9FE40021054423CB75022FDEFB817EDBEE3E5145328E96A85C34C21B36971ABDF7D747BF998C90623364B499682258B066667173A7D058DB66450A30A5522CCF44E0509D519EE43EC1C9BF5DACDA472AA7156EB54C097D89E5EF7E9EBCA1159F8B2FF94B7917FF00FB629CD025258AD2DD08B9F66FBE508E3F16A7FCA5BCBFFF009FD3D638142925B3A4827A3E96DB6FA69AB422867A7F1B384A59C8950D4F8400347D2FD791E8C4264EA09C9972939D0A05CA466B93D1C69D039D440A0B88711E5D0A6D61DD4403C9D2799A3704B9A6FA129BA8AB648262BA46132F0B29A8A7AA429563952BB9B9E449275BC48C6A4FFB9514C9532513990A0CA4DBC42F66BEBA6FCA3C6F38701BD89284FD5F0E2DC90C5D86529C4B842B92CA53151977E4C29C326148B39CC5AE5DB2869492B55F61BC76870DF119504CBAA49521442559C020A5EE6E3F35EDB837B6B1A51DA9F6492315A7C46A3F0256B12272832092EC4836DC723A9B35A3DB7C2433BB11E29E31F185471838E0C4B8EB0AD569F3C1D05B53935465CB204D388504DD4AF8E2398A1BF63D63AE7E22F0BFC770AAE74A42574F213326E6431093529B249D8A7BA720B9BE9A13E6EF05E1D3301E24AC93894A3421357312813C6474A5458F89AC5CF2008F28DA854A2B529450A4124EA0A4A9373D3500AFE93D88D8F68F0B78E259463753DC8252998B0549BFF35DC00D650F4B46D9CB9B2E6D0A2648509882900290414D803B166D7DDEF13CBB8A6DF6D482906E41B916B14906F7DBA9118FD0E498334C504A8390542E48F6D6CDE7168975673E558290A39731B82492EC58D8D85ADADC18F00E287282899DD91198196D549444DCACFD0A61726AD05C996EB72E9130C4C4B5AEE151710B48522E4EBB026F63B5BF0E3C7B3B87B8AB0FCD5429822A258495AC049739487D829248E80FAC629C7F831ADC1E7CC44A2B2A4288616279B8F773BC6BA31E9D800681BCAD1EC44C91FF00464907401EE4585F4BF31CBD84792678CFA2999638B661C017CEA4CD4B21B3DD4E32E276B6F72542DD2334E026918E2A7A9208553A920A998A8BD9CEE5FCBE66351BE216BD349C3B5925445D332CE6CE9D9CEBA9B6B1B82782C61898C29E1D19032B30D299357A6CF6206D0A494DD350448B7700F507E17A81D6F1E2EFC7EE289AFED57144CB5E74A56A49F1020F88D9816F5FA5A3CA1967F115152B0011DE2D4E43D892EC762DA1E57DE32BC36474FF00B761F231E697134C1327CB4A5AC038075CBB9676B37AB9F2978620A274D17BBEBB37D9D39738E427A0F90FD23128B9C46108421084210845258B91F21FA9B456CC4997229D406555CEBAEA7DCB7BB44129250B528BB7EADB3DB604B31E7BBF0661C719E6724FDA5D84F426E92E8E674EC13ABADADED736CFF8671C12574A33E556648052C08B84B82CFC88E7B9B03160C7164E4CA49637B697258F2FAF5B5F4E5F1DECA87B2BF8CFCA2CF89060314ACD192A661FAECFB80265DAA926A53326E17DD3A509D12AFCB295AD42C83726C447D10FC09E3A317E06FF006498BEF589AA92952B31EF274A44B9AC4920782520816172EF1D9DD96F17CBE1EC5F0FAB5CDEEC4A5CB330E6CAC12B0A0F71E8E3D0C613B3BF897A661C969DC35835499EA93C971B9BA8344B89975105254CB893A094EE76BF4F7BC6ED55767AA9D5826E42139AE02497166660CE5CB38201BEE23BF7B41EDDA5E214CB952EA9C2A594B2661727281B17B33F9EFA08B10C278571CE77E3C91A0D025EB38CF11D65F4896A2CACBBEE3DCE797A7F983F38D34392C24900A16EA1002493B5E3BD7847034E1F4A842A4A50128B3A41623405C13763E47A346A462ABA9E2DAC9995732685A8FF003A943C5C8BB6D7EA0F48D8FF00836F0A0C2D964AA5E37CF26E5F1A6345A6566D187925B552E8E1214B5313C862C875C529490398E1559A50DB7BE634F2932D730A400E6F66D5F6B75BB74D1A328E19ECC27D22CCD99289EF082E52ECF7704DB77B78AE7A36686429F4BA34B0A7D269F4FA65365DA0894A5D31A4B52B2413609B252A55C84F97751DBB455C6C570B6009C3E5A54A94900009FC818BB390E19AC18ECC7998ADCE1EDF818476326A5126584A5297018D8338DF4D39F3B79C4A5A2AF30EFBF6EFBEDD2D6F78AE487487BB80403B79756D75DFCE382A0BF1B839AF60DAFA34020A363D4FEFDE3961C87B08E2260402094858EE93D0FE9D3AFD20C390F611CA4949046D13F31BDBFF004E8FCBEBFD5F85EF6830E43D847135A6865006CD700FD45FD629FC858761E9EDF48651C87B08B54EC165CF2559125F7291F2B6FE7F48E9B8DF01E0FC7D449AA3E33C2F47C494C7DA5B45AA8D3D1373002C14AD32AE29256858041484EE146F6DE28EA27F74A0819763700EF66007D6E446238A767527149E26AA5A49660C1AF7D2D6F6D6FE5838E2C7C20256AD2F55C6FC38BF372134969D9EA8E05A9B6D3466DB405B930AA6179965D43CDA3FFC74B4E951510129518B7554B15082084E8760E4373B7F88E89ED07B2B9D225AE6C896A0CE5D014347D0A6DADB4D630253F4EC759478A1E939FA55730BE26A1CC2982ECE33312AB94536E589982F213F1282A49D37D62C0DBDF03C5307EF73A4A432810C007B91B6E3A36A4F3B75D70CE318970955A10A5CF025AD3AA9603037BB8B59FCA322390DC4253B1F3030F6259A149C4520121D7B572935255826C0AFCABBA813E53FD5B4744F1C766C9ACA69825A594A51629706EE5AC7A06BF998F473B12F886A5A4912A5D45427326584A84C98F719458294480DD06D61B77BCF29AAA4FD128D81A94102B78F6B323469096974EB9A7A49F7343A8084EA5282CAD876C13BE8BDFADB09C030FF00F8461758BA8392549A79D3A62964654CB407CC4AF62ACA39B961165F880ED569B89A9A7269AA1CAD246542F5716663A5C5C3E91BDEF01591F25C3AF09F93994922D3685E1EC17457EB5E4D0F8C4537212CBAC29CD81BBD3A5D5AEE012A17EDBFCFFF00C66F685378BB8E31239C844CA99F34A10A3DDA4AA66664BA8B84DC3B9B3C79F8A923F1932733B95788B392E2EFBBB5FF004DAEEE5D5CD5A937DD249F6D8F4FD3F3DFBC68B4C524B82012E0BB8BB5C3FAEE4EA22B51A06245EEDCFF00C369BC72748BDFBC51AD7CB5D2C2C1BEDBE5AB4554462917F98FDED08443087484224045CF626C6C4F7B9BFE3B7BC5C697C0852B98EBB6CCF6EBA7E908A9636BF6BDBEB14E89E4542576FCC2C40259D83EBE5CBEB121572AF33CF57F7D629ACCAA4176694B436C254F9712A290D06C02A789B5B53771A6FD8AB63BDBB4B87B0B9FC478A61985C996A5FE2262107225CF88A6E7280F627A1BBBEB16FA9A8C88327C39A73A58B9373CDEC093E679BEBA6778DA71935EE26F3E91C1F656565F94CBFCB99875799D334E7F5D3311E2075E6D971130EA35B4EA29E996994B21B50004E39F7AFB7D047C24764323B38E0DA6E20AFA74FE2ABC20512548095CA12D20CCA898E0121D6912F44ABC565338ECDECA3B3BA9C631BA7A8EE14B97DE254A514E677513941219AC5EC768B0FA451E9944A53147A4B09669F4A9666564194EC1C742425D7937EA3C89248DBCD73B18D96E28AF4CE6A94ABC201243DAFB30B103DF9878F60FB32E194E0D85D3A0C844B5265201025A42AC058B241DBD01F37FA4949425282A2A29012544DCA881626FDEFD630B9733BE4899665DC375BFEB1DB19945C1240BB072CDD06DE513446E468488E21073A3DB941CE8F6E508E18721ED08418721EC2108A69A82EEC6EFA79DB4BBF3FDA2A242920B167770ED7E63CE207FB8FD444996179D8AB30D85C903DF76D3EAD15134A5495048B80790DBED8E9A8E713B96D02FFF00691F881195E1D332041258020B39058EADEDF58C2F1BA74CEA7AA494A4854A58BA5ECA4B3D83962368F21E174AF2A7C4332AA6F4A69F46C5B306940A7CA959AA4DCB09AF9ECDB5A80DF707D0C5E3B4447FB876638A84273A9292A700139532D6EE7903FA8DA3C8DEDD785E652713AE6A11DDE69E48284E424A967FA5AF6F96D1B8207D2B1A52A2A09011A95D490077DAFD47D0F7EB1E0FF17C8553E25896701FBF9ECE1ED9B6E619F4319B70B4BEEB87658513648D6E7F28D497D87AFAC12DEE55D0107D3AF7EFB7F68EB2739105CD94D6E56DB97EADEB45312B989003F86606661B9D180FB0F0B15794004AB600F424EC01F63D0FB476070ECC34757435E145065CC96B24129200BBBEEED737370CD17DC5D299B82CC944329528B0604BE536F1737F23CA3558DB9BA7FA74DEDF4F5FF78F6EA3D51C5670A6A13A0F0F36D05EE7993E71E01C43BCA9EC2F43C2120853957C5D8858A54AA1B1A9C710552E85A023CC08587C0E9717B8B11197607365D0D2D462534E59349227D44D568909929CE5C8167BEF7DAE63CE4F8A1E2029A1A992951F1A5490DA02410EDD19FCB6E7BFAF09596FFF0049786DC94CBC5321B4E14CBDA153D0D22E94B2EB8D38F4C24024A8956B413AC9370371BC7CFCFC4EF10CCE21ED1B159CB9BDEAD5327A8ACDDDA62D8F8586846DA7520C79E782AFBE4D42C6866285AEEFADDCE8C0F41D22E554004F96D627E63FE2F1A5D3CAAA7139A955DA5A8005F549D58EFD34B45753CBEEEA66302C413A36E6D1507416F48B12832943400903C9ED1510886108421084210FD221A4137F4B6FBEDDC03F3FEF15336685CB932C5D49DADEDF3F939D624D44DEEA59274B96EBF5E46C768A4BE436A4ADC4254A51290557BA428596E26CA02EDA2EBDC11B6E22E32E44FA697267074DC29C07D0BD987CFD48778B70A5358952F6059CEE4E9D1C9200D7908C16F8FE70F5FF0058B826C498D68D21373B5AC9EAA0C5ED2D085DC61F9144ACED6A78B8CA50EA25DB9494779AE21C4F2D2D29695A092A8F68BFD3D3B4D4D2E2585E12A58986A952E8D28528D9738F7692CE0BA49D1F958DA30BC6E7D46164896548502E0076617F7FD3CC46899905C3E66371199852380F2F69B393EE226597AAD599F65D5495224DE5D966AB3366D0DA025B5960A9D68909515297DBE85786174989CA96B5842959520B0058B3173AB92E0E9E71C6054B8BE3F39092A9AA0A206E581DC83672F6B0763D5F6D2E13782ACABE1730D372349A3A2AB981392ACA6B589E725C2E69539A0F396CBDCB09650547CA997D0916040B98CB272654821080371BEA3A3EFCC1F902636BFB3DECFA6538953AA25160CA254921DB5D5F7DDFD8C5E6B6DF2584C828A55C824AD68528ADC5396075B9ACAD76D161756D7D80B9110AA5E54A56C40568E3D75B7DB98D87385D14893292132D052003F945DBAFDBEF154129472C5823A580173F355B51FA9882385264212532F282030D353E807DB449A53E9F9910FBFBF68A1988528009F6F6EBFA1FDA7B9F53F8C5722E94EF6F99BC554B494A1293A800442E4F53788A238100EC6108974A7ADBF0247F784251FCA4F57F98FB313422ED226CA00020397F220071A68DEC6CD03BE8FF00C15AD3BF456DBFBF41D6E22D555256B9E0A4961A803404972E41BEDCB42ED1495D5C6956854A032E52F671A9B5F7F6FAC48E210E294E38B792544296F36B5F31B03FAD22E4109BDCA4A4A08FBC920455A299920ADEFD011B5B4D6DB6A7918A2EE6971E94B933509515BB381E5E640B7ED78B01E363814C11C5261676A9254C97A0E6B53D0E1C3D5691684BBB5AF26A0279A40128E9E604FDE6524EB3BEF169AB928217A39B0D2E5CD8837046F7DEF1D29C75D9953225D44E932929594A88200DBEF78D4DB1CE06C7591F98754C2B89A4A7F0F62BC2337CA4AA71A32EA9F966DD52553F2FAD080F0D4D26E4071BB2C6D620460588489C679973A5B245EE36E65EDC8D87EADA9F2A7631C2F533CA664E4A5135762E2C2E05B6671EA4B8DB353E10F9538978D7E34F2F6A95F924CEE0DC97A17FABAB95275B52E4173722ED3E5292D3CAD9A1315413333325BBF9952A421B4A52A11A6BF14DC6145C1BC198A284E122A2B50BA4968B34CA7095AAA54A3FCAA4CC4C801C87049019E2BC71855E2B35289F356B0F7CC492953DAE4E8C4BDAD1BFAD3A5D6C2A642921B2A2DF312940424AD492A5202400901A23400903E51F33BDAF631271AC66AABD3342F34F5827303BAB4E8C2DF2D62F400EEC16B9482FA9D8F9FBECDEBF45084364A9090926E49F5BF5EB78E8B9931EEF6FDDEC2FA5F488D3A0F2882D5D87D7F7FBFF0034E56E2D63A7D93F5D7DAF531327EE8FDF788211342108E53F993E63EB0892E35107ADC11F80B7F78B816EE5597928684177F778454241D449D086D049D879D5636DC8BFE16BDA29A8E42A74F4200CCA52D2C43B80FA00FA17F78A758214482FAB0B33F5F26DC83AF368C7F788D7144CF0A5C27666667CCCE891ADB720F533093414D87E7AB9372D3024E5986DC0AE6AD453F74215727A5AC47A55F065D8C4CE39E29A3A954B1DD51555395AE625E5CB75392A51601232104B8DAFCEDC29575588D02002477A3304B93AA59EDA5B96C3D747DC96A454E6A9751CC6C505D9EC519933B315FAA552714E393EB72657CE5CABCB2404961531BD908579EC7B5BDECAB461B4780CAC2F0E328228248A695DD1053DDCA4848CA1C92E43BB9BEBA5FD4EF87AE06A69786D254CD9290B2896B25490E0900FA970DF3F3F7148092D148B16505B6FBE942AD71BDEF7B0DD5757A1EB1D47895515CA994CA3E32E058DD8EF7EA2FF00E23766448972650952801943727EB6D44000901205801603DBEB10D2A4A644B4AB54A403E8037CA22D2231510842108421084226894172DF773E763A8D9DBA7BE91019813310922EAB8F4FF1103FDC7EA3F48B6CC010B012E3437F9BF42C475DA2E2856619B9F46D3689946EB427FA4A46DF33FE3E5174A69B910492C12F61ADB7DEFCB99B0EB66AD9266255AB3106DB3962DFDB61A3C7806369D99A0F107C386280B2C1A6633257349B0D2C998A616D249053A5252E5B55C9D4A24DB68CE028623D9C6352D5E27A7AA0010E73196962399B7A1667DFCEBF896C32448C550B6621614E181D4EFF00B39671A3BEE312AEF3909787DC74A1C6EDB0D0B420A6DEA23C32ED729BF078C62094A425E7CC66DD9675D083773A5DAD1D7782D4A060A84A7461E171C8BEE4F41BBD8E91F517E51E5DBA0FCB7FCFEBEF1D312E44C9B4C5694B842CB90341CC9E56D39B9DAD5B454C2749CC41233662DCDF4EBB368CF726290495102FA751B0574B5F6BDFDBAFB45DE8710264A2981F1A40209B1B036BEBE9B72789D3099E9553B38008EB6B5FA5FA7AEB1AAC32971E76E96C8503A4A09DC236BB9D3A0DF6F63BC7BE270F74A0A266752D0951401E2049D23D25E3AC5BFDBF0F99372156541D0B06DC8B1EA3576BF26ED9C0CE4C3FC5A7885E52E119168CF60CCAB9F94C5B8DDD5CAAE6651A664E792F196734A92DB2B9D4493ADA1D70A820A35142ED162ED478864F02F6678C55D48266D5A5726427433109964CE04EC0A5696D8DC0D2DE48FC4471DA315C5D785892A4AB2975E63B921258805C10799DCB46FAF2EC34DD3E9F2D2C90DB32ED6845AD608421B690CD9205B9296C1BDB7D605869DFE737B43E2395C41C5B89D72432553270CB9B9A9446A6C1FF00C46B5E08F4889885DFBC538243102F7B9DC73E562C5A390A074848B9FEF6FDF4FC3B4746AE77E17119B34A3BC042D838DCF36F724078BEA027BC52DC5DC3359FA9F5D5A271B003D22D130E65A8E8EA3F5842208421084210842237DAD6F9D8F5F4F51F94729B292A3B1076B5EFB38D3EED143588EF90C9246DE6EFF7FA4525B6B5EC8290B295A2EA49500971250AB0B8B129245FAF7F411971C4E4D5514BA64CA095A036721F51626EEC5FEDA26522D1225842F31CAA4AC652C4941CC97770403B3F3D8C740CD1CBEA6663E01C6D9775D6C4FD2B1CE16A9E0F9B95710172C6995A9398919E69D6C82A754F3532E0052A494DC5AE378D8FF869ED066703F1AE089505AA5AEBA4070B2023F88972E9D2C6CC4336BA08B0637868C4E6A67785194B90198B13721C5C8670C34768D347C3D6952DC3FE7A712BC2756E872B258CF09E2B7F10D16A330C8667B1150279C996C48294E0E6258A5B521AD2104EB1384796DA8FD5C7623C592F88F02A2C66410A45452CB5CC96924844E42121484804A9B2E455C972A277B76476672A8A8EAE54B9929335495A43EEC0F90B93661B30B4660E59D134D36FADC7D6DADAB001694AEF722E545B24DAD61EC07B18D84A4A638A2D534AC4A28BE53B82FA0B172DF60346EF615F83386A66499212AC83C235072EA6D7F60081D04546D21B6D2DF5D254759DD4AD447DE3DED6DB61D4C1338CF9D3699B28A72539B5CDD760DA7AED16454D993E7CC4A9C25077079ED766DC7C9B489A27F702FE2DED6D05EDAFDB472259DD6FFF00E503F58443DC17D587D7CAF6F5D3AC4F95910E54028B59C6FBB6BCACFA73844F4A42430828E6512030274844510C21084210841CF38453AEA132A600A482E0DD9F721CF4689CA948A8A55A161D409651D406D05C7BEAE7D4445AE2E14A171709205C7706E0EC7D2D15A9526621D2351AF43A7B1D0DBF58B45109B864ECE0660492120E9C88B11F460CF72F112A32C87C34B71C53D6E5A94417A58FFF000A824048371D527A01D22CF3E532F338B282B29B3826E357BB16B375B455E2B33FDD505053DD852487203380410FE7BF26F2386BF177C85CBEC4395A8CE49C9B92A4662E1B9C96A2529D12C958C48E4E25C52E9AE25B5B4A5BED1956CAE60A8A525C00B63588B57132A91183CFC61494CA14F295E0258928049676B6960E7918D51ED7702A4C350B32CA0A94092430209F223F73A18CCBF8117098BE1EB84F94C6B5DA6B5298AB3A5DA6E289A57C1AE5A718C34DCBBEF5165398EA9C5143A8A895AAC9093C949091B11F3C5F1D5DB92389311C4787281264FE1A64D97DFA26E742CA0A905486B04ADB30E82E7431D19C3B822EA0AA7998122E48208200D2C7524F2EA3A4678F65A52EA762A2B2E83D54EB842D4BED61706C37B0223C55C4EAEA4544EA79D30CD698A5E7279936D0F3E7B79465C0A913D74A2E5091E21A102DA5EF7E6FAFA22D0A566E822AD12C801C81E9E7AE9102904DCFA5A2189D11E908421081DC11EB112139D694870E407173025813C83C4A40D9449DB6FC37DF68A9130A14A94A199992FD6FAE8352036DBDA384AB307D2FF7E514DC0B582424AD2CADA3A41B6BE6150D20D8D8A74DC937EBD22EFC332BBDC6692982331A89C25EA7C374804B6A0BD874778A2AAA8124124155980BF524160FBDB4B5EF1A8FFF00110672BF8DF38720F85AA34FDE469B3CEE3BC54969D0B614E3AEC8B149919993410ABCB1959E2B5ADCD2E07800846824FD0EFC0BF03A384B82F887179ECB562926969E4132D94833D13F3290AD42A5B249DC66171BE5BD9AE1A78931EA6949053DCCE49510C4594080DC8F37BB6F78C65C832DC9C84853194A52CB689C9C6DB426C2588F864ADBB5FEEB87484EC9D3A08DC9DB6B254A9D453AA1532699B294A2528D59DFCF9DF5672FB47B3DD9570B9C2B8729A61502D25076D426DA752FA6BB6F1CA8C4EBE466AD35215E0752B233EA438E6C3E5611D954539536A4CA50600817D1B671CB5E7B75308A804100A6C0871EB15D3D1926AD2E0B28DC75BC23989508421084210844D4CF12D3948724BFA1DFFB037894B9256A4CC76CAC1BD5F9F51F3F288117FC41FC0DE29168EF0E70A6706CDA5CB0EB7D4FB454A67776026CD726C49FAB6DF7AC44EEB0BF4036F523F41F8C4EEE8A65AC380C82DE7D58DF6FD3468A49B3C4C761ADB930F6D62D67890989A9398CB5AB34B095C8E2391082904281332C1242B5796F6B74BEDE9D33CE0F989A8E13C4B0D98970B454F8F98C8CCEFB75FF003E7EFC55C95CBAE42D25FF00210C2E439B6A2FA6C402DA6B1B9360D9933F8570E4F120999A3C83C6DD8AE5D048BDFCC41EFD0FA0B5A3C59EDF28453F1157C94973DFCD503ADB39716FA6D1D21C3C4AF0C4254480E05EC74D03E9D2E6FF003EDAB3700FCBF21B6DF2FD3DEF1D038656A64266D32E5E74CD4A803A10A37EACCE7FB3467F86D32655266CD99C396D1CB0F5DD859EF6B44AB56B01247416F2F537F4F43D6DEE6286995F86AA42D57CAABEFA38D06BD7C85F9DBC5319150A9AA5829727297D09E96623A38DDE3510CD4C7A9C0587A7279C2815C7241F97A7B28365AE69C42C3480804A94B256DEC900EE9B1DC47D14601864C5A054CF7082B0949525C212E0E625C0CA01751E578D90EDBBB56A0C2E8EA24AA72065429BC61983DC0B7A46D09E093C1156B872C9B9FCDFC774F5C8E69E752A5EA3501509632F3D49C3C194BB212CEB6EFDAB6A7BE3669D054405256921201B9F353E363B6FA71495582D05524C9A797329CA10A1942925495120382490CFAB011E5A719E372B89F18995F28E748252E03D8924DDF500FA3D8C673396038B5A084B4B71C521BB58A01081B8B9EA4122DEFE82FE2A4BC4E6D4D7D4CE512A1354B984E61AA89720DBA6DC858463F4F28A05F99670C0FD4BDBC85EC4454B6E0FCC7E9FED168CFDFD52C936F11B7276F99F3FD62E487CA3E5E5F7F28451AB53E67EB114238842108421084210F3892A4DCB24B797DDA222E08B758AE91318A46A9B007A0F6EA7CC9884A1C3652C3A18A6E38A6C17EE12E320B8D85DB4EB48BA6FED7B77EBD2E778C9F01C6D7846274B5F2CF8E9A6A569209242828283105DCF41122A907B898424B849D0176D36DF97ED1A9878C9657CCF09FC66E4771B387DB729F8131BD54610CC45368E572A7256624DE70CEBA9B25B4CECBD542190E24EB2CB96240207D30FFA79F6B52789F8729F0FAB9EA5CC4C8945282B0425811354410E424049D587B43867153495D2C394B2C06B3862C36E6E35DF9DE2F5E8F5393ABD164AB72251FCBA6E42527DB710A0A6912F36D95B2B2B1B695E95E93DF4ABD23D4E5624292A92990AF04C50622E4ED76E5AB5ECFA068DDCE0AC6115987CB04E6F0071625DACE0FB9D5EDD23E99BA56A42B65A2DA927A8BDED71EF68C9534B925A2A4243D407246FB8FAF58BFCE94997314B01B33663EA59FCFF00B42388970842108421084210842108422827A5E68EA3F527E86D1CA67041C84FE60F60FD19F6B3C4C9246B55AE10852D67B250917528FA048DC9ED1552D795236663BE8799B0B3070D6EAF15669730700105CF202CE3C88DBCE283E5B6D21C0B0A0A5349D8DFCCF6AE50BF62BD0BD3EA126DD22D7555012B3999B5049D03B1B1F968DA1D5C58F11A99547267289014942882580F0DCB3F30FA6CDA5E31278D30A57BC41BC4032DF863C2E5E98CA0C9D9E6EBB98D55944AA669CF4C3D392A99E727261043082E1910994E66BBA4CC017DEDAB3F123DABD2F06707D723F129939E54E972867C8A5CCC873100BE64CB1942D9AEA4871BE96F693C44AC527CD94951584AC8201CCC0120025FAF237D2373EA1D029587A934FC3B45A7A69745A24A334BA44925096912B4F92406A5594A4252025B6D21205ADDEC9B6DF2C1DBCF1EAF1CE29C42A5330AD1326CE20E6FEA516B8B7CBDDC4621C373552A5906C140B06B97DF5B79B5BD447DE536842414A813B020107B1DCD8FB0F6FC493AB55134CE9EB986F9AFCD89BB3E8D72C390BC5FD2826A5537FA92475D8FB3066FED1244A8AA84210842108422649B4D437F50810E08E61A236F2DFDEDF97A44E969CD5A124FF3EED72EDD3FCB69BC219367D39FBEBA79791EAD514AB21006C1016FB84F72D849426FDB51B81D7A7A88EE3ECCF87535DC5986787313532F51AF893CB771A7BB5A2DD549330A85DD49661B59AFA3EBF7A0D0178CCC66BCE4F124CF9C5734F7C5C860899461FA6BC17CC976D72B313AA6996D77290B5952AC91B929BDA3E943B21C24F0EF661C394C94A659AA136A96C194A42A5538944976B10B6B6E6363BE19B877F1F8D575414B8926581E1704BADF4E6C1EEDB738F8081A753C9DCAF96D04F5296DC0B2E9B0EC0A51ABB0B88CBAAA715055F6201D7A5F97405F6EB1EC9707524B95824A90C3FED2037A680E9B39B6C3D2A463D509CC5CB59FC8B74FF3FAC433650A3A852D80014D676D776D5C6BBF43A9440341E42271567257FD57F784731C42108421084211297A8F2FD4C463F22BCFF684469FCA3D7EA629D7A8F2FD4C22B121F3067F09B7B45245AF7148162818450DA0971389A9810026EA3CD7D1CBB773AF96AD236DC11DA3B038469D12B08A82A0C324F5124B0CB903EACC367E8DAB468A7C57292BA99697B84A188D3771F3B746DDC1DC5F2E99533807062177E62B0D525D5A542CA0A5CAA09B8EA3A478AFF1013E5CCE2DAF45AD366BB1B0F196176B5FD341D35FF0305386A19C7892400D6605EFCB6B6C3CE3B99047516BC6B52D3DD4F2A018105B737D48D07E82D68CDB0EAA269F2A9D57B6D61BF2E9F7686FDBAF6F9C48D66B820B904EECFEDC989EBD6229ABCF99CF436D80F26FDCED1808F0AAF0FF00C55C6067052389ECF1A04ED3B24F2F2A7295BC19846A2CACFF00AB8D31D44E48B6FA1E4843B2F31516DD6E60A5B72EC102D78F693E243B75C3BB30E1A9FC3B8654A1788D4D22915B528983F86A99DE217224105CA4CB090B5784E6252DE073A9FDAD71C625C498BD4C81397DDF7AA09439D1DC1234B29FD9FCB751A5C94BD36974EA6CA30CCB49C84A372B26CB2004372AD957251600005B49E5F4D82001B08F01FB5EE32C4389EA2A27D44E5CC44E9EA5F89449295289DC9D1CF9F2D0C60982514DA7A7509E5E62A6155DC9661637BBEE39302F1CF26E49F58EA8C1E84AE92A27B0052950049D6CE5BEC6ACD17A12C06BE97666DDFAC4CAFBA9EFEFF4E9FBF48C7652FBB9AA503A15021EE799BF5BDC7AC44A5652CCF67D7FB4491C12E49E65E22842108421084210894A6F7B123EBB44C4A4100DFF004D7CA1104ABB1EBD8DFEBD7F4B402B2D8EC751E7088A9C2871B5E9E614292A083BEB2157D3DFADBBEDEB1365679F311293AAC8487BDC9034B3F417BFAC70B47792E625C070CFC9DFEDB7F91C7F789AF0B948E2BF843CC8CAF97944D4711B346A8E27C3932E361D9866BF48957661A44A020A83B32B32ED8D27512D0EB1E9AFC0EF6A957C1FC5B87613DF94A0D4C84141514A48CE014A838F09DC369678C22A54AA3AC490420858CA5CDC38D6CEEEFA90DD63017E1BB9C3378DF247FD0B889D73FD5F9433731836BD273AA2671D96A71D326F4C2576585051984DD40D80B031F4DFC3759FEF583E1F5E14266794898562E0F8505C5FA9D431F48DA3ECC71952A44A4297A849673CB467371F2772FB6431297D3A79E4294A69B5158E856756B4FCD1E51F5F717EDF97342E8A9A58FE4431BE9A6CD6D39DFA1B46C0AA689A84286E1FF60D7B5ED789E25C4B841C6E7CBAC2108421084210842108422927A5D614FA59BCC738A5593F8848D4302C35D7F6DB7D220AD2015292A58482A0DA05CB8A4EE1B23B85DAC477110AD4132F523C21DB5008FBB383190CD5F754C565DBBB3A5F627F563EC1CC5A671B3C43C8F0F19295DAD34B44E62EC4F2EAA1E0CA530A1F13313F526D4DF39B4EEA2BA7AC327CA094FC40E9717C271CACFC3D354CE52F2F752662CB9032E51F4E5A5FCA35E78E7890D3A6A519F2E64AC0F16F71F4DBEA22F9FC1338327787DC80566BE60C9B9399C19EEE9C49896A5506FF00F5D44912D97E5A454B7017521C5CF3BF78A2E5AD85C08F9E9FF501EDDAB958B546114552A4C890B5489684A880C0A8198B0090662C0198821D83C6AC842ABA7D4CC582A2A98545F525C161CD9EFB8B98CD9A15A9A64A9252E7291CE04DC87ADF69D86DABA6D1E42621366E2F4D32B66A8AC95924B9B9625FEAFCFE952995F842325B448036F32DEFFA5A268C31ACFD5BF7FD22ED4CB52CA546FA8274D8B5B6F9EEF7847115D0842108421087489B203CE962F750D3586B004690013604FE837FEDF8DB68A8929CB5E010CCB4FA31737FBF23A44A9C7282E40607E42DA6FAF5D7778E0D59458A7CF4CA1CD21320EA7D2CF0438A17F53BA4EE36F5BC6D276252E5CCE2DC252A00BD4C92188BF8D04EC7F6DA24C8489A5208198A8BBEC39F9F98FA88FCE5B0D569CC479DDC446259D3CD9BABE624FAD6A26E796D4D4DA5BDEF73D556EDE9EB1F4774129345C0FC252C32569C2E4A54058384825FCC11FAB5A374FE1629E5CB9B8B4D2920E6490FFF00E673AE875243EDE9EC65C7145166EC92773BED7DCF6FC77F6116A54C7B383B81B7CB7FB31E9BF0857E7948927602DF4F7663D793C548A399737BBBF41FE5F56E9A45FF001D941092B4B30662D72ECC7AEF7F43088348B64824C996497748BF384226C2108421084211297A8F2FD4C46E04B5396BFA6DBBC2234FE51F7BC53AEE43721F5308AD46A7CBF5114330E542CF204DFA45B7E774A3F8AB15E4EE0C934972A98971A25C6A545CABE1255FA7096361BE9BBEF5BBDEFEF19AD0552A8B85F14A963964D2543EC33A903207E658EB6B7988F3B3E27311EFB134CB2B21D4904022E013B74275B7B878DC870FCA894A6D324D07ECE56424D86876421B65294A3BD80B1DB63D7B4785BDB9622B9DC675E12A71DE4C26F727BC3AE9F521E3ADB8765A66612826E4B5F46B06BF93DBFB47DB73B7D7FB474E544C4CC4CB601DB5DDBF4EA09F48C964CBEE29CAF51A3DC5DF9FAB86E514E24CA0EBFBF3FD2212B706DA8E7CFD2325781706E1CCBDC3F46C2783A912587A8187E511214AA653586E565A4A5D0D86CA1A69A09424A8005CD22CA56A3D0C639DB0F6BD8A717625513313C4D75A55314D9D6A55CA891AA94C1DDDFE7B68ECE94BAAA9335473AD4B2EB2EEE7FB9B39BDF6D3BD21094202136000205BA00493B7B5C93F324F78D6AC4B129B5CBBAC9960061D43EFBBD9FA003577BBC84AD08CAB249B6AFF00AC4FD22965D6D44A96654B985282194012C793DF5F3F389F0F6EDE91486E49DC973D4C70C0EA01F4842398421084210842108472091A130880481B811C4220B52920AD3BAD035209DECA1B823AF422F7ED159875AAE49019960DAD1C1B850E6086E6E343D0C715D9495130D9754E34DB8C292DA59074B4B55C95213701249209F5EE768EEEECDB1D9F81F17D155C89E64AD35129614924310A4BDC37986FD62C988534B989CEA402522CA3724B6B7F3B9DB511A72E78E049DE067C57AB54B0CB749C9EE2B15F174C4348F85A3D2EB9539B71993FB01F6085B4A75D5CC292A04731074F98C7D497C237698788F8430DA4C42AC54CEA7912E58CEABA92B48C818A8F892412A2362036B190F02635328B129728CF5265674F85DDAF76BB071A1BDDB9B464F12E05A5294DC36948E56F70B695BA1E57ABAE804BA77BD931BD48CE9F102A0850F0F21A6876707CF5BDA37530AAC978861F2152085282015A8751EAC6C1B73D0E9344CCCA2CEA25B99FB7F58E664B9D98F8940B8D5FE9987DD8738433A9FF003126C2E74E5AE9E67AC56D2D8B2CE81AE5EFCBA9FD7D1D15892E073163D4B5FD3E711AC82A24583BB337A11F77844510C2108421084227F2A51AD7B2756907BDEDDBD7E5F3BF68A5AFAD91229172B20EFD45C2B522C2FF002DAFCA38FC14E9AA13C12109074B7BED6B6C74F6E24FCFA28928F55A69D6A569B4F6953B3B3CF381A4CB4AB092E3CE95A8F4420151E9FE2D58555A65226D456B2E5A412CA701989DF4605B4F90618FF117114AA2A499294B01484900067B0B8D6F7EAFAF58C5870B795359F13DE3ACE2EAEC8CCBBC2D70FF003AB7E48CC053F47AB622726C2D99032CB0259CF8A4D36D3977095252C6A49B46897C5676E143C1F846232A82BC5356D4C99A8972D2B0932A46523BD5328399C49082D6EED5ABC69BF1BE2F515D5EA4CA9A4CBCECACBB927477361B8DC7946E2D44956E9F288A749A12C4936CB4C265DA1A19E530928693A00B04A53B253616FCE3E69BB56E309FC598A621598AD5AAB661A99CA44C9AA73F98B0B956DA3683517734D229A4A5083DD8CD95DC8B8767F7611DA6EA3BA892A26EA27A93EA635B2A2AA62153244998A448CDF901203DECDA35FDC9F49A644A2CE816D180B422DF11265A505D21BD9BD035A1088E10842108421089F4ADF8894E1C670E34E708748A99A526BC14DC7789D39BD9BE512A6876E773E65ACFEF1F22B6426993E4B61C6D328F2D4D1170B7396BF314DAC49000FA7B08D9BEC1D4A1C6384E73635528E52DB2D2CFB38E4CF77722F13289290B0E900B827C81D1ACCE3DACE1C47E711976D191CD2CFF00A3CC20375092CC19D49D40071083393C426FE801DAC3E5E83E9196B13B82384A64A0DDE504A5E9B14A3A93B6BEFAC6F7FC294BA69871B0B969CC3BB60A6DB3E9A3EA6E35F28F7E52CF90051D3A74903A155875F736EBBF78C6EE94DEE79F2FDCBFD79078F40B87A9A64B98952414A2C459835D98F2D3AF48453CC98A50092A2E3DB910D68CC6BD426490959248E7B103463EBB7D211126C963AE9E57FDADE516B94C25A43378436CD77B7DEF08E623842108421084221EE56A0A98F64D9B61E7EFFE4C43303CB3D0A8FC87DFCA264A50A365A8A4589B8EB71D07BDFA44B9753290A12D4D98170FBEEDF767DE2A70B97DEAFF008802824BDCDADB6FD77B9F489F415DC200B01D48B5CFE67F3F5ED19261D48AAC9D2B2273256B4A4DB5048D6C6DE7C9DF48B6F1654D2D150D4A90D2D48913141ACCC937E7D49372EFB4752E13F06CD67C71F78224512E66E9595D4F355AAB83ED25645C919A694B4366DA50A7801ABA151685FEE889BDB26274DC19C115C3BD4D32AB0494CB95A674CA44D338962C582E5F4BE8C03F933DA763231FC6EA52B589CB953E6049D48F17840F624B1D985E36D169B665F4A65C290D048E528F5522D64AB6BDC11D06E01FAC783FDA46209C5F892AAAA511312B5CC04A6EFE2B3FB9B45470952CE974C1131CA2C4077000E846A4124ECC20493D493F38C49669D144996B4033C29DEC0E971E96D75F568C927CE42A61903401C87DCEAE3AF3E761108B7A662125C24FCBF40225E54F21ED195F4B0194F9544DAC06A24AAC361756E49E97277BDCF78D40A933EA27296B249517724971D2D7EBD59DA34B68E50482A5067B6F7B33BBBBD8388AE8FBBF58A59B2C4B2066CCFF00DBF7F94561001B1789A254710842108421084210842108421084210DBB8B8EE3D47A44FA698254E42D5A24BF4B11F7F281D0ED6D794012140EA06C7CA08BDBE5BFCAFF00DA328A1AE5C9AD97572CFE5585120960CD705B6D472DA29EA650992169087394B293D41DBFC6BE7182CF1DFE1BA733638617B3B707D352EE3BC84A88C5527312C926A535245B4BF3F2A852105C976E5853D8534E365C254F39E54E9055ED07C0BF6C424E3384E115557DD49A85CAA65AD4B3FC2CE40EF402D9B28D03877D4461D4D3A6D0D726600A395692002CE017617771E76EB68B5EE1633969F9D59138171F22650F4E54645A90AA34DACBAECAD6A4D96454A5A6490952032A71A0DA943CF75929469DFE85703C4E562783D0CE42B32FBA057CC1CA9D6E5DFF005DDA371BB28C7054D1CF44E5B8CA9CAF76E4039B33DFADF668B8C01614E2169014937480490A6B7FB4B902DFD3B0046E7CD1746E7E9D3FBFDF9F702A64B9E1810C1807372FCAF7D39FBEC8453A93DDE8E4E97EB7F6FBB6908AC941903ADFF61E8D1182E01E61E11321084210842108896D6E84357437AC3CEB2E4CACB5284CB212E4C071D407168286F42B669448FBB73B463D5B23BEAE4052990C1C1660C777FBBB795CCE234D4784CE131694AC956A766DDC5BD3F58C5A71E79B18CF30B10E13E0E720C4DD7334735DF91A7D6514A79C43141A2D466554F53130F4B85AC3CF813066D2A6D0897974CBB816E29D525BEAFED638E309E0CC02B26CFAB44844992B5AD49290B510939509B8754C6200FCA08B90D1A71DA37144C5554E972A61233166516D4B13E5EB7F71B2F702FC20607E0E787CC2994186996D7504B0D56B1BD610D36CBF5DC5936C3226261C436562CD96B4241715A49276D463E69FE2DBB72ACE2BC72BD326BD739014A952C09855965A54A09426E5807366677E91D4F4895D72BBC98147C40B92FA8724B976766717B8E422F219934B26E14543AD8A401FA98F37710C5A7D42D7994ACCA249B960FD7578C8C0603C9A39A4DCF4B6D61162BDDC924926FD60030FAF53CE211CB866DDDFD1BFBC7308E2108421084210813604FA0BC47295966215C943E767F477812C09E5135C045CF404FE62DE9D444F90AEF2B90543550373A653FDAFEFB440F99C37AB3B6BD7969D5F68A2EB48986B4BAA6D2C2DA7DB98D44DD0909BA5562083AF5286E401A7AEE63613B25C565D0715E16A2A0922A653DC6CB4DF5B6E3CC126E625A96A9398005D2C42AC013BA497B00C1CDD9C6BA47E7B79D181E632A38F0E26B08D41025CD5316B957A33253CB33326E3D39A5CD3601215736292A1707DEFF48DC058A48E20ECEF8566CA751914269E692036794994A2DCC34CD0B1E40C6DA7C30F12A68312C4644C98009CA94C093A12B1A1B91AD8EBECFF0057ECC2580959517105C7469B729D16B35B1370756EA363B0B88E3104892ACBBDF4274BF51A6C5CBDC748F57786172EA30E97516FFB60E9A0B6ACFF00ABDDDB589E2D929A61629D03B6B7F4DF58A99930CD9C65BE6D773ABB173F7ED08A8D22023296E56F6B421084210842108440F436F48AB97325A299695119944B02402CC7EBFB6B11E42A412CE1F4D8EDABEDFB36B14CAC124B89B348BADC55F70840BA881B6E05F62403D2E3AC634AA69F36A9D092C556376D7FBBFCA394D40A294B5964B026E40B00FB5EFBB74DB4F38CD6C7F2F80F09CC55CA4AAA01A7D9929242C844E549B405A2552E8BB810F07590D3A1B5152CBA9D00201576F70AC812C4B33328292082A19420002E4B5920DC9B30B9208BEB076B7DA2C9C3E9EB64F7E12552A6A00CDB949660FA9E8C766DA32E5E117C303D94D94F58CE0C6D4E98463ECDB71B9853F329297E9F2812E38A95438ABB8E36FF00C5A752D41B23942C937DB49BE313B4B4621493B0FC32A8CC954C1725012ACB701944A42884A94D7D49000E51E7660A9A8C5B17AA9D312A226542D6E5CB82A7DEEDD47B46608795B61BB11C9650CEEA2AFB808D89EDBEDFDFAC795D4733BEA89F327A89CD99409F76EBD7AF3B4776D2A25D0D2A5360A09B82C58B338E7C9F7E42CD1B0B5EFBDFA7F78B7559CD3D65F761E4098B5A65AD55467310823AB3BF5F23ED108A68AD8CB446A04DA82A709B0E9ADB6FEEE5FA469A29D23C2186EDF2FF003E5787D6FF008FF70229CA94ABA89F53FB130412439D5FA7E908E223842108421084210842108421084210874EBD3BC22098F94E5D7F4895685DC2C03A46FD7DF6FF001D37FA08BEE1B324A69E609AA00876245F4D46BA5F97D23994B4776CA201637201F6DBD2D1D4B1760EA4E37C358A309D6E525EA14DC594A7E95352CFA02E5C4B969E439CF6D6929597BE200FBAAD91BDB6BED17C3671B49C178C2833D4AA5A13532B7292C16346D7AB9EB18D55D2854F0B480466D53BF5F2FBE91A6CF0BF2B53E0F78CCCFBE09B190E4D26A9587B1860371F0A0CFC1BB373AD3CED3FCAA484BFCC94BA11A5C1CB4EB40B08FAAFF87CE33A3E27E0FA2A8935499F964094A577816BEF25206652C139815661E7721D8C770767989A6915369D331944A583B1B92C3605B70010CC232D4D21D265D6A515699275A716374A96DAD91A491717373626C15625254018D874CC428120D87DDA36530B33E6484CD5B94B03989B333EBD1F7B93B0BC4F1CE649DFE47F68BD2549AA5044A7528580B33BEF7B69AC22E32D0AC89B6C371FBC44A4141C8AD5363E908856B08B11A6BD3D9E388136EB12CD4203B916D6FF00DA382424392C39F9C46C6C0F631C0A9964B0209F33FB40282AE92E39889524293A93BA6FA49B1001F7BDADEC4EC6E2C77113173512D1DE28B27AEB6DDBEFD238529290E48116ADC5FF0012742E1AF29AAB8A670B351C4D32448612C34E1E63B56ACCDD98972CCB2438A765D9794CAAA20367992C5286D2FA816C61BC4588FE0A966E2692934F292A4A979C27C4C6C4A88000704924243B92D78E9EED0389FF00013BF0D2E690954A0A64BD9C1B9018936D399D768F77F05BE0731261192C47C6A67F48BF3F9E399EB7AA785E8B536D2F3F8530FADB4B92936DADD2B6587EB2A79D9795432BD6D7F2ED4EF242904F873F1C5F11F49514F5D826098A899512FBE96A44A98B75AC3A4BA8B16B3253A02090D98BEAE63552AAEAC5AD799492336627C24927C29BBB8675386F10626E6360E6E518974A3E19B75284A532ED36E2829C6DC04AD538E1D4429254BB0B2D4BB20F9378F0B313C5B12C4B119F57892D644C3317996B511E251CA082E0285EC2C5C39378AFC384B44ACA03314957E51993BCB497724F3206A09B3373631559904924A497D4E5FD58C57C229A6F77A219DCBB0FB1EC6108930842108421084210881E87E46394EA3CC7D638502410358893F6647537BF43B8B6FF005F6F5899295DDD4A56A0C124BFB9DADCE21969297CD7F26BDCF5B7BDA25E59710B4292D212B43683AF51D7A54B2A26C93D01036EBF3BC661C33894CA7C7E86A65A94254A9C852D4EC0242817B31275EB6893529510AC84AB3289E89748013FA82CEF6D2F1A6B78F4E4F5432678AECAAE2464248B387F33A48E1DA9CDB08024E5EAD479965D5B530536D2EBC8AAA4A4A93A5C083655D26DF463F06BC694BC6BC095584D1554BA89983A69E6CC964B2A5AA6CB5266972D66948B03E4EED19FF64D89CEC1F8864F7AA3284E988487536665161E5767B1B69162ACBACBAD735AD2E2668B732CAD04292595A54A2B045C58DC5B7055B9403636EF1C752D5464A1CAD24860E030B1198116F76DC73F69FB37C4454F0D485A5798AE44B3A83FCBBDEE3AFEE62AC5253D1CD949EF6686494B0653BFB1DDADF5074CA2814A35AA330784921C860CEEF7F21FDDA110ACA41241B5B5F61FA3F58AEA85CB4CD580A0CE75F3308862505A54582813C84204B6B13532D4BFCA1FE5F7F7C8C2210A49B3FD626FE1677F4FCC42228817266203A936DEE0B79C06EA427BAC94A7DC8173BF4D81BEE445B278AA5D54B972925482DCB9BDB7B06F5EB12D388514950A69B31A7AEE9433F84B3B97B6FC8C70EA33B4E94A7BD3B3936DCAC9212EF3E69E0B4B0D36C80A7D4B5D88D2DA3CC40B950D9214768CF705C3A5CF5A25AD2F394058A7F5235F3F326F6C038FF8BB09E19C36754621569908085104EAD94B69EAED6717678E1F07390D39C6FF0010CD57EACE25192194F3B25509EA729414D56A724DF71F94A7A5A04F3DC714CB85D52829A2DBED02E120A5359C678A2383B87F145CE4F753E7D1CE9689A09265A0A09CA948DE6BB1558A02410F1E5776B1DA0C8E29C58CAC12B7F148138E6092012A2AD4936F0D980B12E368DACA4A5A56954DA752A4E55A94A7CBC9A65A9B4E603653225B4A5082A435A90D92128B5CA774EFDE3C52E30E22ACC6B13C54E26668926AA70415A54A74951219FA3EB6BBEB17CE11A1934B265CD9B91331684A95A13988E7A83B5AFA6FAF2D9E6165AE60B2D09E5AC92012B46CA3D771B8DF707B131D23882108A82287C4093F96C6E77FCBAF95B9C5F3129B30CE0658796E1CA4E9772587CF7D468F135FCC5237B024900D86E075B5BBFAF689D4F854F54B33E6CB16198EE48DF98D4F4BE9D6E5F8DC3D34494F789EFDC166255A1B3EA4B6E6C1BD627D0AB6AB1B7AFF00B753D228D53A91337BB09BBB5922C4EDA8E607BF28932A626636453967DC1FBF27D632CD1A451A75084210842108421084210842108421084210842D7DBD76FC606C09E51C2BF29F2310D5BF2EF7F63EBE87F5F43BF78BB61D2D33654E05883D5B401B5DDFF4EB14CB43A416005EED66BBD86BA6FD622B6961B65B6C9F8879C992D01F7B4212D6C091BEEAE97B13EA378CA383ABD38263922A9F2844D45C69E151209F3DF901D628262194AB5C0B3960E5F7D187B7D6358DF1DDC86AE60BC4F93BC79E57D3172D5DCB4AB9A463E725501B54DD26A8E4ACC21D9D527675A964D32600E6936E71B0DCC7D097C01F6CB22BF0EC470A5D4A14EAA70119866CE91312026F6D4B80C15BDC089F86E2BFED788531272E755C8274047DFB69631EA396998341CD3C038771DE169B6D549C4F234CAB34C0375B4C392CB5A257A1D2B96E7044C0077529172A22E3D9AE1D992B12A04D424A559C036B9BB1F95DC9E76B46E7706E292B12C36520AC2894246CE430049D2F6D1B7F28EF315E6481332021B301A5BD3A731BEDB465F2650A39D99AC4920FECDD08DEDF545CC4C094A5214C121B293AFAECDA86B741098BEF16A5732FF7F584524CF1153117BF4DA20881FEE3F5114736966CE494CA4F8CB161B804126D7FDFDE25CD495232B3B90EFD086B6F7D3A889D5FFB60FA6AFEFEC7D3FD8C5D6824D0CA1DD541489C468AD41FF222BA969E58944AAD6246FE977BB373E7B474ACC1C7B8672DB0657317E2DAA3146A4D0255CACCEB8FA8A135497936B9A65A5AC0DD6AE496AC020951B5FBC635C5153FEDB295349690DCCF89CD983172458003CA3AD38C78965E12898D312E87736BA6D6661ADF5DC13B98B1AE04385AC6FE24DC4F4BF1539EF439A94E1AB2C2B68395586670E993C46FCA3A8984CF4C4A2545A9861D99E520A9FD4086D4922C2D1E687C58FC51E19C1986CFE17C3ABBFEA2AE9E62AA929210253A549125ECA135D24CC6190A549F11B81ABDC47C49FEF95A6785B840284DDC177625ACCFA1D45CB6B1B74D3A4E5694D49D2A9F2ED53E4241932129292ACA199532928847C3B4D25B4A5004BEB51B048FBF78F9CDED538E67F14F1055D58529626CD5A9DC9FCCA537305B99FA308C6C4AEF941C056C76F23E97BB5F478FAA5606DDFE5FF1DBA474C6293E729294A828279836EAF7D9F95B66B98BBC8A6EED1CCEAFFA00DA0E4D7BEE584D16289F0842108421084210842108423905883C883ED08409724DEE77B98452712E9E9D2C6DBF61D00F7FF6B45EB05599738298366BF26DDED77D8B9EBA3873F9FB0FD1A31DDE267C204A7197C2A63CCB6128DAF1652649EC53822A6520CCC8E21A5CBBA65589776C56D09D53890E041D2B2CA35821223D16F83CEDDC7657C512E8A69CD498C54D3A6AA4953266CA4A94952482406F19B10CD160C4F12AFC2EBE86A6973012D4E4A1C310525C91E5ABB3DE34A4CA5AB54E9ADD7F2BF1AC94C51B1D60C9D4536A3233A0A6652DD08BD2C89720951E621530BF880482496F5151008F77E4D0E17C43C37FEFB864D975027C81554D312E153254D4674299412AB81A1D8691EA07C3376CB4D88D1D1E175F5094CCC92A5A90B5B97218EA4805D9CECEEE58C7B0C74D61F5F892B1799455695A64216A4877D012036D60F7200F3DF7CB119085D2A2B70F2159D216E82082F7DB5F2D356636846473901331413A662C072E9D3A6D1229A42A6CA4296019840CEE40BFDEBD6112B2AB91F689A640478B2A411A31FBE9AF9EA211C290588367B3FF00831455556B91297DD139810183BD9B421EEFAF4B1BC225143071B3EB7B0D35773CDE20A2AAAF9E74985C0737D2DCCB6FE606A39225952DED7F33FA388AF9A8AA2851567B6CFEA4B02DCEFE770D1337AD2E21D6DB0B0D2AEE29EF2CB21B558294A51F28504EABFA0B45E30854B4CF96A9D2C1255F9887013B925886D5F76E767B6621270FA1C32A71AAB98844D9095105643B24022E5F57B5F5E8C63CE72FF2831FF1D39F546E1AF2A915046156EA32CFE3AAEC9179AA6C8539B750ED450A9B97F373D72C1619654034EB83438AD37233CE34E3AE11ECFF00860E3558BA7A7A9EE262A982D28CF31494F854125C99614F99475B84B9063CB5F88EEDA2462CBABC1A9A7A660495CA2016D1C063CEE188D2DE719B2CC1F054CF6E13E992B98BC0867A54DCABD229ADD42AB97F8955332D2D5DA84A239CEB68937587B0FCEA0A8680671E0A21442AC0DA34C387FE2AF8278FF18A9C0B8A853CDA31366265CFCED36582A09F0824226060084AC9483A6A634164E2988D056AEAA485A42965434CA6FA16248FAB36B1E5B817C4A330B2C310BD96FC6B64E57B2B71207112F318C29B8704961FA8104B456D4D4B34CB213A81714B6DB03CC08247495C5FD8AF0771B61D3712E08AAC3F134CF54D50A692B952F1090C017994EA282A01F59066070DC9FB4F03ED3EAC2E5C9A8CC8203397297B3B2AEC5F57637DA32BB80F31703E6361C97C4382715E1DC5524FCAB4E308909C6E6265964A6E96E605814CC3608E6A49D4091F38D22E30F87AE2AC126CDA9934D53DDA4956421492C1C8053F9800016B01ECD1DEB81F14C8AE952CCD9A9399237075D5FADFAEDADA3B8E9496D971A7C6879056B95BF992B007986DB04824582BBDF7EB1D4758713C03FE9EBE926A43E425692DA9704E86ED7D1F4D233DA09785D52DD2B9654012580D0B1B7936EDA5A25D5A4137500373A0E95586E6C6E2C76D8DC58D8DC4712F87518B844DA1428CF9846542527F317374E8FCC9B1BEBBD5D65561D874951CF2EDA170DBF3772790B0763D32D11E7D469B42108421084210842108421084210842108421111B11F3889092B5040D54587D986B14EDA9C161736DF6DEFBF53EDFAFCA2B25D42A90A917D9D835F6B5BE4F7DC98100A43E9703A01B8E4D7FB789DE5594829242DBBE9503E64DC0074AAFA85EC01B5AF6DFA4402A26AD59905414F60EDBEF71CBD229168046815E7707CF359C5B5B8F68F15CF7C9AC2F9F99319939518C65513944C6186E7E9E65D4D21C519F71A58935B214094BE85A8E871165A01558D8AAFB9FF099DADD5702713A29D550B962AEA656519D4904A56C5218B87CC46BA167B458713A25CC99267A411DC92480D616F16C1836B7E9D351BE01B10E21C84CCFCD4E05B359D5338A32DAB1547F08A674ABE2A7E41A9D5CB4EA25661D1AD72EEA8492E55B42B969690BE5A529B88FAB0EC2B8E2571270BD2E212EC9AA912E78961B2CA529214A96350C876B38362F1DBFD9A7189A59B268E64C7282941753BB167673D4DEDA3EF1961654EB92AB99290801DE5B92CA1F68122E09077576EB7DEF1DC526B1332B169170547C2198DCE8DD0F4B6DCF6B65D50ADA54CC43789292082E74727FB5F52C778AA34FF45F41DD3A892AD27EEEA277BDAD7F78B81980AC8666B11B803A8616B5A2343E50E19801E6D63ADFDE11390339617B121ACFEACCFCF7E71142C4824148D0953B655ACAE502E1458EC4B813A123D488BBE1D369A8E78A8A864CB0820E6B80A2922DADEFCDB4E71C804E9FAF9ED1F231055E9B46A33F5CAB4DB7214490617539FA8BCF2586E99C8056A4CD28A9376FECEFA141492955883731D5DC49555E9C5975D499C5225454E9242425CBBE836D9F48C5F1EE2497854A58EF02084ABC4766041F97CCEF18B8C3383B333C5B788890CAFC0CB9AA470BB96B5043F8CB14239B232F88912132A999F9365F486D736CBC1B534191A90B4ACA4A6C483AA5F129F11D85F0670BD4C9FC4A25E26890B12A5E609989535A6AAF99241F14B7F166014C12413AA9C6FC4F331754D972E6382A21C10C45F7DDDFC8731B6DFF0094796984327F2F30A65AE04A54A5270B613A4CB52A9B2D2928C49A1F44BA945734F34CB6D85BCEBEA7097560ACD937276B7CC9F6E5DAE62BC77C5759593AAE74D42A62C24A96540BAD4CC4923D4475C61B493C662A0A2EB203DDC1E84D9B6F2EB1E8AE2825494800841514816B20A800AD23FA4AAC35586F6009368D779B56942CAE6A8951399CBEB7D83EDE6C3934657229932D24E8AB392EC7A3EA40E8E1C9DE298428EFD8EF7BEE6FFBEF11AAAA92AA5A86AACAA60C07D6FE4DD5E2A0CD4203393C9FE436B7B6ECF15A3175B675368E5A21D6110C210842108421084210842108405C81CE108BAD29EE806706C5FD5EE3A107EC423813626F5244B381B4AC10E056E959360949491624EF6041EB19FF000A62429B12A6AF3332AE926052482C5DC1E6FB6B607CE23CB48B953135284A8A8320A99C58BB1377D34E578D63BC627C31F1139885DE32B869A73BFEAAA448CE54732708D325137AE35AD97E6DC97A536D166727E61414A5BBCA53EE04799674C7B87F09DF131475D87D3708E395485534C97264489F3540AA9969192512ABACC86242903300729086048B5F0BF1262DC1FC4126BA8E6CD448973731C8A21050140F301F5BEFB98C0F607CC6A36336A62594B99A4622A2ABE16B7876A61123544CEA0A92EB6D4ABDCB73CAE2169B2136BDAFEB1BED8A609435325188512259993E5F7C89924A5489885004292B4B820821C3BA5D9401D7D69EC5BE23F09C570CA6A3C4AAA599A94210A13141CA998820D817605F959C88F4E96507937425ED42C552F38DFC32D83FFED17084070A142DA82DCBDAF7B461AA92B428A569F10B1701FE778D8DA4E2AA6AF9C6753293DD4C53CBCAD97293A803417B10D106D4495837BA480410748FFEAA3F787D4DBEB10F767FA47CA329155DF49CD620877166FA5F5D3DC69139BDBCA424EDBAAD61BEF7B823A5FB758953D39259565166D81672DFDF711434F3651AA409E5D0A512ACC036E40E4EEDA74DE2575D4B68BB8359EE5AB8F97DDB5AFDF7B9BFCA25534BEF94D7655B41F57B7F862F1929C5707A196A566941924DD80040E418BE83A920BB470A72AB212095393938DB326DB45D5CFCE699269A013A8B639819E6949F2DC255A88B826F739252E0267E564FC897DC0E57F5F3DE3A878C7B5FC0B0644C06A24208736205873D1DC8DEFD045BAD4734B13E7262FA46446445127B1462CC715495C30E26410E02E22A7329923352D3492D89212497D534A9C438C9294E92EA928091949A0C1787703ABC5F189F2A90522264D42A6A414AD72D0552E584A92ACD9D40219B28CC0A992498D1BED9FE26933A8E7E118554B89E85214996B6B97049B82000CCD760400748DD9BC357C3E30CF03D935272210CCF66D6299392AC663629504BB30F4CCC8D12B4692985DDD6154C2D2D536A6395CF130038B740007899F16BDBDD4713F11D4617478977741207E1A4D3C89AD2A4CA0B5BA42416F11529449049CCC0B0481E6CD54CC4B1DC6A6D6D4CC99313327A96A2B5120E625CB682C583DB76DE326012E1692D3C0BCD04900384B880166CAB25774A42AC350005FE40479F5C458CD4E12A955984E253A5CF52D2A599530A48048243A487B92C1EDB81A467A30EA25C84CB54B4B80C54CE4960FF004F3D79BC793E7470F793FC43E199CC2D9B397B44C794F98656CB626E9F206AF21AD0525D66A4F25B9B469B829D135D53D6F1DF3D9CFC49E3BC193E8E7CCC4EA7BC421014B4D44D973012438CC95A54412015006EC1C6D16C9B8653D382A42120E64F8941D2A377CADA1B3F898FA4600B3BBC14F34F25EAEFE6470179C952C36A95599D772CF12D627CD2E62613A9D7A5241A992FD2C38E14A1B3FCCDD6E5D5A501A590176F47BB35F8C1E0FE3E91230DE31A5A6A82A9790564A4CA97579D59528EF49EEC4C4206624AB329C837BC432715ABA153534C52427C3949B16B950D5896E9D62DCB097889E6A644E27195BC72E49E24C01895B59A749E3B94A4293409808710D99898769BCCA6ADB78243BF172885B080082EA75A35773711F639D9D7695839A9E1CAEC36BA75A71952CC9975603789A42F24C9A428A434A4AC9D52088CBB05E3DAFA29A5750A5CB0A494BBA8A4DC0D744D811723E71E9DC447891601C3349A0E0EE1C1B98CEACE1CC36912D87B0F617945D5D2DAE65B0944CAC21050D8975B8D38EA4A810014949B9116BECE3E1584AC6A52A6CA54AA4973419AA9D2D40A4024E528292B054D94272D8DC86062D7C4BDA455CC9330226A8B83940535DF5770EE1EE09B3878DAA23E6E1484E89F9BEBC8BC731017DEFD6FDA25104163088C710842108421084210842108421084210844C9530CA98958BE53F2DE112A53A541409D85AC7DFF007F3F784E98672D4A2E33379DB4F28E49CCC0EDF3F3E7052428DCFE5F33F3F58E25ACCB50500EDB1DDB73F7E712F20D1CEFF36FDA205486C1B3A5B71B22652A090A500CECAE50292953C4AD2109505248D5E526D6CA3863139F458DD16212990AA39A898002C090A06EECECDB3EBE514D56724A3674A8292A21DEECCECC000DE77B59CC6B2DE395C2B624C038B301F884E4D51A698C4F81A765DBCCF93A43579C9BA2B8024CED465D905F536148597D61213AD482A209023E8A3E087E23EA714A4C3F8671034D4F2D5225C9913D6B48489C027289854A64A14949BD86609B80631CC2A72A831144F94A3FF7038E8E2E367BEBCADD4768C8ECD4A0E73E57618CC4C3F38D4F313B45A7B936F30E25C976EA0EB2C999979A48515B6EB6B2E0208490A49076B88F60F0412EBE9515F4EA2A9931209965C113080482351BB8B5FC9E375381388057524995348094A12905C5EDD3AF3EA76B7AD1569559640055E429E8A1D7DC5C8F4DBD22F32697169B30A8C9484B9BE64BEB62412145DB4E477DBB1512973147BB054924B6CE398BF5F573AB08996140A0213AF56FA6E12A5DBFA504903513D01ED7BC5F2452544A0153D21200670DBEAEC4DDAE186E0E978E67C89F210EA45C5DECC433DAF72DB7EB68A13CFCAD3A5A6AA1529E92A7C949B0E4D3C671CE5AA5D0CA0B85532E85061A4129D3AD6A4B690A0A5909BC50E312E555512E9BBF325765128241F0905DC0043B5FCE319C471FFF006E933261CB992198E999BE5BEF768C4566062ACD7F11DCF36F84FE180542432E642A12B2D9AB98F24879AA74C4AEB6D557956679E1F00844B4BEB6D16485CD94044A9756E35AB56BB68EDE70AECC785EB24CE34B327F773254A33168EF4B258CC2EA04A0974929B950235B46AF768BC715752A989932D0524104A4EE49B58866D58EB6F5DAE3855E1832D7848CA3A1653E5D509994453D9955566B886908A95667D0D3499D7669E404A5C6DF9842D4010094AAC7AC7CD4FC4FF6FF008D71DE3D5C69EA1465CC9CB00266950604EAEA3E10001CC0B08E9EC22B2A6BAADEA12C92AD1890972FE8EFE9A45D532A2E82B5DD2000128B0484A401B0005C026E4F7249373B468B56D7D52E795CE49CEBF13390FD5AEE7F68CE952912BBB4A2F6D459DF41B8B6BB3EE22991A9640B8DCEE7723F76FD22D7366AA6A8A893E44DBDA26BF8401E65EED7B6BCF7FEE5EB93D3A0B0B44B4A9482E9241F3E7B7F8D2242E5E720BE9D59CF5617FBDA211C44C01801C801ED08473084210842108421084210842390588235041F6842270A858E5E8E3F58441448091CB4AECE21CF36A162D9240F291D751B8FC22ED874D98B44E23C2A005C12E4B1205C917BDBCA2DD59878AC9929667AE577649CA824050B72E440D7A0E6FC09B9454E2669332A438CCDB856E36F32D3CC68B2D0A614C2D0B43AD2D2B21416955EE3A758ECEECFBB49C5B84315933A4A8FF0E6209254468417370012CDD3DA1574E8553894C1C25B396CD6003BEA79B102CFB8023029C7FF00820E57F1035B9ECE4C849A95C9FCD7B3B32BA55367572946AFCEB87985F999671D70216A746AD2D29A4F9D564EDB7AFBD88FC66CE9586D2E1D8D193514A132A5A93314833102C93DCA964997BD810924070A64C5061188E23C3D522751D5CD19561565902C5F40C08D1DC1E91AE6E6CE4A71B7C2D56A66899DF91D8A714E1FA638F4A318C70DD2A6EAD499B62557CB4CFAA7E841F61844C213CD4A67DC4BC02ACE2750508DF4C0F8B381F8B24C9C46871DA742AB25A2A154B55365CA54ACF9546589A4A24AD482ACA72A8BB12924398DB5E0DF8ADA8C2A968A82AE4CB5AE9D0896A985D4A2520024DDF63736F3B378B35C49E0A07955893AFE1F7D1B2A5EA544A904376D941A75B93FB54A48095A8AD6A0ADAF78CF918160D3E489B4F5D2A79525DA4544A9B725C3896A514B8B8701C36C6362303F8B4A09F29299DF874822EF6E6FCAC08D069E61E2A3DC4AE592104313551AA3842425993A6541BD6A51B04F31E954A13A4EE75293709291E62045A6A787095293FF00A16254A9B2D0A0967B254A04B5DEC6DA39BC5EEB3E25F079B4E55227C8134870124B72D73374671B5CC73A878D7363346A4D50F26723B3171A54262C1A7E4309D7E7A9E8BF42E3F2726522C06FA5CEA7A98A79BFF11C0291559896314B2912DBC09ACA75CE7701BB996B52DC394974B0BE9AC74D7177C4DD5CA93365D3290A2A49CA7311E999C0D1EF61B6BAF77E223813E2372B7271ACD6E2EB1527010C44A44965FE4F61B7E4AA58CABD529D713F07CE92A47C7BEC48C934F3731506664333E52C4CC9B67E3D21A191601C59C31884854CC0EAD152A41004C9E04B403943952A72532D09771996C9DC1168D34E3BEDA788B88A64C659961454004A8B92E5B424F2D3CB6B6C07E085E17ABC83C1349E2373568725FF0053316CAB8FD1A8D555CA3F3384687372A934A7ECD2CCD4AD61E6DD35408995F39B6E625D0EA1252511E6E7C67FC41E2986E2133843089F2C50AA410BA8A79A41993485778B202F28292320CA908294029725CF50D18AFC5271ACAF9F37BC0A3E052890403A02FADF35C963CAF1B23B6DB5A1B482A5A92A2B71E24799452902E364D9253B103512772768F11F8C2A6A2BB11A8AC9D5D3A6CC9D35531CAD4540AAE475FA6EE2ED9F502C212121203A024160483772EDB8D6E430B738AAB4A0D936B7B8B6D7B77DEFB74B763D7D311A7130A8CC9B3573521C842D448DF63A7B45C3BA5175198B06E4016BFD4B9F96F78A4A6D2A02FA82D26FCC6D6B6966DD012DA9208F9DFBC51A55397309CCAB962E90A480E5AC458750410378A79C0CD4E42490189B9670EFCEDCBCA24710E2C04A74DB6D576DB5F33AD8381695051049B2882AF31DEF19970ED6D5E153513A9EAA74952492C85948049F37B1E5E5A452268D21947C4FCF9B8D89725BA5BE63C7B3532172973A28B3987B3570061EC7149A88532F335BA7B53536C8536E36932B533A6A526DA02CFD94A4D30D15045D04A53A767BB39EDEF8DF84711915785D655552A504832D73D4C94B87219693B024BED7E711CFA644D97DDB64E643BEFABBBBBEFE7CA35EFCE5F02EC7993598F219FDE1FB996DE0AC6B86E7A66A345C335D144AA536443854EFF2E935D6A5672652D9B2186B9B306C2C56AD898F563B10F8F3A15264527194AA4953A6E44CC9E0A3BECC01B925452544EAA5824DEEED18662F8610850495298E84580BDB4F20361BC6CEC06DD49BFA98F9D14AD4ECEE0D8BEBAF3D63B273A79FC8FED118E6665CC32970DAFA98E4106E2112E3984210842108421084210842108421084210842108471E650A710C8427ED19996A6526E06AE4858E5A8122E85F32EAED740BF68BB61B3049EF265B310C92A7B0D490C6C6D677F4895365098CE4B00A1976254CC7D08D1D8BF48EB18E30450B3270C624C258C64E5EAF47C514C9CA1D665A6DB0F4B5469F506CEA5160A4A5A5CA38DB6A428042ACA5104D8C6D6760BDAE54F09E3945FF0050A96897365E8583670C5FA337AB6B18EAE9552A6B84304F5D1AE1D9C9B3EFF511A6A664609C7DE10DC4D55703D75BAA55B84ACD9A938AC275B71976A14BA24FCE4D26652DA1F934132C196D6F2421F55AC9B5B6B47D30FC3176F787716E094A9A8AB9736AE5D34B3365A94332D094A52169B8056EA1DE26EA24E60004931D91C33C4EBC2C4B41514249005F42E1D2AFA0BD886D5A32A542C4987315D1E46B187EAD2D55A3CD4ACB4C4A54A5DC4AE596CBAD256CF31D49D0D3EA6CA75B0E292EA17A90A40525406D950710E31595B30D3C84AE91730992B1E20524821989B00CE743B46C970E71E512A549EF569CD9124BA83070C75B7316EB156B15CA451E913D55AE4E374FA4D3DA5B93550997D1252B26D3682EAA6953AFA9B612025212105775055D208208CAF10C657494A5758132C250495125274724BAB636B807ABDA2FB8FF001C61A8A39850B438960FE600D8727BFBF3DEF189AC518EB3CBC49F3493C35709626A9196B4EA922999979B8DB4B6E9D354B92704CD45A66AB37FFA3743CDB46500925975ED450C1E6AD263583B57EDAF08E08C1ABB119F552A5AD1256512D53521473248428A5C29214E169CCD9810402088D4BE33ED09550A9F4F4F30B296CE97D943CDF5637E6D711B4D7059C17E59F05594D8632F32D68B26ED7DB6173B8D71B4EA10E54F15555EE63CE22696AD2FA1A69C2DB722590CA501A64CD17D21DE67CE1FC5CFC4CE23C698E5451D1621344898A988CD2D6B530CCACA02525432BDC802E5EEE63AE25CC9B891CEBCCB7006439728F15D6490E4E5240BB30B0DE2F1DD6DC74EB0B09528EA5A6D6B2AE491702C4024F403A6DEFA188A9AA9922657D7CC5CC24A9414BB953DB7BE8C18B1F9C5C138722907788D478ADA1D35E9A69EEDA5768143642D40A9573B0EDD00D875EBEDFDF19ADABFC5CDCD942427C23A8D47C88FD86F5B4B315345DCE55105CE9707C8EBA8F68A61275DEDB5CFA77BC51C574548421084210842108421084210842108421084210888BF617B7CF6F7FF0098ADA4AB14C160B32C8D4F27BB6EDFAC7043FDEDB8F5E9136B581E4294280D94A4EA483EA53DC7A8DFD62B92153BF892CDF5B33B1DEF6BB7202DAF3A79A82A0A04383A3DB7B5C68E3D46D6B450F86635175B69B5BCAFFDC33214E15F75724A540366E76B8D811E9B4EA7E21C670C5B4AABA8920365285B04906C483F987449B45B66D29538CA2EE016D41E4E6E7E5D39F5BAC52A9D57957A4AAD4D95ABC9BCE2D2F536A72F253ED2DA24FD9A5136CBD2A5B009D9D6D6E5AC4A89BDFB9B867B70ED0B0A453CAA6C527AA9E58012BEF9603002D94A811B3101A2D69E0ECF34D477EB41984AB2A54C120DDAD77DB7B00F16F188B82DE13B1ABEFCC625C84CB89A75F374392F4454B3EAD7E673E2B92FB729CC52EFA4CAB4CB6537BA09E9B01807C52F685492108562B549530702AA6A5F401F2CC0EC0B0D80B33697793814DA74909A99A02400095020EB76D75D7CC3F38F874AF0F9E0CE86EB5354EC84C01285B710B0EBF4E43FA55A81DD332F3AD104F96EB4102F7002AC466749F13DC71894DFC3CEC6ABD2952144135D3AC425D9CCDDF97563637A79B2EBE4A95DDD52946EC92A0C6E5AD636D40D437A4778C653D913C2AE5E631CC97E838372FB0BE0EA62A6E69325274AC38E4C25B42396C49CECC36D7C54ECD6A4265256596E3F34E38D36C36E2D6906E1D92F1EF693DA4F6812703AF15F3F0A5D5A91DEA7BE999A5A4A8E677585064824DECEA360F188E273F1251266CE5A9249D4E8072DB561E7EB1804E1532DF1EF8ADF16B53E2E33C68AEC9F0E194B5B7D193B84AA867E9F295DA953DE54BC8555D54C3CD30B6D87D4DD49728F8D53932D38D290ECBBC9615BD9DB9F68D85F621C013B07E1DABCFC4788D34B15F37349989A79250850A79672B89E56099B3104E54AFBB74CC4A9A8E8294CF9A89935CA125C02EE54E4124368CECF6B66B8D767490A43122DB4CCBA39328C21B6A5A450DB4CA659865B436DB4A5348421FD9014DB975E864B6CDC06C253E20F687DA5E3BC4B8B4EACC627AD7356A52A592BCCC87569989D4BB005AFB80D19AD3D2242032580B66B5C37EBA1B8368FB3A5211E4F2116011D6FEA493E9F38E99ACC466D52C925C6EFB972E472D98F48B9C99252058BB8DDADB35EFF003893ED3F768E69CB0502F724BBF3B1B746F9BDCC5C10E05FAB3BDBEFDA2A44E099697673D3F416B0F2FDA259412E19C79B7EB1305102C00FCFFCC3F14502CA0E2E05C1F47864568C18797DF972E9112B24822C2C6FB8D57D88B7B75FCBAC5CB0FE28A8C3A62E64B485A94928BECFB8B8059B9DE19093716D0E9A7CFCE387CA086A60B2843732E2B63756DE624AC5CE90A02C537DB6DC18A5FF0077C62AAB454A2A6A650CC54D2A619601D406B59EC482E6EC629EA28913CB1B0E76E5A335FE623936B6DE9B7E116020A5446E0B7B189998FF004A9FCBF5FED088A686500429272870A0C4173E51365A83310DE7FDFE5FBC225C4D84210842108421084210842108421084210842108448BBDB6B7D7B1EC46E3F589F215E308760A2DC989FED68446E556425412A23EF1B5874BDCD80B11717E9BED6BDE32292A9B86AA5D54A98525042832803B11EB7D2FD7489536521692543AB8373B5B9EB76D3CE3C1F881E1CF2E7899CB9AFE5AE68E17A6620A0D52594CD3DC9C693F13419A524A533D459A16704D22EAD162E8DCF93D3707B0DF897C67832A69908AE992448992DBF8852084AC12F70E0E5BA48D39DA2D73C194AF0E636BB073616CD6F091ABD8EFA9BEB558C3C1CB8FCE1C2BB3E8E0CF3A64717E017E7665F6B016399A92627A992AB796B9770BF3D312AAB308525255CA08DEF609B01EDAF66BFEA3DC128C170EA2C4E7CA15C990844E9EC184D281994B400EA75386490CEF76112D38D575125265CC5E500B3925C3116218379BF5BC56C29E0F1E221C4255A495C5B67B51F0C65DB4FB4E55B0860CAF50678D669A85875F9579CA53AF3B2CE25C1F0FCA76EEA9009BDAF141DAA7C7E70F4FC26A666155122A27AA4ABBA59590896A0C52B4A12B492A0C1B39286B292444A9BC4F89578EE15326A41B13E2B8DC13CBA8B03E71B1970CFC2F64CF0B397F47C0394D84A9B86E8F272ED3535352EC876A75A9C424F3E6EA936E6A78A9D7829E162DDD5A469B794F8BFDB6FC58713F1C4FC428135D36626A27282D7DE2806CCD60141200D02521800E368A74E08BAA9A26CC2A66CCDCEC092E41277DDDEEEF172FCA50792B07C840B0B1B7D3DFF001DBB5ED1A755D366D6CCFC656CC33567C5E239B52E5F7B824F9B0117BA5A4974A82946CEEFAB9041F4760FA9772758811A4950DCDC8EBE877DF6E9FDBE716CABC495552D34684B2010033A5EECC5C9B59BF78AD2D312DA8D34BDF6EBAFCCB40282F71FBF975DBD3F2DA2DD3A9A6D314A66800A838B8258F36FBE710CB92248291B9727993A91E7FA0B3888C488990842108421084210842108421084210842108421089828A6F6B6FEB0C857A025B937DED10A9452CCD77D7D225B12401FDB7FC7FE7AC55D3D5AA9BAB16662772EEC762037D60E950B91A7B1DFDBEED1026DB6E4F703B5FBF4B5F6E8627CCAD953537961CEB6FA173E9CB68E320E67D58FE913F250AB13626DD48DF7DCDC8EA3F6045322B6A81099648009602C2CF60799F3FED466A2B53372A12E8059CB80D7E805B9BFB448436CA4DC0B1BDC8EA0F7F5EA7D80F5DBA64D83D1E3B5D31024B84A8D8AD441236DC339B31DBADE2298AAB5A5DC07E45AE46BADEDC85CDDF58E8198798582F2CF08D7B1D634AFD3F0E61BC3124BA9D62AB5479B6A52564DA5252B1A9C5B6954D3EA5265A45AD44BD3CEB0DA50E29610761FB3FEC6B8DF8CB14A2C3F0F9530CC9F3104CC40504848214A054EDA2487D376722316C4675461C17573561694120A52ACC6F6D01F5B79DD9E357FC695FCE7F1ACE2065F0765E9A8E12E0CF2A71507EB555756FB4D633939098B4F054C28B489B9F9F529C4B52884A8D3C2D0A53204B18F61F85B0BE0DF871E01973B1E9743278B461899A145283534B3662000B55C9CF35044C4850BA1692C5DE30D9DC4F2ABD650259C854012124051DF57E4DD407711B3C657E5A60DCA1C0587B2F70650A4E8D85B0D48C8CB52E8F2CDA5B654E48CBB2D227E7DD480B75F794D098754A5242D6A248F35A3C83EDCBB6AA8E37E25AF12EAA7544B35534A02D44A194B25C9D1893A25801A002330C0A4A6ACA484A92E960C9BF422DB0D1DC93CC47A134E25D53AEEA529C75616E8B7D9256129404B1FFC410947F52BCDAB7EA06ADE34AA99D5095D410094BA424B86BF5373716B466829BBA4E53F94593719998139C6A144BD88059B9C56E91681254E1D9BA1D3CEDF4F78E42002F72DCDBF40211C99850A641D0DDEFF0030DEADE4F052882000FF005D624F3027CA373DB6BFE6638EFE61373AEA05BF788E205449B276F9FF007F9443989362CF7BDDCEFABB6E7FCC2264A74DF7BFD3F7EB1514EB95216F3466074B726F5B6BF77E0902E62622FF0050444732AD4A59120650E58871EC1FCB5F268E33A79FC8C525BA1D2082494800956CA24775000589B5C8B017B8B5B68BE0E1E9F4A8993EA82913A54C53CB506F10BB317245D872D758B7D2D52159430B68E5C74D39BEE3F78A8D8BA53FFDB4F6E9B6F6FAEFF43DE2C15F5B36B6705CC96841420212109CA1924B66726F7BDC08A998BCCA0CC3E9D1F523C873D7488C51C4C43BEBE7D628A42AE08E97DFF7F2F68E4027627CBFC44D8AD1C6908421084210842108421084210842108421080241716221089866CC5062B510CDAED088DCFA984B9B325282A5AD4953BBA490621284A9DD20BEBD621CC52D646FA8A74157F52923A02AB0245BDEDB0BC64F4F8D564A423BBAA9B2C8672998C7AEE7DBDA203224905D093D0A411E637F4EB6E9C654903F746906F700800DFD8587F7BEFD62A66710E2335395788542D25C10A985AFE8621122402E252411FF0081FDBEBFB41B94E5282B6B0BEC4FA8B6C3EBF80F94592B27A66214B242A613656AA73A5DBECFCE782D64B81D0103E968E4DCFAFECF58B499B30820AD441D43984220D348422252D6B6CCA2A60C1F6108443084210842108421084210842108421084210842108422346705D009E7671F77896B4A94D96DAF2E9CE11592909981A62402747B6D73E7D0FB44210A60E2FBDC42277FB785DD0480C4B5806E9AFEDC9A2624102E6E4BFDFDF947157392CC2CA1735CA037097125C0B776F2A402836BED6BFCCDFAC745864CAC9C6521255350404B6A482000C01B9DF9B7568A69D572E5A4BA5266074E60E0A53CC8721EF73D46D1E419D99FD96B905806B998F99D8AA8586A854D975FC43530E264EA552F21537254E44CCCA82A69F521210A4B2E5B71CB51371B77D86F623C5BC6B8AD253CEA09B2A88CC4242D32D614B482E0A544313670CE59F9462D5F58B7294CD98400493998E846C19F95AC1EC358D6C2AB5CE233C6CF353FD3F4592AD650F04F802B613579F6DA9A62AB8C69D2531A65855671CE54B4E4BCFD404B1684BCA31A0ADA5EA58410AF58A911C19F0D3C26AAB59A2C4B89C513675AA5CD461226000A9591B355B2B2292A5012CA94152C94BC628535188D4090B5AFB951202560BCD5072C39A433DB96AD1B25E44E4765E70F196B43CB1CAFC2F2F86B0ED0E565E9E1E94436B99A84D14244CD567DD43485294F3AB71D5158EFF7AC2F1E51FC40FC40D6F1C62B529915F31699AB5A94933592A049536BD58274660031022F74B804B925CC84306B6516D2E395F5D753CA3D99C68A53A0AF99A4692BE9AEDB6AB5FA2F622DEDD846AE77A9ACA75CF5A477A412546CA763A68E6FC9B93465D4320D325252026D6CA000DD6EFD3D2FAD8C0D2142D6F37A7B0E9EA3E5B7E7187CE528AC82A516275512753BFB45DB395804973A6BD7E515E251528862A24722491ED08471084210B0BDEC2FEBDE10842108423199C01788D655F189845AA63EE8C1B9C78793F098D32F2B0F225EAB2F36C2432F3F2D2EEA5B986E454F36F25130B6960A90E26C4B7757AAFF0011DF0B588F0FE26BC47069099F84D6AD5369AAE97F894D3D2A39CA513100254BC8A4E64804A49CA79C758E1F8ABAC0CD71AA6E080E5FC3721EE3E978C95A5D0871D966D95CCCC855B9216197595292950E73652E11B28280B8B8F35FCDB68971676733707A94CA32569564CCA7053E224E81AFB682FD358CCE967F7D29330286505CD9C948D46BF3313A1C0496CAC29E6EE1E4A4795B26C52926FD7AF6E96F58EA7AEC3A6522C8292C3576B731FDAC5B68BA4B2E5D98338BEBAECDEBFADA273701207A81F48A7956B74F320FD98A94805DF6493EB134532B53E67EB10C238842108421084210842108421084210842108421084216B7EB073CCC210836BD75842108421084210842108421084210842108421084210842108421084210881B9D877BEF6BFA7E7BFE5D2321C1A9D13D1382DBC2035D9DDFCFEFD184800924001B52DABDFD396EED688DB4A929B02544582961B4926DB6B215A7A1B581F90B88933E8664C9C25C8CDF9AF9415313A68C6C1EE1DF9BC534EA8421248371B0D6CF6D472FA18A6B71286CA89B39AAC5873ECDF401B15B6D9D466120DBA68BDC6E2E2334C0380F88311C9DCD34C58514FF002A8B0537B937243ECD16F9B88A424F47653BFB9E8DADC6F668C6C71B7E24990DC18532625AAD567314668541B725F08E0BC31CA9EADCE579DF2219A853505D7E5DB438487516529B2424A8DAF1E837609F0915BC4955438B56484C9A5909454D7D4D5112A969E524256A5CE9AB494A40D81D4900177118756627FC55E656AA20252495172400C0172F6B75318B6C9DE0DF8B6F135C6F4BE2178DCA954F0264E4BCCFC7E10CA54B8F482AB14D98744E4A2EA0C4C0B065284B687580C15ACAC6975001076FB8EFB6BECC3B18C02770C709CFA3A8C7A4CA34E31497265A0A66CB4196BFC2A92B5158510A026B90A9649C833068A4CA9952139D395240010E4926C407DC0D40D4100398D8E32EB2FB0B657E12A260DC1540A661FC3B429514F92A3D3659B9690618658530DCCA5A48E6AE69C1A56E38E3CE24B8B5A8206D6F2A3B50ED8F8838BA757C9AAAA98B9559356B04CC51042D454F72C2E5DB42CF17DC2F0BC9532E6AD395282081A10400E2EF63B8E4EC4477566ECA4A5B0528524A1C03AB8140EAE61DC1363DADB7CAF1ABB594535530AE6AF3072B0A55D40820D8BEAFD0A58C654B932945C806E160386045BC3BDDB99DF47115927524036B74F90D80F71B0BDBBEC7B889132B152A51952BF99EE090EFF7A732FA0BF0500F4F26688E909D81BF7EB7FDF48B5BBB9622FB868241018F3FDA11CC450842108421084210842304DC77785854ABF8951C52F06D597F2C3894A23BFCE1F92A4ACD3E4B17BF20AE7312FCA95D0B54C3A1B0C2A6541DD49281C8F212AF727B07F88EC2F8830095C25C7EA4E2B854D012A95302664DA45A8009A8A45AC9C93259016031CC521C8D4750D4E0D572672A7232A569DC12C43E8AD9BDBA3E87E9F049E295298D71149F0EBC5D5393947C40D25C4D1CCE54AF252588E6DBD2C30ECABF3296545530F25615AB502A55C28EAB0A6EDABE1E66714A57C57C0D3A9711C01526CB9601A894B56650973A5273649A9053E10A20862F7B5CF0FC7E9E807E12AD2B4CE26C19D376B876705EC1839E8C233712D312F32961722A6DF6020F3E6658A5D65E2B092DBDCF0402909B924022C6F722C63CB4ED1783B15C06B6748AAC3E7CAEED4A056652822C58EBE435B7AC669435F4F5233A54CED941D9C7E57EBAB163A3C72C1D64E904A1241E6EDCA57A84AFBDBBEC23A5A70FC3AC80524B90425CF99B0F2FF117513000E3F981B6EDEFE5EF13C521B927993114238842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842234CB5292540800733AF940D813CA11044B33072F7B7EF08E402A2024124E800731019E90D6372DEBED08AE9787CE5A5CA908B3B2CB1FD2F118980EA08F9EDF62CF7894AAD7B855877B6D688E561553366776907FF009149CBEA5FCE26800E8A4FA98A8D3ADD96B52AC940054AEC8BDEDA88E9DED6B8B83BED19451F0A62E854B4D3CC9530CFFE594B248361E26E9B6FD22DD88D4A69528CDFCC4B7566B8DB7BBFD63CD734734700653E16A9634CC4C5948C2986A9726ECECDD4EAB30DB4D372CC805C5B6D2D6DA9D50D413A42937241BF68D99ECB3E1FF8B7896AE966FE0CCD96B5218774A2F988D2DA800B0D3C8C61D578D480E0B80FAF32DBFAE8C1DFDE35FF00CF5F141CF9E2B7174CE44F86B60BAB57BF99BAE52B15E6C54A4DE44A50A58AF92BA85326A5B98969B0A25C428BB7D2949DCF4F513813B12E0CECE70A9589F68732970F299299F2280A659ABAC32C0250A4AF2F72862332FC641397217262CEAC45554A52648510EC56E72807CBF3173A37AF2BA0E0CFC23707654575BCF0E25AB7339F3C45CEA113CEE26ADBC154DA54FCDD9F9D6A5D8994CF2A64A1E3A5133CC972B09D5CA4EAD23A37B71F8B0C368696B384F8100C2F07A5993109A1A4697214B1993DE2D4829EF16C5402FC36528B5C34DA5C26715F7C7C6B533AD57241BB0E439F974BE65E464C49CA3728D36CCB30D1429A61A482DB41008084582004A76B5922C36B1B47979C55C6231EC426D7D655542EAD7316B482A25249249B1D05EE1CF521C4667875114175A45EEFAFB6C4F33BB691CC1BBCA7144A94A1A6E760902D6D237EC2DD46C7DB7C46B7109B369573497989004B62CC2D7E6EC357E9D632232D9032F808E8E0BF3D1B7F5F48AA6C6FB0DC58FBED68C567564F9C085A8B1E4EE6EFABFDE9BC4BF181B2BEFEF99EB055881A45AC2DBF436F503D7A1FDDE950188CE6D9812D761BEBF4FAC471017EE00FDF7F78AAAA3209477249F0F8BCFF0043D3FB422314B084210842108421084211C47913328968CB8750C4B952E4DD49BCF493AA3A96E050EAD9579800B174DFE9DA3C11DA0D6E055B2809C432C7892A2DA0DEC5C6F60D16399462A01CE904104104302EF666E5A863AEF68C74F1AFE1D1929C68619997F125265305E64B0CAD34FCCFA1C9B3FCE5B54BEA7641DAC041967A6651A9871E5A00992A6545E5252B2BB47A0FD8C7C5654F0E63347475B524E1AB484CE97399729626F86605CB52824BA40177B3EF161C4B8724AC77CA4174A6C45988F7D1DC3EE47531891CBBE3038C9F0B6C592592DC65E17A967170FA2643184336E9AF4E4CBF4FA5B6E06A510ECCCC4AAD7372E96815BC87DD9412D61A39FCD568DDBE38E06ECC3E20B84E7CDE14187C8C7A6D399A285E4A1539450A33552143F2972908964312497043C62DFEE5370C9C2592A0805B37F4F225AECFBFCA3634CA1CE6CBFCF2C1745CCACB5ACAEB783EBD2CDBB4E79080DB726E388438587901C5EA5A0287436163F4F1C7B4AEC1AA7B3DC531295892532FB99939D0BFCC9524B04ABCB4DEC488EC0C26B8D64B42C28310EEE6E96D2FCDF6E4D68F5B8D5E9A90898B48B84A881E86323844B84210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084226194B0813329C877F523DAD12D44E6CAF62C3DFFCC41448B585C9207F9FCBE5F38E64AD2850CC1C1B5B67B13F7A6B1CE44F33EE3F6890389248BF4EA6FB8DBB81198D2A29914E6A654B0B992D39C24072543460C5EE2F7E9B3C4464240CC4E96F736B91ABF3F789B526E13A93A8F417173F217BC500A2ACC6A7664C99895384A529490080761CC9B3EFB691473A6A653B906CFCB4D40D5EDE51F0310E22C338529D355AC4F5B6A814D946DD7A6A6DE98659A6252848257522FBAC1B917D4108780401B9E83BF3B3BEC838BF8AA6CAA0A7C3E777538A1026192A03C459CA802598817DB578B054631DD29C076248516B36E356D1DAC35D58BE13F89DF19FCBAC2D517B2AF848C1B3FC42E774DCC4C48CAD3288DDB0C51DD41434CCC19D6DB9B0E19A75C56A0A9768012DB2957DBD19EC7FE0770FC0A9E6E3FC755D2682966290A4CC9CA493298152B2CB9990AD6014B27C20BEA0C58AB7165D60CA1D653B6AE058126ED7D4B13A88B74CB9F0E9E2E38EFC4F279ADE20F9975AA1E03538DCFD2F263093F34E229E95A83A6467D97DF919671AD1A5A713CADC249DFBF62F1276FF00D9976234DFEC3C2B8709F3E9A59953718AA1295553968F0A574D4E14A146CC4828A89A4BDC0CAC6D29C3EA6A56A54C6D4E49693E1CBD567F306E639467BF23F21B29B876C1B2B80F29705E1AC2986A5586DA5A24251A945549D69012998989C665C3AE4F2815296853453A96AFB5D813A13DB17C47D776933679A4AD548EF0ACA8AA6A92F9897B827561E768C8E8F0A12825410A50703C2916EACFA37577DA3DA5A012DA004AD20252025CB7300B6C17627CC3FAB73BDFBC69FE2B8CCC9885266CD3366DF32CAB3662355137776DF5E717F9549959830DB60FB8D2CFB0F9F3A96DAF6DBA7B7CA3AF27D419B34A89D0923ADF5FDA2EB25052DB65166B7ADB73AF40DCE292479BA6F6DC1E82D6DC75FEDF388BF12B328CB7D6DA91ECDEEC5BE422A8AACC4DC9D39EE7A003D6FCA2AC52C4308421084210842108421084210842113BAAF2DAF7163DC9E9B7E1FE2F096F2A692FF914CEDEEDD40D2258225F88EA2E06BA72E87AB72BC71904367981C2176D211BF41720EDDC93D37E9F867D47552154C85AE6995392A0CACCC59837F306B92EDA1B011CCC9A898854BC9A85329C6AAB337462FE7A18F3BCCDCB3C1B9B584EB583F3070A53F15E19ABCB2D9A852EA4DB4E30E0295243E10E36EA4BAD85AB46D7F39E9DFBBB803B6CE20E0908387574F3DC9065A9139799053F94A483622EC6C7CAD1855770EF7F37BCCA9F11D3505CB369B5EEDB5C8168E0E4F650E09C94C0D47C059714090C2F8469EB53B4F94906DB6D2CAB4A124292DA1B09F281F87A6F189F6AFDB5F11F1F54CE99884C9B366CE5297366CD2A54D9CA57E652945F328BEA4BB8DCC5750D28C3C22581A30CACC03E8396BA5981676B47AC47401254493A92E7D63294E83C87D211C47308421084210842108421084210842108421084210842108421084210842108421084210842108421084210842110B8BDBBFF009FF91F8C5D04F942844A206700EBBD987BF57E8DB7052DE3BE86E5DBEED112AB581D49480ABB884EB2DDC1015A091A86FD36EDB88A9C1387EAF1BAA97229D0A65A901403926E2EC059FCD9E28E7D4894012013A804FCBD48F47D5A3CCF1FE6765D658D15EAD63FC618770C5259D7333153A95499A63A89666EB79C7651056E4CA5B4A56A5326FCD00A3FAA3723B3FF00875C67189748A4514C9C1443A1085294B16364E52F62D7FDDECD558D265CB5BCC60907C2AF107D035EC473B16DE30ADC4178CEE0497A94E606E10303D7B3F731DE7CD3A9F352529312986D99E715CA65D66B0CB73B3CE10B5255C87298D4B90024BE94A894EEF702FC20F0EE1A6462DC6664E0F4A8089CB338CBEFCCB06EA449CC1CD8F856A473D098C6D58E0A9514A3C6A0481B07E4F71BD8DC73DDBC1287C0EF88D78804D358A78DDCD2AA650E5BCC38DCCB194B427E610FBD4A78EA32F3F2528ECBC8A57CB1A6C1C7414A8155945494F65F13F6D3D8F761F44AC338528E46255F4F2823FDDA726529299E9CDE2914EEB194029216548538578583980514FAD2EA394125902E6ED62417DD9B9728CD1F0CDC0D70CFC26D0A4E9B93D9798765EA09659FE618D2A146957AB15B99612AD0669DE4B8F20CAAD4E2D3A9E5DCCCAED6B6FA17DB37C62F1771904A70BC4268968CE14D354159491940CA4B000358FE9171A4C10CB273900280094E9CDC8767F2D8F5BC5E24AB8DAE5820F9DF43C56B5309F8765091FF00C408053E82DB5B6EF1A4D8D71CE358FD42A6E293264D52D454E56A51503AEC58B91EAF7378C92930D4A00CF97460DBAB66234B3DFA33C7201B8BC62758B9AAFE2254A4277492C4921C1FAF41CE2E0A969942E0300C6C068DE978815806D7B7B83D0FF9BFCFB45377AA54B4A4924D9DF7FBF2E7D227A65029045DC0B1B7B5FED9BCE00A8DEC41FC41FDFD6298A083A6E7D3CDDBEB111494D99BEFA44403705477B5ADE9F5FF0068823889A108421084210842108421084210842108137163D3A7A7E906B93B9B9884A52751D3EF6880007402FEA4027F1209FA472A5294C14A510340E40F605A20EE92F986BCF53FA441490A26F7B1EA9BF94FB11D08EC47423AC56D26213A8AF24DFF00F2621BC883CA273D9986843B5EFD75FBF26821B4212B4A4592BFE9FE94FF00F44F44FD04735788CFAC20CD090435D203BEE4DB778A7994E89A41512E342F7F27D5BEDE278A089E2C00E50842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842200006F607DFBFA6DE9B77FCA2AE6514E453A2A5BF86A2C0EEFAEDB73BE8FE90AF33166D37E7F6C79C757C6D2B88E7F0B57E430AD45BA3D76728B5597A555DC473134FA9AE45F4D31E2D04AF5A4CE9642C6955937241170765BB05C5383A8EB654CE219456A428720ECAEAA008218B3F2B3C58AB65CD9815CEC2C3A680B7CC06D4F9EBFD46F070CD7E21F14D4F1AF1C3C42626C74C22BB34A93CB4C3755AA2692FD294FDE51E9B982F48A29EDF2882F312CDB9F6683642CAC83E96CDF8B4ECE3817064D1703E134743894AA608A6ACA89722A2ABBF324256AEF179CCBFE2662928538043170D18B4EC30CECE26A94A049747E54E5D2E3551D2C407E66331BC3CF099C3CF0CB4B92A664FE5AE1CC2D51926132EED7D1489399ADCC2123492AAC3ACFC6A96413670BDAAF63EE34F7B45F8A4E32E2CEF8D6E223F899EF297914C49203A5ACC4331E6F6788A9706952C8CA9372E06D7E7CDBAC5CF25600250B75CD4490F4C2D4ECCD8F54F39C25C08BDEC80426C7A46A1F11718D562EB986AAA664C2B2A72A98A51199D83391D59C6A3CA32AA1A308661A6AE2CA67B5DECCC2FD7CE217290436A5320FDE4B0A2D2576BFDF4A2C14773B917DFAC60536A44A2A3209FE2865025C59F673CFE97B45D932501B3252ACA4949233104B3DC8B683488292951048008EE3627A7DE3D4F4EF14D2EAE64B5660947FF00502FB7389E92521869B3B96F2736D9DB560F0000161FBFF3F38E27D54DA86EF08B17B5874B696DBCE25CC40981947CFAE9C88E510D293BDBDFB8FD2DF9C494ACA746F6BFDFDED13124A4000E9110903A088BBE5331093E63FBB4092753118964B973BC7108E2108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210842108421084535056A041200B7A5AC76FEF7F7E9D378BBAABF3D0CBA562C93A90399E8FA9B1FA4460A72DC686DD6DEFFA69105A14BD212AD04282839A52B520A4829D285DD0BB94F982FA03B0BC5FF85D545226154F9E25E623F9CA496018B8206B6376E46242D0142CC0F222C75D77EAE2F1054BB6E73358534A7B77DD93519571E5A40085B8582DEB02C9D4DA896D56B1052488C97169585CE42AAA556A4CD4254520CD2A72A052E03900DED94383705F5A4994485019521C105C9E5CDF9E9BB6DA5C19012940756023A2804EB3FF00D8F7BFCFF531834D9B51500A4CC245C02492080EC7AF993A9B1111CBA508BB26DB1BFE8C474E7F3989205AE4DB62483F874B74EF707D2289787CC5172497BDDFC8FD3668AB094822CC398D40D3A96B691147426DD7F7F87FBC524FA73200248249D8FCBE87CB7888B6DF57FD05F57F489E29638842108421084210842108421084210842108421084210842108421084210842108421084210842108421084210843584223EED7FD26110B8F51F8C4041058D888381A9685C7A8FC639092AB00E79405F4BF95FE90B8F51F8888BBB5FF00498E58F23EC6171EA3F110EED7FD260C791F63118776BFE931C421DDAFFA4C211C142C072920084221842108418B3B16E7B470E06A40F584221EF11FD4211104288700B444083A1784431CC21084210842108422248CC425C804B18A65CC5A56C2E2EFD03D986FC9FD2220DBB03F317899369CA40226036764A9881D7CB7FF0011185A8D803EA2F112AEBE548FA6F13514730CA54E33D29C833652B2EA6BD99C1EA1ED13337FE2AF68962648AD5A080A621C5FF52EFF0064C705476497EA211553B133972A05F9BB81CB76F367E512CAD61DAE46B61FDBE4FCACF11DBB580DFE9EDF4FDFB5B26CF5CE3E3DB937D46BCB5FD23994B52CA9DDB676E9D4E9BE83944224C4E84210842108421070352D0841C1D08308421707A1BC21084210842108421084210842108421084210842108421084210842108421084210D2E3686B13E83EA9FC7FDA22FC42F62A7FFE29FDA0E06A5A2422C41251D6E09B7E7B83B5BAF4F94121738B252A528D980BFA75BBEF12D492BD3463FDF47035DD8FA44C12DAC12B525241EC7ADFEBD3D37B6E6DEA669A5AA96CA0850246FA8D7CBD5EFE76694EBA624E55282BA0B72DB7F206D7816D9B1D2B04F617EBF9C3BBABDD25B7FB31CFE2D674429FC81FD229E84FA7E67FCC45DDD4FF004AFE50FC54CFFDB57FF588DC0DAE36DBAC70D502D9556B7E51FB4540CCA00B1B8736DCC2E3D47E221FF51FD2AFFEA3F68E58F23EC6171EA3F18E1427904292A6DFC23F40F06235047A44625645FF004ABFFA9FDA3884322FFA55FF00D4FED088DB6BDF7BF4F68E1D693958806E2C7576D1BFB6B12165615F95F6040B3FCDF51F3BC44E816B2AE6D73DBA5FD6DFDFEB1C3CC55CA6C4BBF3D9ECE0B336DE71284959B9045EF720FB6FEBEB12EC3706F7B13F3FEFD07B44C4CD9A9041B0FCB70EE3DB7F7B4542539370CCC1EDE9F2F3844B89908421084210842108470C390F6842396034004239CCA6672DC9CB7B4211C42108E18721ED08472C06800842108421084210842205E83CFF004308E5AE1ECE1DF5B449412C0B97BDDF5BC4AA4DFA75DBBEC47BDBE7172934489D97C612ECF7D398B9DFEDA27A4A7C24B16E658E8C7AC100806FEBFD8453D6530A699902B303BFE9B1FBD6232413E1D36FBF389A29238842108421084210842108421084210842108421084210842108421084210882BA1F91FD2264A4E79884FF00516E5AF5DBCF68E46A1F988E3B6B595805571F4EC3E87A6FFDAFB8B97E0E4A54332C0F50C766BF96FD4C4150024A5BC232BF57B39BBFA73E51D2F30CD72568B313587DE4B13AD214B48490B71764937D0E1580761D1207B0119B70F61F87CC9D2FBD4A549CC3307B9D34FB23A9313A813DEACA5F5209B682EC1D98FCCEA7CACE9ECE9C7F4E7552CF4F95CCB6B50986D6DCB24A2C404923969209B2AFB58DBE71DA88E13C2AA80525196528032C84BBEE7507A137EA778EC0C27875388A0952012860599C72F4B6BBDB9C73D8E20316B607316C2963A29694E927D48414AADEC2251E08A004325C3DFC21C8E574B0E6EC79345EBFE13288632BDDFF0042639E8E223168B0E553DDF936FDFF00277FCFE10FF85503969674E482C5ACE320FA7CE38FF83C8FFDA1FF00EA8E627889AF1DDCA74993FD44158DFB91774DAFBD81E9DFA448570252E62404B13A143B7470CE7CAD120F052038EE880346517FAE9C9C9DA2A0E22AAD6DE42541F659DFFF00F431C7FC1246C847FF00450FDE38FF008523742FFF00B3FED1599E22AA41C4F3241829DEE10A5157D005DCFBFE30FF0081D390C5097246892033877245B778826705A424912D479B927E435DA3E99E240B4805CA5DCD8136E60B7E040F7B778E7FE03487FF004D3ECDF48A43C18F709581C8001AF7D4751F2D62238932403FC993D3FEE73FFF00A888BFE0549FFB52FF00FAFF007887FE17FF00F57FFD1FFF00AC4E9E24D0010AA484A8F4B1748B7AFDF3BF5F95C7BC51CDECF24CC9998494948B064FEEFCC1D6DB3344A5706AC28069BCF2B0D35170966F26F9C54638919353C84CC534A50B296F512BB24AB607EF5B63EE2D6EE3A97C012E5A484C84120153006FCDAEEEDF3BEB12EA3850C896544CC0078B41D5C7E50599BD5EF68F69C038D67717373534ED37E12525EC65DC56B027011B58A9442AC00FB85277F9475DE3F81D2D01CA152D6ACA4A909FFD3531F09D5CEE6305C4902996A4070C7A3060D677F9F3BDC47A5475DA9B3298300486F23100B81E42110C7308421084210842108421084210842108421084210842108421157452D136A1085B6520BDDB6D5F9F9D9E21507077E508A8ACA60951EEBC403B005CB7521DD80E9E8F14EA396E4E8F6240E4E2FD43FCA267026CAD21C0509D487824AA51D5752DA976B85249293658B11D46D6E6870CC4A7A8193266292A2D649CC9E4416CAE7935B523734AA9E527503762C4B73F26DF4D75DE06C52855D254A4DD6947DC42AE4593724D8A4026EA26E7D223C430EADA29894564B989528050CE18B17BE809B86E51554B34CD4924D815002DB11BFABF918845BFBB1FD27E7155087763FA4FCE108910842108421084210842108421084210842108421084210842108422045C103B8222396485A48D5EDE66DFE6391620F2222921AD26E55723F4DBEB7DA2A26098BDEEEF63A740FA036D39441500CDFCAE1C3176FBBFC9B483EC34FDCB8D2564A74D9449163EC763F845CF0BC427D04C0B5A8AC0FE51EFCFCB6D5E14D9A4060A29721F736BFB5F93EE3945A7672E5586F5E27A63284B639AAA925B4294B2494A99B252ADB60EDC80476ED63DD3C25C4E2B91329CE6409646472C94E6706E43DD835F68EC8E1FE2F95403BA992332940242C162AF7B5983DB7D22D45D65A404120A54EACA1011F7C1EBB83A823616BA9247A08ECBA7CD34FF00DC16B904DBD7426EDA476A6178B4AC492081DDB80439DC8DF987B5B7222A27992E2E97DE4D86E0F2557B0DF7E5DAE3D07D2F13E64A50BD9CE803936DF5F367F2B08BE2A58480A05C38B1DC7B6FF6F1497A1775595A95B95123727A920003DFA7D00885339831290536B9EBE7B6FB08A895534EA013DC051000243DD981E7777DDA29A5094DC6906E6FBDCDBF388BF1096B94D9C0BFDB8F5E6C62A15329C24114E492EC329F9B3DA26BDB74A520F6363FE7F7D6099CE43104EAC35FD6E366F38A7554485FF0C53B120DD988E841BEB6BB74D6F15A94E0B288B6DDBA81EBEF7BC4D336633B11B5C0FD2204CB945DE501E96FA7588210857F52C01DC116DBD361FE3DE39CE0302468EE406F73A7AF9445DDD3339091EDFA0814A41002B5A55B022CA5155FEEE9EBB5C1077049DBAC45F8C44A494E54A88199DD80E6E4301A73B5F62628EAE6D1D302B64121DDD81602F67D75DAE3CA3DC72EF27EA1891E96A9551BE4D212A0B5A16DA838EE92952528374DAFD0900DAF18763BC532644B5A5082149046641D1C31D8FB9F56263AD38878B68E509B2134C92B214CE7CD8916240D480C5CF38BDEA451E4E9920CC84B369665E59094CB06C6952481625761E706C2DD3B93D76D7EE21C515553A629198249B826F73CF5773C8474C620B35F31531242492EA6701DDD92092CDD5F6F28FB31886B016007202108E6108421084210842108421084210842108421084210842108422A2950A9934252ACA482DD6DF284401BAB49DBA6FF0087E978BAD32849AD952668EF5C82A3EA4FB3E859ED7768A69D604B681C7A97BFADBCBA45897890F1278C784EE15F1BE7360612B315DC3EBA1B32F293AD972415FCEAB92746428B616DB9AD954C97964BB6581A40178F41BE18BB20C1FB4DC628686B262A9A9D6B69CB42506714243A84BCE952412CC145045C13B88C7EB2A4CB4ACA402A00B3BB13737662C46A07CA3D5B838CD6C419E7C33E4DE6BE286E5D188F1EE15556EA6894416E544C26AD5291FB24A96E14A4B7248362B5106FBF68EA4F8A4ECFE9B8538D5585E1AE645299B25248016B44A9935292A648198801C8003DC0022AF0FAB5092E50E4B1243B3903CCEB6009DF6D4DCC8075142BCAA1DB620FD446A5544A994E48520D8B69FB6E3F43A45C056390326BADF4EADC8FEE35113F2FDFF2FF0078A235045F2BFA1F5FBE5E713D33D2A0F6EA1EE3D37FD629FCE24C4CCE7FA4FDFA42E3625491BFA8BDBD6DE91C3EA18E8FD3C9E22049D9BEBECD113A7B2813E900FB86F507E43488988D411E9108E6388FFFD9, '1', '2021-10-06 01:19:11', '1', '2021-10-06 01:19:11', b'0', 0); +INSERT INTO `infra_file` VALUES ('8448cada8c714e4ab61f521c8da21990', 'jpg', 0xFFD8FFE10DFA4578696600004D4D002A000000080007011200030000000100010000011A00050000000100000062011B0005000000010000006A012800030000000100020000013100020000001F000000720132000200000014000000918769000400000001000000A8000000D4000AFC8000002710000AFC800000271041646F62652050686F746F73686F702032312E30202857696E646F77732900323032303A30343A30322031373A32343A3135000000000003A001000300000001FFFF0000A00200040000000100000320A003000400000001000001C20000000000000006010300030000000100060000011A00050000000100000122011B0005000000010000012A012800030000000100020000020100040000000100000132020200040000000100000CC00000000000000048000000010000004800000001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD9FFED160050686F746F73686F7020332E30003842494D0425000000000010000000000000000000000000000000003842494D043A0000000000D7000000100000000100000000000B7072696E744F7574707574000000050000000050737453626F6F6C0100000000496E7465656E756D00000000496E746500000000496D67200000000F7072696E745369787465656E426974626F6F6C000000000B7072696E7465724E616D65544558540000000100000000000F7072696E7450726F6F6653657475704F626A6300000005682168378BBE7F6E00000000000A70726F6F6653657475700000000100000000426C746E656E756D0000000C6275696C74696E50726F6F660000000970726F6F66434D594B003842494D043B00000000022D00000010000000010000000000127072696E744F75747075744F7074696F6E7300000017000000004370746E626F6F6C0000000000436C6272626F6F6C00000000005267734D626F6F6C000000000043726E43626F6F6C0000000000436E7443626F6F6C00000000004C626C73626F6F6C00000000004E677476626F6F6C0000000000456D6C44626F6F6C0000000000496E7472626F6F6C000000000042636B674F626A630000000100000000000052474243000000030000000052642020646F7562406FE000000000000000000047726E20646F7562406FE0000000000000000000426C2020646F7562406FE000000000000000000042726454556E744623526C74000000000000000000000000426C6420556E744623526C7400000000000000000000000052736C74556E74462350786C40520000000000000000000A766563746F7244617461626F6F6C010000000050675073656E756D00000000506750730000000050675043000000004C656674556E744623526C74000000000000000000000000546F7020556E744623526C7400000000000000000000000053636C20556E74462350726340590000000000000000001063726F705768656E5072696E74696E67626F6F6C000000000E63726F7052656374426F74746F6D6C6F6E67000000000000000C63726F70526563744C6566746C6F6E67000000000000000D63726F705265637452696768746C6F6E67000000000000000B63726F7052656374546F706C6F6E6700000000003842494D03ED000000000010004800000001000200480000000100023842494D042600000000000E000000000000000000003F8000003842494D040D0000000000040000005A3842494D04190000000000040000001E3842494D03F3000000000009000000000000000001003842494D271000000000000A000100000000000000023842494D03F5000000000048002F66660001006C66660006000000000001002F6666000100A1999A0006000000000001003200000001005A00000006000000000001003500000001002D000000060000000000013842494D03F80000000000700000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03E800003842494D040000000000000200093842494D040200000000001400000000000000000000000000000000000000003842494D043000000000000A010101010101010101013842494D042D00000000000600010000000A3842494D0408000000000010000000010000024000000240000000003842494D041E000000000004000000003842494D041A00000000033F000000060000000000000000000001C20000032000000005672A68079898002D0034000000010000000000000000000000000000000000000001000000000000000000000320000001C200000000000000000000000000000000010000000000000000000000000000000000000010000000010000000000006E756C6C0000000200000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E670000032000000006736C69636573566C4C73000000014F626A6300000001000000000005736C6963650000001200000007736C69636549446C6F6E67000000000000000767726F757049446C6F6E6700000000000000066F726967696E656E756D0000000C45536C6963654F726967696E0000000D6175746F47656E6572617465640000000054797065656E756D0000000A45536C6963655479706500000000496D672000000006626F756E64734F626A6300000001000000000000526374310000000400000000546F70206C6F6E6700000000000000004C6566746C6F6E67000000000000000042746F6D6C6F6E67000001C200000000526768746C6F6E67000003200000000375726C54455854000000010000000000006E756C6C54455854000000010000000000004D7367655445585400000001000000000006616C74546167544558540000000100000000000E63656C6C54657874497348544D4C626F6F6C010000000863656C6C546578745445585400000001000000000009686F727A416C69676E656E756D0000000F45536C696365486F727A416C69676E0000000764656661756C740000000976657274416C69676E656E756D0000000F45536C69636556657274416C69676E0000000764656661756C740000000B6267436F6C6F7254797065656E756D0000001145536C6963654247436F6C6F7254797065000000004E6F6E6500000009746F704F75747365746C6F6E67000000000000000A6C6566744F75747365746C6F6E67000000000000000C626F74746F6D4F75747365746C6F6E67000000000000000B72696768744F75747365746C6F6E6700000000003842494D042800000000000C000000023FF00000000000003842494D041100000000000101003842494D04140000000000040000000A3842494D040C000000000CDC00000001000000A00000005A000001E00000A8C000000CC000180001FFD8FFED000C41646F62655F434D0002FFEE000E41646F626500648000000001FFDB0084000C08080809080C09090C110B0A0B11150F0C0C0F1518131315131318110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C010D0B0B0D0E0D100E0E10140E0E0E14140E0E0E0E14110C0C0C0C0C11110C0C0C0C0C0C110C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC0001108005A00A003012200021101031101FFDD0004000AFFC4013F0000010501010101010100000000000000030001020405060708090A0B0100010501010101010100000000000000010002030405060708090A0B1000010401030204020507060805030C33010002110304211231054151611322718132061491A1B14223241552C16233347282D14307259253F0E1F163733516A2B283264493546445C2A3743617D255E265F2B384C3D375E3F3462794A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F637475767778797A7B7C7D7E7F711000202010204040304050607070605350100021103213112044151617122130532819114A1B14223C152D1F0332462E1728292435315637334F1250616A2B283072635C2D2449354A317644555367465E2F2B384C3D375E3F34694A485B495C4D4E4F4A5B5C5D5E5F55666768696A6B6C6D6E6F62737475767778797A7B7C7FFDA000C03010002110311003F00F544924925293A64E929F18FADE19FF3ABAA48DC4DEDE49FF454ACD369FB3380796ED036EA74F26A9FD78C97B3EB8F55606C8F581FFC0A958D6E43DC037807B28C86505BB87D62EE9F91F68AEC7BEE6B5CC6BDC6480F11A4A1FA7D77AB07DD8F8F93934564FAAF631CEADB03D477AD77F315ED67BFF48F540820C1D7CD751F55053FB1FAB6EA8E4BFD3DA69AF09B90F26CBB0598CCFB45EFF45EFBED67E830BD1B1FFA1B327DFE95753D002D0644079DB3A5755AB26AC4B316DAF26FD68ADE20D83FE05C7F4767F61FF4FF0047FCE223BA3758AADF4DF876B2D01C4B4B44B431AFB2DF536BBF44E6574DCEDB6FBFF4562EC7AD136756E977D8DFB3D565B6DA2CC3763D4E190FC7AB1ECC4C6C8B1EFA6DB30EDC5F4F333A8F52CFB55946162D5F6BA2947EAB4B68CAEA05D6E43AFC6C4B9B6E28A7631BA6536BEA18F5E55F6751CFC1DFD532EAF53D4F4E8C965D93956E374FFB2E3D6FA0B6DE4BA6617D6B654DCBE9D8B9FE9583755763D76ED70F169AFD962EC3A17D64EA76D96616774CCAB32714B5B9365143DEF66EFA1F6BC6637757B9BEF66CFA7FE8D65F45774BA0FD5DC3774F77AEEEA15E583F68792CF55D87898D9AF69C766E6E6BB1ECCAA719DFF69ABAECF53D3CA62E7F17071B3FA8E3518782E155F6D6D6E2073AF7866E69CAFD27A75D9FCDB6EB5FECFD13130C227AAF8CE4351B3E96329ADCE6B032C60225A2EA6DAC3B69F7B7F4F535AF757BBF495AF37EB34578DD5F3E8ADBE9D75E4581958101AD277358D6FEEED77B56C3BA8DF4F5CC91439ADAF1AFC8A716AAC06D2CA197595B71E8A2ADB4D753FD365967A6DF52EB3F4F6BEDB150FACEFF00B47557E735A5ACCA6B09932058C6B6BB5AD77F65088119505D3265004F47296AFD52FF00C55748FF00C34DFF00A97AC995ADF54BFF00155D23FF000D37FEA5EA4627DE13274C8AD524924929FFD0F544924925293A64E929F09FAEEC9FAE1D59DFF0CD1FF8152B01DCF9ADEFAF0E23EB87578ED734C7FD6A9584E1EE07B4C7CD3482B82C0CB869F246A6B0F3B5C246920F1F728B29703C401C9F056B1D90F1A73AFC934AE0750D9C3C5ADD680D6001C35811C15D0E374AC79935336EEDE06D1F4A3E971F4952E958FEF693C49D7E2B7EB969E254323AB6B18EAD46F49C7F730D4DDAFF0073840824FD29597D6FA5D54EE2D1B77341606E9A8F6ED11FC95D334FB493A203B1ABBF21B65A37067D169E1464906ED9B844855393D1FA1399563DD60DAF68690D8D23F74FEEFB5687D60E8746474DB2DA5B16D23D481DE072B535EDC4A85969D0763A1F81D101908365470C786A9F2EDC473F72D5FAA07FECAFA47FE1A67E47ACFCBA855977560406BDC00F20568FD516FF00D95F473FF7699FF52F5781D9CC23523B3EF6993A6450A49249253FFFD1F544924925293A64E929F05FAF263EBA756F036B47FE05542C62241EFBB50B63EBE83FF3C7AAB876B87FE7AA56383EE1E1FEBEE40AE4AE2E207808251702C7D9696BB9747E2546BA9CF7348D7C63556FA7623EBCA24F0D2224729922297C626DE9B0A88EC0761F2F6AD4656EDBA842C0A9A183C5690600DD79EEA06E44506ABC32B682F78682A01F48FA37327CCA3BA9A277D906741BB80AA64D9D348F4CBEA6DA4C0687B43893DB6EE4C902BC16C8C80E86348772496F1082FCEC4F53F4B686469E253E3E2399510C044F8F654EDCBE97D3AD1F6C7B2BBEC05CDDE1C4C03B67DAD7353575E9ABC8F5EA5B5758CAD9AD56BCDB518896BFDDFF00548FF545B1F5ABA47FE1A67FD4BD5BFADF6D195660E650439B657657BDA080763B737E906FD1F5551FAA766EFADDD1C0ED94CFC8E57212B01CDC91A9C878BEF8993A65231A92492494FF00FFD2F544924925293A64E929F07FAF4377D6EEADFF001EDFFCF54ACEE8F875E7754A31ED1348DCFB478B180D85BFDA5A5F5E04FD6DEAE3FE1C7FE7AA5677D5BCAAF1FAC62BEC23D379752F9FF84696367FB4992D8D2F85710BEEF656F4FC73B5B93815D41803BD7C56ECF4C1FA2DBC7E77F2DC8195D2D941DF4925BCEBE20AD5B711F71BADCCB36E331D3B0BA1A770F6EF8F759FB9B10290CB2921ED2DD7DAC773B7F35D0AB027BB7A518F64BD39C7609E56A31C0F3ACAC9A5BE9FB55EA9F1051486593D2B032B5C8C7AEE3DB7B7700818DF57FA7E3DA2DAF1A8AC8320B2B00C8F376E5A55BC10028DD76D6B9BE4A39DD32C00ECCBD4AC360113DD0ACC7ADC009DBBF50476542C3D4FD3230D958B5D1165B25AD13EF3B1BF49C9E9ABABB2E0E7BD9E8B87BE352E70FE49FA09A9156D6FAE5D2DD6FD5E7E4077AAFC1B1B7B4F70C77E86F1FE6B98FF00FADAE33EA79FFB2EE91FF8699F91CBD22EB59753762BC82CBEB7D4E1C887B4B3FEFCBCD7EA583FF3ABA313CFDA980FDCE56701B15D9A5CDC6A57FBCFD04A2A4A2AC351749249253FFFD3F544924925293A64E929F06FAF13FF003BFABFFC70FF00CF74AC0C5A9F6BEC63352C63AC81FF000637BB5FEAAE8BEB9D2FBFEB97576B4682E6973DDA35A3D3AB955FA1E1D15F556398F3634D193EA480266B737D8D4384D13D14271E211BF53B9D07EB6E364D2DC7EA4F155EC01A2D78FD1D9FBAE738FF00376AE86C6B1CCF546C1A4EF90411CFD29DABCE31F01ECC9BF19F040D58EEC44E85AB5717A65C5A186D2299135C983FC90D55E7117A3771E43C3A8D5E9F7B79699F056B1DEC70826216457B9839D111993E9EB29ACA24EDFA80409F821DF6082663B954075105B13D92AAD16BE5CE803523C5327AE8BC11BB62EEA36D5596D741B081A1710D6FDFAB952C6EABD6ACBC0BE8AABA5C61D1634B88EDB55CB286E437520055D9D3E8C571BDD74EC05D06001085689120CF2F26BC5C5BF2DE76BA8ADCE209FCE03D8CFF003F6AE2FEA5B09FAD5D1FCB25B27E4E5B3D55CECF2EA812DA9C7D4DAE05A5DFE8DFEF8DCCFCF46FAA5D2998FD7B02C277385E3F2394D8FD3E64B5739E33A6D10FB028A928AB2D35D2492494FF00FFD4F544924925293A64E929F1DFACEDFF00B24EB193635CDC4A725AD73F69D9EA3AAA6373FF003ACFE42CBC7E8D93D7F2ECCBC1B5B895E3868B6F735CC68304CB760DDF41BFA47ADEFF0018DFF8A0C4FA3FCE5DFCC7F52BFE77FEEF7FEEB7A6B56AFF00C478FE6FFA3B3E87D1FA2CFE95FCBFFB91FC8F553A5C7C236A598FDBE296F77ABCF3306FFB0FA79370BEBACFACCC86506BB1A5C1BFA11BEE6EF764B5F47E83D1DFBEEA7F3DEA66814BFD116B4E4080EC7782CB8388935FB3D6ABD467F5DEB62EFE9479FE7EFF00E6B8E723FE4EFF00CD97FA1FF805CBFE60FA1F487F3BFCDFD21FCEFF0027FD2AAD2E2BE8DE87B75BCFFABC207ED7571DCEC88143D8E71240638ED7123E9358EFE6EC43C86E5D409B68786FEF012DFF0039B2B773BF9ABBFE4BFE6AAFE6BF9CE7FC07F23FEE27F2D407F363E9FD11F4BE97F6FF00EFC992ABD131E2AD5E6DB90D2ED343DC23D7925BA83007753EABF4FF00C17CBE925D17FE50C4FA1FCF33F9CFA3CFFAEC4CD1935AD1D0651955E39C9CEB3EC58AD05CE7B9A5D66D1F9C31D9EFDBBBD9FA445E82FC6EA37BC574DB752DDAD7E45CE643647AAE2719BBBE9D6DD8CFD25B6FFA5F4D56FADDFD1B2BF9FF00E98DFA7C7D13FCFF00FC0FFDC7FF0087F595CFA93FF22BB8FA777D1E7E8D7FCE7FDF7FE0D3870AD971D6BB3A9D4F0CE660D95B768B1CC2F617090D73C86D6E688FE73D3DFE9FFC26C5CEF4CCAA717EBBD5D2DAC706D394C635D21DA966F732CDA7F95F4D7517FF003C3FA5FD3ABF98FE6F86FD2FE4FF00DFD55BBFF141D2BFA1FF0049FF000BFD33E8DBF4BFF44A78DC5B19D8D767B851524CAC3554924924A7FFD93842494D042100000000005700000001010000000F00410064006F00620065002000500068006F0074006F00730068006F00700000001400410064006F00620065002000500068006F0074006F00730068006F00700020003200300032003000000001003842494D04060000000000070006000000010100FFE10DD2687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F003C3F787061636B657420626567696E3D22EFBBBF222069643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E203C783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D6574612F2220783A786D70746B3D2241646F626520584D5020436F726520352E362D633134382037392E3136343033362C20323031392F30382F31332D30313A30363A35372020202020202020223E203C7264663A52444620786D6C6E733A7264663D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D7264662D73796E7461782D6E7323223E203C7264663A4465736372697074696F6E207264663A61626F75743D222220786D6C6E733A786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F2220786D6C6E733A786D704D4D3D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F2220786D6C6E733A73744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F73547970652F5265736F757263654576656E74232220786D6C6E733A64633D22687474703A2F2F7075726C2E6F72672F64632F656C656D656E74732F312E312F2220786D6C6E733A70686F746F73686F703D22687474703A2F2F6E732E61646F62652E636F6D2F70686F746F73686F702F312E302F2220786D703A43726561746F72546F6F6C3D2241646F62652050686F746F73686F702032312E30202857696E646F7773292220786D703A437265617465446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D65746164617461446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D703A4D6F64696679446174653D22323032302D30342D30325431373A32343A31352B30383A30302220786D704D4D3A496E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D3232623834663439646366312220786D704D4D3A446F63756D656E7449443D2261646F62653A646F6369643A70686F746F73686F703A64633333616566382D343164372D343134372D626566652D3133623366363839326632642220786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D702E6469643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222064633A666F726D61743D22696D6167652F6A706567222070686F746F73686F703A436F6C6F724D6F64653D2233223E203C786D704D4D3A486973746F72793E203C7264663A5365713E203C7264663A6C692073744576743A616374696F6E3D2263726561746564222073744576743A696E7374616E636549443D22786D702E6969643A39633734393932312D633861652D393634382D613065372D613762366131393131336266222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222F3E203C7264663A6C692073744576743A616374696F6E3D227361766564222073744576743A696E7374616E636549443D22786D702E6969643A34656266653730652D643236652D623834312D613962612D323262383466343964636631222073744576743A7768656E3D22323032302D30342D30325431373A32343A31352B30383A3030222073744576743A736F6674776172654167656E743D2241646F62652050686F746F73686F702032312E30202857696E646F777329222073744576743A6368616E6765643D222F222F3E203C2F7264663A5365713E203C2F786D704D4D3A486973746F72793E203C2F7264663A4465736372697074696F6E3E203C2F7264663A5244463E203C2F783A786D706D6574613E2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020203C3F787061636B657420656E643D2277223F3EFFEE000E41646F626500644000000001FFDB0084000202020202020202020203020202030403020203040504040404040506050505050505060607070807070609090A0A09090C0C0C0C0C0C0C0C0C0C0C0C0C0C0C01030303050405090606090D0A090A0D0F0E0E0E0E0F0F0C0C0C0C0C0F0F0C0C0C0C0C0C0F0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC000110801C2032003011100021101031101FFDD00040064FFC401A20000000701010101010000000000000000040503020601000708090A0B0100020203010101010100000000000000010002030405060708090A0B1000020103030204020607030402060273010203110400052112314151061361227181143291A10715B14223C152D1E1331662F0247282F12543345392A2B26373C235442793A3B33617546474C3D2E2082683090A181984944546A4B456D355281AF2E3F3C4D4E4F465758595A5B5C5D5E5F566768696A6B6C6D6E6F637475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F82939495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFA110002020102030505040506040803036D0100021103042112314105511361220671819132A1B1F014C1D1E1234215526272F1332434438216925325A263B2C20773D235E2448317549308090A18192636451A2764745537F2A3B3C32829D3E3F38494A4B4C4D4E4F465758595A5B5C5D5E5F5465666768696A6B6C6D6E6F6475767778797A7B7C7D7E7F738485868788898A8B8C8D8E8F839495969798999A9B9C9D9E9F92A3A4A5A6A7A8A9AAABACADAEAFAFFDA000C03010002110311003F00FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8E35D5BCC737C2D3C9BFBFF666A389DAABAAEB92D09964A9F7C78D5CFA56B736CD2C94EF538F1AA82F96F534916762EE10D78F8E112B54DEDED35BD3EEA09B45B992D25620CA14D3265239BD8EDBCD5E6BB286DA2B8BE79A375FDFA924D4D3205B0232DB5BD4EF199998E5459C58F6A9ABEA16F71CB9114EF9125B120B8F3A5CDA026573418AA583F34D616346AB5298A09A424FF98F2DD0F80D2BE18691C4925DEBD7DAB05B61522434CAF2C51C6FBA7FE7122F60D17CBBA84175B333D4D7E6329E172714DF5E6AFE7ED22CE1043865814FAAB5F118F0B9A26F8C7F30BF306DEE7549AE2C8889391A95FA71E1499BC4758F3D5037A77ACDEA0AB47CBAE4E30713366E12F35D43F302DA14901531CE7ECCA7C72C11718E7796EAFE6ED57516663AA12A0515431E99608B8F2D430D9A677E524F3FAA4F5A9AE5822D0750978B98B8D140D8E4C63B63F9843BDC13F64532431B1F1AD0C5DB916EE72D8E362656ACB7457BE4BC3606368A13F2553F7E5321BB5F0EEDD0B6F916C0141ADD0558F5385BE2690CC5536E98B682985A4527312ABF1A6F5C9F44527A6F5255114979C48EC4E424136EE70A2D2593E54CA2516432D265A76A6F6B5FAACACBE041E995F0B319DE9DE5BFCCBF37E8C54E9FE619A075E8A1C8FE18699F88FA4FC9FF00F395FE6ED08C0BACAB6A71A302D2BFC5B0F98C890D8323EA6F247FCE5769BE63B8449ECD62F50F5D875AE564360C8FA2EC3CC5A46B32DADF898514F2F4EBD72B21BF14F74FF4D7626F1F53F8A192BF5207B785320439FC4115A4693711DBDF5F5F12CE8C0D913D857B640865CD910BAFAE46A41FEE46F95909115A6CE4BB46B98FAC20D7214C643662170CF7323C858AFA27E2FA314452DD56DE2D4F4C9F94A6B1827AF862DF163FA65C8FD1C2C11EADCA80D716F09EC33DE42A6D1472A2824F861069AB502C331D3BCB3E55F3C412795FCE9A746D05DC6CB0CEEBBD4A9A6FF3399784BA4D445F8C9FF3931F9253FE507E61EA96B145E9F97B57919B426A6C402C4D3AF866C605D3E41BBE5BAFA5230FC32DB583B90724F865D8B930CC5BCB5A16375C55AC5578E98AB78AA8BFDA38AAA2F7C55A3D7156B155EADD315560D8ABFADEFF009C6EFF00D677FC84FF00CD73E56FFBA45AE5A39349E6F68C28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF917B754FE45FBB34FC2ED532A855A803C71E1551370C0E3C2AADF5A26361ED863155D0DC52840DFC72C2A39A6893B3D0124F8D7205B423E172F227A6C401D86D9516714AB5F0D52FD80A139193607916A21A49641526A722125825DE9F335C1F4C75ED96C434929D699A6C96C434DD0F639708B519B2F86D62F8446DC7EB1F0971B52990CB0D9871BE87FCB0F341D3236D0D5B8C6E3E2981A1FBF28E17231CD35F3479E9A06B8D356666080FC7CAA4D6BDF0F0B9919BE7FD5BCC7246F2B3BB10C4EC4E3C2994DE7979AD87666AFDAE9921171331B2C0F56D4F996EFF003CB045C5931D8EF2A483F765822E3C93012875EBB1C988B4108794A034D865910C68BA38D5CFDACB0048895EF171AE4C36479A0A470A7A6580362A4738A2F877CC49C775A4724E0D32149016B354935AD71A4A1DD6BD77C7853689173C4000D282981B835EBA75A0AF8D30316FEB00F53CBE780C5810510B7617A1A7CB21C2C68DA6FA7EA011872EBE39021BC16463520EBC791A11BF8640867128FB5D46EECDD26B2B9642A6A021A6408660BEA2FCB2FCFDD73CBED676DA8D64D3C301752BEE42FCCE56437639517E927903F33746F37E9D6F35B5CC6CC69C5188FE272B21CE195EF305FA4D63FBD6531AAF4047864086E8E4B486CAF94DD3C40F0427627A64086D8CD96A5DDCDA59B81C5A07EAC065720CA52B09035922C373792515250683B641116276C6D6D61BBE6F53302029E9BE2DF179F4113DAEA124A8F54249515DB16F0CA34926E2FE49AEE5291C6018F7A54F860465161EA22FDB4CB9B1BE11ABC42946201CC9C45D46A60F8AFF00E73E6C935ED07CAFE6151B69FEA733E1CB966C6127479A3BBF21B5802DEF21BB07F772A9A2F6CB896A8B7129F492423FBC15197E12C7338F7CBDA14FB8C555475C55CDD7156B156A98AB78AA8B1353BE2AB6A7C7155E3156EA7C7157F5CBFF0038D9FF00ACEBF907FF009AE3CABFF748B5CB472693CDED5850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91688D3E8CD770BB55732D29BED5C3C2AA125C2826831E155317408208D8E02155E1B85AF4C8951CD358A7AEC0640B684DB436F56492BD16B9596615B5884496D2F7DF6CAE41B2245BC82F22E370C08A6F82213221279612262C82A46E7E599100E3CCAE5B8127C2F41C732621C6949524D42354F4A234917A1AE47306A2535D3BCDEBA4425797FA536DCC1FEDCC76FC4509A9F9B4384B899EB24952C6B5FE38D39824C1F50F30477E480698D24CAD8EDC5C8D85474E95C9C766360A4574C1CF635E9EF930D6404B3D13EA5541F0229BD72C01A26023D4B200A41E5D969BFDD9688B498A9C8A643CC30A7422BD32241B4C601C9CD0D0D4622D78559E6DA85BE9CB031A4148391EBD7EFC95A3758ABD0572A31B6611B1823A838384A95415A9D8EDDA98F09415600537EFDB070962DFD589EDEE477CA8B782D7D5877207CCE16629B36E3C4570F267C214BD23C80EE4F4C2427802690DB9461BF5CA484009D470F214276A6FE232B21980A5CBD19290CC580EB4DE83DF2B660332D27535212DEE8FFA3C9B487DB20591D9EA7E53F3E7983CB371CF47BA75B588D42722361ED5CACD22322FADFF002DBFE729E486FECA3F324A5B4F43C6EB7AD6B403F6B2B2DF0917D9AFF997E53F30E976D75A2CF1C72CA0114615DFE9C8172A322F48F2E1BBD5F477844BCCF02EA6BE032B937028CD596783CBD6EAE486690291DF2A6C890F3BF35C434FB6B478C9AC8A0B530D37C4879A9BFB99670B1D41AED5EFF2C0DE0B228A4BA8602D3935603D3A78FD1912CE554CFF004DBBBDD461B5B6949F4D3BB6DFAF32313ABD48BE4F08FF009CBD8E0D47F29B5582DF79B4BF4C311B9F889E99B081D9D0E789B7E39EB9664FE87818D4B86E5F7E5A1C5029425A239806C20F8732B0726190DA1CF7CC86A531D462AAABD7157375C55AC55D8ABB15506FB47156B155E3A0C55BC55FD72FFCE367FEB3AFE417FE6B8F2AFF00DD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF91745DBAE6B5DAA0270038DFBF4C557A007DF1B569937DBBE025217C042073DC654C931B4B9E50CA83AF638153ED2A660AE69F7614A367BA58ED6466DC57BE210497946B3748D33508EB930030322C65AED519B7A6D930C0A4B25EA976A1A6581AD2C9AE872FB4704D38D012DCEFD72B6D40CD37A94DCD07BE2CACA024DF7F0C56CA8140C8FF00BB32CBD8569F0F7CAB27369C922D18005B7B89916CE2B561340E5BAB2F4EB92C64B5D943DB5FDB89F5295B5385DAF559A094950D1CE7B04AEF99B8C2D95595FCC31E95FA5A2F2DEAB79369A4C971E6692CA54B64886DBBF1E1B7BE654698F1747A07953F25FF00357CD5E47B8FCC3F2CF921F5AF26DAC924BAB6B8AEDF686F20A01B713919D1482F2ED2EE9AFF0053F4EEAE9567B5774B4D35A8AB291B1591BF678F6AF5C85320537786D4C727D62D7D2746ACB0024AAB57E1A37BE16C1BA0A592333C1F5AB6956F6452D6B040A646283AFC2B8B2D91111FAC46DF5AD0357B7907FBCF3A594ADC97BBF4ED8D30F103505E5DC61A19341D524914F1B6B916725593FDF9C698D3094C2BC17577C9A69749D5DD17E004584A7930F1DB6C698198519259239ED629ECE48EE637F5EE6CEF94DAB7A0DF64D1E87010C6D165EFA492CFF437FCEC1AD7982636B06996E39B2843F0A8095272AE0B6424C9F59F2D79A3CADA9E9BA7F9E7C8D3686FAFA7FA33DD1786BC056A3985C85331262333C3A54F76F7BC648AB4B360D5AF80195D16C12513E60D2CD80917D45D661916331703F0A31DDBE818981642749BC3AE6906375955CC900F87512A429FE19594FE60222D35781D3EB68CAD1034926660015F9572B3129FCC840C7E65D1D24BEB4B581E196ED089EE402E021EE32070CAAD7F3211EFE61B4168AB6D299934E50F75301F184E8085EF90F02523417F34193E95ABBEB4AB7361A9FA4427EFD88A72403A53C6980E92498EA8047DBF9C7CB567070FAFC915C4CE561708580643F1127B54E0FCA49C886AA2CCF4DFCE48343113DBF98273C2842D0D36FA71FCA172A3AB8BE9FF00CBBFF9CDB4D1FD0B6D435C905A2AD18F0A9FF896425A434CA7AC14FAC348FF009CD2FC9CD42C53F4D798CACC46EA631D7FE0B043465C6FCE29EAFF00F393FF00939ABD91B3B0F33299266A44F22AA8527BD4B659F932D90D6EEC1B4AFF009C92FC948F548E1D6BCDBEB7D5488E20B10E0B20DAA581E9954B4843B0C5AC0FA4F4CF3168FABC116ADA4C424D0EE943D9DEF51231DCD3B653E018736EC9A8E21B326B4D5ED26FDD28E20EDB6D8D535DDBC63FE7231043F97F76F6EA5FD68D8B83BD681BAE646271B34453F1A350B93EBFD65BAC723023C3E239B1C54E8B53B294BF1309FB5C0E4332C38504337F1C2CD662AAABFC3155F8ABB15587AE2AD62AEE15DEB8ABB80F1C55DD36F0C55D8ABFAE5FF9C6CFFD675FC82FFCD71E55FF00BA45AE5A39349E6F6AC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90949CD3DF35AED52FB89CF2AF7C55B86E091D7E78AA21AE147461F7E02A39A924D50F534F0CA99A334E620B96D86F4AE054F2D6EFD2473D3C3154A750D59DAD254AF1F88648734179BDEDD33C8C49D8E4C302C72E27356DE9930C6492F362E77DB26D6A44FC66A69B7538CD38D42523B1FA72B6E435483D7156B155F63A7CDACEBBE57F2EC774BA6C5E65D66CF4A9755A8E708BA9021600F600D6B93C70123BB466354FD9DB4FF9F49FE51E9B35B5DF9C7FE725E596D2C19259EC276B48A07400311EA48EBB7C865808ADA838F7BBEA8D27FE704FFE70B7F2CBC93ADFE62EB5E4ED2FCFDA1F97AD1F53B8D68CE66458A1AB332885B893F4E5D007DEA4EFDC5F217E7E7FCFC07FE716353FC95F327E49FE4E7952E35AD3FCD1A73D92DB5DE9DF548AD1A421898DE956229B1CBE2A0D9B7BB7FCFBAED6DAEFFE7DEDABC11C097125CEA9E608E58A641C5CAD0F02C474D8EF91931E27CE5FF386BF901FF38ADFF3939F947F9A5E46D4AC20D13F3DE4D4AFA3D5B502693D8AA5C31B692CB911EA29FDBA74FA3229E2A7E6C7E75FE48FE62FE43F9FB55FCAFF003FD93DAC31B9934FF32509B7B8B752CD0949A9C492805403D7037465694FE5779EB49FCAEFCC9F267E62EBFA147E6CF2EE9F1490DDE9774291BF26A6F8B2E2EAFDABFC97FF009CC4FCA9FCF4F37697E48F21FF00CE3B5ADDCD7052DF51BD5B3AD9D9DB103D4066084034DC570B1E305EEDFF00393BF9B5F917FF0038B736896771F9223CD9E6AD663E3A258D869FF588BEAA48520BA275A9D862C38DF24AFF00CFC07F285102BFFCE28EA5A6B472F2BE54D1A4243F7A829818193E5CF2EEB1F945FF0039A1FF0039BFA5493F92469FE42D5B4CB5D2E7D04C660314D0D43332281435070B0326BF337F28BCA9F919FF003F16F267E5FF00E5ED82683A169F269B7D6F08FDE822E95988A3D41D80C89E4CE25EFF00FF003F7E5B6B6D7BF216FAED56EE1B8866F5D446B172F848FD803B9CAEB9B3069F945A4FF8720F3D7902F7CCBA4407CA305FC0757B66735684CAA5B90FF572BE8DAFDCAB4F397FCFACEEF5A9560F2669B26AD218AD25536AE12579540001F528C7B5460970F716278AB9BE8CF3FF00E497FCE0E7E5E7E5C69FE7AF387E5468DA6F90EF8441677470419BEC02858124FCF23C239D7E3E4E29B7CC49E6EFF9F50CE925A2F93B4A8B4E1113C84120527C38FAB5AFD3938C224F543E93FC95FC95FF009C13FCF1F2BEA3E60FCB0FCA9D1F52D0EC646D3EEEE9E378D870A93D5DBC32D18815DDE0B79E65FF009F5A683AA6B3A4DE792B4AB0D6B4B9A7D36FE25B7763CE0AAB0E5EA53AFB75C9C71041BA7E10595CE9716ADE686D3E258B449B5DD4A4D123AD185A191BD15A7871A65BC23AB5926F67DC5FF3827AD7FCE27E9FA779F3FE865346B2D425D52E61FF000CC570865F4A341FBDA85652A49A1EB8384364645FA0ADE64FF9F54F0E2FE56D1154776B7907FCCEC7843689C97DBEBFFF003EAD240B6F2B684EC4D14185C024F6AFAD80C026539232EB55FF009F5B229F5BCA9A1AB20ABA7A7202A3DFF7DB618E30D5C459F7E5FF0090FF00E7DF7F9C370BA2790BF2B6D35DE5F66FADEDE6FAB236FD67595941DBBE1300CE32931BFF009CC4FF009C6AFF009C4DFC9FFF009C73FCD3D534FF0021E85E59F375CE85247E5495A765BA92F792F130866DD857B0CA66221CAC5399237D9E1DFF0038E06E1FF24BC8D6FA85CDC48EB67037D52742BC18C62AC09DCD7357A900BB9C123D5F4B695A658ED26C48DC819824539F1281FCC5F2E5A79A3C9FAA5A7107EAF03F15EE7E16E99386CD59793F083CE5A73699AFEB5A5BC6D088677081C52B466E999F8CBA3D4C5283B5B59A9054AA1A5733226C38110866FE39364B315545FE18AAFC55BC554CF5C55D8AB5CE9B53157733E18AB7B9DE9D715750F862AFEB97FE71B3FF0059D7F20FFF0035C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EE4B96A57F0CD6BB54BEE6E4F2FD78AAE86E01502BB62AB1E41CC1F7C05211724A0FA7E1953247B5D0458CD771D302AC9756E0B4AE2AC5EFF0053332B28F1E9921CD058C5DDC9A1C98605209A72C684F7DB2618C96890713936B5093F7854786F8CD38DBF476F6CADB96AC542DF462ABFD318AAA691E55F3379E7CD9A1793FC99650DD799AF254BAD31DD8AC8AF1B7C3C69EF976201C4CE5F60F993FE70D3FE739BCCF6ED6FE636BAD4D0A7A0BA64974C55430141414FC72EA01A2CBF643F2F3F273CFDA2FF00CE0F79D3F27751D3560F3D6A7E56BAD3AD2D236678CCF22154058926A49DF7C9C764136FC52D1FFE701FFE72CB48B23A6C3E43D327E0C6E11A590B4CA587B532C0520D3F6A7FE70B3F25FF00307F2DBFE70CB52FCA9F37592691E78BBBFD6E6B3B02DD56EF8984D76EA01C892C0C9F94DF94FF00F389FF00F3995F93FF0099EDF98DE46F2ADA43ACF97B58B9B9BFF5A5741716D34DCA84568C0AD6981417AE7FCE7FAFFCE51FE6E79534AF35F9F3F2AB43D1FF002EBCAD1B32EA1612BCB7E1CA1F51AE118D5072AD074C590953F38FFE71DF41F23F993F327C9F61F9CBA9DDE9DF96FAE3B23DCB201688E1C22891CF40316CE27EE04FFF003953FF0038D3FF0038DF77A57E43FF00CE2AF97F45D77F31FCC37D67656F7518A6957724DF097B9BD427E3626800C58195B18FF9CAAFF9CCDFCF4FC80D7BCAFA67E687FCE3DF94F59BED56CC3691AFD83497715B5C16A2A4323861EA03B85271636FABFF002FFF0038507E40CFF9F1F9F7E46D13C8B05BDA9B9D3F4E4445935042AC10CEACBB48C69B0C5812FC5DFF009C15D5A2D67FE7381F58D3AD6DADAD7CCBAE5CEAD690D688B677723CB1C6941D830DB16264F56FF9CB6980FF009FA17962F26790A01A3C56CD08AFC512BA95FA2BBE25B81671FF003F8D92E6E35DFC86B458964B3FAB48F6A53790B537046408641F93B24769776F1C5A8D8BDC5E5005AA9AD32A21B8153B8D1ACADF59F24FD5E27B49CEB5640015A8FDE83B570034CB9BF793FE7E412ABFFCE01F962299A79644D5F458DA471425D6A77F6DF2C8C6A9818EE5F822DA1697A868B63A7E97A1869E3B413DF5D92F5F5075EF84367007EF97FCFA0C347FF38C9E7F8608E44B9FF10DDC61C0FDA11353EECB049AB806DF17E12F9AB47B1BAFCC0FCCEB8BA8DA7BDFF156A70A3396A02262C6BBF8938253D9B3806EB5E3B64FAAB416104933FC0DC4D7EC8CC7F14B1F0829A683A75C3FD616C230D727F7CA091B8F91C7C52918C27967E5AF2D4C04779A2A4DE22AFF00D71F14A784226DB4BF2FEA7AAD9F93BCA1F97771E62F34DF4C9FA3B4FB38E4964E75A091954D4283D4E4A323252007E937E427FCFA63CE7E6BD624F38FFCE42EA16DE50D126845CC1A268937AB24A08A94B9E6D5414EA2B970B69343DEFAFBF303FE72AFFE716BFE708FCA571F975F92DA2D9EB9E72107A561A1E8CA67B496FC01F15E4C0B1526A6B4C8CA7B338C093BF27E59F9CF5FFCCAFF009C81D6EDBF31FF003BB537D6EE21B8F5743FCBD8E42FA6D9467EC96E276A53BE60E6CF5C9D8E0C3B6E1F657E5BFE6369D731586871B246D63122D22A1B745A50468C07ECE61711939F5C2FA534DBE8E15925460EAE054D72328B7C24CC22D5AC61D12EA696CBEB7CA290B102BC7E13918AE4E4FC43FCFDBED3F5AF3EEAA2CE0F41D256DA94A6ED997093A7CE1E1FEA48CAB1C8FCFD01C57D8667623B3AF229D96A1D8ABB155CBDF15546ED8AAC1D3156F15770077AE2AEE03C7156B9D36A74DB157733E18ABFAE6FF9C6CDFF00E71D7F208F8FE5C7957FEE916B968E4D279BDAB0A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D34BC51D4D0F8E6BA9DAA5D757887900C2A71A55B6D7229BB0AE34A897909F881D877C041506914D7085128E2A32AA2CB88285DDE7100A372E23B634578825125F3B6DE3DB0526D0734E0296AD08C9008291DD5D541EF920C0A4C65777FB27E7930C485FCC81BFD3930585174720E677DA9824530148B0F5141BE41B2D48B91D8FCF15B6BD4C56D917917CEFE6DFCBCF3E68FE74F25D8DA4FADE8686E21BDBD1FBA4E07970AF89F0CC8C3C9C5CFCDF7349FF3F5EFF9CA09EC6E2F7F40F96EDEE2C9C5CDC4A63A3948C50D169EDE39750B71DFAE1E46FF009C8DF3C7997FE70D7CC7F9F77D6D65079CF43D126F318B287FDE7668D4B05229D0853DB26021F945E58FF9FADFFCE5A79B35516DE55F22681E62D56E938AD859DA9967DABFB0057B78614BF5BFFE7113F3E7F303F3EFFE71A6FF00F34BCD7656107E6269DAB6B5A78B38978242DA7FD8475A7C2DB1A8C04354DF9BBF941FF3F0CFF9CA9FCDFF00CFA87F28345D1BCB916A1ABEA975A7BCB321458A3B4765E4CD4EDC70522934FF009CF1FCF6FF009CA8FCBB54FC9DF3CC3E4CD4B45FCDAB77FABC1A0167BE8560F85BD6561F0D6B51F2C5987E547903C85E7FFCE1F31E95F90DA75CE97A4DCC5234B6925EBFA51B3F2E410B7892705864FD16F257FCFA23F3F26D7B44BFF33F987CB7E4EB2D2CACD0DEF97A57FAFA5C210D14B5634E4AC01AD70A0BF577CE1E75FC81FCA3FCB5D0BCB7F9F7E7DD07F32353F23411CEF26B7325C6AD737D0F499537AB531624BF32FF00E7323CE1F9DBFF00392DF975379D3CA7E4D9FCB9FF0038CFE50893559ED75188C37B3C51FDA96341406234F84E1A60FCCAFC9CF2BF9BFCFDF9CDE47F2C7E5B79864F2479AFCE0F1D9F917558E43088E40A5C7AAC3703883D31E140897EB27E5E7FCFB5BFE727B4DFCF1F24FE6C7E63FE61689E709343BC49F53B89E691E765414DAB4AD6B5C69B86CC2FFE7EF9AD68DFE37FC9DF2EE8BA9A4BE67F2DDBDCBEAF6D237C36EB22928CDE0180DB2259805F3C7FCE28FF00CE04F9B3FE7277C8B379FED3CEF2E942398C3C1E42073EA05011EF913BF26775CDF5A68BFF003E80F35DB6ADA36B1ABFE62B5E3E957F6F77F57E65AA20903D055BA9A5300891D14CC17E927FCE507FCE31CDFF003909F913A5FE4E5B6A8FA49B39ECEFCDFF00EC97B4D954EFDF2C0C0CC9DDF9B23FE7CF5E6CB5D3445A7FE68CD0DDBB5651EA3052BDD766A644829F10BF463FE710FF00E717AF3FE717FF002A75DF235E6BF36A771A95F4DA9497719F84348A568373BEF954C90A245F9F1E67FF009F44F98B5AF37F9975FB0FCC06B6B3D7B50B8D4C42F211F1DCC86460C037515C4094BA289D17C03FF393DFF38B1AC7FCE29F9FBC85A4EA5AE9D56D3CC32395915890415F72727E1D06CF11E5115ADBC0BC0ACCAD3B3189E9B75DE990E109E22AF02A25CA98A4775EE7B60A0C6CBEB5FF009F6E24C3FE73B742F456393FE752D5CC824EC9C7E265F714DB2E8061225F657FCFCFFF003C3F35FC97E6DFCBAFC96F2179A27F2BE93E74D264D47CC3E6289FD3B9611CDE998B9D3BA8E9965048912FC9FF002E796B4CF2F6A1746D8A5FCB75704DF6B7A99ADCBC86A4C8A6BD77CAB200DF025ECD06A30454B7B39648D29FBFB81D251E0C7C335D962E7E29109E69570F65730DF69E56CA20DF15B45B4751D5BE6731E31A72B8ADF587E5979ECDFABDB5F5C28E2005E47AFE18261BE05F56793754B6B9B7BDD2DD11E3BD8D979B741B532B00B39BF217FE726FCA5FE19FCC1D4EE238EAB732332D3A1A96E999100EAF5043E588DA30F351BE22DF1A9EA0E67E2D83AD9157A1F0CB98BB7F0C3452D12075C08B5CA46FBE2AA8C46DBE2AB01DB156EA3C715773A6D4C16134EE67C31B5A6F883BD7AE3687701E3855FD72FF00CE367FEB3AFE417FE6B8F2AFFDD22D72D1C9A4F37B56143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87A96FEF941ACBF8E623B3B0963DF5F16DA5AE34B611515DDF541F571A5D9318B53BD42A1E4AA7ED2E0931927706A3CC0E9BE52D61166E7638B38A5E6EBE33D4E2D8103717049C52833FBC23155616C42F21DF15434B1D3B62A868D7E36F0F0C5894746A3DBE8C582BB461BE43155168462AC93F2FBF2CFCE1F9BDE7FD1FF2EBC9776965A8EAF19905C4E6900A1A7C7976271B31DDFA2BA47FCF9FFF003D7597F43CC9F997E58B4B688049A0B3123CA57AD18AEDF7E640F268B7EC4F907F217CA1F937FF0038F179F955E75D6E26F23C1A335AF9A359B87280447FBCAB9AD12872616DF1CEABFF003963FF00381FFF0038BD6BA743F96BE5BD23CF9A8D847C5755F29411C972838D2B3CEC2B5DC8241C905B5BFF003EB4FCC58FCF1F979F9AFA45BDB470DBEA3E63D675CB68140E5026A2EC544B4EFF00150E4BA2F0DB17FF009F7DFF00CE324FF963E63FCDAFCFEFCCDB44B09FF4B6ACDE5AB8B8F84DBC31CECCF23927F6C74DB010CB81F96DF9DDF9D7FF002BE3FE7253CE9F98D6F74D045A7CCD65A2E9970D50A9033C3CA01414E4054E56436C616CDFFE712FF28FF257F327CF9E6FF31FE72FE7149F963AB796353B69BCBCB6F75F56B8942307356F0AE459786FD51F38F93BFE71CFCE8D7B3AFF00CE71F98B48B4344BB5D3B5DE01005028483E032A32A3CDA4E2277A79DF977FE7DABFF388BF9C724FA9681F9DFE67FCC6BB8EA6F35A1A8ADDB0A750CEC07864F8C745E0A7D95F97BE4CFC8BFC81F25FFD0B3F99FF0036D7CCFA7F9B4496BA47977CC577EBDF4905C8A0B58A951C00FB2B931913C07B9F1A79AFFE7DDDFF003895F947E615F32F9A7F3CF59FCB2D465BD7B8F29DF0D405ACB64ECC4AADAB863C4A5683DB26269AA1C932B9FC9FFF009C6DD4E4B4D31BFE73E3CEE249C520787CC4435C9EA55985795326770C385F15FF00CE607FCE3DFF00CE35793FC93A9FE677927FE722AEFF0035BF320CB15BDBE9DABEA02FAEAE854A30AD6A780ED95C837C075A7C55E4DF31FE71792B429EDFCA5F991ADF923465E12CD616174D00776151B2E634B6673887D0DFF38F9E6FFF009C92F3EFE7CFE58F92FF00E576F99F50875F9E3D66F2CA5BF77A5BD9C80C9148A76A3807614C8F38DD72712517E82FFCFD9BF3BBCF5E43D53F2BFC95E46F376ABE50D47CC9A7CBA8CF75A64ED0168E297830629BF6F1CB9B7146F67E4949F9B1FF0039096D688A9F9E7E6F8AD66FDFCB72DA8CA013ECD5AFE382DCA9C283F6FBFE7D73E78F3479EFFE71CBCEFAC79EBCD5AC79AEFB4CF30DDC2BA85EDC34F27A0B192A159EA695A9EB8251704737E2FF009DFF003E7FE720AFBF30FF003022B5FCE7F34697A7DAEBF7D69A7410DF3A2450C729F4D68294016836C31A05CD8E332890C035DD5BCF3E67D574EF30FE64F9EEFF00CECFA07C7647509CCECBCF614AE4E73586911714D00BE54BA9663752A97D3E2AFEEC022A6A3E5989293951D3D2B5AB7A48ED5FDAFE3862584B1BEBEFF9F69C9EA7FCE75684C3FEA4ED647FC933991170F2C69EDFFF003F6FDFF3EFF26475FF0070139A7FD1C60916A897C11A8C06541DF8C9CA998F22E5C0A7769767EA8B08FD9ED9448B971679A34DCA08E393ECD77C85B75DB34B4D4A5D2EE2196CBA0209A64245CAC6FA93F2F7F32121B8B35B9702BC565AFBD3DB220B64F93C6BFE7316D6CB516B1D6AC183B3AD5A9F4E64C0BAAD445F9DD35A43EA99631F13EF2FCF2FE275A614A6E782D075CBE05690E243D3DF2EE882BC0E79596B937C78ED819479378B2762AEC55ACC79736D1C9BC4312578CB43592EEB920C097F5CDFF38D9FFACE9F905FF9AE3CABFF00748B5CB87260F6AC2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF864BB048AACD51DB311CEB4BC2B147612EE01C56D17621DC0AC98ADA65E8307525EA2BB8C124129D5B45D38F4CA501306040229D716C8A58E28E49D862D88571C9F6DC629548E36A8DB154D235AAD08E9DB1541DC42687E1FA7154A1D5D0F43BE282A91C8E0F4C58F0A3519A9BEC3B62BC2B8891BA2938AF0B21F2279EFCFF00F94DE7DD13F323F2F2682DBCC7A3AFA3682ED3D5818B1AFC51F7CBB1CA9C4D40DDEF1F99FF00F39CFF00F3963F99305EDCF983CE163A19D22DDC48BE5D88D8BAB28AD1F89353F4E5DC40971E9FAFDF975AC7983CE1FF003EDFFCC2D67CC3ADCBADEAFAC793AF6692F6F5CCACAEC87A96F0C9476B5A7F387A7BE85A5F97E686F0C4B71A859A08A7863264776DF812A09AEFDF240AD3F707FE7D29F951F9A9E58D67F327CEFAF794AFFCB3F979E6FD06D2D74586F289F5A962209786B4A13D6A72D06C289D3D0FFE7EADF9D7E75FCBCFCB8F2D7E4FF95F4E9747D37F3126922D63CDB6EA5623146D510C6CA2AAC4FDADF7C494F1EEF91AF7FE70E3C83AA7FCE05F92BF3AEF2F5BC95F997E5B8A7B89B5A998AC37BEA48591645EA49A0A13EF9592D8323E2BFF009C7CFC90FCC1FF009C9CF3F6A1E5DF285F695A3F99A0478754D4EFA15781907C3CD50EF5A6F91B6632ECFD44F20FFCFAB7F26BF2AB40D53CD9FF003943F98B1EAF1E9122DD31D16E0D85B451A7C6C6757AB301DE83A60113F0419DBEF0F30F9D3F2CFF00297FE7157CDDF985FF0038E51E8F77A2E99A34D3E87AB584002CA507C25DB882FDF7A647C2A533B3BBF9ABD5FCC1E62BDBFD3BF38B52F3E1D5FF00332009E6CB79656692289588A59C486BC597C06110A62723F717F317CA1E4DFF009F8A7FCE1B683E61F29DEAA79DFC9B6E93C371250BAEACB12ADCC53746E24D763921162676F3AFF9C76FF9C4AFCACFF9C2AF256A3F9DDFF392BAF68DAC6BB25AC8348D2EEE1F56DE1050845489C37C66B4AE4B8D1C4FC98F3C683E4FF3F7E6A7987CE9A0F95AFF00CB7F97BAD5E493E91A34D227AD21690B17B72BF654D4103C32B3367E3523BCC3368DE5ED38437CCF631C29EAC4D72DCC48631544A0AD49A532A3BA7C6B7EAA7FCFAF3F21AF74CB6F31FF00CE577E62D9AE9F1EAD6D2BF93BD61C560D302B7AF32F2A5140527135F00C38ADF0C7FCE507E6BC1F9E5FF3923E60F3559336B1E4BF277ADA2792A590F34B9B5726B3475EC1AB91F136761A7C24EEF13D4A2B98216F556DEFED9374B08928CA3C0D76C7C47272E2D9FB2FFF003E9130C7FF0038CDF98534B0936D279BAFFD6B75D8AA08A9C7E8CB89DBE4EAB83D4FC42B8373FF002B0FF346E6C618E5B6B7F36EA8E7D75E4157D634041F0C864950761A68F34C66823B9FAC35E7A572978ABF0C0BC42537E99852CCEC052AAA97948E11B154E30923E3000EC721E2309CC24B3CE90432F3902146A3D4F427A65F09383972D3EC4FF9F65C7327FCE717971E44204FE4DD65E13D792F03BED9990E41D74F2713DD7FE7ED2449F9FF00F92E10F22FE5F9CA7B833E5732B10F862E5828B84A5655AD5331E45CBC6126D3AF59262937EEF7D81CC79172E2F55D2984B0523352AB5DB204B918E36C8F4C9E559024919604D2A72B949CA80A679663EAD494CBE9348414FA32024DB241F9EDEF35FB18ED9C35C431A101FA819938E4E0E585BE39D634AB9D26FEEA39A268D2662D096EE3DB2EE370E5898E354B6FF7E6463938D38D34D18D88FA73281D9C5915363C7A76C8940709053734381B03B9A78E2AB81077071575478E2ADD3C329237656EA1F0C900C495DD865803592DE4A9812FEB9BFE71B3FF0059D7F20BFF0035C7957FEE916B96057B562AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF86BB8802C67311CBE240DB460B32F63B1C57899159D94483A7CB15E25595139003AE465C97891F6DF00CA9215659878E2D914A669013D6A7B62D81411BE21E18A519137BE2A8C57A6F8AB52BD57DF154A6615A629014E35DFF008629A469140B8AD2262C5682DBA92EE182EA4897D5B636D227A6366F588F8581F6C944B46585BF40FF00E70A3FE70BFF0024FF00E723FF0029B5BF3279AFCCB2E85E6CD3F54FD1B7D1CF7CB1F2A8279716604E5FC449B718C2BA3F4B7F3B2EFF00283FE71B3FE7103CF7F9456BE72B18EF350F2ECFA4796A059D267BDB87144850231219B975392053E1DEEF8D7FE707F47FF9C0DF27FE58699F9D5E7A920D17CE3645F4EF33E9FE629BEBB0472C5F6A58ED983503B74A0C9DA38084AFFE7217FE7E75E7BF365C5E7907FE719F438FCB7A1D9BB245E63302FA77D68A6A9F554D84551B9A76C78E9A678492FBA3F267F36BF20BFE73B3F246D3F2E3CE2F6ADE69D3EDE14F3568B7AC8B7B693DB95E53432C86A3D4707ECFBE0333C988C469F327FCFCB3F353CABE53FCBAF26FFCE267E5CDFDA3C1E60317E9B4B77594D8C5624344ACC8763215A1191E3A663097E57797752F3AFE5FF9C6C7CCDF943A9C9A0F9CF47B37B69ADC3304BA5917E290814069EF94F8AD834F27D89FF38B3F927AAFFCE6FDA7E64798BF3E7F37350B297C93A92E973E8C3516B68AE39C65D8B46CE015A8A5732465003038E4FD4FB9B5FF009C5EFCACFC8DB6FC88F3D7E61E976FF96F73A61B09B4D8665F5F8B1DCB4D11635DFAD301CF148C322F85A05FF9F51FE534B65AAF9524BCF3E5F69779EB5A587D6E6BA592E54502399556AA41E94A644E701B069645F0D7E4CFE707E71FE4DFE6779E7F353F27ACA7B7F2BDEEB5777FAA7901F91B67D325959D04716C81E8C454657F9A8B68D148F47EAA587FCE5D7FCE207FCE64F97A0F277E7DD8CFE44D68148A2F29EA333219A56D898E455E2373B03F7E40E51F51E5E4C65A390DBABF3FBFE735BFE7193F2E7FE71D6EBCA4BF931E6B9F599BF306493F44F97BEB7F5C7B6892AE2854B05A8A0C81CA48B3C9A8E9A47A24BFF3851F919E41FCF8FCE08BCB7F9D5E708F47BEF273A5EE8BF97374C527BFF4784AEC676A2B2AF75EE36C1C6472EBD57F2E62FB7BFE738BFE730D64B5BBFF009C5CFF009C7DB8B4B9D4AE02D96BFAD6931886D349B68C7096D02A1E279A93BAED8F89E9B972FBDC8C7A49134FCD7F2F791E1F2BD8A68176E65963AD2F474AB6E687E67304EA2CBD060D36C9D5FF00962CDEC2E4C7290D6F197694577A7CB271CD6DB9F4FB3F537FE7D471DBC1FF0038CDF9836D79756F682FFCD9A8A47EB4F1C6DC425391566046FE39B033B1B793CF4F170CC03DE7EF7E383E88DABF9ABF332F6D2329158F9BF538A57471C64549295DBED5731F3CEA2ECB1E2B0B64B2FAB6DC295ED9A83959F8450935A7AA80863180EB571D695CB2191AE78497A47FCE3F7E527E5A7E66FF00CE4DE8BF97BF9B2B736BE4AF3858DC5D45789762D544B6F1928399200E4453E9CDB69C931BBE4EB73E120D53F757F207FE70C7FE718BFE71AFCE927E65F912FE4935C165716D61ACDEEB114F0C16970A04CA23671527C4666125C2188F73F2B3FE7E3BF9A5E4EFCDFF00F9C87FCBEB2FCB3F30C1E6A87C89E5FB8B0F31FD554D22B812972BEA74AD08CA67CADBF1E3DDF31DAC4D05A3A188C69337A8439E4E1BFD6CC69173A18924F4C0BA048EF98E4B950C4F51D01855631D5C01954E4E4C31D3D46DF46944493053B8AE63CA4DA229835ADEBC6A5222C22EBB64449245AB5B5C4A54C33C541EF9938E4C4C2DE59F9A3E5C4BCB14D4ADE3DED50AB53DF2D949A32627CC778E915B014A4B5A1CC8C527559E348462CA23AF565AE6C22EB25CDCA390DFB64CB3839A315C836114B7D35C50EA53618ABB155C1C014F0C8916825AF572403025BF532603025DEAE5822D64BFAEAFF9C6B35FF9C74FC823E3F971E55FFBA45AE0661ED78A5D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF881BC880420F5CC3E20E424B0A857A1EA4ED8F12B24B50B4218D31E20AA8F08670CBB9ED809B0A39AA03C41076395F0B604BE5662C6870F0B30504E1C9AD31E165C6D29E277FA7070B21205171354FC382928CF8A83E78D2B8D698D2A12406B8A625A8D0D7A6D8B2B45B23300145698AD85F1EDB1EB8ADAA4A225884FC4CD3AB045B6AD0153D5BE8C429A2868F47BB86133689E66D47465BDBA56BFD32CEE6585789FB529E0402465832531E005338FCBB6FA84CE751D4B53D461B17E766D79772CEAF20E8C15C9030F8BDE98E11D11F0795F499EFEDAF6F2C266B595F85D69026222007FBB997ECB57C30F8C19F83BDB33B782934292BC7E8C4ECB672C2823F4231B2D78815DB6CA67985B64710EA91EA7E5A437115F68D25EF97EEA32FFA4F52D3EE5EDCDE06FB3511914E390F1E9B3C081768DE5FD3ED8FD72E26BBD7F5E0DB6AB793BCAF427B1724ED909E7B671C1001E86B6EF2DC590922A49044CAFABA1E2483FB240DF7CA8E50DBE0C52883F2E6D4EB125EC771AA59E917959750B0B1BE96DBEB128E858C64549F7CAFF3738F271A7A404BD4B4AFCA0F20CF6D75A85CD86A90996129159DE6A12DD0527BD5C9CA726AF24F9B762D180ED0FC95E5FD05E19F4BD0603769271769155C18BC68475F7CC796693B0C7A50F52D3ED674B48A28163B4912E1A66754142ADFB0C0751EC72BF1A4E6474B163FABFE5BF943CCB3DC5D6B1A12EA3716A39D98B522DA49246EB491402299911D4D7544B4B1287F227E4F59E81AD5C7992EAE2F3EB112D346B2D46E1EF7EAA0FDA0A64AD36F0C9CB59C5CCB8FF901D143CF1F94BA579AAE96F74992E3CADE648DAA3CDF6933C721435E6948E8DF1034EB9286B047CC2FF2782ED17F2EB4DF2AD9BD969566F737F74419BCC533F3993F9B9330E4C5B213D582092E54745188D833187CB62EAD134DB88792A75D40F53FC73046716D98F152B4FE598AD6DD2D6CC85957EC5CB0A807C48EF96C753109CB8F886CF269BFE71FC4B7D793E99E62D5B4A17B5B899AC6F26B783EB2E7E26F4A3206F99B1ED1A157B3A89682E5C54CA34AFCA7D23CB5A63D9C76B2DDDC475996F4C86AD3B7DA771FB44FBE5597571946ADCAC7A7203CF75FD0E64998087A1F8B35E32370D384AE0D338C0E49F4DD47C2C45687B6646292CB00609E67F2EBEAF0D8DC5DC93DB6B36CFC6DEFEDA5689E28C9F8802BBEE336DA7CDC2E0E7D2C65CD8A6A3A0EA36B2B45A7F9B35FBC8C7C715BFE91B85141D57ED77CCD3A814EBB369611E5F794CB42B39B42944DA3DD8824D64F3D75661EACAA4ECCBEA1DCE512CE1A2189EBB1D84090ACF0C6C2D8AF0F58B16E4DF2CA279A2E6431A0534EF527AA2D77CA2598391114CF346D3E7867B762945E42B944B286FC71E3E4FA7F44D352F2C21089CCF115DBDB293305B0E0932587CBA3D27458E8CC3714FECC00B0F0A439B17D4FCA324619C2D3AF41FD99930986420C0753D0A76B1BCB59D39C12EE58F63965F1726196161F1E79A3CB8D63A8CFCA32B6FC8956CCBC669D26AB1960ECBCB91614543C53E599F09874D381054A46F4E95D81E872EE265034A4F2F1343D698096C26DAF52B8A1557703155C411D462A8377F888AE203592B79FBE48062EE7EF93B6041772F7C9713120BFAF7FF9C68FFD671FF9C7FF00FCD6FE54FF00BA45AE066393DB714BB15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8779E6690D0E6BDC86E0B62C55A9D0D6B8AA7B1454C555F8814C473508693A9CB59A5E480C49E98AB4CE9E18AA1A465236C05945742699536F1047092A078E2B61716DBF8E15B08391B7AD701482A9130DB026D16ADB1FD78ADADE4395715B5CC6A062A9859FD93912D914FACBEC37FAD95C9BA09CC1906F8A6B0A0645AF8E565124EE5B5E56640EE320531482C21F4EE0AFF29DF2B9330CEACE0F56829B9C8368E4CDAC6C8B24629D3205B22F49B3B43FA35969534C81722095DBD8BF3A50F5CA8B97065B6766FC7EC91909392190E9DA51E60F1A6F539510D822C94E9842EE2B4182922294BE9CBBFC3DF1A6D10413E9C95E9808D9918A3AD6C100A53AE505ABC3569B4C47A10BB8C57C3455AE9E00E9D714786EB9D2B9A3F14DE9B62830A0F10F35689708F3388C77C945800C0A1B0924B69D5D00DF7CCCC658CA2C43CC9A64B085600D3332127032879C5F44D1D651B3014CBB8DD6E68EC9569E93493D373BE4096BC707D0DE5ED224BCD3238D81217E2194CE4EC2186C27B0F95E4120223E9ED98F22CCE9CB2BB2D12485E12E869514DB2B3272F498082FA3BC976F1FA31C6CBD80C00B9B2C4F5CB6D22065A85FB5D72C12689E35F75E5C826423D304E4C16838DE5DE70F28FA16FCA18FE12A4B003FB332B0C9A270A0F913CE5E598A54B82F0FC42BDB33232B755A885BE51D7EC24D3EE1A3E344EA332A05D2E68531CB9903428D5E99931710841897950E5A98F25656C595ABAC805315B5479401F3C56D2F91FE33BE4C354B9ACE7EF8B1773F7C55DCFDF157F5FF00FF0038CFFF00ACE1FF0038FDFF009ADBCA9FF747B5C9ABDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88316FCCD45335EE42630C7C17891F11D862AAE55A3FB5F862AA7CC9751DB08E6A164BD4E58CD00D192493F67C71552654F1E98AA832AF6EB91290B797134C832564620D6BDB1557E551B1EBDB1542C8AC687016512BE3246C4E0656881228DBC715B5E11CEE294C56C2AD0D003D7B629B4CACC1A53B9C896D8B20B34655607B9A8CAE4DD04EA089F20DF14C63AA7153E3BE56512656AC0D9EFE1902CA2C7A01FE94CD4D89DB2B9320F44D1A22C54D36A641B43D174E882B0E4366E9902D917A259DB936C4506FD32B2E44175B598E7F677AEF95972E0CB2D2D502EE3225C90C86CA10A46DB6574E481B270E8A474ED8D360012CFAA73AF15EA71A6C0109258B03BAD3011B3202D523B609F6B314B2E04D22B3590034AD714702362B38D4D08A62BC08D92CE26864A0DC8D8E2C670D9E75E64D0627B39A4352789ED928B8A214F04F4608659A2058B96A71236EB97424C65040F9A34E89EC95C28AF1CC98CDC1CB17806B5108838E3DE800CB3C475D9216A7E5FD3A7B8B80238C31276180CD9E1C4FACFC9BA25D0B4F4DA1019539357C331E591DBE1C2F4FD1740FAEC9C12352E3AD76CC796473469D93DC796E24291B4604886A6991E2B6EC7800667E5DD3440E9F0D0786112672C6F5FB14B68E3024AD587C3B65824D13C69CA476CD41BFB6D9609B41C4A77FA1C17F6B22320208EF97E39B899A0F913F337CA4B6E2E0DBC436AD4D3E59970C8EB33E2B0F827CFDA605F55B851D76FD599B8E56E935189E113865050F8E66C0BAAC91A520A4003B66406B05554D3AFD38A6D706A1AF6C56C36D20A7738ADA14B124EF930D6D54E28754E2AEA9C55FD837FCE337FEB37FFCE3EFFE6B5F2A7FDD1ED726AF6EC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88EB5527A8EF9AF72138584000F862AB580622B8AAAAC0BC4B6D5188E6A1033851F3CB59A058A952062A876E3FD715506A74EF912BC90EDF6B2B5E254AD00A615E25367618AF129FAA5B6F0C0520ABC75207BE0648911B1236E98A11A88C314DB60126A7E8C59C135B35DC644B745925BAED95C9BE09EC0BF08C837C559C5181CACA24CA6DC7A9694F6C814C52DB7B73EBF4EF95C9987A5E876C788DBB641B4727A3E9B685DA314E832B2CE2F46B2B6263094C8172609D5AE983903E395972E0C8E1B001694C8C9C909A5A5A8AF4E9869B849363682831A6626BA2B44A7D9C69B04D42E2D12A76C8C86CCC4B74B4DA1AF4FA3304B7DA6F69684F1D8605B4CC590AD298ADA30598F4DB6ED8944B7093EA9610CB613A9515E27F5620B488BE60D5F4C486FA62ABD1F7FBF260B19063FE62F4CDA08EA2BC72624E0E58BC2354B0E572DC96A9434F9E4FC470B82CB37FCB4D05AEB534E70FC3CBA91F3C066E5E2C54FB7B4ED02D6DED144680394A1CA2537678A349BE91A6AD9CA5F852BDF2894DC8B013A36A269D98AEDDB0464D9020B26D2ECD232A4AF4CB049259A5BAC2FC435053A659C4D134E3D3B7420F2C989341451B988008879061BE4E33A71F246D83F9B7CB36BA8E997521505CA93FAB32F1C9C2CB8DF97BF9BDA0BD95D5CC623A0DC8FC336584BA6D563A7C937D66DEA91D2873658CBCEEA0520658FD26E077D81CC98F27094F0AB44818ADA8B362B6B7AE4C2BB15762AEC55FD837FCE337FEB377FCE3EFFE6B5F2A7FDD1ED726AF6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A0B7896BB6D9AEB72116C388EA3DF1B553E05BEC918DAAA51C2F1E43082A94DDF21DF25C4CAD2AA495D8E3C4B68696564D88C78D6D62B926A41380C946EAA2367351B0F7C8DB2F0D50055346618DAF86B1E30C2AA7AE36BE1A82A146F886C7A6048852696F172DE98A784A64B1AAF5EA7A62BC255982D0D06F8AF0950E209D87CF10120F0A696686A36C0436C66192DBA1DBA6552722124FEDE2240E9ED951939312AB340C29B8391E69E1B647A78ADBF1EF4C8908BA46DB5848CE1C5284E57209137A2E836CCC428A5477CACB744BD434BB378594BD083E1954A5BB7443D074EB477A11403DF21C4E5420591431716F8874DB225CA8C29378D4505075C8916DDC48BB65A374DB0ADA6C232C36A615E3A44288D054A934C5B233B509551C6C0D7232E4DC0A10C04B0D866010DE3284DED6DD956B4191B65E222429077180C93C48F8684712363913365CD21D4D084954746072226BC34F9E7CCF02C124EED4249DA9F3C98935C9E37AF34B2B829F647519306DC3C91B49ECB467D52EE2855284EE49C375CDA31E2B2FA6BC83E4C86CA38E568D79F723227239F0C74F6EB4B13EA0DA8A17A1CA897240A4E96C569F0819598B2E1255C5B46801A6E3AE08C59C2242716691BF414A78E4D914D2283E3156D97240B4C85A36508CB452464F8DA4C54EDA89255892064E32B6990A446A33A3DABC22B475A0CC9C73A699C6C3E1FFCF3F2C7A51C978C8ACA63AFC3D7B66D304DD46AB1ECFCEAF30DB98DE4923015549DBBE6DB16EF2FAB86EC2259FD56E46B502999575B3AEE02A7CC7BE4830229631A9F6C242A91563DF224D32112570141BF6C226B54B4B81E3878969776AD7256B4B4B01D8E2B4FEC23FE71977FF9C6EFF9C7C3E3F96BE53FFBA3DAE4D0F6FC55D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A889788DF6CD7539086B99B8D6871A5538666618D2A20C8C0548E98D2A0E6FDE0A8FBB1A54BC2D1E871A540DC805F7F1C6954F9704AD37E98D3387344464BAEC298D37F120A6B794B7C24E34BC48A855900E5DBC71A5E257DA62140DD37271A5E24C625E031A5E256049231A5E2452AF2071A5E25F1435AEDF4E4834CF74CAD63A1F6C816706456895207BE51272E0CAADE1A2034E994C9CA8F25EE9C8D298C4ECD80A75A5C7521299125AA4CB9221146AB4F880DF2A2562CC7CAEB59D790DAB9025CB845EC16F10E4B45DBC731E5CDC880671A58A28DB22E6E309C2A0E75A77C5CB099451A918B021116F1FC74F1C5253A48A806D8B54954A2D3F8E2D9050E0B5A78E097272A28848158F4E9984425191A0414CAC8641A6A02476CAC86C0BD245515F0C810CC1A63DADCE1629187864405E37CFDE636699A6205687A64C313BB03B7D224BFB9E012A2B97458F876F5CF2D792A38E786478A8DC7C32333B2638A8BDE749D320B481005008194B7009FC50C75D862D8023046A0785316C010F20500E29A57B324134C2A426292B066C0D642A3CAD4A62D6421C5C145624EF5DB2C816B942D0525F173C589A65F02C0E379AFE66E996FAAE8570B40CE10D3F0CD9603BBACD5637E4D7E6158C9A7DFDCC0148018FF000CDE603B3CA6B31EEF25039027DF326F7757214D85F965D171A4E2BF2C99601BE3D3A65127231A9323576E9910C64A0C8D920C56A96AD0E58155D0035AE495FD83FF00CE337FEB37FF00CE3EFF00E6B6F2A7FDD1ED72618BDBB15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8A8F54702DC7305BD2695FD57E9424E2A898542F520E2A887914A15F11D71542A9AD452A7C7154BA7942494A6F8AA5D31323020D2B8AA22180135770569B8C5944EE8E411D28B8B6A1979198A114DBAE2AAF28F4D775E55F0C556DA71E4E7895A8C551EEEA829D7C062ABA08DA46240A0C55341198D6A472F962ADC13A92CBE99153D7161229DC101A06AFD19596704DECFED57C0F4CA24E5C198DB30740A053DF2993971E4ABE8947A7DAF7195B34F74A819650FD457A64496B3CD99C712CF2569C41A6C72B25B718671A0D9849148A139025CD84767AD58C01D5052847539496E8C7765768521A2952D4F0C0E66308812564340684EC3172404CE1734AF86282138B70052A7AEF4C5849368D948F0F6C5AA4B1C507DADB16D8286E7BF4380B9314744D4ED98A42551989208046F9590C8284C5BEEC810D810AEEDC0F6C8109972633AD4B5B765A9269D7234E3C4BCC24D39EE5DAA6B53D31AA72602D3FF2DE80AB74ACEA0EF5A530F139508BD86DECA389A3E294A0C04B394682747E08C7C3906B015ADA60E7885208DEB8B301184D462CC0404A18EDCA9E18B346D8802B5607160423FD440C7DB162434F32018B59096CD729E1B6374988492EAED549A0CB2326528B1CD465FADA3C4DF65D78D0E6CB049D5EAA2FCECFCE9D1E2B4D6AE233462E49047BD3377824F2BAB86EF96678C452C89D402733E06DD0E6145439004ED991170A4B8508AD29932C03741E19449C8C6DF25029C77C8863258789FD9C218A1D901AD053BE5A154591BB1A6495FD84FF00CE32FF00EB377FCE3E57AFFCAB5F29FF00DD1ED72618BDBF15762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF89F0E3D33BE6370B90957306400773B63C2A893C9057A531A5414B39AF107738D2A6360038353D31E154BB508584E08FB23BE34A81F41BAF8634ADD1B74AFBE3C2A0A32D41F9E0E14F1353B32CAA4277A63C2BC49B7C0D082CBBE3C2BC484A537514C785789A1148F22D477C78578995C16E91C4848DC8EB8F0AF122B8464531E15E2524B74120A0EB919041DD3B55548C6525BA2BAD1AAF41E3BE5127320CD6CD78C60D329939514DA35E681B8D77CA645927FA70008DBE79592C3AB2FB280C8E1E9B1E99025CAC4377A3E8500E6A4FD39592EC71C5EA7A75B5694E990655453A11716DB172F105648A86A7BE2E5008C8F614C58108849CD7AF4C5A64994539D8E2D5269AE0B122BF2C5B20A911248AF42712E5453D8A9435CA2412BCD011E195C83243CCCBE34AE564360404C418A403C36C8D32E618B5E219BE06DFC31A6B1043DBE9C88EAC57E795C9BE019569D6D142438503DF2A2E4C4D0653115722831059C8D84C245063E98B00142301771D7BE2CC05766DB16C010ACA64AD0D08C595226D548A8AE2C486D890C77C5AC8519588077C2C084B26734EB954CA46C92DC826BBED8C249914B48F8C0FA7365824EAB54762F867F3DA0FF738E69DBFA66EF049E5B56777C797AA05CCBB53739B5C6E833F34BD97AE65479B8325C3651932C02ECA24E441AA0C88632688184315608BC47CB2D0AA4C8BE1D724AFEBEFFE719F6FF9C70FF9C7E1E1F96DE54FFBA3DAE4C317B6E2AEC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88C69196127AED9570B9096DAC8649D09D80618F0AB26963050B571E15484A8697C287070AA610308CD41AF88C3C2ADCF2ACBFB1F11C78556B47C63E5C7B74C78552891B91200E27C7052A6FA64609DCD70213292D95E4A70A537AE0295CF6C586DB64789544DBB12AA13EC9DCF8E08CAD53386D49A129C6992B545CC68AA03538F6F1C6D54EDCB4A695C6D5368AD893CB9F4ED913BA2DB9A42B48C0DBC72A945BA324C34BB33248007EA6A4D328945CB8167013EAEA13EDD7BE5243951927DA622C90056D8D4E52609326436500120402BEF95CA34DB0C76F41D3AD38471ED94C8539B8F15335D2217F500029EF95172E269EA9A7A88E38EA2A69BE066237BA6E6207E2AEDE18B91134E238D3BF862DE26AF1C7CE9BF1C549B5AABF11F638B4C8A3D361F2C585371C7CBE2AD37C52364CED5796DE180B7C7226491D3F6EBF4640B3E25B27C3DEB4CAC864248095B96F5A65526D0508CFB78E479320503E887979D694ED9599B6844B5B86150DC699519338A6F6E802019592D802776D1D5280EFE3823CD289766E3403A65BC2B6A28581A15A0F1C7859892282961B1DCE3C2DA0A998985487EBD4E3C2C81B5D1A322B1E75A63C2B24BE49DCB9DBA63C2D6A4CEEFDE871E16B2859A1928183D699465145318DA477AF242A0D0B1390894CA0878F9B3A9A54115AE6C7049D4EAE3B3E30FCFBB7923D45AE78F2AEDC7EECDCE1C941E53571DDF1B6A16ACB3C8EC69CB7E3F3CDBE09ECE8B34774918D0D3C333625C1986E95EF97736B6CAD3BE5320DD02B9412064445245AF1193DF080BC2B0AB02464C15E1586363DF1B5E17F5F3FF38D029FF38E3FF38FE3C3F2DBCA9FF747B5CB03597B6E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D98A8B7639072125B39544C3E78AB27797F75F462A948156A62A88A30C554E163F584E5F67154E27E0D0D075A62AC7648CA82701546E95381285F7C8143339230D1864153DF2252A0A08201195211D0C695078D7C718F34A39A48047C76072C548AEC8E69C0D41EB8AA63A7C144E647CF154CE175AB8F7C082B1A1F524141D4E466CE2CA34AB6F488246F98F37331B2066569157282E4C59269F6CC5D4A8F848D865726639B34D32D97EB09C865322E6620F41855508551B28DB289976100C974992928A8DF2825917A04120E2A7C70B743927B6EDEA003B62D88958F93118B64516917100E2CC287A7F113E2716B3156040F9628E144C4B45DF7C578530B55EB812228A1CA83205B5425E546C8499452E7E54CA4B70429EA3C32259072FDA39410CC146A005699021B01B4CD015400E4086C0532B7978AD46301452792351CB76CBD00A2163E54DB61BE2CC145A41B74A571660AC922A0DB6C5B6254516BC875C5050BF54E4EE695C581287961E1DBA62D64A02694468478E63E50CE058FEA24BAA9032B8865296CA5C9A28E33C7AED99D846EEAB57C9F257FCE4246D0C493B2ECDDE9F2CDCE11B3CAEAB9BE25D56759642C050140299B6C01D0E61BB139012C69F4667E37026BD010287AE5E1A951BF865726C8AE465005722DA15D5D7EEC2AA9453BD3AE2AEE2BE18ABFAEAFF009C6BFF00D674FC82FF00CD71E55FFBA45AE5A39349E6F6BC28762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EBA9D962318514F1CA2DBD2086568E74237E4DBE36ACCE37F5223DB1B543A8E2F5EB4C6D51AC57D3E58DAA5F50581AD0D76C6D5305E4C8057E9C6D5053A108C08DBC71B5405BAFA73F20DBD712ACF6C6E8AA54A06DA943912944170E6BC403E195A15D2E022BD5474DB0412C76F2F19A4214D07B658AA96FCD8835E7E3ED8AB258A65861DE9B8E98AA5E977C653C68C09A9C5053DB39C33A92A0E426CE2CC6DD8351BA517A663CDCCC689854B5CA6F9417262F56D06C8488A37F63944CB7445A791C0F0DE2A28A8AF5CA497371067F6567249C7634A7DACC79173E316496561E8C80F224E524B221964638A281BED930D914DECE765A7C35C2CD3B81F93569D4E2D91473B6DD3166146353254D29BE285850F2229B62AAE8EE9B7018AA6768F4EA3AE2551ECCA83C72B2C908F286AED909328A11C8A74CA4B7041484006942476C052A51824824532B21368F8EB5DF61E390219829824818053B656436028F80A82141AD71884996C9BC4AAA011BE588053355AA29A52A77C5B01560CAA37C5982879248DC30AF4C59C4A0165547206F5C524A3519284FF375C5AC940DDAA052791C5812C62F1BE02C054A9E994E4512A414BC1EDD5C8A1F0C8C53C4E6712A20540420AE66E1165D76A4ECF9B3FE724B4F79FCBB1DD2C615947D91ED4CDCE10F35AA7E736A49E9BD1CD0F1155CDA61E4E833F349C0A0E43E23E199D8DD7CDD52DF115A13DB2F0D4D9A93D32B93645408F888AD37C8B6856403BB6154482B403962AA8154FED9C55FD75FFCE35FFEB3A7E417FE6B8F2AFF00DD22D72D1C9A4F37B5E143B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFF00FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF876BBE87315C8485CF160DE06B8AB2DD364F561FA31555941018E2A88452D01F962A955584943E3B0C5538B771C77FBB156AE1D1D4A8EA70C552A02928F9E48A197589AAD3DB22528D63C72A4202EA7288287AE304B1A7959E5A7BE58A9D5BCAD12123BD3156E5D4491C4B6F8AA8C37039160D5A9C50591E9B745A5515EF909B38BD1ED5FECFB8CC79B998D3AB14E57287DF282E4C5ED7E598D43A46DE198D939B918D92DD411A5DA35075DB289173F10675A5BC7E94629BD331E45CF804DE8CCD551B786524B221388549550763DF2D8F2484DA24E00649926D6DDB16C8A3DFA62CC23ADE35E35F6C59D34235E67DF15A44FD5C374C569AF4590EDB602B4BDB91C8162A251B7ED909328A83A353AE525B8210A357A6053C9B58DC6FC71402AA0B1143B7BE408660AF5661DF2B219828BB695BD51BF6C88E6C89D936FAE84E35392620B23B5BB8E48802462D81AB89929B362D80A5227ABB0E58B3057AA826BE38A928D8CA804571604A1AEDD781DF16B258E3CF17C5191CB91A8CAE41ACC964482E3946A9B0ED8C42789A82CE732B2AA1E20666E1145C4D472795FE7CE96F2792E591A3FB009CDC610F39A97E4E6BCE5EF64A6C17E1A7CB3658DD06A39A5F08063DF3371BAF9B7407A65E393535C4572B9364541E262C48E9916D0B789185555436D8AABAAB53157F5DFF00F38D5FFACE7F903FF9AE3CABFF00748B5CB472693CDED7850EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87BBB5531935DF31E9C863A543921B61ED8D2A6FA4DD324A200070AD2A7AE1A54E75173071F4C0656FB44E0A54C34F904B0716006DB61A54B2E222B72A00AA93D7052A342468952C41231A543955506452491B50F4C2020A1A83D415385871325D3E4F8B8F6E38299DA6373444E4BD7DF0708674C7EE1E4956941B1C1C20208A4BE38BF780B57E8C076502D386904501E00134E87236C8458C4B2C92CA6A00DFB640C99885A3AC80F4E466635076C788B194190E94DFBE06BDF2066CE117A759CCC4AF4D865129B9708B35F2E446F2ED44BB007F67283272A317B669F69F5495668EA76037E998F236E4420C87D2378E1CECC3F972B21CA86CCC749B3A471835AF7CA65172A136530C25187C35CAF80368926D1C2397235A9ED92029B446D328E20C37AFB6165C29A4302A01427E9C590D915C1586F5C520A362015401DF167C4E650096A9AE2BC48A85CED418AF1225959874FA3015E25AB6EFD5853293265C2E3180694EBB642526622AA2C95C7C24D72A25B4042B69D3A49CB882A0EF91E25217B5A3FECA60E363C28792D66542C62F8475A6478923642B46C3A46D8136B6349C3AF08CF23DCF4C40DD0648EB9B19446B21A863D874C953113455A7AB1A0E47638D33135D7771E9AFDADFDF1A6CE341C127AA58D7A0C04536C668E499D76FC7032E26A5BBE20107AE2C52A9EFA490F1DA98A0C6DD691722CF4E4D5D864A301269C9B328D32131373F4D4D7AD4648630A192470DBC70BCC8A0DC336E87A53333144071353C982FE6C68306B9E45BF515F552363C53C7369843CDEAA443F147CC3A4CB6DAC5F5B5C03188A4603E55CD96301D2651658DB22C5550DF2CCB8389382C415515CB9A0C5771CA6452154283414C900D814E445180AA9C6C4B71A6C3224A53058C507BE438D5FD727FCE36EDFF0038EBF9063C3F2E7CADFF00748B5CCA8F20D079BDA70A1D8ABB15762AD374C55662AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AB97BE2ABB157FFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8749E4AC447B652DE9347F131A77DB1557B6AC3386E9BE2AC8AE5C5C427F9A9B62AABA7B98D4027154C4C625607BF6C550579CA31C7BE2ABA08CC916E31415268087C5AD34B4E51B03F462D8134B97E51FD18B68415AA076901F0C05126A5B602A5464648097CC484653D32B6C4A963A927C7BE565B62B91FD30E3C4E218493CD1A4E532FCF2126507A969FBBA8F1198E5CB83D5FC9B6D5BAE9DF292E541ED92A18ADD683282E54026BA2C2EC39B0D8644B7443D0F4C8D782E5527222190C71AF31B641BC04C52104834EBD316F8A67142076F9E2C9305B72698AAB0B638AA323B7341B62C9CF6C7154C2DAD136DF154E560840F703014851692255F88019410DA95CF7766A08E601F1C810C9049AA5BC469EA8DBDF2B21B0228EAD1488C88E3938F872045325B15C4951591720C11C2E55455DD597B8C55DF5AB56EC98AAEF5ED88FD95F7184319206EAF2071C3D41926210735CC7140A43D77ED8B20C62FB52E4E141F6C5B137D2C92189E8C36C05B2298CAC1109C8B3B486F2EC28DCECB8ADB1A7D7218A5E25FA75C56D33B7F355A5BD393800E5B02C08B4DD3CFDA7A2D0381F4E49908D2D5F3FDB199B8C808E1B0AF7CBB1C9C6CF0B4A0F9D67BAB6BFB49B7826560A0FBE6CB14DD0EA30597E74FE7368325B6B97B7B04748A51C811E273638A7B3A2D462E12F9DA60F1BA07EE73371C9D76514887015A83C065D6E21E6B7204A40554FE1841D99A9C9D701296E28F7AF8E564AA37A0CAED5FD707FCE36FFEB3AFE41FFE6B9F2B7FDD22D733A1F48683CDED39243B15762AEC55A6E98AACC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5572F7C55762AFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8739D15050D6994B7A56838C8A53A72DEB8AAACCDFBCF87C7154E2DE86024FDA036C551B6EBB6E37C551F1CA237523B763EF8AADBF40F1FA83ED1DF156ACE5E30D0D3962828D58E3937A5716B5748B7A1FB23A62D817CA6A287718B68528488CB15EF80A24AE5CB0C8C9012BBB4F877CADB12C8C1DC0CACB6C50EC84B1E58B0927DA3C6038206F5C849941EA7A38F526507AD36CC72E5C1EDFE4F83D39B95329939507AE9ACD1A2D3E119417371F2659A55BFA70F151DB225BE219469B190429D88CAA4E44427D6EAED3053F6720DE032686D01A6C698B604D52D1788A038A5328ED8F15DB6C5518966081B7CF1555312203418B2433E2ABE3623BD3155579F82925BA024E2AC5AFF5A8F81A380720437304BEBDB89598A49F09CAC8641266B8946E646FBF2B21B436BAB4F1FC21CFCF2B904AE3ADDCAF499BEF394B05875FBCA504E7E938AAD5F30DE29DE7A62A887F32DC471971354F4A610C648287CCB712CB4692B9260190C1AB4D31285AB45A818B30EB6E7753FC7B8AF6C5B1E81A7C451197A055DB0499DD35773908DB8DB22BC4F3ED56EE5A482BB0AE2BC4F2DBFBB732B166A11E18AF124536A2EE4297240E94CB20CE25080DECB25217600F8EF8934D9619058E9FA9F2462599BB1DE9928CF76899B67B67A56AB7118528294EC3336191C2C98ADE51F9ABE4D9A5D3EF649E127D0879A353BD333F164D9D06B70D17E7FDFAC4CD70B30FDF40E4474D86C7BE67E2C8F3DA914972492301EA50B77CCC8C9D613BABAEF4AE025B61BAB2004D3240ECCCB6F12D2A7224AAC0FC7E8CAC9558F3B76A7CB236AFEBAFFE71A8D7FE71CFF2049EA7F2E3CAA4FF00DC22D73610FA47B9A0F37B5E490EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87FBA8BD4048194B7B1D95BD16A1EB8AAAC3FBC353F3C553112FA6A476C553AB12255A8EF8AAF9E321AA3B74C5549AE015F4D8EF8AAC4AD76E871414E6D7B138B5A6C801E9E18B6042DC6DF3C5B52DF50A927C701449176CFEA353B646480985DD972841A74195B63152BC1C8EC0E565B62A4D4635F0C430927FA42FEF07EBC849941EA7A0445AE51BB0EB98F272E0F7DF2E22D40194C9CA83D12CB99611F5DF6CA0B9F886CCEB4D0C38AD3E8C89E4E44597E9F0FF00A415237DB2A939116530DA8F5850641BC06490460103C31649B2C6B4C551491B6D41B62A8D446A0F871569EDCD09A6E7164817B73BED8AA1243C176ED8AA4379764065AD6A08C55874D652DCEC95381B9520D0AE08355241C890C9171F961E43464A8F97F66565B0233FC191B293C7E2ED954F932E88197C9A00E998CC12CB8F2B8B78DA5E05F8761DF156297F6621AD206DBBD31563176EC6328B0B29AF5C218C90964D289B743D724C0335D3999E52A548F8716619DE89680B863D716C6573968D2918DFF6A980A4A4924C4F20FB7BE4516C475754653C37AD6B8ADBCDEE74C92791A83A9C56D42CFCB5732CDC1622E09EB4CB22764893D3347F216E924D1F1EFB8FECC848A99BD2EC7CA9630AA82AAC7AE40163C4CA6DF4AB5800E2829F2CCA84940619F99FE5A1A8F937549EDE1065F4986C3C01CCFC52D9D36BA1BBF1A35FD2CD96A5A84338E327ACDC54FF00AC7363864F27AD0C6648CC52943D466C205D213BAF4C9B978BBD156E393D0E36CA489BB4E2A3B57204A1219A52B5C892A8749F91A57A6564A1FD7F7FCE346FFF0038E3FF0038FE7C7F2DBCA9FF00747B5CD9E3FA47B9A4F37B6E4D0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88FE09E89206F986265C86217D18790FE1928CAD5640FE91DF2684C42ACA093B8C2A9DE95F01A1FB3E18AA6578547D8D81EB91B4A41229E7CB2064847C0EA29CB718612B2829FC7E888EAA37F1CBA835A26DDD016277DB225B0284E19CD17A65664DA103242114B30EBD30192D5AAE9FFDE644C9908B241CE489D4EE00E982D980C4F50B52AC59453DF06CD8024EBC91B89EF9125B238C1E6C93493FBD51DB2B914F000F5FD094ACC9C45052A731E45B601EE3E5621A401B7AE504B9B08BD5ECA14AAB22D189EB98B3951765860299FE9502D15996AD90E22DE22199E9F6D1FA9EA71F8CD2A7236DB10C9E1894B82474EF8B626B144ACE7E793114A611464B713D3C325C2153A8E3000DBA0D8E0E10AAAC0A8DBEFC7842AAB0F86BED8F085B40BF5C7842DA577708E2DC0531E15B62F3E9EF2B13C490712026D1765A5246DFDDED9512BC4C892DE355A7015A656496C125C88A29F08CAC96F8C95C01D29D72B2CEDC638DBED2D722634B4A0F676EC0D23049ED9548522987EABA7C6C5FF74BF2A0CA49626DE75A8E99C8B462314AF4A61848DEE903BD278F4708F511EF5CBEC32E109FDA69C435553E223AE3B278598E9903C34EC3BE1B09A4E652163241F88F5C8C9B211058B5DFED6FD6B9149800C6258DA4675AD47718B510A967A6C4CFF147518B512CE74AD3ECADD59961018904138AC4B2B49232B420500F9603BA69689A388D176AEFD71A452256FA9FB59206992716CF16A9A65E69B3012452C6FCA33DFE1399FA736EA759B97E31FE70E94BA6FE656B564578DAA3B3431781A939B9D3879AD6403C655A49EB34E794A5882DD36068336511B3A1C9000AA00074DB2B9158121176E55483DFBE52665CB8C6C29DF5C301B361E22A62C6E6766AF235C9B02104B38434069878583FB10FF9C653CBFE71BBFE71F1BC7F2D7CA67FEE4F6B9B087D23DCD079BDBF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8DAB09F719801BD8DDC8A4849EC77CB2294B5C736AA9CB1531B69285636FDADB0A19143FBB5AD7A60554F53D45627B602942BA77F0CA8A143D4DC01E38C0D154FE02C621E19719288A362069F3CACC9B045308E2046FF007E5664D822A7731064000E991253C2A7A7DB7EF3A64789908B2BB5B6AF30456B8F1331143EA7A627A65A831E26C1160A6CF94D41DB6C04B6C62CA746D3099936AF8E5722A43DA746D302F134DC65132CE01E9BE5C88ADC5076398F22E7630F63D1A20F22A1F1CC69F376388507A3D9C3C19401F4641B87366D610D29B6F8B6C53A4401C7862CD31B789CB123A65A392A610C3273C2AC8228C71507AD3155EF18A53BE2AD32EDFC715413AEF8AA19A307AFD38AB696D19EC36C0555BD140360065549010B22D180F7C810C8158401F3CAC86624B3991B9391E16C8C9DEB0C4C5B4168DC8405ABD3299452C72F6F1199878E6398A6AD875ECAA5C90054E400A4F0D2053E371B77C3C48643656C6B5A6D4DB1E254E12260BB63C4AB5A195C30F0C902DB89239AD253CBF56499C9237B57491B6A16C5A24995AC0C083DF16892730C8D1EC72405A225182E881D70F0B2B51376A49E477C7856D512ED36DFDB1E15B649A15D1127C3FEEC0CB4FA0E6660D9D6EAB72FCAFF00F9C90B196DBF342F66238A4AC493F7E6E74E5E73561F394A156460BF66B9B2076745946EA7FC72A996B886BD42A72AE6E643925D7331634C980892493DCFDA51DB6C980C4A56CE49D8E4C06A7F645FF38C1FFACD3FF38F1FF9ACFCA5FF00746B4CCD8F20D079BDCF248762AEC55D8AB4DD315598ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC55D8AAE5EF8AAEC55FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D880E040E87B66006F492FA2F88803AE5914A1C5B7186BC7E2F1CB108781585C46CDBAA9C2ACB15E3684803738154955A35663F6476C05285594BC9C6B55AF4CA8A157D052E2837C8F567109CDB3AA808D8993688A6B0C44B0A7D93DB2064D8229EFA01635A2D09CACC9B0456081581F86A720649E15D6F6AC1C7A6BC71E26422C9AC6D242D535A63C4CC4532BFD3CBC068B534C789988B036D34C731F82849C789B04597E8765C654257204B121EB9648B18400509198F32CE019C688A82652A286BB9CA497371F27B068CA81D582D0F8E5122E7E3E4CF6CCF29D2BD3C322DA39B36B4AF3F84D17B62DB14D56A5B03364368E811011BD284E5D1E4A9B200402A389F1C2A8F49102AEDBD3738AAE3221EA31543927715DBB62A82949036C550F473FB471556457A801A82BB9F6C555E458A31549BD4F639021925B35DB80CA2DD189E8DE190216D45EFA38AD889621EA53EDF7C810C4C92A4BB8DA29A46958B28F8129D72206EB19A0D2EA607D53C9D3F9299618B68CADB5ECB7069E87A71D3E2343944E0DB1C9691DD7EF83F01C58577198F28B609B1B78A560C492483F6B299C68365DA2ACEDDCC82BBE55C28675676A0AA80BF1531E154D52C588E98F0AAE5B1707A75D8E4A21B71A12EF4F2A84AAD0F8E58CE4C4E6B26939A96E2F5F84E2D1256787D2B16319E52C42AD20F018B449E6F79F9A5E52B099ACF51BD4B6B984F16151BE5916B2692D93F387C822A1B5B2BF223254BC4BED3F363F2FAE24A0D6D9B7DEB4C697899345E73F28DE11F53D5D2A7A02C31A5E2665E5DD574C9264F4F555256A428208DF2FC45C2D46EF833FE7278423F31E36DA482653507A13439B7D39741AB8BE3F6565BCB84635556345EC01CD903B3A2CA374422214625457B65536B8849677605E86832500E4C521B8B97527E3CB00625262EEECC791DCD7260312B94E4C06A7F64DFF0038C1FF00ACD3FF0038F1FF009ACFCA5FF746B4CCA8F2683CDEE7850EC55D8ABB155AE683E9C554F97B62AEE5ED8ABB97B62AEE5ED8ABB97B62AEE5ED8ABB97B62ABB15762AEC55D8ABB15762AB97BE2ABB157FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88BB53C866006F5971082E0D3BE5914A16E00488FCB2C42550D19E83AD76C2A98DBC844BC3DFA6054E2E29F56603BD3014A4515564CA8F3423C5C0420F7A65726DC7CD745704B8232B25C9AB6490DEA22A6E2B5CAC96C8C593433ACB1AEF9025B04535B4B70E188A1DB20649E14FAC6C55985464789970B281A7848C328C3C4D9108EB6D3DA78DAA2BB63C4CC063B71A3137205325129AA4EACB4A68DD6829824C4866305B32B2023B663C8B38B35D1A03EAA6D9492E6630F56B106109951E6E6C59D69DF100D81B073673A6FC4AA69D7BE2DB14E917E3C59A7D6B6C48461D0EF96C792A751A711BE155C57DF157703E38AB5F4E2A849BA62A82798462BBD71541B6A616B5AE2AC7F51F31D9C1192CC63A77C910D8C02F7F30F4BB763CB520A57AA93FD99590C0B179FF003C3CB167270BABC593DABFD99590D04A47A97FCE48793ED2A91852C47C27DFEEC111BB59953CAB56FF009CAA82DEE78DAC21A3AD1401FD99710C2390DA5F27FCE4A6BFA821FA8D89E0C09E407F665120DF1C858D45FF00391BAEDAFAED776C556BDC7F6663C839519BE91FC9EF3EBFE61426231805D4B961ED954837C256FA2AC7437AA9E3F4655C0DCC9EDB4C78CD48C3C0A9DC160481515C1C2AACFA79A834EF8914DD8D0379A79E1F7E06526177962A03963C585787BE2D1248D61963B1D453ABCB1B08FE74DB16893F32BF313F293CFDA8F9AB50BE8209A5B79A4668F8F402A7DF32314801C9A64C462FCACF385B6D73A4CF2D3BF13FD725B215D7F2EBCDF34CB1D9E893C751BB713D7EFC7657A0F977F243F30A7991E4967B343BD09A7F1C695F5FFE597E526B1A5DBC6DA96A0F34CAF5662D5D89E9D7251E6D1946CF1DFF009CCDF253680DA3EB11356474EBDFA1CDAE9CBA0D587E7F593C9373965D9DBAD73640ECE8B28DD16A7E07F1ED954DAE218BDCDC0124895E8694CBB1F26F88D9239EAE4E5A031921F8D065803595226876EB9301ADFD94FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A0F37BA6143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88D8294F845330037B52D4B29AF7CB2294AAF6BB8CB152D8D5830A547CB0B13C930854870DBD7C72122C2253953585ABBE54496C4A1BFBC6F9E441552641238567283AD7F86322299E306D98F967CADABF98AEE2B5B3B62C8C69EA01DB31CC9D8E385BEDAF227FCE2EC17515B5D6B32155900A293FB5BFBE5129B9F8F102F43D57FE716EDA2B988E9CF5403EC76FF89663CA65BBC10F25F35FE476B9E5FB932C687D193E1555ED4FA72066C7C10F3E5D0750B0B8F4E5571C4D0D7009A462A6616D632491014AF11BE59C4CFC20BCD9DC4428B551ED931309F0D012DB49CD59C50F8E094BB94C02636B1134F1C8711699C53368A452A791E9B60B6BA65DA0C94750C706CE442DEA763229E15DF289F3765879334D35C55476F0C8B7B3EB023E103618AA7D18AB0DB02DB27B16F8554F6197479330980DDC006A3C30A551862AAB18046E31545718986C82B4C585A57716ACD5E228322B691CDA75D716F8493BD32B2516F3FD674BD4DCBA4523A73040A1E99124A5E3BAE7E4DF9C35F467835BBB8977AAABD3F8E4F88A402F1CD4BFE71BFCE6F3D06AD732B576ABF5F9EF82D9D16357DFF38C5E757A97919DFF0098FF00B78B218D8A5C7FCE3179D43F22BCCAF4AFFB78F2639310E1427FD0B379CC48ACF6EBB1EE3FB720723891C459FF00973F203CD715C436F39F4A0604391B536F9E4253722185E97A27FCE37581BC59757B812AF2ABC2C6A0EFE15CA8CDCA8627D4BE51F22F97BCA10C49A3D9C5048ABC4B462808EFDF2A9CB67271E3A2F52B68AA828287C72102DE629D5BD9B4AA07877CB835909BC569E9815CAE4C0AAB428C0D08F837CA81B402424B733060D18415E95C2DC0B0ED474F6A973B835A0F0C5B0C424F1C216A196B4C5A6710105736314EDCC205E1B103BE0B21C59C2F9249756B69103CE352464F88B5F865298A6B78A5A450278D699602BE19661653F35154070DAF8659369F7D0DA144745FF4821547BE46CDACA1B6EC37FE7263C99179DFF2D64586D926BCB088C826A55C0E2C7AD7365A693A4D5C03F119A136BA9CF6922F131C8D191EEA48FE19B8C727439318B5194888DD21D890787B6DDB26402B080616EB44AB6EE6BC98F5C9844A21047ED1CB034C821DBBFD3930D12438DC9AE58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4F37B9E143B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B535CC00DEAF28EF9645528BA1C8E58AA10C60B8AE2A5181789C045B590982FF7669E191314829431FDE36532D9BE22D52D2C9F52BE82D233467351F466365C941CCC18ACBF49BF21FC950E9D6105EDCDB2BD003C88F9E611CAEDB1617D71FE2ED0B4B8E21385E286813C0E512C8EC71E057B7FCCAD0EF6EE386270A76037CA2591BCE165F7369A4EAD6CF2CC527122FC209AD32BF111E03C475DFCB0B2D424966B78946E69B63E22F80F329BF2DEE609654856A17ED532D195071525571E49BB86BCD0ED93191071A437BE567442CEB4206DB6113B6AC90628BA7345395F7E98789C5945329ADB8462BD69D71B6BE156D224E33818F137462F48B49887515EC32B917618850679A4C84B2FBE06D7A3E9CDBAD76C5594DB8E4C3154E6D5C89197C32D1C9984DE13571852886FE38AAAC7D3154C228BBF638A6959A21DC74C82D21999882380CAD692C9ECFD53BA0A9DABE1919288EEE8ADE6B65F4924EA29838DC8F0D092DACA8793C8013D1BC31E36631A5773F003CAF01FA4E3C4D831B1E96F2047DEE86DEE72139ECCBC2B496EF568492A9722A7E798A7228D3282B5C489EAC373561D1413959C8DD1D3A274EB7964B80D2C859ABB2E40E46E1829E8D6914CC1226B6E117FBF48C8F1DB2963A65B6D6E11176AED96C0B5109D4238A82075CBAD810ACFCB8E5732D6425CED22568763D72B896043A38A39012454F8E49B6297DC5AF21257A0FB38B7249FA3958B6DF4E2D3916C1A423ACBCBB1DB22538B1F131ED53CBE8FCA87AE20B6F82C364D0258A60231C93A93938C97C047C505C5BAF43B6596BE026B6B0C976D645BED452127E583AB899B1D3D3AD2DC6ABA76B1A6CC39ACF6C63507DD48FE399D84D3A3D5C2DF87DF9F7E50FF0003F9EB50B20BC6970CF4A7F3B31CDB6296CE872E3A2F1CD4855D641FB4BBE650DDC7E4C4AE362C3C32C6322969FB67241A64876EFF004E581C7921C753963497F655FF0038BFFF00ACD1FF0038EFFF009ACBCA5FF746B4CBC72692F73C28762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF889B360BD730037A3E4A1E9DB2C8A529BB42C76CB10A50AF165A8A625211B55C622D8494E52786C77A8C998ECD60EE83BCF8AE9388A506F4CC2CFB39F845BD1FF2CB493A96BD68047CB8CAA6B4ED5CD5E59DBB7D3E3DDFA93A3D8B69DA6DABA0F4D1211555D8663176D8A2F2BD72D751D7353962B3321084B1504D32893B1C71D952DBCBBABE9EA26657046F5EF98F26FE009EE8DE78D5B41BD1CCC9344D45911892001DE99595107B868DE79D1B5B31AC92FA5310014069BE36930658D6A8E1DD40E128F81BC72C69945299F4A421AAA0D7C46581A0B0DD574359012117A1ED9312A6A9C5E51A9E83C2524201BF618789C69C58F5D69DC410476C789AB85274B5E126DF0D0F518F137C22CBB4752028356DFA9C376E5C0507A4E974053B7F98C2C9E83A6CA15803DA98AB288E7008A62A9AC2E480C3BF5CB63C998E49A42E69D4E14A395BA62AACADEFB62A9BDA5D536206D8B35F7373CA945A5720B4840ACDD09CACAD221232BD6BF3C84CA62375D2AF53D0E637139A12B9622FF0D49E5B6F8789B404A2EB492CA69DB071338B1A9BCBCCEE47106BED919CB66D88DD47FC2E3FDF43EECC4B6F115787CB8D1C8A40200ED902590A661A6E841543155A8F6CA8A788271E97A478D6A3C3082899B08E801D854E5F02E3109AA82A0153990C4869A471EF954CB590A2D2B32B0200C840DB54C25A4B89050903C32D6714C963F5A3DCD0A8DB16E4B64B295492010B5C5A72289825D8455A7ED655334DDA734BBEA32CA28687E782DC9E2583494460B201C9B71F2CB014F10448D060906EA3EEC9028E25F1796914F258FE9196C5C4CC2D36B6B45B53B2B03DC8EF97E39EEE9F518DF9A7FF0039C1E5223518FCCD15B8F4EE295217F9797539B2C32743A8C6FCE1BE9B8832EE55968066CF13AB9ECC50124B549CB4B594249D4E48354940F4CB038F2511D4E58D25FD957FCE2FFF00EB347FCE3BFF00E6B2F297FDD1AD32F1C9A4BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF88089A86B9801BD338CD40F1CB22969E30C32C420D8713B6291CD6D4E4A00B1C8B58D46E69979AA681CD40FC7331F019ABD4BB4D353E9EFF009C74D21751D692A952B535A78669C9DDDDE101FA397F6CB6DA3D360563A01DF2120ECB0B7F96FE5B8F503777862ABD08AB0EDBF88CA661D96309BF99F4A3043246918E9D8663C8373C0752D0F50796436F096321A37C35DBEECAE99458DCB65AAF96E48EF4A4B50C0D02B78FCB101127D05E48F375D6BB6612E418CDA850BCB626B4F1CB0071E6CFEE66658C7BE594E34C149A525D1AA3AE46450030AD4EC83B31A6F91DDAA51613A958D0F4A6DD71DDA845864B6A56423EFC6CB7C629EE92854283D6B9747937067DA79A32E4959BE9FBB8FA31564A83718153C85A8A9F2DB2D076660A6B136DBE1B4A354EC3F1C2AAEA4D3154742E148AF862DC119556C8324C6DE256A74DB2B28559630B95CF92421D979661B900A87A7BF4C0CE25B30F2ED8B60696C4160481B74C05B224DAAFD487F2D7E8CACC5B812EFA90F0032042D9575FDD0E23E9CAC861C454DE124FA9D7DB214CA3225673F4CF4CB62C885C353111AB6E3A65CD65506A91C9DB2120C0B6F771D36DABD7238F9B44D0E675AD69972628BB797D571C7609D716F64B58A587871DE98B4CC162B7F21D31F8769872194E45C7612F87519A46A274F6C886EE229B44E646066D9874F96482F116416C22E23A64D788A756F2AAC4151030AF5CC989D98917BAA344D37488610E0E78BE6AFF009C9CFCBF4F347E5EEA73BC5FBCD3E2661B54FD963E199D824E83541F83FAA5A1856F216D9ADA5650A7AECC7B66EB09D9D0E6D8B0FEA58E5E5AC1D9072F7DF2516B9287ECF5ED96071E4A2A773963490FECABFE717FFF0059A3FE71DFFF00359794BFEE8D69978E4D279BDCF0A1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87EB35F7CC572138A74DB2415A634196054B67900E44E487355B1CE38D2B96EC8282B9AB74F1CA665880A912F22CBDE99ABCE5CCC5B3EEAFF9C4EB113DD988815E25AB4DF6CD69767A626DF647999435D5A5BAB1D880403FC32B93BDD3F37B97962CD6D34832280ACD0EF414CA245DC621B30AD5A77B849A302A6A77CA2459494B4AD209812478C115DC951FD32316A1CD3AD5F49D15B4D91DCC3EAAA134655EB4F964993E64BFF300D235631DB30085C8F82806C7DB1453D5F45D7E4D52D54D6A683F56147084DE0BB3C9C4B4DB619645A728A49EE7799DFB1E992A68A627A944199EBD4EF8D2D30A9AD944BF3C6928AB440B28A61566BA79A30C559A58BFC43E8AE2A9F46FF10C55388EE00551E191BDD04A3A3BAA8EB8414A363B91B6FF003CB1B02312E47CE993661328DEB43E3DB16E099C4E38FF000C82A2606A656528D2A5C0A75C84D5BF4CE6310DA1A2877C890DB169537E99590E405754DC572239B656C98C511A74AE4E419C10D7111A1F7CA64E4001085780DFE9CC793090097CD7263A953F17860873681CD26B8D4E58EB5A6F97AC92A7BD9A405877E9938B4C9AB7BC9D09CB29A095433DDC8E4AD7010D68F82EEE0515D6BEF819C5368272159E9C69DF16F82223F307A4425457A62DD1016DF39D5F871FB4A28299092C804A6386EB4B928C84A9EE722C53D86EA3640CFF0068E2A98DBCF0D462A9EC13D221C3ECD76CCBC5C94A6B67744115CB1C2CE16F9AB4B1E63F2E6A1A4900FD7A090014FF00248CC9C45D06AE0FE76FF3A3CA4FE54FCC6D7347652AA9348C05283AB1F6CD96293CFE68EEF03BA6FDE483A10732E25A2B648E7152773BE5C1C69F35315000AE6445A96E5A036C407F661FF38BBFFACCFF00F38EDFF9AC7CA3FF00746B4CB43833FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B31D2B98AE426E47C3920A8694EDB6F9605482ED982BD01AF864952E86670D435F961B414D50730396D909A0370370B8907B7539AECCE5637DD7FF388F76A359642E05617A0AF7CD74C53B4D3737DAD359B5DEB30730410C280E63C9DEE9F9BD5EE3513A558B2745F4F8E5327718B9304B6D4629D679188EA69BE63C99496DDF9DEDB46B231B952D355547707C72316A1CDE15E63F38EA77F2C896933047A8A2939364C22DF48D42E6669E7E72173553D7157A56853DCE9A1622080682A715672D70DE9A3AB862FB900D72D838F991729E56E186EC7A81D726D2905FC25CA9FF277C558B5CDA9049A6D8AA95AA71931565567B32EF8AB2BB37A11BEDDCE2A9E46FF0010A9C55358CD40DF21D58946C792641191E58D811B1D6993661368998003C316F4D6273415E990423918D4532B294EED8065DF6F0C849513C465242789A2828720437464B553C7AE4087263255A002B4E9910376CB454520E3D69ED864DD0536219C0EA3C7289736F082BB1C50D3AF8E63C98C986DE4AC3950EE0E087368EAC3758BA99281493F2CBD125897130B346FDA66A11938B4C9111C92B15A6FEC32C0E396596B6D298D0AA924F51896B45C92C36A959402E3AAF7C8B6458E5FF99A0A18E21E9F0AF3AED8B7C5875C7984090BF30057662716F8A79A379A8C328726A95EBDB2052433C9FCC16DA94694515EE46458F0B514913505413E0315E14EED0C408E5F0FCF6C53C29D2CD1A2715229D46F97E33B302AD6F78A1BA81F4E4F89AA70B09B5AEA9CAE91030658C153FECB327149D36AF13F22FF00E7387C9B168FE686F3446800BE6259C0DAA6BDF3618E4F37A8C745F9A7786B7136D4F8B3638DD7C85256E09ED9787167CD408A66445A9665A1BA2FECC3FE7177FF00599FFE71DBFF00358F947FEE8D6996B813FA8FBDEEB8B1762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF884B33D37AE62B909B337C24788C2150E57E1396854A665FDE0C4AA4F29A4D5F7C802828E0F545DFC36C24A02E97EDB53C33132072B13EABFF009C5AD5E3B7F345BC6ED40411BF8D735F986CED34BCDFA88F12B6A36578375E20D730A4EF74FCD11E719DCE8F2CD16E6BC49CA64EE317278326AB710C14E5BF2E998F26526317AF79AA5F3210480A29918F36A1CD97683E45BBB86599E33C4D0D48C9B27A641E5FB0D360637340C47C18AB1BBFB6B494B7A43A74C550FA4A869DA222841A0CB60E3E6667058D09A8EBBE4DA503358061257F9B154A27D257D36FE98AA4034E546229DFAE2A9D5B5B22815C5536854290A3A0A62A9E47D302A2524A151E191EAC4A670CC7EFC90649847374CB1B022D26AE4D984E6396A06FB5316F098C6D5A64109A44C2A32B294D216A50D76AE4648298FAAA76C890805BE55CAC86D896F9656439112E26A322DD12A65C0EFF003C8C9C9C6D7D657A65126F086BA9818CF8E63C98C983EA32F10EC3C7A6087368EAC1AF2F19A4A7865E8936B7C562A1DF261A648ED37518849CA4DA996071E48ED7BF31F4AF2D69F25D4AEA0A834AFB62583E6AD6FF00E7226C2732CF030660C40A1FECC8B38A3BCB7E7A8FCCF6F73717527A224A7A5BD2B8B7C53237D1CC5E2AF348F7AE2DF1627A87E63C76529B0869198F6A0EF902D8032DF2B79D6FEEDC0E478B7BE4534F6FD0F5096499096DCE2B4F4225E5E1F175C5691261936A4DC76E95C9034D13E6EF425FF968FC71E26C10B08CB698D9D02B739240791AE64E29381AAC3B3E3CFF009CDAD163D5FF002CA3BF02B25A30634EBB54E6C71CDE57578F77E2BCF2195DE43FB44FE1B66DB0F27479051428EA3E79921C39A1E41B9F9E6445A90A577CB83745FD98FF00CE2EFF00EB337FCE3B7FE6B1F28FFDD1AD32C7027F51F7BDD7162EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF87DB371502A2B98B4DF69C13D01C90554E3B7D19312094A275F8FF005609482B1EB8DA6F964225055E3625900049F0C9A014D110167327C238EC4FCB31F240B938E41EA3F935A8FE8AF31DB4AB2846332802BD413D7303340D3B3D2C85BF5FF4FBEFAC6876376AC1C7A43E319AF90A77DA722D34B906FF00CB573DDC3120663C8BB9C4367CFB35ACCF70B0202CDCF751D466392999A7A8E81E5AB7F53D69286408A48F0C62D319025EA16D3456B0085221D280E499DA4B7BA7C9A99268691EF418DA5E5DE60BA83439191E550D5FB24EF82D52DD0754FAE6A30B28E20FE396C0868CA1EC8564540C632011B31193B684ADC1624914DF738ADA94F1A985A8C09A614816C6CDB92C4D3BE282295046CBD01C55150EC77FC7154F22208EB8AAB2005AB9162533840A75C21923E351B64DB0146C69B64EC3208A89CF2A5698DB784EA17D86F90B54D616AD28722529AC6F414272242AA2CC01153898B0E0368F4DC546FF002C818B6C415F46F7CACC4B9116B953A9A7CF20634D91284B89000486195483978C84A4DC7C62AD4F7CA241C805B966AA1DFB65120C64C33569F843235413D86463CDA3917973DEF2BA615AEFD32FB6264159AF9A12ECC85815D864E2D5229249E6048924DC230AD01EB9686821F337E6C6A3ADEBF6F1D8D8A4A07A8DCD97B838086145E59E5AFCABD62E21ADDBBAF26E546FA0F8E459C43E91F2CF96E2D234B68AE18C92C207A2ABB9F7C69BA3B2AEA725EDB594AF65138918100537C5B8178FE9DE5BD66FF547BABE57ABBD547B64241B4483E92F2CE8A6CE18A886A06E70527883D934189F9AB73E86871A5E20F4069278F8904D3C7052F105C6ED89AB392DED80DB44B9B5F5BFF29B23BB91090554BE113C4C5AAA55AB5EDF3CC9C4D3A88D8D9E47F9E9A41F30FE5579801AC92C51B32C23AD02935A66C71BCAEB31905F8377711867B8848A18A46047FB239BAC3F4BCCE7152418076DBBE65C5C19858EBB9DB2F8B4A1580CB04806E8BFB2CFF9C5EFFD667FF9C76FFCD63E51FF00BA35A65A393813FA8FBDEE9858BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF874B265328CA593246507853C72259C513C07139596D0935D28562721D5279311BC929375CBA1C9A24BE0B90268E872F8F26013B9650F1EE72126FC68DD12FDAC351B5B98DB8B472015F6CC2CE36761A73BBF5CBF267CCA9AFF966D6D24903148C0A66AB287A1D2C9EF3A5AA3C9FA30AF10FBD735D91E8714B6615AEF96C695E6084C43E0998548F7CA29A739B7B3E89E598CC6B3247EA19D0034DE996403878B9B2EFF095959C5F5ABB70AA054A9C910E482F39F3AF9B340D26C192C028B85560E57B900D32B21982F8EB53D425F345F4CD2A91463C09F9E565B014C740B2D46CEEC39AF18D870F964E0C66FA4B4DB8379651ACB27C400D8E5B17166956A21E262886AA456B9634F54B2332383B6581C8835E9301B8DF0144D690475C0C694FF6CE2B48F85C01F2C569188D520D698AD2650B50628A4D633D314D23636DBE58A8B6D1C73A62E60E49A44FD37EF8A53BB6906D8AA64241B6298F36CB0241CB9C9149B5ACC1471AD2BB656BB2600823AE40ADA1A7038B37865534DA493C828731CB740A4B3C94AD3AE51272E054DAE1BD322BDB2892C8B17BEFDE73E7D32B71E658826968D7264A7535C21A2D327D2BD40401D475CC88AA42FE528A69099146F99015747E43B157E7243EA03D0787E38C92194DAF9574C8900FAA8DBDB20C9CFE5AD3CCA812D40F1DB154F57C91A75C45536C3953C3FB714A4375F9736C2559628F804EBFE75C8948445AF97520223A74C0A9FDBE962CF7036AD4E2A9DA32BC746C550727A49B03912CFA2025B845DAA3DB20D40EE827B9574702868466463E4E55EC93F9C6E3D6F27F986253F11B4947FC21CD962745AE2377E0879810C7ADEAA87AACEFFF001239B6C3C9E3B55F594A17F8E67637026B24077FD796171D02EBBE5526E0FECABFE717BFF599FF00E71DBFF358F947FEE8D6999D0FA47B9D7E4FA8FBDEE99260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF861D3DE432034DBC72964CB565278537DF2259C51C6600152C2BE19516D093DDB13CBDF23D5279308D403ACA3623C32E8726892193D65742548F039911E4C03258F9B415E276CAE4DF8D49039755A94A1AD7E5989945873B0BEE7FF9C71F39AD95CC3652DE0EC3893F3CD7658BBAD34E8BF49F4D9C4C12F512944AAC9E39AEC90779872A6B75045AA442EA420CF17D95EFB653C2CF24AD9FF94B596B3B6953D1FAC49C6853BA8F1C9014D111458679F7CD173E94886630F20691FDF890DC0BE62BB6B9D42E984E8E6366F858F7A9C810CC1645A779360216644E04EF9510CC1640DA298978C49CDA9BD30C42C98F1D46F6C2F56DDB946A4F4CB22E3CDE84B492C83BB0666DF2D69EA81876276DB261C88372321620900D3A602C8A0E414DFB604521F73B8FBF15A5652C3A0C5691F1F2A2FEBC56933849A5295C569348C9D85715A46AB506FF004E290162960DD3E9C5BC724C627A002B4F1C529DDB38DA8698AA6AA4F615C5239ABA1EE72E6DB541280CA396F5DB2056D324B903E127E2CAD6D7CF23189FC29D72A9A82C7AE255E81B7F0CC72DF0293DC39505A9D3289B95028069DE9D0D3C7289A494AAE999D08A6F5DF2B699157B5B55600D37C21A93AB6B3ABD38D76DF3222AAB3D8AEC547CF3202A360B3429B10580F881C64C8223EAE9F6792FCB20C913069A240EC08057ECE2AEE735BBF02E062A8EE64C4C18862DD32254242E8166AB0A6F812A978C161AFE38AA412DD98E062AD52062AC4DB54B862C0D46E72126CE88492FE43B16A6443472288B5B8E714A7957A664636F32F4A035894C9A16BEA4D57EAD257FE04E6CB13A0D74DF86DE6D503CCFAE85DC0B96A7DE736D8793C9EA0DC98F053E199D8DC19B9CAD3AEF96171D06E2A76CAA4DC1FD92FF00CE2FFF00EB347FCE3BFF00E6B2F297FDD1AD333A1F48F73AFC9F51F7BDCF24C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85DD35C96DF2964CB6023E1F9E44B20BA47FDE1DFBE5526E081BC7A2935E8323D527930FD45CB4887BE5D0E4D1253673CE1073223C9806516854C237CAE4DF8D12618E343336FDB31E4E66366BE45D767D175482E623455606BF7E61E58BB1C137EB17E5579EA1D734AB485E60D23280457E7EF9ADC917738723DF2D678ECAE638E75062946C7B6F94F0B9B1DD1535D496978CF6BF0C53281B63C283B21750D223D6007B800D7C7224282803E4ED387A4428AAE4086C05192E8F15BC5C621B814C810CC1632F697AB3858A22EA7A90322366576C7353F2BDE5CDCA4E632287241A26C820B0921B658DF7232D691CD4A5B431C6C476C9872209210DC8961BE02D94A72313B605E15200814C5695D6BBE2B48D4278A8F6C578531B76E9B62BC29B420938AD261E9B1FA714D2F119FA462D815D63DE98A53680D0818AA6F149414EB8AAE6980D89CB99F12D5605948EC6B5CACAF12A7D6292EE77C815E245CD755888F11954D416352CE7D43ED98E5BA086B89B92F1F1CA66E5C4A5D24C146E731E4A4A57713165F8776AE56D5229B69DCDA95C218B2AB5421AA4F514CC88AA37EAE5F71D33202A8C917A2373C6BB63264103FBB06A64A78E4192610DD451A37192BE3BE2A96DC319E4E4B21A0C551714AF1B202D514C894847CBE93A87D8918158F6AB72681074A74C55894D73C636538AB16B9999559972326D1F4A4C2EE477A1AD322E393BA716F70638580EAC4664636523B286BB2341E5FD79D8F10D6B21DFFD439B1C4F39AF93F11BCC8E24F30EB0E0D435C3107E939B5C3C9E6729B293667637126A2CB5AE5A5C7502BBE5526E0FEC8BFE7183FF0059A7FE71E3FF00359794BFEE8D6999D0FA47B9D7E4FA8FBDEE79260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85EB109D5771E394B24EE19497451D3950E44B208D724C840F1CAA4DC1037B50A4378647AA4F263B7B18AC6C72E872689206EC51A2653D32F8F26B08F82E48A440FEF295E39093918D3FB23F595759AA225EA7FCAED94172E299412FD5A2223FB75F8328C9172B1CA9F48FE507E663685756D0DE5D985C90B1A13B577F7CD7648D3B4C3983F4F342F325A6BDA35B5C3DC235D7006300824FE398C767698B202C860D46692358E54A18B704E0B05BA62D35B6BD77DBA0C890C63128A79D8107964086D102AC932B00246DBB9C898ADD2296EE2B643E8C425E5BB31ED95914CE3BA167D4A2991B946108F6C431940B13BCBC049111AD32624D3E19B4ABEB13382AC2993130DD114974E3892186F8DDB6092041DCD46D8AF12E6EA4D36F1C57897091456A715E2565993615C578C2656CEA69EF8AF104EEDA4407738A6C27B132151BE295540189A62CD1023351B7D38AA24232D0914C55148DD29D31559373AEC32DB544DB9A0F8BE9C812869C7C7C874F1CAC94B6F229000395CCDA84AA68DB996A6DDCE63B7C36414CE95A577CA66E540A45792D09DEA331E6C88B41C2FCE4006E7C32B6B9448DD9259C81283A64C45AF8939FAD3715E0475DF2E0BC4135B7BD2A9566CBC49788295C6A1137DA3CA9D4612CE26D8F5F6A9044A5AAAB4DF761FD723C2CE982EA5E7AB3B105566524D796E36FC71E15A63C9F9AB6B1D47A8A5BE63FAE34B4A4DF9AE92238128592BFBB507AFE39190544695F99324B308EE25A027615FEDC8D26DE956DA8C1A8C0662D56E831A5B63BA93FC7C23A927B531A543456723C3FBD4A313F86464D8262A90ADA70462426F91693024ECB5ADCAA0929448D8733E19763906194F0879FFE736BA343F26EA571EA7A69776AE96EDFCCC54803EFCD86298797D76404BF1AE617524D2CB74BC6791D9A415AFED1CDBE290AD9D1CE24EEA7C18F419990C81C498A5AE8C06E2872EE305C7A52E058ECB5CACEEDC1FD8DFF00CE308A7FCE35FF00CE3C8F0FCB3F290FFB935AE67C3E91EE75D93EA3EF7B964983B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BD3BEC652C938B6FEF53FD6C89641399500ABE5526E090DF3B32B11D40C8F549E4C7AFDE4E31FE397439344905217668C78E644793584C2C406BA27F9475CAE4E4637A6796B49FAFD95DBA0E455AB94D5B951E4C7EF266B5BC6B775A50D304A2CC4D7C26EBD7496194C7E97C48D5EF985931B918B23EA0FCA5FCDFD5B48BEB6B6D4EF19AD9481F131A537F139833C4EDB06601FA51E59F3FF9775DB2B764950C8CA3910457F5E53C1C2EC6192DE8D0C7672422789AA08AED91B72E050F34C84A88C74FB59025BC6ED2C8DF3F0C899354A289496A8CBD2BDB21236CF0C50922D011E390A6E314BA4B22416A634D44255246633BF638D3021033905B7F0E996C5ACA0682B5C92AC734247E18AA8337BFCF1572B74FD78B594CEDA6A0A62D914EADE652462CC325B6605462D89B4282A3BD71668EE031558ED8AB68DD3C3155772A77C9AD2989950100E56534A46707A9C84969A1254D474CA8A40DD648F5539516D8A4B350354E5126F821258048390DC0CA26DF14B638945C71E5C4D3AE463CD728B8A6358E05E4641B75DF2C70F850ADAC5B16E0660BC4D6B5C9C53C0D4FE71D2ACA2224B95A8F7FEDCB578581EB3F9B1A3DAC4FC640C4D42D3C7EFC945B2029F38F9ABF379DE597D19DD63A9E95FEB926C7906A1F99CD71EA52E9AABD4127FAE2AC557F301DE46ADD356BE3FDB8AA656BE75BD915E4B79CB2A1A36FDFEFC8C9059D7947CED24B7F18BB6661C803D7FAE455F61F973CE960B68891EE0EED5F1C559347E6182E6752B106A9C55939B95940658F8823A64486A3CD0CEF5AFC19590E4C64A2FE9B2FA4C2866EDF2C9C22E0EAA5B3E40FF9CA7F308B7D046911BFC71A9F86BF3CCEC71793D61DDF9A864E681D8FC4D527375861E975929521B91AEDE399020E26492E33A13C5B7236CB40A68B4D2CE28A4EAB9600DA0BFB03FF009C6A017FE71CBF2000E83F2DFCAA07FDC22D73363C83AFC9F51F7BDB324C1D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85CD3C715A1EB94B24E228DC303B75A8C896514F44323C058D3EFCA8B70499EDCB24B5A647AA4F2492F638CAAFF91F6B2E87268925A5E07F8D2B48F63F4E6447935854B3E4B73327ED15247DD95C9C8C6FA0BF26AC66D5D2F6D22512486A287A6541C8E8C6FCFDA1A586A5710950B75093EA0ED936B32A79F192E1220A4D2A39291954A1698CD562D4A485158BB2C8A762329389CFC59DEF9E40FCD2BDD0960334F2B46E42F52694FA7313538A83B3D36A1F767917F3C6C350B782092EC06A00431A78660183B5C595F44693E60D3F558D7D39939103BF8E53214E7C260B295B66E21832303D286B94CB666775DE8488EA781A1F6C31DD944D35246EC6A23603B922992A64648A11A98B8820B569418D06B24062FABC2D683D4996887A531A6B25884B751B92C84D0F8E16050F57FB5514C285BEA57BEF8AA9B9F7F962AEE42837C5ACA2612716C8A3A17756152298B30CB2CE71C455B16C64115C28A55A9418B3470B943D0E2AE3206E877C55B57A0F7C5548CFC07C677C9B6D20649CB37C26801CACAAAC659B71D32125562DC76AEE72A2AB7983515DF2A2CA2955F3D15941F88D29944B937C1A8A4021F8CEF4CA26DF1631A9DD7A3C9D1A86B4C8C39B29724A9EEE49E3203354E58D54C4758B3D4562F5226DCB5363BE4E2B4C2A5D0754BE722494F1EF56396AD05A7C8B6654FD61CBB1EC7A64A2B4935E7E5C79767564907C4C3C324AC0F51FC93D2262CF6E7883526BB62A935B7E45D8FA9B9A927AE2ACCB4AFC83B510CCFEA705E42A323241677A0FE53E83A5C81A62A597C722AF51B0F2BE90CEA96BB1514A2F4C55153583E99708A895DF638AB2386FDFD3459051FC3034CB9A2D6E19876C8F0AF1D34D342CF1CA4F1FAA2B35D7CBAED9918A3BB81AAC9B3F327FE7257CD967AF79AEF2D74D9DA48E0E4AEAFB6E2BD33638F1BCDEA4D97C82C5D763D3B66E30C7D2EA66511000C4572DE4E24CA356D6126BFB44EF86D880C92C2CE20061E26F8C5FD757FCE3780BFF0038EFF90AA3A2FE5D79580FA349B5CCE87D21D764FA8FBDED19260EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85BB6F848AE52C9904352B5F0C896514D3D7E36C77CA8B704AE3943AC9BEF91EA93C921BBFB2FF004E5D0E4D124854D2198FF94BFAF2F8F2601358471B966F18FF0086424DF8DF5BFF00CE24D8A6A7E63B9B6715564634F7198F234E544585BF9F9E5A934FD775396342055B7FBB1136B9C1F3100C614E4370B96036D06C20E54F8078D72756DB09334D247FA1C629B9EF9467C761CCC597853D827BFD3254B8B6BE642A6A141CC09E27698350F58F2A7E73EBFA4DC470CF3B988951CABE14CC49E276F872BECDF23FE7858DD476EB3DD8694815527E5ED9893839A26FA16D3F306DEFE28A55911380A28AF5FC32318A99D2723CCC6F10233A229FDAC970A0E54AEEB5C834C9030BD578C8E4C6BDF1E16A395E4DE74FCD485A64B586753DB63FD98F0B039103A66BAD7D124BCEBCBC30726C89B4F45EB1A2F2DCE2CD1092357AE2A88F888EB8AA834850D3C31605562B923BE2CE2895B86AD6BD716613AB4BB7000AF5C5B03238AF8FC3BEF4C59A651DD934DFAE2A9925C57BE2A89593E1FA314C79A065763BD726DF4A22BD7E9CACAF0AAACC13BE424BC2E6B8AFC43B6545045209AFB8BF5CA8AC50571741DAA4F5CA64DF04BE7D43802AA731E6DF148E59BD77A3FD9AD4E461CD390D04F6CCD998C291BD32C71B8D4EE6D2240640BCD5B6E3FC72617898FB58A732E4045EF962F1A51A8CB688AA88FF001D77C9C59C656C3A7748E4E6D27C35AE49938EB9A728547DC8C55522D734F520C7154FCB154C63F30B49F0C44411FED29DAB91920A5375AAF2B9553217A9ED9157A77945B99568C1E05A8D5F1C559B798AC80B713AA0E406F8ABCDE3D44F221CD181A53080E3CCA6D1EA238F5C20346495060DF999E7087CAFE5C17AB2859EED1C15AEFD08CCCC31757A89D87E54F99EE6EB5CF30EA3A93312B2B311F4939B5C50D9D266365881B52546D999195075F38DABDB5A9EC3194DA2504F60B08D8AF8F7CACE4651C4CBAC3490C071E9E190395CA8627F58BFF38EE9E9FF00CE3F7E45C7FEFBFCBDF2C2FDDA55B0CDCE23708FB83A3CC2B24BDE5EC59635BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85884F361C76CAF8536C96DC111904D6A301816424D4A58C5C075A65462CC6441C41E1560CA5C9E80654765394525D76A423B31095ECD96E336D12CA18F05E69242AC0B484107B6C733230348134E0FC0EA6849910814F964278C86F84DF60FF00CE1AFA8BE6C997890CB5427B6F98594539D8657B3DBBFE720B44F56E352AA8320526BF40CC7E2A679214FCFAD422F413895A713C4E591CAE14F6485D8351286B5CCA84C14464F40D0A20D0C709A127BE3964006F88E264377A544A16AC797E19892C81CEC008418B78D5951D6BE04662642EDF164A099E9E2EED2E565B29CA1435A1398920E58D500F50B0FCCBD6A0F4E192770F0ECBC4ED4F7DB2996CCBF3024CDED7F37358E01259E4E245363FD991B41CAA7A97E61EA7771FA705CCD461B963FD98DB0F1187DA6A375A8DFA09E4919F97DAED8DB1337D27E58965B5B3854B971D70F0DB958A7419A457ACD2AB576F0C781B78D90C37CB51F153E79122990926B15CABAECE3E9C090B6491493DCF8E282143D555F1F962C86C8859EB4A57DB1640A696D24840DF167C4C82094556B5C53E204EA09169DF14F1A3A19949FB58A414DE27523ED8F962C816DD4788A0C9B68CA165630A41EB4D8E40848CA12C9E4E3FB5F3C810CB8D086E9551AB5395485053249E694B3F2076F0CA0C911507B8526B5E998F2986E8EC954D3879295CA8FA999CA229B69D6F1CF22ABF422A708853564D4090A6616FA65804AFC5CA985C7F1107776E2353E99A8EC3240AF88C3AFC4EA181A508E8327C6BE2306BCB3672F20635EA41CB319B6DC79186DFC7292CA49A65DC2DBE284858411732558B1E95C7857C5097FE9178643C5453DF1E14F8A11BF5DFAF71E6CD13A0A2F1E87E795CC5309660CAF42B41EAA34BFBDDF6AE52649196DEDBA3AC91C6A21554A374C1E2065C69DEB17D722C9A3908269D7263763E2878E3CB28B89030DEB52C3A53261C7C99022CDF47042D34AFC238FED13964604B87972BE3AFCEAF345C799357B8D2F4F98FD4ECA80723B1AD6B4CD861C6EAB3650F99E6B7BA8AF3882BE99D9877CD9E3141D5E49A0EE2DC076006C3265C594952DA2A76CAE450236CA34DB28E591405353D7316526F8637AF68BA242630596BB6527239718BFA78FC884117E47FE4D443611F91BCBAA07B0D32DC674FA7FEEE3EE1F73CBEA3FBD97BCFDEF56CB9A5D8ABB15762AB1FA7D38AA962AEC55D8ABB15762AEC55D8AAA62AEC55D8ABB15762AEC5572F7C55762AFF00FFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF858B4FB432AE36EF0D94C1F6457A77C789061488210F4C89DD81539220637E0C15E9F0B7865660C244524D756F13A52693D47F019761C6E31905B67E5ABED43F756D68EAAFB89E9B0A66C61065198B425DE8B7BA7DD4114CFD036D95640E66220BEC4FF9C378DD7CE37019830E62A335D99D8E10017D63F9B7A7A6A3AB6A7005E47D36DBE8198526DCA6DF997E77B23A6EAD25AB0E2A0D7200D38138B07922A10C33271C9AC459B79526E573E9B7602992CC6C3958B67A75E5A7308CA3A8CC493B0C692359B89375DF28C8E6C792BD9C6E26238E63C925131C00CEC5C5083B644C6D946549998D5694C1C0CB8D1B1395E31815AEF8F02F1BD5FCABE5F49D16764F8BAE3C0BC4F5AD3A16810474D94ED86A9CAC4764E919B983F7E25B814DE201A8CCD4272A93644A690F1029C8E41B0146FAD40003B0C5928B4FEF8A559273F0D4F862A9A5B5DD286B8109DC57CA08DF0B105358F50403ED7CF16C051297B08228F8B3051E9A8A01B3F4E98B3B6CEAC4FED64896622B7F4913DF205988A067BD249F8B204B608A0FEB47725B6CAA6526282B8BC201A1CC599445269AF5FB5731E4DBD17DAFA93480F63928868996716303222B74DB2E1071AF74EA3770295230F84B6A53B32AF23BD71F097898EDED5C1F871F096D8D4F0121885EBD72CC71A6C81B63B77A6990310BB9AE5CDAC12FF4AB80CDC50D0F4C558EC9A3DE3BEC877F6C551B65A2DE8956B1B52BB653910636F54D134C962319910E6290D9183D46C42C7C05295DE980067253D7A655B76DFB665422E34CBC8AE2ED959C0FB3FCD968838939879279F7CD7E8594D630B9591C1008F7AE5F8E0E1E49BE6986D2E66B998CE4C8EC49673EF99D8F675D96492EA9A6709AA13BE65C4B8336373E9D234AD45EF84968E04759E8D2B015427299C9B61167BA2E84EAF1931F5CC6939110F67D1F4BE318F87B65326F8BFA35FC955E1F937F94A9FCBE4CD047DDA7419D5E9BFBA87B87DCF29A9FEF67EF3F7BD372E69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF855B670AC2A330CB984B2785D5A23C4EE46C300938D3C8037146EC0D640A57B1EA73271C6DC59E7013FD17CBB7FAEB98A106353D588EB9991D3B85A8D50112F59D1BF2CACE1557BF01993724E5F8F03A39768B3EB2B0D26C08B45317A454D401F16C3C732BC3D971F68BE7EFCC1D3E117D1DCDBB5631C8041D7BE60E78D3B9D2EB789F437FCE1B5928F37DC48C4A6FCAADEDDB35595DFE973F117D6DE76B8853CCBA848F19742AC38FDD98530EC4EEFCF4FCE7D0AE26D50DF5BC263889E5D3AF4DB292D5283C3230655657431B275AF7CB612A6A31A651E578C9BE1C5A94A65933619E30F7148792460EFB653273F1AF4B1ABB029C89E87C3289B9B16EDB4CFF004A3F0F5F6CC7924A3C6845A6E741D7A530C5814DA3F2DB4D4A2D3DE99246E9B59F955DAE230141A7B62BBBD7748D35ACA255DABE00615B2C9238C83C9969ED95973709D912B1FC4081F31912E48298C7C788D8E552660A2D08A743EF90660AA7A95D80E9D31656EE05BF6A98A6D772A7C35E9B62B6898A4E3D4D7145A244DDF9D315B442DD11D1B1640A3E1B84A8AB6F8B65A6D1DC42109A9E98B3077524BA534DFE5809724144FAE0A9A1A6DB6449660A02595BFDF832A25B0150FAD71DB9572B994CCEC8692E958D28731A4D112BE38BD42083D7B656D97B325D36D5415240F965D8E2D332CC15408C00287C732E107189B2B7E207ED5465BC010A95E638B0AE3C0150B2DB07E8B8F00543A699CF9D453C32328D3762431D138B54D18785320DE8693CBF0CE45502D3C7156E2F295B83560A47CB154CE0F2E598707D351C4F865536704CA6D16085032D001945365A47724C33A90A7805EA3C7271834E4C94C63CC5A8C0B6EDC9E840DF3371E375B9333C3755D61A4574B67F1ABE640C4E064CFBBC875ED367D4A61297F881DC9C988538F3C96A56DA488630CD1737237232D8871A52B492FF00449A798BAC3B78658254D2425FFE1E666DE2A1F9644CD90C6C86C3CBDC40AC5DBC321C4D831B38D3F468D387EEF7A6F9592D822CEAD2C5234038819596603F7D7F27871FCA4FCAD5F0F286883FE9C21CEAB4FF00DD47DC3EE792D4FF007B3F79FBDE8D9734BB15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF84F5A9238F5CAA50699EA135805C2D19413C7A0F1CA841D7E5D4BD77C9FE4C9F5955BAB9531A36FB8A7F0CDAE9B15BABCBABA7B25BC363E568B8428AD2D3E13B75CDC474FE975F9B54642929D43CD1733551578D7C3251C4EA660B1C79EEA4E530908600D30CE1B231715A437D65F5A82269F76DFAE6A75317A5D04097D2BFF38A5603FC513C69B50F519A5C8F59A4818BDF3F32C8B6D7EE550D4EF503E8CC4C8EDA06DE35E6CD274ED634C8E1745F5C2F2DC6FDB31645BC45F0F79C3499F4CD4E482088842DD40C6326A9C55BCB703DBDDC25B66722B97036C22FA334EB45963889EE06093998D91DB69F1FA87E1AE5191CD8F245DB5845F5ADD46512E6929EC1A746D253877F0C8DD2631B66365A3C2101283071B2E0641A7E9B6AB2F22A0536C7897813496D944AA517E11D71E35E0463C28C415E94186DB63B2E580602DA0AA88B88F6F0CAA4DA0B74A641902A65A84D3164D09A9D7155F50686BD77C55DCC0DB90C554DA6A54F2C516A26EE9D1B16C06D552F883F6B0330518BA937F37E3859834AE97F4FDACAC96C1345AEA15523976C812CC4D4DAF474E5BE544B671A88B82CD4E5D72124CA7B2AAB0E42A7BE504B18B23B331FC3B8C039B6B27B39A35A6F9978A2D190A73F5D8F8D2BBF6CCBAA71495CB728DB636BC4ACB301B8F9636BC498DB3ABF518DAF126255154103AE4265C8C25AA467ED0CADC97048491B0C5556910EE31550692256A823DF2B9ADD216EEF23E34AE5643194D846AFA82420B33058E952C72EC637703365781F99FCDF662678397A8A4D0919B2C7074D9B3BCEE7D5EC0C9584D10EFF004E6588389E2DAFB7F4AF4811906B80C11C68897479C39A3D01E8BE19514A9FE8B71F69B204A695974DA007803EF4CA8C9CA84764C6DED78EDC0636CF85905B45180BF08069BE368213650028A0FA3157EEEFE50FFE4A6FCAFF00FC04B44FFA80873A8D3FF771F70FB9E4753FDECFFAC7EF7A265CD0EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD0FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF85F8ECA6827585979C84FD919084FC474B9674F6CF29F906F35036D773218A18D833A95FB437DB719B1C3A1E274FA8D43DA2E0C763686D6D2216DC06CE3BE6D30E8F81D5CF2F11610F34D76CEB212EC8767CCC3300535006ED2AB986E56455F4CB03FB54CC7F1699CB7539675B32AB335030DEBB532B9E76EC1877633ABEBD05BC4817E3095DEBE39AFCDEA7A8D0E301F49FFCE3379B34BD275C3753CAABF58466DC81C4F875CD5E6C342DE931914F72F3ADEC17BACC9A94171F5A4B9DFD21FB35CD7CE36E44254F2DD5E40F74AC253188D3E28FDB31A78CB951C8F3BD4BCA69E67B826C23334CBD471FEC395F0D322049E6DA8F93752D03518E4BC89E28D5BEC95207DF4C2254C6389EA9A33F3B58E48979851B8C4CDC884699569EEACE6BD5FF000CA652722324EBD158255940E61BB6545927D6AB1D43EDBEE47865728DB644D32A8A7884600F0C1C0CC4ADAFAC952283BE3C0DD18DB27B39964B73CA3DE9F6B1E06C186DD1A90A6A77A9C9C62D528515707AED84848D950380A2A37CAA41902A4CC7B0FA3214CC490EC549353438190921A42AB53CB14F1297390814AD3B62B6A2C66F7EB8ADA8BCAE2B5E98AD201E46AFDBA62C97FAE07FBB2A7BE2CB89DF5C03ABD0F8E02CB8DB5BFE34F8ABF4E506569051B1DF7203E2C896C89561755FDBC8D3305556E7810FCAB4ED8382D24A252ECBB57A7D39138523252716B7C626525B901DB11869978CC9ACEFD64A7C5C72F87A5AE53B4DE394935E5B53AE5BC77B35108B8EE82903957DF229114CEDEE62E5566E43C3DF1663127705DC0A2B8B3181305D460208A74F7C05B618F854A4BF87C46001B2D06DA8C6BBF2FA3088ADA1A4D622029CFF001C9702DA17F4AC4C681BE23D05729CB1A5AB405CDD731BBF0F01918C2DC7C9B3C4BF35FCCF268FA60B6B78DEE2F27158E34AF434DEA332F1E3751A8C8AFF00959F947A8F9D3433AAEA90B5BFAA2A3983B75F119B1C717499A565BD67FE71E6F9B549EC74CD4B9F04E6005EE7B74CCC842C38E254C2A7FCA7F39795E57730C9731C7D5829FE991941B23240C3785A76B4BD06DEE22DA507B6634E0E4455269E35902A2FAA9DE40731CC5B8056F5410027D9FD939518B9319505E8CE36AE222C84938B13CC8A8E9D708091BA7885760570A781FBABF947FF0092A3F2C7FF00013D17FEA061CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8797343B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD1FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8D2F23F91A57BA4BFD6D6BC0D68D99B874D4F199B556F6FBFF00315959471D8E9F1AA0A7024019B9C18F85D466CD6C59E49EF25615E4332A52A0D50DCB2DF2D6856B70C52551CE43DF31324DCEC38B88D3D353C81A7CB0F32AB551E03FA663193B0FCA3E7DFCCDF2B2E9FEABC7B2C7E1F4E53293938B4F4F9C6F56297D485DF7198E64EDB4F0E146E83AFDC797196E2DE46AA9A00091D7E9CC6CDB876719D3DDBCB3F9BD24F2C31DE0DA94AB1FEA7308C1B0667B4D94D69ACB0BD12208D97E3151D3289636F8657A07911B4F7D723B3D2E146909A39DB7CC738DBE395EB1F997F96F6BAE687305B355D42DA332D55454D47B0C8F03938A76F86AD6E6EFCB17173A65F42C9F1955E429DF0183920B2BB7BC4616F2C5B16DDC65660CC165F14EB3463B9032071B30532B566E2C3B83B65538D1499526D019BBD6990E16719A6917C5DBA63C2DF19A6D6F7CB1008C7E8C785BE395344BA420107AE061396E881329C892A0DAD663C8D0ED9592CC054571DF2BB6C017F2B7FDA1BF7C2A8599ADE876DBBE2A82372A361D3A0C5541AE7155295D4AD477C52934EC6BB6D8AA0C87F138AA8307DB7380A43AAD502BB7865062DA0A3E1269D7A60A6C0510A5BF98E34D80ABA3316515F98C69369846687AE16B4C2075322A96D8F7C55328A7F498156AD31564767AA23108EDDB08544B5EC55DA4FC724C81444378A5A9EA7BF5C2CC14C92F401F6F6F9E06C1277E9458EB593AEC37C84CB6715A849AC27412F4F7C8829421D6A25AF292BE1BE580AA026D6226DC3FE39602A841AA52B2C64B329A0032AC82DC5CF9B81E8FA0797EFF00CC36DF582AC8AA3AD30C62E064D45B23D2FF002E746D666FABEB1682EAEE27FDDB915A27874CCCC61C0CB2B7BEC5E5C8B43F2FBD969AA96E889B050053F01997034E0CE16C3BC93A446D35E6A37975CAECB32853E03A665C25B38C63BA6F3C3CEDB526BEB5496201B83151EFED82526710F942FF00F2B62F34EABAAEA1631FA2F393450294A57DB31E45C8807897983488FC97713E9FA8CA1A624844277CA0B7C52BB760F0C4E05030A819590C81A45AF5C14CC14D74F6F888F0C7859829D237C58D3305FBB9F945FF0092A3F2C3FF00012D17FEA021CE9F4FFDDC7DC3EE78DD57F7D3FEB1FBDE8796B43B15762AEC5563F4FA71552C55D8ABB15762AEC55D8ABB1554C55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD2FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF911B5D4CA4450905BBAE74F1C603E6D3B48AE67FACCEA900FDE16A6D9682038A626D9EF97B49957795D99CFEC9195CE6E660C6F47B1B58EC87AAF540BB961D4661CE4EE74B87D4191C5AFAAC65616692836E5B65066EFC600F1FF3E4D71AB45708F1045607E21F4E5329B64703E3BD62C6EECB539792FEE8B1F88FCF31CCDB04292D9AE9C158E18C484915AE57C56C8DA31A49596358E416F21EA54E44840059C68FE69D574B44824D51BD24151F16E7D8E63C837C6DEEDF96BF9A30697AC437F733A5B98C8A9E5D7E798F272216FBDBC9DF9E9E4FD7AF7EAF7B7111F56309212474C003978362F14FCFAD33C9F3EA31DFE8572B34929E46314A54D7C301736DE23636377C39471820F5F6C8101B0499559B2DBA8F59E847619590CC14FAC751B37996105CB374DB6CA671B613932D59618940988453D0F7C8F0A04D136CD6F2352390BA9FDA1BEFE18385B064A593E9D74D30689498C9DD8E3C2CC66461E76A80354A81BB65538EE9F15B87528DDB846416F0272B316C8E54DE3BC454025A06EF4CACC5C98E45296FE05DD4B37B5321C0DE24BA2BC570095007BF5C8B0326E59EDE9BB004E28B4B5E48F7A1A8C56D41A44DF7C56D45A4DB167C482797AEC315E24135C76A62BC4A06E0D7A75C4A89287AB43D72921B414545734A53E9C785B01B45ADC8F1C785982AE2E42D0D7A74C14C89D95D2EEA2B5DF035DAAADD92C17953DF15B4CE0BB006EDCBDF15B44BCE78F247A3FB6109050E2EEE01FB44FD392664A69697B329A93DB147123FF4A3014240FA71533A434FA846D148EF394310AA81DF018DB28654A6E3518B9DBAC324B2198D1CD3A60106CF142A299A4BC92D622F2040086237DF2622BE28651A77947CC5A9C4F35BD83945E8C4102996082F881EB3E4EFCA9BD9D44FA8388EA7918FE5898BAAD7E4DDF4559E9967A26872A40024C828A0EC09C9083AFE3280F24DBDEACF7535F5BA2C8EC5A075DFE1DE997C4522ED966AD33DA5A4934D2963312A213D299785E152D23CBF696D62D3ABB191FF007A2BDCB76CB449A670DD4BCD4C2CF402DC4249715529F3DAB80C944698D7953405B5B06BB9A61140D1C923CDFB5D2BD32B25980FCBFF003D4B379FFF003D6EF4486FCC7A769D39ACAA7ED509EB9021982FA1F54FC9D96DF4DB7BFD27525BB9258C39B52C28BB0D85322907778AEA52AE8F70D677C443780D046761F7E2C814CEC599516534A30AEDD30365A6515E425FE26A7B61676FDE9FCA021BF297F2B997756F28E8841F63610E74783FBB8FB87DCF21A9FEF67FD63F7BD172D68762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFD3FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8EF578F9B5C06FDDBF4CE9B8DE267A6651E54D1967BAFADC9BA72AAE552C8E29C1BBD62DE25826E4AB45AE56656E6E0C28FB8B9068427241F697C72B9F276F871F0EE94C97B4256184257314C9D96395B10D522BB9CC8D23058687965129399116F07F30E857BACDF35B58446572D4F8728949651A4E34BFC8DF335FC6918B3912693756A76FBF2B126118D966FA67FCE2079E3569D2425E28DBA7F9F2C4C9C918596BFF00CE13F9AA29D1E5BD255853896E9FF0D944A4DD0C4CC2CBFE706B5A9E359DB5858C2EECBCFF00E6ECA2526F8E265563FF0038CDA7E8171691DF7994594A8F4F50494E4476EB91126D11E17A95A7E487956EAE62177E6E597881D6407F8E032660A7179F957E4CD35D2DE1F32C444A28C798DA995993602A69F929E539E932F9A6293BF0120C812D82491F987F2C348D2EDBEB1A7EAA048836F886E7EFC46ED3964C33FE55FF009A2FECCDDDAAFD7517A01BFF001C970B57131F6D13CF3A6481DB4B6B5B68FED02A454F8E3C28F11136DE77BCB598417D6E4229A31A634BE2338B4D6B48D6A25442179EC6BE380C2D81CD45BBAF28385F5EC65A93B8A1C81C6DF0CC92CBA4EB91A13E9B3D3BE40E37331E54BCCDA9DAB7EF6D0923DB2BF0DCA8CD53F48A85E722346C7ED2F8661CC516CBB516D4ED5BED311F3C82AFFAEC741C5B63D3E58AA8B5E27F362AA2FA82F4AEC3BE2D96817BF5AF5DBBE29B59F5A88FED62B6DFAF19EF8A82A2648EBF6BAE45B42BC6CB4FB5BE1640AB2B8DB7C0D815B92D3AD70164AD1B0A75CA9AD7F2DC50EF8551D0135A5715477A8513956BBD310CA3CD6FD61BAD324CCA9BDF49F663EB8B548A3ED2C750BFA705635F0C5ACC99E795BF2D359D7F538AD591845506507C0FD396E38DB0964A7D476DF933A0D959033C4867812AEC7B6DF3CBBC363E2A47A4F937C9BA5DEDDEABA95DC29145BF027AF1FF006B2C18D7C5629E7CFF009C98F23796F4ABBD13CB56714B76A0A0950577029E1ED93F0D7C57937E5BFE746B779ACC375AC4AD0E9CC4B70EDC6BF2C84E14E3E63C6FAAB53FCD9F25F9AEDA0D1F43981BDA8590AF5AF7ED80069E07B5E83A3AD8E9B6019FD4927456E47B03DB260278588F9D0BDE6AB67A65BF660580C902ACD043E8C3A7C1D2A02B8F96264C4861FF00987FE997DA7E996FD178F35191E2470A335A8DA0F265F5869B66D3EA4B6CCA0815DD908C921F9C3F96FE439FCB3E7ED77CC1E77D224852EE6768DCA6F424FB9C3487D831793349D5EC21D5BCBBADB441E3E6D64ED4E1ED4C348B7E587FCE45F9ADF47F3B0D3667A346FC5A64F6A60E1660A1FCA5F98F1DD086D6693F771A84563DC78E34D80D3DA2CEEF4FBD50F1CC391F7C69982FE81FF26E83F287F2A829A81E4FD0E87DBF47C19D061FEEE3EE0F25A9FEF67EF3F7BD232C69762AEC55D8AAC7E9F4E2AA58ABB15762AEC55D8ABB15762AA98ABB15762AEC55D8ABB155CBDF155D8ABFFFD4FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF8BED12FA6D457F46FA12ADBC7F626A7C47E6736E72BCD5193DAFCA1772C114D67796EF4894FD51E31D5BB72F6C899A63A6B6609AB5DA32C37B6E2DD587C2E452BF2C78DCDC5A4012093CFBA5D95C5C4123AA9B7157693A7EAC13C9B39630D30CD5FF003318397B28A39E2ECD18AFF0CC4326D863A62B73E79D575085C4517A61F6F886DFAB29949CC807D51FF38D7F96B36BF24BE60D7A33C62F8E30BF64F43BEF98F29378C40BEE7D22C74E69E9269D0C76D07C10CB1AD18BF45AFB655C4CBC1E1DD9E8BFB58ED1ED0C421BF857933462881478E266DF8E16F93FCD9F9B3A89F3543E5DD06E92E5E7904370EC6BC2BD48DB2894DCD86114C9FCEFA4EB5E4DF2D0D6EE7CD33CD77749CA3B3864DAA7B5331A536C38E9E45E5CFCBEF30F9C746D43CE7E64D66E20B0B2532DB425E858FB0C89C94C463B64BF967F973179E359223BABDB6D26DEBEBDD31A6CBE06A32072527C17977E75585B796FCC53E81E54B9BBD4A68BE15773C8F2DC640E56DC7A7B286FCAFF002B79ECCC351D62C6F9A0421B801F0F1EB959CAEC31767F13E9997F303F2DADECC68BE67D3A6B4BB20707028DB6C4E1198863A8ECDA28BB3F307935EDBD0F2EEBB25AA1FB2B2BD313A92D3FC9A82D7B509BF41DC2C9AADB5F475256456ABFCB251CE4B4E4ECFE17805ADC68374F7306A7693F224F0940D8E644276EB3361314A5FCB71DB96BED36F0C31F22521734232F0C2386C59661A17994D9010DE5D212BB75C90882931A7AE681AF68FAB442DD6E22172B5E418ED919419C7210C953CBDA4EA2A566A7ADFB253ECE63CB6726398B18D47F2CE695A4789223131AA377A7DF98192365CC86434C1755FCB7B8B552CB1866F0EDFAF2A316CE379BDEE87A8DB170B6D29E269D36FA3234C81481A3BD462258245A7B645210F34BE98F8C1030B7525C6F2035058838B3115212F03591CFB53148802A6DA8C6845198E2C8E20022A1BB59A95241F6C5AC48A3967229C6B4F138B30510B73D37E98B74510B703ECD7AE03BA65B045070AB50D91E171BC42AA92EC64AEEB9131489A36DAEC3380DB0F118084892266BD759111006889DEBD71886C81DD1F0992E18C50C4657A7C210572CE16D243D3BC97F957AF798E482792310C524A1645E8426FBF5EB8F0B8D393EB1D1FF002374CD2AD24B8FACC8B2409CBF7A76247D38F0B8D29A0B4DF33689E5E3793CF730C571A7D79F134A8197618B10789E11F993FF003955A5E97697F6FA0A9BABC98323B49BA8EA36F87325AE669F188F3B7E6079FAF9ADAD2F561B59FD46B94534201A9006C3C70DB8E7290C5B4AD3E1D275392DB592F717334A03C8FBF53DB27C69194BEACF2AF93E2D6E1161A2A492974A3B36FC411DB2B99B6C8CDED5F941F9172796BCC4FA84AD2CE8CFCA6F537E277E9BE56CF8EDF74C691C2A8109E1025501F6C3652082F3BB1AEA1E6A7BCA739223C78FECED8DA683D06F1115A198578A312DEC72F8C0485A90180C006AFE6C9243F14708DA982500189A66B1C4F1488518AA4B5E5F25CAA52A6069E4DE67B48BCC7E67B6D2DADD25B585C7AEC07C54077CABC621AF64279ABF2B6EF4DD2B5AD5741BE6B484216823534A0A0EBBE4865B6C1005F879F9B02E6E7CD9A80D61E3BA9E1958073B9DB26269E00F3089B568627BAD3D12358E4A1E636E3ED960368D83D2B43F3C4F63259C11C9CE5968272DF641EF4DB274178807F551F9093B5D7E45FE4BDD350B5CF913CB92B11D2AFA65BB7F1CDEE1FA23EE0F2DA8DF2CBDE7EF7ACE58D2EC55D8ABB1558FD3E9C554B15762AEC55D8ABB15762AEC555315762AEC55D8ABB15762AB97BE2ABB157FFFD5FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF90FF00CB7F20CFABEB70F9784FE9BBB0569CD76FA727E3B8A3474FD1DD03F23BF2F3C93A589BCC5E60B79AEDE3E4119F707EFF007C7C76C8E969F1C7FCE4679DBCA97925BE9BE5331C6DA651649E3E8DC698F8EDF1C34F985743D435AB73A95C5AB244568B514F57DBDF01CEC8E34D74AFCB3F36EB344B1B65B6B63FB4C074FBF29395022CB74FFC91D5CEA169646F0CB792B82B02D6868457299657271C5FAB7F90DF96FA8695E588AC2E2331968C027E81941CAE6460F7693CA361A1E8F705C896E5DC145EFCBB1CA8E46E10BD9F397E76FE60587923CA7269D6404DE66D67F72186EC81E9BE0395C8861A60BF911F93BA0E956D75E74F38EA0B3DC5CC06ED8B36E8C6BB75CC79657371E36216F637DF9B9F9A52D868F792CBE5AD35E9287354A2FDDE198F2CACE589ED7E70F2C5C6B0963E42F2E5C1B68B4F939DEBC6688E0F63959CAD4715259E7AF3EE89F933F97B37956C5565F325C2141243F6F930237A57227236E3C5C4F19FC99FC9EF3579E357B2F3B7982E85BDACF299409BAB2F20DEDE390395DBE97476FA57F323F30348FCBD8C68F62F6D3B88F837115DC0A7BF8656723D0E9B40F813CDFACB79A75A6BE9E0145242328E80E0F11CC9F65F131F9AC2248F925F4B6EDE08D4C81CAC4F6481D1434AB8BFB2BB8A73AACD71A746F59A177AD4F7C9C32BAFD4F66D07D412F9D7C87AC79623B2D3ECA38F5644A34B415E599B8F23CE6A7414F0F3A6EAF7777248B3B95AD16253B53E599D8E6E8F2E1E03499E9BE5C56BD53AB192DE2247276DB2F127127165D7FA0E8F0317F2EEA85EF1002C8ADB93E18CA4D6229B7953F33A6D26F5346D6AD65424F1FACB0FA3AD330E72722117D2D63AAD9DEDB42F6B79CD5D4155AE634B9B971E48AF5AD89E372BCD7C72B219A1DACF4FB9E4A6C57813B371EA3C72B21B2293DE792B49BB25BD08D49F6FEDC810CC3CE75CFCAFB296390C4A2B534A7FB78B787916A1F965240EFC54D05698B6061D7DE50D42353FBB240E9F462CC31B974CB8B7E4B25B9AF8D31672E4848D2584EE87171AB74D61B9A8E25295D89C5B150951DF1640B4B28A80A773DB14CCEC9AC658A0DF22E2A3ED62326C7A1AE34B68D58A15824653F18E831E15B645E43F296A9E67D5E1B75899A194D2B966385948C9C2FB83CAFF0092FA779295353D5A2170654E410EF4AFD3991E1A0E77A4E82DA4699F5ED6AE255B3D3ADE3630C55A55C7418F86D32CCF3DD5BF33AE7CE574749D20496F6ECDE9B4E36047CE98F84E34B23CEBCF1A3792FCA7A1EA926BBAA97BEBD80FA4BCF7E743D725185328647E5DEBFA8C32EA57C2CE212DA991B8B91534AE4A98E4928F9735ABDD1EF0DD69B251CAB7A918F9634E29927A350BBF32B5ACB1DBB3DFB5C207A0DFED634CA2FD64FC8CF29C1E5EF2B0D66F63A5CC9081F17662A3010D8F77F23D85DCB6FA9DE5CC815667261AF8646922D3CD6EEC69D62189A168F8D7DF1A6C8DA43E4EB4FAB9B9D4661B4D5E24FBE34CF74E755BCFABE8B3C8C68ECEDC7E9E9878E934520F29DB1B2824D4E71BDC92149F7CAE5918905956A139B4B19A73B7D514927FD615CA253B6B312C23C8F6AD35FDFEB972B54B824424FBE5129313128BFCC0FD23079435716F2B969636A460F4DB2D8DD391189E17E06F9FFCB7AE0F34EA9A85FD94CD01998F220D2996C4B0902C7749D26F7CCD7834686136494AA9229C865824E348909B47E4F86CB506D288E57711A09325C6E399C83FAA2FF9C7E80DB7E437E495B375B7F20F96E33F34D2ED87F0CE9307F771F70FB9D2E5DE67DE5EBB96B0762AEC55D8AAC7DC7D38AA9D0E2AEA1C55D438ABA8715750E2AEA1C55D438AAFC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD6FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF233CB9FF0038C3E4DF2ADCBEB13B133D0B1911C0CC3B2E7ECFCE5FF9C95D5A6B1F346A1A7E95AB4E6C625612C5CC96E229B03DB1B29A0F89DEDDEF00926B97974FF5394909AFAA47BB63653C2FA87CC9AF797F56F2279774DD25D34B4D3A86707FBD6A0A751BE365061B337FC8DF2C5E79C752B7D26D6F2E0CAEEA11B937122A32B258460FD2CD3FF27FCBDE569F47B4B9B432EAF28065BC6DF8F427299172618DF40456B6BA6D9C16FA4C4102A51E4661D69EE72891A732106272C4F737978F79C94DADBC970B272AA1F4C578D077395D972B1E3DDF9E76B6317E6E7E6FDCDAEA08F69636B318F8CA7ED509FB35F96425272B829F42FE69F927CBDF977E4FBCB5B1FAE896F63315A4924C4A7A8694A0F0DF28916D8079F7E5DDB5EF907C986636E96B7BAC9ACD7DC6878B03D0E512939118A6307E6459E97A6DCD968086FF00CD3316F4EE07C67936DBD2A72B2594B0DBCCBCB9F94BE65F327999FCDDE78B1B8BA4327A932C95E0141AEC08DB2264E4E9F4FBBD4FCFBF9ABE57F2AE8F0E81E52E7677F0A18E242F550D420EC32B26DE8F498007C75AEDF5D6B378B7DADDCB4D7B292CBBEDD7C32B327A0C31012DFADC21FEAF343EABAED118C5283DF07139825174B3C0842B583B13D2B91254CE285BAB580C5EAADAB41714FB1FB253C699289759AA31AD93BF21FE5BF997CF5AA25B7942D9E390B52E6465257DE9B6676393CB6AA9FA0BF97DFF0038C4BE5FB186E7CD3299AF1497996BFC33618E5B3CA6B620CB646F9AFF0025F45F3497D3AC6330A8F843A6C7C3AE64893AE9C5E7FE59FF009C4B6F2E6BEFA88BA9E78B90608EE5878F4C12935883D1FCE5F91FA16B366919822B5BC450A27550A6B4CC49CB7722317CD97FE5DF30FE5DDECA90C72EAB696CD44F4EA683000D8F40F2E79AEC35E884733AD9DD746B7907C55FA7010CD983EA0F1AFA3C1404F85180EB9590D812B7FADCADCBD6F84F4036C810C834F248AB406BDB7CADBD21BA53293CD41C5B42552E936F221AA038B20C2B54F2BC3217A44BB83DB16C3BBCCF54F2A4B17F751803E58B5F0B13B9D1E5B706AB4FA314243346F1FDA53BF4C50A5146DC838041076C0589927F096E03236C0A6F6C582FC3D7FCEB931BB548A3A0D2A6BABC820B40CC2660251D7AE5A22D7C4FD0BFC98F24E95A1E9D6B7A2D985F08F90673515A7865F8A3BB4CF23D4FCD9E6780AC36D247CE78E3ACC3F6683AED99341C7F11F21DDF9E17CF3E61BCF275ADF243A7D94865BB8D0856A0EA2B5F6C691E25BD5935BFCBEF2569062B7A34F0A7266EADCBFD6C683025F9C1F9BBF987A879ABCC37C25AAE903E1B5727627C0602144A9E07E85AB1755670AC4D77C1C2C2791D64B67A6DC898BB2CBB8849355DFAD463C2D5C56FA7FF00203CAB16AFAF433BBC73C664570817DC1C785BE127EA25D4634ED0934E0BC04DC5828DBA0ED9121CDC401E6CF7CB6D0268F089CBAB2814A1A7DF829BC4425FE6C65BF8AD6D636E3561C877E38D331009F689666F74B92DE195614B215766F6C69B0462C1FCF9AFE876D2C3A341AA4308545370ECC0EE7AF7CC79C776C1008D7F39FE5FDA687656D77E64B5630D0944700D7DF7CACC14C22C4BCD5F9C5E4792D27B1D3F5980FD6C2ADC55813F08A0A6FB640E32D6718653E49F37F93EEB4286C1756817D221A3F8C035EBBEF90F08B0F0C273AE79A34C3A7CF099619CCBB2B5410C3DB7CC8863A0E44202980CDF92FE44F3BE963EBBA72FD6AF3ED3A902B5C3C0C258C3E78F3E7FCE23685A523EB9E5EBAFAB6A963FBB823076A2F4040EB83869C69E10F9423FC92F3C4BE66FAC49A6CB33C8D46B8553C4FE18971CE9EDFD0E7E5058CFA67E52FE5769B72A52E74EF28E896D7087A8786C21461F78CE9F4FFDD47DC3EE797D40AC921E67EF7A2E5CD4EC55D8ABB1568FBE2AD547862AEA8F0C55D51E18ABAA3C3157547862AEA8F0C55D51E18AADC55D8ABB15762AEC55D8AAE5EF8AAEC55FFFD7FBF98AAD6ED8AADC55D8ABB15762AEC55D8ABB15762AEC55D8ABB15762AEC5578E98AB78ABB15762AEC55D8ABF30EE7FE3932FFBDDF60FF7998EE4BF25BF357FE537D53FE39BFB5FEF6F5EDD716D0F1497FDDBFF001C5EA7FB9E98B745253FDFDAFF00BC7FDE0FEFBFB9EBDF23264793F4DFFE7143FE3BBA67FC707A2FFBC7FDE74194B18BF42B56FF0094853EC7D8FF0077F5E9FB194CDCA83C8BCEFF0061BFE521FB5FF1E7F63A9E9ED98F272E09DF927FDE49BEDFFBCB27FBDFFDEFFB2FE3953938DF1A59FF00E4EBB4FB1FEF50FF00783FBAEA7EDE464DF27D01FF00395FFF001CEF2EFDAFEF63FF008C1DBAFBE53258F3625F985FF92AB47EBFDCAFFBCDF6BA663C9CDC6F00FF009C69FF0094FA7FEE7ED0FF008EAFCFB65679B9717EA37997FE51BD43FDE3FF00799BFDE4E9F64F4C94F936E93EB7E3179D7FE531BAEBFEF43FF7DFEB9E998E5E9B4FC921BDFF008EDDB74E9FEEEFB1959E4EC23C936D3BFE3A375FEF1FDB1D3E5DB029F8ABEB3FDF27D8FF009E790973627E2AB17FBD717F75FDC8FF007A7EC7D39383AFD47C5FA1DFF389BD2EBFE385D0FF00BC3FDF77EB99F89E675DC8F37D49AFFF007D71FDF743F6FECE6645D066E6C5344FF7A24FEE3AFECFDBEB99117124CCAD3FBE7FB5FECFA60C9C9AC3CD3CF1F69BEDF5FF0075FD398736F8BCA74FFF00A587FBC7DFFE3A19747E9497CB7AEFFCA552FF00BCDF6FFE95B80A43D7A1FF00792DFF00BCFEEC7F7DD722DB1504FB67EDFD1959641565E9DF2A2DE12997ED606D0843F4E2C825571D5BED7D38B6B12BFF00DAFB3FECB14179F6ADF6BFDD78B51611A8F5FF00757D18B192017FBB3F67A603C9804543FDD8C805926D69DF2E8B44F9BD2FC89FF1D6B7FEEBED8FEF7E797C5A25CDFA15E5BFF8E6DA75EA9FDD7D1F865F071F27262BE69FF8EB6A5F6BFDE47EBFC32E71DF97FE4FFF00C995E66FF7BFFDEC93FBBFB7F4FF00938ABEC7BDFF00943F52FF008E77F70DFEF47F7FF47BE2AFCCCD7FFDEDBBFF007A3FBF7FB7F63FD8E1632E4C6A3FB4DF6FE8C0D3245C3FDD5C74EDFDEF5FF638583EDFFF009C50FF008E9C5FDCFDA5FB5D7A8C0E4C1FA41E6DFEFB48FB3FDCF7FB3909399064D63FF1CF8BFBBE9FB3D320DC3E2C67CC5FF1D0B0FB7F647F77FC71671F8A62DFF28CEB5FEF67F74DFEF07F7BF4E167F37E67FE65FF00C746F7FE526E9FEEDFB5903CDBA3F178737D97FF008EDFFCF6EB8127E2952FF7FF00F4B5EBDFAE2D72F8BD3FCA9F6D7FE526E9FF001EFF006708607E2FA3EDBFDE1D1FFE523E8BFDFF004FF65930DD1E5D5F5BF977FDE0D27FDEFF00B2BFDD7DAFA72054A7FE6EFF007960FF007B3A8EBF47DAC816324FB4DFF8E7D97FC733A0FB5FDEF4EF902C1F62796FFE51ED07ECFF00C73AD7ECFD9FEE57A7B674DA7FEEE3EE1F73C7EABFBD9FF58FDE9D65AD0EC55D8ABB1569BA62AB315762AEC55D8ABB15762AEC55D8ABB15762AEC55D8ABB155CBDF155D8ABFFD9, '1', '2021-03-13 12:29:10', '1', '2021-03-13 12:29:10', b'0', 0); +INSERT INTO `infra_file` VALUES ('9a2317ba-fa4c-4f77-84b4-7cc537d382df', 'jpg', 0xFFD8FFE000104A46494600010100000100010000FFE202284943435F50524F46494C450001010000021800000000021000006D6E74725247422058595A2000000000000000000000000061637370000000000000000000000000000000000000000000000000000000010000F6D6000100000000D32D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000964657363000000F0000000747258595A00000164000000146758595A00000178000000146258595A0000018C0000001472545243000001A00000002867545243000001A00000002862545243000001A00000002877747074000001C80000001463707274000001DC0000003C6D6C756300000000000000010000000C656E5553000000580000001C0073005200470042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058595A200000000000006FA2000038F50000039058595A2000000000000062990000B785000018DA58595A2000000000000024A000000F840000B6CF706172610000000000040000000266660000F2A700000D59000013D000000A5B000000000000000058595A20000000000000F6D6000100000000D32D6D6C756300000000000000010000000C656E5553000000200000001C0047006F006F0067006C006500200049006E0063002E00200032003000310036FFDB00430001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFDB00430101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101FFC00011080190019003011100021101031101FFC4001F0000010402030101000000000000000000000405060702030108090A0BFFC400511000010302040305040804040404040309010203110421000506311241510713226171088191A1091432B1C1D1E1F015234252162462F1335392D20A4372A2253482E218356317192655648393A3B2FFC4001E0100010403010101000000000000000000000304050601020708090AFFC4004A1100010204040306050303030302030607010211000321310405415112617106138191A1F00722B1C1D11432E10842F115235233629272A20924E21617344382C2D225354463B2F2FFDA000C03010002110311003F00FCFF00F041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C10418208FD87B813D3E67F3C7788F3FC6E69363C22D6FDDF0411BB815D3E63F3C104286410153D460823760820C10418208E4027618208E7815D3E63F3C1041C0AE9F31F9E0820E0574F98FCF04119A10A936E5D479608525EBE1F78DBC0AE9F31F9E08520E0574F98FCF0410702BA7CC7E78208DADA0999B6DE7F8E08236F77E7F2FD70410777E7F2FD70410777E7F2FD704118A93C317999C10CF13AFBFF008C638219C72013B608232E03D47CFF002C1046694F0CCF38FDFCF094D4158006875877214CC4D4FD59E32C6132985EBAD1DBC7E9189A1DBE576B559DD9FA7DE0C2D0D1724AAA4545ABF8AC18553348A7AD1FC695F7ADF44E1946C9F53F76F5BC6C473F76174E33BB4F03024EB57AF9368DA3830E51803308511C2536ABBB6EC6FE9D1A366135E0FBF1DE92CDF335347DDEE075873FAB3873DD005AC29CB7F4D6B780E5F4D5A851A8FB2D5C6FCFDE363F973C309B988C092848E23661A353F0E1FEF1B1CBBF5AEA52806AD7954F9B1B391E70DFF567A9D7C397282190654A510010227ED1F523D3E3A0CBA7F68FE44CB50E2F95D8D8BEBB6EFE908AB3AC2766471AE623E4A8721E9CB4B73D7AC467586B5D2BA4A851555F54D2B3108594242AE1691B7849036DA2498EB6BC763FE0E62FBF335285B02145D07567AB3373E839C707F8B3F13F099FCB1290B41E0052E143F8D47E2EF1E7E769BDBC67DABAADECBA8415508529008E12384980678418B58EC46F7DFD51D8BEC1E2B2C54A331040053420A6D4D5DB4616EB78F1AF6AB1E8C5266709A17DA8E49ADFDF98A15D4F1A96E288FAC39726D6264FDE7974E5B63D138341C3C89686F942403B1259FA01BF3146BF11C561D4AC41535D46ACE2E3416D980B78C33F7B56CB87BCF13677208B0B58013EFE77E5BE1D4FC4E164A0103E602A5EA0F46E9EB5B45932826536F4DD9C352D4F3D2FB3D52AD755FC9CB69D6AA85405AE080831637111067A72BE2B38BCC82D570DD5DBF34FB545E26B329A26A101DC0DBCB6D7DF296D2692FAB2135D9FD5200FB41B252088822E08322C6FCFA5F112BC5898E259248B9B01B6DC8F3B5AF09DD10CA04B0BDBDDFCB5768E2B75F6579237F56CBC0EEC82952B8ACBE1B022790F58E57DB0B48C089EB97C60A9BF6D051CF2BDFD0738CF0B7ED2DBEBF58A8B526BFF00AE05C41924CCDE6E6F620C5C7A82011CBA064F952259494A49B3DC57AFD1875DE32C5EF4D9B4FE7E914E669A892E9971405D51B73DE4FF00B8169E78BD48CAC2C070C031353E0C4FBBD214960D6BEFA7D2AFD5CC57B9BE76C282A48264F31F388F2C5830A8561C0094150029CEB5B3D2FEE90B02458C5659CE748414107884AB8960CF0743CC103623167CBE79596EE94016DFA3DBC474D602A56FABFBB539443ABB50B652A4B55A16A0090D94F09932624F43E9E98B127284E3903893DDCB7625C9A1A3B5F7FB466F57751D1B9EF688457E7D9A212B536D0A74916295A5C2F728099244741BF4387185ECAE5929655FAC4F10A974B355CDDB63E2E7687F845F7038881A74156ADBD80C46AD1966479EEB3AE4D1D165F58FBCEAB852A34AFA112AB495A91C113E7F3C67138DCAB26429B1929D22A0A92096E4FAB69CD8690FD58B29038998F420ED607C5F4D23B15A53D8935667C935FA8EB5191D227816D347B97D758857DB061C0A68A45A08BCD8CC6397E79F18303226AB0982FF00E6785D2B354849D2A4172F5A13B46E9C6CB482490966E120BB1B9B1EB77F28EC2699F669EC9F45774E57D00ACCC1AB9A90F3A8950DD5C21445FEE0440C72CCEFE2063F16B2A9092949774049513D0B75BF4143185E669593C441239EA1F73A0A103520EF16DB35D9169D60B392A825A5A424B72A3C2102D75493EF323D310723033BB529EF714852384BB11551275D400DA3B93D22B79BC93982870034D75F00FD4921BF2C198EB9692092B4DE67C43A5C6D6B5B162C2F651583471CA4958005003E16BD3F310F2B2598925C103426F5F2B5B5BED15FE6DDA286F83B92823C5C478922236DCFC45EF893C360F1085702B09316C59FE617A060C77E40F51599C365533880AB01424569E5D6C4E8763F43BDDF9FCBF5C7C6A8FB131B1B6F7BF4E5EBE78208D9DD93B19F77EB8208CC20A6666FD44608239C1041820830410A1948215239E082377027A7CCFE782083813D3E67F3C1041C00EC27E38208D884004CA62DE7E5CFF0C10A4BD7C3EF1B3813D3E67F3C10A41C09E9F33F9E0820E04F4F99FCF0411B5B481303A608236E0820C10418208D0FEC98DA4CFEFD7E6704369C2A7937D0084D82108DEC6EAF4C10429C1046B7397BFF007FBEB85E454A81B375D768D54A2080CEFEDBE91AF1B2C0248D296E821DCA415F086277E956F0E9061B2BE57D5B6F7E71209C10500785CF3A0F37F1A6FAC7307A1F81C3757CA1EE7503D2B6E7CA36FD3357840DEBA79FE233458906C4EC0D89DF61CF1B494158E32A219CF0B78EFF0096D371A99A9927846B43A93CB95EBEAD1B0DAE6C3CEDF7E135E3E725624CB4A94FF28A3EDCB9F3DA31330B24CA33662920B7155B7D4927E9CB584B599BD1E4CC2EAAB9C42184A655C6A090A001DA489F389DBD316AC87B198ACF6721465AFE6503504B545C0B373357E4D1CCFB55DBEC2767E4CD4A26A78D20FF00700C40237D3EA6E0D23AA9DA97B41D332DBD41A6DC42570A471A162EA883736EBCFDF8F507633E14272F952E66270E1870A99419EAFAD5DC0D2F78F2376E3E2FCCCC8CD932672812541252A3F2935B0BEFA0E978E906A3D759BE6D50BFE3B50F2FBF512C00A5917BAAE9240B0E6664917DF1E89C8F23C248C3818591292500098FC2CA61435D983B0A9BED1E7CC7F6971666A973E72D426124024D35B39BBBD3C621A3307585FF002524A567ED106D3E666F7B01F118B1AE461928799C0929B0000E7561E7A97DAB0C5199FEACB1750258B9F017E6684EBCA14AA96B1F5B45995B951FDBE2E020C0E289E1BF5237EA31058BCD254B79682DC2E2EEEDD2B5D4EFE0DAAF0495BA8861A335EA46F41A915AE8226D94E87AE6529ABCCD680C7DA2952900F08BFD9E2927CCFEB8AD4FC7AB1130CBF9893D75ADFDB1A690DB80E1EA0B373BD036B4035BD3C21C333D4F91E46D0672361B554905350E18F09488175023D23F2930B96E2312B515F114D38433B5DDB5E437F28CCBC419CE92F6605DDC543DAFEDDA29BD41AE1350B50CCAA949249E16D1C5C23A094102DCF7F28C5830B904E5280E025C8AB352FCDFC7CEA215E015F6C3DEBE91546799EADC2D990191C45B5055C8E7304116DAF8BBE53D9A595259160E5C10CFEBE9E2D521962CF5DC5BDFD3C04573996A24B4140AED3D63EF31D07E62D8E9596E401013F2ECC1897A56BE356BFA1D420EA5BDF5F7F4AEF3AD4C1DE0E05C70F14DEDBF95BE1E78B561B23E2203300D417AB7974ABD342F0A2106AD5F2F7B8BC5719A67CE9E2217293B4131CF97E38B0E1F26C34A40330A53C357207DCEDE20C6C4117D62249CE6BAAD6696929AA2B5D7D5C284B2D2DD0924C429494A8226D1C513CAD384B1D8DCAB2F149D2828034701D86B5F76BC64214A4A940512CE5F7B7BE9168692F674ED1B5938DD5D4E5AACBB2E708597D6EB654942B9941215B6FCE76C737CE7E25CBCB5E5E194E5CB70D8B01A5B52CDE71AB6BB74BF4BEFEDE3B33A5FD98B4069B525ED515BFC7AB7C0A61A525D61348A4C158F0A8A1C0B3D640E9D39DE3FE2666999CD2995355864A5DC825D6F4AD886FB36D19FF74A552D2EA0BB8D49EB4AEBA336BADF946F643A6A8D34993D150D22109E14A8D3B0A58E1020F196F8A6013BDF7E78A86638BC7E6734CD54E9F3261FEE0A98906C2C0B1D80A51AE6012E7B01F3569BB72BD76AF4110FCDF581A4595F12AA03F370EF7496639A532019E805ADD4E12C0E439962A60E34288243B80E4022E59EC7DDA35EE26B5016AB0DF7E5EEB158675AE6951C6B7B312DEE4B6A4A9503A711BDFF00327963A7E4DD90594A0CCC389967240A1D74AD58C024CCAB8507D2B5E75F75EA22A8CF3B4FA36520533E85405719EF00EBB898103974B7AF47CAFB21C20BCB4CB048E1000DE9B5D80B1F4895C0C86204CBBD5F9BB0A8A50783F952FA8BB5C5242F81EE217809503693D2763EF1B5B95D309D9BC0E1C0FD44C9680003F3149D8D8989944992194DC99AF5D79BDF9161B0A9332ED3B38CC1C4B7468AC599321961D7449DB88A52A03CA6FE7189299FFD9DCBC12B992262AFFDA1DBA56A75F5893952E4FEEE14B269A0BF2A75D8C7D9F702BA7CC7E78FCE947D488CD00899E7820856D7F4FBFF001C1046C7397BFF000C1046BC10472013B0C10473C0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208CD00899C1042D47DA1EFF00B8E082327397BFF0C10A4BD7C3EF1AF04291B1BE7EEFC70411B304118A93C51788C10463DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1046C4366F0472DEDD7D7046AA4F13559A33E03D47CFF2C11AF77CFD3F98E0A4A6262F820EEF9FA7F318E083BBE7E9FCC6494F14DE2309AE7095AD4DC0F4D21ACC404AB702C767F7AFD9E32EEFCFE5F1E78C27121542AB50F46E9E17AD59E25B0880407143F624F87500F231AD41485A63633263D63979F581BDF0A0636ABFE7F36F48972BEED2598003A7ADE9785E97611E000AA2C009933E847E5EA6CA0C3950709AF536F63DB457B1D980960B1B3EBBF386F5A1F2E7795280D2904965C2425206EB27607C89983B637460B12B9A897250541440A026B4B5FCCE962D103333EC1C94AE64F9A947007F995AEFE837E758ACFB40ED7B49691A171BCCEA9BA8AF4A141A085414AD22D3DD9BEC3A73DAF8ECBD90F86188CD97266AE5514439526D57B37516FE787F6DFE2F4ACB53364C99C0B710042BCA8EFE1D0DA3A0BAE3B6DD45ABAB3EACEBAE3792A4B818E05F0C2153CD30A3CAEA9F863D51D9AEC160B2097C62524CC64F1929D980615D49D2BE71E43ED576FB17DA099302672D94A2ECA25DDF9DEF67D0E800A32B5C72AAB0A299C5960A8A9C5A964913E2B9513CE79F2F71E852E6CA54B1282412DC219852C2D7A6F60E3568E61370B880B3396A528383577AF89E7C8E9631ADEAC697C34AC8EF9C62CB4F0F1294544110482607979F3C44E331ABCA5887F9AE1D83D7F353E71159809B882020171471F6E648FE1A90F794E98CD7365871491474A2EB2E04DD063FBA08B4D801E5D442CFCF7138C3F2950068384925CEED785B01297214935040AB8B9D6F5D2BCF689839FC0F48B45197AD0F5554A4FD6D44F180A6C0E1E10A2A09BCDD3E569384F0F87C4E26612B4A88A312E5FD0BF8FF009B14BC406093C9CB83D2BD7A00FE759EA5D6AEB895A50E2D2992084A8C46DB0F4E9EEE58B9E5D9271315203D2AD5FE437D5C447E2809BC4003A7B715A5EBE42F151D76A72E71F78A22E4824C13D46F3E71B62FF95648944B0A080E68430E6DCCFADDB946B8190CA20861A1AD7C3EFD4968AF739D40D10A2B50B4F43BDA79F5F527618B8607260E9FF6C1377200BF20DB7F889054A0EA6340CDEF5D76F48ACB3ACF95C214D3A4F0C9E0130A9DAFB88FBF6C5AF078144A07BC481D40A6CDE9FCD635EEF9F5F7D22AFCC750D45495A16CFD58DE17DE7113CAC89E76DA7D4C624E4E270F852429495736614E47CF7D768C940A72F50F5AF9FF0010DF94E5B9FEA5A85D0657435598D4A9494B290D3ADA254620BBC3C2396E4623F31EDC65D93389810A55C7CC01A07D3ABB3788A4615F29A51DDC69E1E71D89D1BEC9FA82B8B199EBDCF13A5E8950BFA806915E5D418F09534AE24CED3CA76C732CF7E2B4EC68523289267AD2E95242FBB67E65810078F2302502BC5F28350757A93E7B1FB476974DF673A0BB3EA7713A6B25A6E3AA091579A3C43EAAE5343C2A4B2F051A7E13C93C24C99C73AC463738CD27CC9B889D312EDC3872A5349767F9C11C4F7A337AC60D0326BC5767AB1D9E9515A316F25D5DA83EAC9296F81A481012D8091FF4881B4DA3D061C48C9674FF009A6ACAAF42E6B5D5C9B5691A457D9CEADA068076B1CE052788A1C924A6638A403723A6E3EE7533B2B389419128A8387603FCF9D0E97896CB90851F98F2B0D3EB5DAA75BC5459FF0069542942D34E7EBCB4880B528D3F099B58C4FCE0FCAF5D9EEC84C982599C8E12083548275F3A00C452912E2549092431B0E74DDDEC35B750D14966FDA5D6BAB5F7CA53886C92D36DAA4B53361C175CEC378F22631D7705D95C24940527BB42884F12C81F330E76620B9153EB194CA9003900DEBBD1CD6ED53B3B18AF2A738D47AB5E34795B55656E12800D33C94C9B7FC45242779B93077E589350CAB2F9759D282807532D0F4D83DED6DF9C60C99360D7200602E4120BD9A950D123C9FD9B35B66E876AF50E6E720A65F0AD912DD49A94AAEA94A17C4D948EA39FC6859BF6DE5CB5AA5E58B338CB2CBE1052CF600B17F0AE81AD08CFE0C30534BE252838214CDD40FC01436689851760DD9DE429073DCCD39B3C800AC28AD90A2093221640B08F39BDB1589B9B67999A80968C4278AAE0A983F26B7DBC223CE2A7AA8A24241B52A0D59FEBE1A38896D1661A0345B6B190645423BD003CE3AE36F13C164901E4A888E7004DE7961493D96CEF1E52A9B889E90AB92165B4AFF86E4E408C9C54D724120D2C6FE1FCEF4DFEA0B813D3E67F3C7C448FAE1182C01103AFE18208DAD7F4FBFF001C1046C7397BFF000C1046BC10428640215239E082377027A7CCFE782083813D3E67F3C1041C09E9F33F9E082315262201E73B9E98208DC8FB43DFF71C10464E72F7FE1821497AF87DE35E08523637CFDDF8E08236608236B6099813B7E38208DBC0AE9F31F9E0820E0574F98FCF0410702BA7CC7E78208D8DA0C99B5BC8FE3851129730128492DB03F88D4A929604B3C6EEEFCFE5FAE345A552DF8C14B5DC41C69DFC9CC25A84414C49B1E584BBD976E34BECF1B42683D0FC0E144FCEDC3F33D9A08554E82AE29062D68F774F31EBB74223333973D2C532D5CA86EDEBC879C68B0E40F60381E3F6850503991EFF00F7BF2E9D79623E4CD5A3F7862DF6D6EFAFD62530A81F2922ADA1DDCE87DDB48E52D852D28304AE403C86D79B6D7FCB161C02D33F85D8BB3695ABEBE239F284F30C64B9328954C4861A9D9E8CFA74DF94346A0AFA5D334CBADA8A86509402AE15BCDA4D8490125533F38B5B173C164F8AC424193214BD5922AE76A55EC06DE11C833FED56030CA5F162D0821E8A50B8EA59AECE63A7DDAA7B49A94CA32BCA4A53671B79D6D4991FDA640133E47CFCB1DFFE1A7C3A39924E231D87E0EED890A4DDFA8ADBC9AFA793FE2AFC5299972C4ACBA7F7DC45415DDAF98A509A57968DCBA35A8B3BABCEEB5CACABAB72A8B8A2AE052D5099E504991E57E533338EFF0085CBE4F673865CA94084B00C1B7B9FCB6E1A91C067E718CED0054CC44C5A42854124924EDB30ADC784343D5A5B6437629779003C3C3BDC093BFEF9CBC9C7FEB4F0A93C06C4BF938A0B50EA79561A0C18C19EF0AF8F5F5DB7F0B7431BB2E4399B1197E5ADBA9754614E702F8403170A2909023CFD30E4C993844F7EB9A193F31147DC51DCD7D0E85842C31699E44BE10D40FE62A49A0DEDE57B0E934E64BA5984D4E62B43998B838D282AE2248BC5A529B5A481327AE2BF982E6672BE1C3C95144B35531170C0B1E96D7A42F2B2EC3A4778B5A49502458B36F5EB7FA9AC3B52768350EB6AA44C5234994A3BB29320587D88378EBE7732712195F67A6383310470B1729DCFD69F5EB0C7152E4CBE208502DA8F1D411BFDC08A6B36D4F5544438FB8A750F71142F8A763264090396F13B73C745CB324C31212402B4B3B80F514A11B8DF588552D6E785CBEDD357BF4D6A6915F663AC12EF1092679C9F988B753691E918B2272A5CB712A5B8A51987D4FAC48E152B985969246BD01A7566AF9440338D4895C70AC08E2913173F03CCED2475C59F27C2290969D2CA53A72BBF27F06A5A251587080080D6E54B5BA69BB12358AD735CFD6A514A572A13B193F0DC9BEE2E4CF2C584CE918541AA52DA9A9D3D2FD5BC635280D40C7993E30DF9465DAC351542A9F22CA6A2A9C5A9295BEA429286428D882B4049045EC63E2315ECC33F91282809E974BEA97D4DABA680758D084E8AB339DC9D3A5347BF28ECD683F65862AFBACEFB42CDC30530E0A20DF15EC4A4A9A544C45C8B1BF2C72CCEFB6B880A29C0A3F505D414CAE1E1AD0824D79B7F319FF6FF00B884DD892F6D4B6FE3CA3B2D97A748E8DA6396699CA695A0A486DCAA5212A5BBC0212415A0A916BDBE3CB154387C7E7E1588C56257420A52C7E4D48A5FD9B184D402E882585E80BEDD05B6E7AC36D7E7294A56BA806F24153A4848BFF4931EE03D7AE24F07947E9871A0998A0C48E121D9AA6E796E1ACE29A2A5AD3423F1AD36DCD7EF15E57EA96E902FFCC15A144C24130D81E7263E3CB98179895350A5241C39045096626C0559A8DF4D69191C61C90EF67A5BD9D2FE71516A3ED0D0C970072499E704C728EBCADBC8907170CB24C89A9038784B8D59AAD5F3EA06D4318214A366F114F7E315557EA3CE73E525ACB32FAAADAA04F70C06DC4B6E1302EE9414245C1249B832671699589C065724F7A25ACAAA1D497A6C2F60458D61591395248649A967AEFB1A59FEF1BF2FEC875667EE7D735BAD3A532F242843ADD515A39C869414391B89BDFCD15F6F24C99331380C195CC450000A5EAD761CDFCE1CCCC54C0A294925243B87E47E94E74BC4E99D15D94E97434B08467EF23ED54ADD718EED49DFF96A242A6368F80C404EED57687325A532C4DC1A4B8E04A78DC1D8B53AD2E23518D50354F15033ED7F1DEB47109732ED674CE4CC9A4CADBA3A100708E1A7694A03942CA267DF208DE775A56498FCCD5DE4D9D384C2039254012756240E54E8F185636610DC2A67E9A860ECFEF9C53D9FF6C152D9E2A3CD9FFE7717136D32B7A609800241088BDA00DAD8B764DD98C065EF33319885BD7E7604355DC972FF0047E6CFB0AB188A4C3C2D4F9B5AF33EC88AFDACDF5CEB3ABFABE51936659938B5405A9A7E992A2A3FDCB404C5F798138B0CCCFF00B3D948225A641290593C4870DD1CE9A3DC0D61E1C3C915E201BC6E2EFA0E55040701E27B45ECDDDB3E7C84395D90AB2AA65805152ACCD9594A5512A2D1701300EC47E00D6F17F19329C29549C3E152560904014D6AECCDE7472212386921CF186D6D576BD5CEE2DA120C7D69E3E0F47D6C80807700FAE0820C10460B49511161CCFE9EE8C1046D423E1F7FEFF41E4410A020FF00E91E9F8608232EEFCFE5FAE08237349E124CCED8D16680737F2FF3030370F1BB0946186C3C840403B807D719722C488180B0020C62061B0F28C929E29BC4608CC65DDF9FCBF5C1041DDF9FCBF5C1041DDF9FCBF5C1042AA64F09573C1042AC104182304034306081850B5ADEFDB4189CCAB32C3E102C4E0090000E1FC8B7D9B9C6ABC14CC5074288E1B73D3EC7C6FCCC218F9F2F18E25D097B36B61B59F5E95B335C89987352FC2EE0DDAA0F27B6F4F28E201DC03EEC5715964FE22A0A535C162037E0FD358C271A38B8483521EAEFE0C2DF6D9A081D07C06257053460C8EF403C2A04BD2BA8AFDEFEB137879667B0142C2C3A8B5396DADB44EFBD50C42984CA3FF32C3DDC89B1BDBD0DB12788CD70F8C09969949530201A6F714F0BEBB46D8CC30C2A4AD6A6D6BAF83F3AFB7E02D971B554D43818424712CA884EDB8F1116B1BFAF2C2723B353735534A96A1C4400C1E87A0ABEBB522A599F6B30B964A513312E906EA03C6FE26FA333C541DA0F6D7A674BD306289E6DECC21C4852553C2A168316E9626FD48231D2FB31F09B3099325CD54B99C2483549EA2FE3F5611C1FB61F14E4290B44A9E051428B048F5F31E0F531E78F68FDAB679ACEB5E1555CEA69829412843A4002F000491E86DF3C7A7FB21D809597A658C4C80B147E2480777A820E94FE44791FB63DA2CCB369B37F4F8B98905DB8546E6A2C5BFC6E0353ED39F5BEF50E71252DC0EF56A51E2264CDC99F75F1D824A30B95202644B4CB7150960ED7B0D3CF9C735C160B1656A56653173C9248E304D39151D5C3728D0D507D62A52CD3B6BA92A500549E2013B740A1B99E7CFAE23F1D8F95381709D6A6A75A134AD1AF577D8C4BA42650F91013C3FDB667D1FF001A88B432BD0D49414EACC3397D219090B0C2889E662C67CCD8F96F8AE9C61133BB9293C4AA822C9BD7C5DE9D21B6214A52439A0D1C543F3F4FE6AC79CEB3628D2BA4D28869829052A584A7888F252D3C5C8DEF688C4AE1302AC510AC5A9534E8092914E42F4A795223A62969712FE471A6A75D68DECC55199EA1A9796A5D538B150A278C95920ABFD227840B1FB3BF9E2F794E12522584942526C01001A35CEB4A353684D336711C2165B9DA8F4A07D5EF468AFB36CE5B85294E78AFCCC73EA6D6DCF962DD84C12569E14A472200A5431D3CFC7946122613572FA93720DEFA3914E422B1CEF3F70777DDD484B7E20E34471F780EC02BFA63A889D8733896C3E4F3259E304EE4B353C1CEBCE8FA448C8420BF100C3EC06FF715D62B1CD756B6959629E9781D5482B0E05993009E1F9E2C3231185C394F7E525290DC2435854BDB6F06A8B44B495CB9690C90EEEFA6BC8F2F58D794E88D73AE1E0C64740FBA0901EA93FCB45325C363E20028104CC6F1104E18675DB3C0602504E1D32C5083F30736F122D63CB91DE74F49D406B6B4F2DFD3A34766344FB30E4FA74379BEBFCED35B54385C145DD9042B7E096D445AD7237B75C726CDFB7B89C428A70B2C94A9C779C4C13CC03CFA7943454C4B925437602FE1717BEADCC98BF69DEA1A1A3728B4BE594F454CD25282F169A2B7922C93C4B4858889306E0ED338A82B133F19342E74F54C5BBA6A5210ECEE01634D08A784325CC592529A03D2B7F2D7EDCD9BF88D6D1F7AE57B854923ECF140883CA63FF6FC394E60F2B13C0E22492000C08776D75A7F8864B953947F716B9DDD8B337ABC40F35D4F4AA538A6DA085A64874AF842226E12A0019F5F518B5E132B97804242A604A1603A08A9AD43E9734F2890CBD1C0FC4E4D402742F5DF76F74A8339D7CC07974AE55BB5EE9202596DB5C09361C4806D31CEF1BE2CB839397280485A11C41CBA85FA13E5B3BECF28426EA0EDCDBD61137936AFD4AA6DBCBDB5E5197BD77EADCE17613C8842E15617107CB6C2B8B19561105969993B4484D49D03D58D817D34A46532788B80C3572C3D6BEBA7521DA97B3AD1F912BBED539BA351D427C61B334812B17E1250A20DEC6D163EB8ADCEC563D5296AC3619724A8FF00B6A0EA7008AF0B6BEBBC6552D095014551EFF7F5D59E8766FCE3B60A3D2FFE4720A0A4CB29D00A1A6B818A85D504F475482B411D4193898ECEF67CE7EBEF33698A42E5D415CC32C3171FB78922C36D9EA63454C42414801376D58F53CCF872678A633BED3B51EAAA834D4B479834F38A29406987DD696546DE24365B4836332201F762D98BCAF26C9C30C44998A483AA43EE1DEBB35FA930DCCC4A9D400246BB8B73B7873BC3B651D8F76C1A8D21CA8C8D54744F416EB975CD71F02B752A9F8829300FD95004F316B56E776E72FC14E54A46150B5208621373D598BB7A8DA324CB090428125C10D6F4B45A593FB2665A809ACD59AB0D42800A732F148B49EA51DF2147E37E4646D86B33E2662F8BBBC2E583855699C403529429B83A75148C254805D469A5363416B1D06FE962651D96F64BA5160D268D6EB2AA53354ED738A0B52765774E7104ED31104F2DB15BCCB36ED0668A4CC9B982D085391282384240AB3A59F6DEDE08E2B1219A586291A7D37A6F5F48B21AD48E65F4FF0057CBF2ACBF2BA303847053D22D684C58F106F8C9F7C8F9E20D7964CC44DEF67CD9AB59673C6A00B07FDBC5F4E9710C3F578866EF0B1DEBF588F3B9BAEBD6E29AAF5BCB0417525469D289D8004A527A1816F7E2464E5F2C30984166009009EA4FE5F78D3F513BFE6AF323E847E23DECC7C878FB35060820C104668483337DA3DF82085A845801CB73CBF7C86082378481B608239C104184E669E3F6820C27041820830410A69D20F1126361820855C23FBC7CBF3C10473C00ECA9F77EB82083BBF3F97EB8208C8009993BFBBAF9E0823991D47C46082091D47C46082091D47C46082091D47C4621F3113411DD922EED57D4F93B1D59E257018A972814AD9C8A39A16E5E2FB738CA0F43F0C38CBB106510269AD1C973776A73FC6B1A62A4271615DD01E06FE3CBDE91C7BBDFD316B463642D2CC38D8598EDA7DBFCC404DCA57294555046B5372FBF5B0E8638E24FF70F88C4762B013B141465A4925D9ABE81B4E9CA91B0CE64659F2CC58043072469BDDEDF7860CF3525269EA735D52F30186D2A53895BADA490279150240E606DCE3161EC8762B1D986251C52E61054E070A886B9FED6E9BD6AF143EDAFC44C24890C99C80A092C428072CE351D2BA79C7457B62F68A73375BF95E9474B4471216A6CDBA13361E97F4C7ABFB11F0F4618CA3889628C4BA7EFE75B08F2176EBE22CD9C26093394CCA145EEED626FBEBAD1E3A69996779ED6BEAFAC3EED43EF9256788A8B7B9BDCC4836F98C7A432BCAB2EC248484CB40EEC072120396AE9A757D3568F32667DA6C762B107FDC591C45AA58392E0BEACDD3D21BDA7F2FA154E64EA9550B8E1404A892A2622124F5DA06E3918C298DC44B961E5A512D20162C34B52F5229C9DF789EC8B13DF9499EA249209E2BF874ADABA6C048B2DD2F9FEA073EB4D27EAB9332429D5B812DF78DAAE3842A167C3BC4C03E726978FCC53326A65713A96EC12EAAA7FE4D673BB06B4587384C94CB49941367A36DECF5058D584E4E69A774A52F7394B68AAAD4A48754A9B2E3C5754F3FED36E62C30D6565F89C428F1A1610A6F95DDC3BBD2941E9D62AEB584D8F12AA09EBE60536FBC5699F6B673325254E3CA6FBAE2E2A70484906C048201B7FB5F169C0F67E61E17430A3121CDDB930AEA5C4205D4E4D46BC87BFCC54B9BE785D5A8B07EAEA932A9DFCC93113D245A7173C0F67C84A68C056C1D8F205B91F1A3C375CB7341A50FD8F5FBF5884E699FD5AD0DA1C8847142D2A04AA44CF86E23CF9F5C4A4DCA972787802985E9D35FF00378564C906F53A8A55AA3969BEFAD4D659C678E1529216A2ABF824924DF95C99F4F332379DCBA6A70AC66D367274B97366AF9738597213AB31140DB7F25FF10D195E9FD4BABDF5D365740FBAB94A0BAA4A9086B8F9A4A841041E46DE5CA4719DA5C1E1E51056805B7AF956A29467A79EAC6C68123414E5B54DBC394762344FB346459625BCDF5D66A0D4D9C6E93BA2AF172492DA88DE05E773D231CA33DED5E23133169C04854E9609E29817C3C2E59D8D09D4FD890C999852FC4A22EC2A6DF96FA0D62F7A3CCDBD2ED2F2DC9B2F62832F74043354036B5D4A50224829E3470EC66F27E15F91819B9B28CEC4297C52AA904A83137700D40E6E28C1A1133D75483C40B798DBCFEAD0C55F56D289A9A86D554E93214A754900998F0CC45EDC8C46155640FF003214E454802C006BD3ED194951503A9B87DBA52C1E83A8311C5EA4038C38FF007684CF7680809088E448DFCC9E7F0C208CB664999549D1F7A727F7D21E4A4BA8248626C5BCDBD9FCD51A8F54E7755589A5CB10E3E952A09424A80E57201DBA74F2C59F018D561E850CCC03FAD4DDFAB3D2241186E3B5199EFF009630A5DD179B6694F49519C560A1A532A711092A701024182088DB6C6732C562B31E197870A2514570DAAC45474EB5368274AEE1228C2C74D9B5356731B54AECFF0046B25CA6A0A7CCAB523894F2AA01525606E1B5151372791B817DC8C60B2AC62B87BD9CB96C352479D5F416DF9C240BFA1FC7F9EB102CFBB58CD7345A32AD314350F553C4A1BA56A95C4366E213DFF77C207424C74C58F0F829186509B3B16898A4B9659156DAA4D033DFC2360A2011E5CAAFEB1865BD8BF6A5AD9095EA0617A5D959E21506A5BA92A49933C09585260728BF2DCE1EA7B6B96E01250252710B45199813B71330E77E718D9CD0D5EFE3EEBCA27D967601D9E64C108D639B1D4158C90695052ED3C2EC5CBA150676932003D23142ED776CF34CD8A1394E19783624284924B8A307481CCD183F388FC6CC52280EC47E3C770FE348B8B2BA8D3DA5E9114BA7A86872EA74240495D3B358E2D226DC6E214B13EB23AD862B3864E6D8F081994C9F420875AC1AB12E1D8EF0C0629490C1C13D48600D395EFE50D953AA1AA8716AA665D65D905D79BE3E07093E129680E04C5AC1201993CA2E385461658509D350B0C004A800400198A8B957992D7D635FD612096AEAE5FD1B5ADBC5F44C9ACCEF30584B4A79D4AA3C3DCA933B40E22981EFDFE58D978FCB70C4944B4A9B6200240F07AF2FA467F52B7DFADB56E5D474D6B0A7FC2B9FD514ACE524857DA75750968A3A10851133CEDEFDCE23E767F2E6B2508091A1150DE1D18EEDABC67BC330D284D087BDBD34BF2EAE6D7672E389E3ACCDD3978DD48E10F01CB70A8F94EF86ABCDE6A52552D0A98480750F566D9C0DBC63520BDED42297F7EF7D4F68BD23430735CF3F882893DDA50CAE9F808FB576D438F8AD726D1206114E79892549549286622AFE83C7762488D8D855C540B0FBBFE0347B95C0AE9F31F9E3E55C7D9E8DADA0999B7CFF007FA608236F77E7F2FD70411B5A401337DB718208DF8208304106082324A78A6F1184E669E3F68232EEFCFE5FAE138236B68179BFCBF7FBE98208DBC09E9F33F9E0820E04F4F99FCF04107027A7CCFE78208514E002A8168C1042AC10425A80094C8B4608213F027A7CCFE782083813D3E67F3C1041C09E9F33F9E082324D10A93C72AFE544004DE76B741F8E1DC8C3A2783C407537A3B01BF37F37B44E3953D2B4997C4CE6D6DF4FA6BAEF0E0DB8FA07748488800C807CBA44F337DCF28388DC6E0D6853490E09A84835666A8EB7F1312F97E3C480F38B505C80E3CED4FBED1A5F7174692BA9521B61CE2EF14A2910123DDB091B73C3DCA329C5E226A3E4590486A12CE45A9CC72DF410CB3EED66070D87983BC9614124FEE48D0D3AF2AEB1D79ED47B63D37A5E9DE672DA943B570A078566CAE7CC8933CB6F863D15D8EEC1CCC70477D289A24D52FB568C18EBE2D5AC794BB6FF00113B954D32A707054C12A1CE9473F8B3D5CF40F5FF006A59CEAD71A43952F21849761A4BAA48712ADA4248DB9C83E5CC63D43D90EC4607289056A909E32126A914A54543F3B9A3758F2DF6A3B7D8CC7CD5253354415100859347B383E914C54BB534C4AD973BA0ABAB888515493375C1BDFCFDF8B96225C8C24AE3949482DA5096D8E8CDF6778A32F173F1A499855F31AB9A52BEFABD617646D56E64EB8D6574CB0FACA454542C1291FDAA01620082660F493D2A58CCFE6A55C090404D1C3D2E6A35FCDE3072897FBEE4B3E9FE2BD356DA2C8634C69DC890330D50E22A6B40E36C724AA398448F2BF2DCE231798633174758E226B52C05F4DB4FA464BE098A0971564914277F53E8F0C59FEB9398A1BA7A750632FA4E24D321B86CA81B10AE182AE51C409BF217C5A3B3B94A5466CF5CA2A9931B88A9D56B33D07A56F183984DC480164B25E8F67ABEF563D68DB1AA735CE91255C769EBF39264FDE791B63A160F2C007EC0E7968CE0FD3A728DD0AA9737667F7FE62BACE738010568584AC025299BABCA79C5FF002B62D183C081F2292C926AA6019B5E74F585C70A5882F77BD7F0DCEF155E67AA9F5AD6DBAB0CA45B912AE5B8BCDF95F9C6D13D25183C3B1510784B5D859DDBFC7842C9009259C8BDDCD051FCA18E91CD439E3E32FC832EA875D78F0AEA8A565082A220C389200BC83378DF0962F1F824216A98B425206A5209A56848B51D88D2F028F7601259DC74D7D6DEDE2FCD11ECFAE53A919CEBCA80F03C2EA59B022D37EECFA4D8F4C730CDFB49266AD72F2F52A628062405009BDBADBD7A616B143B8717AFA534A55BCE2FC6ABB4F644C228B4FD3329425212B525B485022C2545215E867EEC50B158DC5CF980ACA96A7F94D58576B12DCAF7686EFCEFE2FEF7861CCF3543AA2E3CBB7424C08E8240B7E96B9C4E65B2573B87BC04715E8C0ED41BF87E74324AEA5C9DDAF6D010F119AACEA9DE6D4A4284B1C50A5287849E8933EB6D8E2C404BC0002628049BA451C6CF7FE29BC09C3D406A93434661CF42DE3D4DE0EFE7199660FA9965E5D409212DA5B2916FF58106C2E6479CD8617958EC19708940391FDCEFCFD61C264A87EEAFDEFAE9E75BF5C93A7731AE5A6A334CC5BCAE8A98F12E957C0A35C954784AF88291C3039DE71B4E5CB5292997244C2B70482DC1B1E6CEFCEE6B0FA4C804B936A8D3952BEE94DDBF34ED0720D3ABFE17A572952F3357F2CBCDA1CAB0B7088064B6B489DCF8A3AC61EE1BB3FDE052F198A4774AAA65964B001C7CC0825835361489044C9690C181F37E5B5ED6DEC68DAAD2DDB06B30CD4552065F973D252FA9DA76E1B277EE8A924100DEC3D37C6ABCE72AC8A62E4E19231539D94C951029AA8022AFCAC39435C62CA920B7D093BFA379D21FF2DEC4BB3EC9168ADD539DBD9A6683C4AA64A2A0202FA12DA94D913D3CC6D1883C7F693178D98512B07DCA1569BC605D8FED6069615F2AC4705A48E251A8FEDF6DBBFA74B0A92BF2CC98219C972E672E60C065D1469AB71F8B4951694B6A37B91336E711189C0AE7A92A56348A12471D89157655486FBF4D04D2096B1B0A7E35F4E70F02B7516663FCBA1755C768314DE83C5C200E5B5B0D8C99787078E626601A8AD87224B7BE507784D002454F3DFF003BF28C17A1AB73458733C6DBCAD283FC950A843EA7A7ED4F0A8F0F0C73DEFE987D82ED0C8C220A25484CD5D944A4023A15276FA0A6B0CB1838882B0C3A8377D06FEE90E4D68BD2796A439559877CA489293C66E04DA146DE5E76F2D3119C62B1CAE14E15287A382353CBEBA4302DA17FF34F4BC64ACCB4750A0F754A97DC16061420898DD379E968DEDB61AFFA4637145C2D487B3F3BD29D5C884F84EA3886E28DB0D2FA0B08677B5CE60CA94DE5342DA132027F968317371C49E912461D48ECC82927118863A82E3D5F71EED19083606BA52D4EA012DBFDE1BEB351EA0CC0215983A5A0890D25B084833733C040F59F779CBE0F24C14A1FEDAC4C7A17D1BA9B97BBC38972D44BD9B9FE3DB8863A8CCEBCC8352E0106D0AE9E768BCFBFCB121FE8D216DF28045ED47FF1FC428401AB9E43DFB6D21ADD715557AA754BE01E13711CCEC47C67AE355E4320B1041BD185BEF6B51E8CD180CC5CF41CE3E827813D3E67F3C7C7F8FB3F1B5B481303A608236E0820C104182083041060821553278B88CC6C36C27334F18215777E7F2FD709C119A1004CA80F5FF7FDDB0411B3847F78F97E782083847F78F97E782083847F78F97E78208CD20098333FBEBE78208CB04118A93C51788C64249720381730463DDF9FCBF5C6AE096D76F7D63608529983BDBFC5E0EEFCFE5FAE1512A61B24F913F40605A4CBAAC30DFF003B41DDF9FCBF5C2334F73599F28DCD3C77AFE37AA299A859E14972341527C89B7B78534C9525445E1504988100733FBB4DF082317316B12F0A0CD0A2C420D9DB40E75AE96A562630F2F2E97256BC7CF97228E9EF080E79390FE1C9B788CEB0D5F41A5A8DCA875E6429092A20BA806403C8999DB91E5B418E89D9DECF63332988E3C32CB91562589E4CD476BB53998E3BDB7ED465D97226FE93192D7C214DC2A1663B135DEC6F56AC744BB53F698A9CC94D65794ACA427BE6DD5A0C8BC817FBAF8F48F64FE1AF109532661D8FCAAA81D59CED4D0D5F58F1AF6D3E27634CD992E54E5A9CA83824867A7D7C868D1D42CEF3E5D73CED4D7D4ADE75C5710495120711FF00EA039FE938F42E47D9A9397CB4012C7CA120BA59B9D458372B470CCC3B498DCCE61E352C827576AEEEDEDF788655B952E3EC968294F2CFF9742415711D8F144C0DBED45FE387B9D66E9CA6584259D42A686DE9BDB9C37C265E9C5152E62C39AD7C4EA77BE8D13BC974066F99A5198EA17052D23403810A521329F301493CB68B4CC75AB4CCE958B484A428A967E54D58BDDEE282F5E5D1E9C2A247ED62CDE8DCFF0005DF61128CC7566579553232BD38C349718053595090388923C264893CEE955BEF7182C82762662A6E25C216C509290C96B8A0A9DDC437562D95C201A5E8E7E87E8DA3EF54671A8D0B5A8D73E5F52893E2511C27DE6F1D7A7CEE380ECC4B29042028581671CF47D0F23D2009FD439340AB3F8374A6BB5B940B31CD5A4C2997070AE7C01511E9E5EE1B7A62DB97E59FA67404301C3A0F32E1FC7A50886B3F08B92C5150A3A07F56B6CCFAC40335CD9C4F100BF326401E46F1E9EA316294844A0EA4B3022A2D6FB7D6D1ACB1301AA4802D47AEBA6AE7ECD15DE69995556D4D35252A1E7AB5F2A4B01A6DC713C52012B294A929DC594403060E1862F389387491DE253BD406141B8A8D39DA1E4B06A542B4BFE2C0DADE9170E89EC0F36CD4359BEB157D5E96CE21B252494EF10D906E2D713F7628D8EED580B992A44C2B58B241372E3F75A8EFE778792F800F98F08AB9D69EFDBC76068FF80E9160506459730E180976A6101482810140AD24C9BCC751B462A1986698EC54D96662662D21D9292A003E8598173BDBCE23F30C414B7764177AD2FBD34FAC26A9CF5B7C2D352F29D4A859B014902DD45AC23F1B4E2532F94BC40654AEEF89AF5D28E5A97FB8BBC45A264D591C454403CF9EFCFEED588CB953474A8A87DA4C950920927840BFA83B7BB6DE313B23279666A42D21DEAED762E5C359ADF4899C3A09038B6A6FB721AEDE01A206E664FE6D59F56678F854A8309200927E7D24DBC8624274AC3E15C24A681C00DD69B695F21BCACA93C4C4DB6D9BA69FE3687E7B45505232D57E6F9A8A765292B5309256B77994F0A145423CC7A6F3881C662138C981082FC27E773C2C0D475B579B43A4E1A5862A2036FA9F37A368DBEF0C6BCCF35AD7865BD9FE9E5BC80425CAF765B027FAC77E913CF63CBD063051230C92A54E48091F33548A5A85FF008B18D4A253965060ECCE4539BFD4D1D8C3E9ECB9FAE432FEB5D48595BD25596328E22B3B9471D3AFC3130277D84E1A2FB45DD14FE9C7788018AE8967A588721F97F0D2694A49F99B60E45AF725DABB7D227FA6B4BE41A711DCE95C9425FB7F99A86CD471AAFE206A10AE199EB691888C6F69A64D2518A52E6CA49F965A54A9652F70E92FCC68F4869FA9E0A8FDC054DC17BDDFD37D61FABB4AE7B5EB69DCFB8282957C45A79B7D0070FF0051EE5A5262DFD247BA766927B6B2706152E4600AC1038B89D45BFF005281347F5EB0DE6624CD62A2F7602D7E839B7918E5BCB343E46DC9CE0668F0FB4C2E9D6140F3016AE2927A8E7EB25A623B513F18B213853281B10FAEE3847913A7584DD2F715E7AD21BC6ADC9E914E0C972B69852A05429C21D0E47D8E10EA484D85F86DBF4C2F84918AC6AC199314800B8BD1FA5E9BB585E91B8243B6B786AACD4EF541934AA120CF7083EEFF00869171CE2F8BA60B2247085CC9E8593A294000D615569FE37813C27FBB6D3DF99D8B88630F66398929A3A6AC2763C61F0049B01C6047BA67D7066392E1528044D948D7852A492B6E8AD07F26129F2EC01E2B3062C0BDEC3C284F58DECE8AD61527BD6E914B46F0E3C94C4DAFC4479741F2C44CACC70B97100AB8DA8C0120FE29CC4371289B1DBDFE37E50E88ECD757558E34D332D773757154D39E29E775CD874E91B61E1ED8E1A538EE540A87CB425F42580A78D77D633DD172C41B569FC736BD4B73854741EA36C774A0CB6A00ECE30AEBD0C0F7DFDE30D2767A8C602CA992C1D4254E1EAD40F5DFA467B956FE405FCFDEF18D3F673AA9EE33C54EFF0040AA8A747044EC14ABCF2E9F2C311DA03972BE554C98146DC0A16EA0EA5DDAD6DE3432D40396E61C13CADE31ADEECC756C1229E98EE20D5D34DBCB8E3A6DD646D7792FB6CE2A8586A97496AEE18743E71A80F6FA81F5863ACECF33DA28557B494850F0065C43C6DBCF764C6DCC5F962630DDB01378B8525811C44B8EB7B5EDE87508502035DF51A728F7531F24E3ECFC6C6F9FBBF1C1046CC1046494F14DE2304119777E7F2FD70411B5B40BCDFE5FBFDF4C1046DE04F4F99FCF0410A69C01C51E5F39FCB04288D7C214E085235B9CBDFF008608C100DC03D635E08186C3C8472013B0C1030D87908E7815D3E63F3C1030D87908D8DA157B74E63CF040C058011B3815D3E63F3C10307076B78C668044C8FDFEFF0076C6C2614B2407E2A01D2BEEDB3C359FC5C40006A6F4D05DBC2F5BB346785D385A778A21EF7E9A13A7D99A24E44B44897DE2CF152C6F4366A90DE16AC1C2AE12A4C42374F320D847A794EC6D8D6667327040A182D5616D5DC59CE9EA219CD98BC61328A4A454055A9AF8FA3D1AE212BAB65B6D550B712D21B054A2B206DBEF122DB7218CA32FC57699918696A495020F00DDDADF8262B79AAF0DD9D44CC5CDC5051038F8491FDB56A9B5361E4E2284ED37B7CCA34C5322872F79B72B569752A29503E24881C88E7D7A5F1DAFE1A7C1CC561CF7F8C42A677842871A0B5CEF414F3178F297C56F8BB88CD8FE972F9C70DDC128265AC8E236FED22ED53D4F21E74EBFED6732D575AEA33079F4B4E2D413C2EAC24024C084900F291BEF8F567677B1785C0703E193403FB6D4D4355F937DE3CEF8CED26678B2A13B17326715C9528D198EBEF6D62A879229525C2BE2454DD3C4789422E7724CDFD79C6F8EA38746130E84A1084CB54B152183BDBEBAF9B522BB89526629D63BC7724AAAE75F07EB42F7B99664398E67529552214585195A9426C62FE2DA2F61CBCED8431D9BA2524A1243B338D7C00BD9CD8BF488C561D0E78500381E0C5E963EA4DA2DCA4CA74F69BA32FD429B5E6CE241610BBF8C0B813206FEE33EFE7B99CCC466B8860925292DC4347EBD3F11A80A940949290A34BD750EEDE8FB8AB18AFF0039D4F9AD71719CD5459A3121AE05048206D6410761F9626F26CB1485238D1C5C2DA37D07DD8B6D7D54B529DCBBFF0098AD6A3306D0A78D2BDC2DA2EA59333EB26E3DF7E5E7D37098796108050EEC0066AF27B0FBEF184A52028ECCE2BE15F637DC57F9967F975538B69F05D7A4C2C15244DEE427A799F5107162C2C9320278260969B94B03CDF88DB9D7F11BF100CC1D85DDBAE95DE20D9AE6C9A3E04345556F5448A6691C454D907621326E0F38F888C482F1B85920AA64C4A5491F35871B3B16D0D05BEF0EA414AA93038A54BB0A6C74F3076898689EC7F5BEB379198662E9CBF29242D69742012DF41C5C2A88E979337E543CEBB628904C994388A9C24A6AFB59FD5857A8859425004200E26673D76FA3116F18EC9E53A6744E8869C672A6587B30E148AE79C4F7AA2B47D828EF02B809BC94113EB8A5946619C4C98B98552D0B6E1AD3CC1F4FE59152411F2B12474AECE35E7EC21CCB54B8E9534D921A1221321201E8040F2DAFD2F187527B30A92F38CD2B53394B17D2BBBC47AA5CD24A9C9074B54F4A5BA6E6230E6614892A52DE879C32DB241FE6904C82B261113CFCF98C4B610253FECAA504B515314038E6C4574FE630241511C639EF7DEBE875E5766AACD2ABBC08711F524A8C02DA7EB5C5B6E5B0787DE47BB94903849201252B53514070D7C286B6E8FCCA889291FDAC5C31A13AF5F752F1B5BA3754D97EADF729694C71250C29F5D6CEC0A100AD920F2816E5D62F1799F00A2824070EFE55EB4AD4F8C3A4100304D5B7BFB7261D6974C67999B61DC932D4E9BCBC5D79DAD48A979C4F350A273F9A9BC8E1099FC2B589CD0AE67019C78D40F0B3905AB734AB0D6B7D62465CE64BB0005FC6CFA9DE9D00892E4FA1320749152E556A7CDC91DD553A8A8A1692B06F2D2C06A395C006E7D21A662679F9C4C082788F0F10268FA82F56AB55F90A35C5CD247CA4B52A2D714B7B689F2321ACC9A9C9CE730A6CA68801C148C32C3EE2D16F0778C8E3498804933798C3246266E20A97294B98A059414E90347A96363E50C8CC58001554BF51E2E6EDD3C6191FCC743658A2FAF2071E7D5766B5558F2FBE527ED1EE1455C107900266061412316B981427F0CBB997C03415F17A6BE75867366926A493B1A37D6BE5D06ADAE76859DD52CD2E474EE32C1F0A51F538001DA5C53408B79F9CE1C7E8A42D7C5318AE80FCC2E07FC41EB7DED0D56B58D68795AD478C469BD61A865EA97954284DCB86A12B94A8CCF76560A607288EBC861F4A380C229A64A0A245B878812D6259BEFB5A149014A075B6B56D287EBF57785AD681A3A24F7B996A843AB172C7D5D33E63882C9E5D27A635FD58529A5E5E9087A2DC55F56E17047DC690B306BD7663F58D4F37A3E9212FE567315A6036EA5F71A8237242779E876BF5BE674DC4BBC8986504B12909041A6ED46B0F3E990A2976D7F98DADEA6CA6800FE1F9421881E12A577845EFF6C198C20BC562D48E05AE62C30B122BEAD56661F88C0252EC5ADB69E11B5DED033152404229DB4806006184904ED278413EFDADCF19C26055885BB4D26E5E62C8A6C0F8EF734A46C662CB39B72F7688C663ABF50D5CF7550100FF006F0276EB045C0E87160C3652400E8A0DEA7CEFCADAD76844A1C92F53CBD2F11A39FE76C294AABA97561CFB1C2E28011B93C26FE73EEC4B48CA9142A969F14026FD2C7E96178C701B7153DB307AC267351D6F279E33BAB8D667DE5437F8FBB133232E9691492936B20680727209F08CF07FDC7FC5B5EBE7E6DD51A96BC1003EFA45FECBAE0DEF78541D8753E98CE232993359E4A054D4A053500B03BD396D0DE70502DC47A837B6A0BFAEDA426FF1357EDF58A983FF00EB391FFF00DE18AB2295A4A4D1EC903EC5E1100837BB6F7D353E821C6875A673421C55357A9A0A8E34BC03DC7D000E93C31B1E1DFDD76537B3C95824CBE1356091C3BECC096F5F187D2DC3B726A3FBFAD63DF2C7C938FB371B1B04CC09DBF1C1046D83D0FC0E08214D3A24AA645872C1042AEEFCFE5FAE08233420099501EBFEFF00BB608236708FEF1F2FCF04119A4013041DBF1F3C10A4BD7C3EF19608523058262013BFE18208D707A1F81C1046E6904CCDB6DC608236F77E7F2FD70411B9A6F7B13B6C0FE1FBBE0823670A7A7CCFE782063B462B4C0040317F4E5CF12783C3226254A590E03B1D99CF4FBEF1B15A1287203D6A5B7E77E5E20F2D720EC715ACD7309D2667732C1370C1EA3766353CADBECC82D7C454B244B7724D9AE69AB72F1A3430E7B9CB792532B3075F69BA7610A53C95BA8471003601441277DA7A461FF66BB298EED06253C4898CA5025D24DC87D85B67B58C577B53DB7CAB20C24C509F2FBCE134E201884F22EDCEEDE31D13ED87DA357982DFCA74D3DC05054DAD4DAE4133133B6F3CCF3DB6C7B47E1C7C2C465E9933A7CB0AA24974D281ECDD5B6F28F10F6FBE2F62F37C54CC34998A12F8949052A2C41A587837956E7A559EEA3ACAF792F56BCE3B56A52D49F1120124F99178DBEF818F5065B94C8C3CB0992896942000484A68E3C398AFD8C70DCD312A528CF99338D4BA91B390F7353CB7F186A6AAA9EA15C35C897366C4493681B0FD70AE33BBC2A7E42900BD38478DF9FBDA253882A62E41A3EADCDC8736DFF1129C934557672B5D5BEB0CE5F49C2A6C3D08E34AA09E1E382A8E71276C52F1D9BA04D1292BF9A61200487A8A55AC5FA5BA43D94492EC40D79FDA9A743D224798EA7CB74ED31A1CB5082F2014A9420C9D89BFCAF78E57C272F018AC5BAC9514962915A0EAEEC40D7587899695330E44F9F9D5F97845319CEA4556540AA75D5F7CC9596D209892798109DA3E4479DBF22ECED38E6A6FA9FE7CBAF9C32C64A0804B8A55F7045075DFAF3222199A6A4AECCC776FA825B48804285E0C72BFEFAE2DB2B289723F6A40DEC29EC57C623A2135D9A06F853DF453890F80A92676100C9B9E585D4A124306A74FBF88A6D56104194E99CE75555213A6A996BA752A1E75C050009BDD71B78B9D8FA623F179BCBC3A0AA6CC609D4338D2C1DFEF4BC0C5DB972F4F0EAFA6AFD83D3DD96699D28DA731CE386B33480B534A0A506D62E76E24804FEED8E6FDA1CEF1989983F4A261924B05071C41C034D81E84D2052CCAB1A9049E5F987FCE353D45731F51CBD69CBD840E1086C253316004705F6DFAF5DE4B26C14B992C623128E298402AE22FA9D0F3E8EC291A4B9CB5900A80E47ADDEFABBF5D6B1057DAAD4142DD54C932E158973E26F1D3D39E2E127F4E10AEE40240B04D88FCF94498410905B47B83F48E5450F2785082A7369402A9923A0373F0BFBF090C5094B69DF225E8E740357341BDBA438952C077B6A3917B03F7685997E83CCB3B2B742D6865882E305B23BD0AD8070C14111CB103DA1CDB0D2912CC85A4294E15C2DE16D0DFA878526619203A6E0BD7C373FCDA2C3C9B485365E90DA1B144BB0571A7EB7C645CDD5C404F381CF7B038A87FACAA624852DC0DEFE8DCF4A8686531205856E096F13A0B023A72894B191A288AAA29D4CE5F605ECC9D4B6E848022452AFC37E612075386989C699E82953AC2AC904A49634750723EF6A3420B5F097E26167BB72A36BB7ABBC20ADCF322A074394F5DFC57334EF56DB2A65A4A87FF00D327F967680784C917C212D6A5A12E8EED350A415711FF00C9891E6618AF1252A3F3120D8F3E81F5BBD8D7AB4BFA8B5B67A453E4C94D2251E1A851A569B35A954F004A948496F807349133279E159587C3021641F92A3E6248772410E7D6DE91B4AC42E6FCA4BBD09B7986B071E7CE1C29346D406CD5EA6CC4E5CB2389414B35416664C2428813BC45B688C2E7109207E8E477CB7A86EED88717342D537F285CA080E4814EACE396AE6A368E10CE8FA55ADC34E3367198EEEA0A96D06CC5CF74652A98DA396FB61E0C3E2A709678BF4C43F12182C2B6E41BD2EE690CA6AAB51C6FB16B015BFBD21054F6888649A4A26996DAFB01B14CDF108E5DE16C1B0E7EFC38465120A84C582B9A2A5414A0FCDB88016FCDC43798B2C00A0AD3F9F1FBDDC98FD7E7AEB890B4B8AA253A09E14ACB9F58E920186E04F4EBCED33232E4CCE10A008A5581296A8EA793F28CC87AB12051F9EE39535F2D621B54F55AD7DE2E8DC75333DF7D6942DC8844CFBA3711CF1228CAF0FC410141E8FF002B5090FE7CE1CC694661510A4D354164A7EDA548E38E6002ADBA6F187A32492082A4A549558BD4EFF7ABDC068C804D8437D4E635C8E22B7839E7C294CFC36FDF538712F21C22D8AC01BFCA0D43B506DEAD625A33C2ADBD47E79C34AEB1FA8214E2CB6048179E299F75FA1F5DF1212B27C361FF00E90E27B800A6A7ADEA6FE42321075207AC6835A968FF00F33B5A26D7F203F7BE1F232F4B8694F4FE6FAE8EF4D2F19EEF9FA7F31A9CCE5B48852FBCE9CF879EF73FB89C3B46014689484B3D680927AB7BDF4C141D0BF266FBC373B9E20589BF9188F4117F3C3A4E015A3807C7E8FF00568D82030715D6BF83086A73C64F0F2DF73F98E71F2F3C64E14CA7E21C43A1F03A73F386F3D0281BA1FA7DE879C26FE36D7EFF00DB1B230E85D801BD0D3D457942299628D53F4E7B7D7CE1155E6297D4DAC37C696E4ABC653131161138728C14BAA480E450B061A6E77DF485D2909622E35FE0BED1F4AFDDF9FCBF5C7C3D8FB350A69D20154C1B6E47CB0410AA0741F018208E426761EB10304119702BA7CC7E78208D2EA488991EFF00C8FAE0823540F3F89FCF0411B5A493C51276DCFAF53821497AF87DE37702BA7CC7E78214850C8202A45E7F7F760823760823058262394E08230E0574F98FCF0410AE99E2C25C4981C7B6C76F7E08238642DC778B913E7F18FDDB98112100D0C10E75CE328A64B40A42DC163D001279FE9F3185A54C9C169972D2A5719E12DA3F423476F6D198E988920CE5CC094A0124380030D5EFB6B5DAD14F6ADED0324D134350BCC6A9B2FF000ACA47109E20091201F302637F763A9F657E1A4ECFE6CB9864F105104BA4D053537AF90DA388F6EFE2F60F29C34DC348988E209525D2AA82DF5372C36778F37FB52EDA730D5D990CBDB7DD4654A5BA16A43CA40E124DCF0907D24DBEFF0052765BE1AE1F2244B5AA4A1C00E38439FABD5BF378F11F69FB779B67D8A9AD3A6196A52BFB8904134A3B3331D5ECEF1D73AD71BA7AC2CD02D4B43A654A528A8C912492A9BDF69F21D71D6B0988952909932E58433024306601BAD3EFB456D05253C53140CCE65C83A53EF5EAD182692AEA1F6E9D8A75ADF74F85E825283CC9E569E640B61DE2330FD22490BBD4D852BA02C75F7687C526629557297B6EE6FF005DE2CBC9B4AE5F92B69AFD46B4BEEA405A1361C24DC02127D224408E4315AC5E613F1A0A6529552012D41E7B8EBADE13485020B11EF5DBDEB0DFAC7560AF6A8E9A99D0D52520743286886C90409E32D9055B082A07CBCF6CB3294AA719AA492B9853DE12E6DCAAD7D186FBC3C97354E012C2BA7E3715F6D14B66B9A13C5078B7B9373E649FDF3C752CB72D421090120160E48B5B97D34D9A1F4BC400003403526AF567FB115F5881E659C2DB5A5B0986AA09E35822101331F7CF9F438B1A244A928E3550A050333E9CBDF3108E366A6600010790343671A9FB38A188DF05754D4A58CB1876B3BD304A38A1324749EBD45BCEF88FC663A5A41248480EE5DBF0FF009ABBD21845CBA5BB17A6AA6C66BA81EE1202568A55133782A100824F3BA76F953331CE809C9952419855C4E412C9E6EF5EAFF48D92970E4B6DEF6FE768B6E9DDA5C9694D164686E97812132128055C22665404FC639ED0045AF0E714A0BC4BAB54A41347E94DB9BC0542A1346A3EBA1FC73F1778A5566B98A56EA89E22A27BC2A215DE003FA649023CA36DCE25F0D82C2A929EF509734402053E971CC5793426651984FAF878F2FCC46DF759AA5296E2BB87A6787C44ABDC0817BC5AE2679E159981E075CA514A459AA29BD75236D2309C32829CDC10C351E2FCF67B33C6DCBB21D4BA96A053E5D42EAE92988151532521295DD2785513D6C77107081CEF0D97527A93C6A1F28A39005B97E4F9484B2A0068C0737A1B036BEDD18068BDF4FF0066F4D94B287AB2A43EF708516D4DFD9205E4FBBE1EFC513B41DAC18A131121010CE1252A724D6CD6D2947E7787489812CF524073B7DBF1CA251515D4B9636942DF699660CD3252826A026D0A5A6EDC4089B99E56C51309371B8A5CC54D52C8D0173AD3F716F768C4EC40018AC33073E0EEC1EA3F976888661ACBBC7052E4B953944FA8F087D3C5549715D7EC94A77F75F78C49CB90B47EF5D4E85874B9F2A93EB0C66E252A040A91A35B7FA56BE4EF0997A775167686DDCFF34148C0054C84F04BC93B8521B50298062E01331C8E1DC941E258BA92DC418B07B56C4977FE61929455521817A7B25D8C6E4651A5F20477C809ABAB45C28A8F89436B1240F4B6DEEC3B4380AE24B59CDC1F2BEAEFB97B3C335CB2493663CCDECCFB7DEB0CB5FDA03ABE063BB4502192A0D77684A8B808DC94266D1B9263961C61A5212A2AE1AAD892A2FC4CE6C6829D1FC61690952487B569E0FF007F3A4476AB3CCC3300422A1E7A6E3C0A2083E57B795A399E92885A1218048E6004BFA0F6E6B0E88704421629B397B8BB969E215B80D2A075984FC663A6D8593894A58A949049A02A0391D9EF5DA1A2C5880799F76A7BD96A348EA7ADF137401C0AFEF521A37BFF005011F1E9B6379998C8921D4B0280923E61E2078D89F48414973415EB7E5D7C9F4736507B35D66E82AFA8B4C81713594EAE29F22AF0FA19F99C309BDA495288EE54B26AEE950D6A2A069EE90ACA414F13EE05F6FC74DE13AFB32D6A1265A6B9C4D5306DCFFACFC3D631B48ED6A9FE67045CF09FB06DFF008061686DA9ECCB5E0134CC30491E33F58A69B6DBA89E5BCF5E789893DB293F2F7814787604B1A5E9F53CDE320136D39C42B37D05DA432543F8621F1D5350C73DAC93CFD7A62730BDADC3AFF6A08D6C4539B80EFAF93504655C563FE6F5880E69956B1C9C4E71953F4C854F741A9A82E017325A49E083D627979CF60FB4322791C4532CBDCA833317E47CB58524A544579B167EBB72FAF38ADB33D5154DB8A61541534E663BD5B6EA408E67893005A7A40C4F49CC654C03854950701C11A16D0DE90B777CFD3DFDE3450EA4ABA54BCAE36EB52EC120B886D54D133209255363FBB4ACA5A2714926DA3DFAF21A8F1A46021E8EC45FECDD6BE4CD0DF53AA5A2E052B304A164925908E28B1B4881899932524710A00185CBEFFCEAF19EEF9FA7BF6758E06A34BD1C46020595F678A7CA6DF87C2313F00A981D20A8867715F0D3A8FC468A92E0907E63EFDB8F0DF7379EB53056224733CEDCE2DB73C248CB6705070BA5C70B7DEDD5B4F04BBB0356D5ED5DFF00970DCE36399D34AE14858F71BF5BDFA75DFD2D87C9C14C4B7C849E63D2DFC7D6125A824B5CF2000F478FAA9EEFCFE5FAE3E0C89885332856DA7D63ECDF02B6F51F98C80099922FD6DB7BFCF1BC60822E232C6C124D40F51188DCD0078A481B6FBF3C1C0A360FE519009B08DBC03FB87EFDF80A14039040E719E056DEA3F3182DB248893EEFD7CB1AC60822E230EE8F9FFD27F3C1188CD08899313D446DEA7CF046E8203BEB1B3801D953EEFD704280836AC66941131267CB1A95A45D43CE36E151D0FD3EB19411B823DD8C7788FF00908D84B59B249E958CDB4154F84988D813F763066CB01CAC010195305D0A1D4465C09E9F7FE784FF005521DBBC0EEDEF9467B998CFC26CF63F86F568DCCD1FD60D85926E7D6379F38C2C852564041E27DBDFBB5DA135BA012A0C05CB8A7BA7B11CD77065ECA96A504800995111600EE4C7EA4FBE42565B8C9DFF004E4A95AD219AF1F8496FC7392967B91A7F98EB476B7DB153E92A0094D436AAA7D2E86381D4A8A0A78B7292637B131F9F67F873F0FE766EAEF71521480820FCC9A1AF303AEBBD75F377C6BF8943B392D387C24CE3EFB8904A14CD60F404DD8F851A3CD6D53DA1675ADEBEA55985538A602D5C03BCB419E40C72B4F9EF79F54F66F274E46512D12010800060D6D682BEF48F1AE6ABC4F6856AC54CC4948592B292490C4BB5FD05EF15AF7DC4AA8654B01282384A884CC9E52798F2F8F3EA32387152871A780B3049D5FE9A73BC56A64D97820650471173F37A3D8D76D1C561E726D3AFE78529A00A2A4AA54E14F840DCF88C8137BCED26D338AF669265E05E677A01A9617BD07F97F1686D2A5CC9F30289294B82CFA03BD2EFA8AD4B88B5159964FA6281140F34DBB5E5252B7400A2D91CC403FBB7962030866E6B88A4D644BB23877B5F7D5BCE2566995C094801C0152CFF004D856DB6F150EA1CF2BDE5AD4DBCA758519093E1E117D81DBE5CEC062E383C9815255C3517A7959BF3EB0C968490F46FAECDFC6915D3F52B6CAD6A7788AFFA788908F7DFCFA4F4C5AF0F9726500B4A78599C357D456BD4D4EB0C660208AD9EBE5B7BBC44731AE5A8A9216093602428C911D66E64587CF12273097857723E5624BB6B66D7EFD61A4C9F32A00B8A372BD6FE2F4872D2DA2B36D60BA8525B5B34148506A9C790503856411C05613C5707EC123699C43E65DA790E995DE00A502129152E342D41E3D442B875A9555BB356BEDF4E757768BD727674AE85A72CE5F4E8AEADE185A8A54A8541132A0A1FBE5B629F9862B158E70A52A54B770805F883BBD08EAD57B43C0A480183B863EEB42FEDA1AAB353FD72A3BFEF14C3927829E0A5279401013B6E7CF09CA4CC4942425C02439AFAD75FC35DF5AA8EE4FAFE3DF266CADAC76B104BCA2CA87D9E19326D13C302F6F8F4BE2C384402DC4013D767DE9716AF8B46C25AD4EC934FE3F30C14ECE735CFA29DB438E2CAA28CB692BE393E2E220787CB8FA88E785F1624A071F7C9414876240A6947AB723E0454BCC2CB493FEE029E166D8F503F3CF78BD7487640F5425ACCF57114ED8E15A10A2078409B8491D472F238A4E69DB43210BC3E0BFDD98974958B0D19CB8F5B3F8AF31284915001A33EBB7E75AD79DB5519CE41A529914997A986587070385084AD4F706D300A9245BF7BF3DC5CFC4E6B34CD993162612E0D404BF205B5FA88426AD09E24A0B00C431BB53C3A52FD1ABCAECF755672EA98D33951553384872AD4EA510956EA09700279EC76E6409C187CA4E1D499D3E695A49FDBD2DA9F01CAA223D731492CEFCA94FA78B8077D192A34C657918359AA33A554D4D6F89597776B2029024A038824279C9116E9B62C38752E6BCB918701219A7050A3EA451F66B5219E226A8872A2FF00F115FCEFF4D2353DABFEA08EE34BE5CD503401497DC08A852845C80EA54A13C883387C32844DFF00F1534CF208524A7E4E12EE47CACFB3F2A43718850601241D5C3BF990D406B4B7288EAEBAB6B5C52FBAA87AB1E3FCC7077894715F8785221099F281D79E1DAA4CA4242414A5800EE1CB6875A59FAD21DCB3C572DD747DFC79D39011CB1A3B51D72C3B54E7D5E9946656E249E1DF6E20498FF6DF0D57325214521D6694009F221F7143B3C394CA04124D34A375D625D43A6345E5A92739A94D7D42C0E0400A4F7253F6AE92649FF6C349C9C62D40CB965080CCA05DC11701891EEF48DD4254A624B93BFDAB6DDC79C66EE6DA53290A19765887B876F11B40B5940FC79EC71B0958C23F7AAB764F9DBEDAD79424A992C9141C989FC81A359B4DA1B9CED26B18F065CC3396255FF10961A7FBE036FB48053C3E5136C61596F7E52A9C998BE1FDACA2867DD8B79DA1B4C9C12A74A80045880D66D8F95A962D467A9D6F9B56821CAA0B077E06D2D5FA0E100EFD0751B0C4861F06245449240B12EAA6E5DDFC4FAD61B4C9BC4CE5B71CB414AB36F0C1539C562883F597999076716BE23D202A047291D6713123264E3D24AD212CDFD8C6B6FF0088F7717856428105B96B777A8F7F58685E6F5C3C23317C0BF35106E660150F2DBCB0F13D96929D52C030A0D7D9EB587108DDCE733490A4662FA60D812BF17FEE3F327F2772BB3126951FF88DA87E95A1DE08554FAB7356665E5BC446E77BDE64FEBBF2C3E4767F0C3FB80074E11E9E3AD057782143BDA066EC94F030CF0ABFE221D69977BC03A7789570C738009E588DCCB23932F80A10B9A03F094A9496A87B1A8F7BC3DC37100588ADC10EC2A3DB11AF8A0ABD47A5F3F6CB1A934D53BC14005B88525926F04CB4DC8F71F7E12C261B31944A70F3978643060A495DABA97676FA43A4A52E4A92EE46BC87DC37214A88AC353F62DD9DEAC4A5CD1B50AD3158D859AA696E3D509AD5ACF8002E2C25AE0DA475BF95832FCCF35CB26138E7C64B531130327BA019CF0A7F7120BB35348DF825ABFED3B56BF41AF5D39C75EB56F60BDA26960E5751D02B35A16E562A1A79B512912A2AE04952AE22DBFDE7A0655DA9CAB14B4484E27866D1D2B4292DCB89403973F50EC29A2A42C00A6A6A5C1E761AB5F4B5A28B7F5156B6EB94954C3F49514AAE1710F36B6C12491652C242A083B480778C752C85781C4820CE96554003A6A497FC579EB68C77547D2BA8F02D7B5E95B8B18D88D44A3E12E0E5042C48DAD63F95F9C62D072C94A0E809376602BE156EA2908AE592E521DAE68F6F03B721E50E14F9EB8BE2FE6131037FBE26E6F724EDE78417964A480C815059CBB74DFF00311D365AAEC4B3BEF5ADAA63EC831F9C095839AE5C94B333823C0398FB38AC4CB510CCF5F1F21D6343DBA6F11CEFCE7CFCBD7CF1212A470DDCEC1F53D2E3EFA4604CE21FB5C0BBF875DE3142547727DE6607E7FBEB87F2C0003D8D4B6DA0FE3AB460254A2A60FC8066E9F9FBDD634024102794F9FEFA7973BE10C4E255254E84710E9CABE95D3988DD0A4CB07BC152D5351E819AF5F02446DC3318C5AE851D5F6D49A563071491F2A405528C697DDCB78C641D71BFB09E2264F5836827FD8FA1C2A898482E1F4D00FA7A69082E7CCAB21C1079D79DB71B5F48DC871F7265C089882426D7F4F891F3C2A99214FC47A06D2EE7DFDA1A2B158B144C9596772029F968C0F58CDC436803EB2A352493C3C1E1088899E106645EE46C71198FC4CDC2377492B7BB75E9CFA74710BE19626907123B903FE619EFAD350DE3AC6D645393C2867879F89447DF1B7C4619CA9D8CC45449587E4EF7BBB7430F26627052407C42001B2853F9FCC294B9C0084A1A8E654E206DCE144193CEE3E7897C2E498FC5B34B5D6C58B87FAB577E750D0CE676932CC3FEEC44B2D562A039EFECD0D210D566F9753A66AEA2999817979B047FEEE53EEF38C5870DD89C74D01C2C9BBF09200AF27B74F5864AEDE64F2B8BFF009892C3750BD3737F43B558B4AB5C69ACB829F39E5236C27FE38E26D731F641F11208EA089838964FC32CC316C89689C566C02155BBD746DABAF48AF66BF15F2BC17FD39929628E42D34F00F7E5CB9C305476AFD9F38E2AA17A96910DA264909827CC71016B8B7E786B3FE10E6F2CA4AA5CE06A482953EFD6A3C7AC42FF00F7D39714F0F1A050D5C1D1FD3760ED788F7FF882D0D48E3C8A0AD6F306CD9C711C490D948812448215D2D389AC97E1C63A4CD48992D65881F32496B55989EBBF368AA673F19B0BC0AE05205C82140BE87974AF2DA3ADFDB07B4AB6F52BD4990BA12A712A49295410152362266F8F41F63FE1FC996B44CC4CAEF08E160A4B01CACCC3C79C70BED1FC68524CC12A6F0B3D44C2D63A3F414DABCBCFFCEF3FCD7397AA2B739AE71D6DC512DB4A595589364C28913E5BF28BE3D1990F67F098342448C3A50081600585EC037D9F78E19DA2ED8AFB5530AA6CCEF382D5048E757A121FA446DB63EAE3EB617DCB0B3E14195151260EE64413CA712F88561B08E1494B8B9A0B7E39379C57933A620325440E4FF9891E53A1EB33CA962B2B12B6B2C2AE25386521494FFD244907E26F8879D9F4A48299412E91400F09D79FF24E8F08A997FBAAFAFBF38B0F31CF69B49D28CB321E05B65252E2C70C8B4925464CFBE397AC28C2E23362672F8B8DFE506A05480D56B35852F405A3604A1D293F2D35F3A0714B6A08D6292CD754B85F7B825750EAAE5478BAF5902DD395C8E96DECEF6695862A993430353A3E9FE29C8B184A612E9726A4DC935BF9DEB110ADCEDD434B35EB0804184FAFA5CFBEDE5B1C5C026560EB4E11577DBEDE0D5D85352A2431F7AFB6886D353E77A82BBEAFA769DDA94A963BF6FC412B04D8F78A10809DCF5DB0D713DA0C3006A904023D8170DAE8046840343EFF00117C699ECC74FE4C84669AC1D0FD7405A3282A50E1501201750608363703F3A263B158BCCE7AA5E1507BA3FF00F7014CDD13AB9A5EAE0BDE0EE65A43962A06DBBEAED421B6D5EF589466BAAA99A63EA8CA114F428494D3D13294A14DA62FC4EA1216E4DC8E2923118325C661A72A6F0AE6AA690EAA96B58924797D291A9412C123A803D77373BF9C578BCD09A82AA263BB0A2495384A84F33E3F3F772EA7167CBF07C491DFB020390696DF61B579428896430218DCBFA0FE34FAF0FB88AE537F5B6D55552927B84B28E1851201E22D0215CB7B731E52AB460E4310B42529152549714AD1DEEE000C6E3943A97C23E635E16A351F4DFC9A2CCD23D946A4D45C35956A19665A98510E841251B11E320FC2F7C52B38ED4E1702BEEE5AF8D6E78528048A740CFCDC561F4B5A58D0067AD3DD7DEA62D166AB44F674DBC8A453559982C27EB0BE12EA82D03C3C09855CFF00A76E722D8A74FCD7139CCD69AB5CA969B24122EEE0B16AEBE70D3173C24012C877AB6E0D3968FCFE91F7B38ED0FB415919165AA4652930BA871C45284B60DC8438104C01CBE7CD354CCBB0491DE7F796763314EF42400E2FAEDD623BBC98B3FBAB7BB7ADF7B56B4B8829F24C8F272EA733AE39AE6C882BA5571A514CB1BA439250B0A33245875BC61696EB5132E5F04A1C244CA7CCFCB46D7534B426EE4B9BD4B9277AB79C32661AD2B985FD4A887F0A4A894A03480F95721240913205E636C3E3292A6E3F99BCBA37DC3460DCEBCF78D74BA7758E7A7BF790A7583E245538529E049BCF02BE7F773C615899520F095849D921CF90B426B524508735A5A9AD6D1236B22D3F91242F3CCCD1595200229D0D91067ECCB648DCC5F975C2B2E6E266B8949212A3498E4335D81A9A381BDE13EF24A48AFCF5F958DC73B56953C9A0A8D5F4F449EEF2ECB9B6985C84AC84ACAC0D89E24120C7291CF0F519799BF3622615ABFB5BE5D2AE030F5AE86D185620243A52CF76D2AE3D75E8394305767B51988216A5B73C924A449F48E47A5CFC04DE1B052E526890ECD50EFE27C06BE702B16433DCF36BFBEA74148634D3A5B2A529C528B907C4A2A889E64902797AF4BE1EA6420B02905BC00F0B7A13F66988C4296C1D9AD57EB7D3ABFD63538844C48EB78FD9F761512258B2436C403FE39D3486DDEAFF00E47D863E7FE1A113E1B000253CE0C739F3FF006E5CB0E65C941A8961B9900D76A59C6BD631DE2DCB93B54BBEFD3FC6D0DEB2DC1F10E8449FDFAE1C8C3A4DE5B1AE83F0DA535AB41C6ADFD0437D43EDB407881E2917E51B6FC8003CFD30F644874B24330D8B1A9D87D07D1A1F609D8EDA7ADF43BEF414840AAE6047119236836FC7CA77FC30E53875357C6A47A53D6EC224211BD5CD9E102204FEC4CFCFCF0B4B9452E2DB6BEF5D6086F5D6A0837F75BF7E779F4C29C0DFDCD6B0FE75B4109975295F0C19DC99B812622DD630EA54A4A920A98DC5439F571D4DE1594A29762D6FBC2571D4926C24F97972E60FAC5F0B1932DAA81AD424026BEA7CCC2BC6ADFD07E211FF0011629DE6E9DC42BFCC980B42949E0E1BC9281CC91F9E18CC934B50BB16707CE81AB4EA233C6AA9E2AF415F187D4EAED47A78368CBD62AB2E77FE221D0878047310EF11DA7CFF00185C56592F10A4AA623E641252504A087D8A4A49F41F58D84D98971C47C61AB54E97ECC7B4EA7A56338A5628338752E019836853629DD588054868210BE251FEA369EB87582999D65E5588C32A64D91218A6471F0950D7E62788F09FC757D84026FEE5313AFAB01D7F160F1D27ED53D9D759766CF2F36A243B9CE975A8B89CD18BF76DEE3F92D95AAD2522676338EB1D8EF8872B19325E127AB827A084AE52D4C52FCD4CEE7F1AC3A9984E1142E0DB571A9FB5E28C7739532D06E83892572971C7014294A4DA0A1705252AF8F3E98EF3844E17152FF51316821829297147B9A1ABF36AF230DD58628F95497357D497059BD2AC07578FB7CC7E6CC4E4005806DE9E2D43E61ED1F5CE5E196E2E583391BB3D89F01EB189415DC49E1DE01547AC6D84578800B685FC391A3FA6FA343D44934228055B7F13B356362131629B799223F3FC30DCE2175E10E2A3416F0AF41E70F654B48AA9403914E7A3FADF468DE4445EE7974FDDFE18DE562012CB6E840F1041FAFF00889191946171B59D8844A61476AED7352DE4238F3E5D712386C32710C10872A346035F27EBEA4D21A63301966041271B2CF0D7F7245B9397B338D8E91C8AC66990B5B8F32DA40995B8DA66378E2509F77CF6C58A47661738A7E457CC47ED4151F161E1E02D57A8637B5B93E59C5C58892AE1B82A4876D9EDE1BE9101CFFB54D1790717F13AFA747083C5C2F24ED7BF02AF37FC2716AC17C33C7E2D295CB9334BEBC2A1434F6C7CB4A9E33E3664181E249321D3AF120BB5F715B6AF14EE7FED67A03254A5392BADD638B2A0F82B578236FB522FD131B62F9D9DF8178CCC4A8E264A900311C697E2D2C5A9CEE5EBA472FED77C6FC1E62C9CB9694B38265A83DF97DFD228FD4FED9B50AE2FE18C84CCC70A84011623C3CB6BF3E78E9584FE9F644A62A4A69FF60150068FCBED531C8B31F8AF8E524A53316EA06CA3A740E39741B98A473AF6B2D7B9BAD28A2A97691B4157111C278E6C394DADB7588316B4E0BE0C61B0801EED0786E784333BB1D0F98BF8473ACD7E25E6CBE2E19B32AECCA50B31F37AEE29D22BECD3B5DD679E89ABD4552C71CCF0855A6DFD2A1E405B6F3C4E23E1FE1B0A18C943501748E5C9E8056FF68E73987C45CFB895C3327D4B8F995D75A0FA72885D6EA6D4C1B729D8CFAA6BDBACBBFC4B71B0D04191BAAFC57DA448B8C5D7B3BD9BCAF0C952E7C89448A25D209D41D1DBD3D1F4CABB519CE68A3DFCD9A18B3A8ABA01567FAB6950CD543459FEA47539551D6562005CBAE77CEF0113C46545511CB78E90621E67392647264AA74C44A4B876E104D4D0301ABD9BF02D12F178E58613D6FBB9A9A69E7ADFC1EE845651E87C9D1943657519854208AA70BAA708524784924A80927918B6E314BC176770D8C9CB9F2E4A65C804143A402A72C6E90430A9603D6AD71A718A4979AA73D69ADDD9BADBA45479857ADFAA5AEA1D212B55815710B93CE6DBFB8822778B8E03249320829480C050003425A8C683D691CFF34CB71B3CA8A96A2E6A2A5A9422F46DC68613AB2B26A29AAD4FA9E4492DB224F1156D10542248E5CB61CE4A7636560E5AA5B04101B4D68EE7F36342C28865597CEC1A9466125CB80797234F5BF568B0B29D2CAA85B59AEA43F56CA5B1C4DB3CCC0B4A130BFB4049239913BCD1F34C67EA94A9723894B07F68762F5FDD7B7E0C5859EB615E6DEC96F3DA156A2D76A4538C9F2C4258CB784A68DD109242478CDC0572DC993CAF7C43E1B27C54D9FC650A01452E6AC7566B060F517D235AB004BB453798E7EF309729D0B53AF2EE5464D899373236B833E57DF1D4320CB5324244C484877A803C6BEDBC6088356E6FFCD652DB6B5D4051EF42413727C26D3F7C7AED8B6AE7C8C2A56164310024380CC2BE06CF616A54C68BE11C240735706DEF5D45625394F66D9D6B071AAFA9596689052B50721129064C85149881EFF7E2979E66B2427BB0B20A8909094953D6CE079D830D2130926C29BFDA2EAA2CC720D194472AC9E95B4D6B8808ADCC4242CD3140012784A55C7C664784CFBC629333078A9F3828A95C176F9AA0D6F46D3D01B4093C229E66FAD7AD621398E64E54BAA71D756F8513FF00C4AF6E63F9009B0FB3616126D8B5E592C4800ADA8C48A0714F76829B7F17E7F7D21A1B0D3ABEF944BE1933DE10525EE2D806CC404999B79DF13B331B879728A54B44B49FECA2B81BAD5CD2DD3ABFC3A41A90E5C317E97A9BFE0BDA24F9668DD41ABDF6D748C8A4A0491DEAD4128F04DFED7018201BEE663151CE339C2489265CB98CA51674B9E2B5481CC55FAC6F31254556029B507A036BF48B9F2F6BB3AD0AC34CB884E639FAC40470B8B097936B1852609B4EC27CCC731C6CFCC674C5913D6845D2789F8C747A30E571E30CE62F841653BDE8CDE1EDF9B346BAEA9D79AB941B654727C98447086D00B676B0E056D1D7CC1DB0D30B2972D45531E6951ABFCD5D4B976B9A5295864BC5292E09DD80F0B73AFDE358C8B4D643DC3950D7F15CD5525352B795C34EB024A968E25257C53B1B401D7124A0B2B4909EE9201E2481FBDEDA79F2686C310A5062E0AAF514AFD4F23A8F04399EB6CF549FE1EAAB0BA758E0698A669B67844C0054CA4131379DE2F33824616521456996EA56AA3C43C8B815D79C1C44EA7E9F48479668CCFF0032EF6ADE7BEAB42F14A9DA975490A693CC84AD416E7A2648F961E2E722594CBBAD60F0A52924121CB5289A8D5AFD6000973E25CFE624ADD1E90D38D9552AD3A9F3148BA57C54FDDAC5F759E130768B58FBB32A5E618A0AE296707C27E5B2FBC1F6A3539E91BFCA9B1E23E829A6FB7DE19EBF5A675512CB6AFE174A652AA642438427902B48936E7CF7BC62530F952070CC5278A6007E725C3B5684B0D98FA5223F15356976376DBEC75D2911879D0BE2719A4358F2AEA79C78A003BF17028FA98FD99697842861C2C1EA001F8B1F1B56EF0C7BE531AD740DEFEDE3686D7F316E80CD5BA1D53A3C2CC4060A6C405010AF5F899DA4A4E116A50253A9AEFB528370D077C40A54EC5BEBAEDE7686D7B3C61CE20D909E704C586C2E39FC4FBB12F270A6CC6D5A1EBF5DB954C6BDF2D550695029D43F5E74FB43554E7BDDF04B89E1331E20408FDC733EB787F2B02A2E58B8B8009A7D453E958511C531C9E55347F01FE3A4352F5118BAC4F5E2E43CFE64488C394E5EA70E9BDEC006F1A783F9D6151289B1F4FE61B2B752287042C73BF103F8E1DCBC0106897A75DB73F43E1780CA22E6F6B7E7F10D4BD48A9238C473F1263F48C38460554F9091B55ABD1FEFBF28C777CFD3F9844E678AA823F98070CFF5723D0DBA4F2B03D061E49C1949FDA45C9A337AEEDF6A54BEC2A7868EEF5DB7FC5FC2C61BDCCD557858B03FD42DBDB7F4BFCF0E061AA686843DD9BC7DF287D1C3599A94092B163FDC3F138C9C2BD8795BA51ABEDE08D6BCC094AAE08DB7079DBF0E5F0C63F4AE1A85C8D09E7BF9B7DA08C98AC0BE2E2500444091B5FF00630A264A903840A5F60078D61497AF87DE335D40EA09E5E216C1DC294A26E1FA7ABF41F4DE148D6DD5B6D05171016372AB029DE62449DBF59C0708667CACCFA5EA2D572DEF9C118A3306AA41432E48120A4836B9B5E0FBC6D37B63656042032920061517661CE96621B4EB1935EA6FEFDECC183E28140AE345424C120F024A9256A1B10A0653C27CF63B6C70C3172A648E032C128550B6828366D75894C0021DC6FD36B8E7F5893E59ACEBF2D6159457329CE74FBE3BB5E5AF849EED06D679C0A54DF885E6D88DC6E5183987F592268C2E392CA44F413FB83DD23E52F6A8DDE25E5CC09F9549E24D68CD53CFFCC513DAFF00B39E47AAE81CD53D9D14525536DBAFE679536254CA9409406F8882E711927BB4AA22F02D8B0F67FB7799E0F112B2ECC662D9C264E28D133C0607880608614009ADEB1B89095974D7705CB0A6FF006E76158FAAB14EF3A0A90E82D93F6004F101D36FC7CEDBE3E20C8913A610385441A00EC29F4E56ADDE91F59F118E9125DD490DAE86FF006B73715684CA72BE9969450321B4B9FF00CC2D7C30A236238C5A04ED3B1C4F617259D3880124BB12361D5B5F3615E55BC6769B0F21C7789003B90459BF3D5A346659A64F9630AAACD6B594388054A05C48D874040B11FBDCD8B0FD92C4CF1F24B596607E53AD99C0A3B781F2AC623E206130E5415350E9E62AECDA86BEC6295D51ED01A1F23B1A969E750141084AD5E28DC120981B419117DEF8B7E49F08F1B9C1E24CB5A58D5924BBDB9BD29CDFC389FC45F8DF8BC9001815A960BBF02C96B33B37AD772CC23AC3ACFDB12B96B769321A314A83294540712E0F230527D63CCDB6C746CAFE0AE2706B42D6851622852696E83DF28E1F8CF8F19E63C1733920B82CB51E5EFF002F1D76D4BDB8EBCCE8A5751A89F7D2A2BE065A6FBBEE42B70A53647174BDF9F3BF55C93B11272F20CD9292433F12013460E1EDE94D22A38FEDD6719985033E7278BFEE56BF9E81CD2B68A8EB739CEF3A714AAE456D5F19932F3C99044EC09DE76F49BE3AA65D272EC2CB4A3B99492033F08A11C9BDD6F150C4A332C7289563660E225DD458EDFDD61D7C43426469E72A882C650FB6AFFCC52AA1C571CF4E2F2E60F98F27389ED0C8CB292C2268D025012C756615E60B786ADA42E764C5466CF334A8BBA95FC91AB6AD48548D25999108A4EEFF00F538099F45183CE07C0DF0F307DAB4628006530AD1CFE3ADC3BD0087E8CFE5CD0C58BD49241F520B06FAF36852D692CC385C76A0329EEF8424171A4C9263FB8191F1BFAE24BFD6F0CA21012A49554B851E66C3D39439978BC34EFDC94101E85BA7D768CB30D179DB9429AAA32CC0FB49EFD904806F04A81EB6DF7EB8653F38C1AD6649242CEA50A6259EE4352D4859385C0CD1C4532EA4172C585AAFADEBE2690F5A734057E64D30AA94A5AA51C4730702D2AB054A6E93E1E60F0D8F989C406639D7E854132144A9764F86DAD6CF5D21B626661301592122CECD4622F46AD6BF7A43FE7799651A5DB396641C2B70A7856EA0788280BF8A09DC9D8EF6B622E463E76366056252A59249E024B002C0D9CF514AF323546768482134E747A57933D7C1DB56A8EAF37CC8D438AA90A71970F8D2A32A50E5C24CA844990244018B1C89F44B27800601A8D6F036D6B67DE1519DCB200501E2CC5EB6228CDEE91B586691C5216F952D959114E38B8812481712AFB5F95B7C490CC0CB04710068C68767D41B6946B0BB46A71F254A07840511BBD2F5F0D398B345A5A7B4E52E5684E6D99AE19580ACB185927BB800B9379B9FEEDE3D6299DA2CC2662E60952145453FBF841ABDABAFF815863889A998414A425EB4F1DB9FDD9A10E7DA95556FA90B3FC9448480610001174A77B81FB3891C872F993129529152410E2A3CC5295637F366CE6A37BF845339AD7F7F52F9AE7434DB5FFCA5E37FB51C246F6FC76C74C9197C844B96A44B4A94C4AC1A11B5E97F2DDED9E1E1153C3B58BEA7F930C748F56E6358DD1D1503952952827BF01400E222E4C5F97CFD31179A6351824B23852402D50FF8B35AD188BCF23D03956414DFC5B3BA865C7DF095B2C2928968A4788113CED756C67C8E2818BCE711899BC082A213422B6D6D4A0D7784E669E3F68E730D45F5D49A4CB406DA48290A6BC00804DE131BC7E00E25F299299A7BC9E1C83FDD5D3636E7AF22E634249A3D36FA7979727AC4442D4C970BAE2540901C4900A957EBBF53FB8C59952E4147CA8482D7A5B96963B0D2EF1903E663CDFC9E1C28281FCCD696F2CA25F093E271415C3732480A1C36DFA1E98A8E6D8C1872A12D40B39A1ADB6A9A07BFE4C6B164657A4725CA50BCC73A790EBE8095374A91F6940494F0A099320EE3CB738A54DCD264D532D642483F315370D767AD74ADDC42D2A6A50E09620382F5A93E57EA2F0B135FAA3533E9A1D3944ACAF2E42B816F1010148062656944D81BCF48C5731B8E9C14AE07984E9FBADEFD758DD7890A003EE6ECFB83A6AD489454645A5F4C334F5598BC8CC739502A5124ABBA7073201503276DAF7C34C3E231B3A6F0AA42F84D2C751CC396D6CD7B4305A8A892FD36F2F65A19731D675B99B2BA64B6453A13C2DA5A1C32361050013E7E7D77C742C9F2CC3293C4B484294CE144DAE4B28D2BA72B690D264B54C2017A390296E6435BC341B430E41936699EBF56A710ED253D2A9257DE9528B895CDD25571B5E397BB0E33DC26070E990254D4AA64C7F9501C820589492CD5A529CC424652921418B26E5C83E1FC52FE32DFABE9BC97C41BEF2BC5C2D456A057B4C1246F7F5F8E2224E0A628B5810E4004D08A3D6E45BD2350417176BD4B8E5B7A1F4864CDF3FCCF38EE997DC2CD352F10A7436AEEC10AB10AEEF878B6047145E4811898C26532A592B4CBAADB894AF9AD66E276F2B3D636330292E406D0DB7D2E756F015A4459C71B6892577EA5444D8F9DF6E7D7DC276560410DC3660EDBB696D81D4D810635AEA7AFBAC37B99BB4CFDA583C5CCF4079DEFEEB6E67A49C9CB8948012FB966D0335FD6F0DE7A0A8063E1D2D5FB75AC30D6EA1607142C2605A1511F0FF7B79E2464654A2DC487AB501A574BB8EB4AC35EE14C75B785DEC69A5493C8443731D44D150E250E70499F7DB90F3307CB13527292C192D4AD3EA7C3F98C890A1FB8172FEC445EAF50B4A9870081D773BF336D8DFAFA5E425654A7608A167A6C18354BEE3703CF412964870D5DF476D1FDBE95860A8D42D7FCDD89FEAFBA76E7B6C6D896C3E50A2E782BD356E5CB95BA3079213C3C4E18500ABEEF4AFBEB0D2FEA36D323BDEB7E2549BED161D7E76B6245193F100F2F95A8FADC1FCF5870DCBDFB3EB0D2EEA141301C9FFEA3637E5C5F2E5EFC381939000EEC9ADDB4DED7FC6B04225E7EDC1FE61F39511CFC893F324F3C3A464FC207FB6FE14B73A7BA410DEFE7CD9E11DE1E67ED91F71FDF9F25464C546881E1414B682B530E246B4A7E34F7E9AA6FE3ADFF00CC57FF00E457E78DBFD157FF001FFDC7F30E23919E36777543FF00EE1FFB8631FE8CA76E1ADEE6DD5E08528CF51B1709B5A547EEE21F2F7E30AC98D886B356C2D4A182370CE9300A5C2379851EB6B138426654514E177F06F16F75F1511AF87BF585EC6728FF009849E9C5D49F3B587BAF384C601418701A9156B3D39EEEC7561A39521C539B2146EAB73BF96DBFDF8D7F46520B259AD6F6FC818215B15EDF1020A44F21CED3D7F51842661D4456D63F6D7D5F94652A29FBC2DFADA5704116BC0249F4F2B0E76F761BAF0E0A5495241705BAB52A5F958DDFC5E49C404A48258BD0687C7F8FABC6F6EA87507FBAF7B100585EC3CBDC714BC664D8CEFB8DD5DD951219E82FE03DD2A21F4BC4A0D8B6FB1B31AF8D8DADAC3FE539A54D02955B40E115D4E4162482D142A03A1683FCB5CA0C0E206390E78595270F3A48C34F40285065814571519943E60C58B067E7123271001704380C09E6075AFF0036BC7BF3AC7B66D1FA494E135ACADD6F8BF969741937E84CF29B1906048C7CAECA7B258D5A920E196F7FDAA0FE83C4F531EF1CEBB7580085706312431FEE1F9DABB1B4757B5DFB5DBF5C86A9F4FA02035DE25C5226564D9264A790E9D37B63B1767BB0AEA4AE7492C4070DFB480696FB0D2C63887693B7EC17DDCF0407019635E43AEC7C2D1D5FD45DAAEBDD64FA9A554D4B2D3AA2375253076E968F3DC6E37C763CA3B1D9722524CC4A12C3E674876E76B695BB33C70ACF3E206378C844D5A81268146A1C9F7F48853F9054370F6719829D2FC90AEFB8CB7175484ACDC83CC7E38B7E06760B23491839299A411C4C86236D3D436BCA2A0BED5CCC7A9B1897FF00885973A58973F52E29C92BB4FA36851C7519B87D699259EE9627AA78879DA6D6E9CA6E5E6F89C6D25E0B80287EF6700F88DCDFC2AF1B8CCF0F313F2E1D24E8CC2B6D35B68D76D21A1CD6BA4E81696D8CAD2667C6A755FCC0911212A16117813F09C292F2CC66255FEECDE02BA049400D5A07363E760FCD2999868892C75BEDD2BBBB6F4168459876AF96D1B455474CC36A1BC14AF6B8DC6F613313E71189C93D869F8801E729955A24B7938ABE9ECB338CC52D8CB4A9AE4077DB4AFB1CE2BDAEEDFABDB52D287596D2926490D2605A2640F88EA22F3890C37C2C389502A9856D5FDA4B750E6BE7D1E1D61B28C5672E161496620170FCEF5B6ADAF843731F685A900977326DA039A4208DB62523CBDDD799B5603E142920140528D4905045056CDE3604D77874AEC74E92FF00EE1009A51886EB42E7AB8A369100CDBB7EFACB8C0FAFAAA5B1C657C2E16529B5AE08076DC0B0F22709E61D959395A4A66A9285D8829009E8EF4E5CEF1A8ECE62921452A5280AB0734EBCFEE41BC4F3B2DD59A9FB4BCE11419526A0E56D2D3DE3A9714A6B845CCAC9E1DC1FEADE6D7C736CF0230A0A829013BB25CB1664B3B9B7DC434998799875042A694AB4049A1A316704EDFC476FABB3CFF0F50AB4FE584A2A8B694D7B9DE71C92014F0A892266C4249DEF7DAB581C1CBCCF10578850013FF4C287EDA005EEEE2DA588A40AC14C989056A25DEF527CF5A1ABECD1515467148DBCAA62A2ED72D478944AB72646E623DF318B6C8C830F2C02569E1BBF981AFD2DD2B0DCE5938170694AB1A8D2A2DA3741D23706DCAF7A8A9A991DED792AEEDB4DC2A6E66011617B8D88F3C63112F05212409C800025DC1B03ABBE9AD74E9AFE82671001449E8C697D7AD0B7A87B7F28D3993E4544732CDD4DAF36E12A452954C2AF7B4A4181B102F8A5E3F138898B230C82A92927E70E3A535EAFD378789C1AD20294B246DA8A01A5EEDE0CE22BACEB573CF1ACFADA9490084D1308F106D3B1FB13B8BDF7F8C4CF65F2D56625467A3F6915533EBA9BB336EDAB340A32A4D0CC0496A3B9BF3AFA1881566A25B74A43A92A75C308812A99816BFAC799C5C96309971212B438FED76F20CF72DCBC28A04952428541D7E9E75FADAB0F9A7BB38ADD4494E699C2D4CE5E921684AFC1C693720494A8F2E477F3931B89ED194132A5B296A042529A8B6A459F991EA2123365A4B15007626F7FC74E7168A6A72ED374668F4CD232FBA94F0B8EA8A0293D482EDCDE763E5CE0577103118F5257892A72E529721AA2EC454EA2BF58732D132601DD825F502876D0B5EFAF237AD734A8ADABA89A9AA5ADC7092E3409086AE6C9E1F09B1B91E5BE25B2AC9A432A6CD02805E8ECEE0EE079BC253A52D052160A5ECE3F9DC74BD617656DA8A85252216A71C84850429504DA660F53CFE42C9E2F1185C1F1095312549B80A17D0BBD6D6D3EA8CC065D5747ABEF6E9E9F58B032DECDFEA4A39AEA1A8029DD85B2D12018173C412411331045E0E2A38BED5AA52952788D1C392D7722E2A0FE63596D33F655B6D3C36D983562734F9837DC8A1D3F40142380BE940213CA78949BEFD794623518A4E378A6AE6710350E77E4E6DB39A6B1998B4A4F091C2545AAD5A3B6C2A3434A3DE36D1E9AA3CBCBB9B67B541E7D10B6698A8DCF310959102C208BFC31178BCB06371084E1A61E00FC6A14096A8D6AF57A7833B33C515A0029716A8D7E9F5B0A8611AEBB58E6D9B32AA1CAE91BCB291A051DF24B60A9239FD94933C3313BEF899C064986C214CC9FFEE2B73AEF434AFDED0D133575150CCE29E429D2B70FE706A4C9B32CD2B1D6689D5D63C149FAD2DC909493241415CA4DB7E13EB737B14CC56598792FDC21C0D05475000724599FD21CA160B82A1BDFEA7CAFD22CBA0A1A0D254E1DCE50876A0890810BBDCC4A245AC36E700E2AD9863664E495E102920B874B87D03A41715FC720E5065A4FCC43806C41D8F4D79BD9CDA23F9CEB87AA5484D2D3A68E9FC4105011FCD02D0A80088E5C5EE1318C64985C5E2262953C2D4090DC4E48E94A5F47F178618C9B2C2992B751A000B123A7B6F07887D5E7A5C3C6F360CDCA94B13BEF1CF6E5F8DAE585C192689D589FA0B1BD6B5F0061B9933420AB84807521FF0087F17FA447EB73E652905A792557949504F0CF2127C899B49C5870997AD4C384814D2A4935FE6EEFA330D5089C43B384D8B1A3BBD1ABA9B52B101CDF5496F8A1C0627FA80B6FC8FA6E7EEB58246553385F80B51BE5D29E36BD34A42467252A62B0145831F16E5BFB3104A9D56A755FF140E136F10BEF1B917E53EEDEC6C183CB0949796F673F6A73D1FCAF0F25CB2B62490E1DD9DC54F833D2CEFB445EBB51B92A3DF0B72E31CFD081F9E2625654A2CD2AA6D4361BBDACCCEDCAD0B19029F35AEFA74888665A91C2A402EDAE6CB11F7824F3E7EFC4BE1F2B98C0196CC2B4D99F7F4F38D44820B3B0F7CDC9F088BD5EA35AB77A081FDE09336D81FDF5BDA465656A0C44B735D1A966B72F7AE5586AF102CF62DC98DCB69AE85E23D53A85DE4E026E7ED475E84CFEEF7C4DE172DBBCAA1D83FF00FB7F9AEB511B09640147275D76D74A35294B986A7F50BC2DDE4DCCF8891CED73E6791E5D70FD3966BC1E9BEEC0F3E7B178CF028E9EC7A7B1B874275039C4AF1CEDCC7CEFCF0E519726A0A1DB71F753728381434FA7E634AF3E7099EF08DCEF73E5BF2DB0E13972187C9C8D016F27F483815B7A884AACF56A375931CC2B693CFDFD3DF8C2F02948FDBC2D761A0A0A836F621442141C949D3EF1C7F1B56DC67AEF68EB311843F4D2FF00E5EBFCC1C497670FB4033C5F270DED3C604FE3F2F96373824B71105AF51F9A42810A21C0710A919DAEC7BC2473F10178E7CB9FE58D5385973094A594D46BB574D746A0FAC618BB6BE10A5ACED6A27F983FEA120499BCFEE309CECBF87E6200480C5C33BEEE2CEFB3C6E3E43F3538980F53EFAC3AB19D2A44B824EDE2DFE7E7F7CC6E19AF06548744BE2A35001EEE1F91703585C4B5A83A524F4F7EDE1F28F3852F8897072E7F2DCCDFDDF2C436324F700712784A8D396F435F2DEB1AA814FEE0DD61F98CCD500F18F5E21E5E639EC797CB117FA79AB2549415234228FD2952F52CF0977892581726C07376D46DBC3E51E653214A06C902E0FDA1E5BC193C845BD1A9C2198A0B52486771B1D76F7CE349A569524B108A574E7EC08764D428414AC137240222E041B7974EB718D664A49490A48200356B68FBBFF9E70B49C428D2DA6EED52DFCF833B43AD354ADCE249516E9AC5F7044A4FF48091E2326D6DB9CEE2B98ACA2522677A164A892A096D056F6A1E8FD686564CC55DE8343B86B54FB6DEBDD07F2A7EB966BB51E68B78995AD25D5113B9B0599BCEDB472E7E6F464597E1788CAC3A54117FF6DADD534E7FC3C6ABCDF3458FF7315354FA712ABB0725F4EB5DA1A2B750E92CA94D37474C2B1E1C414AE35A4A08D8DECA2623A8B47338778693C7300972C4B492001C352D46259EFB986ABC5E22692264C511FF00A8D5C5E95A7AC46F39ED12A92C292D25AA66384880947104C750028DFCFD2716FC176566E2D940A9054DA16ADF61B16FBC32323BD72A0E75700FD4D77B52298CD7B44A36D6A51CE9548A24F1A1495381DF20552940126E3FDAC69EC4E270252BEED5890B63FB2CC694A8FCF3786D332B54F520CB1C201B8DBA1E6CD5D62AFD41DAD65B468529354DBAB0492B2E804F9F093607CF963A3767BB2A7112D972532980705007D40AD35A08B5E579384201980A8D3A790D9DFC2B14E673DB930E3ECADB5B95350CA5D4B0594AD5DD29C0526528078A7948E56C48E65D93C1226C84F7D2E59E2A80D70A17636A72AEE6A5DE27052D2582343A01663EB5ABFDA2AD7BB48D5CB52BEAABAEA976A164A58348F2001C5207196E0083126398E78E9995765B2E19795AA6C952932C70A8CC4248201AF0F103FE1ECD19C1CB44B5FCD2D240342C0F3367B3E9D4421AB63B57CF9756E8C8D4D53381B97175CCB5208B1E12A4949EA2079F5C46644BC164B8D9DFAB216852FE43C25693C2589F95D88BF9178BB607F4C8427BB090A57EE0CCDA8AB7956ECEFAB4BBA27B48AAA734EE5336D33B92ACC1827726092E037B8DFD31D025768FB349E29AA2A134821291216C4B14D592C295F3F04F345A5212124352CA0DB55893ED891689B766DECFDDA4F6919DD26554CD2A8A868D73985621E6DF4069638941442884CA0280BE3CC1F17338929C4F7B257C1296A2C0382A721B84382CFB0B448E5C70EAC24E2A092A09BD284397D6C6F67A8AC7A7DA732DC97B11D3597E8CD2450BA9792539954777C4E3AA0429D8717C4A4DCB9B28C0F28C732C0652ACDD2AC5E632CF73874954849510FC42A48043EF5D758E17DA5CC38735484CD1598CA00528A037E571EAD0B17574798B952FF7AA6DA2106882B88A90E11FE638D47C4A0573F6CDA60784E18E132F3FA99812582154140E03D035D9BC46A6F12D9866024E1B0E65A5C902DD2A7AF3A6A6F11F6B2319957A5145C55554A5C2D494A884A64026448FB26E7CB7C587198708C1A953A67720268A26F7602BBE839C62566A66CB09EE6AD550D49AEDEB6D748BBE82874FE81A46B32013559F54B6A4788A8FD50A93DDDC2894F882B9C4103D31CA55226E231AB95326A9520AC10AE2FDCC5EC0D3437ADAD48C2E7CDE207BB2923400D1FC3A78F898ACB39CD5D6C56875E50AE9E342F8E5203B2B03864A620C6DD77C752C065B2A64AC3B04AA5AD2C4F0B31096AEB53F4BEE86231844B50E0341CEFB6D5FAC4332646679EACD1D0D2386A9A59FACD4AC12921C24A080B1C161CD24FADF1B2BB9CA933921494853948000239DDC97F6CD151527158AC424A4AC242EBE63A73FC345B796690D3D90B09AFD50A45555C05B68BC0526F109907E1D3DFCFB1737118BC4998952D48E3372AA5580772FBBBF95A2F5875265E184B27E7296A80F47D34EA35F44B9F6B2A8AE0C50D2B41BA06F8D14CB6CF006D077E2E10999B7DAB75DB13D95CBC261B8A7CC03BC980099C5524A4101817029A8BE9568AD4FC1E2A6CFE21C5C014E1BC4D34F77A9784B8E3C1F0DB6B72A9D70C70B7C52924F3299D846F3D622E5FCEC5485281484B519A81AD7F3A5045EB275CAC34B4A2704B902EC7424FE3E9BC58F90E81AF75BFE259BBA9A3CB602DE715C2A7109DE128FF88B9D8C030664E21339ED0A30F2D586904F785268976700EA0303AFF22233B438B44C9F27B9E1090A62D5A53C6F5DAEF6898399DE9FCA194D1E94A0EFDE309566DC2A52F8A409FABAD2A32488B72BE39F65AB9B8C9F34CE9C4A492482AB55C7CC4D3D3C19A1C66186C24EC24A2A9C996AE0A92D570FBD74AB0E5A339655A673BCD07D6F52D7C65EF0E26B8949417920DC774950537C361B49911B1C37CEF0CBC54F1230C851EEC8E352412002037CC28AB5DCF50042DD9CCAB2CE19AB9B8D965C5124A5F5A371120F2EA7585359A8E9B4F28E55903086A980E15D42871957532E5F73C8EDE78B4E51D9996AC27793D4AE34A5D280EEE41D9B9162348AF768A4C9938B47E9A7A540289201150FB8366A5F95223158F1CD1C52A9C3B53528238D0952F856A5ED00022D3CB7F29C3695227E0674C13414A41F9490051B525B98D2369C50B912C149058B3D74E61AA36B73A3C8B25D159916C667AA6A92C65691C69A2942145226CA285070C98DC6C79E1BCFCC4AE67712945531F404A438FF0090A1A6C74DE23BBA0012452C2F5AB3D6DEED78DF5FA8F26A40963226C36CB414145208593112A52BC44C89B9C38C3C99EB09131454A2CEE1C1F3F00F71F56137E42A2091B1777636F7D6D4101CDF55B8B90B5156FF0068CFDFB79EC36C5AF2FCB52B002E502555228CE395BF35B4305AA6EB3157BF9B0BD2FE3E1100AED4C9511C64240E28D87C36F9F4E98B7E0F2B4253C294840236AE8C6C37D0FDA23D52B1137198758528252A0540BB2AA3C3ABC42B35D4CD99977C239050006FB41FC39EE312B96646A52D4E93C2F4241E7607E9B3523A6E3F1386958194C8485F08726EEC1EFA9F0E9726BACD751B6784A5D2278A7C647A7300EC63D2D7C5CB099294948E0F9410E0A76B7BDCEF11996CF958B97380482A4A5836E41F33D0D6E62BECC73D016497491267C66E26799803A7511EFB449C0012EA803421BD34BEAF6715B452733C24E46352A4F184859A6843F56DDFAD2B10CAFCFD2A20A5E3CC471458ED3CCEF6368E932313380CB93F334B00534A8F4B8BEB16F12C0C34B2470AB87CFF00C9D1FCCB3C72AB3C041FE7122F038CFE727F1BD8DCE2764E5E0542075007833D3A8D28CD68D00510351B5BDBE86AD11DADCE92A2901C2626E556B8DB97DF389291800E494826971D3D4E9A52D0B212096D05C75B577E4F0C2FE6E9B8EF0C8907C47EFB8BD80FC30F9182096F901A12C45697723A3FD68C21CA659507B253B877360DD3D986E566817B393BF3B01BDED249F2E7F3752F08003F280C6D46E9BD3FCEA61544B4921C13BDF6E51A1CCC904005C1CC8827F318553866D007E87DFA9BC2DDD207F68FC7B6D6B081DCC900CF1C5C8E511F1BFEFDCB0C3A3500F4FF00023532050D4036603DFD3531ABF89A3FE67DDFF763612258B068D7B81FF23E5182F366D304AF6E7E667CE22206FBE37FD089E93F2920820330E7B6FAFDC08732D80EEF878B8A8E0506CFB0D2E3D04708CDDB5184ACDFA9B0F53F95C93388F3D9E0999DEA945DDD9B47D6A7C2EECD08E2BB3C427BF132AAF9C241AB01D76E6232733147085779F3B9F77CA6FCB71872BCB4CE0100708662406BD09D0FD39B5619E1A64C4FFB2A964B1E106951636DC55F42F66781ACDD04C0548039288BC5BF1EB6EB8424640308B334AD4A51735A00FA5F6B7D7589BFF4542657EA0CC0EDC412CE6AE483D3F9856C57000A8BA46DB133D7D48F5B8C6715844E29065A2E2F4B3353404BFAEB48ABE3A64D9B31294A58254D66074D28FE62B5B557B79924812B320F3511F1826E2C6E6FEF386D86C0F7482820716A2AE0396D2A3F1168C9CA12825601F946BAEE5FED7E6D0F9439A24260ACC7FEA3D6D6F758CDFD6062A1DADC02D430E65820F128A881CF561D7EAC62333A50AF754D4B56AD43F4F6D0FECE6D0532E1B40B289036FC87CC72C39C0604A7088F943B397DF4B83E15D75884CB92A5CC2555622E79EA2E7F160CCD25A4CD53F694E9D8589DBCEC418DE399EBBE19CDC2B4D989090D4F3AFABF96D58B062A48084828D9F57736FA1A75DE25F9766A92412EC8B58C1F84FE5F9E22F158321D9246DE7BEFEC0AB06A895F351343CF93EEFEEA369652D7B6A0003CC4DF7B8F744131BC7CB1018AC3109502284353DD8EC2BA8A43F961980B0B8B6EDCBA6DEA7B219EEAB6E95A5FD62B0F0806C571EBCEDF87AC1C72BC364431A383B8097A12C1ABB9603936E213329C38A0BFF817E7B34509AABB4FC8B2921C6EB5282AE3E200970A88D801E254CF48FBB13384EC54B94A0B52425AA03020D5CFA7D1ED1852284804DADA55AAFBFBD5A98CCBB5ACFF00523A6834D52D5D53CB3C083DCBA841262095291C31026E408DF7BDA70E8C0E5AC26A524A06AC2DB780E605232A94A007C8DC562EED67A7F35D233A0EC93B5CD48976AF515635A7A8442D9529DA6796F21775F842C2D25201DFDD87A3B7B9660D6654AC08C42D343721F467497A11AD76891C3144A523BC20F17200FA8FB574A3337E61D99766590A8AF54EAA566D5693E3A5E07D94A9437485A16537DA45B99B4E2532FED1E6F9DA972B2FCACC94AE9DEA48F945DD8A6BB7D22E9829B2152E8D50DC3EEE3E9F46AFF13F649A51B7579369168D414CA2A9CAE5BC5C52365869DE28F3040BE37C4762F3DC462A54EC4E2662F88BB04B04837143CEEE6C4C31CC70A99C7FDB04390CCF770EE6FD0559F68ADB3CF683CC909AC5E5E28E99B69486E998FA95328A78CF008516E7722E76BF58C5F51D91CB30180188C7198E99654B3DFCC40E24A5C538DAFCBAB5838CAB26C4CF530043B3029A9028EF5EB6FE7BE5D867B04FB587B54F665936BFD1144AABCBF35EFD65D69DA461BE14BA529E1515A4288023C33067AC63C6FF0012FF00A98EC8FC38CDE7652BC5A0622528A4CB215319AB555454784770EC87C1FCC7B4B2FBC9485814F980671E8D51FC459751F429FB6CD45452B4F65D54D31DEA4BE456529051C60AB67B98B48EBEFC5070BFD73F64BB95A573D05C3026517773AF07BA458B35FE9CF374AD053C6F6142D701D9F5ABFADE3D1DECBFE8BAEDDBB30D1D4995E4795AC6639B3406A2AB5BCC2DC694CDDA8EF16A32A25425044F4338E2BDB5FEAC7B399EE6527101626092B265B9525290A6770C0286DB1DAD133967F4E59AA3018842B8D948621AA684DDDE8F60F6D68F49EBBF649ED5F48769DA6742E7D95139CEB535634C294E324BAAA26B8EAE405148DEDC660D809938B8647FD47E418ACB674EE20512509EF439B90426C059BABBC79E7B4FFD3AE689CE25A5D65E691FB08FEE6707E9A3D445AB4BF46CFB42D49425ECA96D0A920BA0394E4348DD3052ABCA6F6F43B628B3BFA9BC9938B5CC1352895C44035B24B7ED6E46F78E8723FA6ACCD78592172D7314100D53472295FA9BB7888B7B25FA3E7B5BD1D4119564FF005DCD5D480B2B5B03855104F8C916079100C5F0AE69FD4A767333C2A513310489696484F125C9A87600383BD2D4D636C2FF004F58FC3CE32D724872CDC20B8D03D7DF9C573AB7E8FAF68259733472856DD3298A9AACDA5C615DCA699B53AD0482A9B84C7839D8CF3A8E5DF1E32C9D984A0AC50095CC4A5142CE4802CF476BB5EBAB4BE3BE044FC2E11734C83F2A492E8B53EBAF2B39B4744F2EECD7501A8CCAAB523BDDD0D3551A7714A292AFF2EF29920A428AF7411CFD71EBBECEF6E138BC04AE01C4B9B2819600DD2FC4ED4F2D3908F3F768BB1C8C04F54B5B009514970D50762E7CC7D627398E63419027EA790D334964A10972A470852884813E283636DF9623B1B8FC5E2672153D478CACFCA280026D60F436BE94D6B53728918596B52784FCAEEC36BBDCEFE1B56203579AA5F59FAD2D55255B24491799802474D8751B5B173C065F2D7850B253C5C37200D9CBF56DCEFAC51B138952311C01C241621C806A1ABF7AB6BBC2FC9B4A6739FA9C396B4A6B2F4149AD5BA9EEC2127EC96FBD00AC58CF0131BF4C54B37C48C24E1282C3AC901296502C6AE4394D09201009D00B45C30064AE4B9090403767B0E5F48B532B4767BA3592D102BB3822E9521D514B906627893BF4076F53886188C66266097DEF75243712A84A86A286E6A09B51E915DCE731FD33940248240009607951BA73E6D1853516A1D615AA7D2E2B2FCBA9552DAD5C21086D7BFF002CF0F78142C2C626D18639B63158541938792672A6063303922E2AC091D7AEF15CC3663331934959258B81A07D68D600D0FA3B89AF0698D2D4E56C5334FE6FC278F3499471C183F5720A01E5B743BC1C4365D819C95F7D3B8932D45D726A14AD5B881A35ED53A6CEF33C262B3195DDE1E72D2A01833967ADC569ADEFB88ACF33CE2B3317D6E5456283DC47EA8A49E04BE09F100DA4A528E110088E5318B4CACFE46101C3CACBC84964925D4A0DAB94B91AD7C394060FB2F9CC8529671B3B84D59D41C07A5FC8D3D5A0A5C83526A501971AEE196E097C70994820CC88B408DE60C1F39FC267B83C220CE501C4A0590FA9B86D0BEE2FA343B3956324CD42E6CE5AD94092A2FAD6E59B975E5135A77B2BD254EDB3488455E6CD24F79C5B2957224AA5361F740E78AFE27319B9CCE99C492251344F0B1AE8EDCAE0DFAD2CE71495C9972825949001377207F1B7E62079FEADACCD5E2ED5552997D3B5189088B08E2042222E3A89C39C1654785294228F43725DCDEEE1FEB5308124B925CF3E7B69CE20799EA4A5612820043EA90FA7886FC8CDC13CB9F9EF8B7E03252A524A935A55BC0D5C3FF30D4827881AD68F773FCF8DEF15FE6DAB1A1C44293BC0F101B9F2B8FC63D062F797E48470B259AF4FAD74F65A1232DC07152FD1BAB50DFCAF48AD33DD521CEEC36EA418513E21279D8137B6F63E6631273302A9588C3A384B2D55A74BB35C1D3A8112D9765C898854D203A6ACDB68F6F0B6A62B2CD753B8B2A0974285C1215BC7483CBE5E7B63A461B2F9186972D53120384DC35C36ACF43CBAD0C46666B9B3C2D087570529CAD61BF3FBC40EB351BA54415CC722BDA3AF3FDFA9167C365F2972C2D0010402384392FD1F573F8A46BD9533533D52D692C540317B3DAB7BB50DF42C222798EA074951EF02A761C516DF91DF636E9B6109582519CB41140450587B6FF348B567995210A93338402AAD03EDA003DDD8C44DFCF5D244AF7079DA7EE9371FB8C5AB0780EE9344B95004783BBD0BEF7109AE4714B4252C03063C837D3D5A186B33C74AACA2520112153EE1D27D2F7E5B4ACBC1AADC229C8F4D05858EF51D124E1406E2A91AF95181E5E3CA19979BB8A90A5445C5FC8F9C74E62DD36C3C460CA4B101EF4FAB51A95DFAD4C3A97877341437A7F3EB0DF519BAA6CB85007FAB7B7AC7422FD075C3B4614901869F96D7DEFAC3A12000346BDF573BF88AFD2A959CD5C5154ACC0E40FE33E44EE4018752F0459CD01F60D6BE1D616461F4097D6B46E752F4FBD0462E664AFEE5DA62F1F8DFDDBE161826B26D46625C697FA53D046E70E59CA03757F1BD3C5A123B9829444A95F133CF19FD116A20F93FD49BFA368F5C770FFD8EDE2DEB1A85728FF52EDB9981F3FCF18FD1285D247FFA47DC08C19005E581D7FCC62AAA539CC9888337F7F23B7C2FCE709CCC44BC1944A586E270E457F1AB75A68D0BCB4265A492900914047A83A50EE2F7BC02ACA08014491B9076E77106F1D63EFC48A1099C90A0C41A8E6799A6E2FAE9681299D354000A52491462CDD756F61E35BB982D447888BC448BF49DB9F90DF0D1139026141961206B7048FA0D776F387F3B2E912A57794E221D98120F9BD6DB73856C3EA4A544ABC46F79F8F9EF617116E9853152D465ABBB62520B10D40472F7AC442FBC532524948705B67EB407939FB70ACD5482471F0DC820AA0D89E46E3DFF007401179361A64C9738CD4170A277B13E54FCB40BCB810998104F139701F913B52CE2D0EACE66B21104C9DA3981B91E97F3B79E1A6608561710084FEE34DCB03777D3C29A3C3544B5E1C28005B7D00DBC2961E20830EAD666E20825563E640B4F537F873BCE1BE232F4E3D09F95DAACCF5FAE9CFD68C710833ECE6C4DCBF81A79EDD19EA97355909E254CF98DE663CFD26DF18D3F41DC4B292914140DBD35D687CFC94C1604A5567259CF2AB1A8B575A8DDA2434D9A2B652FED6C26F6EB11163B5BE2710EBC110B52B86A76A86B0B1B736DC6B594C4C970070B90CD5FBB816160695A0897E599A2E5202FA589DFE307F1C4662B04A20921CB5473D77E85F9814868249492FF002BB102FEB6F7B3458393E64A58582AB2787FAC1FBFDF7E5CE3158C661BFEC2F5F99ADE15D7A575AC2A896439BD9852AC4BEB1AA95BED3BB4FABEEA8D87E8E8DC5417950070C6F0A026C3CEF3BE2898C9F86CAD049280946819C54B52EFF61E6A892AA0B3EDA791A7E62C7A0EC034D64094661DA0E6C9AD7C80E53305C20A08BAC10DAC83E844748B6206676B26E2499584415D6ABAA7836A1BBDAFD79EE24F0A5492C4534AD399AD1ADFE21C337D75A5B4C512E8B48B5474CA690529714CB6A5981B853A8E29F7CDC1C3CC364F8DCDC714E0B592494B3A58DAC3E9D7A46BC0EE52E0747B5ABA30D472B475AF51F6C59AA96F2330A9714B54FD58A1E5251CC2A1283C207AF96F8BFE43D84537793A4F11A28F121CD37D69D4EDD59CFC3CF5AD250E438AFA5B93781A36FD6DD55AFABAB5E73EB4D2DF4A8F857DE1B0246F17239C4F43EBDA7B23904AC2A4A512932CBFEE2069C8B52F5163CAD6DCA708B0904A8956A2BA695A3F5A54ED15C6639A3CD394D58BCD3B84A43850C4779F68006402608F39BF96D7D3819331425094028302A34E27346068D7A5A2DB86C38580172DC9E16511FB18EC68417F30D488857EA6CB154F507EB1F58AC514F842549248513204401CE7D7A62A7DBDECC77F92E289C40C30EE54CAE2BFCA6A5886F16F48EB9D92C9F0D3D72C280D2AC391A5F60DA72B47E80DF413E62DE61F47FF0064E92D04BED8CEBBD709971415992C2428993610624F4B5B1F9B9FEA872F9B967C4CCF659C519E81353C0B27E5A26C1C90EFE7A47B93E15E5F87C160125084A8D2C91CF46DB773473B47B3A0212121490BDE2C3CBCA4F203D27738F33489C661583352E08A3B372BFB6DE3A6E63DD95A099009E497722CF46DADBEF53AEB94534C5688111E1005EF1BF972B73C45E284C9988969188FEE70CDB8D8DFCAB611218432C4951320370A87084835E122AC3CDED48F25BDAB2B6BBFFC5E7B3204B24203FA9803C3B4D322796F020FC71DE3B31842BC927A913C02657CC2F50926B6E82D51CABC1FB50A9433843E0C319AE0B3595436D77FABC7AB54E7868284A129054C3455E1927C099E53F198F2DF1C2F379B8C958F98254C51489847083407888D7DDC476BC8F0D859D97CA54C9284932D2C0A43DB524736AEBBC2E14EC8325092B804D85CC5BC85B903EE8C4A499D3D5201571061B9A96F0D796BA188E9D81C01C67089681534606CE76DCFE221FAF1B791A6B3BA86929E16B26CD14E3600F19144F70DE0C41BC5C6263229AF8AC3A66A8F12B1128A0D411FEE0241B1F173F730DDB6C1E1B0F934F9D2A5241125668904512696DDFC0C7C74EAAD78F54E7BA8E85D2AA7E0CE730484892920573C36063D3A5B9463EB17C2DC189F9560F8940FFB32D9D8FF006063BFDC9A88F8FF00F15FB55FA4CE3112C0349CB000A37CDEEDE1486BA4CA737D595F4F4F44DB8780F0F72A96D3565C8BF784009E1113E2C745CE30586C1CA56257313FED8E23C243F9024B1D5A9CC473BC1E74BCD148929155B301FF00736BF6E717552765234BD3B75F9DE4B505D653C6DB050EAD92A5899FAD2525B3C8DCF5F7F3F5FC43C221472F958D4495717013C40A85588E17DAACC0EB68B3CFEC362E64838B3216470F1F10496B3D4FD47942456619FE7B52D653434DF51A7A7E24B25A42528602A64ADC484A5E9E8A51E1B6D189B09C0FE8E6637BD0B9B39214B593C5C647ED29492787C39C73A9D8D9F84C5FE94B8659480EC4176F176B7D3495E4DA0E93295A733CE72F7350D7892EA69D2E28B4A3211C4194AC1DC6F698B6397E6FDAC95809CA9499E996A0AB93A38DF96B70E6F17DC0F62B159EE1FBD44952F892FF00B5EFD0381C9FC18D63BAA6BB33A52F36285DCB929FF84C10A6D6DA0C9F1029413E188E2FBB1D0BB199A65F9C4BE35AE59596FDC52A0A7A30AD35A6B15ECCFB233F20528CF94521C9A829147D2FF626FAC41D9CE93528465C285FCC2BEB894B496CB8A51524F2080A1CC4DFE76C5833C9596E5E8562A6E224C99680E949524F16BFF2046F60748D3229189C4CDE091215398B3004DF981A0EB4A0DA27F94F6579952B4C669AB296A68D2EA92ACA2816CB8555414A1DE0052906DE1DC1EBB639D27B7B93E2272F092FB92CE933810784876241BBB72D758B566395E6D864248CBA77090C7E45077F0BD28D485FAF2B339D26C50D3D2D3D569CA5AA491DFB94AE3A1C4881214E204483D441331CF1BE1E6E0313350B463E54CE253F0256950AE84051DDAA2DA4404ECBB16A92B33B08B96C29C40D05DEA01B7F9ABC52BA87508CB5483F5AFAD3AF24A9CA82384AD452083C3B02276E73B6D8EB192659271B2E5F772D20331501C54F01CBDD445352489D312F54A99A8FE1AF3F08A773CD646566403C8CF999D8833CAFE7B62F597F66CF106451C3A9835F636DD85DE1624E9E5BFBF22D5D08ABB36D53F598E2708E19BF15CF3BDC7588C5F703D9E4CB0974D5AA1AB50CFD4302F4D61CA5254453AB69D3D748AF735D4083C52E1EB1C4479723BDBA7E0459F0B94A5000096AD9AAF46A9F51E5A0859325C907A3EAFC86BA7BBC12B73F68B88594778A01690F178A031C40832926153CB7239DB1B4CCA0CCC5E1D610084A9DAE28DB126BF8D5A27F0004AC1CF0402AE1B9069422C76A5BC225DD957613DAE76E4C6A66BB23D3CEEA9AFD32AA75D586AA50CF748AC2A578B8C904700306F611BE28DF1A7E20657D8691949C7CF460A6630284A429871776520B10D5F017D5A935F0FF00B213BB4D371E65CA54D12880CC4E86DE5A7A5E2A0ED234A6A9ECCF5256E92D6B96AB28D4D96142731A353E1D5214E242D01412400384F2DCC1BC63A07C21ED3E1BB5F942F15879A99C829470A8317770C0FA59C6ADAE734ECA2F20CC528992CCB06654314D9B5F3E5A456157992493E2DC5AFF0018F5F2F3DA71D6F0D94A44D9930A5C1219EB6B7AD6A5B5BBC63B440A9186421AC28FC853DD7EEC6EE6095ECA262473B4F5E5D45883C84626E5609291448716E54DDFCBFC4472243CA4921E8ED5E5D1DF52417D4B59ADEAC02615D64933F21F77A83E4E9184A82534B966FB9AF56E70A230E285827A56DBD6FB3F5867A8AB4920F175D89B8163791E9704FB8CE1E4BC182430706E763CAE6E21D4BC33800077D68D47AB1B7BAC372EAC6FC4608224EDD391803D7E18708C154B80E19DCFF3434E7A43A1863F2B33694F47AB1A7836CD1ADBAC4A64F11B98DF90F79E7875FA5E160DE94A575377D7F98728C2392784BB6DCEBAD2BA6958E175A08038E7717206FBC926FEE8C6C9C3D4FCBEFC2BF6854E149B20BEAFB741BB743091CCC1488EEC933B9E5E5CCFE07CB0A8C3B8A8D742DF5F41A78C6461535E2A7D69E3CCEB78D5FC51FEB1EE18CFE993AA5FA91F983F4A8AB971D2B4B5493E8D0E1495DC6CBAF39501A5330024A67BC0B3004F2F5F7629FDA0C1A5536532C4B636B95390481A3F87DA18E230C7BD972D128CC4CC77502C11C350E357BB3E94A9A6972ADB5FD692D3A9A3701680A92A0E719598F0B64C6C48D8F2E58C62E72725C21C4E226F04A4A38895960400F724742DB30D00E83D9CC8862F0DC265712D88059F90637B30229BEC0595A6FB32D55A9F2ECCAB729CAB32ACA3C99943D5D99268AA4310E24AD04ABBBE048B45947DF0239D4AF8A7D9AC6E3D3814E3F0DDFA97C28477A80B2A70FC20A9CB78DCC2799F6233390B33132D66597247012002F5D74E86915A8CD2B5C72A51564D1AE956A69B70A78CACA1452A1C02F3298163E831D6A41972B069C54C295485238CA8AC335DC9A7F2D6D4B5C1F644CCF9420AD6A241604104E9677E4DB44F74B767FA9F57E5B579B655A7B33CD90C20BB595C9A5AA699A64B61452A24B45A5029178200FBB94E7BF18BB39946612B2EC2E370C674D982594098877E262C389DDDFC9EC4C4F0EC2E324CA066CB522500AE005069A9A8A914D6D5862A2AA4512E9DDA9571B8D2AA1B5B1B290A6CA9041024CA488BEF1E78E8786E1CEF069C62450A02D2A1FB4821CB69C874A450F39C957852A48B28906837FE6A07D840D6726ACAE4F025B24A5237B93631723DD699DF1A6580778B92AFDC0B01D1DE86956BB5DCDA2BE32C095213FB9CEDB11D79B72F0872A7AE91E9E67EEDF6B74E73D5FE2B0CE8259F930EB4F643E90F4E0061C0570D5AA6E3C5EC6E7D22434398250492A2640B93B46FBDF975FC0E20CE1DC9252C4934059BDFE68290C8A4CC253A0D2953B8AFDF9F496D06669041E2BDA21476F8EDF7EFE586389C30AD03D6AD4BFB6A168D152002771A558F377FBFDDA6995E6A94A95E3224833C47CB6BFE43CF6C55F1984624A8380E053EB4D39E90D94185410A0F4AD7A731EEB48EEFEA4D77479252AF2ED2EC314A96D250A791DD83000BF88024983B6C7CED8F2FE5F2B159ACEE2C5256A5ACFF00738034B160586A767021D9E15324103503DF58EAE6AED6A97D6971FCC5EACAD1C64B3C4B09428EF1E2298B721237E738EBBD9EEC22310D366A42258296200A825BC5A8C45EB58D84924EB7DABEFEBA0A18EBB6A8D522BD4B4BEE2E98A49809528CF99E1D86D73C84D8C476BC9BB2F84C0CB4A932D130001D4A6480DB0259DF97A429FA550A31074E7BF4D5B72F78A8736CCEB9D5B4C37DE55074A934EB6817140CC1909E2373D7CF718B94B5E53859478E74894784BA0A904D05831D0D1EBCDA2CF91E5986C413FA852659A37151DF968F4D236E4FD96F6B9A9DE42729A15AA85D23C6F06D9E14AA2E7BE00C409EA7A6D8A3665DB8C264EB599684CE0825B816C684B38483ADA8CD56117C9794E0A4CB79650A0055A8F461F5A569D69169D1FB2556B259CC3576AA6B2A091C4E5325B6EABBC9890436E1E189FEDBC8E98A663FE3263D73E5093819894F1101B88155280FCB6E76035BC45CCC74B9426489412A3C4385419C005C80CE4BFAD75A0794763DD87E9FCC5A7334A819C901417097D89213127849893B1DAE7A5A37B5BDB0CEB3DC8B1457266E18092A62144B82935A00CCCED4E82B16DECE674AC22E58528A7898026868DFC0A53CA3EE03E86DA1D2543EC5FA019D1F972B2EA39CD4477AE3A14057AE08EF0DAFD2C2DCB1F017FA8F38D9FDB8CD25E2F11DE244CFF6A802925892E412A3CB88B801C56B1EF1F837987EA700389355004A8B905C13FE45FABC7ACA84A9284C99266474B8EB279CC4FCF1E5D9397CF13261134A413B9AED7FAF5A476AC5CF4861C1C4776B0E8DAB7DEF0933104A50A0762094A60D8103AFDC0F4E738DA4E0569C54B0B98684B924D6ECD5DF61A7587B839D2CA1654001C35A5A87F9DDAEF48F33BDA9ABF2F4FB577B32B6E368EFBBDD4BC20800ABFCB372424DCC0E9CB7E98EF9D90C2CC392E604ACB2658E100D4D0DAAE7ADE388F6AB17874E71292A97FF00E630346FDC2A36F623D30A31C6CD3AA3C219660721FCA4C5B9CDBF1C7259B2509C6E256A524A8CC3C2EDFF00222DBFDFC23AEE5B342F2D9440E11DDF9B871F9F17E71B908714F49802E77E97F81DFE6061CAD52C4A60CE41A02CE1BFC7973AD6E5C9C4AB1C5452A090B2C482C2A77FF3D4888E6B2E3774AEA26511DF2F26CD12D091E22285F88E5BFC46F8DF2B9DC18FC299859A721A97216920817F5AD3AC3FED6611589C871A07EF4E1D756FFB0E9E6E7E8098F90FA6ECDA9EA7516A6CD357A90C3633BCC56D78924280AEA8200283D2279DCF4C7D2EF869DA6C5CACB30DC1296DDD203D69F2800DAAC757BC7C4BF8C792255DA1C50E2048C42C5F751D743F4D9EB0E8EE76D51D7B74FA66943CCE5EE35C4C349F155265370E04F123840B998DE77C755FF534E272EC7E2312A2B9E994BEEF8C90124A486E13436614A748AD64395230D9865E388042A6238CDC5D37D1A95D478D7DD6EC934769FED6FD96E82B337C929575AEE5B5AB7A987766A5B5529594F13E91DE8928B49079729C7CDDED676B731CABB6D394A339027E300487504B05B0205850B9661E71F47724EC46599C762A64DC22A5CF9C8C239084A5441E07A90E0171CCF311E2EEA7CFC653599E69EC969052A72EAAA969D4148EF29D21D73861C52429C2A026C48000EB18F76763710ACC7B392B309DC6168C2F15492144CB35634A31E6795447CD3EDD65389CB7B5E70AA92A42558C290188FF00F319B9F869ADE3D58FA3C3B28CA33AECE6BF5BEA2A76733467A406175C84A52834CF2DA50497A5224DADCE37B63C55F157B6389C3E73324E1714501135695B176F9A9A1F1711F48FE057C3CC366191CAC462B0E95F14A41495258074814D76AFD691D5CFA403B28CDF24ED3720A9D3540D51E4DA8BEB7F5B094B6DB4D2699A4849E22129209322201F3C760F81F9FCFCC30AA973318A54C40485A8124BA8D280DC78D7CA391FF531D8D9191F02F0B2C251F31570A40A029ABF4AD746B8887FB20F66D91D476B9A4F2FCC6859CD65756AA84A825C4A0A5A2B4F1C71A45C5A472816C4EFC699F9865D951C4A7319A014FCA975077206A473A8D2F1CD3E036024E6B9870CBC1A715C0B4F79404258D5FE53A0AD7AB5045D1EDE1DA9E96ECEBB5CEC972CA3A0A5A5CA74EBB5EAD48865B42B81B710D2E9F8D9420A956981C2666D8E19D83C266F9B23133CE266290B4A9D64A884B850DCDDDEF4A9348F58F6C256478491264FFA6C94AD80092948515001EE01BFE2D48EB97B607B5EF62DDA7685CBB28D06C37519BD2D3210E3832E76894D38037C652A718471EC762769E77EF3F073E1B6759A6638B9AAC74C9B2913905BBC2B48471925FE62D4E8ED68F3F7C431809981693804619625AC06481C6480DFDA34634DDAB68F22739D68BAB6D0E0A97EADC1DE175A4D33884B026C0391C2B1020F0CC45F79C7BFFB3D84C9F2597FA5C462E4255292848599882A5961C4384AFE562750E4C78F8767F375E3311311859AB965648012A00004EA017E474F28AAF35D4B59561468E96AAA409934EC3AF8B1DBF94857A72DA0F41D07099B767247089B99E1D0542814A46875756FD7CE26B0FD94CFA785775974F98CD6428EF7F969E3E1159E61A8AA0294D3A87699E132DBE95B2B3E5C0E2524C499F4BD862F395E2328C6B1C262E4CE701B8549376D028DDA8FE71BCFC8733C00FF00E6F0B370E752A490EDC940575D85DACF09CDF3DA8209E3299B03313E9B4CF31E91899C5FE932F94666216994801F894C186A5DC7D5B5D042984CBF1189253265296AA330249F2D0D869E31147EB2B5E6BBC3956695C82470FD5A96ADC41837975A6CA52204DD5D205A04049ED7764D13C22666D8497312AE101531018920070577EB4899576673DEED43F433D12D49AABBA5916A5386DCFF0088FA24FF00C3F34FFC4F38F69DEF288501A4A6D32426A521C5A78A9DE3F65E128248E8279EC4E3E6C7F5FBDA5C0E3335EC649C163538D4C95E278D522604865AA5900842AADB97F3B7AD7FA5DECB9948CD5799A4A030215365F0E8AA7CC0077F2EAE23C90FA4F9F799F6D1ED756B1C2555196A65238504229624204045A2605EE4E3D39FD1162A7627213278569C3A254A290B51506A93F329F9EAD63AC56BE39E5584959AA7F4265CC5198A7086705E96BD741EA1A3CFB62A6AAA96B14ECBF544D9229D972A15249E4D25667CA3F1C7BB3199FE43810462730C348EEDF8B8E621268F4AA9361E6F1C1734C9F3198A93C7849C525B80842D4EE06C08D75DA123D499CD2F78E55E5799D2B523C5534354C220EC789D6D222F3BFBCCDE1307F11BB1588C51C3CBCF708B9A5410940992C9772187CFE6DE10F53D97CDD3290AFD0CF08E176521428C1B4766360073B4332EA9D75410D256B52E7850D852D4A22660264FC26224C62ED3331CBF0D253899B88968C3A805A6628865248705C9666E7E17847FD1F1B2D410AC3AD2A51FDBC25DDF52DE97F186EAA5D43062A1B758528F843C85B73D63BC026046D244EF8532ACF327CD57DDE5F8C953D4925C2169241ABBB13F4B36D0FD792E370C90A9D8698806A92524537A86DAAFBD748481C71E3C0CA5C79667C2DA14B51F720127A9306D7EB896C663307974B13719391211565AC8F17A8F74D61F61320CCF1C954CC361664D4A3F7292951677BB258D053ED78D2E9A964F0B8CBAD2B925D6D4857C160131CEC7E186D97E7D93666B28C163E4CF502C52852491D589FA427FE9D8996A32D72D499828A0526EE69B0F7CE13A5558F71772D3EEF0DD61A69C584FFEAE049299E40C4F2C3AC666795E585031B8A9520ACB242D690F6B3900D4EC5EB5348772F25C74D415A30D316848752824F08BD7F6BB53F98D68A9712EF74A4385E5FD96D2DAD4E123786E0A8FB87CB0D319DA3C87052933B139848932D41C294B400433EFEDE12939662F1333BA91216A5A4F094A52A517766A5AADD7CA1CCD2E6E96FBE5E519AA59DFBD396D586E3AF7859E1F3DF11586EDD76471733BAC3E75849B3096094CD412EEDA178959FD8FCFF0D2FBD9D97CF972D9F8952D6CCCEF61A08D2DD653394D52D5532424800B8A25B2D284C4A6CAB9226622DB8B61CE6B81C3E3A4A71D22705F7693351C350A08054E5A961476DB788FC160CAB12996B4578825448B0763D3A781E7ED87D1C5F46D7651ED01A2D1DAD76D5AE32BCAF4AD3B89A84D1D656314EA7514EF10524FD65A7374581078B90BC1F9A5FD527F5419DE4017D9AC9B289F8A9C53364A972F8C04708677082F67BBD3C63D37F0FBB2194A9289D331929165709625CB96297D6DD23E8A352763BECDDA0BD8D7B435762D94652FE4C9C86A1A7B3A453B6F2AA1746D3EDA16DBCF214A212E20DDB70C8E626FF363B07DBCED3E63F12726CC733C5E310538A9B351853366A59D5C452A4F1071703886CC184764CCBB37835E5AB972F08853240337841715AD459B5F5BC7CE37D1D3EC0BD9C7B4E506AAED5FB5CED2B2BC9F4A6439EE60E1A2AE14F4A5D6D19A54A3BB014FB4E2802D40213B444E3E907C52FEABFB4DD9AECAE5D91E4DD9EC4E3F159AE0E64B13E5A9694CBEE258E251504101C56A43E95B50324EC4E469C619B89C6C99650B1FEDAB841249B00F4AF237D9E3E9B321F67CF66FD2BEC9FAAEAFB23C9F24CE3237B4D66ED8CE986987455B941495282B4B8A42D40A5D41921773D6063E6164DF157B5DDA0F899819B9862317215FEA282252D7308495CE4F121A80B3B07A8F37E87DA3ECCE00E4CB99859289A132DF8D207CAD7AB5776DF5A47E7EB99553CAD5DA81FA670AD946A3CF5A4B53E14A5BCCAA5B09126200004011D06C31FA51F85AB389EC06553B17F2CC9D8294A73534969F534A3B11D23C5FDB3C261E54F9C94949505101340CC5BCB4D3ADDD61A9E179C360A20152428409120743783F3DF0D64CE50CDA62250E24998C4836A9B36F5F50D578E6D2240E30E011FDA4EB537A68DF4BC2EA5AD22C5422473E91B19FDF3DF17B9D870653B7F66CE6CFCABE5BBDE15CC30EA4C8701C0069D28F4FCDAD687715CA44428136BCC6DB72B72B73B46D18ABC896A993660092C341AFDC59ACC1BC62B3224BAD4EF7DBDFB2D787EA0CC9700C9E5CF6E5204D8F4F913CCC46195574B06EB7AB81AF8E9CC18DD72D9C1A8FA3F5BDEE225B419A2E6EBFEDD95B79DBDE3DFD6715AC7619469C06AE280F4FF01C5BAB329A9B38FF00D5CEB4B794762B54E6C071A83A41333E237F58DBA5EF7DE71C7A565D225E253C12921883448152281C6D51B4339649559857C6F7DAAD7D6281CFF365B6EB4FB0A9711DE44999E4678A6C7AF58C769ECFE110BC1842C3215C2EC360E2CDE21CED13786AF8375E9EBD1B5178A7EBB33ABCC332397B6477F5B534F4EA240801D712824721014762248DF125DA5E2C2E54461D4A4044B515106AC2B73CAA7D889895278A6254A4FC86C79B0E5A901AC3AD63BE792F641A23B2BCAB2CA9CD69855E76ED326AB89D4AD694ADD6D2E8B282907EDCF3DA48031E5F38ECCB35C73E1B1737F4FDEA90085AABF310AA39208E7F888CCD676264CE0B0B29516A804381414040EA79B934AC573AED1B387EA1C6A90B34797A014A034869A21116FB294AB94FAEF8EB196F667032A44B99350A9B3D41255C4B591C4C0BB17162697DAD161C063316BC1CC2A9A543828EEE457C6CEFCBA5285CF359E62BAEA86E81D76A5E724A94BA8500929499E14AD445FC85E3DD8B22B29CBD6A92956165A96183809716636ADA9EDA23275CD5E3546628A92A5901DCB876677E74F3A98AD6B350D7BB46E2EAEA453BEEBED0727857094BC018BF4990236DB1359E76764CCECFE365230E90A561A6540AA7E451156AD3DE9178C405CBC5E0FBB0CEA4B80F40E9A96F36F311F6FF00F44CFB487627A07D8CBB31C8339D5749499930D6646A43A8292A5AEB0AC0054A093626627CF1F9D6FEA4BB1B9D49F8859DCF5C92705371044859500ECE08FF0095F4E4C358F7CFC27CD64E5B92E1C14FFB9DD8E335776A58789FE5A3D3C67DAE7B07A893FE35A0513B789223FF00783D368C79E667657311C24E1C8059994039DE86DC8C75D91DAA91312B2A092C39967F06F7CDA305FB55F624AA86186B5AD125D7C90DA000E070CC09F19E1DC7BB6DB0CF19D97C6257294B42A5A9C355DF97F9BBDAB0CD1DAE90913425600D6F5607D456DBBBB831D07F690ED5FB27CD3DA6FB08D495F9AB0EFF0085179EAFBE43842426B29D00294942B8556BDC1B74138EDDD8FECCE3E6F67B1C6493DFF749E04B0D01E2BB5EB7B4705ED876C24FFAEE140AA0CE72412EFC405B9791FAF7968BDAE3B1147749FF001C51381D6DB4A29F8384B2A420050278A4C9EB1B5A0638D637B25982F1B3D2B796B4CC5380417254FEA5FA73AC77197DBBC2E0B2FC12952C282E527889A30090C0536D47DA256DFB4AF63B52D17D3AB290242642B626D22DC40CEFBFA7A88ECCE612CA122515B9B920077D9CF21B35ED12D84EDCE027CA331284B84972D504F36372E5C0A39BC42754FB4E7636E64F9B32CEADA572BD596662C52B009056E3D4AEA001E21CD437F8EC70FD190E2B0D9860538895DDF14D965831765A6ED43B78D4456B3BEDA8C46539A32C1692B09029FDAA05CD3DDA823E726BB4D6A1D439C662AAA74D2E46E667983E97C29278D976A9E701001076563E90760D587C2E43841DC85CC3212C1AAAF94063E8FE11F1E3E27E67FA8ED1E2C951FF00F10B377BA8F3DEE1F76D1D5A15A4F42B81592559CCF34752A43E56C2D2195A92522EE05257C526FC8EFE53B2E4E2B3454D95DCAA44A7AA41278C39B6C035999AB668AC23303225CA5057FB80122B66622BE9EAD1EA67D1C3DA356E6B4DAD74267D5014D965A4E5ECACA600A843AB73BB40B0B284C0DA77E5E47FEA07B392F2DCC32FC7C99211DDCCE359081F310A4DC9036AB9FCC7D02FE947B5666659986131F33BE4CD95C284CC53B5160F08579EBA691E6DFB57D02F43FB446ADD2F48CA826B336CAD9A6436D1850AE711DE59293301D2609B795E3D03F0CBB5D82C6F60569529089D2706B4A8135044B291B3500F0E748E49F1ABB1E319DB5C26270F2190BC5B92948ABAC56800F46D9DDE3D63D679EB5ECDDECA7A4B4FD3D70A0AFA85E55514DC09EE9C70565753543E0410612975415CA3717B785F3FC9A7769F3FCCE76154A9A11885BB025BE657E29A1AF87B5BB159B49EC8F6772F913C0940E1D00020020F025DF7B86F1140219FDB652DEBAF673CB7B42A1A84D65465397D0AA9DF6520281A92C21F3C683E466F3F3C74CF833982BB31DA219762014AA7CC9685A9668CED650DCEDA5ACFC77E3BC8576AB239936534E2A9534A384026B4D37B80C28D778A1FE8BBD38ACC751F6A7AE3362A552E434B4151953EE712D3E0A675555C04CC41410A8FBA23A6FF005398DF9BB3D83C3AF8D3981095049A2788CB0280B7F73D5E28DFD1B7674E447B478BCCE571197F34B334587FB960A0478383D2F1D00EDF3B4DCB3B5FF6D6CC1CAD6C57698AECE692810DF787BAFF002FC34CE0481B12B490A81EA2F8BA7647E1F4EECC760A7E2952D4A5E2704660590470BCB2A0C5BFEEA6BE04449FC40ED2C8CE7B5D2F0B8629E04E2420A50A0430500D4F3A6D631D85FA4C7B09ECFBB23ECBF446A9D0990B397BF5B42DBB59DDA882F71A29E49E202D0B5796E76C3CFE9073EC42737ED665B8C9866210660725C83FEF70B29CF0B10051ACC6AC218FC68C99183C26453652693929E2012CF496EECE68EEFD6DADC5EC3BEC93D82F6D9ECCF95EAED55A69877387A87303535EA75C49A782E214E10980B800AAE6D1CB1CA7E2E7C43ED4766FB6F3F0F85C6CF121589504A12B57FB80AE8007A338D2FB88E87D81EC064D9BE469C5CDC1CA0A449054B29490E52EE695766F13E1D77CB7B55FA307D95F5337D966A5ADA5CE7575066CE50E74A5D0E6150D2DDCCAACA695B0EF03AD00D77A124A55102F187F2FFF00BD4ED5E0F119A617178CC26151251370C4052C21900AEC6BC446BBC5C3B2C9EC56598D56031587C199A66776C5281A90033737E8417878FA4D3D843B14CDBB0EA1F692EC3F29672E6F2DA36F31AB5D138E38DE60D661DDF7278388251DCA16491C2798306062D1F007E3B76A724ED88ECFF6AB319B3947132E5494CD74F02428853D4D081AB0B1B8880F8E1F0DB28CC72F46332AC24A948EECA94A9612D514B0B3EDCE3C95FA3EFD8CAB7DAFFB5072873D529AD09A51F4AB3B7B825B525C0A52525692950F1B651E156F36C7B53FAA0F8D583ECA76572F5659344DC6E61872112E5CDF996B2945B87626B7B4713F853F0CF0F88C7CC33D2172E52D24852416626EEE28CCD7F331ED076B5DA3FD17FEC44ED37657AB32FCAEA3324B69A5D4714B53982DA70B63B9529C6DB78B654553E150BEE4C63E7164B86F8B7DBDC662B32C1CFCCF0F216A13249489AA4A03BB3BB105FF00168F54CEC1F63B2E912F0B3F0B8452929E151504024D8D1BF8AEF1DBDF602D2BECA39865BDA876B9ECBD5AC3B9676954F42FE7397B02A1B5529CB5A712C0522A085A78C95010948E5046DC7FE30663DAFCB73DC932DED38C44D9A89FDD89B394A257F3201531729091A3F3ABD1DE5792E513F038E393AA5C80B40F96530268A37074F1A7311F2D9EDD9A0F5876C5F48CEABECE34B65EED466DAC334A1A4A4A169216B534C53A1352E955FBBEEDA25C85471011D4E3EBE7F4EFDAEC8FE1E7C239B9DE3B1B2A4ABFD3CCCEF145293C5C059342093C54E57358F3EE33E1D4DCC3B4015899AA9A9EF8B25609A055C13AB55A3DB2D21EC57EC31F474F627956BBF6A534555A86AA958AB7EB6A8543AF5454B8A42C34DD134A70ABBA5B81B3C283B49006DE1EED3FC50F89FF001AFB4999E1BB0F331872FC36226A672F0F314A010A52C24802B5636F08EDEBEC6F65F26C1E1978F93875AD284901410E4802E48247E5CD843AE8CED37E8AFF006F2AD1D8C694A4CA58D699834E31434BF52AACB54C843656DAD0FA9A612F153402880A244C1BEFCFE7E59F15FE1E6608CFF1F3F349F2B053113664B519C12A2140A81724338E90DE68ECAE3C8C2E1B0987750605212785A9B397B5DED68F1D7DACBD88321F60BF6BAEC9B33D4CDFF17EC2359674ED3525229B506128796C539429E1DE3A65EA800159F43C3B7B8BB2DFD48E3BE26FC3CC660A5625597E719560D689A9E22B521610A0826DC5C5C1D45758A2E73F0FF0D2F32C34D4E113DCAE62492122A388122DABBB73AB3476CBE995F611EC7B40F609A23B68EC4B4CA74F30DE5B435D9C2A9DC79F4D50CC51485A512BB2203AA22DD7D71CE3FA55FEA0FB519476C336C176971F331C9FD6777253314DC23BC58701C9A863A8F38DBE28F65B2EC365584560F06842D329D44243BB26EC0BEB61F58EB77D0CBEC69A0BDA2B5EEAECF3B48C9115DA5F4A379686DFA9714DD3B8BAE6149578EC9052E8B4F31B49C7A03FAD0FEA531B90766B2CC264188386C66310A226CB554B942943875A1ABD5E25BFA7ECBB2BC6E0B35958DC14B9CAEEF853C4134A2C3D41AFD77148CFE9C5F64DD15ECCDAABB21CCFB27D389CB322D4633E5E7556C294EB01146DA0B01448291C4498BFCB101FD0C7C4BCC3B6D8BCE26E7799ACAB02252D6664C241E30A51A1506B6C45F68E55F113B372324CE3113A5C905136728CA4705140ACD1EA035F9DDACFD87FA2DFD917D9F35B7B1EEBFF00682ED6B49359BFD7B23CC6A324CC2A5E7996D353963756DA8A00849979B48E524629DFD62FF501DA7C27C41C9F24EC7E70B9185C04E50C6CB90D30CC1F229292C5C380776D8BD7A9FC3CC8F2AC66478B18FC1CB13264A696A5330252AAFEDAFBA433FD16FF0047C7633ED01946B2F6A3ED7329198689CB736CF1CD319170BC80D51E519856D354789985B83829D2BF1209E84E3867C56FEA47B5D9965594653879D88C2E2B13284A5CFEF540A0808054524A5F8AA7C1F9C2BD81F875976133AC563674B973A4A269584148660A510CEE282EECE03C76133EF6D8FA209F5EAEEC8F37CAB2FC8AA72466B32CA247F07CC5C73EBADB6FB2905F14C140FD612920A951B99E78A9F6313F19666639763324CDF31C62A6E2242A68016A4AE5AA624CCA9240F95EDCAACC23B1F6C71BD9E9992CCC20CAA42572E4A92662529BF0900B04D5A80D5CF947CB7F6DD98682A9ED2754D0690A448D286B5E772AAC69C7385FA7756E38D1088E26F852A40009E77BC63EF5FC2D19AE27B2182979895FEAE6609099895D4998A9490B725EA0B9602C0DE3E7D66984C361F1F8E992F86B3144240FD9F329AD43EEA5DA204E7699DA05168C4E8ACBB50E6F43A64D7D10EE28B31A9A50106B10B221879060991D0DE6C4638DF6FBE086071B85CDB35C76024CF294CC9A17325A4AAA16A35209A0E679984BB3798E2E5E6F874CBC64CE033405490EC9AB0ABB1E63611F719ECCB4196577D12940C55079D6DCD299BA9CAA7DC75C71C5F0BCA256E2CF1AFC7B1528C998C7C5CCCB0B87C17C7E46130C844AC2231E89699290004D92599AE6E1BD23E876569953FB10B98B960CE18572BA12FC14D3CBEF1F1263B45D6195D26A5D1596EA0CCB2FD38ACFB37416286B9FA34A93FC52A5442FEAEF2146E49BDCDED8FB5123E10651987C3D938FC560244E9BFE9C572CAA524A83C804949524A83BD5887E758F9EFDA2C6E6327B52A12F1B350062FF00E902B0923BC6625C69C888FB62FA37436DFD10F45C0FD454A91A67582955352FBD50EB8A5AEB4925D794B70DC9FEA81E58F87FDB0C1E1B24F8E786C34A9489586959AA1299694A5213FEEA1DE81DCEEE7C9A3DDDD9793FAAEC4A97894F78B5610152C977F91C13B6E1B6E71F0D41E4FF0019D517B1D4F9FDE7AE6F567CB97A48DB6C7E8E7B00A188F879911C3B07CBA58615A8949B3035F060DAD63E7B76F113067F8C96147804E5F0DD802A3FC39F106F07D6386A5E954FD98127A6D791711D3117D9EC22E566589993417E371C557D4DFD3FCC56E4E19425CB2454025F5AF2BEBBF4D442B65F4A549F1117D8133B9DBF111118E9C7826CA5310DC2CD7D0FBB51F70D0EE6CB070EB0A0F42DCEF4F5ADDEA21DCD581C104806C04932237EA6F6F33E51882C348EEE6CCF9581347D1AE08A8FA3F28AAA241EF4B503D5875A537EBE46EED495890078A368BED3D3E23F29BE179A8490C589624F869F6DFCDA313648276D542BF9E477DED125A1AE4C99267C30677DAFB99FC09DE4E21B13265F1D520835622C4EC74F388C9F29945C5363CF5A1AFA9F38BB35566EB3C70BEBFD43CE36900188FC0922390232E2A9C9530A9AB077DFEC7D98889490A55ACD5AD7EBAEDA738A4F33AB7EA52E21A5C3A2E825406D1363E5CB68BCE3AAE4321387929EF43A05F50E5DB4B124B7B1161C248B52A0723BB1DBE9BC55D5D555F97D6B398A163BFA5ACA575C3292785A7D0B31FF00D2920C5AF8CF69B0C313835CB961C290B4816A28105EDBB1B78C5A70187965491387FB6012F5A16A73D06DA7231EC2D0E6343DB5F64794EA9C890DD4667945070670DA16953A8521096592A6EEA121063C33F7E3C9887ECA769A7E0318A29C3626705604A87CAE3E69B7A0209D6F0CB37C009C25CC4A6A824289A382ED4DF7DDF58F3FF55D53A8A8ACA6756ED33ACB8A429B295A4D94531C8F974DCDB1DD70D99499F230FC052470804820B8206BEBAC38C2614A306BA31092CFBB6C3D19BEC6A1CE2A1B6E94D552D6298A961412A012A529C0E2A0DA64409E7127A0C5AF0384EFE64A524D8855BF8A03AF2E710793A267EB485A010A98782AC181A8A16F0FA51E155F574F58EBB978796F3ED86D6E28A54890A0144126DB74F77417FCC241959262E7CC4A512BF4B31C382C532C87BEB52CEFD63A16225A9388C0CD029C69AB87A902B7D3AFD63ED77E88CF630EC27B6BF627ECBB55EB6D3F559D57BA33712D66B5F441A28AF536ABB0E212E714011702DEA7F365FD5776CF189F8939D6065CC12F0786C47FB44049E2E2249AD598BFD2CE23DE1F0CB234E3B22913520F11949E2150CE06A59F5FA3B523D456BE8DBF65AA623FFE03AE03911A9336303CA1FF0021D463CC333B578E584BE2980141C29D7EC2C1FA474DC3F64C244D704F10B329CDDF97AD18C3831F47AFB34D0BED3B4FA1EB42D0AE20E2B50666AEECA60A6389D26FE5CF0C31DDAB9E152C4F9C95936F9406F001E9EE86AC91D9204CE025100DEF5A3FB60199F58E8D7B457B34F63B90FB4CF611A5D9D2D50FB1AC1CCF9A52179BD60211434C9FEA53849B120472B0C769EC576BE6A3B3F8FE09E1333BA1C33784167E270DD287626D568E0BDB0EC71FF5FC277608499C1856EE1CF8F883AD8C776E9BE8F0F65F3DCD4AB485635565B6DCA8FF00E399990494050801E001E4607AE3924FED5E28E37124CD1326198A2E400D521C001B6A0B58EF1DE25FC3DFD5E5B81EF16C44A4B062744EA0E8DEBA6B2647B107B36D3B229C698AC526200FE31997DFDECDED68F3C03B439AAD49299818170191C9B41AF3A1B81489BC2FC3993230EB48554A7FEEE7CFF817D4B4373EF61DF66CCBA92B734674A568CC6932FCC2AA8E737CCD490B6695C7495254EF0C4A07DA91CE3A3E959C63B178EC1AF10B0A289F252FF2820296806D5B00ECF50FD28D9D7638E132ACD5810F26656BA254CF50FB7947831A8B5585D456D065B50728A0A5CC6BE999640FAC1E062ADC6805289E2D900DE37DE44E3EA4760F2892AC83033D127BE52F0F2CB92DC24A126D50F577AB97A5488F8E5F14303364F6931891C494A3113372FF00316D0FD39EB157E6DA919CBE1798BCDD436A5781D84A0C922E40F14926D72676BC0C746CBB234CB13172FE4580EA05360493737A1D08F431465F7E664841258D0726605EFBEAFBC7643D8BFB54CD727F689D274B96075594666E3E8AF5281699504D390D7138B0126E6DE2BEC271E5CFEA1B24978ACBA74D080A5484AD5C406C1E80835A3787311EA5F835DA09FD9DC760E54B9851FA85A1376FDC4021AAF43AD9EF1E95FB45F61995EA4F69BEC673E6F2B15CAD6AF57D4E6CA292A43472CA765CA72B51494DC8944C49B0DF1E36EC176EE6E5F2339C12A62A5CA96932C20A8BFCC169FDBC8B75BED1EEFCDBB132B3A9D94E63DD85AA6844D2784528824DBAEBD23AD7F4A7F69CC52E7FA1B413084A19D334CF273069A7C6FDC32BA7EF1B4AA525251299026245B7EFBFD3C761D3DA34E6F98CC1DE89EA2B0E976F9A61D47D7978729FEA2BB4733B289C9B0B2D7DDB0082104876E00CC36DABD358BFFD99EAA97B78F624ADC89D712FD65265798F7895381C752A654FAD80A049298E04F082013CAE71CD7E2CE0E7761BB62AC5A5E54BEF9250C0200E020166BEDA50C59BE17E151DB7C97867FF00BA7BB4B05391F303BF5AF86911CF672AC47B3A7B09EB3ED133C0296BDD6F51D1D4B8F8EE5C5835F5D474A49500612952786D7E538D519DCDF89DDADECBE0A6CC52E5CB9A8E034570F01965B672CD5B6D175C5F66657C3DECE677899284CA54C92A24A592F45D68DCD9BA574F9C3EC1F5EBDA8BB72D195B5B52A5B95FAC2BDE2932B5BA87736E26EC24C00A107EF8C7D53ED664186CA3E162B8E5A50519594824004B61C8A3B17A73158F017C3FCD67F68FE214E4AC952518FA3925819A7EC03E9A0BC7BC7F4D6D6FF09EC47B2F57D6453B4F652CA9692910A866948B58DBD31E0EFE93F15C19F76C8B904E215F35DBE79C2D7343E5E2DED0F8E39209B97767D93FB25A6800BB4B7F13AF808B4FE8FACFD549F477D567542FADA751A6B51A9350941242D2DD604A936894A8026098DE7149F8A586979A7C5BC1E1A604AE5CEC74B40492000EB4824D9A8790A1E7171EC14B184EC6631228A4E14F096B325479F3D0347C5C675A8733D4FAAB3FCF33FCC3F8B664F6AECCB82B9D400E2CB19DBC96B88993FC9094000AB940B1C7D81EC77C2AC9B29F86BDEC9912710B9D960592109F915DC71000B106A48A3171CDA3E7F67FDA7CEA4F6F92893366F7631E9494B90083380E8D5E5E31F657D9FBAF6A0FA23A8EA350D51CC1674DE661E5B80AD4E16DC70530264901AE1481702009C7C62CEB02B97F1C71B8192938799FEA00219C703289A33338A8A6FA47D19CCF2FC6633B0183C54C4A9415820B59209249402E6E472DF68A37E836D3D97D07B32F6959EB85B39ED70D46E553EDC38E452556666907123888284252902463A27F51133192734EC5E1E74D5CE9689B2C1E25BA4A4992FF00292798DA39F7C1CCB958939C1E13C487090C410471F206ED4FF11F2EFED8FA8F52EA1EDDFB4CAAAD79DA976B73A79AAA1564B8A4A296A1D431C21E24B7084A638627CC63EC27F4CF90F64717D89C395E030857FA1905733BB944BAE587513C3423E66249203D5DDF907C4D999B617365204D9B2E5F7AA0CE4502B7A7B2F4B1F7A3FF000DE663AA9DA2F69CA1CCAB9FAACA72CA6D37FC1A89C052CB21D69F35019512507888957081B7A63E5D7FF101ECDE4B9676EF245E562428CCC4CCE3EEC207012A433B683CE3ABFC229B889D8498A9B89513C0010493C4E0DDCB79D7ABD5E7B03CBF24D4DF4D0F68D575CD30CE6D9355D21CA92FF03A0177285F7E5A6DC94A89008514A4C4C9223152ED6CCC661FE0B49948C44D38695879616842D690BEF1496A820D09B30F1022F08C2E1FFD53884F471F192D4DBAEDCB77B88EB6FF00E230D59AD55DAE764D903A9A87749D28CE52CD0F7C5AA5AC52D868F1AAE107B8761694A8192200B63D3DFF00C34F22CA670ED22F30548EFE7770654C9B2D2B291F395278540BB8A170FA93148F8AF3A6C992832A72827849E04A8D580377A7361D291E2CFB2666FA9325EDFBB38CE748E72F2F57E539ED1B74CDD3346996EB15B52C35508213C29792DD3A949921462488C7B6BFA81EC7F65476273EC4FE93088C423093945932DC321452A0C9B967A5059C5E3987C369D8AC6E745D4BEE4CC40092A2A0083F31725EA6AC6D1F57DF4EE657923FEC8BD9F6ABCD99646A8D3949A7333CA1F79612F37501FCB6A6B0A4AA0C9524C83F2D87C73FE96F23C5768FB5BDACCB30EB52B0F3A7CF429491F2CB4A0CEA10ED50001401A8C418F5EF6865E0B0781C14D9851C72D095558392013737ABF56630F196E6C7DB87E89E6AB2BEA1ACCF3F3A7DBA6532036A768FF84389658909B9E2453A6091F2C42E6B879DF0CBE2F4FC3941978638827BCB267900A8D2A070977B3DCDE2A99F60F0FDA4C995DD11314896470A43905801B16D872B3563A8FD8A6643D877E8BDCF7B415D40CAF58EA9CE5867EB253DD55775976A834D716591DCC0936817B6273E21CDCC3E3576830D8096959C3E4921656A014A48EFA53A4B86A120B579D59E203E19E5E7B32719DE3A3F50B02B4601441E573BC5A9EDED95A7DAFF00E8B1D29DB250BE8CE35150399652D3543284BEF819967749435012A471281EED478C4DEF24628FF0CFB77987C09CEF3BCBD6B992A5CF284AE695143F0850173BABCA85C45C7B4FD94C1F69049528A14A7252C94921C826CC4D40BD5C3888E7B42D72BD89BE877D2FD9464B982323D579CE541540853694D43C330AE69FAC480B214B05150A077001DA76E91F09F21C57C6FF008BB8BCF66838BC1A274A33E6295DE252148F97E524EA3D0C547B5394CFEC764A9186E2E12820000B903722B6FA5447523E874FA4FBB34EC3F4D669ECE3DBA54B590E5B58B71AD3D993A953CCD5273971D7F350E36D2421BEF3EB0471BAAB4C836C76AFEA6BFA64CCCFFA6669D98C3AE64DC2A0AE6C99287131410909AA4109621D9AA4EF7A87C34EDF19B3F1387C4A08257C20A9554804824BEF5F5D6DDE1F694FA20BD9A7DA6B2BCE7B5BF657D4395E4F9BE694B559BE6147401399AB3AA82D395094ADC53AA142A2E1544849515584838E71F07BFA83CE3E0866986ECE76F7B389981731121189C4F04B32471048290A96EB0C45886AC7A0D59060BB4592E3F112260E3EE4A82407E27492D7DFDEA7E40BB5DD09AABB12ED0354766FAE3277329CFB22AE55355D33AEF7CE04F78A0C3BC424C3CD04B800FB33048DF1F6F7E1276EB2CED864F97E6D8032C61B19290B9694149487487629A50D3ECD48F9F3DA8CAB1180CE71D875850509AB090411FB496A9B50F5E948AED154DADD6D0EBB14C2AE8545266E3BF6CC72E639EC3963A6F6F932A5764B3498B4A7FF00C24EAB80DFED2EB434A79F9BC7767B0CD98E1D64007BC0E7982057DD5AD78FBEAF662AFA773E880CB14869229BFC279D8EF645E3EB039827DDBF524DB1F9A1CDF855FD47AE7713FF00FCDD2424D984D1AB81A5E84599CC7BDF23C6A7FF00B26B95C54FD310472E02E763B7324B5A3E04330A827526A39794298EA1CDC8DFFF00E6753EFF008FC36C7E8DF26C560D5F09F08BE14850CA4A4D451E4000EB73CEF7B4789FB418642FB4AA25001562814ADFFF00F23F9D3EBB53EF17E8DD7C39F43DD125091C08D2FAB036A172AF1D6CF29989FD6C4FE6E3E364B549F8F1317254ED9BCA5708714EF52687A104FA55C1F727663853D8DE07001C29DADC157B0153CB7BC7C2A3EFAD39C6A42018FF0013EA08FF005019BD64C7327AFA5F991FA25F8098838CF87D9226657830328126A6B292DEFEA2DE09EDCE042F3EC41480C672DE9CCF5DD9CFD5A3172A549A9709901411C2677B5E27E605E3974BA63F049C14C9B36581525541AD7DB6BADA22315970932A5F086A3B806D4A0A69E1A6AECA115465266E0F23C87DE7D63718322C51C52E625CB75B1AF93D01F5D221D587E397303513A1F16EAFB6FABC38AEB4422157326D73E9633F3208F291890C534951090C4D9BCEBE1B79BC41230CCA5921874DC9BB37BB42DA5AB55A5506DFD5E963EF3F872C45AE6BD5FC5ADBDEEFE95DE119B2039A3020B86DB9EDF5F52FD4D5EA491E2E917E91EF13F0DB0CE6A8AFE660143C7EA3D988D9F86AA986CFEE9EF5D22ECD40F90557B78B993D4DA3E47FDB15AC1E5E95B16A534B3B78FF00377AC5670C82E3776B3DCFE4D8DDADB54D9ABE12410A20C988B4753337E5636FBF172C149125212C006A8BF4D34B9DAF16BC149E2670E77AFA86E5E0E4BC56D9CBF2570A3799BF39B5A4733D49336318DB1B244E42924536D2C34E7BF268B6E1B0E0814D7CEB563D43D69D2B1D8BF644EDD6AFB31D768C86AEA4A74EEA7710DE69DF2B89942584F80042E42788A88F0804DB7DB1E5BF8C3932D58BC3CC972495A78CCB524170A2285FCBFC5DF62300674A2AA0E023E56078838366269B36FE3DF7EDCFB25C8F5C255AF34025A348DD38A8ABA36133F5A2A6813C3CC4104F8419918A6F65B3DC7E5C24603385A84F0A3C0A51A293C4E1C82C960C189A9E704CC20460A6AD2070941AD058359F4A9FBE91E5F6ABA775AAE7D54B4EBA179B70A1CA2752429B521453243804F111C42C37168838F4C765F3CC24F5490262492120A5DC681F57BE9A6BA8A165ABE1C4995310584C265CC7BFCC49D34B171D62B87DFAD69FAA7AB82509013E201209B47282771698B5A717AEDC62049EC8662BC3034C2CC345137428F366735DB58BCCCFF73138201F88AD0C1C9145245AD6E576ADDBF421FA081E6DFF00A3B3B225A2C952B3DF173319ABA0C1F224F5122DCB1F971FEA4D53719F10B3D52C9E3562893BD14A16D396B4AD23E8D7C2099DCE47210A179483E40793687A78FB2AA6CAA07148163F2F3B7FBDA31E7E998351E021668C08F2AB7A4760958896A0B205007A5BD3C357B469ABE15367FD31045B9ED68B7EE310F9AE5B3166594CC371AB00DC3CE96F6E211978D9604C5300100BB867B8B5796ECFE5E4C7B5B1AA57B657B27D400AEEE95FD58091B0E3A56C5CEE0F4BFBE6D8EDDD83C0CC464D8B2B55049AD2DF2A99C6FA0361D2384F6BF3195FEB7840502B3C696F9921FA5391FB7AAC8610A436F95C7794F4E08BC59A02F11EFDB718E62AC0A978EC4CC0A202A6ACB7451A75D5F6F08EED2B3A95232FC17124377496AE9C290CE7F834E8601429510B0AD89277B0F5E717B7AC61E04AA5293C35B8A9DD85A96FBC3D939E499929443304D7A0B576EAC79C326AC729DAD3B9F07109FF00F25CD477840F07F917E4F513E58525E24C8CC72F05C257390493AF0AD275A1B0677FCD373ECCE5E2729CD014848EE576BD9557DEDEB678F8E1D4F9E32D6A0D474542DAAB1F5E7799A51C00F8146BDF1B00A8B9927CADB463EAC7C2DED370E418342905411225B56CC8079DC0D46978F8CBF15A44A9DDA3C629D81C4CCADDC7191BFBF48D794F66398E69568AFD5EF16329716DB8DB6B570C2525248F0A82809EBE40E3ABC9ED34C9B87C42654BE29841E1029BD5D9A9A3ECD72639BE27092654DC312404B83D76AF93459D996B0A7D019AE42EE8D2D3797D2D7D025EAA6C252B4A45432167BC23886CA04F15C18338E4BDAEC9F17DA2C973097390553CCB99F2B3E8AE10DC9C5FCA3A764989461734CAA6CB53211325970E416282F73AD58FDEBF499A435D685D45A334A6BCCCB39CA9FAACA32353D48A5D4D377CCBA28501EE195F182A5A609B4F3136C7CE35F62736CAB3DCC72F460E7AD789C4A124A652F8529332AC5883451B6EF1F4DFB3BDB3C12F22C04E9F8894572A424104A5252C90DCDA805BED1F2C5ED9BDAD37DA37B40F69BA9D7998550D53F4AC51C39DE3605334A60F7601294C9489E10279E3EA77F4CFD805E41924E070CA2664996A09292EEA492AA915624D0DFCDFC45FD50F6A65F68733CB8489A0895318F097A0296D756D6B1DD9FA1DFB66CA5BCE3B40ECF33FCE986F2FCCBEA21A159528A7692840716E06C3CE2130A04F170EFCE71E78FEADBE1E4FC595E3E4E1967B8528F0CB4173C6A6FED0F7FA0B08ED5FD3776B70F96E1B0F879F31290B4CB492A22C000E1D85377E7179FD33BDAF694D0DECA2F765BD9F5565CFBBAC5C4AA918CBABE9C70FD533043D530197140F1852CA85A7A1338E73FD28FC32CC734ED4A71188C34E4A72A9D2D40CC94B0E165E8480D6B579DEBD7FFA81ED86053D9A9D2B0F350158890A4D140BFC9B3DCE9B79B7CD77B2766A32EEDEFB3072AE9196D0BCCDB577CED5B61A6141C68B8A5052826E649E23F9E3EA97C69CAB118EEC0CDC26124949C3E5F302B80151534922C072FE77F017C0B92995DADC4E3262811FA90B750666593ADC6ADCA8ED5F79BE9D9D6196E73D877654CE4F99E5F9A5553E5A84BAC52D7532948E24520095069D2AB0041045A27CF1F3E7FA49EC8E367E73DB554CC34E92133C8495A1697F9A6B91C4002D705ED48F717C4EED06171F82CAA585A0996800B10744DAAC35D3CAAD78FB04EB9CA32BFA322972CA8CCB2BA4CC9BD33A992ED23B5D489794A79157C03856E05137B5A6F618E61F14FB219E9F8C32E5E1A4625CE3A41429329652405209F9827845AA01ABDCE88E51DAEC265DD9DC44954C9602A5147015024B8237AD4BFB68F8D0FE20A6B3ACCF2DFE18DFD61ED599B283E2A91C1C2E674FAD2AB9E002140CCDC791C7DC6F8739663F07F0B70CAC5952972F2A53CA5A492B6C3D2A41208DACFE31E4BCC065F3FB6386C72928E0FD5A56A371598087F324EEDBC7D8F76739E65591FD132CE50EEA5CAD19A2F4F578550AABA914EA438E2C941417B8A549510044DE7A63E2DE2B2AC6F683FA929A065D364CB9F992A5999C0A0901CA1DF85855F56D3578FA378CEDA64EBF87F230B24C92B4E0D2821D2E0F00167A35EA0757631E6A7D081EDA3A43B2BCFF005CF619DA03AC65B926ABCCAB98C86B2B2B521A612BA9AC5D61256A4821D2EDB8D4041F0F2C7A13FABDFE9E33ACAB2BECD67D96CC993E64A93FA832132C924F0CB5247102598D5ABAD63897C24EDBE5B95E6799CBC419694CF9A52975003F72858B543EC2978EC3FB64FD0D190FB42769B98F69FD9176C990698D3DAA5F6EBB34A76CE5D5296DB442D6A05CAB04132A5129005E3AE285F08BFAACED47C30C966F67F1992E3D589EEBF4EE654E676294B132882E1ADA758B476F7B2B96F6BD68C5E1E74A4852B89D251576367B0B55ED6611E837D1D3D8EFB387B29E95D73D9668FED4723D49AEF2AA2A56F5F66685D3D297DF71A71745655429B5F772A4FF002C9B092463CE1F18F37EDE7C4AED2E5F9EE3F27C7A30D331266A25944D99C492B4963F238D0E8E29710E7B1FD8D9393E1712138E4105150E915093AB862ECECFB6F1F33DDB8FB4F663ECD1F4C46A1ED372CCD5BCC34FE4B9C50375B554EB40A5758CC28934CB529C6CADB5F76971517544198C7BA7B13F07715F11BE14FE8B1597CEC3A4E0E92A6216145728129FDC12A1F307F3022A824A64E76427304BA67317208AAAA2AAA96A5C37D7E813DAF7D9B3B11FA59BB1ED21AA346F68F91649AB74ED122A28EA7EB14AE3E8A8AE4B2AA805A72A5B5288525408502236F2F337617B67DBEFE98BB4B9A6066E4B8E9D2319394995365CB9BC0844A2BE1AA65905D245F7EB16DED7F6270B9D60A4CD46310A5997549E162E03D4AA800FCC7527D943E861D25ECD1DAA50F6E7DB776CD926A3CB3479555E59973AD515021A0868A544ADAAA01E3E04AA540C102379C5CBB6BFD55F6E3E20E538BECEE0F2BC623179924CA0A2998C94AA8B042900170A34E434022A1D98EC9E0BB278A13D7390A757168EE1CE84F202BCC563CF9FA747E900D37ED2FAAF48F62BD926629A8D1FD9B0ABA2D52E53387B9CFF00BE6DAFA88412477628D6D7FE52941405C441C7A5FF00A01F80398E588ED467F9E15C939A2113128992AA85A9331F849A9752812D67AEB087C4DEDA77B2F0F2F0EA2C804712554228D4D080EF7FB9EDDFFE1ECEDF34C6A4D2FDA67B3F6BAA9A5FE1540D658D51A730AF45335C351DF3CE06D0F389063651493245C1C79FBFAD5F8659CF677B468CD7012A6CD97227CD5F14B9449214A0CFC214751BB5A8224BE14F6865E2E4CE958A57CAB486E2340C0BD0DCE8FCEB5BB37D3F5DA4E8BD03A1FB2AF67DECD1CA0A9CA73A733E5E6AD50660CB8CD3943E8AB68AD2D2D6992B24A4820CDE4E247FA39EC5E6FDB0C6E7B3730C24C4CBC6A30C897DE4AF993C09525552028B9706CD6899ED6E7185CB1483865A400A51E20407ABBB3DB414B02EC0D6F2FA0EFB42D17DB1FB2AEADF66DD739965CCE55A0AA327AA0335AF6025C5D4E647304708A97533C2B6D2004930400231CD7FADBF81D8BEC8E6B968C2C99C3FD51538CC99264CC3C265F090FC009ABD1FA0687BD91ED29C74A99356B0132785454542805682DA1F0AF28E96FF00E221F684C973ED77D94762FA3FEAB5D93F67F4999B59A2B2ECC1B5538EF6959728F8D34EB2DAFC4D88DE3CAE07A6FF00F875FC20FF004DC873AED2E3662C4C9F252B9726721495BC94AD2C38AAE586973C8423DB1EDE6599C4B565AF2D7DDA4A388917218BF3A6D7E51487B197D12992FB6E7B2EE8CED8727ED3F2DD13AFB33399A33AA652E99CAB4269AB174B47C295D534B47F25008E048277B9BE257E2DFF005739D7C30ED563B23C4F646766982953C4B933940A92A4053121E52DA9CEC361150EC9F6224625189C6E16600A53A884B50FCC6CFCAAF4F08F793E8ECF653CCBE8CDD13DA8D576BFDBE516B1D33995031534197E67534ECAA8450B4FB8B6DA53D5AEB87EB0A2010902D682231E11F8FF00DA8C5FF513DA8ECE4FC83239D95AE54EFF007C4A90B481DE197FB9425201E1FF00D4760D1D0BB35DA49BD97938B918C2552D614900AAECE0D34636B5C3968F907FA447B67D33ED09ED73DADF6A7A792C3391E695F46C65686214CFFF000F42A91E712520254165B2AB822FB99BFD73FE9B324CC3B0BD8AECD649889F3711330F2815CC585024CC29531724D1DB661E5E67F89599E1F33CD66E230C94A553564A929E1726ACC40F4E82F1D247948AD71B69A3C6EBB574490B1002385F6C12784DC01733F7463DB1DB544EC6F617310924A95825B0B9FF00A65869AB59F7BB98AAE538632E7C998CCC41219C82FCF4FE35B7DDBFB336A1D3793FD1114D91661A9B2B7EAA9F4B66FC544BAEA565F42DC2F2908E00F070CAA364C9DF1F9D5C776733199FD434B9630338056684F7E25CC2857CFC553C2C963401EEF736F5164F99A11D9F989EF83995C25259C3EC77607E952F1F0AF98B15CFD56A6AFF00A9341273DCDFBA685437E20732A80DA80998363E933338FBBF869388C2FC36C361895059CBD824920FFD216075B53D77F336793258CFD2B04F0F7C4F78C4DD428C2F6F1E8F1F709F468EA4A2C9BE879C99BCD33DCB28F323A7758A2AB2A76B690D4203AED6A590A429D0E7892411E1988B63E137C46C8B198EFEA09787999662168566329489E25CD32CB14A89E2E129A1A5CB178F5A6419AA47645C4D48E1C3906A1CFCAC19CB8EA3A5EFF1079D56A9DD479CD0B47EA85AD47A8D65EB2D2B0EE6956B491C8820C8B9B75B8C7DEAF8272BFD27B2F95E166829030D253C268DFEDA685EF6B0E81AB1E46CEA60C566F3E61629338B1707FBC8AD6951E62102EA1F436DB6FD4FD6384A8254121300A8EE2D3F0F48E7D23B4B365994549775A48A6C03DDA9B787268C6712929C2A1807E116704061E2E6A3EF1922AA23C441F5F9441DA3DF883EC8A0F14F51258177DAF4B57EDB45630D85EF44C0D41A5FC5B6BF4DA17B3540F3E7613EFB1B0FD8DED1218FC4254B2904120D791D1FAFF88613F0641248D5B6BBF4D7EEDBC39B15299BDCFADE00F3BF31FBBE23FBDA0A38EB4F0F188E9987242810054736D4B915F1F5AC3E51D5004CAA768E7CEF73B794DB96136F5FF10C26E16F4E7EFCFAEE445EF9FBCA495C99916BEDE5E63E7317C37CB7BB3C3F3247450F3F06F5B450309C248A8D4B1D694F37766F4200A9B337AF24C133CF7822DCE08F95F6C5816B961988B5C355B5F0B922EFCA2E99690C12EC59AB4FE2B7A45739CBA47149067CED07A12768E7E98CA172C9F988FBEA6DCF98B45CB0286006B4B80C1AF77AFA6F102A9AAA8688729DC534B6DC43BDEA55C2B49696958008330A88B13D3683880ED276670B9ECB4A804AF8056D4B6A3A6BE4F13D265204D42D49E24B1052752A70E79EB6E5AC7B09EC69DBAD16A3C859CB7357D0E56E4ED064513AE052AA82C14990A3C809BA4FE5E61F899D9E565A0FE9A590563E65A41E24F0331A5473AD87384330C0CD93869E94A14B0524A5816AA5C5F50E0121CFAC4E3DA13D9FA83B45A1ACED1744308A4CC5092EE7B97B0907838070B0520402560711EED26F20CEC28DD8CED5E272BCC70D81C629687584CA98A27FDC018977A066662C4EED1C7B0699E8C7AC4D744B42CB248019D4E59D89FC1A691E516A5C933664E654556DADA76994A4292E24B6B3C2483E15709361331B796FECA9D9AE5F99F64B152578A97DE4CC22AEA492FC0A162AABB8FF00069D070D353331B8128F9F8549B312038BDDBEB406B1F7FF00F40754328FA39FB1E678871B6ACFC2E08327F8A3BB7C7AC74DF1F9ABFEA9B013301F14BB412E5874FEA125019A85C92799BF851C47D21F84F8633F219135350258141B74A6F6B5CD047B573C37170AEBCA3D3CCFCA31E7054C50E1FF006EA6F5B3791DFD6E0C752958644A4AD2A50254F7D3933DDEB5A53484756DFF0029464057862FB99E40C72BFB879E22F1F899A0CA4A65120104B5AF6B3C30384470CD26684EB56B56BA3DB4DB9C7997ED4C8A65FB4C7B3BBAA092ED2BD9F84A8C594B6100F39F90C769EC5E38232AC64B5A7878E5A68D664976D79B6FAD9F85F6B7088999F61BBB980844D1516FDC0E84801C7F916F48A8549FA95229C215C4C35179FF00CB06C07E679FBF9ACE5CFF00D6E238657CA16A6A8DCE9E57E7BD3B9E1729958CC0615256DC32D249A97A07EB60FD042D4BD07812D9E13304DA39449E9E71CE2708CC54D0A41E0B9AD411F57DABA9A56F0F5394C8C3C99893307EDE4052BB8FA9FBC43B5AF0AB4EE774EA8E0A8C9F354B8B240E0FF24FED7E60F97BF0E25619789CCB2DF91E5A27202C805EAB481CBAF4E91CF73DFD3C8CAB3596710973297C2E039649E7F47FB47C9CFF0087F4FE94CDB52E62C96AB6A579C664B21C50250AFAF3E47DB2779DA01FBB1F53FE18646064797CBE220CD92876154FCA08A354D5A9F48F8F1F144E2FFF00B438D54B96B52062165C02D45162FA8F1D6BBC55DAEB5E546669750ED48629297C3DD214059560070C1E42605A2F6DFB5C8ECE1C0C852E5A4A8CC0E0849B8D7CEB7F38E479AE2B1AA5E1C194B0C468695076E5E3A87B50F9EEB658CB5CCB43D14CF1E24BA560A92A6D457224CCF1446DF0DE7FB23D98563D73D18A90485FCB504382FA16AF879B45D329CC2711216A7E29401B331706FEFED1006BB78ED1F2C6574547AF330A6CA2950B67EA816EA92A4BA14DF081DE6C27A72F7E2771DF05B2D44F9589978290A54D515294654B7D2E4A5DEA48E62D48E98BF88D98E1B06A9285CD010801202D4D404559BCB4D0475D352EA97DD5BA0E60E5754BCE975E754A502B2B595192499DC9373EA39F77EC7F6364E4B82EEE5C84A4290DFB40B03A369CF5AEA1B926699EE63DA1C5099890B3C0B3C04B9D5F4B5BEC08D23B4DDA8E75A5EB5CACD3B995569FCD69D1097A95E741A80B4C2B88B6B483C0098924FA1DE9FDA8F85F27B4B8BEE276192B97316428AA58500E402E0A483726FF0066BE7663B5B98E46B9264159092976590CC41D19C035F28856A2ED63567696ED2D0EB3D4B98666CE9F53C72FFACBEFAD3FE6BC6F405B847BC9DE23A62FDD8EF82992F6170FDF60B0B25733149056A42128293A12007353AD9A8D171EDEF6EF34CEF05874954C502901438891A0E7737D2FA562BCA9D40FE459A65998E4B5AEB2F30E38B62A10E2C2DA5248B8F103722C7A581B62E0AEC761F1384C56131081313884291C2A0084F102050D3534A0D2D669D809F332E13B1330702D4CA36492589E553FCD8D1F75576A9ABBB412A6B5A6ADCC337A4A06826969EA6A1F5A112DC0094A9C2081C291EEF2C503B27F0872FEC763B19330F879481984C75704A4A48724D4015FDCF5D9F58B2E69DB1C7E2E6A10A2B28413C2EA2CD57AB9E60DB4D2B0DBA7FB70ED3322D34AD3997EB0CCA8B4E5225F65BCBDA7DD0D38D3E56140A43804428D883BE2C78DF81D90E3B33C3E3A661244DC4718985664A38A9C2AAAAA46C6B5A42A736C5E2E5A13DF2D0966238942A7714A5ED7E45E29276B87091C6E77AEBEB74D4F12B88B8E3A5C2B3B1278953EFDE71DA26E5B2B2CCA1196CA940C8549324200040053C26C0EEF42F6B34426264CD97884CD1338940951AB12407605FEEDBF3B353DAF76A54BA75CD08D6B3CD1DD38FB62687EB6F25969B47F34A0254F0042CC8B00224918F3F49FE9D322476865F69132E4CB9C7102795F7238828A8170581A1B6BA691D4FB239EE2F31C0CEC2E227AD12D29290952CB0670CEFD0FA91AC55D97E635EE553D9A503D5394D530E05A2B29EA9D69D6561478969536B428971424C2A6E649C768EDDFC3FC0F6970795E5D8C28C4A70C9084A972D2414B2284104580F3DE29598CDC564B9909D869CB525530FC892415392FF303A383E1B34596D7B5EF6FDA7285DC928BB50CF5BA1E014ED527D62A57DE34B942C77A5E253C2826FCEFEEE57DA2FE9DFB213A660572B29C112E0AD430F29C905372106B4D4E84C751C176C33395839404C5AFE573F39245050172FD473888E53DBA7695A1AAB37CD74AEBECEB2CCE75496959C569ABAAAA55616E40E24ADF3C3C016A48BCEDE98B2627E09F63F0323087FD1B09356809242A44B64D059D3BF4AF844BE13B7D987E8F1038E602A490071177A8FAE9A6A6B117D41A9EAB52D43F9CEAB7DCCFAAAAF8559966AF3CA4D4D5A80F0124953814D936214622C462E384C8F2DC9300A9383C049932B807CA89684866A8094A40028C4806BEBCCC769B34399098274D333BDE2EEBE6660A7AA8D2D5AF41A448342FB40769FD9636F27B25D5B9DE421B5346980CC6B1E69238A5CFE53CFF00040BC023CAD8A64FF86BD95ED9A7128C7E45835CC50204C99265A8B977214A43F3A9BD6BAF4CC4FC40C68C3C896B9EB432085312402C1A81C1D9EDF7996BAF6BEF6A7ED1A84651AC7B64CDEA74F3C80D869B0B614C881C485165D4B8E0717E12A3B5ED6C73EC37F4A1D99C2667FAC9383C2B77817C2244B00317350351E075BC452BB7388C4A529257C697A959215B720DA0D49A5E3AE55D4AFB4A7731ABAB71DA9E24ADBAA71D53EE38A599597256B52CAF97193C3336838F487677B3780EC9E5DFA6CBB0C894020256109E00AE1D580F17A8AD1ED10B8ACCE6664E272B881A1048B68C6A030E5666ABC4B3477693AB3B3DAF567DA1752D6696CF5F6C8AF4D1ADD6FBEE0414B454A42DB49F092773B9F29A4769BE1764BF12153139A61249AB1EF65A5770C28A05F97D350FB25CEA764AA3DCAC94A8FCA453AFD5BD2D0CFA9BB4AD6DDA356B59AF68F9F57EA4CC925EFE1AE555438A2C820A5CE02A717C05405CDA6DE470C3B29F0B724F845881FE998594B18958E2084252031352C1A8ED4E82D0BE79DA4C56629497514268B3C4494BB0B7D5BC636E94ED33B4DECE686BDBECFF0055E63A4559CB8D2B325D13EE95560A75CB417DDB8829E00624F5B7385BE27FC25CA3E24A7073F192A415243A44C968594BB1A150A3F215F5898ECFF693FD3B018A40593DE2181763622CFBF9DA36679A9F3ED6F9A576A0D5B9C556A5CD4B6C8CC6A6B2A1C2B57F2C210525C7167ECD884CF520EF8DBB15F09B03D85C3AB09829E89689C9632E5CB084B005D82193635A728A5CA5E2F1B33118C33152C05A9481C4FC45CB6B46A3D35B6D38ECDBDA27B6CEC7D8699ECA35DE67A5B2A60AD4DD0B0FBAED3A5C512AB32A7782EE19FB20199E6629DDB7F813D98ED8AD788C5E59869D393C44CC5CA4151513772924D75BD2B6ADFBB11F11B1B904D9B82C4A55312BF941366B5D8BB8A7A5ECE7AE7DACBB7CED8A94E51DADF69B9D6A1FE2922A285A7EA32E4308A732DA4AE95E42561D4813D3AC99315D88FE99FB33839A56BCB70C9EE8828224202878B39F7766893ED0F6867E67C5364932CADC800D01FF0026E47211D79A9CCF2D06BA99346E51B34FC011C6F2EA14E71FDA59714789449F11BA8DE099938F42E1BE1865F95E1E5CC91C3DDCA1F227858D00A017A352C34B4727C7E0B187172A6AA615AE693C40D804B6B6FB0D8986AA253ED24D45112A6DC50214A3050526410150A9E7D248F73AC4ABBFCBB1197CC4912D52D52FA8208B1D34F037AC4FC932A470778A4A66242788022B6D8E9D5ECC77B799EDC7B60469F6F43653AE7356B260DAD2BCA9350F374FDD9F1B8982F25B3226C419F2DB1E6FC2FC0CC8979F9CE152B0FDF77E66059948E3078B8BF71F9BE96B35AED83CEA52705350270AA18004D4D59C3DBD8058456B4E8A377EB05552B156B5713882B594A9C995AA4909F12A547D63963B2E7787949C261B2B92014A502529A80064A45052C00D3A544727CCF118B56350B12C2A49987E7A1FEED989A9B5ACFCA2DCCA3B77ED9748E937F4A69BED0732CB34CB882CA7256DC7154E50E921C484F7A1290A2A26C800CFC38FE7FF000772AFF51C366430B865CF52F8CCDEE659980B823E729E22D472F5B728EB595670A95932E5A9652F29B85C80696634F1F48A997589A4A751CCFF00CC562D4E3CB741BADC7945C52894F52B24FBCC0DF1D672D9672AC36170E80C1090030D801BEDD1E968E42A44CC4663326C90425535CA49B7CC6C4DDDA837A5A120AF55434C9EE032DA4ABBB571F115C9BCF3116B9E7BF9CB6653D73A5A454FCA34DC375F3E9511379980BC3CB48A900B80795F402D460C4794642A215008B7E5BEC3DE01EBB8C3DECDA3B9918A333E5252E09D686C2C746B5ED588CC04B4852828555AD2BCACC5B9F95995B5504CC72E5B7E1F84F9EE3103DE4C5E2A6853F0F116F07E41FECFD0C6B98E1857853C54E54F2F7CAD0EAC54A85E6E39C8B18F78F4FD92E3D6212661D4011C377E5FC74D1DC5EB0EAC55A81B2A662DCA39FA4DF7F8E1C4454D90B0E18815F467BD7CBD63B31A83FF0030F9729F3FDF5C5772ACAB109E1FF714DD5EC0023C58BB56F1C87064FCBCF5237BD9FDF8454B9AEFFF00501BFE1FBF23B62EF2329594FEF248BF27D37D7F2748BBE560F9DFC3C0D9B56AD9A2B8CE261572771BF33B7A4795B9DA30DB13964C40A2D887A8D46947F7CF5BC6096A6000B063CECDA06EB5F1115F660B2961D00F8942537BC03B73FC7737387196CA54942C2D7C65ACE76B6B4BDEE1E2D3804898A4BA4900B7A87B3378FD1C44F3B1CD74E7669AB726CED2F2D2AAEA80D5537C6A094A0A92D789174FD9513F64091B49C72EEDC61246213338A5853F1338043814A1D4B57A88BAAA4495E0D49525259140D770E5F7B8B92F5762447BBBD9F6BC0E06B32CAEB52BCA6AE9D872A11C21E6EA389A056DC2B885D4549909244CEE31E5DCEF2C4712FE4E15851E152404941770411B30B50EF78F3E76CA58C3E216A909EED890C000FC8351CFE34AC535ED49D82A35A6529ED5740E4E9A7AB6997D59BE9DA75A54A76525A0F155B7014F42516DBA623B2ACF335C3ABFD3B178F9AA2974A165D299A935E16FDA3803246F7DE1976471844EFF0076BF3A0A5CD5241AF9FDEB5871F656FA6A3B60F628EC4B24EC374A766CF6754BA42A2B02AA5CCC9144A52AB6B5750B4F74EB6543854A5241BC81320638FF006E3FA61CB3E296738DCFCCBE2C6E2780A94093FB53C3B905C72A0F38F72F60BE2CCBECC65430D310172C20339B33B3537F6E4C770B49FF00E240F69CD7DA86974E649D911454BAF52A12DA73AA5592952925C20A99E4992795AFE7C5F34FE89A46094B64148960924836A126FE941B6F0DF3FF008FABC3A138B4A949134AC896096649203902869B56A23D6CCB7E946EDBB32C8727CCF30D00AA3AB553A5754C8CCD874B8A7109264049038493CAF18E793FFA5BCBA54E992C4E49282C42914046C7463A87A5F78E6B9B7F54D8891296944A293C24385549B6DADC0E61A299ED17DB175FEB9D65A375E55E96FF0039A3D756B651F5E689FF003894A1710009001BC19E587184FE9EB0F830A40C425282188018116FF9023E9CE38ECEFEA5313331C27AE5296EB772A22C6E28CC5B4DA2E36BE93BED716BA5A2CB745B8E14252DA17F5C6E13090904CB7113CE4EFE7784CDBE03E4B800A5290272E6D4B121D89ADEB4F623B1645FD5CCC95874CB9A42025200E2581A731FE0B062D13CFF00F78C76CB45979ACCD74D251E00A4B66B2941822C2C276B0B6D1B6C6051F02B01895BE1F0EA4826CEA557A380F5F3B3E8669FD59AA705844D0285C85E8D4B6BF93BD693CFFE94CED32B5EAACB2A749A99A3A9A6ABA45BBF5D6D40F7ECB8D6E102078B91F23D7177C87FA70913264B5AE5174A90B49E134620EAEF51B8D2D58E4B9E7F5278EC6098133490A0A0C0D3E67BD18B83B1AED1E5CE7FAD2B97FC56A2B1A5533B9AD53F54A417F8E3BC79C7AD06DF6EFF00083B63DA3D83EC09CAA4C994A5525A5090E9A06006A4BF3D8EB68E099DFC44958F9CB9B3308959592492D5737A03D6DBC5199DEB069D0950A8E2E2E20B4F111B5AE49826DCF9FC477AC16449290854B414A406FDB5B3863E477BC404ACD70D9B14BE1C21ACFA7FEDD2CF435F18A7B506A469C04A5C22247085189322C41E66D63E51B62D797E4D230DF34B9684ACB5001E069B0FA18939494380848036B742FA3015D5AF58A8F33CE0155DC8E22A27C5B983B8B4FA1E67CA716C912A67CA9324CCE166A3F326C69E874261F224226065241069BD01E777B58E910BCC3356C93E3937BF15ED6E93D39CFB8E27646267A180C228B5D81B55A8DE7CE159396C90414CA1D5A8DCE84EBD1BC221B9A66685442828F8A4CC98F599300733D05AF13382C50278A7617BB240624786C0914DE9A4484AC24B42920A1D542CCDCF46A90DCF4AD6227515C8415149009DC8B4EFE9CC7BFE18B1C8C52267082C4358DACFAB8B9DBC6257825CD480B47101448B81666A7A8E9BC30D4D625704A8929B013D77E7E5D2FF002C4B4AC1A26BA811F3352D517634FAB57C21F485A657CA80C9147FDA080395EA1BC690C4FD741549227A137378DBF641F5C3A392CA9DC2ABA81B9F114F7AEF1212D32D4C4A58D093AF23F7F5D6120A90A0AB9BC5A48B74236F3103F1C18D9A8CA25A4A93C6E0806AFA3E9AE8FB43D4CA3352D2DC70D9BAD4D7670046A55401D2D7F4F5B1B8F761B4BCF70D3C1E342411404B1AD742F4EBFCC2FF00A25CCA4C25540CC0D35AF263E35D4437D655B29E1529E5A0DEE0124817E578063CB68E85EA71689A03106DC2011EF53EB6687B8595330A0894B28B384D1DFF003E957B086F73336F84B6CD42D40FF470290099EB11BF3369EBB61BCCC4E2CA9908330A59A9E9507969B0787ABC389ACA9ACB2352C589A8343420DBEE61B8D0BB592EAA95252824951793C4679804D8EFCBD712381C4255FF00F50099007ED330815DEBF9D4522470D3E5C84B2C150B003A369CBFC5C9C0AE812420D32BBC1027894B00C5E3700C748BFAE36C766794CB0D3319294002C389346E60E85BF9B4384E3E5A50A12D290821D55677AEAD7A873A36E63356599AD78032ECA6AF306D32169650F2BBBE232094212ADFCC72DF618A466BDAACAA43B4F94B4A6FF324003667D8DBEACF11E3159782B5AD6896AD0B713F27D08A0D2ADE12BD3BD9B6BDCF9E4D3657A5F365B8B20049A1A94A2FB4AD6C817E4662FBF2C52E6FC4CC9302A509788912D44D077881BFFDCF47A8A6CCF0CE766523898AF89239368F5F3B5B5EB7F647EC4FED1BA9592EE5FD9E2EB1901254A7F33A7A5EEC2EE0F0BAA4933D22C79E29B9EFF51585C866265CB2311DE71550AE266009A876D9F5BF3868ACD70284ACCCC426514D5296B96347A7D757B18B5322FA373B79CD78467196B7908541505D6D255F08F4EF8EDE5EEC5626FF0054D85980032542EE0A54DE3F2F56B5E1827B4985492EA0A4BE8A29FCB03FE22CCA6FA2AF523A38F3DD7AD50A94077484D132E1FF00571290E72F3E57E830D07F536B72AC1E14CC209E26251C3CEA9AE85EC393B05876B30E1242425059A8429DB91D5EDA58D61DE9FE8AE0820ABB4B440DBFF86A26FBC78EDB9BC09C34C57F5238FC494AA6E5A66105C1E3A83E29E42B082FB53289FDE189DFF173AB46EAAFA2DA9C371FFED6114EA13C08394A55DE1F52E7863AF5E76C43E3BFA94CD019694E0A64B4D4169855C351A70F2AF4DCD7795DA9C3A1DD6140DC7133F5B575AFA6B5FE75F45E6BC4073FC3FAADACE42BEC90D314A1C8DA429C1E42F204DB78C2F23FA93C50E156225AC002EE49F06497F4F4787D23B5387B258053BFCD4F0F3B33EDCE9ED4BF4777B43E996C2E9B224D734EF19EF1BAEA425B0904C96D2B24F15E39C99F2C5CF25FEA37018C5894A05C517C4952589E7C3A837DA8EC224A467B85042C043F25025F5737DF5703778EAA6B6EC6FB44D0150B6F55E4398875054389AA479C4A00B9FE6B2DA926D17E288E918EA7967C70CB25A4292B94870EAF9C135B386241DEB534262770DDA3953662509295710600A9AA2B525BC45FC1E2AA5BE5B5C3CDAC380C354EEB65B24C90788AC03311B89DC62DD84F8AB96E6B294A18847180591C4002FA00E2B436E578773D5331E4F0A824A59CA485B3EC5DFC34D8E9A066C95BA9A761BE3A8BCD37D8481B9872C36BC49F5C472BB55FEA738CA968E1492DC4CDADDC063BDCBFAC269C9E7A921E62B84F11EF1C93CA8FAD9CF8467515AD28B694B85156DF107D909527B90A8E1874001CE213B1F0EC45AEE8E4F3023BE91892B2594521A85BD59FCA1C232AC4489615C4BE136507636A91D2F4D6D5847DF892413277B9927CCC74EBD7094B54E0A6C42485248F995AB6CFD3CF5A5779721082954C4F1105C3D811C9A8FE7E158E7EB12209558D81262DCFF2FC3125326A26A50090B2072F201B4FAF487188C41527810A5252CCC090C3D3CBF980BE15F68957A927EF18D5D2400500B6E7F888D12824B82C6B6045FC63732F4C80600B6FB03BC08B72DB029408AA016B57FC5BDB465482AA1538B5BAE9D7DD21636F264C44DA4733F2B72F5B7963744E280C9A0B30342D4AB01E3184CAE0FDA5B5760EF1BFBF09E1BEF78FD8936EB1F2B37514051213525F66A79746D21708E200AABB121DFC1E961F6852DD4A6D06D17DE4738FBBCE7973C63BCE41C73F6D4FAC379B2900314860FB33574BEB6878CBEA412B24DAD37F75B616E971CF960331F4F5FE222E749410484802A6C36FADEAD7F08EDB6A0040701045BF3C31CB7304BA7FDB2FA579BFA3F378F3BE0813C15616661576D74F22D78A97340544F0DE27693D3A6DF2C5AA5E6A5293C2082756FF001A37BAC5E72C07C68E3A83CC7DE2B8CE5278556379E477822FEFF909279989C7672B03F6B9666DFA9D41BEDE16B9E0DE83D1EE29AE971E7B08AC734596EA29D441E0495950E5E11B73DF973F7C028E5D98AA695F10201DFC81D18EF4A79C5D3286A92C188B8DEFCADA9E95B98655D7AD550FD7107BA2A40A640994A93092A02D1E200ED1067152ED203384CB9A1E571B51E2EC84F1C9E009A81F317A105F6E434B691EA87B17F6AD539AE96AED10F362B73FA1EE0D0075F08516D6B538EAC15595DD340280327C3000918E059E610A662D4B5129413C619DCA8B245011AD0ED1C7FB6F9605A953254BFF006A603C079A5B8DC1A8A83B69B47A5DA2B519C9DD65D72BCE6B475414D66C1D6781B6A41406FB95CA48BA91294C18E2DAE68F98658713254152FBB5A6B2A60357049D1B50E4127504B472CC0A97976238D880F50E5AFE43C3C63A43EDADECD20297DAAF674B41A0AF4AAA33BC9A9A9D24502909096C95004AC3CAE25C25238660ED8E87F0A73F4489F3F29CD4044F96129C34F5B0FD55092364F7618126A6E23AEE4D9C4A9D2901DDD8104FEDDDC1F3371E05A3ABFEC4344731EDD326555708144E540A9429B0A054195252786265244D872F5C4C7C40C6CA380C47E9CA44DA061C24873A91B8A3BF8C3BED14AC3FE88CE511C2A4121D80703CEB4B5483A08FA26A3AE6695960B550AA86D68285A12DA95C240E14400098D87B8EDB63CB39B058E352A50410494A9C55EA4FD7634AEB1E54CFB339471CB94140A7BC29E170D73B694F26DC9892643A5DDAAA866BAB6A0B742B2E29E6DC470020FD910A20F316F973C73CC51C4AD6A329454F4F94BB7BAD4EDA5A3599230DFA633BE57E1A3B6DAEDD75AECF120CCF55E95D2A834B42DB4ED50078DDE107855CB84949111CC1E9230861F23CC33450E2428F0961720FF8F2D4F3A34F993B153552E44D52425458A7C7A7954DF48A0F57F6A4CD5171BA8AD524F8821B4A484EFB5845AC49881BF91E89D9FEC7CD94A4999873421DC3BDA963BF8C38919762D5533D570EE4DA806B715A39AE9143E79ACEA56C3ECAEB514A1EF152AFBB42CAF80F12BA14C6D7371EB8EC99476792908030BC4A02AC198598EFA6BD280C4FE172013402B9D5531A834AB5A87DD0C75E750EBACD16FD7BF515EAA86698B68427842678FC2600D87BA062EB23245CA4251264103CD893ADA874E4EE3533527B2D216C14B0A70EE69B1621EBE3D62AACFB53BA1C4968948209510A241E200FBB7F2F7462DD90F673118824CE2A961E9C5B6B41AD830E6FC9599934BCBD8CA214FB537A0BE962DB83CABECC351BAE182BEA6EAF5226E2C0F95E2D8BE60FB3699443CCE2F02C7C2DBFF0D573250490C1B42CE6EFD6C4D76A5E910DADCDD6E470B920C830AE978DEC7E43C862DB84CBE54A041097A0A8BDB7BFE7C62730F24380C5A95B3EE3DF5D5E2235F98BE6DC6522F2662C3CB909F3E76224E26E461E426A780780E5B0D89AFD627E4CB40482000534059DABB6E74F1DC4465DCC9C3FD44949224107E22FBCED8713B2CC3E350C3853B148A55B40D6B757EB1208C009A54501ADA6CCD5FC4335557B841324037BEDF3888E9CE7E1ACAECDA10070CD34B86ADFABF95442A32E54B7E21A8615DAB6229B5872AD5B055ADC2B009514C4917DE46F7BDCF5C494ACBE6618057116A358380CE19E8D4E96A5A164604B3F091ADAA6BB5ADE81EB085FA9B9922FBCD88E563BC8B79FBB0E06231086F914AF3A6BB73FC3DE1C0C3B1143535F0A0E7A1A68C79B205D5A927C2241BDCC7E22F63373870AC2E1B31923F56B4208144AD41243BEAA21E9A535DDE24B0613294788B6940ECDAF20CDF6D0C6C69398559029E92A1F9B70B2D38EA8F580DA56A3E71F28C44623B3F93212B51C74892054ABBE4D80D7E70283916D5E1D4CC5C8428A52A4BB56C35A5F517FB1898E9FECEF59EA4714C659A77347AA8A929612ED154B485294760B71909BDAE2C23CED48CE3B4390E43C6A939B61A7AA557804D43BEA080B27CD9EACE2194ECCA4CB524AD6025479114205081F9D83DE3B1FA33D823DA6B5829AA8A8D24DE5F93B852A354E56D105A5B55C9EED4B42E40E5636E471C7B35FEA7728C8B10A9070DFA8992CB06248537309203B1673E7584F159E6065CB4893344C24328BB70B36F42FD37D03C76AB4B7D18342E37DE6AAED03F83D43010A7E8D1446A038A31C480B69C8B796F6EA46396F6CBFA9CC776904B9595E58A9281C41644E32D9EA09701EDC9BC62B38EED62A505044C03621890297BBEBF715A76234B7B0C7B3A69A6D0D66D4BFE2CAB4402B57D6A8F8C88BD94A001E7726FF001E653FE26F697304F0A27CDC0F15E6199DE316BB13FE69688299DAB985FBC99C6F70297E8D5D5A8DCDE2F1D37D897635A24B8E696ECC6932E53DC25C79DAD35A1E0DC701087D2BE1E1E805EF388239FF006967A97FA9CF66E212A6F9423848FF00C4DCE9CB486533B461638904855C7CDE7AE8DD7D4C58ADE6EBCB1B0C65596E5542DA4404A72AA25280116E3EE38BD6FD245F1018ACAE7E366F7B3313882B26FDF4C0097B9653005C0B5F5BB207B4734D02CD5C1D7E9D46A2352B35CCEA7C4FAD3FE90C3696072990D848239C11E58565E117824A93889A663B7EF256D5A312FB8B7E62BF9AE753D750B21C9700967028F5D2A77F368D2A7EA957E37D20C41EF17CB7E7EB6EBBE1C24E1D54E140F2FC52FE3E110A3339E47EF556ACE58BFB0EF189A779D952DE748039B8B813D25437F9ED6C3D96990406425B56001E868EF7E9A5A31FEA9882ED315E2F4F33F6869A969D6C9875C302DFCC549173D7D3E7E787C89120904048D9C0DABB7BF53FD4E79A7117143534E8FC9FD3AC3154BC040A975D41FE8BAC91783B137E5EB1698385D381C2CCAA9085686836E4FBFD615959A620280E3350C2A59F5D77E5A5EB0D8E54BE3FF97CC9F644DBFE27431CFEE9C67FD270CA344A48D030B9F3FE6FC83E4669884D96A0372496BF3FF3053E619E33C6E0CE9C5017871B2B00F48595020F39C2BFE888A04A824AA80A5203D2EE08E5F6112387CE31003898ADB5BDADEBD6DAC6AADD4A9CDA9D596EA2C872ECFE81D05B794ED1D2B2BE056F0BEE4AE483BA4838513D9854A2A5C9C64C96B50A1E252803D38A97B35EB1252F3EC48293DE2C503976A35598B8F27A523AFBDA07B24FB3376A34AE53D16408D199ED5059773D6DDA9A914AEAEE1429414B6A9262DB74DB1B6165F68F245CCC4A272F1C5052A912BBCEEC283BA83BD29A11BD8C5FFB2DDAD9786501899C4059657117E837EB56D63CC6EDAFD81FB44EC9456661A5595768FA71216EA33AA608A27A9DB00A84D224A9E547D93693C338EE1D90F89E8C5A256071F2460F14964AC2D4286CE16400697A86A08EC9957697018A530527829C21C11CDDBCDBA523CF9AA7336A5AEAACBF36A3768DDA359406DE694D380DC292AE24851E1B8F10EB78C77CC9BB43230C12B13C6202C0243BD1AD42DE3E517644FC3622524A4A4F10B023A585CF854D79469EFD179880379B7A13C8FF00B6F8B81C761339960238252D983303B3E84B9EB4BC4163B0E2BC15B503F5BB36BE1A93A6C53E821245C1D8F5B5C5BA1DE074DB9C4FE8E76114F31F8093C24B904540D0B7E5F788C1294160A9F57A31A386234D1A30EF93FB9FCB193300A91EBFC42BC0373E9F88DCD3DF6B87CB9FE630779CBD7F883806E7D3F10B1B789F23B1FC2D1F3FD70779CBD7F883BB1B98C9EA854A60FC083F1B5FF1E671A2E630AD01E62BD76FE6374C9777A0D1DDFEA3DEFA728A93C8DBEEF740DFAC1BE11131C5C3D039B5EC694D07DED09CD906AC016A74DF7776E7B0877A0AA502A8369111E51BDB73BF2F2C678EA694A372DF4AC45CD90E750350C0D3EA7C34BC77CF51E5EB71C5051932AF0404F3200046F7FDED8432B12183292C19EA090F570FD3D63CC9817E2041A0D2F4B963420877F2A4545A859772E085200A5EF42A54921F2E70FA4F0C6D1F9E2DF839586C43844C042400414B33DAE35B6DE517DCB9822C1880C7AF2F2ADEF152672FD528A8877BD1CFC011689E83CB7F5DB18C5E512149078D2C7567B9DDF5736FF371C194B25CF2DC8A91F7E6CF6B456F9A07090A75239806C67AEDB7A7A4DB7849B21182A022AEC436AF7B74FA1BC5C32F21201497E4C777E57AED5884D70001B08DE3901FEF73CA715FC7244E428F0D4824017A1B791F0A6D175C11331043162C1B660FE15F758977649AF33CECFF005EE459FE56FA99629EA52DD692B012A6DF5A5BF182608095288F7F4C735CE32B528F1000A49571029D85C93B35CF8436CD728958AC0E213351C5340FF60B1F95CFCD4A03AD76018C7BED91EAAA6CDB2ECB731A65A2A29336A661C438D11C3DE25B4174786D3DE133D31CEF1D8732C2A581F32497B549B7A5ECE2F1C073FCA15855AC80C1CB162373E9CDDDB58B9F24AFA4A9A07B25CDD947F0ACE98729EA9D7877A965250A42086D5C533C53E1162271CEB3ECDC6553A44E49289D20A8A568F96F7729BBF32D70221F2699311315FEE94A4104F83DABA1D1C6D1D4EEC5FD9A33FECFBDAC296AB4A65CEE69A1F3172B2A1CAD282C329EF2956BDD60D92E2C8104440DA6D50CE7E2262716854B2E02B84125454DC2AF3AFAED61161CFB389588CB061D5891DECA4A8218D55C40BDB6A7531EBE64793653A529EA5FACAA6DDAC078D146B4825854CC49242A77988B4EDB55B179C62335526570144920052AE5541E219ABAF8011E67CCB2B2BC72A709DC40ADEAE3FB9C6AE06A01BD05E23F9F6B5ACCE10F34BE1629590784A385B1C2245B8426F6F5117D8E25328CA6520FCB24952AA5C955FF00F559DFA56D589718713B0DDCF7CC4A48DB403536DF4E44B375A7546B1656FA99A373BC5D39525DF119BED249BF2F2B7588EB1D9EC9A58964AE5A52E450A406F120120FF8E6CB2CC84C99B316495125C5BA915A7BD6F1486A0D50A056A2A04DFA488E62DE9E98E8784C0E1E4814492350D635A90187E6AFBCCAF00A4B324834AB1F2E75714BB549D6A1CEF527D65B2B5BE5A53615C12779F2E5B01F0C5A72F12D3312132854B6E5AFD0EFBF898504AC4A0060AA52943F47AD87561147E6DAA1E53EB6CFF310A2249D94394DAF07998EBD063A265987C34D4874A5058559EBB917AE95A3738591331628EA013A69FE0DB6ADDA2279C67C9643243E58EF02B89253C7C7CA24ED1C84CE2CD84CB82D4B200570B70914636D285C1D4D1D856B12983953B140F1254403525C9E6C0D9F666D5E21D579AD1B92A7495F9DD03DC200F5F85A31312F2E5AC072CC5A877E96A6B5DF78969381525884B39A505EDCB4AF97278D556654C920D22E5641E23C53C3D01067AFDD322D8772B2F41238E604116255FCB8E571B077893958650E1E305AE094B38B0667FBD9C07BB1D43F5AB9716F828BCA2104C45C5AF7F41720F39C2BFA1C3BB1C5A470FF00DC001B33A8EDA8A57568934F0A40484B1FF95459C825E95BEA46E2195758B0A8A5A4A82B9873BB65D7E49D884A52A22FD3A6DCB0B7EBF23CA10AFD66632934FEF58727C4D39FF989EC0A4A05D04914248F3A9D43FF00910FB94697D5BAA1D45365390E6B5EEB842508FE1B54CA5449B7F30B010073927E57C41E3BE21766B02852A5E658770FF2F7A8A9E4EA716F52D0EE6E265CA6134A43E80A4DBA758BAF4EFB1DFB456A250FE13A25CA3A77F83BD79EAA6124A55B1097824A60192239DF96396E7DF1FB26CB57C266226F0F170942F8830AFF00692396B7B3C68730C1A038989516622CDCAA3AFE2B1DA1D19F45CEBECD908ADD65AA5BD3E084A9D6BB962A7867ED0FE5BA0DAE3913CA39F3BC6FF565270C95FE9307FA8526C97297BD1CA5B415BDBC5BCCCD7082C108AB12EEEF6A55B7B45FDA73E8DFEC8723528EA8D53FE27523861A148FD206787EDA7890BF1F19040998F8E395F68BFA9CCF7B41C49C3E5F3B0411FB4A2612EE4D7E516E6C0F48AC66FDA456087FF293434CBD02883E20FA5FC5A3B0DA47D9DFD9F340703990E8C65EAE6C828A879C79E0549FEA28792B499B7236C73B9BF127B639B288566B899725414152FE6143A3B83EC86357A64FED1CE9B314B5A895A8D482C36D282DB8BB98B869AA58A64A5A6724CB1B61B1C34E96F2EA442909800CA92C711311751B462117271D8854C9EAC7E20AA6D55C53A6904F205675A9A798863373EC4AC01C67CDEAE343EC55E1CD2FD4D4A78471B083601B529A17E894948827947DD66B338E516989EFC821CA839FFC8824FD81D4C47AF339EA720A8F16B51BB8DB9D3F98D468452294A538A25DDF8D5C5B7BEF37DBCF1A771FADA22477406A05075A026DEED0C311899F32E49376726DABD7C347784AA4324C828F23001E5D0CEFB637FF004DC423F602A6152E453CFED5D79B41326AA951E20BF58E50A4A66556E84CFC24DBF19F2C06662B0F4EE896E4F50C7C793EBD68ACA335C072491AEE082E599BC6B4DE352D6CDE4A63F7E53BFECE105E718B92DFFCBA88AB104F3DB978C39E09859A85AAC01E5A9D2DF88C5A75A4856C7C847E53E9FB8798654ECDD1C53126504EE2EE48B167F1F08CFE9153182FE63573D6B6EBBD9F68D6AA865332073E6246FE40DBE1F761FCBCA59BE634B6E7ECC7CE3539730D0B1D6FD286A7C18BBBDA105454B728BCEFB1E7EEBFC236E987B2F2D20B124333B936AF3D34D7CA31FE9ED7040D75F1753F46F65B9CA84110543C849FDC7CF0F51810CDC64B5F95DB5AF3DF58DBFD39C58685EDE05DFEA7470CF0D954A6D7C3E14922FF003E5B9005FF0008C3D9187E1242AA92E1C6C00BDEFF00687787CB9249A07D8536D7A8F2AD21B1E423FB42444FA5FA81B7E1BE1F22525CB38E8FE546F53F7872701C24961D0D7C3A569F567742B284F100A067748833CF9C7FBFCB798274B0148048AD0D08EB736D9B5E90230C906CCDEF7E9AF386CA85260CC08312204FC23CF7EB783862BCC71F2AA994A34B3134DEC76E9CEF0A09006AFC9BEEF7DA9E570DAF02D34F5624A5229C0E2480257C5B7BF6DA4C9F84BE5988C4E34844F4AA5F17ED7AD06F4A74FA968AEE7388C4E1969FD3F130AB87172294E67EB0647A9730CB4B9581487B2F78143CC54A50F36A6D52850E07828010790B1E9C94CDF03879C8017F22E59E274ABBB248A872962588F1B8BC4F7677B4F8EC3AD1C4B50346049DABD3C5AD1D6FEDE3D913B30EDD32BCC73ED0E8A7CA35EA9A5BCA2DB6509A87402A212DABBB641E104481E7CF09E4DDBACCB24C477338CC9B2414212A249090282DC44B6B5D23BF767BB5EA9C2524ACF0967756D70CCFA53C447833DA4765FAA3B34D4359A5B55D15465CED23EB4BAFB8857054A428A9252A808BA40FB24EE3D71EA2EC56732332972F153316996DC2A282B1F33B16151D08AD6B526BD6B059849C5042E5965AA9C1722D5AB3EF70D4E8212E555138D34C50345A6980A06655C449B9955CC993B9FBB1D4F1B9EC9C721126524112D207159DF9B68D6D77A51DE230E95A8AC91C440E2200A1B587859B972D1C6AEBF21F96233BD2400D416AFF0010DFB8FF00BFFF006FFF0054668708993F2FD318EF08B06F183B8FFBFF00F6FF00319F7C46CA23DDFA6326613704F53FC41DC7FDFF00FB7FFAA39EFF00A92A1F77EFD0E1099340D58ECEED7D1BCF997D614461C382EED7D1DDFAC6F6DEDA0CFA5BCFCC79C1C23DEDFE6F4E9CBD3C79C6B3648014F534F7D7C07850876A2A88E3BEF69FD8B6F06FD6D80CEAB1557A7BB36DAF945CF94CEC1A95F4377DEF4D758F7DB59FB27D26A443B5DA635EB4942C2968CBCD121244EC8EF56B493FDBFA63CBF947C4ECDA44D48C4E1A64A941899A492E05E806EDE7E11E55C0844BE22B0F41C20D385B67BF51D6F1D57D4FEC9BDAC65EA29A3C9139937E28A94D653A83813B28202D453D62FE9B01D3F2DF8BB8698024CD5255F2820829ABEE40BD6C7E916DCB6721012153122F471A8B73DB7A6978EB4EB7EC3FB48C982FEBDA7EAD8E1E204B2D29F802D6EE90A99E9F0E98B02FE26CA29ACE43B3B1983ABDC1FF000E368B860F1B87494954C0C0D9C397AFDC98EB8E75A4751D2A887B29CD94429524E5D569098EA7BA88EB3B615C2F6EB038E5813F152D1A00482DA9B97E9A79C5B7058CC3A923BB5252DFF70735A6AFA68CF4A59EB6CD686B698AC3F4952D116875871B20DADE2408DF9F9CED8B049CE32EC427E4C44B503A710D7C7D9F38BDE498A925B8949B860E0877EBEC79986BC1D70A9A69EEE8929936B292414C90445F698E5CC5A2B369D84282D310EC5CB86E46F4FA3F9C5ED69C2AF0EEA29720FCAC0D1B4A56D7E7AD48F5BBD897B40CC75664343D9C966A2B333D36427EB010B7439F5A73BC400A09527C298FEAEB2236E319EE3F012664D267A0281759E260C1D99CB5A9A39DEB1C4BB7B83C3C997DE808952E6F1F761C1248FDCE2E2A4DC748F63B4776415EFB8C661AB9C34F42D842A9A9140053F61C40F010A4418FB42083E58E19DA8CCB09984F54BC1ABBF525C4C20370F9D08D3D46B1C1262E5CA4620A2684A8711005C8D350DD69AD758EC054578CBE9A8B23D3342C656FD1021CAE86DF754DA882485A815094822CA3BDE6F8A0A32B5A97326CC26622614F025B878384D41A56B7E948E5D98E678C998832D2B581C443B96356B68D5D76DA2B5D4B5685E66A78B8BE3504F7AE952825E21104845922FD2D04C729B4E599710B4B49766B0766E751E773D69B4DC22D720CC2A3C5C2E473DE9A170DCBC22A8D619D56B4C2DAA5580D1042B848063A7AFAF39922F8E9F926024F1A4AE50E2A3063E2EDA534B73310984462BF50996A52B84A83925B5FA1BBD0C75A33DCE99CB96A595CBAF93DECA88BA45AE491E91D6F16C5B71B2C20CA12889628080DBDF7726CFEB58BDCC989CBA52149F9CA920921EB4D48DA8D14CEA4D5C885F0EFE216923A5F96FEBBEF7C5E7B3B9461315C2676252E786854075A936E9E109CACDD2B3F3CBF4AEC28D4D2D41E315257EA1A7AB2454B6F786780212E2A49B5C207BC75F863A748C83072C20CB5C8530A9336586B6EADBD626F0B889136E024D1DDB6AB747D08E7CE34BA2CD337738327CAEBDD5AA424A28EA0DE3707BB20FCC5B91061CCF46558297C5331D2249009ACD411E6547C6C37E526818472192E1BFE3ABF87F9AC3ED0F60DDB16A984E59A6AAEA9498E02F27EABC1C7B7FC54A42E6D244C75938A7665F1532AECC71204E938E4BFF6CD4929035F94A987D5EBA44B613F472C1F9D32FC8B33D81607D88B334FFB047B43EA2527F88E548CBA8D712A35348A294D8981C4156116B138A4637FA95CAB0AB5265C932C870C3896D70F6200E861FAA7E0D80EF25922A15C4915BD9F77BEF17264FF00462E6301CCFF005CA72050E12E205222AFBFE6A00A1CF0F0DC08DF79B629999FF519889EEBC061D734172BF9CA0827F6B710F5AD199E90D66E6928278664C42B87FE991C3F2B9E4EFCBFCC5E5A4FE8FEEC5721EED5A93509D44EA2EB47D5AA69C2C8DC781440980091B75077A2661F1E7B43382C4A91370EA2E1333BE2BE1E60354F2AF5111ABCD81042A7858D8003D6AFF6DC98BFF21F673F678D2602F24ECFD8AB7EDC750ED4BAB00A2784F76EA488277023998DF146CC3B5DDACED3F12B139DCF4A0542424A59E8CE0B9D2A5C44163F3C561DBB952ABA851F1B1DCFF116AE5E9A1C95A14FA7322CA72E69B84A5272EA275691C80716CF17BE7CE462BD88CBB34C414AB119A6216D60264C079D38ABA73110ABED16281A2967672487F115E9AC6E7EBF50BDE27D6CB68FE8EE5965B007A36123A7481B63323033258527F50B98E0385F128EBAA892DAB0FA0AB39DDA0C58F99D55BDDC78339161EEAD8A756E2CF7F993A49DDB8584CF9C1F2DC6D63118789CB4104AA5850ABD03DBF9F462F4664BED062839F9C93677FF003E7FE5400C34900B21C0B175973681209124F2F5E584E6A8E0182240505120808725B5766A79EE7409CAC7CEC7179814CD406BAEE696B59ACF4846E54D2B5E215694C4FF002FBA1FF4F144F51B448E5B61CCAC589A901182295D3E600D6B701836FF00430B842D475009342C6A3504D6B7BBD9C98E59D4540D85875B48200E05752378006C236F96D892460B133EA1250EF46DC3B37BD28CEEEA561C29B8AFE94A917DB97AC3755EA8609FE49092072DB6371CF7F31E98929393A830981FA8DFE81BD29A43D978246ACC4588E953A7A0F188F556A171EE1529E8093065439F493BEC2D6EBCF0B4EC327049F96495BDD8174B741FC36B4108E2B0E89600410A05C11F4A9FCED7A437AF3C8559D4C1DA143F1EB6F31CFCF59730AC809C32EC78810AF070C1EE7EED0CD329CF090E6E77615A57E9FC423775129023BC0799F15C419117F873DAD8949382135819079BA49BBF27F5E51212F0C9201E163D4DBCD872A747844BD50A124AD244990543CB789BF3E57EB87E32394B002A5027FF00450BECCDEA21FCBC1A76FE1F4ABEA39F852139D565327BC03D543AF9903CB95FE1855191CB402112B843D404F2E87AF4F386B8C906511C20D5F9F9381F8DE342F562C890E0F14FF5A7DFBFBA3CBDD8DCE5069C29A0E458DF952BCB4F38E75A07CE3EC6BCAA7F10997AA564FF00C498B18526DCFD0EF8426E533459246C5B6F277A73BD1E3624F0B849AD8ECDCAAEFCBCE12B9A95524F1DCFFA87C7F7F3C31565D8A07F693CB86F7A0A13B59DF94612166BA6B46F3A16FE232A5D46A5F79C6A1023723DDCFDD387584CBB12A727880D4116A9D1BCBADE1D61D6438343BB86D7D3EFE718D467920CA811BC7145E27E516E9D231248C04C961CA4977DF6F06B373A73858CD27FCFE07F88C292BD355DECAD29E1893C5BF900489F5BE362860077640DAA5EDB8FAC26A9AA49AA29CCFB6A59C470FAD2A0A097048DEE0907DC64DF7B5FCF18135083594E2CC53AF3A6BE1AC6AA9E4D58FD7A685CB5FA436BCF30DB0EAAA1D2536F009F1F4FB33B72B4F2C2F2A782A4944BE0BB909F2D3CDFC01895CB72C939A85F7C4258382A67A3B8140C69A42043F963ECCADC2DA018EEC0599336F2F7EC3CF096372D9D8E6505148AF11B167D6A36DBC75847199248C32D4652D2003466A51BC5EFBF8D23625C6A9174CFD2BA685F492BA2524921E832B4A84C7900B917F8B34E130F854AE5CC94261218A88B3B8A52FCE15CB7133B07352CA20021AA6D5D3F3E24D44417B70EC334B7B50690A9A5CC2829F2ED7795D3B8BA0AA6DB4F15529292AF1A9B084494A07DB260911E2DA3E4E3B1BD9F9885C89D31380E225402947B872080C0BA828DB6B5ADDAFB359F70A90A54C09581A970C4070C4800E869B697F9D5ED2F416A2ECD35766BA475150BD4B59963EA6C294DC36EA3895DDA9B5A5210B1C204F0931378B63D07D83EDACBCDC1913480A40002890EA70EF50E3CCF2ABC75BC1E324E2A54B988980F183C4970599C56A5AA79024F9D7DC6A98813D20CFC2671D6C294A4F184929677D199F6DA1FA51C5FB520F808C16E2936B03CC117F81FDFE0D978E9083C2A5805D807D75E7E958C29007EE4B7A75B461DF2FCBE18593392B0E9623707F88C25295164873B545FAC721E5733EFB7DD184E62CAC809E8C2BB6BF56E861712BBB0EB0C0DAA6EDD6BE0F0A5B7AE20F3369DFDE479EDCEDD708A8197520872F7A93CAB0DA601707D2FCFFCE90B98A92926F04C11703CFF000E9EFC69DE23FE43667E7B7AEFE71173504A8EDCDEB4E7E14F03611EEB687EDA28B56E4B4B5F415A52AE04F1D1A5E217C560411C4166E3A7DF38E6399F626461D6102527814FC2B0078B860C29A8ADE3CD998767A74BE2480525248A0B9AEA39EB56D5EB178E49AE334453F7F4CFA815892D38BEF0A78605FBCBDFC85CEE76C51332ECD2A51504A4109B70A5B5DC5C575761B55AAD3B0B8CC3AC8429418B0BD0EB7A1058D37DE1F59ED3F380A087E9289F44C12ED2D2B93E678DB50DAFCFD0F2A8E27239D5265CE26E005AF437007260CDD6C61C49C46310A1C530BD1BFC3FDC0BD4439AF5CE555D4CBA5CD34F64F5497C4718A2A26C343FAA5419FEA9EBBD84E18AF21C793DE495CE90031502A5176EA6940FF589019B62A5283CE551810ED723622BCFCF522B5CDFB3AF67DD66EAF2FCEFB396332AFAC2502A292A1C6C256BB02453A20415036FF66188CEB38C8D4923325CB9693F32141F880E64D2F423AD6AF7CC8BB5BDC00264D2486A9558EB63B8E756E515767DF44BE94D4D5943A8B24CC93A634DBEB53D9865EB4AAA14EB44828405B8E25C4102D298266F84317F16D6B0642E712A0024FCE471102DF9DDF5BC5D95F1144891FEDCE1C481FEDA8A8324EB427E606DCAFA477C7D9F7D9C7B1BF67AA34A342D0D3D5679C094D4D6B85456E38911C443E55B5C0124016C53B1B9B6233E0A016B9724BFCC16544BF315BF372F1C73B5BDB4C4666B9AB99882B5ADC10080070B8700161A3B00FD62F7ADA8AFCDEA1E79E7128503FF00080084A06C0003853B03748F9E236528E440AE72FBD44DB155C80DA924F5276E42397CACC66CC5CCF9C92EE43DEFABFF001D2C18EA1BA868C90EAD5B7F2DB52A40B72067D66230EE5769702A2C6580FF00F73B3F40C352CC35F14CAD255C4B40E2B82456A6FAB730C2B10ECEF2DCD336EE9BA1CADFAB7D1C501495D3DD5612A5800CF9EDEEC4CE03B5584C3AD5C012C59EAF41767E5CBC21533CB049FDA6800AFD056FFCC41ABFB1BED433849527206E8A9553FCE56614EB21276250A58579C73C5830FF001272BC3AC209698080592ABEB5667DB9962F184B03C4940079102D52C34F0D1A22CE7B251CFDC0E6A4D7BFE1F553994308CB855F7FC5F693C6D984949B1379C2B9976FF173C4B396E0063925F8D426897DDD9A8C1DF6687285A6682274DE103F682C767D3F1B58564D967B21F65D4252333CE7FC431F689A77A9B8E05F63691CBFDB11E9EDC768387E4C1AF0AA028A13DF84F47FA862CCCD192890141960B37F6B7D77A0F1B356279967B3CF6099382468C4BCEA88870D53EAE229333C278A2FE93E7B618E23B5FDAF517FF599D2907FB5DEFA163A57CB7AC6FDEA01749D2EE5B67FADFADDE27796697D21A7CA7FC35A6A8A9383ECF1B0D3A44411FF0015B331FBB620330ED06758E97C189CC31334310E16B49AEC42BAD346A88DD38B9A97216435AA4937FF0015E512919B57BC022B6928D086ACC062969D98B00412D213C5B5A648F2C43E0654C26628AE74C2B238B8E6AD5FFF00B288D74617BC4763731C59002669D59A877D4F3ABF23B4267EAAA9D1C2DA96849D82145239DBC307E189232491F384B06350090FFE79C468C6E3CFFF009AB67BBBFBAFF986E4D23EEF117DC70C1044B8A264CF99318CA70A14C18005F4034B53D4185C6231441798A7A52A75D9EAFE8D7D2368A669BFB4A048DA483B6F2663F59C6DFA142A9C219EE40E8297D2947A987099939BF7AAD73CC31D7E8083AE91B05752D28225002F918E533B9EBE62E37185E4E02683FED2481AD2DA6D62C0DF43768590954C204C2549A9AD3A5074D61A6AF39A61242D23EEF94FE53CBA494BCBF1258976D86DE36A5AFE26B0A77097A02C3D3C798A5B41D6182AF5353D3000BA0C93CFA6D173E5D6D6DF129272A5A8025245AADF7EBF4D69019090C421C7476D39EAE59BC223957ABA94FF00E6206F7B731F0E5BCF3DF9E2564E50B15009A6C69E8E29F7B464E1A5A88F9051E8CFF5B7DE9ADE3D57AD92D001B766667C5C899037807DF07D7793939089A1D480A6FF00B45DEA6CFF00CF9C2B2E44A03E54B3D28E35F23E1F5AC46EAF5D1332E024F981703EF9FDDF1292BB3A84B34B48662070F2E9F4F387224814E1B5BC798F1FF26AC4FEB8248F1C8BDA76EB3064CDA67DE30FD1912524809BEC9D69F9F43194A149B06ABDC7E61ADED6E20F8EFCFC5CFDDCC7C2C230F5191BB30B96B379BD6AFE1195778BABD0FDB772D7B6BE02AC559AD9C514F0AC889FEA22F3B7EE63ADF0FE4E412CF1712126C47187FAFBA1D2329413FBEBBD6FB6F0D8E6B47044B86C6F0A3CE23F73D7D0BD4E4328544B40D43247E2AFA53F30B2252410421B9D2BB52F5D77844EEB4709003863AF11D86DB9F8F9DFD554E4B2D364D79240FB31F77D1DA2593FDB4F23EE9AC37AF59AC190B3D278A40F7491BEDBFBF7C2C32996DFB6ECE784D5B4B034A6DD2B0E901496615AD684DB66F7531A15AB7BDB29DDB621506FEA47EF95F1B272C4A5DD001E97F21E479C273A5098C0A5C8D4E9C98B7D630FF13A3FE72BFEB1F9E37FF4E47FC47FE3FC421FA51FF11E9FFF0014649D581BFB2E154EF2A063E78D55964B3FD96D923EE3DFD33FA61B0B35403B6E746A465FE3157F7FCC634FF4A957EEEBBF0A7F119FD3E8C1B664FE63735AA43C4953844742448F71F9FBB1B0CAD228897E694DB5D3A437992BBB366E8CC3DF5610B11A89B3092E18F27279CF33F0F3C68BCB4D7FDB05A96B1E8072D0C26505AD4F03E90A46A244801C2044471013D363CBC81DEFBE1BAF2A0C78A58DEC34BB346BC25DDAF7706B4FA78690BD8D428FF9A4C46EA3B73B49F2F293E986D332A4176403425B8454F887376D3EF0265077E1A1E8FCEF57A5DE168CF1A72C482636DC1F98D8FE7E8DCE5A949FD95BD874B1A7807D79C6C999364D251297BB38A3FF0027FC085CC668C9220A2368205BCF632447ECEC9AB06A0EC2FB69B3D7ED5D1A144AE6ADF896FE0F777A9A9AEF7FA2A7ABA99D085B8A03BBFB306DE2E824903AED88CC5617852410EE0D5BE85B96AF6B6B0EE5CA4B8243AA846AED434D9ECF53E149365999E694291539324A82E0385253C410601B9BC44FAF5EB4DCC6429414921D2F620B7277D798B51A25254D9929B814436D4F67AC7567DB77B00A5ED4BB305EB6D394AD3BABF4BB2E5454B4C3294BCF0755FCC2E148057C2DA55048558408B636ECD664BCB3324238FBA4A96912D4E594010E341C83FE5BAB762731981610B52969510169528B125D88B90C6B71E0F1F3DEDF7C9CD169A9416EA90E3AD34D2814F0AA9CA90F02081B7091E21D0EF8F67E419B4BC5E5492A292A54A0D624D00249A55C53CAC63BCE1132C278480A5000AAA0B712411A36BCF4A4697EA454D5BF503C285C252208129B1811D762371BEC3140CD6562958CE296A57095D6A433B5AB6B0D00E909E290002430B0FBFBF5A911C71A7AFC8E2D7830B97853C6493C22BAD479577357A437C2F0AA635C3816DCD79D6B5D7AC1C49EBFBFDFC79616CAF1697982656B47D2FEB41B810F33340084100301BF2DBAD86BAEF0718DC18F49B7FB7AFC70E715884ADF84B372BD6CF67A723CE2118867DB6BF383BCB8857A933CB6DF104A2B33388289ADF66E4F50631C2083405AE453F98BEF4CEBFCDF43E794F9965D50E9485A78A88295DDF0D81BCF01B5F613E9389CCCA4CD4A54264B2DCDE9A333756AF955AB79A64B214E90122E5D87873771AB063A47A3FD9AF6B949AC680D577E18AC69B6BEB6C71EC4A61302449317E104C11D714FC523052810B2902A5891426A5C92FAB5FA54C72ACE32B420AFE502EC58E976D2A03FF88B92975032FF000B3DF1EF098060CA89DAD33F0B9C432E6E5C16489B24DE84A74A015D7F8AD6B41C609525441205D9B715BD06DADCD9EF6EE83ECAB5B768350EB793E5B50FE54D29BFE2754B96830DAC8285202C02E710E48E5638E73DBAED8651934B95204C947133828042784BF0817297E17D373D5A2BB8D5A964996E529BDEFCB566D0135AB011DD2D15D90E98ECEDB64D251AB34CE4F0F1B6F36E0097089238DD053B93B1B45BCBCFD9BE69333C33A825243F090A492A0C492CF4E76356880C4E65370CC10B50A907ABEA4034FCEB511720D1FA973CA74BB9850A68287861084D6B6070931F612B498883613BE3974EC1E18E294938898A585314894B22EFFBAD4E6CEDE4C27768319C247129B60AA6D6F13E8C740859ECF74CE5CE17559BFD55D0656D80B724F31C5C5CAF7DB7C59F058F9F94200448336591FB94B09B5CD7DF48623113712A75AD4E6ACE6BB8B6FCEBBC3A21DD1F9780DAB2B39D2C1FF8A2A1CA5EEE01B9008E3E2F88F4C6313FABED08025E23BA425DD213C44BE875A31E5E4D0E01EE482C41362E4F56A1F62140D434ACC8CAF276E8F7E12B58A883E7C6923E0394E3597D9D9B29242E6289D4915BB3D01F7A1BC67BF528D15E0DCF701FCA13BFA8733AEF0D656B14FC00865A6E89A05C9B1054840222DB98F538DD1912A5926592CAFDC5CB6F625FC9A3638936770391FB8A35A181F4E60F2A4D33CA6C99EF9352A02277EEC1F7F4F33857FD3141642940A8EBC21D853C8F5DA35EFD4C3E7A3D8D6DD6ADA7F9AEC66899701EF2A94542E5050A3C3D07113B5AE7975C4A6193370547252451AD4B9676A1D7913A43895378C92E5F4FA1DA9A7DAA615A72DA350BBC1405B927DD333F9728C3BFD54D5DB88B9A72A59890799858924B98E54DD2D00965C4A4B932080EC91B1B931FEF8D485CF0CA4A8105810E2EDA5AB5AF2B883894050B35BDDFD61AEA734A76E4ADD4C83C92904F98E1FBA2270A0C02D5429241D473B56CFADBC633C4ADFE90CEE6754A248524C03BAA260F9FA8DEDD2C2F2585CB5612921041D0B3D4F2A57F31812C4CA6A2D6D8D1CE90CF55AB69A9F9A401207881E66768998B7A5BAE256564EB99520925BFB4DFEBCBEB1B230FC26A1F6A8007853CEBBED11BABD74DABFE1B89404CCC280BF2267EFF00C0E2464E44416E124DC534D74BF91D21D4BC3D89A1602C5C9F7B6F4D622398F682B6C2A1D49DFF00AC1BF9F8BE44FC70F9390AD80EECBF215BF4AFD0E94687430C4A696D5F9D59BEA2B10DCC3B45714524BC00122EA03F1BEDD207BF161CB7B3A560BCB714041B8D057EBF6A8877230E5AC69A569EF96BB0BC56B3B4274CFF003C1B5C718B8E5CC1D8FBF13F2FB3290C020B3EC69C85EBE7BD9A1D7E9940174D2847A3B1BDFCF61AC6730D74EBDC20BC07093B2D27AD890445C72B5AC31212BB38D5087DC375D5B5BF846BFA6511FB5B4A9B79D2CFE0F117ABD66F4121E1EE5811B473EBF2F762491D9DA0FF006DCEB415BB3D3DED5739FD312E025FA9BBB8E9D3A8A9BC323FADD4D59C701076F18E80CEFE5BF2B7962570BD9F24370330B30F64756E75610A230AA0FF00280D7D19ED5F77861ABD7727C2E5AF238A47CFA7CBA8C49272229BA7A52956AF8B74610A8C3916FB7E7F9E70D0AD7624CAEFE6A03E127FDB9E1C232276250EDA37E038AD7EF19EE0A86A474B5C6FD6F081ED729BC3969DB8A62FCEE7F2DBD70F139250108236A7F07EB1A8C31146D5EAD7D45C53EBB504379D6E924852F6E7C5E7D247C7D30EA5E48E920A59D8BB6CDEBE5AB88DFB824BB12CECCDAF8EC368D0AD689932A9F5503F8FE1F0C384E4D5B59DD9F4BE83EBE70E65618809171B31153CCF975E621139AD1004057583C561F3F7EDD05A7191947201D9C37A5479D7C61CA70E77E800000DFEDAEB7842E6B34816548DCC1FD7CB01CA3E604A75676F1760FB9A9A51E9ABC9720A52294D69E22AEFCE91A0EAB2F9F02E387FD43F3B45EF323A8C64E535A203176A7D69AB56FB18D2761EE5B85EF47D2F7F1F516783FC48EFFCCFFF00DBFF00DF8C7FA47FD89F2FE21B771FF7FF00EDFF00EA8DECEAA2D1571B9BC478F8BE65780E51FF006A4780FBA4C67F4E7424F8375DF979F9EFFF001827FE60F889F778BEF23DF8C7FA3F21FF008A7D7E5FA03E107E9D85490741BFA46D6F54A9E0781C1E189850E768B98FDEF8C8CA7874A3DC8481E845FCFEC9AB0E4E8EDCF7E9E1710B1BD46E5817418F303EE36F79DB91C6ABCB05004B3BBB5AAFBDEE1CEA4D18C2470E496143AEDE2FBC2D6B50B8AB9581111E2927E6267DDCF0D26654521F87992C3EAC2DCDEF194E18B12407D28C79BB17FAC3A53E7EB1B391CCDC193D37F38B461A9CA8104B709DCA5F9D01AB6B5D89D2038751B06F33E9EFF0FD459E2D6482E4111CC5847AF4F8729B623F17960FEDB1D5ADBF43EADB420BC3312141C9361F663AEBD4C3EB19CAC443827D45EF1BCD8DFDF798C33565E59CA496A0A5FEBB3D7D4C604B22C9DB63B0F2B44932BCC52FAF8AA163BA6E244EF3B6D24C6E0EFB79E2171D97F08F950E482CCFE24BD36D3CEF0B252DB82E1CED5E741E9BD22CFC8335A8A358718521748A0016E526124729BEE79F3988C5231F8104A93C3BDC5413A1F1FADE1CB52F6DEE7A7DE2DCD26ACB975754BCC1097B2ACD695FA6AEA75A789BFE732B65B24104594B9102058CE39BF6851330CB42652CCA58585058151C2A04B6B5142CD422F16FECC6293879C1CB391AEBD1EBCFCAF48F9CEF6DCEC453D8FF006BB9B53E5AD1672ECD2A955793A82785B525D1F58A80826CAB2C8DE4131CA31E81F87DDA6188C261E5A965CA02189B94809FA82DA72B3FA03B3D8BEF25D54486A9357A5013A0157D7C0C74D2ABBB052EB3096DCE5FEA480164CDEEA9FC31DA6465C8C4A5331828DC1AD1EBE66C7A686B162C47CE9048A1BD7A75F01F50212F193CC7CBF76C2799A46164100B508352C4D19EEF6FB5A1BE192CB1460487B59EB7B35FC290059E4418F43E938AB60712A4AD556726AFF4EBE3614A43DC6A3890973A58E9CBCFEC39C1C6AEBF218915CD2A04855DA94FC6DA188CEE81BD4E94F6F1A9D5AAC449F203FDFE7F942492AE249507BDADB7F93A36CD1B265814BFA790DDF6FCC7A3BA43D897DA2F5C86BEA1D9DBACD2B9C3158FD630D2824C1E3EEDE0950B72DEF1CF109DACF8C391484CC42E6A105415C251F3B535E10DEEBABF38C7769704B92172B12998B1747ED3714E22DAD4D6B66B4771FB2EFA323B56CA2A9399EA1D78747210A6D6AA3144CD726A4020A9254DAE121039911D31E74CF7E22FEBE6CC565B8A54C492A74F094D9C8A96176F66B4ACEBB4B97CCC32E5CDC083359A54D137F6124B9617A373DCC7A1DA23D973B3BC89348F6A0CF3FC499951F0127EAEED2071698B424C47879881C81C732C7F6AB39985412A9A82EAA85135362C08D34F0D8C714CD7321C4A505F0D4B03B6D4D816F2B477032AD5941A7B2EA6CA74F640CE554F4E8E053A82859AA000092AF00360247112761E58A2E2E566799E2A6623173A64D248E10AE2F92F6AF47635110F85C72269520AC5ADBBD1BC3D2B4763086BF546655AA2A4B08926CA0DA02B9DE4241B75B5E7CC99BCBF0F2E401DF715AAEAB378FF0098658C099AA50490E2E68C3A6CCC7576A924C372179A66055F5879E42531C0038B00850B82124585BACFBC1C4DA27E0A50FF006D12B88B392949B5AAA07DEA62115825153BBD4B1A7A6C6DA7D6323953847896A51B9924998247351FD7717C41E6D2D58B1FED6D460D76DB5D6C2BD0C4AE1308997C2A533E808E76A6AFBC6D6B23EF02C13B478BD7900227F0C23914B9B9671778E78F7D2A4B6B776F3AE85C6324215C212CEC4B0E5CFF000DF58548C992D7DA337DCCCFEE3F199C58558EE2B067E8C3ABB3F85B48622411CB7D7EA60759669C02549E7731F2263AC1D87C30267297706BCD81FB7E203294081777DBF3FC6F081DCC1A6C11C4205809B5A7CE3A5BF495912B8FFB59DF57D7AFE2F18187481F352DA93D69E7E9CD9ADFCF295B1E25A0127910368F537BF3BE1E4AC04C9A3E54BA74E4EF57E5B887985C3BD402DA1AD6FCED5FA54C45331D494C0C77C241BC28DF9DB90FDDC9DA4E464AB5172953D1836BCF7A57E9A43A1865392E4826819BEE0EBB9FB443AB75AB742210F7171CCCAC9022D6931E640E9EB89CC3F678AC0FF6D8EED7DF4B8F2DAD1B0C22B899ED5B73D75B369BF2787E65DA1A47178C738B83CBF5E7CE713B85ECD129629A1E5BB9ABF41F5AD2344E14872493A746D9CF336A6C0C40733ED0B6876082AD97122D0441E5F3E66F89AC07674A685048E8F6DC6DD2876A43BC361CB9E77A5697F434A75BC436BBB41324F79BFF00ACDCFBC4C723FB8B0E1FB3A354576E1EA3969F4EACF93874BD4D4B39AE834AF95222959AE43F056F149127ED913B8037F5BFBF13123B3547EEE81B427E809B914B386B343A4618306147AD1CD6C6BE0DE43788CD5EB068C8EF8DFAAE6DCA6F6E7BDBE589797D9B4A98F7551CBD5ACFFE7A3A4E1EB56E5B9B6B5E7AC43B3AD58DAFBBEEDF20DEE167EE9E5E66D36C4FE5DD9FEE81FF006AA2AFC3F5035AEFD61E49C307B1D19C1D2EDEF4B86788B3BA9D2265E3046DC6ABCEE7AFC671369C981AF776D4A5CFBEBD44385E19EF47D83BD3607CBF8A36BBA8D0A36748893F6D573FF508FDDBAAE8C9D229DD9ADA9FC72D6BE71A7E9056A6AEC18DC7D5B7E669B35BFA844477AA02F3E3E7E4388EE3D371CF0E1395049AA6BA387E9B37DF5A46C30E052B7A50FF001573EA219AA73D42A25D3B1DD5CA36267F73877272C4A480C0A8DC331157DDBCCB42A891566BEB5A5DF586B5E78DFF00CC83CA144DBA993CFA6DF0C3D4E5A1D9491E403EBA9D3FC6F0B7E9B97BFF00CA10D4E7483C24382F3324C7DFF8CFBA30BA32D4D999ABA13E2CF18186219EA77615EB5D36B5F786B733947F79224CF888FCE3E1BFBB0E9397A00140DB307ADDB9529BBF8C67F4C1852BC8D3EB60DB8BF846AFE309360BDA6FC479FC3E736E470A0C1A122890185C00F7E46329C355A95DDBEA490FF583F8B0BFF337FF0054C0EB73BFEE6241D7F4C904B2789DDE81EBEFA7285D3866360DE05BA0AFDFC213D466893C1FCC169B4813F33EE3B0DA231A8C3006A900B9B81AF9FBD03C3A120B8AB0D680136D39EF6E468C98E66836E3DF9123EF07F0F86F8C0C280A761D7DFE2B0E8480C38BC472D371EF5B473FC5120D9C8DB65728F51CFC87BED07E94034008E601FC74A8FA97D6761C10E030D8D7EBEDDB678E7F8B27FE67CCFF00DF83F4C3FE29FF00C53F986DFA73B0F21F98066C9FF99F3FCD6707E987FC53FF008A7F30770761E43F31BD19BA37E31E627EFF0017DD1F2C1FA61FF14FFE29FCC67B826EDE207E617339B213C5E33B8D951F8FE76B4EF8467614355218DC507466277E909F72C482068C43535B3BD5F4E421623371FF003150623C64FAF3133F39E9BB7386410FC201EB50D62E4B1EA5CFD8EE52DABEFF00C3FE617359C246EE131FEA8F4B4C7EF6EAD2661527FF004BF5BF466F00DE91A1C3A740FCEC7CADEF943A339CA0442C836985DBCB63EBCC01E47082F0A91D342C7C6FCEFEB78CA64243D1BC4926FB1FE6D7879A6CE923FF0030F23F68F4E7F9FC45CE194EC185E8F76205B9B3F98B6D0DE6C904BA412750697A59FF00C33BC49A873A4C0FE64F985493F80F39F29C355E5CC91476D19B6BEECED61630D55254E5A9B8D9AFBDF661E1131CB73D6D2140B84484DC93FB267ACF3B5B10F8BCB8A83F0D3E6E6E7714A536D61352787C7935A2C1D399FA03E805C24150B719EA3913D6D7EBCE6714BCC72E67213BF42EEDA7F986C0BBF36B16A0FB7D1B678ECEE8ECC935D4EF3282081DD13D4410641991307EF3B938E37DB1CB140899C25C3F85BCFDED0E30D8BFD3E225B1A715DCDF57DC97AB52F7B8E9CFD269D90AB53F64592F68F48D71BBA51BA82FB884CAC8A9752D278D43C4AB279F981CA63FB199D4CC2E3BB92AE14A16800380F4D282C2FCE3BE763F302B44B4B965D0DB7F16F2FA57E759550EBA029C04252A5049DBEC98363CC4796DEB8F6BF65F3046272F96A7015C1524BE9F7FBDDE3AC292424275A1EA0D7EE235973CA790BFAFCBEEC466758B4CC5292142B46BEC7714F5EB1ACAA2D3617FA1FAC6C43A6FBF2E7B7EA7D047DF5D912560B83424F838D74A335372D0EE727BD606840A86F2F7EB1B0B806E23D4E2465A295DEB7F2F2B9FA86847B8AD154E8E7EDF7FC62AAF7996D4CB090A2F885180600E932458F2BE375A8A0505073DCFA6BBBC6532120D4B87A7E49AFD0D23EE58D7D7B87F90F334A23FF2295968091784A12916E623D31F37578BC5A49054B501AACA97471FF27AFBE51F3CA5769715303AA6101EA6B5FE43ED5118703AA5A7EBD9D2CA567C08EE54A9F78988DA670B48C74C2A0F6342C03823C295B785A3188CDE74D4105448152E6ADF515F10FBC0E648A52C3D4AEF7A94C12A29E19D8EDF3369DEF89FC362659FFA92DC8D697A7DF5262A7986266CC25B88062E01D5DAA4330DAEDD21C9344BAA4210D27854CD9CB44CF4DB6F89B5BAECAC44A94B981494B2998961D0DBD2D5A44223193A4AD8053137A83D2DABDFA750BDACB5F6CDC098B4904DAF17E9B11E82F88E9DC331F8080EEE069D1F43EBCA27F098A54D62A0DB56FE9B3824C6F51553C7188045A0031B7404EC3783BF4D9A270D338832B6607D75F21CAEF1348E129D1C742EFF009FA51E95D2BAB49025503DD3D3CA3979DEC77C4B49904252407FBF99DFAF3D8319F8954BF9520921D9A8E487A300D7606D5D286123F9C374401EF078A6F206D1D7A5AE7E785958454D0C0356E2BAE9A68CDFC467033666214789241AFEE24BDC5F41D7CED114CC358776094B891C878927A81E5FBEB87587C996B3AB86A36A58F3BFA44909243D0BA7C5DDF9EDCA21B5BAD14EFF00E6A470837E310679DCEE3E78B061FB3EB2CE14E74626F66BBF9BF278DFF4E5DF57DFF9BB546819B6880E6FAD9D6F8887B69D9423AF22479FE63160C376616A1FB554D83D6DB7B1CDE35EE00AB7A1F5AFD6F15B66BDA0BE88870DE40F1F48E73CB9C1FBB16FC9FB30025416973472CEDE5A7869A562470522A6C69A0DFAD36143CEA220D98F685502DC7133FD53B6F10636F8FCB16CC3F6725A588439E9F5A55F95F6DA48E1C1B25AF63FCBFD36882669DA3383878DCDE784957BBD2D7FDC625A4644840712BA8B0D0FDF5BED77C7E98EC697DB96BB11107CCBB458E2FE77C553F79B7EE71268C9D9889543AB6DE1AF2A6F48C7E90E80B68000DF5310FA9ED0A7ED390449BAAC7A9131BF947C313383C8D731C22512433B06F56DCFD2978DD187E0366A790F7B539C45EB7B40041873CECAE77F506F61B7289C4EC9C8668209924071A52F7A57C0727DCBA9529D541C46CF6F01EFEAD11B7F5BAEA15097002264F1011D0EFF000F76DCE7B0D9404FEE4682E3A7D747EB630F112663064B02D522FABDB956CF6863ACD5CFC121D83FFAB6E53CEFCBF6226246552001C400A6DE27D9A6D7A391216CE433D4BEB40CF6036A18607F54BEB8974D898BF2EB24EDF893E78929796C9154241702A18EFA7E5FEF0F24A1449F9438B7A787AF367AC34BDA99C5132B248B595BCF94C7AEF85060D2094A6583762DFC35B975DA1C194B37413D4084ECEA0717C72E447FAC5FE26E6DF75BA6A708D6433BB8E1767DEDE756615A083BA57FC3D04277B3F59305C1CEFC5BF3F21B0EBE9B6105618B91C0430D8ED4ADFC1BD088C2A5A9AA8F4FB8722DF686D733D75572E584DA473262D3E5BFCF69DD18750154B73E61AD6E553585A5485100A505F723C47DBDD92AF3C5DBF99E9D4EDCBF630B265115B9DA94F7D75858E1A610CC5FD3F9F2109159D3A77583D25447E9E97C2F2E492C40A92761ABBFA54F846061542A5FC74E77E637E509579CB9BF797F5FD679F2FD70E44903FB69B381F7FABC6DDCA989AB3EDE9CE386B365A8A871DF7BA8FE07CF9DFF001467A120064B72B8D3D3A529CA364E1946A01AEC0F81B10357B46EFE28BFEF3EE3F9ABF0C35602C1A1C2308B001677DEFD1C68E2135466AB1C32B3B923C407A49323E1F9E08769C32C81C496E9AF3B8F6E7AA6FE2CBDF8CDBFD53F120C0BF909D873C10BCBC3B100A4DF5177F1A3539E83683F8B2CECB3F1302DCCCF3371CE647492359D86528D05A9AD3F3E3D2907F165FF0078FF00ABFF00BB0423FA49BEC472335593F6C7FD5FA9FBB0460E1660D3D3F98528CDDCFEF1E6388FC7D2FE57C118386982A416E9FCBF942E673654125520C589DB698E636DFDD717C379E3F69F0FAF2FBF5168495865F11A1AB3163CFF0093C86CF0B119B2AF0BE9FD463CB788C335817173A6FF00CFD7EBA9C24CAD1C8B50FA7F10A7F8BB96F1CF520FE67F7EFC345A5DCB3034F2B5A82BECC6BFA69C2C83E00FE217319C2C412AF7C9F4E5E5CA7A473C362826E0EFAF4B535F1F078C9C2AEFFF00ED3CBCB43E476877A7CE5C9BAAC77BDFDD049B4F2B7ADB1B499449F9833EFA5F57D79C379D87527FB5DF6A03B59FEBA59E251439D2ADE3B48983C85AF33D798FBB0E4C8960114A5AB42EDD29F73630C66495281052433871D7AD76FB44958CED61248724881F6A08F74EFD7732047945E2F0C1493C29A54E9E3CFF008D618CD9132AE9248A06FA790D6B6A9AC4D34E6A073BF44B877B99116E9CA47979EFCE9998606612AE14B8360C49D795296E8F11CA9337662FB0FF00034E76A563B63D98EAE0CD7B54CB5857D64A123C52045BC5D2C7A8EB7C735ED464EB99865CC54B628428B9005FC2AD66FA35232795C99E8F9480541B4F57D999E96E663B0DDB9E9A4EB5F67FED074C5434568FE18D5435C49903810BA8F09DFF00A44C1B9F5C79C50A548CEE4F092026629C02CEC59E9F6DF68EE7D859A4F03BDD2D6A5B7A59B63A74F8FECF1B6E92B2AB2F4A4257499857B4A064484D4B891D62C2D6BDBD4FB1BB15989465C80B53012C30259E95E6DCFC6D1DE904AC7117AA535028C05E9E3F9864539E7246DF1EB1E5CF0F67CC99889C7841238B9B33F900DB42A94D416A7E1E3969DBA813111D7F7E677E589944B972E5A12B676ABFBE6478187A9040480CFAF37FBE9D2371713BF14FC6F6F3F2C39425240E1200D83726D7A46EA42920929206BEF58C1EAB4D35338F012B4A9BE131600A84DE236EBD461963D69952D550686A1AB606F570ED6E51893C33961093BFA036F7D23EEB90C0E9E222361023FDBDD8F9E53E52438291434F478F99099412E05069ABFAD2FF00C0A4284B29FEA48F7807ADBCA30C912439A3541D3C4BDC68E7CA3612D9FE6356A36CDF8F7AB830F25BB13007B848F3BF97BEC39E25654A25258508A5DD9EBE1CFD8D0E1D157653DCB6E051A91B1598B6CA499049E9E198DAFE9D77B5FA6C704A9C40A80EEF5BD49F0D3F986D3B0729D252800005C52BE766F76863ACD46D37BAC022CABF4DAF20CF2DB79C3B93922D740E75A7A786BD7A88D512C22890C34034AE9A9E9EC45ABF59B54E2CA0419B1503100DF63F77E789AC276754BB8552CE2D466F7AC3C94859B17D19B5A52B51E9CA2039A6BE80A01404743EBB7E6019BF2C5830BD962B22A5AAC081F6D7973BC39124283901BC86EC6C3F07AC40B32D78E389480E9313693FB8F58817C4EE1BB2490589D469CC9F1A7BA0791C1E193A21B7D34715A7DD8B96315F66DAE570A3C6AFFA8DA37DE48823F41CAC983EC8CB05249AB0D00DAEF4D7979C48270E4B101B4DEFE3AF28AEF36ED01C6403C6A13360A304027A411E738B7607B2B289B03C2DA313ED8FE09683F4F5B5CD00FA50FDA95A33C57D99768CE92A951833BA89DC1DEF37F3F741C5AF0BD974060C2806839834D5ABE02D19FD393702DB0D34707C07E2209996BF7564788C09B137E80EDCAFB6E6313F87ECECB940B84D59E8DBD0DEC5ABD76687125A43850BEE1FD3CAA4FDE2215BAF1EE4AEBBA8F4F5B49DFD791C49C9C964B03AD68431246F7A07BFD21E09C820820176D486D6ACE2B7BC43F30D542BF87896416E600279FBF9F4DBA4624E564D2D92C052E4B5791F1B56C3785D130711A38A11A38A6BEFD2B17AACE512789C37064F118206DFEDC879E24E564928814018D28FA07A73D6DE10E51310481C2C7CF73B1F3FE222F9866C1C4A421C208E52473BF3DE2779F4DF161CBB05270E829094EF6150FE22C346FC6B36499EB484D00B902F50DB1BEBE2F0C2FE647FE6CEDCFDDD6D73CFEEDA5D12E4B5427A33B7B1E1607487D85C190A0E9E56BEFEEEFE24A2566409252E12044413F70EBE9CA63094D9485060863FF2A02C1DB6E94360444F49C1800028046C5A8DCDB7A8B38A184CE660019E33111F68CFDFBF958FA02488E99809ABAA490C6A03DEDB6C5F5D6BBEF3A42024FCB5FF003AF2DFC7486D7F304DA1CE479F49E9FEF6E587B80C2CC90E26329CEAFBFF0022FE15B6F8292921C867715EA77AE9BFDE1B575C913E3B936379FBFA7C312BDDCBD852FF00CC487E9D1B0F2FE634FD787FCC3F13FF007633C12CD78475FE633DC27D83F984CE55CC8EF0DA48B9BFFEE1F2B7974C704BD93B697FCC63F4E8D8797F309555A0117F9917BD8DFCB0D67A521D9205054372F1B75BEC214972057852FD037D2B1A1CAE17857A7895CFEEF4C3585FF4B47E1A1D77BDFE6EB094D7264CAEFCFC4BC107E99A8CDCBDAA38FAF23FBFFF0072F1B71AB7F41F88C1C283700F5FFF00EA37355C91C442F988B9BC0EA48B0E64CEDCF094D2FC3B87F173EF4AD6B0F30F85490C523C869E6F4DE87CE395E62019E23FF58B7BFF000184A1D7E8D3B0F249FAFF008848BAE0621479F318236FD2816007BFFD5187D70FF71FFA8608CFE9B97BFF00CA33456024CA80FF00D4411849603D2F57F48C190137D793FDCC67F5B1FF00311F2C690774397FE23F307D707FCC46083BA4F2FF00C4473F5DFF00F553F1FD7041DD0E5FF88FCC29A7AE09E225C076D898F7C1C27334F18061D2AAB024720295F0BFF887046629DF8933B1BABEE9FBF09D3DEDAC67F4C9FF0088B6C9A7F3CC79C2D6B304413C493B4C927E026E45F6F8E352949B814BFF003FCC63F4A9FF008BF4F7F585A9AF4C8F1EF72388FE7FBE538C7026FBB6BEEFFE231FA245F847D835986C75BBF285CCE60949FB569E4ABDA76B8993EB68C359E0241005DABF51B7BDDA23F17252904049200AEA6FF6F7762FD4D99A2C02F94183FAF59F7FB8E1A4462F0E922CEF534F1EA6FD6DBD5F18CD5278471C7FF5449B4F3F9DA2E3D304021BD7686D330E0B70D80A8A1DF707CB9C4CF29CD5B8038C8E5B91173E73720F5C2664CB533A438D587E3E90D558740BA4575DFDEACCF174681D52AA1CD58097152A75B54955E10A06C6E248FBF9099ACF68B29973F053D6123E596B7617749FA3B57D68D5CCD70E04D96426AEEE1A80355AA2BE7C8DE3D7BCAEBDAD5BD87E78F00852AAF24AA055024F734CE8B98F2B836BDF1E16CD248C276AE4B025299EB013A1E25746714BD599A3A576397C0123F69F958B1D3C2FBF9EB4F8CFED532F465FAEF523688FFF0036AE040B01154EF2B44DAD138F4D64B30C9C2618874F1212487E40E8D4D5CD01DC18EFD964E3330F2C7EE00539B8721F7A1D686DA45798E83964C9665924076BD34A1BD47D5A2591281E9BECD6DB4BB6AC6353AA03867CFF000BFA61863713F3B0535695E6E050F869D61DA249E20402C2EE59C737D4F946BE31FDC46FD7F77C2B2316521B89F4676E4ECE3E97F087989522649EED0C54DBD453AF4673D19A1592D5552BB4AE186D650A52F6E1E054C5C03E2888F7DE711F99E238A54C7535CB3FE4F98E9CE2264489D267A2784964F13ED5BE8D4BBB7231F79E8692483607CFA4F33D3A7E78F0CCE0A2753F8D1879FB78F9A610E03D0D5F57DB5D2372DB40493C42C0F3F96E709A10789238581D5B6B7B3F78381B9F2B79D7488ED6D4A5A053C6011100902237E63F600C4D61E4BF0B8B81A5FC2DADBAF283839BBEBB7AD5ED10FCD3352DA13C2B07ED490409BF3BC413187C65AA531425478B46D34F3F37F209AE5DABBD5AD6E715467FA8D6DF170B8044ECA1CE3A1DA62C7AF95A7300A98E01944BB35DBD0780A8F18C26497B39A69E3D4DEDE622A9CDB58AD9FB6B242A62E6DC26F6E9B7BFC8E2FD96E144DE10A9646EA20FD00A5A9FE21DCB96524937D2C7D2B5EB4E45A2BBCDB5B92170B55CC889B83D36E5E5B46DCAEF80C9E5A824DA81DC74A0F1FF0030EC218543BDCE835EB53EE910E7F5B59414B226D04EFBCFC62F137C4D0C914E381015CECCC76A3DDEF7D054449E0D245746D859B969A575F288566DAD93713E97B7BED7F48E773890C364D3D0CE87E82BA519BCC5A8D41121107ABD522AAE49841E6779DA2667CBF238B0E172F9E900041F6E3F3AFD60F7D07B6888661A8132A957B819F5E401F77E589FC3E167243841A5A8CE5E9706E7D7AD4888D4E7685127909DCFDF079FC2313586C0CC9C3E6490ED52DF4BD7931AC67F4C673102A7F8E63C3F9788B57E70832479F1413F7C4DF78F98C4ACAC9144BF16C76B3685BC7A54C2C8CB961EE096621CED56356BD6DADE22F559B990524A4C192491F1DFCF68E9E92B2325208F999E868FCADCE9CF5687A9CBE651817D6FE0DE218FD1AF1FA8CE1641959581EA2F71CBD3E3CF0FE5E4CAE22126946FAFAECDD6B48772F004DD241E86B7DFECC7AEACCEE6AB51FB479D898B5FAF9C6FD23AE1C8C9E63808AEEC6A0BEB5FE3986896C260121412450B5C1B53FCFA8BC36BF992C09E226677F48E7CBF0BCEE4AA9CA2626A2B6DCEED4A9E9FE1A7A4E050006482C5C161AE97D35AF84256B3155F8D5BCC4F9CC70F5E5B5BA61C270252C5436FF17E56BEB1209C2B248E17DC8D2874171E2E7C2BC3B5CE411260FAF59DCF2FDC61CA30E84B3801AF41CAB47DBCFCE23E7E1493661BFB1B37896A351B2A6BD5E0B9B024816B1F78F2DA2FE77C36C5A65A47CA41248DBC79DB6FB554C0E1EAA090E297E67DB9D078C36AEBCDF7F2137F84DFDF862E6EE5F778933873FF0017BD5EDEDF9F8C70D57295C526C47F70DFD27F7EB8C3EAFCDFEF07707FE3EA7EFE5BEDBC60BAD11BF3B78B7F9CFEEF8CB9DCED7F483F4EAA7CBFFBAD6BD7E9CE13AAB48820F90B8F91F3F3239EFC9A4F533EAFA93AD3EFF8E8ACAC39049663E07D5FDD7C343958B04EE6666E39FE1FB3869C67610BF72ADFE9F9F7B084A6B960917F88FDCE0E33B080C957D36DBA8F7BDE31FAFA86E63DE3F3C1C6761EBF983B857B03F31926BD5E220DCDA26479EDE42D84D6B347ADFED6F661C4A94A4D086E647531A5CAF72E01168237F9FCFA634EF03B51EB47AEADF673D690B776378D62B9CBC903A6FF00AE0EF361EBF7F380CB1A13E35FC4726B564CF11F404C7BED8CF782BF2F42F6F483BBE7E919A6B14641519F7FE53F2C36985CDB73E7FE20EEF73F6FCC67F5A3FDC7E7FF006E138CF00DCFA7E20FAD1FEE3F3FFB7041C0373E9F883EB47FB8FCFF00EDC10700DCFA7E2334D6A93B1E7CC9F2E91F3B61399A78FBF7F783806E615A2B960DD56F53F7613804B7DCF41A7BD7D216315EABF885BCFAC7EF6C101975D41E63CF6D87942E6F31541F189D8127D39F5F33D7041DDDAF6F3E6397B78503317131E3F2DF9CD8F3BEC3973B9C359C6B4B1FB010D71320936B8EBCB507D1FC21DE8F335DBC44C45CC4CFC7A7C4F5B611861330EE9735D29D46DE0F73E7477FE28B0A49E3DBFD44EF1BC47CB6E7821A2F0B47776D36F51F7EBBCB329CD96384F1DBD76F9C8FC799C10D26615DDEC76BD1B57AFAED13FC9B54FF000DAC61D51528CDB8495472BC0B5CC826DD31AE324A6665B8B2A0ED2D4C06A58BFA3442E3B08A98A49093F2B9A3F96AE6EDBB7378F6CBD997355EA5F67BCFDE52A4D3E5758949245FBD4BE9304FDADF604FC71F3FFB649123B5982401FF005712B04805CF0A9EB4A6CDAD6D13591CDFD3A892A090180A736B6ADADCD5F78F93FF00685CA9CC9BB50D594EEA5499CCEA1490A052654FB8A98224CCFA73C77EC19E0C34804D3BA43518B848A7979DE958EFBD9C9C3138292C6CE14D5B9A3EDD628C2A80241133F2FDFBBA62D597E294994B00B16D4E95F5B5766DA2EF2E41090598F5D2FAB5FA5234B8B24A523ED5EC0C9B6FE1FD397C22A7628AE6AAAF5B57EB7B33B36BD61D4A944CA98487B51EDA6FAB4042CA0AC24C0DC81205E37023E3E784BF5CA42CD4802CC5DFC896D0B188C9638B1291A150B8B870198E97F1AC29CBE9DCCC5F6B2C485F1573CD348E0495ACACAC25094A520A89248989F3BE2371D987121614A77259CDB9FB6EAD169CD25CAC165CA9C0252B12CA9E95A55C9B3E9BF847DE977E9FD93F963CA8403711F2A7BBE7E9FCC24AA7C04D8C588DFEEDAFEA396E30BC997C4A7091422A7617F0A0D2FCE0EEC6F6B53F98AE73EA829E205467909D81F7DFAC98EB8B460240212785FA8B1D797234783BBE7E9FCC55B9BE6EAA44A932541C993C46D137079FC276B0DF16DC1E5B2E7FEE48A33D2FC853CDE977730A224F103A9341A6DD5BEBD04529A9B3509529C0FA9B324D8157EC7C3DC716ECBB219331490994058D5ADBD773E3CE90A8C314967EBC9BF3C9C7845379BEA072B141B455F129B24429B080667990072DF68E5D6F381C9B0F2582C25205CB8A7875F6EF0E932428DFDE9EFD451EBECD735CE5BE25165B0D5E1C0F34605EFC324C8FBBCAD8B5E12565C3E4EF0120541A35A84BDFD97870891A31A54923DEDA163B1A4429DCF5A794B4D4D690B444212D1B13BDD3BDCDB96F7DB0F26E6395E5F45CC9638AE4A817B73F7A521C0989902CFA0B7A38F74A52196AEA9E767EAD4F5954397754B50A99E9C2855FD2DEBB9CA3B5393CB0077F2ACF5501F53CA9A5B68C7EAC3BB73AD9F62D7D6C075786FA6D3DACF3F5AD19469CCCDDEE48EF09A5A96878BECC153402BA7C49EA17476E32094DC588C397D0CD40A8AEFCFEB4615C8C524B92083E9A569E74AFD62454FD8576D19B81F52D2554B04FF5B896E3D78C00236E5D779C253FE28F66B07FF56749177E15856BA70B92E2951E942ACB9A8501C4BD580614F7BD7D2AE87D927DA2F30095536892A09992AAFA54403B1852A779E56E7883C5FC77ECA61292E78249A32555AF20D6D5F95ED37815A12ECA490C18961A787516AB52EC81FF00637F692BCE8804117FFE25487E1E212379DB9ED84E57F507D98A033A9A517BBD68DE0C74E71312D72DCFED1677228C3E9E5118CD7D8FBDA329921751A114A4C1852330A7544033210553EF1F9626709FD40F67669E193312F40428A83FFE4297F57DA1E266C9B28A5EC198B1E4DE75FCC5539FF61BDAB69C4ABF8B68FAF63BB9E20DA16FC0E63F96850BF53BFDF6397F1B72650752E53901BFDE4F8EBFE3EAAA67C80400C40BB306DADA9315366990E774CB08AECA735A22991DEAF2EACE111BCCB2058F3DAD0716FECF7C51C97342522749413A77A9513CD9F7F4BD2CF244E0A53A025401F992E900DB52DC81AB1E42B11475550CB8505A1992447DB50A45373B82954131E9BF962D67B5997B3C89F2C837F9817D857573A69E313B875C9984F11EE82438480540F881EA28FE70D9993CC3686DC7AA0B0E89EEE9D282B0DFF702B13C53E77C2A7B41859A974AD249D5EFA52A29B5EC3C64A423BD05405750FA581BED5E9CE1BE9B397140A1CA9E200785250124F2898916EBB79E3538FEF090920BB1047A519E96FF00308CEC27CC4F0B39734A1E5B8A0A5DC51AAD182AAD6A2A2A6CB69DD04DF8BA9DAD7E57B72C379B356A2789C27A9248F3E7BBBC2B86C1A407721EE386CDCEEDB75BC2672A81BF17A99FC62DFAE10E24EFF587BFA54D9CBF43F47FBFF089DA9008E131D60FCEC09F960E34EFE8631FA54B7EE3D58FE6FEDA357D689DC93FBFFD3838D3BFA1FC41FA54FF00CBD0FF00FC51A9CAAB893BF5E71EEE56E5CF7C369EA1422ADE1AFB3E3A43997870E0B3F890CDBB937F6743AFEB3E7FBFFA70DBBCE5EBFC438EE07FC07A7E639EFC281926DCA3F41EFF008E0132A1D34D6BFC41DC03640F06FE613ADE4C89F76E07EA7DDF760332EC3A560EE07FC01F2E576A7BE75E5AA8826F3B474F41B981E9EFC379AAB134049F7EF58048E7C23A3D7C08FCC6FF00AD790F9E11E34EFE8633DC7FDFFF00B7FF00AA13545403C3CBD27FDFE5EFC1C69DFD0FE20EE3FEEF4FE6137D60753F13F960E34EFE87F10771FF007FFEDFFEA8DEC5481C5700F9C9B7BFF2F7E3459059B478C89203B906DFDBD79FDFF951F5AFF5A7E18D236EE872FF00C47E60FAD7FAD3F0C10774397FE23F307D6BFD69F86083BA1CBFF11F98D6BAA16950E7E5D3C8E119AAE16A3F8FBF6F183252756E80463F5BFF005FCFF4C23DE72F5FE231DC0FF91F211B1BABB9F1FADFF7E7CBDF83BCE5EBFC463B815F98DA94D6B7E56F58588AB103C5BC45FAFBC6FEA70779CBD7F88CF703FE45BDF9FA78C2E66AC492553EF9E9222D3EE048DF1A124DC93D6119B87245F8B9B337A9A7BD6AEB4F5A9170AB7979ED79313E7BFC318866B9203862DBFE43D3F8A43B335C991E2045AC4DFF003BCF58B804D8E0840CA150534BBE9EC6DE90FB4B9824404A88E978F3B79C580BFBB04365C8493C4CFBF3D37D4ED5F1AC4BB2ACF9346164C2839C299578A0191FD524738F90D8E179CA6CAF16583896B63B0E13A589AFE758426E042E5CC5D9858815EA6E0B79F808F71FD95EBCD0FB2ED5D6344949695DDC13FCC0E54282E4CC90248BCF4137C7843B48944EED9E012520A7BF9E56C43020B8DD81E4DE8229B3E7FE96690E032806D5BDB9E54A068F05FDBDF432A935AA356D3B60379C3CF297C090005320054C08B99DF73D648C7674C9270F87521354A45BA002F4B6BD3731DABE1D6681695CA597E3E16F326C7D1AA7D63A00E38971BA5B01F6828C7398FDF9DAFB626F0292A96AD29577EBEDCF5BC777932C2A47117AD46D5B57434ABD2FA3425A86DBA37DEAB026A14128A74DC821638551B83123E1CAD88F97294664D5317AF9543B7315A9778D258E14AC3BBD816771E7FF00768DD636D3A2B1861CCB1100D47F31E5282645BBC4DD5B589DA76B622F160C849AD43D0EA1F6205A86F5AF846CC42D13BBF2966502036C58BD346B335F778EF6FB03F600AED63B51A2D479CD314E97D1AE1AACC1F7507B8716A6CB8CFDAB28871B1B489B5C462A198E35499530A13DE2E89097624AFE5706F477A7E04557B71DAD4E1300AC31980152140A5C38614F3A07B1E51F58E1D3CB88FCFF001B63877007E5B7F37F778F9F9C01DF4DBF9BC25AB74847F548D8111F8DFEFF00961E48284B0A51B56BF96BBDDB918024026DC872F1BC5719F3AA2493369DCC1E87E3F23CA3169C04C92809798916B9D35F75FAC67853B7D62A5CF90A7DB5109714B483C21B6DC5933BC84824440DF165C366F83C1DE6254ECE1C353A6BD357DA364B4B2F50D7677D47DE2A6774EEAFCEEAFEAF96E455350951294A9C4A9A499302EB40817BEC79198387A7B6F83921A528248A30587A72A0AD7F9A43849E201D56E5E76B747BD8561E97ECAFDA4EA84B0E2E81BCA1944971D152C2D442AFC45016140813637B7B8C0E2BE2B4A94B3242D7C7503E55106B4AD4791EB487680901DC30B546BAB5CF2FF1132C8BD89F2547039A9B582D6E0238E9452BAA13CD2548570F94ED88BC5FC58CC65ADB0F8733127FBBBCE137D99EA74A1B5377085201254B02C01DFDEE6A7A98B4F2FF0065CEC474EA52ACCF4FFF00885C708EE5DFAC5453776A4EE4A41F1151E4623A9338ADE69DB3CEF3CE032E7AF03DDFEE1FBCCC7A5EC1B938BEB0C71B3004FC81FA503EDD39D3517BD8F92E82ECEB4F84FF0002D0F4AC70C7097541FDAE27BE428CEC7CEF88539AE70B491373198A7B8019E8D707D6FAC46778ABF057FF005505B4D1EC6BCEB411384559612114F95E5B95A2200465F48E97472921A0470F29BE21E6CC2B5154C9D3D4A15713A6001479057E5B771194CF9B60199EE7C4E8E437D2F48C175599387F969A65CC7D8A561991063ECB698FC3EE406214876338D35993162E373B7AECC20FD44FA1A5A96BB9E6F6F510980CD883DF2C5288F070A52AE3EB3C3B797320E14E29F8A002261436F523CEFB1B6F511A2B1D8894411C4C0E85B8ADB786AD4246D081F4D692AFF3EBB5FF00E198DBDDD6DCAE07A6F2F05892586206946035BD6D4DEF7B46C337C4B8002B954FD7D98E292AAAE9839C59824154471D325CE28F250300758BF2387A301895103BF2E3FE25AECF40CFA43C4E6F8A21DD7B357EFF0088455B995528101343524FFCCCBA9940DB9F1B4A3E9B1DEDB4C94BCAE69487C4CC06C7FDC56CDFF2F4737D459CA33AC5ECAA5CEA7616D2E77A3C42739A2CAB3E6CD1EA1D2F95E6748E712168451D1D31095483E36D90AB8B4CCFE2A4BCD330ECE2BBCC06227267AAD302D6BB16259448FB75D657079BE216405F130AB59EEDA8F0E7AC755FB47F61EF67CD76CBF579436746E78F0528290AAAA94F78648F0CA5BDCCEDCC88C5D725F897DA494A40C499B8E24D57C7DD700DDAC76E9EB76CAF3C521011DE84248658500A2DC8A99A9B75D23CF8ED5BE8FAED3B47D2AF36D26FA759654C079C77BB0C5338C34992986CA94EB9C491C8488913271DD3B2FF0014F033A748C2E3712A953E610132D615C20815759F97CCD7D0DD3058CC3CC40216971552C2C3AB88B8F968CDD181F38E8266B95D4E4F5CF65D9EE4F539457D3A96829A86DD6C1520AB8A0AD0849888B4CF58C7A4322CFF002AC44B96A5E3651700BF12542A0355D9F4DF7E73F28C9989052A0A49146A934AEE450727BC449DCDDFA975CA7247774D01B200D9513717DADF28C5AE74DC2E2403849A89CC3FB0BFD09ADF50FA6912299094212B02AA7A359BDFA084AE54AC78BC50373B7DE07E186852A4D155E6CD7AFBB429DDA9BF6D3C1BA6DCE113952A26C6C6F63EEE9EBFA6D848CD40B9EBEFDDE8F1A8049600B8A5ACFCFEBEB1A8D4AC0B98F327CFE1B5B18FD44A667AEEFF0068C9045FEA2353952AB024F316BF5F2F220F48F8B798B4ACBA4BFBD6A76DBF10B4A415548A6845FC287C7D79E935046F23D47FF6E112A22E9F5FE21C77279F98852C544855FE71F801F29F3C63BCE5EBFC41DC9E6DD45FAC62B7FA104EC2E3D4DA3D718EF92ED4715BFF001E9783B93EDBCA349A829224C1BC7C0F41FBF38C27326254086AE977BF4F7E31A2E480D4726FCB6AD1F583EB47FB8FCFFEDC2109F75FF6FAFF00307D649E7F13F98C10775FF6FAFF00307D60F51F11F96083BAFF00B7D7F984EFD491C3E2DFA1E9E83CF09CCD3C7ED1BA255E8478FE49F7D213FD68FF0071F9FF00DB84E14EE4F3F3107D68FF0071F9FF00DB820EE4F3F3107D68FF0071F9FF00DB820EE4F3F311B1156AB8E23F13F97EFE184E669E3F68D552942C09F23F4F7F6D9F5A57F71F9FFDB84E35EED7FF00131B9AA95C9FB5620DE7F21F0B7E4463815B7A8FCC2D455192788C7333B7CBF3C60902E5A0E056DEA3F31B455994C2ADD419DBADC45FF6318E34EFF5D6353254AD3AEAFA6F0B98AC54C71729E53EB1791F1913D2300524D8DFAC21370C412149F16EA199FAFD61C45728100199BEF7046FB0BF2F775B8C6D0C662129714BD7EC6F4A0FB43C51D63C2150AE198920DFF2837F7C8C10D7BBE3A243D68D424DB7A373D2241475CA75496388953EF30D260C905C702009E57311CE6DD433CCF172F0D96E2FBC584032D4CFA963E3AF4874890D2660586F94B02CF6EA3C74173B8FA1BEC932E1D9FF00B2B68FA5ABF0AEB692B56FA17214A2B778DA2524711FB408B1E51D71E199934E33B638F2E5430D3D3DD96268B25EA37B9DA38EF690044F4F0D52565C8B33EDCBCB7D0C7955ED5B912354691AE79C6F8DCCA3BF5B64265403EB2AB089DAD69F3C77CC34A98AC249F94FED0496A014F07D3CE3A3FC3AC54B44D9616B01D40124B061A07F7E11E28672E2A8A502789B75C1C306603846D048B7DD79DB137815CA08582B014CC4539D6F4D6F1EB0C1CD953B088E050AA400072035D35362D76DF3154DD453A2A160ADC6C0EE85E49912600331CFE06D8D1084A4AD4A2CEECADE9A7B6BD223CC89E678E142B81EEC5BC09D0EE2D7A54C4A74DE9FCEBB44D4791696D3ECBAEE699C54B6C90D24A9494A5C6C2AC0181C04CDFACE2A39E4E9638D226A52A6E27BB302F63B0B18DF3AC5E0F2EC0CCC4CDE1265CB2E95109F988212C4EC40FBD63E95FB2CECA72EEC1FB12CAF4165E86D8D5B995353BFA8AB1290871402D152DA54B1D1B5A9278546DBE2858291331F8F5620712B0F294D862D4512196E1AAC46A3CDA3C21F113B633715984F9689A5654B502534012F40002CC07896E91EA7B1926655447D58771C5B712527DFE2B981E43A1C70B9B89080E54C0D5C124FDDBCDB511C942944D0FD21D11A1B377071E6199B6C22070028412AEA0106C3DF73CAF88F566409694A5129FDD460281B91A335E90ED091424373BDF56D3C39F8F1FE09D3E811982D35A6E1512824F9413CB78FBB1AAF31C451A628307BDBA907C74BDE1596CE695F31BFE3E9B46EA5A0D0D917789A4C992AAAA93E15282DE128F25A4A52098B1B61AAB1D8CE204E295C25F8925DF956FA5FEF189AA008A577F0FE7AE919C67750E7F96A7A5A7A256C94D353A5413CBC41015EB27D26D8D44CF9F88F1926E4AD46ADA827E83F108F78BD090341B46EA8CBA128287DC2F19EFC254A0279020103D23DFC861F2677197500E2E4A413AB69F8680AE6A59C902BA8A37BFF0031C3542120711BDF71C511D49EBE67607AE1C8095A5C067A6BF4A46C0CD21C1247D2BAF46F5F2DCE5234EA47110422E2448E879DCDF6F28C289509746A35F66DFAF4A985E5A4AFF73923AB0DCF5F2BF38D7DCD3B444AD23681C201B7BC79636078DF8535DDCF5B102E3F30B7729DFD0FE61BAB6B29982D8E2499E21C8CFBC9FDFA61497825CD04A659D0D8F4ABECFBD3D20EE0173D1FEDA8FA4361CF295A925C47C0088F779FEC6153944C51A20DAC4747D2A280F5D20EE13EC1FCC6A7354D12225D47389208816B79FCF7E787523249E6BC0455E9B1DF6BFAD2B19EE65B5520EE5839F12E69A43255EAAA3330E3441F31F76DBC91B1F75C3F464588B842A94142399FB5CD39DA329932925F801F7EBEF48627756D1200971B93E693F8FE7E98728C93141B841D34660342F63EB7687689128BBA035281BF07C36844E6B1A1360E376EA40F59BFCBE6360F5392629A81637FF3F8A561D2654AB042481AF969D7900DCDE1239AAE85F04075B91E622FCE06C07E56E78752F239A0033251535DD2F72EF5E40BB3EBA34394CA40FED62350DB03E9CE8F57D9BDCA8A3AC061D4926F2089EBB83BFE3E58D66E5E24A4B4A0826B415A78529E7F58DC4AA6CA3F228A46843D3E82EDF9A533A677F8705BCCACA9C5005BA85ABBD698FEE0A6164A17C62D04731EF64B95396381C841FDCC9295F50B4B283105D8B6E43346F81CC7132D6089AA0C402EA2CC6FC8EEFE5A452BDAEFB3B7657ED079255B59D50D2E5BAA10D2FB8D40C301905D20904B0C25B42BEC84893326712B83CEB39CA1094E13113A6E178A924CC53CAADCA892A2EE0D7A6B1D4722CE56952146610B0DF31A82FA312D6D8163E9E0676FBECDFADFB00D4028EBE8AAB34C973175FF00E139BA1A3DD38D3249517036161B02401DE284F58DFD2BF0AFB726485271B89EF0A827E55A98A696625F5367B3C757CAF128CC51C4C94A92050597CF61E7D2ACDD7B66A2AABCA9879BEE129DDE490E4C4CCA40B481CEF3E631DFF0D9D61F30ACA5A40536AE6BD0D2BA6FD626BF4D2D29725A96B5ABF7F0AC37BEF369754C21125AB17B889EF49F2330009DADCAFC9FAF2B5CE485256EE2E3CF4EBAD3D61AAC4B42411FBAAF4A80F4B0AE82BF68C50A49DC7BB9FE136C4062B053B0EA3F329B986A7893F5864A4AAE09B583EEDEEFB721995A524F4311BCC01EF3BFDDF0CE04A8F1025DEEE76B6AD0E308EE41767FB8E9BDFF00883BE4F4FBFF002C3F2A01DC57FE3EDFEB121C09DBD4FE611D53B3C3C260DF6E9EFF003C319AB1500DB5A8D6AC6CDF88D880407167ABDFF10938D7FDC711EB98A7724977D4C60002C238E359DD44FC30AC82E76D59F67FE1E02906E1DAD071ABAFC87E587718E04EDEA7F3071AC6CA23E1820E04EDEA7F31CF78BFEE381AFF009F67CA0E04EDEA7F31C15ACEEA27D630D67000800333FDA3200161071ABAFC87E5846331B5B59BCDF6F238208DBDE797CFF4C10462A722397CE7E58D9258B9DBCF940C0DC3C63DEFFABE5FA6304B926D030B353683BDFF0057CBF4C20A5BD4D00F1FB46A5293A0FA7D20EF88D9447BBF4C325CD2C43D352C0F9341C09DBD4FE63626A426788CED1D6F31F71C21316695AB12696FB69A43BC3CA4283148DF9DCEB5E5D2B0AD15224907736BF436FBCDAFEB87324D5B6A75773E1EB08E250928500966B53EADB8E5D6E61522AA1485893C324DEDE5BFEEFE7187C491C2A0683CEBE86D6D0FA56E6C924AC17F9EB41E76BF36E557893D16A3294861D4A7822012120C5B9C1F2F4893CCE365E21294BB81F73C9C535D7C637C160F816EA0E97EADB6EE5C9F08B7BB19D22EF693DA4699D1D94053EFE6D9830FB81092A296E89D4542ED36F020F911CA71C5FE26F68060E5772998C262174E261C4052C59DECDE05E1BF69669C2483325A820A12C43548550F5A1AD3D5A3E84BB5B798A3CA72ED22CAD29A7C972BA569B0D98417051B45C848313C6920C0277C710EC5E07F5B3BFD426CB3DECF984CC2760A3C26DB0D686387E6D88EF2628514C5C171527AD407D457768F33BB46AAFAF52565129292AAB45434A4AA088485A504883262FF00AEDE9AC2E0D2AC0042501FBBA0A5DB571FC987FD9CC44E953A584ACA7E6B0E55A79D3C23C43ED37275E9BD63995238DC043EB294910077C4A840023FA8444EE4E39DE33098AC2E294A05411C44EAD7AD4B69F6A8B9F5F763B18676070CA5AF89540A725CD69D1B9B03B5A21AC9719535434A98AA52BF94BE1E3E10B32B49491078C2B844891BE169F998EE38388021245C39A6ADB3C74CC666585C160D454949570FEEA51C07A6AC0D7C1E3DB0FA3E3D9D329D17962BB79D754210F6608074750D4A095B0B48553D639C047178D452B1C690003E13071CB71EBC4E331F351256B51E2F9C970250351C94E1C3E9E71E4BF8BBDAD5CEC28C0E0A6148477826CD0AFF00ADC45D3F2BD022C1AE7531DE6D53AA2A6ADCA87AB1E0A6D4496140A6C89809B2A6C205EDF0117CECDE5AA011C49A06AB0A93ADAFD1C8E4F4F21284DC46314B9CA2B254EE5CD8FF0000B374D23D7253B5B5622980667688113F033EFF004C78E0CC67A927635FA822357ABF8C6AFE159A2FC558E29E1B23C6501039EC6FB5FF0063092945449DEA6DD2A5B9FAC3D41241E5AF2FE291B0656849016B29B192495F43D49C6841208767F7F785E5EBE1F785CC51A5B0A534845544151584A7BBF4E2DE77F59F5C22A965C104BEED41A59DABE118980167D5FED1CBD5F4AC8E17561A3B140492262F71D4F4E9B5C61CCA96B5800034F0A3EF6FC7842600028290DCBCC2848269CC9FEB93F0249DF9EDE677B893938659AA83026BCFA7DCFA40C0B3D48861ADCE12D9512B4003A293CBDFFAF2F5949382510004923EBE3A8AD1BC8C6CE588DEFE1115ACD56180425693C57FB43DFB19FBFADED898C2E5466B7125C8616B1BF8B75A38EB0E30E81A1BEF7BD6BAFBB3D6119AEBD534490B1239F17EA7FDEFD266B0D919268871FF00A7DF8EE75D9DF77CFD22019A7680E3BC27BD1E12A89501327E1E9CFEEC59F05D9B26AA96C0B386FB36D5FB6B0777CFD3F9881667DA2BEDF143FC37BC2A46D6B4FE9F218B1C8ECA099FB500D350DE1F814D2918E02FF7F7E1E7AB188357F69D52D903EB0428CCF8F7DFCE0CFE42062C380EC8238085201234E1B3DF9D7C0F331A9412086E5BF37A4466A3B53A8850EFCDC9895DC472DF7E973E589A95D9094A1FF4D9887A1623621ADA9B96A6B00429ACFAE9E2FEA4F588C661DAB55254909A832267C7681B400679C7EE43F4762D0A149628CEC923D5EBC853A42F2E5A941EAE7705E9AF4AF28655F6AF58524FD60DF9779B7AC91B9FDC9C3C47629240694073236E82BE5E5587694AC0DD46F6A372B7E00E708DCED76B1929E1A851E23FDD3B795EE4ED3CBDE70DB17D8D290C9941F9279DED51A96F4891C3C92B49D4B5697F77E4C5A1DA8BB6FAA640FE793B48E21C88DE7D7A479E20315D8A98A04F766D6E1B79529ADE94AD1996330A482403CC5CBEA473A5BAF3690B1ED06E32A4D3BAAEFDA7C8E2638A3BCE1823C60786373793B75C404EEC54D49E2EE94E2D43AF8066A306671A38786EE95296183925CEC5B5E6D5B7DE2CFD3DDB9E48E1698CCC269E956414D3059924EF2EA6151241B9B6D30311388EC8E2405AA5A4A2616E13C20B35689B568FD68627B058A992AAEE28E2BA1A31A1A369FE2E8CC72DD01DB3E93CC34BE7B47415B97D753F754B5AE1696FE50A5A49E26E65E59716A04C111104918A8636466BD9EC6C9C54954C4CC493DFC90E0625BF6D6825F00BB5DA3A9F65FB408929E098A6B1049763CF42093E25F9478ABDBDFD1F3DAAF65598667A83B3EA7735468AA95B8FA9D692842D968952C2528254F2A0950B09B6DB01D3BB1DF14254B9C893899865E210405495929035B9A59CF3A8A878BE8ED1616700998A09243F7AF5E4C91D408F36F3ACAB30C9730A8A7CC69AA696A92B297296A69DD616DA84820075292A122E403D27618F4A647F127013D2841C44B51200AA83027406AE39D6AD416890C2CF4E264A149140FF00EE38255D520BA4528F7E7A321AA29540B106F0608E7F1DBDC0F3838BBA332C2E6684F76B492B0E450DE86A37A781B8A3484AC22A790D507602E06CCC3CF581152553C46E37BCC721FBEA00368C4762E58C190A019CD2ACE3F8A7A9BC3A565EB9041524A5EDB10DD5AF5F0EADB03E39284F90B88E7FBF74618FEA945E8E0EC7CEAD5F6EF0770B735D9830A7AEB1A5D72786F3BDB6FC3F5C36993BFE5A5A967B79D2DCA306490E49B72FE79C69EF3CBE7FA6102B0BB69D75F01B465324AAC7D3F983BCF2F9FE98D90B2922AC3D9FAC68B41433977F7EFA41DE797CFF004C2BDEFF00DDE9FC4690779E5F3FD3077BFF0077A7F1041DE797CFF4C1DEFF00DDFF00B7F8820EF3CBE7FA61354EDFC2BF602364A789EACD0779E5F3FD31AF7C9F6FF88DBBBE7E9FCC6C439B88F9FEFEEFD4EF93B7D7F1EFE8777CFD3F98D9DE797CFF004C1DF27DBFE20EEF9FA7F31A1E74880047BFF7F77BF1BA5616682DD75DEDE1D3946C257158DB5D23477CAFDC7E584D6B147A0D2F58C19453737E5FCC1DF2BF71F961B4D582181A8F7D6DBFF9C777CFD3F983BE57EE3F2C342B0297DF97A467BA3CFF00F1FE63053E411336BDA3DDC87BF7F9DD25AC121D85FD9F7B987B87965AFA736E5ADECFA6C291BD1526264F283FAC18BDB96DD670EE5A81D6A40F41F6DA1ACF0CA524835A00DE1D7DD0DE1E32EAB090EA9C850013E76F416DB7999185E6CE4CB492685A8747E5E8C7C7A9232E1398F01351F5E54EA75B0DCB830EB398AFB9694942B69046E4C6FB72F4B1D84E2AB9866C25950E2B3EA69F5B830BCCC28C2A4A8A5D22E35D4BD3AB51A879C7AF1F46476448CBB506AAED873A60AE9F45B0C8A05BA8FE5BEACC987183DC2D4385CE051495168AB84DCF0918F2C7C5CCF138AC6617042710A9F32810496E1525DD999F623560E6392F6F730E14A422812E082DAB114D7D1AB1DC8ED0F3DA8CC01AA5A897C3D505D24C12DADD25B1E8106398F9E3A176170A0612495A43290928A6C056803BE963778E32B9C66CCBBD89AB35C6BA077F60C74B35CB08FAE665560F829928537D09524CDCF9CDA37F3C774CA25F1CB94959AA8B35ACD46B7BE7164C94913D079BF4ADAF5B1D9ED1E52FB4464FDFE7C3374B453F5D5A8A951013DCC004AA204EC27DD7225AF6B72A97230C6680012851240D838ADAD4D3C418F4B763330E094002FC3C20279F21CA9A56269EC6DECF755DB57692DE719BD3B8D688D34EB1519F5538DA836613DE52A5B240539C4E37C2AEECAB732236F36AF1789C4632749940A8A14A4F059DC900BEE967E64342DF123B649C932D01C0C4625244B5F13997C20713A6B705803F68F6FB5867B414D449A4D30DB6C65140CB3454397A385A6D80D212C38E0042412E1471EC08E66716DC932698A4A3BF509D36A56BE009245481A03C2081AF8C790B3BCED59A2D4A2A2788927E67A9F0346B68DBB88A7EBDFA948A6A075E2E97B8D5C615207F5904824089237D85F7C749CBB048C3CB0A609006C03F2E5E772358AB8C331E337B7315BF95A8FE74FA0166912C8492424889EA46DB7BBF1EB8F9E17600F100F4666EA7C5EF5F288500A8B0ADE8D7F1B53F8BC735110DF88CDE4498DCFF00BFC6C70BA1249568295677A7BD7A6B0F91FB46DAF99F7E3CE1BDCA869BB2943CC4EC3CF95F0E048E20DC26F7624BF4635E45AF4BC2D2F5F0FBC3555674C5288E3038A440316E460413F779E1EC8CB5534FED25ABE760CFA3F37B429107CDB52D3F8BF9824837B4CFC763F9E2730D92A8B320D69635E9A75EAF04416B75630DECE01320F8A36EB16F96DB6E062C586C8944370D9AC1BD9176822B7CEF5835E387881B59663DE27E079F4838B1617B3A5407FB64EBA8FC0D18736171522A9CE75F268882878A839C5278F6B7207CE2E2201F8DA32DECD93FD8C7667B6946D3C2EE758752120EC0EFE6FE240F467115A671DA72A15E3277FEAB917E9BDE79F2EA316AC1F66C3B775E36D6BA1FF3CA1D7766EF417A796BEFC62B2CDFB4B528A4059B49B28DE3AF98B1DBAFA0B7E03B3A97004B1B540E4581F7B883BBE7E9FCC40B31ED21609FE6AA6FCF96DB93B0F889B8E58B7617B372D828A45A800B026DF6A3F283BBD5EDCB7F1880E6BDA22D6A49E3322608519F7FC7D368B62C382ECECB485120076D07261EFCA1D4990662598902DB68EFD6D5B5DF588A54F682E03016444C9E237F74DEFE9CBAE25E5E4726AE0519E801D7EBF5BC3B4607899C585E94D2BCB93B1D285E2335FAFDC25242D5378854FE16F8F94C61F4ACA248E2F901B7BFB5A9CED0E118124B3160EC451FA5DDB5F1D5CC313DDA0BB1F6951E6B2239CF3E43EEE7B3E4E572831E00FD03F88F62BE6E9182A5BA51ECDA86EB4B6DAC256FB4170714AD5D6E6639DB7EBE97E507189995C851AA1236A8F1E5B5FF00C49613046A120B16D0D3C079DEBD6315F684B93C2A23A78B7882791F593D37C6BFE8586994084316D05CBF5FA91E10B4CCAD4BA10C3A16D8B57CC5DEED0A287B45524A8A89266DC47ADA0123E406D1CE70CB13D97C3AC1696914E87C75E5ABD9A239791A89A21C7420F236D1B6D46D49053F692E0825C36123C4444C6D1D3AF2F7C62BD8AECBC9493FED8A93A0B073BEFD234FF465A2E867DF939DBDF9C58DA1FB69CFF21CE69F30A3CC5C6F2F60CD7B4A76CE050F04052A41046C07AE39B76B3B12314852E54BA804D12FE4E29F810DE7E171185FFA61418559FC3E97F5DBD79F679EDE721ED4B4E2F2B5BB4EBAFA1427FCBD4703BDEF112A52781C0526C0C883B89F2F2C76BBB3188CA718BC4A50A12D45426F0F12598302E19DC81EA4BBC664637168042CA9C7ED279173E82A5FC6C6211ED05EC5FD8EF6F34B53A86A6869B27D62FB6E062B2999534961D424A01532C8432AE30126E39CDC9C55B29ED563F2E9B2A4714D0994AF91456A20825ECEF4A569B522F3907686761DD066B22614858531B17A136F4D2D1F3FBDBE7B16F69DD8B66B5B555197D4E6FA790E38B6736A740290D4920965A0B518102FE64ED8F55FC3EEDF2E709427CF73F2D0A80A0E4588B5DAFB4769C97B41829825FEC4B0058904F3E95DCEF7D7A8A288BEB7FBB2A6CD3102A4B80B6A76491C3C0B852784C8902FF7F72C56792B1F2E5F7530120025883B0D2FE4FD0459B1F8A938896832F84D3420B16E54BDB61CA836B596BEF254BA4506823ED490663A027D4C6E27E0C462D540FF00C5B9357CB66A444A4A6BC49E2F13F57A587AC25356DB84B1C10F3261D5DC8513B1DA3972DF0A8C4059E151A8F7A795F96B0290400480CAF6C418E7892398FBFEEC3842B436D3DF38D638E34FEFF7FBF8E09EAE1A055C69A8A751CAFBC2339C800549F4B17F4838D3D7E47F2C35756E7CCC36E156C63052A6209F3DC60E23B9F38D822EEE36A8FE63193D4FC4E073B9F331B700DCFA7E23893BCDFAE14429C313516AD5AFF98510002075BF898E64F53F138DE178D88544C920F52795B9E08233E3FF0057FEEFD70411A9C50312A077DCFA6364AB85E8EF046B91D47C4632A5B8666DF58C100D0C71C69EBF238653161CF0BB9B9FB0F7D231C097FB69F9F58389279FE1F7E1BA95C2D4778DA3153894F39BFEFD7EEF3C204804026A6D12B8295C52D4793F3D5AAFB6FE5025C4AA6F11D7A47FBF21E587D2940DCD2846BE1F6E4622B152DA6B58F139A795B7F1F1854CBCA553BECB07F9CE29A09DA7838877963D1336E97E8434CD279972CB280614DDF6D77F41B44FE57212521C3961CEFE96BF90DE2CAD11D9E56EB3D6BA7B4BE9569CAB733CA965B7D2D712BB94214D97CA8DF8470951B91B475C714ED3674B9054429E8B7AD281CF8916B78C42F69B132B05879B3967FE98A21DB89C5F9333B7F88FA71D1BA1F2EEC7BB2ED2DD9BE5DDD8464D445DAA7109E15D43B5A94542D2FA8789D2DB8A504F78A5445A0638263702ACFB30398CBE2577B31248539E012D4051D99DAA68EE5DE3CB9DA7CE5599E2169E30424B30346A016D19A95B13D280ED12B920BBC3037DADFB8E5F9E3D25D8BC29461A44B218A529141B51C7A73D0EB15A929E250043F3A8FE3AF5E74E9EEB4A9A9A961686CFF97593F58322641F04F337FDEF3DA3072132C21668CC40B6C4DBD0B3F8D22C980024A9045DEDD341A1DF5ADB9F5AB3EECC737ED773ACAF43E594AA76B5DA81F5D7D081C2DB0161C27880013FCA0660824CC620BB699949565D352A58480929248A82CD6A12E6836D869D3320ED18CBA6226B717082C97672CC5DDEDEB4A47A59A6F46699EC07B39A3D21A6BB953ED530FE24EB690971C7970E14B8BBA97C2A2A0029460898031C3723CA5588C54C9BDD90952DD2752E4FA1BB18E71F13B3D9D9BCD413314A751700BA458000025B4D2BE51535766C336A779E71C2D8E2528A42A2E144C5A01B827F738EAF80CAD322585283300EE0FDF6D869AC50B01835291C641552A1BC286A5CD6ADF688B5255E699857D0E539334E543F50E16D4B00A8A1054028F1198F099EBE9BE13CC7304619052080002545C0B57EFEC98DF1BFEC8370C0B1EA79EF1F44D599B06F8A1409B990403F01CBDC7A63C0F2704EDF2D3A1A7DF5BD3CED570160964B0B33B9D6EE6F5D0D623CFEA0201957853360A173EA7A749F81C49CACBF8BFB0BAA83A52A08FB3E95AC3A9648A58A7EEFEDE2119BEAA5B6550E0000330AF97BA44ED89595969424012DC9D83F37B86FA1BEA216439249E515C66DABDE723F9974F15F8C017FC081F941C59F28CA8A93C4B450B0A8634B796AC2FAB43897AD36FF001EFF00115D66BAA9CF12BBEB9FF501E5B4CE2E584CA40E1025D68CE9D5EDE15BB7A38522B7CE756BA8E187C5C13F6803378E7B9FBA05CED68CBF264A81E2410A1A33F859AD6E45B4822ABCF357BDE287A08B9F1CEFD2FF00BBF5BDBB059225212D2DC3683AD0FB7E71B702B6FA7BD62A9CE75629453C6ECFDAE63EE9B7BF7E569C5A72FC88DC4B6DA9CEA3EA2FB50438929A07A359E807F80DE25F578ACF39D5890170B060C9F1794DA0DA3AF2B62C786C9549209960100B16AF3EBF53AD1E1D3278801CDEB4B1D5F9457F5BAA42B7546FB99F5E73E5EE3CF13D83CA8A6BC35A0B0F7616D3D236128AB88814A01CBAD7CAB110CC352A49278FDD3B41161F1B462770F8166052DCF98661AD799D6D1B270D3174483D4317EB703EBADAD0FABD42924CAC9898FC7F193D3D6EF84B12EC9B5B407C7A537E91399760560FCE926C6FD5E8DF588ED4EA049264C0E809F95EC363E5EB8CFCC5E9C3E47EDB0F11B44E8C18FF00800598354B02FBB56F6EB0C5539EB64595224DCF53B6DFB163E8BCA510DCB51CEFF78729C0A890C9A0B8E5F4F426196A33C499124474371D2F3B1BF3FC70E78D2039142D473714FBDB9D2242565E6C12E59C6A1BD2DA1DBCA10AB3D42448541E927EFE7D7E1E9889CC3126590516AFBE836A6B68792302A4129281522A40617D06E7D884ABCFD06FC5D058FADBAFFB88383098E5310A074151D37D696894465E1403A59DF4E85DAAF4BF95291827512533E2DE2F226C67A72F8EFE5896FD5CB2E4ABC1DC96DFECFF00430F539525491F2D1F6E9A31F4DFC21C58D4C9060AC587F76FF1E436F7F9E186266CB268A07AD3DD8D1A8FCA345E512D4E38452C680FA5AAC34B9B80F0A1DD48B7CB6CB5545A2E1E2212AFB7C3732418100409DF60271B60B0586C64A9826F0BB7F7355DFE82953E1568565F6764E2524109046E2F76F5DDABB3B45E1D90F6D59AF65FAE74C674CD538DE5B515496AA9A4AC94A8712199589200054771CE4440C716EDF76330D8D973BBB48527866592E4163C24B6DBFE1A2BB99F65F825CE32D20AD0C50281F7A1342351A57768FA23D3FAEE8F50E52C67678174599D1D2B9421A70143CA0CA0BA12EA0C24A566E2649B6FB78D732ECC8C1CF5492C67485AFBF510C500A89438B971CA976D4728CD26E232F5A9402801448E86B5D1B5EB09F3BA4A0D4794D56599AD15366F4952853672D7D0D4A12A0413DFB8951E7C5BDEC0488C2580993707353370AB5226CB219692A2363F2DAC7D0F8B7C376DF1386F912B5914043B352CEEDA72D6D1E457B4D7B026579A22AB56F66B1455680FBF9A652CA09EE54428B612A5101CE2B93C22D231DCBB19DB1E2C47E9B315AA48584893314494CD61F35E8963E7E11DBFE1F76B55994B28C54E60867E321C397B93F6A18F1933ED3FA9346E775392EA262A68D54EE38D82E34B4F1C122764F9441FC31D7E4665865DA7A58B310417717BB01D2ED1D725E270B8948326625445569E214DB5AF3E66CD0C2BB2D4509841D9569579C1B89F3E989595325AFE64A817A82FD5CFDABADA14490A6E1ABBF266BDF6A3F3318952809260752001F18C48A1429C25C1201FF27AFE6374A16A0FC247DA39E251124C03B18DF69823A0336C693663060A7DC6EEFD5BA78D1A1B4F42812E0823F87FA3FBA16FEF3F03F9E1AF79CBD7F886D19A386F2E7C41FC4E0EF397AFF118248B07F168CFC1FDE3E1FAE0EF397AFF00118757FC7FF708E0C5A140CCFCB0ACB983E67F96D57EBF5F778712412412185697F17B681B9BED0614EF11FF00210EA30592220F5FC3005A4D8BC11871ABAFC87E58CF1A77F43F88235B8A55AFD790FCB194CC4837EB4351FC7DE0626C1E35F1ABAFC87E58D57352A71C4035BF1BE8C5E33C2AD8C1C6AEBF21F961B19A80402475766E55FBB46785550D7BD469071ABAFC87E586E66A058BF4FF00107028D924F484EFB91C337DE4C7E42DCE7D3E1ACBF98B8AB5CF33FE6F13B9620095338F67B59B938AB8F1BF5E1A58292A83C3C88048313E5FB8C3DC3AD0A04715B516D4D9FD4DB7DE131692A9C78773EA691CD3D6770F21C68F12B8836122EA5170F0080249B9B002FEEC577B418EC361A5AC4E9E94382CE41AED7A7589AC03C994A2B7400E5CD2EFE4C1EBF48F7A3E8E6F6776345699A8EDAF545377CBCD508569C66ADAE175954A997D496DC1C6012B064A40D88240BF99FB5D9B4BC662266130AB3314E4AD601646A2B6214C4339357BC719F8979E61D1226265CE495F0AC04822E6FAD68EDBDF471DECD635D54CCBEF39C6A7F89492140C22E52090792488BFA011675D8DC377C959989F9924740E59DB9D39EBBC799F2B9B37158A9EA98E47112092599F4DF537D183523A8DDA1E624878070126E52140F3F2248DE31D8F2859C36265A00F95C7CDA50694B8DF6F4B3484CB04592CFE049A5FED58EACE66E56E6598D3E5F4E14E3550B536F250389416AF0B648124788CC8F59C75D562F0E8C119A5680A12DDC903FB7AEFE3A43C54E4A40F983FAB83B0A57AD393476BBB3FD2947D96E987B31A869B5EB7CC9B0A69E570F1B6D90AE6652921856DCE23CB1C4738C5E2339C6224CB0A5E082D42600ED34834622A38540EB51084DCC57292784B91600DA8F7E7CEB7E462ACD4DABB8D150D3CF29FA97D64BFE22A83C44F224589D85A05B962FF009065089694AD6809A07040B01D03D1EBFE0454C4AF309892B06849AFF9F16D7A308AB4E64F543AD51D38528BEE04F0A012A32A8FB224989BDA7CF699EC7AB0F8794A485A41092087A58D05583EE49E82D137879587912C82B4A484EB4F4E7AFDEE3B71A0324CA7B39C85DD4D9C3487330A9642E8D2EC071B54113C06542E41F1016EA231C4BB478B998C98B9387515842889894870E5CA471015E6DCDF58A8E72A0E4CB75036367AD2951B1F0E71EA36659C3664717226EA36B409F3B728F80C79D70B8304FED776B8DB6AB0A3176A7A4457027D9B7BE6F107CCB3B4240FE6753BC7A73E53EEC58F099792DF2D000006A907EA6F190902C22B7CE73C412A973ACCA8C7BBAD86E39FA462CB85CBC10029034FEDBBF852E06BCF9662B7CD73B6FF00E6708BDF889B6FB6E4F945FE3369CBF2F649E14072DE7B6D7E5CBA64122D1566779F24154BA45CFF005284EFE7602FCA716FC1E0520A4140AB68C4B7416FE3785E2AACE73B4A88FE612255038CDA796FEF91E96DB170C065E9FF008245051ACDFE75FB42E00141158E739B83C443A7983E237F2EA4F5E5E9B62DF82C024B3A053560341EB6A783C390C34A569FE7D8D22B8CCB34E22005A8913FD47DFD63A927DD6C5A3078364FED1A5C0AEC341B523632F8806A1DF6AF8546B6B59E21398E668F102A207A93E47FDF9CDE263139230C90015005AE1AF571A3736B885A561D45882E353A9D0F97D1A2179866215C30AB09E7FBFBA0DC937C3F972E5D59228D6E4FF4899C3616CC1DFCC56C2F7BF880F678BD556A493E283CAE679F39E63D3A838708968AFCAECD7FC79FE22730F82040743125EBC98F2634B7DA2355B5A2D04F393227ADA39F2F59F5C131080C486BD757F7FCEB12F84C210E079816F5B753E42D1CAAAD4927C4444C5FCAC664721333CF081084A41201B87B52A3EECDAE9AC4A4BC3970C97DE82BF5D343AD7AB2B95A0920A8DB7827693EF883B911E778C375000B00DAEB57DE24E4E1C16743BEC2BF47DB7E621ADFAC499B9F333063CFE07CF7B73C36529CFD044949C20D45069F9FC56D48697AB120024DEFCC47BE08F3933C8F48C359C0177AB3372B7958F9F3112D86C1214DF2D587570D4E74E8FF00442E5724EE7AECAB7C41836F8C0DF0D432052A0BB301F514F7E4F0E0827467AFED3F47D377F268D06B5226E62FFD5D3ADBEE9FC7092A72C502BC341CBED00904101E96A066F0DF95631FAFA3FBA0F3F10FFB8619AA6AC9352DF5EBEF946E306B0EC0B1F3FA1F6F7731C8CC9C410A6CA890A489E29DCC6F262660C1F29BE1D499D3112661130A69A7FF00AB4E5BB7285E4C8293B2B6D4EAD7D6C29E178795E7EF32FD352125448E2124CA4C05483CAF04411E5388BC2AC4E4E204E50997FDC1C6BBB8BEBB6B18C6E0FBC94A253522A6DB8BEBAED6D35F7B3D853B48675CF616F69872A0AEBF43A9A04AD654F2BEBF54560152CF11802D72074DA3C87F16B048CBB3999899008566055DE84BB204A0424DDAA7616F5E19DB0CB9284CC1DD8643906D777D8EB4D43DC388EE73F53DD17521C238D2D917327853248827DF706200E58E7FD9A946609CA5FCC0115218D497FBB694B6B1C52661889A43317A0F1AE8CCCF7F5668462B5AA94BE92E250EBC9E14154149004282C2BC2AB75F4B5862CAA966594841E14A4BB815A9A310C7AB1357A6D3B976327E048EE96657135412051BD5998E9568E977B41FB33E8FED432FACA9551B0CEA1085A9AAC6DAEEC2DC8241212128E82E637DE3172CAB1B3414A16B570822BC44B5294EAD6148EA9D9BCEF1699A850C42810DC4E7881D0821EA2D7E54263C32ED47B1DD57D93E78E51E7D46F399754BAE8A2A94A49404B64CCF76088129E7BD84CE3A9E513E624242A605022F4A027ABF9B78D1FBC6579948C6C994A03BB9881F3077EF1D83F2D49FADE295A97EAC3C94A877F9783B240494FAC4AAC79CFE38B74B99C49705F7B78728B8E1A6CB5212A291C400047A3697BFB10B6A54A0D30524160825A47347F749DCC99DC635984D1CD4DC56BF6D3AFD90C7250B4860C79ED616F523D211779E5F3FD309C45F723979983BCF2F9FE9820EE472F330779E5F3FD3041DC8E5E660EF0F43F1FD3015F06F5E434EBD616932921DC0F5FADF783BCF2F9FE98C77C79F9085F813B7A9FCC6D6D60CCC8F98FF007C67BDE6DE03EC0C1C09DBD4FE636F1A7AFC8FE583BDFF00BBD3F883813B7A9FCC705606D7F97E18D173096657A7F1070276F5309DC5EF3D2E768F86FF00BDF6C20B5AC10CA6E97F1FB78C1C09DBD4FE6908DC73602FD3F7CBD39DCE1098B5503B3BBB787BFA343E4A10003C21EF563EF96B1A7BCF4DFAFCBD7F71867DE2FF00E461544B4D5C3F5F18C915612B4B0A00A5E07895BF08489B1DC7388F2EA313D96AD3DC4E2B2EC9BF817EBAF421A821C7767BA584001F9B6FCE8E5BCABCD653D638D52D496480C01146540492490F44DC93CA7D4621F058D299D89055F213F292435C92D7F5D7AC43BCA973E519A38A73FF00BA384B00FF002B814A0A3B51E3B8DEC2FECA99AFB41F699475F9952BAC68FC96A13575EFB895772BEEC77E80788A64171B22C48B99118E09F16331C415BCA9EA425D99277236BF4FF10876B73C9383CB664B90532D66529D8D5DAE37F5BB347D2566ACE459464747439486D8A2D3B4EDD232C3490DB4A84A5824348E149BA249E1266E2F3344ECDCB993CB4E05666A5C2D42CC28F7771D4D58E823C2FDA2CCF158DCCA6056215313DE2800E5AA4EE49F7B33F5DF54E6EB8AC696A5292903EA4493BA812E45CEC771CA04473EABD97C0F77317F2808243B01536FAD35DE25B0525326425412028A4540BBDDD869E1CEAF1D4BD4AA79CAD577854E3AEAF8384289B1302C081CC63A2CB97C3502BEA1ECDAD7946B3A62D36253F97DF5BDAD6BC4FF0046E87C974851D46AECDD095D654252BA143838B8080428F0F885ED123716DC6196267E2B153C60A54C5140FF00ACC4D033A40635714A7A43513660209516FEDBD77E5E3466F3AFB5BEBDABAAAB5B8AAA4F0BD2869A04029481C205B6111B798E47172C97279328213DD5989E20EFABD5CDFC9CC399438CBABE635777018FF9B7E628DA8CD5FA6A9A879F052144428F8F88AB6481B9E298117BCDB9DA31F3118390C964324D2CE4793EDE35AB449A0A254B53258B3123EA29A79DB578EC5F62FA169DA655DA1EA767B9A0482ACAA89E07894E5D1C7C2405D9CE1500A4911B5B1C6B3CCD2762710BC2C89C5D4A214A497084ED7209507E8F6D62B3996216569E0511C2EE428B2AA34D18D2C1C72BA5ED4B582AB2A4B752F0352DF185F01E068B51FC901B443638500030395E0EF25906070E129946582054F11E2249A92497275678DF2C96AC4CC1DEFCCEC2D7DA9A7BAB47A7398E70F193736EBBF9C733EA71C070F80424B82E36236A353EACF488A880E6F9CB8024827C455CEC4FEB6FC37B59705824A883D2B60343D6C7AF8411586759D3A4AE144EF107D79DBAFCB16591854A00702D717DB4E9FE5E8456B9A674F447113B9224FDFF00B988E718B3E57864872A0030F1F3DF716A1DA08ABF3CCED7E205666F249BC91B7975361E87168C2E141F9A805399B8F5FC5E1C0B0D22B4AFCDDC528CA8AB7BFCBA1E7BC7C3171CBF0A1D23CDC374EA36FB5E1C457B9CE6AE78BC44133CF9413E9713B47A8BE2E183C325213C4028D6835DFC052DA6F0E694F567AF2AFD6D5B30AC0AAF3270932A3B9B5F793E5B5C6DCBAEE6691204A161A786DF6AECDCE24B0B28299D2C28EE5F99DEFF00E221D99662ABC1379FDFEF97BB0BA789C7FC6AF67D1BE8DB8D1844E61F0A82E05D2CE5ACFB575B797488ABB5CB502788DBD4F9003CAFD473F52E258357B166F5FBBFA44E61B0813C2281CD9BD7F00F8F363AAAC549B9136206DF21E7D37E4230E25EBE1F789B918349BD5FDEFCBEBBD63B5B58A004DF7D89E73F8FBAFB6E71ACE7E17D1EBE9F8898C3E112970430A5BC1B9F2209D22355758A13722D37BF5F311BDFD6D866B24853F2AEFF008689195844BBD850F9FE34DACED76572B172649E7FED37EB1CAD6EB86EB511E3AD0337F1D22570F84492C19C5E9BF93D18E8DF46B7AAD706E4F99BFEEE778DE2791C332A7B519EAFEED5F331232B09562001FDC47E2A3D37F16A76B166209833FEFEF9E7C8FA0084F3ADDE9D29E147B5BAD624B0F87482DD34D6A7ECC2D4840BAC50E7E637FBF7FDDB0CD4585013BEDFC7AFD8B93246C0F8FE77FF00309CD5B9D499EBFBBE1B295C2D4778D3B87A801B4A0E9BC71F5959DC7C0C7E1FBDEF11868A5851F95C0AEA7A7DA36EE696F17FE5A394E6A9A675A6D6990E104C9FED20F4EBEFEB6B1CA56384D6A4100877F3B4389785E22549B25B89CEE5A9E76630B9FCF1B72AEAAA026F4C1A4A4F4E301260F381F08C3196BEED6B06EA2C696B8F56FE443D9B81FF00648201E204A74A01E8F53FC523D2BFA35BB42A9A3ED79DD089528D26B3656E38893C3396D2B8F24F0DFF00A86F1EFDB1E68F8D5FED6265B31EF2CCDA33B120DF61B3B35B91F6DB2CE3C0CB9894022571F78453767A024F87D80F65AA3345BC8A9784FF0025F2D4F203BC2D816E97001F2BE39B766E58972C922843B7A9DFABBD19E9531E75C5E1409CB61AB721EC6C776A421CD1EA7A65B2CD538A692B0141692641226D11249B7A62D2A962600B48D6A0D486A539D397DE22F184482962ED6E56A6B7BD296686CCCF35A814BF5653519790422B090547CF8638F7B46D3D4E24F0321226898872B49A2743B3E9D4B1D0522C790E3A624A4034357B7997B5AA0F8C50FDA2F679A635E64EF506A0A269E67BB7050D52920AC29625644026CA20448C5D7018B9D2672552C711769D29C86164D5E828FB73D23B6F67F305B25894B70B58B9E7F4FB3B478BDDB876059AF66B9B55D6E5090F644E38B500784008DC40512AE768131E713D0B0B39D20A4B12016726BB5437D368EA981C72D68055FB8332874D68E695AFDC47565F0E25454567854480DFF6116313D4CED874B2EC742EDE7FE2260CC33D22E08A13BFAF43FCC2793D4FC4E348D7BBE7E9FCC127A9F89C10777CFD3F9824F53F13820EEF9FA7F31CF12873FC7EFC11B253C2F577F7BC1C6AEBF21F9608DA3636A55EFD3A79E0823671ABAFC87E58208E0ACC1936E76FC8608212AD66E67D07EFCBF7CB092EE3A7BF6FFC9089D5ED373CC7B87945B084CD3C7ED0F93FB4468EF0F41FA7EF9FCB0CE1697AF87DE32EF9A292D287F39653DD1BEC3EDFA0E107F330061EC99A65C998016241A72A8FE3A9E6625B0D2C2A5AA81D85478B136D5A96FB5BBD8FF65B9C76D1AFF21D01A7C91F5EAA6C344708E26D252E544F14720A1731EF99A066B982B0489F3662F825A41516E4F76E61ACCE763152CDF1A8CB7BC9C5026CD5823859B85835D8D4695B8BD23EA3BB30ECA329F679D0995E89D354CD53E6E9A563F8F54A10038A52909704AA24C82B1E156C6D36C70ECDB1CBED04F5E317F3617888C356DC2785742C4B91AF3F0F35F6DFB5335026C9E3539E20456C5DBC0023C2ECC2346AFCD29DC5B6DE5CB3F554A54AABB93C4B899337FB5C5E5E800C5A3B35844210AF943900696736AD1ABE768E13865FEB71A56AD5679EFAFAEF4B168EBBEAFCECB74E16A324F1269CED24920CEFCF99EB8EAB91E1021D40073566F3FB8BDE3A409625E1D054588143BBB303D2E5AE2C6231A474F36E29FCFB3B4F1B490A71B045844C6DE839183169C486366AD2A1270DFF0055640E96777BB8B546B1173C025459C01FB7C3466A8FB08AC35EF69CA0FD665A904D123C14C018080278AC049B89369BF3C59727CA6505214AACD5B152CBD48D2BCE97AB54E911FF0032A610372E0B7E69C9C9D7668EB56679C3150B5666FD4AF89B51286A1504A8909E703CCC6F36C741C3E01329085B86E9771B796AF1278595354A1292975173C2E03B03F40C6CE79C5F9D88F6655FAFAA9DD5FA9804E89CA54D3956490429464538213FCC82F2520900FB86397FC46CF93972A4E0A59271789E21264DB88062B3C4681857573477A95F1330A2539D010B5731403F9E51716BCD5AE53D4AE9A8DB0CE5D4AD7759751A2020B696F84ACC40160177124C9DE71CEB08927854A24CC51F994CC5CD5BC2D7D3668A8E2141732D47A5F91B73B56DE71D1BD55AADEA9CC2B180F29D430A90E99F171924A6F061311E62F18BE64E966A1040AF31E5E0E6D5A6F7EECF6010532A610FC676B358D29F4B47CB3E3F3111F6BE0C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C104182083041060820C1041820830411FFD9, '1', '2021-10-06 01:15:47', '1', '2021-10-06 01:15:47', b'0', 0); +INSERT INTO `infra_file` VALUES ('add5ec1891a7d97d2cc1d60847e16294.jpg', NULL, 0xFFD8FFE000104A46494600010101006400640000FFDB00840006040506050406060506070706080A100A0A09090A140E0F0C1017141818171416161A1D251F1A1B231C1616202C20232627292A29191F2D302D283025282928010707070A080A130A0A13281A161A2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828FFC200110800EC00EC03012200021101031101FFC4001C0001000105010100000000000000000000000701020405060308FFDA0008010100000000FA14000707A3E3F659B5F2B3CB1B171B57BAFA2C000BE1ED8731AFC752DF3F2F2EF249DF79D0000A465CD59E5ACA5BE7B09BB71441BBB943DC0017447C95DB0D662E4FD0192237F3E17E8600039B8AF556E579647D0B60807A3DA49368003D7E7AC1A5B678CA3255081A4AEBC0007AFCF5834C6E8BA3DDF756902CE39200034908796C661E82C04073E003D755A4B2FC9F48A34CFA172404152C6F415C4E175B9BB879F8EAB41CEF792A807CF1B1903B7BADA5DC0737D47ADCB3CFCBCE3FD2CCBDB807CE35CAF5E8B3F0757D0FBF1BE7DD655B65965BF384B9397B80F9C6A2EDAF577F05A0F3D9499958BACF4E7F41D0654E168118657B59A8E2E43DD71B31FC73ED26EE33FB0E939E8FB135FEFBA9528007159783CAD981B8C5DDC9596A5231D6E17173476200BE26D8351AFCEB33FBED077DABE2FCFB6DB59CE463365A018B156E4A3CB7DDBC65CDE3EDF71259C945B3D7900725CFFB554C0EA3B769E32BEC92F794A4711EEE3BDEBAC0380C657CB7FD6E50F3D4E266EE0C2E2F9DE73CA6FD90237B7CB7FDB5F554B6911C8BB8A948CB039CE5E79E94230B3B6E98A82945453C225BB87D44E3DA158BB77DF56A00A1452DE6A2DB397D6FD5C562696B215002DAE1E4D29CCF8471C9DBF4E9EB03CF952A028A539DE8296E1C7DD3C2DABFA80BA3690760A5C28514A626A37F4A523DC2D7E9A772B1CC9B7733B2DA2828A2DB628EAFABA523DD1D29302BC6767EE88E46DB1414A29486A1A9CF8E99E2BD91303CF98ECE8897A9EC5428A294A70B04E5E279751D613038FECBD5485BA5911428A514530780D5E9B7B62930B93ED2D6A222EA64A28A514514ADB444FE56D7FFC4001B01000105010100000000000000000000000001020304050607FFDA0008010210000000F3600075E70AD558EA46005B9DCE33E1B7367000694AC32CD3CC00034E58A1A69A59A125A512766681ACD81C9A194D4F44E2B280D94750E8BD1383E7AE6F60E4D500BB0F4BB3CCEBAC540E7500BD5CB7D135B33E0E769342FA6DDE51AAADE56CD084D7DE780014F9CBF8EFEA2E800346D4CDC87F57654104628C38ED9DE6B841064EB5978DEAAEB155104115A7FFC4001A010002030101000000000000000000000000040102030506FFDA0008010310000000EB00043FBC939A35CE4003A76164A7AFC9800061CB22B8CAC0006EDA78C4B0B845F5B8C23981D3533A3CA742D7F0DDCD006A346783E07D9FA05BCFF7A92016EAF9EE0FABE6CE8DD4901AE84ADC1E8F5BCDE0CEC483FA72520BD62DE8D54E46B8F500019F429A318AC001259BEAF3215C8009BC1B5F4C55D2B5924B9560D55CB5AD2490B4EB3FFFC400451000010302020604090A050403010000000102030400110512061321314151203261711014222330425281D11524333440537291A1B116436292C16382E1F0357383A2FFDA0008010100013F01F4FC6B4931051908C2222ACB706690B1EAA397BE9E719811335B2B68D800AF9C4D735CB6D6A56E48036229BC3DF575B223BCDE861A84ED71E3F95AB53091D672FF00EEA270F1EA66FCE8C8863AB187F68A335A1D58C8FD2953F932DD2A628FF2DAFEDA3249FE5B5FD94F2D9BF94D3415FD236D4518C6ABE66D627A9E194AADF6047585622C3B866352E54C49533297E43C3684F61E54E105ACC946B788038D09B2E495063220A77802EAFD696EBF721C79DBF2BDABBC93DFD0346AF750424152D5B9291727DD587E8ACA9090B9EE888DFDDA76AFE02B0FC270FC3BEAB1939FEF17E52BF3AD62A9195C405B4B4B883B8A4DFEC0B4A1D694D3C80B6D42C526B12C39583FCE226672028F96DEF2DF68ECAC4594AB24A64EC3B7327876D22521D4E5988CDFEA246DA7A294A758C9D635CC784D1AC330F918A492D46B04A7E91D3B91F13D9585619170A6B2C74E678F59E575954493BFC3F25BB11CD6E1129C8CBF66FE49A8BA55221B89631D8BB0EC0F37C6A2BEC4C643B0DD4BAD9E47D38B1052B014856C20D488BF26622B84ADB11F1999278734D3CD969D520F034CBCB65576D56A25895BECCBDCFD534F34B65595C16FF346A0C473109CDC465594A815297ECA79D448CCC18A88D15395B4FEA799E88A75B43AD943A90B41DE0D3C1FD1F9499905CB344D8A4EEEEA0A0E34DB805B3A42BD3E92C432F075A9B1E7E3F9D47BAA7283A961F4FF00311E14485253915671BF655FE3952D0082B64E64F11C53DF583CD187630C495FD09F34E7603C6962C766E3D1462130904EA7F0E534EBB20A9A8F159D74B705F28DC91CCD46D185BEE25EC6A46B2DB7528DD4A3BAC2C06C03D3B7B4E53B8EC34B4EA98531F72FAD1E1357208209046E229C3981CC37EF238FBAB43315D73670D92BBBAD8BB2A3EB2797BBA3872017F32BAA819AB4559221393DC1E7652AE3B10370FB0B5D7152961C7A42C6E72438A1DD7B785C7128EB1DBC071350B02C5268CC969319BF69EDE7DD4DE8728FD63123DCDA2B0DD178906735284A7DC5B66E01B513737E824EAF0A98E0DE465FFBF9D436F5387C4680B656923F4FB0E3738C083E6B6CA7CEAD94F6F3F752C25166D06E940CA0F3EDF061B02462920B516C9423E91E56E4F6769AC2F0785860BB2DEB1FE2F39B5468A89DFD37ADF213DF8BFC8A1B59688DD907A20835227C18BF5898CA7B335E97A478524D92EBAE7E06C9AFE228C7A90A72FF00F9D0C7D9E302701FFAFF00E6938EE1C4F9C53CCF6BAD102A563586C58FAE3290E83D54B67328FBAA6CE7A64A54A90323A5391B6FEE91F13E04A1C79C6D9605DD7559103B6A2456A0446E2C74D9081B7B4F3F43193AF852637150B8AD1E942760CC281BB8D8D5AC768E9EFA992A3416F3CC7D0D0E00EF34EE9148977460F12C3EF9EDD4A87325FF00E47107560FA8DEC151F0B84C7518413CD5B68009EA803BA8D1A34F448EEAB32DA467F680B1FCEA4E1EA4254A64A9CE394EFF00CE92A0ADDDC472AD098E97A5CA9AB17D479A6FBCEF3E899714D38168DE2A338E33255270D7FC5DF59BADA5F51CA87A48CA9496B1465511FF006BD4FCE9BCAEA02D95A5C41E2937ACA7978522FDD5896901538A8B82A75AE8EB3C7AA9A630B0A735F3DC5497CEF2ADD49B0161B055EAF57A2689A346A7E30F78C29A8694D926C5445EF4EC85BEE053A84B723DB1D55F61F8D684048C04A13F4A1D59713C526FC7DDE910FAC2321F2DBF655B4530A61B5E646BE3AB9B2E5A9B9F3B66A31726DC1D40AF95B1C693B04391EEB1A5693632D9F3986B67B81A7B1BC5719CD0C3488ADFF3549BEEE550E3B71590DB42C07EB4FBEDC76CB8F2825239D3FA43B7E6D1CA87359B531A4842AD263651CD06A3496A4B41C616149357ABD5E8D71AC230886BD1790EBA91AE5A5C257C516BD4194BF18650B480D1010A17BDCF3A8921FC2DC131ABAB56723E8FBC4703DF51A435362B72A32B332E0B8F4C1453D524771A87AE7DD09D6B9946D3B69B425B4E540B0A52821254A3648173498F37185AA42595AA3A4F93C8549929662BEEB2DA17A95645051B1BD61AFB38A5D011AB780BE5E75143D86C82E37D5F593ED0A8B25B94C875955D06AF4FBEDB29CCF3894279A8D7CA71782D44730DAAD45F4C98EE884F20B994E5B1DC6B0275E6D9721C8D6A2DD64AB7281A7F4714257993E689BDEFBAA4C96A2CA4B6F1F36F2721ECEDAD1F9FF22622B8EF9F993EADBFD0AE7DD446E236A4EE3E813A1E7F9B89AFFDA9A4E8743DBAD99257EFB57F0861BF7D27FBA95A1F879EA48909F7D3FA21251730A685F24AC5AA6C79B86AAD3D8213EDA77560907E6F9DCD855B4FC29C8A35B649B0B5EB1D516F0C91CFABFAD600DB4CE09112DDB206C7FCD692869CD209EB67E8CBA77568FB4E7CA91CB69E3B7BAB1646469C58DA40D82B0D8A21450D5EEAEB28F6D3697E63C598405D3F48EABAADFC4F6541C1A24539D49D7C8E2EBBB4FBB97827E0F0A68BADA0DBBC1D6FC950AC423488032CE0A7A2DFC99281B53F8870EFAF9D048CA10F208D8A0ACA4D3985096A0E4C514AF8250760158AC44B91EE91D5163DD5A218C2B38C3272AE7F92BE7D94458FA4D2D7C96A261C9EB495E65F6213B6A23EDA59B28D88A724A8BAA523603B2B1B19B0C7EE6DB2FF00AD6172DF430194B8AD572A95804790F1790ACAA3BC54382C4004A7CA739D7D6E50B6D69A55D479AB9504392A408B1CD96A175AFEED3CFBF95458EDC5610CB09CADA770E8101408201076106BE4A5AF5AF610E06D21C524B0EED4120F03C29D5CA8DF5D82FB607AEDF9C4FE95F29C4E2EE5FC4922B15318A82E3C8403BD3955B8D68962C716C36CF2AF299D8AED1CFD1A05D429D77C771D9926F76DAF30DFBB7F87158AA99096CA1412A36DF50E0C88EC84A9E43847022DFAD66929D81827B42C56A243E7CFA836DF241BA8FBE965319901A6EFEAA109F589DC2B0F8660425EE724AAEB591EB2B977560788B8E4F991E5150505272E6EEF04B9CC450758BF2BD91BE9CD296028846AFF00326938FC89CBD461CC05BCA1D6DB64F693585C4F1282DB19B3A86D52B9A8ED27C0A48575803DE2B178EC2602C865B06E3720560EB30B4B5ACBB1124588A56C51F4531EF168129FE2DB648EFAC211920357DEBF2CFBFA4EB8865B52DD504A06F26B0684B71D4CD94828007996D5BC7F51EDF0694C53E3D16446506DE5052566DB176B581AF18C4BAB9503B75A6D5E28EBC6F31DCC9FBB46C1EFA4B6848B252903BAB01467C656B4F55A672ABBC9D9FB7431F72CDB4D73398D48F271BC29437EB2DFA8A77AE7D1697B9ABD1E75237BAA08A69391B4279003A3E3216EEA6321521EF61BDB6EF3C2B0DC1D7AE4C9C4B22DC4ED6D94ED4B7DBDA7C38AC3F1D8A50956475273215C8FC29D73C5DCD5CB4961CE4BDC7B8F1AD6200B95A2DCEF4D2D7255921365F5F31D51DE6B08802045C8559DD51CCE2FDA3D0C614A54F702BD5D83BAB16D6F8E40547FA54AC94F7D31A4B8CC43F3D8A1F6C6F396C7F31585E9161D889080B2C3E7D473E34A491DDE834CCDD186B1EDBD7E83257254530DB2F91BC8D891DEAA6B020ED8CF794E7FA4DF928F89A8EC351DB0DB0DA1B40F5522DD15A12E272B894A93C942E2BE4A819F3F8947CDCF2548C4998A754CB79B2F04EC02B0F9C8999C25252A45B37BFA12633525367537E4788A9FA3C1E19DA78EB1BBA9A047ADC298703CD058D97DE391E22B11C2DB76EB69365F2158563B3B082942FE710C6F4AB78EEAC33108B8AC7D7435DFDA41DE9E9E949CD8E618DFB282AB781D73265012A5AD46C94245CA8F6544C194F0CF89916E11D0760FC478FED484A5080942425237002C07A03B8D390714724A9866304241B78C38AF27BC0E3585406F0F881A412B513996E1DEB573E963917C46619681F357CD9DFE85FB5DC68D6251B617503F10A61C7F0F9224C0564706F1C0D6038DC7C659B27CDCA48F2DB3FB8ECE96909CDA551C704B17FDE9E73568D892B59395284EF51E558461BE2BE7E45973163CA57040F653FF0076FD89E6D0F34B6DD48536B16524F115219561B24457AFA93B1874FAC3D93DB46A5B3A978A7D5DE2BCE30FA64C45143E837045617A510254342E63896246E5A4F3ECE871AC636E972FFA628FDEB47E3090F2A7AF6A5376D81FBABFC7D931D85F2843530DB812F6F483B95DE3FCD403250B5C793B54DEC39B62D3D879F7D62A9F36857236F03B192B5E6B91D01BEB1F51563D2D2D6C756866324F6AAFF1A8ECA23B0DB2D0B21B4848FB03EFA59C80DCAD672A1237A8F431E694A845F66FAE8FE705B88E229C8AC6330997C9C8FDBC9751BD3F11D958C3722235AB9A80368CAEA7A8BF81ECE937D7AC3E5993A62DBE47997242F2F7E5B0FB0E1C7C664489AADC545A67B1037FE67A12D84C98EB6944A42B883623B6B47642E015E1F33638855BE07B8D62AB4BF065B4B48394849078D4A82B601531771AF638A7BB9D254142E9DA3A093635A4C9660CEC15D650869297944D85870BD4394DCC6CB8C056AAF64AC8B05768ECF4F2DCD54579C1BD0852BF4AC0148560B0CB7BB563F3E3D1D286836F44969EB156A17DA0EEFD69C92A5EB2FEBA520F78F03F874779C2B505051DF9556E86C00A9442509DA49E1410349E787568B6131890DF02F2B9F750000000B01E0C6F11F1169B4A7E95D5048ECEDAC35F5488895B9D6DA0FA4202810ADA0EC35A3B3061932561524D834B3AB27D9E0698D21C35F9DE2AD48BBB7CA0DBC951E40F434CDDB4161A1D653A93D2DE6B1B5AF11949C1A2A8A507CA94E0E09F6477D30CB71D9432CA421B40CA948E1E1D28CCAC563A6FB3589FDAF58565F106B29BECDBDFE974FE225296662363AA56AC914127665D878562DA4AE468AD371D00CB50DAB56D48EDA81A5188C792954B73C618BF969290081D94FE2D15A4660E67BEEB7C6B1A7D53A6C7521C4E6CF982378B749D7931A3BD217D56D2555A2ED2BC4972DEFA696B2E13D9C3A1A48ABCC2AF61D47C2B00776BAD1FC43D2E99435CBC1EED0BAD956B2DD9C6A1B49912DA6F7A6F750ECA95152C4D534D9590948B85F0A71BF20D3816E93AE56729397B36568FA72B4FEC1B17BFDDD2D2E51F929A8E8DF25E4B74CB619690DA3AA80123C24D85CEE158A2F5ADBCBE6ACDFF00EAB0755B104F6823D32224742CAD11D94ACF108158E600FC99CB950D6DDDCB67439B368E37A8BA332B5A15296C8037041BFBEBF86B1242F54DA1A5206E74AF7FBABC45386B288F9B3BBD65ABB4F4B1FDB3B0349DC645FA18B2CA2039978ECAC4C5E0BBB48D97D9583FD7D9FF00BC3EC4EAD4E3AA5ACDD4A37E87FFC40029100100010303030402030101000000000001110021314151611071812091A1B130C1D1E1F0F140FFDA0008010100013F10FCE0B032D36BD74B69C8F6137A56A00C92E87777A82C152709D05827769D2D7B9F63F9A46C9B00FBB58E2CDE53EC547DD0BE1FDB41C2099E4F34E5A46241F4524D856723E655FC52A491A36144F10CD40C4961A5C0BFF8103389AB0DE8E169ED3DA981205B99E90B6F348CE90978FE14B61C15F4914ABF205FBE8D3D0A94B3D0E3F81769770BD97397E02682183E43CB1E2294727B5459448C1F25223088FE782179644A756382AA57C9FE734AE1D0F0A701E6841A16200E50FD7B5470BDCBE9DFD05429E19C96DC9A7BA2ACC52D45BBE8705A90953D65F35AD3FEB99A590583939461F10F15A997264EE64F3F9E17411A4473255DDB9BE3538D3C6F578EB43B9A352612C991EE56128D1979DAA72568E4EC7A0FF3C04C5986AE87347DCF7BCBAC9AAEAFA548290C636AC7B65C8D3BACB3232B35930F151AC466D20FEFF3CC91C50966E4F24FB563C096344FFBF1D1A6C29CB58E56553F01BAFC6DB92D589215DF9F161A0910DE1309E91A4CDA29F33334A674442CB680DA8854C0743C2EDBC7BD0282100D0FCE0719341D4A99198FBCDA64FBA69E8D4598425190EC4041DDA3C5B82951A60E51DDAA3E3B52228E4F427CED4F18FF0071508A74B9647DCD673FF804D4A38B5059803F0D34D47E461BF60AD946AA06E1BD452466E708EEBFAAB2938A163582A6777A1B4417B4508404404130FF00C248277E82EF8177C57B207167C957A5BF1A24CFA0F83DE8309CD60E1D0E0A6EEF1EB825B909A199214F63F0E714B2520DDA2A51BE056E096A589D2F5DAD52A33D0919F769379F44C1EF4895CE0F71A1286E36727605FDE2A69EC7647BB3F36C7484A6721AF6095ED45888919D64EAADFF0009631BDD8FE42B946162DDFC47AC15012D0471C8F60CBE29652EC840344313C2BDAA752C85BC7FE2A0133A73F9A3E01C400FAA4EEFBD2A6A65A33146488BB82F4E5E9BB25DB53DE895948C8215B268D0F0109B429EF441E5A5555CBF85500DEC3C539B9C696FD37699342E895CEC3DCE6A18E24207DA93D5489913A5DE017574A0FEA8371DB47BE3BD33BB64287CE7EB8A02103004051428F502ABA8AEEEBD8331B14A11200C06CEFB7BA928269B796034B0FC8B944B27FF000F15DE8A43C9AD4025299D5E162529513F4BBBD642AC6592CDB6B71A6A54C1026E2FD19AD4FE9D56EF35A945965D8DDA621FED4050052E66C78735ACD18C8EC9A3D0D1A2A1B3BD4F34B5BCA10E9114E98389E470D4FF00E47B1F402D3C157ADC184DC4D11B27E1289EBDE9A95790A51C2F23B1B79A020917BAE5776A73848E819A57822058E3777A12C6DA4081E68776F0320E1A9FA41C6193BECD61BD6E422644D1A69C1E605290A6D53DD14EC582B905A4C9521224524A4A6F522922B4B3B54EE99E4108D4C94B898ECD23C8CFF544090121713F036F227061F745B95C4087DD76EDA1FC5679B4929F45446DA8786A51E4BC5E51984B7EF8A8C0B0846F3A781F3489EBB4DE198A24320B3903483C8D4C2A4A7CCD00A4B060A597DE69CE00BDD97A839230195B07BA5199B32B5613E2D1531C9029E2FD2F31449AC5B8EF06C780A2C416363151862F7BB7933D9A8BE618658C8659D948A121381A28DBD9A3492C7BB254BBC94292C0466187B944DCA59CBFE7DA9A24FC6498A56248B9542F760F7A04762C3ACBA525502026850E3C127540D1A046D2B454B42CA124F6A72E4227A1C5044809A72C1ECDDF053088498961EF606AF050512C64795755CAEAFA0CB140488E89519BAED8014AE5DB0516E50404E66EA9146859863DCA9B889A276AD83EA92922BEBA4BDA1FEFF1C1A9B1F9B6190EEFDF54A42870B38AB1438400D8FE454E3B10FF009A619765E0DAC03C5EA43892D4AA039573DDAB53A1BA0B0E1603F9ACD1C4C659243819B76A8767DAA22904D9477D03BD04082D2C5F21158C6E001E16580F35255E63C4C7DC3429853B50503EC0FDD36AD1A0667B50146DEACA90E39068C0E7F143BF432DF3152AC253754FA8CA2CAA029E88A344D93D1160C837BBD0AE5E121981C4B0E4A5489372FB2682C64C80ABCB2D1328C00A7B21306CD1EC9A8EA60376EC163E569366ABDE4FE684245BF12BC8C9E32CFEAA0500B670450FA1405C987F403BD4CF6F28F7AFBF834EB02C03C9074791669747BC1CD8C5A934A7A8C5065C622F3E1838A8357E2C4BB1B183D02C2003EC99F32D12B97A62200EB6D2B548D8B7163DCADBD6912F183F15756FB8FC196AC3F11FCD4CAF49A52B50B97C96F04B436BFA8F698F913B560E6C31FDFA1A6AD7922786818BB16A38A686076D63E8AC2D08B30CA09EC4F9A9A7A427A30DBB0D1B85CC0C6C5DA684C5487C95939192811733667B73C52E6B2309E593B62AF84360DB27EF1587D473B2270C3367E28A13D80DA61FBC1AD1449DD2ED0DDF047750AEB8181B018EB1D5E854861441DA94CA50A46CAEAB513914657E8D0F531347030F63D80F3DE8503721835E7F9A70B66248EA27EA99413CACFD9F4A4461B3E832536A2B57F4A8242424AF03BFC6684A9180FE006EE5758F5C7E078E92244C952415959E636E392F4444491B2351565ECD31F559963FDE6823CB5310D61A3E830A3321D4BA4FF4AB81AD22063BEA2381DFF2BE99A5A88064DF8934DB21BEF460EA448D0346C1868D8B794F09FD534A825C81AFA04939A2ED9229CC98E0978A80023E023FBE87E6C7179CC09B6C05D5B06685426CEA4D34B57E252E63F717EE14980B7EB539375AF53A83177B1BF23C539F4991382F4C8109B710E07708F7A3F24F468BB065A6BC089D4C23915EC14B4BD09FCC0E497026CC51B17AB362717045F4A0BA5FB81446803032E45CB4719A26D2613D17789DCA38AC640334FB538887699CCB7744DA7D735353D66A7A26084F09FD531AADD9CC899795A9E93D0F68921BA65DBED404EAF3B86FF153577EECA2BBC1AFA08B60AD002EAB57153A1D4B7060B7EDB1320400401B1D00ACA5ED58A4175E8081873E89A9A9A9E934B53445424371CD397D2CD97B1113FF006A2D52499E215FBD3ACD030B14386DFBA72F7A9F4020196808A198B6F7247C73446CF80054F4BB44F801C3EEA232129773254FA96A6A6A6A6A66A5FC86214473E2D5282BA08B43367DEA76ABB504090CAB36C77A304BC800B021331AD16000384BE2EB1506C402D1D5E0BDF55A5BFA6226592C4C18FD79A8F63DE31876CBE881F77D885F74D25600BE1FD749A9A5A9E9353D27AAA8B716502437B53C09D614035DAA5D36095370388A8ACDD20E56C548A3D3591858C050002B042E9063B7AAEFA600C4998F8286E0083608A9A9A1658095E299DC9DDD894C4D1AF69FD7A67A4D4F49F464C0062F98A8FF00F9260110139B5A9AB865D03BAD74D0A5F6D3000272E5344461216360FF006DD1A9EB6AA660E40FE6B4A73D1254306F0B0D43C7824E1B25081958925CB7F57AADFA36E8DBD0E29E8B03DAA75809A7AFFFC40032110002010204030506070100000000000001020300110412213105104113202232510630618191B11433425271A1C1F0FFDA0008010201013F00EFA005803589B860B6D0578F61615918EED5D98EA4D1897D2961075B576D147A5C9FE2BF0F14BF966C7D0D4913466CC3BF0CFA76726DF6AC96391BA55CAEF57BED4C5635CEF52CEF2EFB7A72EC581006F5886CB1647376F711B67456EA34E445B514F1F6C997A8DB996CAAEE3A69EE625C91853B9D68024D853CF147A6E6BF1A4795451249B9E4CA5A3751BEFDC8E1793CA2861E34FCC6B9F8566897CA9F5AED97F60FA50923BDCA0A570FE2AC4C9D9A651B9FB7776371BD3AA3EAEBAFA8A38788ECD6FE452E16306E5AE29E62DE14D052F02E20D1F682136FEFE9BD302A72B6879E178370F970CA81487B0F17C48F4DADFE5710C2BA390775D0FCBBA401BB0AF07EE1F5A319B5C548731D36AF66E34476C532E62B602FEA7AFF005A50C5BE6BB6D5ED7080CC9227988D7E3E9586C0BCE331D05370A005D5B5AC171AEC90418AF091B1E84563F1D1CF8C695366FF0005AB130766732EC7BD86F046D27CAAE6B807168B02AE92FEAB7CAD53F1BC3019CBDCFC2833F13C419A4F28FF00AD4B6B694580DEA444986561714FC2A33E52453E0F247949B8A6194907BAFE18517E7CF0D8379CFA0F5A862585422D30B1AD0520B0D79620D909352E14C84BC66F7A65286CC2DDCC568557D0561F0B24E7C234F5A8387C716ADA9AB5B99B2EC285EDAF2750E0A9A9E37C2CA452BA4EB6715340D11D76E428C071188C9D2911635CAA34F738BC3ACE963B8A40639321A5716B30B8E51AE670B58440333F527DC13D2AF47515361927B31D0D4913466CDCA30C5C64DEB0CAC175A26DDEBD1366157E43734543687970CC383E33D7EDC9F6A1CAF57ABF26B11AD48E249028DA9E219C2AD5AC4D5F9605408C7CB93EC6877C69A8ACCD7CD7D79FFFC4002E110002010302040503040300000000000001020300041121311012204105223251811330610614A1F02391C1FFDA0008010301013F00EB3B559AA88F2A7535A5647B566813524EB1FA8D3DC17D947CD3C3247B8C8A041EB5668CF325238750EBDEB7E13CE53C89BD63B9DF81914024ED52B2BBE536FB168D82C9F3C6EA3E53F507CF1BB3A2A7BFD9B55CB17F8A670832D4F72EDE8D053176F5371BC182ADD04814B148FB0C50B53DDA85A2FB9A365ECD4A81005153BF3BE3B0E9650C30C29AD31E83FEE8C128ED9AFA721D31515BAC63277A6F17B20FF4CCA33FDEFB50C30C8A0280AB8F16BF8AE1A4E60533A2FE33EFEF48EAEA255F4B6A3E7A4DDA7615FBB5F6349728DA6683A8D0D78FB3CAAB6A8DCA18124FE0634FE75A6B28D63F2EFEF5FA4DE6681D24F483A7FDA9EF121381A9A5F12D7CCBA55F7833BC867B3F306DC7706BC3EC1E1B25824DC7F1939AD54F2B6FD5127D4900A118049AFD41E152DF9478775CFCE6A0F04BD7C465703F34B1A786DB8863DCFF00734C083AD04276A46784E41C1A5F1271B8CD49389FCD8C11435E9B25C966E33DD2423DCD4B2B4ADCCD564904CBCB268C28086DD73A0AB997EB4A5C708572401455A3D185039DBA2C47F8F353DC2423CDBD4D7D249A0D07428E6DCD1C674E0AECA722A1916E2306A7B4C6A9BD03D8EFC6398416C1BBD3B973CCDBFD9B59DA17C8DAB21D79854F6E24D46FC09C0CD5C31C2A7B0FB0077E0A706A19DE1381A8A8E5590647038C6B5211A0EF4064E051D3A95720D6382EAA281236E12363845EAA61AF1C56382120E94A9CA849DE94F9799AB3A0C7190F08877A7DFAF359D318E3FFD9, '', '2021-01-13 17:15:36', '', '2021-03-12 20:30:44', b'1', 0); COMMIT; -- ---------------------------- --- Table structure for inf_job +-- Table structure for infra_job -- ---------------------------- -DROP TABLE IF EXISTS `inf_job`; -CREATE TABLE `inf_job` ( +DROP TABLE IF EXISTS `infra_job`; +CREATE TABLE `infra_job` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务编号', - `name` varchar(32) NOT NULL COMMENT '任务名称', + `name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务名称', `status` tinyint NOT NULL COMMENT '任务状态', - `handler_name` varchar(64) NOT NULL COMMENT '处理器的名字', - `handler_param` varchar(255) DEFAULT NULL COMMENT '处理器的参数', - `cron_expression` varchar(32) NOT NULL COMMENT 'CRON 表达式', + `handler_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '处理器的名字', + `handler_param` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '处理器的参数', + `cron_expression` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'CRON 表达式', `retry_count` int NOT NULL DEFAULT '0' COMMENT '重试次数', `retry_interval` int NOT NULL DEFAULT '0' COMMENT '重试间隔', `monitor_timeout` int NOT NULL DEFAULT '0' COMMENT '监控超时时间', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='定时任务表'; -- ---------------------------- --- Records of inf_job +-- Records of infra_job -- ---------------------------- BEGIN; -INSERT INTO `inf_job` VALUES (2, '用户 Session 超时 Job', 3, 'sysUserSessionTimeoutJob', 'aoteman', '0/5 * * * * ? *', 0, 0, 10, '', '2021-02-07 10:15:09', '', '2021-02-07 12:57:44', b'1'); -INSERT INTO `inf_job` VALUES (3, '用户 Session 超时 Job', 1, 'sysUserSessionTimeoutJob', NULL, '0 * * * * ? *', 3, 2000, 0, '', '2021-02-07 13:07:32', '', '2021-02-08 04:44:58', b'0'); -INSERT INTO `inf_job` VALUES (4, 'payNotifyJob', 1, '支付通知 Job', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:33:35', '1', '2021-10-27 00:34:14', b'1'); -INSERT INTO `inf_job` VALUES (5, '支付通知 Job', 1, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2021-10-27 08:34:42', b'0'); +INSERT INTO `infra_job` VALUES (2, '用户 Session 超时 Job', 3, 'sysUserSessionTimeoutJob', 'aoteman', '0/5 * * * * ? *', 0, 0, 10, '', '2021-02-07 10:15:09', '', '2021-02-07 12:57:44', b'1'); +INSERT INTO `infra_job` VALUES (3, '用户 Session 超时 Job', 1, 'sysUserSessionTimeoutJob', NULL, '0 * * * * ? *', 3, 2000, 0, '', '2021-02-07 13:07:32', '1', '2022-02-02 01:00:11', b'0'); +INSERT INTO `infra_job` VALUES (4, 'payNotifyJob', 1, '支付通知 Job', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:33:35', '1', '2021-10-27 00:34:14', b'1'); +INSERT INTO `infra_job` VALUES (5, '支付通知 Job', 1, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2021-10-27 08:34:42', b'0'); COMMIT; -- ---------------------------- --- Table structure for inf_job_log +-- Table structure for infra_job_log -- ---------------------------- -DROP TABLE IF EXISTS `inf_job_log`; -CREATE TABLE `inf_job_log` ( +DROP TABLE IF EXISTS `infra_job_log`; +CREATE TABLE `infra_job_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志编号', `job_id` bigint NOT NULL COMMENT '任务编号', `handler_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '处理器的名字', @@ -892,16 +1315,16 @@ CREATE TABLE `inf_job_log` ( ) ENGINE=InnoDB AUTO_INCREMENT=25274 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='定时任务日志表'; -- ---------------------------- --- Records of inf_job_log +-- Records of infra_job_log -- ---------------------------- BEGIN; COMMIT; -- ---------------------------- --- Table structure for mbr_user +-- Table structure for member_user -- ---------------------------- -DROP TABLE IF EXISTS `mbr_user`; -CREATE TABLE `mbr_user` ( +DROP TABLE IF EXISTS `member_user`; +CREATE TABLE `member_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称', `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '头像', @@ -922,11 +1345,11 @@ CREATE TABLE `mbr_user` ( ) ENGINE=InnoDB AUTO_INCREMENT=247 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户'; -- ---------------------------- --- Records of mbr_user +-- Records of member_user -- ---------------------------- BEGIN; -INSERT INTO `mbr_user` VALUES (245, '芋艿', 'http://pic.616pic.com/ys_b_img/00/06/20/novPzrqvE3.jpg', 0, '15601691300', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '127.0.0.1', '127.0.0.1', '2021-11-28 20:47:51', '', '2021-10-10 08:51:38', '245', '2021-11-28 20:47:51', b'0', 0); -INSERT INTO `mbr_user` VALUES (246, '', '', 0, '15601691301', '$2a$10$KLvmwoU.bvjU2u/MeWa1iOX2GDRJ2P9YqaCad10bYQCiyOaPexGwW', '127.0.0.1', '127.0.0.1', '2021-10-10 22:36:27', NULL, '2021-10-10 22:36:27', NULL, '2021-10-10 22:36:27', b'0', 0); +INSERT INTO `member_user` VALUES (245, '芋艿', 'http://pic.616pic.com/ys_b_img/00/06/20/novPzrqvE3.jpg', 0, '15601691300', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '127.0.0.1', '127.0.0.1', '2022-01-29 13:58:04', '', '2021-10-10 08:51:38', NULL, '2022-01-29 13:58:04', b'0', 1); +INSERT INTO `member_user` VALUES (246, '', '', 0, '15601691301', '$2a$10$KLvmwoU.bvjU2u/MeWa1iOX2GDRJ2P9YqaCad10bYQCiyOaPexGwW', '127.0.0.1', '127.0.0.1', '2021-10-10 22:36:27', NULL, '2021-10-10 22:36:27', NULL, '2021-10-10 22:36:27', b'0', 0); COMMIT; -- ---------------------------- @@ -937,13 +1360,13 @@ CREATE TABLE `pay_app` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '应用编号', `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', `status` tinyint NOT NULL COMMENT '开启状态', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', - `pay_notify_url` varchar(1024) NOT NULL COMMENT '支付结果的回调地址', + `remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `pay_notify_url` varchar(1024) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付结果的回调地址', `refund_notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退款结果的回调地址', `merchant_id` bigint NOT NULL COMMENT '商户编号', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -964,18 +1387,18 @@ CREATE TABLE `pay_channel` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '商户编号', `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码', `status` tinyint NOT NULL COMMENT '开启状态', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', `fee_rate` double NOT NULL DEFAULT '0' COMMENT '渠道费率,单位:百分比', `merchant_id` bigint NOT NULL COMMENT '商户编号', `app_id` bigint NOT NULL COMMENT '应用编号', `config` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付渠道\n'; +) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付渠道\n'; -- ---------------------------- -- Records of pay_channel @@ -988,6 +1411,8 @@ INSERT INTO `pay_channel` VALUES (12, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\ INSERT INTO `pay_channel` VALUES (13, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2021-12-14 22:09:39', NULL, '2021-12-14 22:09:39', b'0'); INSERT INTO `pay_channel` VALUES (14, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2021-12-14 22:38:49', NULL, '2021-12-14 22:38:49', b'0'); INSERT INTO `pay_channel` VALUES (15, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2021-12-15 09:32:26', NULL, '2021-12-15 09:32:26', b'0'); +INSERT INTO `pay_channel` VALUES (16, 'wx_pub', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig\",\"appId\":\"wx041349c6f39b268b\",\"mchId\":\"1545083881\",\"apiVersion\":\"v2\",\"mchKey\":\"0alL64UDQdlCwiKZ73ib7ypaIjMns06p\",\"privateKeyContent\":\"-----BEGIN PRIVATE KEY-----\\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5q2hYE3loOQoH\\nl/2kh/epuj17W8VpV5vBl7ysJWAbBXux6mlq4gKTHD0QUQdiKtDEUm/bKC9Bi6VU\\nuklM5Y8oCaCbhjklHRbET8jsgd9phSNGviHclYRLsQRO8oXnN89kN0y7DYKm0hYd\\nmaiS12Z3v8VaImSTr4HVeHlC/z3S6mdwSr263stKt931YTcbTj/QFH7znsv9Na0u\\nX6LaMBEEAsJctWdm8Ndrd1tGh9Fzf0DA5VRXsJR3kkWspy+IwiDTPV/FDKOU9NJC\\nSxMmDePerTfkoZ2s1rltqBK0ykDJrXtxR+hTzEsKZ/KpNi8tyYpfNZsviHIlUsLP\\nFJ5UvUhpAgMBAAECggEAd90NltazqTIxpGdeCwrwOzWNnYbIclJprlhMKIJUgf1P\\nNrPTbHoOGXTAgzkcYCat8iAaMEzH/TOu/3zn92m3uqxEcEL9v1UBLqknWHAbkB6w\\ngGocqDAqYUcdNe5hvbyM+fCta5C0SQgV2PQrHOlMMICwYpkTfzhtxCdreXIYMoGg\\nJEIRkZWgrm/N7LTtNgizznuUjy6OURWjXaWKPcs3b3j6G1gLj9Vp++z4y0u51nqM\\n4R6fcvl8M6BjlcC8zo6DbOvCW8cXtuXsnru+2TPrUnsGeybJok4fEQsfW1BvpvPo\\nief38rYJn4OWxIrHcpWrhNtXtgRPeiMGFfIsEQDmVQKBgQDzXK6Nn3Nr3TFfGVTy\\n8QYrzOuY2NqzH8nnsLL6qn3HoKxTv+PcFKOTPsi6f4hIYCzBP0esRrPv0ffMu9oQ\\nJvFtCJvMmcKGtp0Q5hcj0y/XkbC3AWuahJtBv8lhKXVnQXSL0j3+ombljw4/8yN0\\nAzgBz+j/skQQgZ3sN5h+DHGtgwKBgQDDT784/2pd4m86c/uBmrwYfqu6MJo0eHJh\\n1XPtE+u8pOHyNTFk77rKobKDqN5VlrF0uEmBc/08LKhyxJ3vh/zAbcmqT1Mq778y\\nAKKUtVmvcaVDrvSQHsnhj0zt4SHGmmU34U2b9hV+nocq5VszX6/jp//HJi9bs3We\\ndAzfFCmaowKBgC1MmDVGc+6lCraf+X8LPFHU4Bnga70h8qxM6NPd/nG1R76DHn/t\\n25DiA+0rJgwK0unZxJadxoqic9TJNssA5Lmd+5o3GM2Imm311mLVwbcHqHQ4MHZf\\nrqKrd2m9lNv2hCIurVmDk1Gxsj5XHMdQfhFgSQengCHubp30r07vNA3PAoGAUEAE\\nIjdQTSMs8KeXP7mEb8wcY3R05/pVhT1fVJpK0kgtTofss7yM05V88/v+3sv8Pik6\\niqZN9tuimwWOn00Q3UA/DGtrkMjRlooMQ24AW8YmUZkhg9YivTtUMKnAZwopbLx2\\nVw7V5iDdCRMUVheK/c+ZmQpnixZBzcmBQGfYcGECgYBjEq3Mem+Aw6pXOu6+0FwH\\n9y6Xi4HhBkq0OOZZuXFtWVry7YrD3pBgzWVAZJqJCkyPKKZzCzwdbFd3u0lYBs35\\nzYgx7ug4hR+wfI980a3vxjcWGOqnOUUnUJ7ucIa+KDgnYV/bBy4jqpVreXmWAJXl\\nfyjG3eLWBrtrsI9YX6zeAA==\\n-----END PRIVATE KEY-----\\n\",\"privateCertContent\":\"-----BEGIN CERTIFICATE-----\\nMIID6TCCAtGgAwIBAgIUNkEHq6aQcF80NSYqWS58ybsJzI4wDQYJKoZIhvcNAQEL\\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\\nQ0EwHhcNMjExMDIxMDU0NTQxWhcNMjYxMDIwMDU0NTQxWjB7MRMwEQYDVQQDDAox\\nNTQ1MDgzODgxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xJzAlBgNVBAsM\\nHuWOhuWfjuWMuuWkp+adjuWwp+aXpeeUqOWTgeW6lzELMAkGA1UEBgwCQ04xETAP\\nBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\\nuatoWBN5aDkKB5f9pIf3qbo9e1vFaVebwZe8rCVgGwV7seppauICkxw9EFEHYirQ\\nxFJv2ygvQYulVLpJTOWPKAmgm4Y5JR0WxE/I7IHfaYUjRr4h3JWES7EETvKF5zfP\\nZDdMuw2CptIWHZmoktdmd7/FWiJkk6+B1Xh5Qv890upncEq9ut7LSrfd9WE3G04/\\n0BR+857L/TWtLl+i2jARBALCXLVnZvDXa3dbRofRc39AwOVUV7CUd5JFrKcviMIg\\n0z1fxQyjlPTSQksTJg3j3q035KGdrNa5bagStMpAya17cUfoU8xLCmfyqTYvLcmK\\nXzWbL4hyJVLCzxSeVL1IaQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMC\\nBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1\\nYmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\\nMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBe7XgncAY/1PLbCsnMsYt11k3V\\n2cdNZ+yuCxhlOEKk3nHE6WCTL6zL0qWlTKKpnw1rE/+4OS76Tg72wWXcHfHDAOgt\\n9icp62cKx1WO3QweeZpSvLDmtdLgKKrqeIWh+rL8+ZhuAOxSkaRwcsMTWDaLeDOi\\n0pGeqvfG8WNhPxkkaSI8xbiTK641Yg9WT/Q4yfHS7Q6wg1dj9YQdo0dvVB0S2Nir\\nX9IK6PUaHDnQeFKDmKgLkDGLaKaiijEvC91wMEE6qB8b0eNhciaxq2YhGHcFmSRP\\nWUyc5CmBadt7wIOH5Z3bfuwWGxqxKjNw/baM/d+nk7hlDr01YL9c0g16B9MW\\n-----END CERTIFICATE-----\\n\",\"apiV3Key\":\"joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase\"}', NULL, '2022-01-31 22:13:25', NULL, '2022-01-31 22:13:25', b'0'); +INSERT INTO `pay_channel` VALUES (17, 'alipay_qr', 0, NULL, 1, 1, 6, '{\"@class\":\"cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig\",\"serverUrl\":\"https://openapi.alipaydev.com/gateway.do\",\"appId\":\"2021000118634035\",\"signType\":\"RSA2\",\"mode\":null,\"privateKey\":\"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=\",\"alipayPublicKey\":\"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB\",\"appCertContent\":null,\"alipayPublicCertContent\":null,\"rootCertContent\":null}', NULL, '2022-01-31 22:13:25', NULL, '2022-01-31 22:13:25', b'0'); COMMIT; -- ---------------------------- @@ -1000,10 +1425,10 @@ CREATE TABLE `pay_merchant` ( `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户全称', `short_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户简称', `status` tinyint NOT NULL COMMENT '开启状态', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1024,11 +1449,11 @@ CREATE TABLE `pay_notify_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志编号', `task_id` bigint NOT NULL COMMENT '通知任务编号', `notify_times` tinyint NOT NULL COMMENT '第几次被通知', - `response` varchar(2048) NOT NULL COMMENT '请求参数', + `response` varchar(2048) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求参数', `status` tinyint NOT NULL COMMENT '通知状态', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1057,9 +1482,9 @@ CREATE TABLE `pay_notify_task` ( `notify_times` tinyint NOT NULL COMMENT '当前通知次数', `max_notify_times` tinyint NOT NULL COMMENT '最大可通知次数', `notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知地址', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1097,7 +1522,7 @@ CREATE TABLE `pay_order` ( `app_id` bigint NOT NULL COMMENT '应用编号', `channel_id` bigint DEFAULT NULL COMMENT '渠道编号', `channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道编码', - `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号', + `merchant_order_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户订单编号', `subject` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品标题', `body` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品描述', `notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知地址', @@ -1115,10 +1540,10 @@ CREATE TABLE `pay_order` ( `refund_times` tinyint NOT NULL COMMENT '退款次数', `refund_amount` bigint NOT NULL COMMENT '退款总金额,单位:分', `channel_user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道用户编号', - `channel_order_no` varchar(64) DEFAULT NULL COMMENT '渠道订单号', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `channel_order_no` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道订单号', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1248,7 +1673,7 @@ COMMIT; DROP TABLE IF EXISTS `pay_order_extension`; CREATE TABLE `pay_order_extension` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付订单编号', - `no` varchar(64) NOT NULL COMMENT '支付订单号', + `no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付订单号', `order_id` bigint NOT NULL COMMENT '支付订单编号', `channel_id` bigint NOT NULL COMMENT '渠道编号', `channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码', @@ -1256,9 +1681,9 @@ CREATE TABLE `pay_order_extension` ( `status` tinyint NOT NULL COMMENT '支付状态', `channel_extras` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '支付渠道的额外参数', `channel_notify_data` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '支付渠道异步通知的内容', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1373,28 +1798,28 @@ CREATE TABLE `pay_refund` ( `channel_id` bigint NOT NULL COMMENT '渠道编号', `channel_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码', `order_id` bigint NOT NULL COMMENT '支付订单编号 pay_order 表id', - `trade_no` varchar(64) NOT NULL COMMENT '交易订单号 pay_extension 表no 字段', - `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号(商户系统生成)', - `merchant_refund_no` varchar(64) NOT NULL COMMENT '商户退款订单号(商户系统生成)', + `trade_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易订单号 pay_extension 表no 字段', + `merchant_order_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户订单编号(商户系统生成)', + `merchant_refund_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户退款订单号(商户系统生成)', `notify_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '异步通知商户地址', `notify_status` tinyint NOT NULL COMMENT '通知商户退款结果的回调状态', `status` tinyint NOT NULL COMMENT '退款状态', `type` tinyint NOT NULL COMMENT '退款类型(部分退款,全部退款)', `pay_amount` bigint NOT NULL COMMENT '支付金额,单位分', `refund_amount` bigint NOT NULL COMMENT '退款金额,单位分', - `reason` varchar(256) NOT NULL COMMENT '退款原因', + `reason` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退款原因', `user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户 IP', - `channel_order_no` varchar(64) NOT NULL COMMENT '渠道订单号,pay_order 中的channel_order_no 对应', - `channel_refund_no` varchar(64) DEFAULT NULL COMMENT '渠道退款单号,渠道返回', - `channel_error_code` varchar(128) DEFAULT NULL COMMENT '渠道调用报错时,错误码', - `channel_error_msg` varchar(256) DEFAULT NULL COMMENT '渠道调用报错时,错误信息', + `channel_order_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道订单号,pay_order 中的channel_order_no 对应', + `channel_refund_no` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道退款单号,渠道返回', + `channel_error_code` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道调用报错时,错误码', + `channel_error_msg` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道调用报错时,错误信息', `channel_extras` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '支付渠道的额外参数', `expire_time` datetime DEFAULT NULL COMMENT '退款失效时间', `success_time` datetime DEFAULT NULL COMMENT '退款成功时间', `notify_time` datetime DEFAULT NULL COMMENT '退款通知时间', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -1407,10 +1832,10 @@ BEGIN; COMMIT; -- ---------------------------- --- Table structure for sys_dept +-- Table structure for system_dept -- ---------------------------- -DROP TABLE IF EXISTS `sys_dept`; -CREATE TABLE `sys_dept` ( +DROP TABLE IF EXISTS `system_dept`; +CREATE TABLE `system_dept` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '部门id', `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '部门名称', `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父部门id', @@ -1429,26 +1854,26 @@ CREATE TABLE `sys_dept` ( ) ENGINE=InnoDB AUTO_INCREMENT=110 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部门表'; -- ---------------------------- --- Records of sys_dept +-- Records of system_dept -- ---------------------------- BEGIN; -INSERT INTO `sys_dept` VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:05', b'0', 1); -INSERT INTO `sys_dept` VALUES (101, '深圳总公司', 100, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-15 21:32:28', b'0', 1); -INSERT INTO `sys_dept` VALUES (102, '长沙分公司', 100, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:40', b'0', 1); -INSERT INTO `sys_dept` VALUES (103, '研发部门', 101, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:14', b'0', 1); -INSERT INTO `sys_dept` VALUES (104, '市场部门', 101, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:38', b'0', 1); -INSERT INTO `sys_dept` VALUES (105, '测试部门', 101, 3, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:37', b'0', 1); -INSERT INTO `sys_dept` VALUES (106, '财务部门', 101, 4, 103, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-15 21:32:22', b'0', 1); -INSERT INTO `sys_dept` VALUES (107, '运维部门', 101, 5, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:33', b'0', 1); -INSERT INTO `sys_dept` VALUES (108, '市场部门', 102, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:31', b'0', 1); -INSERT INTO `sys_dept` VALUES (109, '财务部门', 102, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:29', b'0', 1); +INSERT INTO `system_dept` VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:05', b'0', 1); +INSERT INTO `system_dept` VALUES (101, '深圳总公司', 100, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-15 21:32:28', b'0', 1); +INSERT INTO `system_dept` VALUES (102, '长沙分公司', 100, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:40', b'0', 1); +INSERT INTO `system_dept` VALUES (103, '研发部门', 101, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:14', b'0', 1); +INSERT INTO `system_dept` VALUES (104, '市场部门', 101, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:38', b'0', 1); +INSERT INTO `system_dept` VALUES (105, '测试部门', 101, 3, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:37', b'0', 1); +INSERT INTO `system_dept` VALUES (106, '财务部门', 101, 4, 103, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-15 21:32:22', b'0', 1); +INSERT INTO `system_dept` VALUES (107, '运维部门', 101, 5, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:33', b'0', 1); +INSERT INTO `system_dept` VALUES (108, '市场部门', 102, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:31', b'0', 1); +INSERT INTO `system_dept` VALUES (109, '财务部门', 102, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:29', b'0', 1); COMMIT; -- ---------------------------- --- Table structure for sys_dict_data +-- Table structure for system_dict_data -- ---------------------------- -DROP TABLE IF EXISTS `sys_dict_data`; -CREATE TABLE `sys_dict_data` ( +DROP TABLE IF EXISTS `system_dict_data`; +CREATE TABLE `system_dict_data` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典编码', `sort` int NOT NULL DEFAULT '0' COMMENT '字典排序', `label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典标签', @@ -1465,148 +1890,141 @@ CREATE TABLE `sys_dict_data` ( ) ENGINE=InnoDB AUTO_INCREMENT=1145 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典数据表'; -- ---------------------------- --- Records of sys_dict_data +-- Records of system_dict_data -- ---------------------------- BEGIN; -INSERT INTO `sys_dict_data` VALUES (1, 1, '男', '1', 'sys_user_sex', 0, '性别男', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:53', b'0'); -INSERT INTO `sys_dict_data` VALUES (2, 2, '女', '2', 'sys_user_sex', 0, '性别女', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:55', b'0'); -INSERT INTO `sys_dict_data` VALUES (8, 1, '正常', '0', 'sys_job_status', 0, '正常状态', 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:43:57', b'1'); -INSERT INTO `sys_dict_data` VALUES (9, 2, '暂停', '1', 'sys_job_status', 0, '停用状态', 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:43:59', b'1'); -INSERT INTO `sys_dict_data` VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', 0, '默认分组', 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:43:44', b'1'); -INSERT INTO `sys_dict_data` VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', 0, '系统分组', 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:43:45', b'1'); -INSERT INTO `sys_dict_data` VALUES (12, 1, '系统内置', '1', 'sys_config_type', 0, '参数类型 - 系统内置', 'admin', '2021-01-05 17:03:48', '', '2021-01-18 07:41:59', b'0'); -INSERT INTO `sys_dict_data` VALUES (13, 2, '自定义', '2', 'sys_config_type', 0, '参数类型 - 自定义', 'admin', '2021-01-05 17:03:48', '', '2021-01-18 07:41:51', b'0'); -INSERT INTO `sys_dict_data` VALUES (14, 1, '通知', '1', 'sys_notice_type', 0, '通知', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0'); -INSERT INTO `sys_dict_data` VALUES (15, 2, '公告', '2', 'sys_notice_type', 0, '公告', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0'); -INSERT INTO `sys_dict_data` VALUES (16, 0, '其它', '0', 'sys_operate_type', 0, '其它操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:12', b'0'); -INSERT INTO `sys_dict_data` VALUES (17, 1, '查询', '1', 'sys_operate_type', 0, '查询操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (18, 2, '新增', '2', 'sys_operate_type', 0, '新增操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:17', b'0'); -INSERT INTO `sys_dict_data` VALUES (19, 3, '修改', '3', 'sys_operate_type', 0, '修改操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:20', b'0'); -INSERT INTO `sys_dict_data` VALUES (20, 4, '删除', '4', 'sys_operate_type', 0, '删除操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:24', b'0'); -INSERT INTO `sys_dict_data` VALUES (22, 5, '导出', '5', 'sys_operate_type', 0, '导出操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:49:20', b'0'); -INSERT INTO `sys_dict_data` VALUES (23, 6, '导入', '6', 'sys_operate_type', 0, '导入操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:49:24', b'0'); -INSERT INTO `sys_dict_data` VALUES (27, 1, '开启', '0', 'sys_common_status', 0, '开启状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 02:57:12', b'0'); -INSERT INTO `sys_dict_data` VALUES (28, 2, '关闭', '1', 'sys_common_status', 0, '关闭状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:32', b'0'); -INSERT INTO `sys_dict_data` VALUES (29, 1, '目录', '1', 'sys_menu_type', 0, '目录', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:30', b'0'); -INSERT INTO `sys_dict_data` VALUES (30, 2, '菜单', '2', 'sys_menu_type', 0, '菜单', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:35', b'0'); -INSERT INTO `sys_dict_data` VALUES (31, 3, '按钮', '3', 'sys_menu_type', 0, '按钮', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:38', b'0'); -INSERT INTO `sys_dict_data` VALUES (32, 1, '内置', '1', 'sys_role_type', 0, '内置角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:34:22', b'0'); -INSERT INTO `sys_dict_data` VALUES (33, 2, '自定义', '2', 'sys_role_type', 0, '自定义角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:34:26', b'0'); -INSERT INTO `sys_dict_data` VALUES (34, 1, '全部数据权限', '1', 'sys_data_scope', 0, '全部数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:02', b'0'); -INSERT INTO `sys_dict_data` VALUES (35, 2, '指定部门数据权限', '2', 'sys_data_scope', 0, '指定部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:20', b'0'); -INSERT INTO `sys_dict_data` VALUES (36, 3, '本部门数据权限', '3', 'sys_data_scope', 0, '本部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:29', b'0'); -INSERT INTO `sys_dict_data` VALUES (37, 4, '本部门及以下数据权限', '4', 'sys_data_scope', 0, '本部门及以下数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:32', b'0'); -INSERT INTO `sys_dict_data` VALUES (38, 5, '仅本人数据权限', '5', 'sys_data_scope', 0, '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:38', b'0'); -INSERT INTO `sys_dict_data` VALUES (39, 0, '成功', '0', 'sys_login_result', 0, '登陆结果 - 成功', '', '2021-01-18 06:17:36', '', '2021-01-18 06:17:36', b'0'); -INSERT INTO `sys_dict_data` VALUES (40, 10, '账号或密码不正确', '10', 'sys_login_result', 0, '登陆结果 - 账号或密码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:17:54', b'0'); -INSERT INTO `sys_dict_data` VALUES (41, 20, '用户被禁用', '20', 'sys_login_result', 0, '登陆结果 - 用户被禁用', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:02', b'0'); -INSERT INTO `sys_dict_data` VALUES (42, 30, '验证码不存在', '30', 'sys_login_result', 0, '登陆结果 - 验证码不存在', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:24', b'0'); -INSERT INTO `sys_dict_data` VALUES (43, 31, '验证码不正确', '31', 'sys_login_result', 0, '登陆结果 - 验证码不正确', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:33', b'0'); -INSERT INTO `sys_dict_data` VALUES (44, 100, '未知异常', '100', 'sys_login_result', 0, '登陆结果 - 未知异常', '', '2021-01-18 06:17:54', '', '2021-01-18 06:19:57', b'0'); -INSERT INTO `sys_dict_data` VALUES (45, 1, '是', 'true', 'sys_boolean_string', 0, 'Boolean 是否类型 - 是', '', '2021-01-19 03:20:55', '', '2021-01-19 03:21:08', b'0'); -INSERT INTO `sys_dict_data` VALUES (46, 1, '否', 'false', 'sys_boolean_string', 0, 'Boolean 是否类型 - 否', '', '2021-01-19 03:20:55', '', '2021-01-19 03:21:39', b'0'); -INSERT INTO `sys_dict_data` VALUES (47, 1, '永不超时', '1', 'inf_redis_timeout_type', 0, 'Redis 未设置超时的情况', '', '2021-01-26 00:53:17', '', '2021-01-26 00:53:17', b'0'); -INSERT INTO `sys_dict_data` VALUES (48, 1, '动态超时', '2', 'inf_redis_timeout_type', 0, '程序里动态传入超时时间,无法固定', '', '2021-01-26 00:55:00', '', '2021-01-26 00:55:00', b'0'); -INSERT INTO `sys_dict_data` VALUES (49, 3, '固定超时', '3', 'inf_redis_timeout_type', 0, 'Redis 设置了过期时间', '', '2021-01-26 00:55:26', '', '2021-01-26 00:55:26', b'0'); -INSERT INTO `sys_dict_data` VALUES (50, 1, '单表(增删改查)', '1', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:09:06', '', '2021-02-05 07:21:52', b'0'); -INSERT INTO `sys_dict_data` VALUES (51, 2, '树表(增删改查)', '2', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:14:46', '', '2021-02-05 07:21:49', b'0'); -INSERT INTO `sys_dict_data` VALUES (52, 3, '主子表(增删改查)', '3', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:21:45', '', '2021-02-06 18:54:26', b'1'); -INSERT INTO `sys_dict_data` VALUES (53, 0, '初始化中', '0', 'inf_job_status', 0, NULL, '', '2021-02-07 07:46:49', '', '2021-02-07 07:46:49', b'0'); -INSERT INTO `sys_dict_data` VALUES (54, 1, '开启', '1', 'inf_job_status', 0, NULL, '', '2021-02-07 07:46:57', '', '2021-02-07 11:54:09', b'0'); -INSERT INTO `sys_dict_data` VALUES (56, 3, '暂停', '2', 'inf_job_status', 0, NULL, '', '2021-02-07 07:47:16', '', '2021-02-08 04:54:11', b'0'); -INSERT INTO `sys_dict_data` VALUES (57, 0, '运行中', '0', 'inf_job_log_status', 0, 'RUNNING', '', '2021-02-08 10:04:24', '', '2021-02-08 10:04:24', b'0'); -INSERT INTO `sys_dict_data` VALUES (58, 1, '成功', '1', 'inf_job_log_status', 0, NULL, '', '2021-02-08 10:06:57', '', '2021-02-08 10:06:57', b'0'); -INSERT INTO `sys_dict_data` VALUES (59, 2, '失败', '2', 'inf_job_log_status', 0, '失败', '', '2021-02-08 10:07:38', '', '2021-02-08 10:07:38', b'0'); -INSERT INTO `sys_dict_data` VALUES (60, 1, '会员', '1', 'user_type', 0, NULL, '', '2021-02-26 00:16:27', '', '2021-02-26 00:16:27', b'0'); -INSERT INTO `sys_dict_data` VALUES (61, 2, '管理员', '2', 'user_type', 0, NULL, '', '2021-02-26 00:16:34', '', '2021-02-26 00:16:34', b'0'); -INSERT INTO `sys_dict_data` VALUES (62, 0, '未处理', '0', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:19', '', '2021-02-26 08:11:23', b'0'); -INSERT INTO `sys_dict_data` VALUES (63, 1, '已处理', '1', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:26', '', '2021-02-26 08:11:29', b'0'); -INSERT INTO `sys_dict_data` VALUES (64, 2, '已忽略', '2', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:34', '', '2021-02-26 08:11:34', b'0'); -INSERT INTO `sys_dict_data` VALUES (65, 1, '云片', 'YUN_PIAN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:14', '1', '2021-04-13 00:20:13', b'0'); -INSERT INTO `sys_dict_data` VALUES (66, 2, '阿里云', 'ALIYUN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:26', '1', '2021-04-13 00:20:16', b'0'); -INSERT INTO `sys_dict_data` VALUES (67, 1, '验证码', '1', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:57', '1', '2021-04-05 21:50:57', b'0'); -INSERT INTO `sys_dict_data` VALUES (68, 2, '通知', '2', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:08', '1', '2021-04-05 21:51:08', b'0'); -INSERT INTO `sys_dict_data` VALUES (69, 0, '营销', '3', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:15', '1', '2021-04-05 21:51:15', b'0'); -INSERT INTO `sys_dict_data` VALUES (70, 0, '初始化', '0', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:33', '1', '2021-04-11 09:30:18', b'0'); -INSERT INTO `sys_dict_data` VALUES (71, 1, '发送成功', '10', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:43', '1', '2021-04-11 09:30:20', b'0'); -INSERT INTO `sys_dict_data` VALUES (72, 2, '发送失败', '20', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:49', '1', '2021-04-11 09:30:22', b'0'); -INSERT INTO `sys_dict_data` VALUES (73, 3, '不发送', '30', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:19:44', '1', '2021-04-11 09:30:23', b'0'); -INSERT INTO `sys_dict_data` VALUES (74, 0, '等待结果', '0', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:43', '1', '2021-04-17 23:05:19', b'0'); -INSERT INTO `sys_dict_data` VALUES (75, 1, '接收成功', '10', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:25', '1', '2021-04-11 20:29:35', b'0'); -INSERT INTO `sys_dict_data` VALUES (76, 2, '接收失败', '20', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:31', '1', '2021-04-11 20:29:39', b'0'); -INSERT INTO `sys_dict_data` VALUES (77, 0, '调试(钉钉)', 'DEBUG_DING_TALK', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-13 00:20:37', '1', '2021-04-13 00:20:37', b'0'); -INSERT INTO `sys_dict_data` VALUES (78, 1, '自动生成', '1', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:06:48', '1', '2021-04-13 22:06:44', b'0'); -INSERT INTO `sys_dict_data` VALUES (79, 2, '手动编辑', '2', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:07:14', '1', '2021-04-13 22:06:49', b'0'); -INSERT INTO `sys_dict_data` VALUES (80, 100, '账号登录', '100', 'sys_login_type', 0, '账号登录', '1', '2021-10-06 00:52:02', '1', '2021-10-06 00:52:43', b'0'); -INSERT INTO `sys_dict_data` VALUES (81, 101, '社交登录', '101', 'sys_login_type', 0, '社交登录', '1', '2021-10-06 00:52:17', '1', '2021-10-06 00:52:17', b'0'); -INSERT INTO `sys_dict_data` VALUES (82, 102, 'Mock 登录', '102', 'sys_login_type', 0, 'Mock 登录', '1', '2021-10-06 00:52:32', '1', '2021-10-06 00:52:39', b'0'); -INSERT INTO `sys_dict_data` VALUES (83, 200, '主动登出', '200', 'sys_login_type', 0, '主动登出', '1', '2021-10-06 00:52:58', '1', '2021-10-06 00:52:58', b'0'); -INSERT INTO `sys_dict_data` VALUES (84, 201, '超时登出', '201', 'sys_login_type', 0, '超时登出', '1', '2021-10-06 00:53:17', '1', '2021-10-06 00:53:17', b'0'); -INSERT INTO `sys_dict_data` VALUES (85, 202, '强制登出', '202', 'sys_login_type', 0, '强制退出', '1', '2021-10-06 00:53:41', '1', '2021-10-06 00:53:41', b'0'); -INSERT INTO `sys_dict_data` VALUES (86, 0, '病假', '1', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:35:28', '1', '2022-01-22 10:42:08', b'0'); -INSERT INTO `sys_dict_data` VALUES (87, 1, '事假', '2', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:36:11', '1', '2022-01-22 10:42:11', b'0'); -INSERT INTO `sys_dict_data` VALUES (88, 2, '婚假', '3', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:36:38', '1', '2022-01-22 10:42:16', b'0'); -INSERT INTO `sys_dict_data` VALUES (89, 0, '处理中', '1', 'oa_leave_status', 0, NULL, '1', '2021-09-21 22:46:46', '1', '2022-01-22 10:40:38', b'1'); -INSERT INTO `sys_dict_data` VALUES (90, 1, '流程结束', '2', 'oa_leave_status', 0, NULL, '1', '2021-09-21 22:47:03', '1', '2022-01-22 10:40:37', b'1'); -INSERT INTO `sys_dict_data` VALUES (91, 2, '完成', '3', 'oa_leave_status', 0, NULL, '1', '2021-09-21 22:47:25', '1', '2021-10-12 14:13:06', b'1'); -INSERT INTO `sys_dict_data` VALUES (98, 1, 'v2', 'v2', 'pay_channel_wechat_version', 0, 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0'); -INSERT INTO `sys_dict_data` VALUES (99, 2, 'v3', 'v3', 'pay_channel_wechat_version', 0, 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0'); -INSERT INTO `sys_dict_data` VALUES (108, 1, 'RSA2', 'RSA2', 'pay_channel_alipay_sign_type', 0, 'RSA2', '1', '2021-11-18 15:39:29', '1', '2021-11-18 15:39:29', b'0'); -INSERT INTO `sys_dict_data` VALUES (109, 1, '公钥模式', '1', 'pay_channel_alipay_mode', 0, '公钥模式:privateKey + alipayPublicKey', '1', '2021-11-18 15:45:23', '1', '2021-11-18 15:45:23', b'0'); -INSERT INTO `sys_dict_data` VALUES (110, 2, '证书模式', '2', 'pay_channel_alipay_mode', 0, '证书模式:appCertContent + alipayPublicCertContent + rootCertContent', '1', '2021-11-18 15:45:40', '1', '2021-11-18 15:45:40', b'0'); -INSERT INTO `sys_dict_data` VALUES (111, 1, '线上', 'https://openapi.alipay.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 线上', '1', '2021-11-18 16:59:32', '1', '2021-11-21 17:37:29', b'0'); -INSERT INTO `sys_dict_data` VALUES (112, 2, '沙箱', 'https://openapi.alipaydev.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 沙箱', '1', '2021-11-18 16:59:48', '1', '2021-11-21 17:37:39', b'0'); -INSERT INTO `sys_dict_data` VALUES (113, 1, '微信 JSAPI 支付', 'wx_pub', 'pay_channel_code_type', 0, '微信 JSAPI(公众号) 支付', '1', '2021-12-03 10:40:24', '1', '2021-12-04 16:41:00', b'0'); -INSERT INTO `sys_dict_data` VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code_type', 0, '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2021-12-03 10:41:06', b'0'); -INSERT INTO `sys_dict_data` VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code_type', 0, '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2021-12-03 10:41:20', b'0'); -INSERT INTO `sys_dict_data` VALUES (116, 4, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code_type', 0, '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2021-12-03 10:42:09', b'0'); -INSERT INTO `sys_dict_data` VALUES (117, 5, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code_type', 0, '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2021-12-03 10:42:26', b'0'); -INSERT INTO `sys_dict_data` VALUES (118, 6, '支付宝App 支付', 'alipay_app', 'pay_channel_code_type', 0, '支付宝App 支付', '1', '2021-12-03 10:42:55', '1', '2021-12-03 10:42:55', b'0'); -INSERT INTO `sys_dict_data` VALUES (119, 7, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code_type', 0, '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2021-12-03 10:43:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (120, 1, '通知成功', '10', 'pay_order_notify_status', 0, '通知成功', '1', '2021-12-03 11:02:41', '1', '2021-12-03 11:02:41', b'0'); -INSERT INTO `sys_dict_data` VALUES (121, 2, '通知失败', '20', 'pay_order_notify_status', 0, '通知失败', '1', '2021-12-03 11:02:59', '1', '2021-12-03 11:02:59', b'0'); -INSERT INTO `sys_dict_data` VALUES (122, 3, '未通知', '0', 'pay_order_notify_status', 0, '未通知', '1', '2021-12-03 11:03:10', '1', '2021-12-03 11:03:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (123, 1, '支付成功', '10', 'pay_order_status', 0, '支付成功', '1', '2021-12-03 11:18:29', '1', '2021-12-03 11:28:32', b'0'); -INSERT INTO `sys_dict_data` VALUES (124, 2, '支付关闭', '20', 'pay_order_status', 0, '支付关闭', '1', '2021-12-03 11:18:42', '1', '2021-12-03 11:28:34', b'0'); -INSERT INTO `sys_dict_data` VALUES (125, 3, '未支付', '0', 'pay_order_status', 0, '未支付', '1', '2021-12-03 11:18:18', '1', '2021-12-03 11:28:36', b'0'); -INSERT INTO `sys_dict_data` VALUES (126, 1, '未退款', '0', 'pay_order_refund_status', 0, '未退款', '1', '2021-12-03 11:30:35', '1', '2021-12-03 11:34:05', b'0'); -INSERT INTO `sys_dict_data` VALUES (127, 2, '部分退款', '10', 'pay_order_refund_status', 0, '部分退款', '1', '2021-12-03 11:30:44', '1', '2021-12-03 11:34:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (128, 3, '全部退款', '20', 'pay_order_refund_status', 0, '全部退款', '1', '2021-12-03 11:30:52', '1', '2021-12-03 11:34:14', b'0'); -INSERT INTO `sys_dict_data` VALUES (1117, 1, '退款订单生成', '0', 'pay_refund_order_status', 0, '退款订单生成', '1', '2021-12-10 16:44:44', '1', '2021-12-10 16:44:44', b'0'); -INSERT INTO `sys_dict_data` VALUES (1118, 2, '退款成功', '1', 'pay_refund_order_status', 0, '退款成功', '1', '2021-12-10 16:44:59', '1', '2021-12-10 16:44:59', b'0'); -INSERT INTO `sys_dict_data` VALUES (1119, 3, '退款失败', '2', 'pay_refund_order_status', 0, '退款失败', '1', '2021-12-10 16:45:10', '1', '2021-12-10 16:45:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (1120, 4, '退款中, 渠道通知结果', '3', 'pay_refund_order_status', 0, '退款中, 渠道通知结果', '1', '2021-12-10 16:45:32', '1', '2021-12-10 16:45:32', b'0'); -INSERT INTO `sys_dict_data` VALUES (1121, 5, '退款中, 系统查询结果', '4', 'pay_refund_order_status', 0, '退款中, 系统查询结果', '1', '2021-12-10 16:45:48', '1', '2021-12-10 16:45:48', b'0'); -INSERT INTO `sys_dict_data` VALUES (1122, 6, '状态未知,需要重试', '5', 'pay_refund_order_status', 0, '状态未知,需要重试', '1', '2021-12-10 16:46:03', '1', '2021-12-10 16:46:03', b'0'); -INSERT INTO `sys_dict_data` VALUES (1123, 7, '状态未知,系统查询结果', '6', 'pay_refund_order_status', 0, '状态未知,系统查询结果', '1', '2021-12-10 16:46:13', '1', '2021-12-10 16:46:13', b'0'); -INSERT INTO `sys_dict_data` VALUES (1124, 8, '退款关闭', '99', 'pay_refund_order_status', 0, '退款关闭', '1', '2021-12-10 16:46:26', '1', '2021-12-10 16:46:26', b'0'); -INSERT INTO `sys_dict_data` VALUES (1125, 0, '默认', '1', 'bpm_model_category', 0, '流程分类 - 默认', '1', '2022-01-02 08:41:11', '1', '2022-01-02 08:41:11', b'0'); -INSERT INTO `sys_dict_data` VALUES (1126, 0, 'OA', '2', 'bpm_model_category', 0, '流程分类 - OA', '1', '2022-01-02 08:41:22', '1', '2022-01-02 08:41:22', b'0'); -INSERT INTO `sys_dict_data` VALUES (1127, 0, '进行中', '1', 'bpm_process_instance_status', 0, '流程实例的状态 - 进行中', '1', '2022-01-07 23:47:22', '1', '2022-01-09 08:59:34', b'0'); -INSERT INTO `sys_dict_data` VALUES (1128, 2, '已完成', '2', 'bpm_process_instance_status', 0, '流程实例的状态 - 已完成', '1', '2022-01-07 23:47:49', '1', '2022-01-07 23:47:49', b'0'); -INSERT INTO `sys_dict_data` VALUES (1129, 1, '处理中', '1', 'bpm_process_instance_result', 0, '流程实例的结果 - 处理中', '1', '2022-01-07 23:48:32', '1', '2022-01-07 23:48:32', b'0'); -INSERT INTO `sys_dict_data` VALUES (1130, 2, '通过', '2', 'bpm_process_instance_result', 0, '流程实例的结果 - 通过', '1', '2022-01-07 23:48:45', '1', '2022-01-07 23:48:45', b'0'); -INSERT INTO `sys_dict_data` VALUES (1131, 3, '不通过', '3', 'bpm_process_instance_result', 0, '流程实例的结果 - 不通过', '1', '2022-01-07 23:48:55', '1', '2022-01-07 23:48:55', b'0'); -INSERT INTO `sys_dict_data` VALUES (1132, 4, '已取消', '4', 'bpm_process_instance_result', 0, '流程实例的结果 - 撤销', '1', '2022-01-07 23:49:06', '1', '2022-01-08 13:21:14', b'0'); -INSERT INTO `sys_dict_data` VALUES (1133, 10, '流程表单', '10', 'bpm_model_form_type', 0, '流程的表单类型 - 流程表单', '103', '2022-01-11 23:51:30', '103', '2022-01-11 23:51:30', b'0'); -INSERT INTO `sys_dict_data` VALUES (1134, 20, '业务表单', '20', 'bpm_model_form_type', 0, '流程的表单类型 - 业务表单', '103', '2022-01-11 23:51:47', '103', '2022-01-11 23:51:47', b'0'); -INSERT INTO `sys_dict_data` VALUES (1135, 10, '角色', '10', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 角色', '103', '2022-01-12 23:21:22', '103', '2022-01-12 15:46:30', b'0'); -INSERT INTO `sys_dict_data` VALUES (1136, 20, '部门的成员', '20', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 部门的成员', '103', '2022-01-12 23:21:47', '103', '2022-01-12 15:46:26', b'0'); -INSERT INTO `sys_dict_data` VALUES (1137, 21, '部门的负责人', '21', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 部门的负责人', '103', '2022-01-12 23:33:36', '103', '2022-01-12 15:46:24', b'0'); -INSERT INTO `sys_dict_data` VALUES (1138, 30, '用户', '30', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 用户', '103', '2022-01-12 23:34:02', '103', '2022-01-12 15:46:22', b'0'); -INSERT INTO `sys_dict_data` VALUES (1139, 40, '用户组', '40', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 用户组', '103', '2022-01-12 23:34:21', '103', '2022-01-12 15:46:21', b'0'); -INSERT INTO `sys_dict_data` VALUES (1140, 50, '自定义脚本', '50', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 自定义脚本', '103', '2022-01-12 23:34:43', '103', '2022-01-12 15:46:19', b'0'); -INSERT INTO `sys_dict_data` VALUES (1141, 22, '岗位', '22', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 岗位', '103', '2022-01-14 18:41:55', '103', '2022-01-14 18:42:31', b'0'); -INSERT INTO `sys_dict_data` VALUES (1142, 10, '流程发起人', '10', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人', '103', '2022-01-15 00:10:57', '103', '2022-01-15 21:24:10', b'0'); -INSERT INTO `sys_dict_data` VALUES (1143, 20, '流程发起人的一级领导', '20', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人的一级领导', '103', '2022-01-15 21:24:31', '103', '2022-01-15 21:24:31', b'0'); -INSERT INTO `sys_dict_data` VALUES (1144, 21, '流程发起人的二级领导', '21', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人的二级领导', '103', '2022-01-15 21:24:46', '103', '2022-01-15 21:24:57', b'0'); +INSERT INTO `system_dict_data` VALUES (1, 1, '男', '1', 'system_user_sex', 0, '性别男', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:38', b'0'); +INSERT INTO `system_dict_data` VALUES (2, 2, '女', '2', 'system_user_sex', 0, '性别女', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:41', b'0'); +INSERT INTO `system_dict_data` VALUES (8, 1, '正常', '1', 'infra_job_status', 0, '正常状态', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:59:07', b'0'); +INSERT INTO `system_dict_data` VALUES (9, 2, '暂停', '2', 'infra_job_status', 0, '停用状态', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:57:08', b'0'); +INSERT INTO `system_dict_data` VALUES (12, 1, '系统内置', '1', 'infra_config_type', 0, '参数类型 - 系统内置', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:30', b'0'); +INSERT INTO `system_dict_data` VALUES (13, 2, '自定义', '2', 'infra_config_type', 0, '参数类型 - 自定义', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:28', b'0'); +INSERT INTO `system_dict_data` VALUES (14, 1, '通知', '1', 'system_notice_type', 0, '通知', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:32', b'0'); +INSERT INTO `system_dict_data` VALUES (15, 2, '公告', '2', 'system_notice_type', 0, '公告', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:25', b'0'); +INSERT INTO `system_dict_data` VALUES (16, 0, '其它', '0', 'system_operate_type', 0, '其它操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:13', b'0'); +INSERT INTO `system_dict_data` VALUES (17, 1, '查询', '1', 'system_operate_type', 0, '查询操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:16', b'0'); +INSERT INTO `system_dict_data` VALUES (18, 2, '新增', '2', 'system_operate_type', 0, '新增操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:18', b'0'); +INSERT INTO `system_dict_data` VALUES (19, 3, '修改', '3', 'system_operate_type', 0, '修改操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:19', b'0'); +INSERT INTO `system_dict_data` VALUES (20, 4, '删除', '4', 'system_operate_type', 0, '删除操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:21', b'0'); +INSERT INTO `system_dict_data` VALUES (22, 5, '导出', '5', 'system_operate_type', 0, '导出操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:22', b'0'); +INSERT INTO `system_dict_data` VALUES (23, 6, '导入', '6', 'system_operate_type', 0, '导入操作', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:10', b'0'); +INSERT INTO `system_dict_data` VALUES (27, 1, '开启', '0', 'common_status', 0, '开启状态', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:04', b'0'); +INSERT INTO `system_dict_data` VALUES (28, 2, '关闭', '1', 'common_status', 0, '关闭状态', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:08', b'0'); +INSERT INTO `system_dict_data` VALUES (29, 1, '目录', '1', 'system_menu_type', 0, '目录', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:45', b'0'); +INSERT INTO `system_dict_data` VALUES (30, 2, '菜单', '2', 'system_menu_type', 0, '菜单', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:41', b'0'); +INSERT INTO `system_dict_data` VALUES (31, 3, '按钮', '3', 'system_menu_type', 0, '按钮', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:39', b'0'); +INSERT INTO `system_dict_data` VALUES (32, 1, '内置', '1', 'system_role_type', 0, '内置角色', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:03', b'0'); +INSERT INTO `system_dict_data` VALUES (33, 2, '自定义', '2', 'system_role_type', 0, '自定义角色', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:43:06', b'0'); +INSERT INTO `system_dict_data` VALUES (34, 1, '全部数据权限', '1', 'system_data_scope', 0, '全部数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:17', b'0'); +INSERT INTO `system_dict_data` VALUES (35, 2, '指定部门数据权限', '2', 'system_data_scope', 0, '指定部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:18', b'0'); +INSERT INTO `system_dict_data` VALUES (36, 3, '本部门数据权限', '3', 'system_data_scope', 0, '本部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:16', b'0'); +INSERT INTO `system_dict_data` VALUES (37, 4, '本部门及以下数据权限', '4', 'system_data_scope', 0, '本部门及以下数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:21', b'0'); +INSERT INTO `system_dict_data` VALUES (38, 5, '仅本人数据权限', '5', 'system_data_scope', 0, '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:47:23', b'0'); +INSERT INTO `system_dict_data` VALUES (39, 0, '成功', '0', 'system_login_result', 0, '登陆结果 - 成功', '', '2021-01-18 06:17:36', '', '2022-02-01 16:44:30', b'0'); +INSERT INTO `system_dict_data` VALUES (40, 10, '账号或密码不正确', '10', 'system_login_result', 0, '登陆结果 - 账号或密码不正确', '', '2021-01-18 06:17:54', '', '2022-02-01 16:44:26', b'0'); +INSERT INTO `system_dict_data` VALUES (41, 20, '用户被禁用', '20', 'system_login_result', 0, '登陆结果 - 用户被禁用', '', '2021-01-18 06:17:54', '', '2022-02-01 16:44:24', b'0'); +INSERT INTO `system_dict_data` VALUES (42, 30, '验证码不存在', '30', 'system_login_result', 0, '登陆结果 - 验证码不存在', '', '2021-01-18 06:17:54', '', '2022-02-01 16:44:23', b'0'); +INSERT INTO `system_dict_data` VALUES (43, 31, '验证码不正确', '31', 'system_login_result', 0, '登陆结果 - 验证码不正确', '', '2021-01-18 06:17:54', '', '2022-02-01 16:44:19', b'0'); +INSERT INTO `system_dict_data` VALUES (44, 100, '未知异常', '100', 'system_login_result', 0, '登陆结果 - 未知异常', '', '2021-01-18 06:17:54', '', '2022-02-01 16:44:17', b'0'); +INSERT INTO `system_dict_data` VALUES (45, 1, '是', 'true', 'infra_boolean_string', 0, 'Boolean 是否类型 - 是', '', '2021-01-19 03:20:55', '', '2022-02-01 16:47:38', b'0'); +INSERT INTO `system_dict_data` VALUES (46, 1, '否', 'false', 'infra_boolean_string', 0, 'Boolean 是否类型 - 否', '', '2021-01-19 03:20:55', '', '2022-02-01 16:47:35', b'0'); +INSERT INTO `system_dict_data` VALUES (47, 1, '永不超时', '1', 'infra_redis_timeout_type', 0, 'Redis 未设置超时的情况', '', '2021-01-26 00:53:17', '', '2022-02-01 16:48:09', b'0'); +INSERT INTO `system_dict_data` VALUES (48, 1, '动态超时', '2', 'infra_redis_timeout_type', 0, '程序里动态传入超时时间,无法固定', '', '2021-01-26 00:55:00', '', '2022-02-01 16:48:06', b'0'); +INSERT INTO `system_dict_data` VALUES (49, 3, '固定超时', '3', 'infra_redis_timeout_type', 0, 'Redis 设置了过期时间', '', '2021-01-26 00:55:26', '', '2022-02-01 16:48:01', b'0'); +INSERT INTO `system_dict_data` VALUES (50, 1, '单表(增删改查)', '1', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:09:06', '', '2021-02-05 07:21:52', b'0'); +INSERT INTO `system_dict_data` VALUES (51, 2, '树表(增删改查)', '2', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:14:46', '', '2021-02-05 07:21:49', b'0'); +INSERT INTO `system_dict_data` VALUES (52, 3, '主子表(增删改查)', '3', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:21:45', '', '2021-02-06 18:54:26', b'1'); +INSERT INTO `system_dict_data` VALUES (53, 0, '初始化中', '0', 'infra_job_status', 0, NULL, '', '2021-02-07 07:46:49', '', '2022-02-01 16:47:57', b'0'); +INSERT INTO `system_dict_data` VALUES (57, 0, '运行中', '0', 'infra_job_log_status', 0, 'RUNNING', '', '2021-02-08 10:04:24', '', '2022-02-01 16:48:54', b'0'); +INSERT INTO `system_dict_data` VALUES (58, 1, '成功', '1', 'infra_job_log_status', 0, NULL, '', '2021-02-08 10:06:57', '', '2022-02-01 16:48:58', b'0'); +INSERT INTO `system_dict_data` VALUES (59, 2, '失败', '2', 'infra_job_log_status', 0, '失败', '', '2021-02-08 10:07:38', '', '2022-02-01 16:49:02', b'0'); +INSERT INTO `system_dict_data` VALUES (60, 1, '会员', '1', 'user_type', 0, NULL, '', '2021-02-26 00:16:27', '', '2021-02-26 00:16:27', b'0'); +INSERT INTO `system_dict_data` VALUES (61, 2, '管理员', '2', 'user_type', 0, NULL, '', '2021-02-26 00:16:34', '', '2021-02-26 00:16:34', b'0'); +INSERT INTO `system_dict_data` VALUES (62, 0, '未处理', '0', 'infra_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:19', '', '2022-02-01 16:49:05', b'0'); +INSERT INTO `system_dict_data` VALUES (63, 1, '已处理', '1', 'infra_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:26', '', '2022-02-01 16:49:09', b'0'); +INSERT INTO `system_dict_data` VALUES (64, 2, '已忽略', '2', 'infra_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:34', '', '2022-02-01 16:49:12', b'0'); +INSERT INTO `system_dict_data` VALUES (65, 1, '云片', 'YUN_PIAN', 'system_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:14', '1', '2022-02-01 16:39:36', b'0'); +INSERT INTO `system_dict_data` VALUES (66, 2, '阿里云', 'ALIYUN', 'system_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:26', '1', '2022-02-01 16:39:41', b'0'); +INSERT INTO `system_dict_data` VALUES (67, 1, '验证码', '1', 'system_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:57', '1', '2022-02-01 16:37:27', b'0'); +INSERT INTO `system_dict_data` VALUES (68, 2, '通知', '2', 'system_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:08', '1', '2022-02-01 16:37:33', b'0'); +INSERT INTO `system_dict_data` VALUES (69, 0, '营销', '3', 'system_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:15', '1', '2022-02-01 16:37:40', b'0'); +INSERT INTO `system_dict_data` VALUES (70, 0, '初始化', '0', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:33', '1', '2022-02-01 16:38:58', b'0'); +INSERT INTO `system_dict_data` VALUES (71, 1, '发送成功', '10', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:43', '1', '2022-02-01 16:39:02', b'0'); +INSERT INTO `system_dict_data` VALUES (72, 2, '发送失败', '20', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:49', '1', '2022-02-01 16:39:07', b'0'); +INSERT INTO `system_dict_data` VALUES (73, 3, '不发送', '30', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:19:44', '1', '2022-02-01 16:39:13', b'0'); +INSERT INTO `system_dict_data` VALUES (74, 0, '等待结果', '0', 'system_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:43', '1', '2022-02-01 16:39:19', b'0'); +INSERT INTO `system_dict_data` VALUES (75, 1, '接收成功', '10', 'system_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:25', '1', '2022-02-01 16:39:23', b'0'); +INSERT INTO `system_dict_data` VALUES (76, 2, '接收失败', '20', 'system_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:31', '1', '2022-02-01 16:39:29', b'0'); +INSERT INTO `system_dict_data` VALUES (77, 0, '调试(钉钉)', 'DEBUG_DING_TALK', 'system_sms_channel_code', 0, NULL, '1', '2021-04-13 00:20:37', '1', '2022-02-01 16:39:47', b'0'); +INSERT INTO `system_dict_data` VALUES (78, 1, '自动生成', '1', 'system_error_code_type', 0, NULL, '1', '2021-04-21 00:06:48', '1', '2022-02-01 16:47:11', b'0'); +INSERT INTO `system_dict_data` VALUES (79, 2, '手动编辑', '2', 'system_error_code_type', 0, NULL, '1', '2021-04-21 00:07:14', '1', '2022-02-01 16:47:10', b'0'); +INSERT INTO `system_dict_data` VALUES (80, 100, '账号登录', '100', 'system_login_type', 0, '账号登录', '1', '2021-10-06 00:52:02', '1', '2022-02-01 16:43:50', b'0'); +INSERT INTO `system_dict_data` VALUES (81, 101, '社交登录', '101', 'system_login_type', 0, '社交登录', '1', '2021-10-06 00:52:17', '1', '2022-02-01 16:43:51', b'0'); +INSERT INTO `system_dict_data` VALUES (82, 102, 'Mock 登录', '102', 'system_login_type', 0, 'Mock 登录', '1', '2021-10-06 00:52:32', '1', '2022-02-01 16:43:54', b'0'); +INSERT INTO `system_dict_data` VALUES (83, 200, '主动登出', '200', 'system_login_type', 0, '主动登出', '1', '2021-10-06 00:52:58', '1', '2022-02-01 16:43:55', b'0'); +INSERT INTO `system_dict_data` VALUES (84, 201, '超时登出', '201', 'system_login_type', 0, '超时登出', '1', '2021-10-06 00:53:17', '1', '2022-02-01 16:43:56', b'0'); +INSERT INTO `system_dict_data` VALUES (85, 202, '强制登出', '202', 'system_login_type', 0, '强制退出', '1', '2021-10-06 00:53:41', '1', '2022-02-01 16:43:58', b'0'); +INSERT INTO `system_dict_data` VALUES (86, 0, '病假', '1', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:35:28', '1', '2022-01-22 10:42:08', b'0'); +INSERT INTO `system_dict_data` VALUES (87, 1, '事假', '2', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:36:11', '1', '2022-01-22 10:42:11', b'0'); +INSERT INTO `system_dict_data` VALUES (88, 2, '婚假', '3', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:36:38', '1', '2022-01-22 10:42:16', b'0'); +INSERT INTO `system_dict_data` VALUES (98, 1, 'v2', 'v2', 'pay_channel_wechat_version', 0, 'v2版本', '1', '2021-11-08 17:00:58', '1', '2021-11-08 17:00:58', b'0'); +INSERT INTO `system_dict_data` VALUES (99, 2, 'v3', 'v3', 'pay_channel_wechat_version', 0, 'v3版本', '1', '2021-11-08 17:01:07', '1', '2021-11-08 17:01:07', b'0'); +INSERT INTO `system_dict_data` VALUES (108, 1, 'RSA2', 'RSA2', 'pay_channel_alipay_sign_type', 0, 'RSA2', '1', '2021-11-18 15:39:29', '1', '2021-11-18 15:39:29', b'0'); +INSERT INTO `system_dict_data` VALUES (109, 1, '公钥模式', '1', 'pay_channel_alipay_mode', 0, '公钥模式:privateKey + alipayPublicKey', '1', '2021-11-18 15:45:23', '1', '2021-11-18 15:45:23', b'0'); +INSERT INTO `system_dict_data` VALUES (110, 2, '证书模式', '2', 'pay_channel_alipay_mode', 0, '证书模式:appCertContent + alipayPublicCertContent + rootCertContent', '1', '2021-11-18 15:45:40', '1', '2021-11-18 15:45:40', b'0'); +INSERT INTO `system_dict_data` VALUES (111, 1, '线上', 'https://openapi.alipay.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 线上', '1', '2021-11-18 16:59:32', '1', '2021-11-21 17:37:29', b'0'); +INSERT INTO `system_dict_data` VALUES (112, 2, '沙箱', 'https://openapi.alipaydev.com/gateway.do', 'pay_channel_alipay_server_type', 0, '网关地址 - 沙箱', '1', '2021-11-18 16:59:48', '1', '2021-11-21 17:37:39', b'0'); +INSERT INTO `system_dict_data` VALUES (113, 1, '微信 JSAPI 支付', 'wx_pub', 'pay_channel_code_type', 0, '微信 JSAPI(公众号) 支付', '1', '2021-12-03 10:40:24', '1', '2021-12-04 16:41:00', b'0'); +INSERT INTO `system_dict_data` VALUES (114, 2, '微信小程序支付', 'wx_lite', 'pay_channel_code_type', 0, '微信小程序支付', '1', '2021-12-03 10:41:06', '1', '2021-12-03 10:41:06', b'0'); +INSERT INTO `system_dict_data` VALUES (115, 3, '微信 App 支付', 'wx_app', 'pay_channel_code_type', 0, '微信 App 支付', '1', '2021-12-03 10:41:20', '1', '2021-12-03 10:41:20', b'0'); +INSERT INTO `system_dict_data` VALUES (116, 4, '支付宝 PC 网站支付', 'alipay_pc', 'pay_channel_code_type', 0, '支付宝 PC 网站支付', '1', '2021-12-03 10:42:09', '1', '2021-12-03 10:42:09', b'0'); +INSERT INTO `system_dict_data` VALUES (117, 5, '支付宝 Wap 网站支付', 'alipay_wap', 'pay_channel_code_type', 0, '支付宝 Wap 网站支付', '1', '2021-12-03 10:42:26', '1', '2021-12-03 10:42:26', b'0'); +INSERT INTO `system_dict_data` VALUES (118, 6, '支付宝App 支付', 'alipay_app', 'pay_channel_code_type', 0, '支付宝App 支付', '1', '2021-12-03 10:42:55', '1', '2021-12-03 10:42:55', b'0'); +INSERT INTO `system_dict_data` VALUES (119, 7, '支付宝扫码支付', 'alipay_qr', 'pay_channel_code_type', 0, '支付宝扫码支付', '1', '2021-12-03 10:43:10', '1', '2021-12-03 10:43:10', b'0'); +INSERT INTO `system_dict_data` VALUES (120, 1, '通知成功', '10', 'pay_order_notify_status', 0, '通知成功', '1', '2021-12-03 11:02:41', '1', '2021-12-03 11:02:41', b'0'); +INSERT INTO `system_dict_data` VALUES (121, 2, '通知失败', '20', 'pay_order_notify_status', 0, '通知失败', '1', '2021-12-03 11:02:59', '1', '2021-12-03 11:02:59', b'0'); +INSERT INTO `system_dict_data` VALUES (122, 3, '未通知', '0', 'pay_order_notify_status', 0, '未通知', '1', '2021-12-03 11:03:10', '1', '2021-12-03 11:03:10', b'0'); +INSERT INTO `system_dict_data` VALUES (123, 1, '支付成功', '10', 'pay_order_status', 0, '支付成功', '1', '2021-12-03 11:18:29', '1', '2021-12-03 11:28:32', b'0'); +INSERT INTO `system_dict_data` VALUES (124, 2, '支付关闭', '20', 'pay_order_status', 0, '支付关闭', '1', '2021-12-03 11:18:42', '1', '2021-12-03 11:28:34', b'0'); +INSERT INTO `system_dict_data` VALUES (125, 3, '未支付', '0', 'pay_order_status', 0, '未支付', '1', '2021-12-03 11:18:18', '1', '2021-12-03 11:28:36', b'0'); +INSERT INTO `system_dict_data` VALUES (126, 1, '未退款', '0', 'pay_order_refund_status', 0, '未退款', '1', '2021-12-03 11:30:35', '1', '2021-12-03 11:34:05', b'0'); +INSERT INTO `system_dict_data` VALUES (127, 2, '部分退款', '10', 'pay_order_refund_status', 0, '部分退款', '1', '2021-12-03 11:30:44', '1', '2021-12-03 11:34:10', b'0'); +INSERT INTO `system_dict_data` VALUES (128, 3, '全部退款', '20', 'pay_order_refund_status', 0, '全部退款', '1', '2021-12-03 11:30:52', '1', '2021-12-03 11:34:14', b'0'); +INSERT INTO `system_dict_data` VALUES (1117, 1, '退款订单生成', '0', 'pay_refund_order_status', 0, '退款订单生成', '1', '2021-12-10 16:44:44', '1', '2021-12-10 16:44:44', b'0'); +INSERT INTO `system_dict_data` VALUES (1118, 2, '退款成功', '1', 'pay_refund_order_status', 0, '退款成功', '1', '2021-12-10 16:44:59', '1', '2021-12-10 16:44:59', b'0'); +INSERT INTO `system_dict_data` VALUES (1119, 3, '退款失败', '2', 'pay_refund_order_status', 0, '退款失败', '1', '2021-12-10 16:45:10', '1', '2021-12-10 16:45:10', b'0'); +INSERT INTO `system_dict_data` VALUES (1120, 4, '退款中, 渠道通知结果', '3', 'pay_refund_order_status', 0, '退款中, 渠道通知结果', '1', '2021-12-10 16:45:32', '1', '2021-12-10 16:45:32', b'0'); +INSERT INTO `system_dict_data` VALUES (1121, 5, '退款中, 系统查询结果', '4', 'pay_refund_order_status', 0, '退款中, 系统查询结果', '1', '2021-12-10 16:45:48', '1', '2021-12-10 16:45:48', b'0'); +INSERT INTO `system_dict_data` VALUES (1122, 6, '状态未知,需要重试', '5', 'pay_refund_order_status', 0, '状态未知,需要重试', '1', '2021-12-10 16:46:03', '1', '2021-12-10 16:46:03', b'0'); +INSERT INTO `system_dict_data` VALUES (1123, 7, '状态未知,系统查询结果', '6', 'pay_refund_order_status', 0, '状态未知,系统查询结果', '1', '2021-12-10 16:46:13', '1', '2021-12-10 16:46:13', b'0'); +INSERT INTO `system_dict_data` VALUES (1124, 8, '退款关闭', '99', 'pay_refund_order_status', 0, '退款关闭', '1', '2021-12-10 16:46:26', '1', '2021-12-10 16:46:26', b'0'); +INSERT INTO `system_dict_data` VALUES (1125, 0, '默认', '1', 'bpm_model_category', 0, '流程分类 - 默认', '1', '2022-01-02 08:41:11', '1', '2022-01-02 08:41:11', b'0'); +INSERT INTO `system_dict_data` VALUES (1126, 0, 'OA', '2', 'bpm_model_category', 0, '流程分类 - OA', '1', '2022-01-02 08:41:22', '1', '2022-01-02 08:41:22', b'0'); +INSERT INTO `system_dict_data` VALUES (1127, 0, '进行中', '1', 'bpm_process_instance_status', 0, '流程实例的状态 - 进行中', '1', '2022-01-07 23:47:22', '1', '2022-01-09 08:59:34', b'0'); +INSERT INTO `system_dict_data` VALUES (1128, 2, '已完成', '2', 'bpm_process_instance_status', 0, '流程实例的状态 - 已完成', '1', '2022-01-07 23:47:49', '1', '2022-01-07 23:47:49', b'0'); +INSERT INTO `system_dict_data` VALUES (1129, 1, '处理中', '1', 'bpm_process_instance_result', 0, '流程实例的结果 - 处理中', '1', '2022-01-07 23:48:32', '1', '2022-01-07 23:48:32', b'0'); +INSERT INTO `system_dict_data` VALUES (1130, 2, '通过', '2', 'bpm_process_instance_result', 0, '流程实例的结果 - 通过', '1', '2022-01-07 23:48:45', '1', '2022-01-07 23:48:45', b'0'); +INSERT INTO `system_dict_data` VALUES (1131, 3, '不通过', '3', 'bpm_process_instance_result', 0, '流程实例的结果 - 不通过', '1', '2022-01-07 23:48:55', '1', '2022-01-07 23:48:55', b'0'); +INSERT INTO `system_dict_data` VALUES (1132, 4, '已取消', '4', 'bpm_process_instance_result', 0, '流程实例的结果 - 撤销', '1', '2022-01-07 23:49:06', '1', '2022-01-08 13:21:14', b'0'); +INSERT INTO `system_dict_data` VALUES (1133, 10, '流程表单', '10', 'bpm_model_form_type', 0, '流程的表单类型 - 流程表单', '103', '2022-01-11 23:51:30', '103', '2022-01-11 23:51:30', b'0'); +INSERT INTO `system_dict_data` VALUES (1134, 20, '业务表单', '20', 'bpm_model_form_type', 0, '流程的表单类型 - 业务表单', '103', '2022-01-11 23:51:47', '103', '2022-01-11 23:51:47', b'0'); +INSERT INTO `system_dict_data` VALUES (1135, 10, '角色', '10', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 角色', '103', '2022-01-12 23:21:22', '103', '2022-01-12 15:46:30', b'0'); +INSERT INTO `system_dict_data` VALUES (1136, 20, '部门的成员', '20', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 部门的成员', '103', '2022-01-12 23:21:47', '103', '2022-01-12 15:46:26', b'0'); +INSERT INTO `system_dict_data` VALUES (1137, 21, '部门的负责人', '21', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 部门的负责人', '103', '2022-01-12 23:33:36', '103', '2022-01-12 15:46:24', b'0'); +INSERT INTO `system_dict_data` VALUES (1138, 30, '用户', '30', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 用户', '103', '2022-01-12 23:34:02', '103', '2022-01-12 15:46:22', b'0'); +INSERT INTO `system_dict_data` VALUES (1139, 40, '用户组', '40', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 用户组', '103', '2022-01-12 23:34:21', '103', '2022-01-12 15:46:21', b'0'); +INSERT INTO `system_dict_data` VALUES (1140, 50, '自定义脚本', '50', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 自定义脚本', '103', '2022-01-12 23:34:43', '103', '2022-01-12 15:46:19', b'0'); +INSERT INTO `system_dict_data` VALUES (1141, 22, '岗位', '22', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型 - 岗位', '103', '2022-01-14 18:41:55', '103', '2022-01-14 18:42:31', b'0'); +INSERT INTO `system_dict_data` VALUES (1142, 10, '流程发起人', '10', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人', '103', '2022-01-15 00:10:57', '103', '2022-01-15 21:24:10', b'0'); +INSERT INTO `system_dict_data` VALUES (1143, 20, '流程发起人的一级领导', '20', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人的一级领导', '103', '2022-01-15 21:24:31', '103', '2022-01-15 21:24:31', b'0'); +INSERT INTO `system_dict_data` VALUES (1144, 21, '流程发起人的二级领导', '21', 'bpm_task_assign_script', 0, '任务分配自定义脚本 - 流程发起人的二级领导', '103', '2022-01-15 21:24:46', '103', '2022-01-15 21:24:57', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_dict_type +-- Table structure for system_dict_type -- ---------------------------- -DROP TABLE IF EXISTS `sys_dict_type`; -CREATE TABLE `sys_dict_type` ( +DROP TABLE IF EXISTS `system_dict_type`; +CREATE TABLE `system_dict_type` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典名称', `type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典类型', @@ -1622,58 +2040,52 @@ CREATE TABLE `sys_dict_type` ( ) ENGINE=InnoDB AUTO_INCREMENT=144 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典类型表'; -- ---------------------------- --- Records of sys_dict_type +-- Records of system_dict_type -- ---------------------------- BEGIN; -INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0'); -INSERT INTO `sys_dict_type` VALUES (3, '系统开关', 'sys_normal_disable', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-07 19:47:48', b'1'); -INSERT INTO `sys_dict_type` VALUES (4, '任务状态的枚举', 'sys_job_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:44:06', b'1'); -INSERT INTO `sys_dict_type` VALUES (5, '任务分组', 'sys_job_group', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 07:43:52', b'1'); -INSERT INTO `sys_dict_type` VALUES (6, '参数类型', 'sys_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 07:41:04', b'0'); -INSERT INTO `sys_dict_type` VALUES (7, '通知类型', 'sys_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0'); -INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0'); -INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0'); -INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 17:03:48', b'0'); -INSERT INTO `sys_dict_type` VALUES (11, 'Boolean 是否类型', 'sys_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2021-01-19 03:20:08', b'0'); -INSERT INTO `sys_dict_type` VALUES (104, '登陆结果', 'sys_login_result', 0, '登陆结果', '', '2021-01-18 06:17:11', '', '2021-01-18 06:17:11', b'0'); -INSERT INTO `sys_dict_type` VALUES (105, 'Redis 超时类型', 'inf_redis_timeout_type', 0, 'RedisKeyDefine.TimeoutTypeEnum', '', '2021-01-26 00:52:50', '', '2021-01-26 00:52:50', b'0'); -INSERT INTO `sys_dict_type` VALUES (106, '代码生成模板类型', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:08:06', '', '2021-02-05 07:08:06', b'0'); -INSERT INTO `sys_dict_type` VALUES (107, '定时任务状态', 'inf_job_status', 0, NULL, '', '2021-02-07 07:44:16', '', '2021-02-07 07:44:16', b'0'); -INSERT INTO `sys_dict_type` VALUES (108, '定时任务日志状态', 'inf_job_log_status', 0, NULL, '', '2021-02-08 10:03:51', '', '2021-02-08 10:03:51', b'0'); -INSERT INTO `sys_dict_type` VALUES (109, '用户类型', 'user_type', 0, NULL, '', '2021-02-26 00:15:51', '', '2021-02-26 00:15:51', b'0'); -INSERT INTO `sys_dict_type` VALUES (110, 'API 异常数据的处理状态', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:01', '', '2021-02-26 07:07:01', b'0'); -INSERT INTO `sys_dict_type` VALUES (111, '短信渠道编码', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:04:50', '1', '2021-04-05 01:04:50', b'0'); -INSERT INTO `sys_dict_type` VALUES (112, '短信模板的类型', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:43', '1', '2021-04-05 21:50:43', b'0'); -INSERT INTO `sys_dict_type` VALUES (113, '短信发送状态', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2021-04-11 09:30:02', b'0'); -INSERT INTO `sys_dict_type` VALUES (114, '短信接收状态', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2021-04-11 20:27:14', b'0'); -INSERT INTO `sys_dict_type` VALUES (115, '错误码的类型', 'sys_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2021-04-13 22:07:12', b'0'); -INSERT INTO `sys_dict_type` VALUES (116, '登陆日志的类型', 'sys_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2021-10-06 00:50:46', b'0'); -INSERT INTO `sys_dict_type` VALUES (117, 'OA 请假类型', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:34:33', '1', '2022-01-22 10:41:37', b'0'); -INSERT INTO `sys_dict_type` VALUES (118, '请假流程状态', 'oa_leave_status', 0, NULL, '1', '2021-09-21 22:46:04', '1', '2022-01-22 10:40:46', b'1'); -INSERT INTO `sys_dict_type` VALUES (122, '支付渠道微信版本', 'pay_channel_wechat_version', 0, '支付渠道微信版本', '1', '2021-11-08 17:00:26', '1', '2021-11-08 17:00:26', b'0'); -INSERT INTO `sys_dict_type` VALUES (127, '支付渠道支付宝算法类型', 'pay_channel_alipay_sign_type', 0, '支付渠道支付宝算法类型', '1', '2021-11-18 15:39:09', '1', '2021-11-18 15:39:09', b'0'); -INSERT INTO `sys_dict_type` VALUES (128, '支付渠道支付宝公钥类型', 'pay_channel_alipay_mode', 0, '支付渠道支付宝公钥类型', '1', '2021-11-18 15:44:28', '1', '2021-11-18 15:44:28', b'0'); -INSERT INTO `sys_dict_type` VALUES (129, '支付宝网关地址', 'pay_channel_alipay_server_type', 0, '支付宝网关地址', '1', '2021-11-18 16:58:55', '1', '2021-11-18 17:01:34', b'0'); -INSERT INTO `sys_dict_type` VALUES (130, '支付渠道编码类型', 'pay_channel_code_type', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2021-12-03 10:35:08', b'0'); -INSERT INTO `sys_dict_type` VALUES (131, '支付订单回调状态', 'pay_order_notify_status', 0, '支付订单回调状态', '1', '2021-12-03 10:53:29', '1', '2021-12-03 10:53:29', b'0'); -INSERT INTO `sys_dict_type` VALUES (132, '支付订单状态', 'pay_order_status', 0, '支付订单状态', '1', '2021-12-03 11:17:50', '1', '2021-12-03 11:17:50', b'0'); -INSERT INTO `sys_dict_type` VALUES (133, '支付订单退款状态', 'pay_order_refund_status', 0, '支付订单退款状态', '1', '2021-12-03 11:27:31', '1', '2021-12-03 11:27:31', b'0'); -INSERT INTO `sys_dict_type` VALUES (134, '退款订单状态', 'pay_refund_order_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2021-12-10 16:42:50', b'0'); -INSERT INTO `sys_dict_type` VALUES (135, '退款订单类别', 'pay_refund_order_type', 0, '退款订单类别', '1', '2021-12-10 17:14:53', '1', '2021-12-10 17:14:53', b'0'); -INSERT INTO `sys_dict_type` VALUES (137, '流程分类', '流程分类', 0, '流程分类', '1', '2022-01-02 08:40:17', '1', '2022-01-02 00:40:34', b'1'); -INSERT INTO `sys_dict_type` VALUES (138, '流程分类', 'bpm_model_category', 0, '流程分类', '1', '2022-01-02 08:40:45', '1', '2022-01-02 08:40:45', b'0'); -INSERT INTO `sys_dict_type` VALUES (139, '流程实例的状态', 'bpm_process_instance_status', 0, '流程实例的状态', '1', '2022-01-07 23:46:42', '1', '2022-01-07 23:46:42', b'0'); -INSERT INTO `sys_dict_type` VALUES (140, '流程实例的结果', 'bpm_process_instance_result', 0, '流程实例的结果', '1', '2022-01-07 23:48:10', '1', '2022-01-07 23:48:10', b'0'); -INSERT INTO `sys_dict_type` VALUES (141, '流程的表单类型', 'bpm_model_form_type', 0, '流程的表单类型', '103', '2022-01-11 23:50:45', '103', '2022-01-11 23:50:45', b'0'); -INSERT INTO `sys_dict_type` VALUES (142, '任务分配规则的类型', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型', '103', '2022-01-12 23:21:04', '103', '2022-01-12 15:46:10', b'0'); -INSERT INTO `sys_dict_type` VALUES (143, '任务分配自定义脚本', 'bpm_task_assign_script', 0, '任务分配自定义脚本', '103', '2022-01-15 00:10:35', '103', '2022-01-15 00:10:35', b'0'); +INSERT INTO `system_dict_type` VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:31', b'0'); +INSERT INTO `system_dict_type` VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', b'0'); +INSERT INTO `system_dict_type` VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', b'0'); +INSERT INTO `system_dict_type` VALUES (9, '操作类型', 'system_oper_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:22', b'0'); +INSERT INTO `system_dict_type` VALUES (10, '系统状态', 'common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:28', b'0'); +INSERT INTO `system_dict_type` VALUES (11, 'Boolean 是否类型', 'infra_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2022-02-01 16:37:10', b'0'); +INSERT INTO `system_dict_type` VALUES (104, '登陆结果', 'system_login_result', 0, '登陆结果', '', '2021-01-18 06:17:11', '', '2022-02-01 16:36:00', b'0'); +INSERT INTO `system_dict_type` VALUES (105, 'Redis 超时类型', 'infra_redis_timeout_type', 0, 'RedisKeyDefine.TimeoutTypeEnum', '', '2021-01-26 00:52:50', '', '2022-02-01 16:50:29', b'0'); +INSERT INTO `system_dict_type` VALUES (106, '代码生成模板类型', 'tool_codegen_template_type', 0, NULL, '', '2021-02-05 07:08:06', '', '2021-02-05 07:08:06', b'0'); +INSERT INTO `system_dict_type` VALUES (107, '定时任务状态', 'infra_job_status', 0, NULL, '', '2021-02-07 07:44:16', '', '2022-02-01 16:51:11', b'0'); +INSERT INTO `system_dict_type` VALUES (108, '定时任务日志状态', 'infra_job_log_status', 0, NULL, '', '2021-02-08 10:03:51', '', '2022-02-01 16:50:43', b'0'); +INSERT INTO `system_dict_type` VALUES (109, '用户类型', 'user_type', 0, NULL, '', '2021-02-26 00:15:51', '', '2021-02-26 00:15:51', b'0'); +INSERT INTO `system_dict_type` VALUES (110, 'API 异常数据的处理状态', 'infra_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:01', '', '2022-02-01 16:50:53', b'0'); +INSERT INTO `system_dict_type` VALUES (111, '短信渠道编码', 'sytems_sms_channel_code', 0, NULL, '1', '2021-04-05 01:04:50', '1', '2022-02-01 16:35:18', b'0'); +INSERT INTO `system_dict_type` VALUES (112, '短信模板的类型', 'system_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:43', '1', '2022-02-01 16:35:06', b'0'); +INSERT INTO `system_dict_type` VALUES (113, '短信发送状态', 'system_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2022-02-01 16:35:09', b'0'); +INSERT INTO `system_dict_type` VALUES (114, '短信接收状态', 'system_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2022-02-01 16:35:14', b'0'); +INSERT INTO `system_dict_type` VALUES (115, '错误码的类型', 'system_error_code_type', 0, NULL, '1', '2021-04-21 00:06:30', '1', '2022-02-01 16:36:49', b'0'); +INSERT INTO `system_dict_type` VALUES (116, '登陆日志的类型', 'system_login_type', 0, '登陆日志的类型', '1', '2021-10-06 00:50:46', '1', '2022-02-01 16:35:56', b'0'); +INSERT INTO `system_dict_type` VALUES (117, 'OA 请假类型', 'bpm_oa_leave_type', 0, NULL, '1', '2021-09-21 22:34:33', '1', '2022-01-22 10:41:37', b'0'); +INSERT INTO `system_dict_type` VALUES (122, '支付渠道微信版本', 'pay_channel_wechat_version', 0, '支付渠道微信版本', '1', '2021-11-08 17:00:26', '1', '2021-11-08 17:00:26', b'0'); +INSERT INTO `system_dict_type` VALUES (127, '支付渠道支付宝算法类型', 'pay_channel_alipay_sign_type', 0, '支付渠道支付宝算法类型', '1', '2021-11-18 15:39:09', '1', '2021-11-18 15:39:09', b'0'); +INSERT INTO `system_dict_type` VALUES (128, '支付渠道支付宝公钥类型', 'pay_channel_alipay_mode', 0, '支付渠道支付宝公钥类型', '1', '2021-11-18 15:44:28', '1', '2021-11-18 15:44:28', b'0'); +INSERT INTO `system_dict_type` VALUES (129, '支付宝网关地址', 'pay_channel_alipay_server_type', 0, '支付宝网关地址', '1', '2021-11-18 16:58:55', '1', '2021-11-18 17:01:34', b'0'); +INSERT INTO `system_dict_type` VALUES (130, '支付渠道编码类型', 'pay_channel_code_type', 0, '支付渠道的编码', '1', '2021-12-03 10:35:08', '1', '2021-12-03 10:35:08', b'0'); +INSERT INTO `system_dict_type` VALUES (131, '支付订单回调状态', 'pay_order_notify_status', 0, '支付订单回调状态', '1', '2021-12-03 10:53:29', '1', '2021-12-03 10:53:29', b'0'); +INSERT INTO `system_dict_type` VALUES (132, '支付订单状态', 'pay_order_status', 0, '支付订单状态', '1', '2021-12-03 11:17:50', '1', '2021-12-03 11:17:50', b'0'); +INSERT INTO `system_dict_type` VALUES (133, '支付订单退款状态', 'pay_order_refund_status', 0, '支付订单退款状态', '1', '2021-12-03 11:27:31', '1', '2021-12-03 11:27:31', b'0'); +INSERT INTO `system_dict_type` VALUES (134, '退款订单状态', 'pay_refund_order_status', 0, '退款订单状态', '1', '2021-12-10 16:42:50', '1', '2021-12-10 16:42:50', b'0'); +INSERT INTO `system_dict_type` VALUES (135, '退款订单类别', 'pay_refund_order_type', 0, '退款订单类别', '1', '2021-12-10 17:14:53', '1', '2021-12-10 17:14:53', b'0'); +INSERT INTO `system_dict_type` VALUES (138, '流程分类', 'bpm_model_category', 0, '流程分类', '1', '2022-01-02 08:40:45', '1', '2022-01-02 08:40:45', b'0'); +INSERT INTO `system_dict_type` VALUES (139, '流程实例的状态', 'bpm_process_instance_status', 0, '流程实例的状态', '1', '2022-01-07 23:46:42', '1', '2022-01-07 23:46:42', b'0'); +INSERT INTO `system_dict_type` VALUES (140, '流程实例的结果', 'bpm_process_instance_result', 0, '流程实例的结果', '1', '2022-01-07 23:48:10', '1', '2022-01-07 23:48:10', b'0'); +INSERT INTO `system_dict_type` VALUES (141, '流程的表单类型', 'bpm_model_form_type', 0, '流程的表单类型', '103', '2022-01-11 23:50:45', '103', '2022-01-11 23:50:45', b'0'); +INSERT INTO `system_dict_type` VALUES (142, '任务分配规则的类型', 'bpm_task_assign_rule_type', 0, '任务分配规则的类型', '103', '2022-01-12 23:21:04', '103', '2022-01-12 15:46:10', b'0'); +INSERT INTO `system_dict_type` VALUES (143, '任务分配自定义脚本', 'bpm_task_assign_script', 0, '任务分配自定义脚本', '103', '2022-01-15 00:10:35', '103', '2022-01-15 00:10:35', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_error_code +-- Table structure for system_error_code -- ---------------------------- -DROP TABLE IF EXISTS `sys_error_code`; -CREATE TABLE `sys_error_code` ( +DROP TABLE IF EXISTS `system_error_code`; +CREATE TABLE `system_error_code` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '错误码编号', `type` tinyint NOT NULL DEFAULT '0' COMMENT '错误码类型', `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', @@ -1686,121 +2098,180 @@ CREATE TABLE `sys_error_code` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=4696 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='错误码表'; +) ENGINE=InnoDB AUTO_INCREMENT=4755 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='错误码表'; -- ---------------------------- --- Records of sys_error_code +-- Records of system_error_code -- ---------------------------- BEGIN; -INSERT INTO `sys_error_code` VALUES (4594, 1, 'yudao-admin-server', 1001000001, '参数配置不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4595, 1, 'yudao-admin-server', 1001000002, '参数配置 key 重复', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4596, 1, 'yudao-admin-server', 1001000003, '不能删除类型为系统内置的参数配置', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4597, 1, 'yudao-admin-server', 1001000004, '不允许获取敏感配置到前端', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4598, 1, 'yudao-admin-server', 1001001000, '定时任务不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4599, 1, 'yudao-admin-server', 1001001001, '定时任务的处理器已经存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4600, 1, 'yudao-admin-server', 1001001002, '只允许修改为开启或者关闭状态', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4601, 1, 'yudao-admin-server', 1001001003, '定时任务已经处于该状态,无需修改', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4602, 1, 'yudao-admin-server', 1001001004, '只有开启状态的任务,才可以修改', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4603, 1, 'yudao-admin-server', 1001001005, 'CRON 表达式不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4604, 1, 'yudao-admin-server', 1001002000, 'API 错误日志不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4605, 1, 'yudao-admin-server', 1001002001, 'API 错误日志已处理', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4606, 1, 'yudao-admin-server', 1002000000, '登录失败,账号密码不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4607, 1, 'yudao-admin-server', 1002000001, '登录失败,账号被禁用', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4608, 1, 'yudao-admin-server', 1002000002, '登录失败', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4609, 1, 'yudao-admin-server', 1002000003, '验证码不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4610, 1, 'yudao-admin-server', 1002000004, '验证码不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4611, 1, 'yudao-admin-server', 1002000005, '未绑定账号,需要进行绑定', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4612, 1, 'yudao-admin-server', 1002000006, 'Token 已经过期', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4613, 1, 'yudao-admin-server', 1002002000, '已经存在该名字的菜单', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4614, 1, 'yudao-admin-server', 1002002001, '父菜单不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4615, 1, 'yudao-admin-server', 1002002002, '不能设置自己为父菜单', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); -INSERT INTO `sys_error_code` VALUES (4616, 1, 'yudao-admin-server', 1002002003, '菜单不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4617, 1, 'yudao-admin-server', 1002002004, '存在子菜单,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4618, 1, 'yudao-admin-server', 1002002005, '父菜单的类型必须是目录或者菜单', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4619, 1, 'yudao-admin-server', 1002003000, '角色不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4620, 1, 'yudao-admin-server', 1002003001, '已经存在名为【{}】的角色', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4621, 1, 'yudao-admin-server', 1002003002, '已经存在编码为【{}】的角色', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4622, 1, 'yudao-admin-server', 1002003004, '不能操作类型为系统内置的角色', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4623, 1, 'yudao-admin-server', 1002003004, '名字为【{}】的角色已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4624, 1, 'yudao-admin-server', 1002004000, '用户账号已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4625, 1, 'yudao-admin-server', 1002004001, '手机号已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4626, 1, 'yudao-admin-server', 1002004002, '邮箱已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4627, 1, 'yudao-admin-server', 1002004003, '用户不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4628, 1, 'yudao-admin-server', 1002004004, '导入用户数据不能为空!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4629, 1, 'yudao-admin-server', 1002004005, '用户密码校验失败', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4630, 1, 'yudao-admin-server', 1002003004, '名字为【{}】的用户已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4631, 1, 'yudao-admin-server', 1002004001, '已经存在该名字的部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4632, 1, 'yudao-admin-server', 1002004002, '父级部门不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4633, 1, 'yudao-admin-server', 1002004003, '当前部门不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4634, 1, 'yudao-admin-server', 1002004004, '存在子部门,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4635, 1, 'yudao-admin-server', 1002004005, '不能设置自己为父部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4636, 1, 'yudao-admin-server', 1002004006, '部门中存在员工,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4637, 1, 'yudao-admin-server', 1002004007, '部门不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4638, 1, 'yudao-admin-server', 1002004008, '不能设置自己的子部门为父部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4639, 1, 'yudao-admin-server', 1002005001, '当前岗位不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4640, 1, 'yudao-admin-server', 1002005002, '岗位({}) 不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4641, 1, 'yudao-admin-server', 1002005001, '已经存在该名字的岗位', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4642, 1, 'yudao-admin-server', 1002005001, '已经存在该标识的岗位', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4643, 1, 'yudao-admin-server', 1002006001, '当前字典类型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4644, 1, 'yudao-admin-server', 1002006002, '字典类型不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4645, 1, 'yudao-admin-server', 1002006003, '已经存在该名字的字典类型', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4646, 1, 'yudao-admin-server', 1002006004, '已经存在该类型的字典类型', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4647, 1, 'yudao-admin-server', 1002006004, '无法删除,该字典类型还有字典数据', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4648, 1, 'yudao-admin-server', 1002007001, '当前字典数据不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4649, 1, 'yudao-admin-server', 1002007002, '字典数据({})不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4650, 1, 'yudao-admin-server', 1002007003, '已经存在该值的字典数据', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4651, 1, 'yudao-admin-server', 1002008001, '当前通知公告不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4652, 1, 'yudao-admin-server', 1002009001, '文件路径已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4653, 1, 'yudao-admin-server', 1002009002, '文件上传失败', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4654, 1, 'yudao-admin-server', 1002009003, '文件为空', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4655, 1, 'yudao-admin-server', 1002011000, '短信渠道不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4656, 1, 'yudao-admin-server', 1002011001, '短信渠道不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4657, 1, 'yudao-admin-server', 1002011002, '无法删除,该短信渠道还有短信模板', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4658, 1, 'yudao-admin-server', 1002011000, '短信模板不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4659, 1, 'yudao-admin-server', 1002011001, '已经存在编码为【{}】的短信模板', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4660, 1, 'yudao-admin-server', 1002012000, '租户不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4661, 1, 'yudao-admin-server', 1002013000, '错误码不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4662, 1, 'yudao-admin-server', 1002013001, '已经存在编码为【{}】的错误码', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4663, 1, 'yudao-admin-server', 1009000002, '获取高亮流程图异常', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4664, 1, 'yudao-admin-server', 1009001001, '请假申请不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4665, 1, 'yudao-admin-server', 1009001002, '项目经理岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4666, 1, 'yudao-admin-server', 1009001009, '部门的项目经理不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4667, 1, 'yudao-admin-server', 1009001004, '部门经理岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4668, 1, 'yudao-admin-server', 1009001005, '部门的部门经理不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4669, 1, 'yudao-admin-server', 1009001006, 'HR岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4670, 1, 'yudao-admin-server', 1009001007, '请假天数必须>=1', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4671, 1, 'yudao-admin-server', 1009002000, '已经存在流程标识为【{}】的流程', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4672, 1, 'yudao-admin-server', 1009002001, '流程模型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4673, 1, 'yudao-admin-server', 1009002002, '流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4674, 1, 'yudao-admin-server', 1009002003, '部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4675, 1, 'yudao-admin-server', 1009002004, '部署流程失败,原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4676, 1, 'yudao-admin-server', 1009003005, '流程定义部署失败,原因:信息未发生变化', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4677, 1, 'yudao-admin-server', 1009003000, '流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4678, 1, 'yudao-admin-server', 1009003001, '流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4679, 1, 'yudao-admin-server', 1009003002, '流程定义不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4680, 1, 'yudao-admin-server', 1009003003, '流程定义处于挂起状态', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4681, 1, 'yudao-admin-server', 1009003004, '流程定义的模型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4682, 1, 'yudao-admin-server', 1009004000, '流程实例不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4683, 1, 'yudao-admin-server', 1009004001, '流程取消失败,流程不处于运行中', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4684, 1, 'yudao-admin-server', 1009004002, '流程取消失败,该流程不是你发起的', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4685, 1, 'yudao-admin-server', 1009004000, '审批任务失败,原因:该任务不处于未审批', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4686, 1, 'yudao-admin-server', 1009004001, '审批任务失败,原因:该任务的审批人不是你', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4687, 1, 'yudao-admin-server', 1009006000, '流程({}) 的任务({}) 已经存在分配规则', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4688, 1, 'yudao-admin-server', 1009006001, '流程任务分配规则不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4689, 1, 'yudao-admin-server', 1009006002, '只有流程模型的任务分配规则,才允许被修改', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4690, 1, 'yudao-admin-server', 1009006003, '操作失败,原因:找不到任务的审批人!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4691, 1, 'yudao-admin-server', 1009006004, '操作失败,原因:任务分配脚本({}) 不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4692, 1, 'yudao-admin-server', 1009010000, '动态表单不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4693, 1, 'yudao-admin-server', 1009010000, '表单项({}) 和 ({}) 使用了相同的字段名({})', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4694, 1, 'yudao-admin-server', 1009011000, '用户组不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); -INSERT INTO `sys_error_code` VALUES (4695, 1, 'yudao-admin-server', 1009011001, '名字为【{}】的用户组已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4594, 1, 'yudao-admin-server', 1001000001, '参数配置不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4595, 1, 'yudao-admin-server', 1001000002, '参数配置 key 重复', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4596, 1, 'yudao-admin-server', 1001000003, '不能删除类型为系统内置的参数配置', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4597, 1, 'yudao-admin-server', 1001000004, '不允许获取敏感配置到前端', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4598, 1, 'yudao-admin-server', 1001001000, '定时任务不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4599, 1, 'yudao-admin-server', 1001001001, '定时任务的处理器已经存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4600, 1, 'yudao-admin-server', 1001001002, '只允许修改为开启或者关闭状态', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4601, 1, 'yudao-admin-server', 1001001003, '定时任务已经处于该状态,无需修改', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4602, 1, 'yudao-admin-server', 1001001004, '只有开启状态的任务,才可以修改', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4603, 1, 'yudao-admin-server', 1001001005, 'CRON 表达式不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4604, 1, 'yudao-admin-server', 1001002000, 'API 错误日志不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4605, 1, 'yudao-admin-server', 1001002001, 'API 错误日志已处理', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4606, 1, 'yudao-admin-server', 1002000000, '登录失败,账号密码不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4607, 1, 'yudao-admin-server', 1002000001, '登录失败,账号被禁用', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4608, 1, 'yudao-admin-server', 1002000002, '登录失败', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4609, 1, 'yudao-admin-server', 1002000003, '验证码不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4610, 1, 'yudao-admin-server', 1002000004, '验证码不正确', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4611, 1, 'yudao-admin-server', 1002000005, '未绑定账号,需要进行绑定', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4612, 1, 'yudao-admin-server', 1002000006, 'Token 已经过期', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4613, 1, 'yudao-admin-server', 1002002000, '已经存在该名字的菜单', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4614, 1, 'yudao-admin-server', 1002002001, '父菜单不存在', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4615, 1, 'yudao-admin-server', 1002002002, '不能设置自己为父菜单', '', NULL, '2022-01-23 01:38:31', NULL, '2022-01-23 01:38:31', b'0'); +INSERT INTO `system_error_code` VALUES (4616, 1, 'yudao-admin-server', 1002002003, '菜单不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4617, 1, 'yudao-admin-server', 1002002004, '存在子菜单,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4618, 1, 'yudao-admin-server', 1002002005, '父菜单的类型必须是目录或者菜单', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4619, 1, 'yudao-admin-server', 1002003000, '角色不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4620, 1, 'yudao-admin-server', 1002003001, '已经存在名为【{}】的角色', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4621, 1, 'yudao-admin-server', 1002003002, '已经存在编码为【{}】的角色', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4622, 1, 'yudao-admin-server', 1002003004, '名字为【{}】的角色已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4623, 1, 'yudao-admin-server', 1002003004, '名字为【{}】的角色已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4624, 1, 'yudao-admin-server', 1002004000, '用户账号已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4625, 1, 'yudao-admin-server', 1002004001, '手机号已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4626, 1, 'yudao-admin-server', 1002004002, '邮箱已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4627, 1, 'yudao-admin-server', 1002004003, '用户不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4628, 1, 'yudao-admin-server', 1002004004, '导入用户数据不能为空!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4629, 1, 'yudao-admin-server', 1002004005, '用户密码校验失败', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4630, 1, 'yudao-admin-server', 1002003004, '名字为【{}】的用户已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4631, 1, 'yudao-admin-server', 1002004001, '已经存在该名字的部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4632, 1, 'yudao-admin-server', 1002004002, '父级部门不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4633, 1, 'yudao-admin-server', 1002004003, '当前部门不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4634, 1, 'yudao-admin-server', 1002004004, '存在子部门,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4635, 1, 'yudao-admin-server', 1002004005, '不能设置自己为父部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4636, 1, 'yudao-admin-server', 1002004006, '部门中存在员工,无法删除', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4637, 1, 'yudao-admin-server', 1002004007, '部门不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4638, 1, 'yudao-admin-server', 1002004008, '不能设置自己的子部门为父部门', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4639, 1, 'yudao-admin-server', 1002005001, '已经存在该名字的岗位', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4640, 1, 'yudao-admin-server', 1002005002, '岗位({}) 不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4641, 1, 'yudao-admin-server', 1002005001, '已经存在该名字的岗位', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4642, 1, 'yudao-admin-server', 1002005001, '已经存在该标识的岗位', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4643, 1, 'yudao-admin-server', 1002006001, '当前字典类型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4644, 1, 'yudao-admin-server', 1002006002, '字典类型不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4645, 1, 'yudao-admin-server', 1002006003, '已经存在该名字的字典类型', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4646, 1, 'yudao-admin-server', 1002006004, '已经存在该类型的字典类型', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4647, 1, 'yudao-admin-server', 1002006004, '无法删除,该字典类型还有字典数据', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4648, 1, 'yudao-admin-server', 1002007001, '当前字典数据不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4649, 1, 'yudao-admin-server', 1002007002, '字典数据({})不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4650, 1, 'yudao-admin-server', 1002007003, '已经存在该值的字典数据', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4651, 1, 'yudao-admin-server', 1002008001, '当前通知公告不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4652, 1, 'yudao-admin-server', 1002009001, '文件路径已经存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4653, 1, 'yudao-admin-server', 1002009002, '文件上传失败', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4654, 1, 'yudao-admin-server', 1002009003, '文件为空', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4655, 1, 'yudao-admin-server', 1002011000, '短信渠道不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4656, 1, 'yudao-admin-server', 1002011001, '短信渠道不处于开启状态,不允许选择', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4657, 1, 'yudao-admin-server', 1002011002, '无法删除,该短信渠道还有短信模板', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4658, 1, 'yudao-admin-server', 1002011000, '短信模板不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4659, 1, 'yudao-admin-server', 1002011001, '已经存在编码为【{}】的短信模板', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4660, 1, 'yudao-admin-server', 1002012000, '手机号不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4661, 1, 'yudao-admin-server', 1002013000, '验证码不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4662, 1, 'yudao-admin-server', 1002013001, '验证码已过期', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4663, 1, 'yudao-admin-server', 1009000002, '获取高亮流程图异常', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4664, 1, 'yudao-admin-server', 1009001001, '请假申请不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4665, 1, 'yudao-admin-server', 1009001002, '项目经理岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4666, 1, 'yudao-admin-server', 1009001009, '部门的项目经理不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4667, 1, 'yudao-admin-server', 1009001004, '部门经理岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4668, 1, 'yudao-admin-server', 1009001005, '部门的部门经理不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4669, 1, 'yudao-admin-server', 1009001006, 'HR岗位未设置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4670, 1, 'yudao-admin-server', 1009001007, '请假天数必须>=1', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4671, 1, 'yudao-admin-server', 1009002000, '已经存在流程标识为【{}】的流程', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4672, 1, 'yudao-admin-server', 1009002001, '流程模型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4673, 1, 'yudao-admin-server', 1009002002, '流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4674, 1, 'yudao-admin-server', 1009002003, '部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4675, 1, 'yudao-admin-server', 1009002004, '部署流程失败,原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4676, 1, 'yudao-admin-server', 1009003005, '流程定义部署失败,原因:信息未发生变化', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4677, 1, 'yudao-admin-server', 1009003000, '流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4678, 1, 'yudao-admin-server', 1009003001, '流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4679, 1, 'yudao-admin-server', 1009003002, '流程定义不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4680, 1, 'yudao-admin-server', 1009003003, '流程定义处于挂起状态', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4681, 1, 'yudao-admin-server', 1009003004, '流程定义的模型不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4682, 1, 'yudao-admin-server', 1009004000, '流程实例不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4683, 1, 'yudao-admin-server', 1009004001, '流程取消失败,流程不处于运行中', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4684, 1, 'yudao-admin-server', 1009004002, '流程取消失败,该流程不是你发起的', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4685, 1, 'yudao-admin-server', 1009004000, '审批任务失败,原因:该任务不处于未审批', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4686, 1, 'yudao-admin-server', 1009004001, '审批任务失败,原因:该任务的审批人不是你', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4687, 1, 'yudao-admin-server', 1009006000, '流程({}) 的任务({}) 已经存在分配规则', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4688, 1, 'yudao-admin-server', 1009006001, '流程任务分配规则不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4689, 1, 'yudao-admin-server', 1009006002, '只有流程模型的任务分配规则,才允许被修改', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4690, 1, 'yudao-admin-server', 1009006003, '操作失败,原因:找不到任务的审批人!', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4691, 1, 'yudao-admin-server', 1009006004, '操作失败,原因:任务分配脚本({}) 不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4692, 1, 'yudao-admin-server', 1009010000, '动态表单不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4693, 1, 'yudao-admin-server', 1009010000, '表单项({}) 和 ({}) 使用了相同的字段名({})', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4694, 1, 'yudao-admin-server', 1009011000, '用户组不存在', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4695, 1, 'yudao-admin-server', 1009011001, '名字为【{}】的用户组已被禁用', '', NULL, '2022-01-23 01:38:32', NULL, '2022-01-23 01:38:32', b'0'); +INSERT INTO `system_error_code` VALUES (4696, 1, 'yudao-admin-server', 1001003000, '文件路径已存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4697, 1, 'yudao-admin-server', 1001003001, '文件不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4698, 1, 'yudao-admin-server', 1004001000, '用户不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4699, 1, 'yudao-admin-server', 1004001001, '密码校验失败', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4700, 1, 'yudao-admin-server', 1004002000, '文件为空', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4701, 1, 'yudao-admin-server', 1004003000, '登录失败,账号密码不正确', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4702, 1, 'yudao-admin-server', 1004003001, '登录失败,账号被禁用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4703, 1, 'yudao-admin-server', 1004003002, '登录失败', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4704, 1, 'yudao-admin-server', 1004003004, 'Token 已经过期', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4705, 1, 'yudao-admin-server', 1004003005, '未绑定账号,需要进行绑定', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4706, 1, 'yudao-admin-server', 1007000000, 'App 不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4707, 1, 'yudao-admin-server', 1007000002, 'App 已经被禁用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4708, 1, 'yudao-admin-server', 1007000003, '支付应用存在交易中的订单,无法删除', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4709, 1, 'yudao-admin-server', 1007001000, '支付渠道的配置不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4710, 1, 'yudao-admin-server', 1007001001, '支付渠道已经禁用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4711, 1, 'yudao-admin-server', 1007001002, '支付渠道的客户端不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4712, 1, 'yudao-admin-server', 1007001003, '支付渠道不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4713, 1, 'yudao-admin-server', 1007001005, '已存在相同的渠道', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4714, 1, 'yudao-admin-server', 1007001006, '微信渠道v2版本中商户密钥不可为空', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4715, 1, 'yudao-admin-server', 1007001007, '微信渠道v3版本apiclient_key.pem不可为空', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4716, 1, 'yudao-admin-server', 1007001008, '微信渠道v3版本中apiclient_cert.pem不可为空', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4717, 1, 'yudao-admin-server', 1007001009, '渠道通知校验失败', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4718, 1, 'yudao-admin-server', 1007002000, '支付订单不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4719, 1, 'yudao-admin-server', 1007002001, '支付订单不处于待支付', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4720, 1, 'yudao-admin-server', 1007002002, '支付订单不处于已支付', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4721, 1, 'yudao-admin-server', 1007002003, '支付订单用户不正确', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4722, 1, 'yudao-admin-server', 1007003000, '支付交易拓展单不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4723, 1, 'yudao-admin-server', 1007003001, '支付交易拓展单不处于待支付', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4724, 1, 'yudao-admin-server', 1007003002, '支付订单不处于已支付', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4725, 1, 'yudao-admin-server', 1007006000, '退款金额超过订单可退款金额', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4726, 1, 'yudao-admin-server', 1007006001, '订单已经全额退款', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4727, 1, 'yudao-admin-server', 1007006002, '该订单的渠道订单为空', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4728, 1, 'yudao-admin-server', 1007006003, '已经退款成功', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4729, 1, 'yudao-admin-server', 1007006004, '支付退款单不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4730, 1, 'yudao-admin-server', 1007004000, '支付商户信息不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4731, 1, 'yudao-admin-server', 1007004001, '支付商户存在支付应用,无法删除', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4732, 1, 'yudao-admin-server', 1002012001, '模板参数({})缺失', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4733, 1, 'yudao-admin-server', 1002012002, '短信模板不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4734, 1, 'yudao-admin-server', 1002013002, '验证码已使用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4735, 1, 'yudao-admin-server', 1002013004, '验证码不正确', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4736, 1, 'yudao-admin-server', 1002013005, '超过每日短信发送数量', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4737, 1, 'yudao-admin-server', 1002013006, '短信发送过于频率', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4738, 1, 'yudao-admin-server', 1002013007, '手机号已被使用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4739, 1, 'yudao-admin-server', 1002013008, '验证码未被使用', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4740, 1, 'yudao-admin-server', 1002014000, '租户不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4741, 1, 'yudao-admin-server', 1002015000, '错误码不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4742, 1, 'yudao-admin-server', 1002015001, '社交解绑失败,非当前用户绑定', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:20:38', b'0'); +INSERT INTO `system_error_code` VALUES (4743, 1, 'yudao-admin-server', 1002015000, '社交授权失败,原因是:{}', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4744, 1, 'yudao-admin-server', 1002015001, '社交解绑失败,非当前用户绑定', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4745, 1, 'yudao-admin-server', 1002015001, '社交授权失败,找不到对应的用户', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4746, 1, 'yudao-admin-server', 1003000000, '测试示例不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4747, 1, 'yudao-admin-server', 1003001000, '表定义已经存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4748, 1, 'yudao-admin-server', 1003001001, '导入的表不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4749, 1, 'yudao-admin-server', 1003001002, '导入的字段不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4750, 1, 'yudao-admin-server', 1003001003, '解析 SQL 失败,请检查', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4751, 1, 'yudao-admin-server', 1003001004, '表定义不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4752, 1, 'yudao-admin-server', 1003001005, '字段义不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4753, 1, 'yudao-admin-server', 1003001006, '同步的字段不存在', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); +INSERT INTO `system_error_code` VALUES (4754, 1, 'yudao-admin-server', 1003001007, '同步失败,不存在改变', '', NULL, '2022-02-02 01:11:46', NULL, '2022-02-02 01:11:46', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_login_log +-- Table structure for system_login_log -- ---------------------------- -DROP TABLE IF EXISTS `sys_login_log`; -CREATE TABLE `sys_login_log` ( +DROP TABLE IF EXISTS `system_login_log`; +CREATE TABLE `system_login_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '访问ID', `log_type` bigint NOT NULL COMMENT '日志类型', `trace_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '链路追踪编号', @@ -1817,19 +2288,70 @@ CREATE TABLE `sys_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=764 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统访问记录'; +) ENGINE=InnoDB AUTO_INCREMENT=815 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统访问记录'; -- ---------------------------- --- Records of sys_login_log +-- Records of system_login_log -- ---------------------------- BEGIN; +INSERT INTO `system_login_log` VALUES (764, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 0); +INSERT INTO `system_login_log` VALUES (765, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 03:21:32', NULL, '2022-01-23 03:21:32', b'0', 0); +INSERT INTO `system_login_log` VALUES (766, 200, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 04:10:38', NULL, '2022-01-23 04:10:38', b'0', 0); +INSERT INTO `system_login_log` VALUES (767, 200, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 04:10:38', NULL, '2022-01-23 04:10:38', b'0', 0); +INSERT INTO `system_login_log` VALUES (768, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 0); +INSERT INTO `system_login_log` VALUES (769, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 12:40:59', b'0', 0); +INSERT INTO `system_login_log` VALUES (770, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 0); +INSERT INTO `system_login_log` VALUES (771, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 0); +INSERT INTO `system_login_log` VALUES (772, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 09:49:07', NULL, '2022-01-28 09:49:07', b'0', 0); +INSERT INTO `system_login_log` VALUES (773, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 20:39:33', NULL, '2022-01-28 20:39:33', b'0', 0); +INSERT INTO `system_login_log` VALUES (774, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:22:31', NULL, '2022-01-28 21:22:31', b'0', 0); +INSERT INTO `system_login_log` VALUES (775, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:22:44', NULL, '2022-01-28 21:22:44', b'0', 0); +INSERT INTO `system_login_log` VALUES (776, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:20', NULL, '2022-01-28 21:23:20', b'0', 0); +INSERT INTO `system_login_log` VALUES (777, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:22', NULL, '2022-01-28 21:23:22', b'0', 0); +INSERT INTO `system_login_log` VALUES (778, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:35', NULL, '2022-01-28 21:23:35', b'0', 0); +INSERT INTO `system_login_log` VALUES (779, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:24:02', NULL, '2022-01-28 21:24:02', b'0', 0); +INSERT INTO `system_login_log` VALUES (780, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:25:00', NULL, '2022-01-28 21:25:00', b'0', 0); +INSERT INTO `system_login_log` VALUES (781, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:25:14', NULL, '2022-01-28 21:25:14', b'0', 0); +INSERT INTO `system_login_log` VALUES (782, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:26:46', NULL, '2022-01-28 21:26:46', b'0', 0); +INSERT INTO `system_login_log` VALUES (783, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:26:47', NULL, '2022-01-28 21:26:47', b'0', 0); +INSERT INTO `system_login_log` VALUES (784, 100, '', 1, 2, 'admin', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:26:57', NULL, '2022-01-28 21:26:57', b'0', 0); +INSERT INTO `system_login_log` VALUES (785, 100, '', 1, 2, 'admin', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:27:28', NULL, '2022-01-28 21:27:28', b'0', 0); +INSERT INTO `system_login_log` VALUES (786, 100, '', 1, 2, 'admin', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:40:29', NULL, '2022-01-28 21:40:29', b'0', 0); +INSERT INTO `system_login_log` VALUES (787, 100, '', 1, 2, 'admin', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:42:30', NULL, '2022-01-28 21:42:30', b'0', 0); +INSERT INTO `system_login_log` VALUES (788, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:42:41', NULL, '2022-01-28 21:42:41', b'0', 0); +INSERT INTO `system_login_log` VALUES (789, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 23:21:07', NULL, '2022-01-28 23:21:07', b'0', 0); +INSERT INTO `system_login_log` VALUES (790, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 23:21:10', NULL, '2022-01-28 23:21:10', b'0', 0); +INSERT INTO `system_login_log` VALUES (791, 100, '', 0, 0, '15601691300', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 00:37:24', NULL, '2022-01-29 00:37:24', b'0', 0); +INSERT INTO `system_login_log` VALUES (792, 100, '', 245, 0, '15601691300', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 00:37:51', NULL, '2022-01-29 00:37:51', b'0', 0); +INSERT INTO `system_login_log` VALUES (793, 100, '', 245, 0, '15601691300', 10, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 00:37:59', NULL, '2022-01-29 00:37:59', b'0', 0); +INSERT INTO `system_login_log` VALUES (794, 100, '', 245, 0, '15601691300', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 11:50:08', NULL, '2022-01-29 11:50:08', b'0', 0); +INSERT INTO `system_login_log` VALUES (795, 100, '', 245, 0, '15601691300', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 13:58:04', NULL, '2022-01-29 13:58:04', b'0', 0); +INSERT INTO `system_login_log` VALUES (796, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 16:34:19', NULL, '2022-01-29 16:34:19', b'0', 0); +INSERT INTO `system_login_log` VALUES (797, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 16:47:54', NULL, '2022-01-29 16:47:54', b'0', 0); +INSERT INTO `system_login_log` VALUES (798, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 16:48:14', NULL, '2022-01-29 16:48:14', b'0', 0); +INSERT INTO `system_login_log` VALUES (799, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-30 23:30:54', NULL, '2022-01-30 23:30:54', b'0', 0); +INSERT INTO `system_login_log` VALUES (800, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 13:30:40', NULL, '2022-01-31 13:30:40', b'0', 0); +INSERT INTO `system_login_log` VALUES (801, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:12:35', NULL, '2022-01-31 17:12:35', b'0', 0); +INSERT INTO `system_login_log` VALUES (802, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:12:51', NULL, '2022-01-31 17:12:51', b'0', 0); +INSERT INTO `system_login_log` VALUES (803, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:15:38', NULL, '2022-01-31 17:15:38', b'0', 0); +INSERT INTO `system_login_log` VALUES (804, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:36:10', NULL, '2022-01-31 17:36:10', b'0', 0); +INSERT INTO `system_login_log` VALUES (805, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:45:45', NULL, '2022-01-31 17:45:45', b'0', 0); +INSERT INTO `system_login_log` VALUES (806, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:45:53', NULL, '2022-01-31 17:45:53', b'0', 0); +INSERT INTO `system_login_log` VALUES (807, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:47:25', NULL, '2022-01-31 17:47:25', b'0', 0); +INSERT INTO `system_login_log` VALUES (808, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-02-01 21:46:34', NULL, '2022-02-01 21:46:34', b'0', 0); +INSERT INTO `system_login_log` VALUES (809, 102, '', 1, 2, 'admin', 0, '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-02-01 21:56:07', NULL, '2022-02-01 21:56:07', b'0', 0); +INSERT INTO `system_login_log` VALUES (810, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-01 22:57:32', NULL, '2022-02-01 22:57:32', b'0', 0); +INSERT INTO `system_login_log` VALUES (811, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:24:35', NULL, '2022-02-02 00:24:35', b'0', 0); +INSERT INTO `system_login_log` VALUES (812, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:25:21', NULL, '2022-02-02 00:25:21', b'0', 0); +INSERT INTO `system_login_log` VALUES (813, 200, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:26:41', NULL, '2022-02-02 00:26:41', b'0', 0); +INSERT INTO `system_login_log` VALUES (814, 100, '', 1, 2, 'admin', 0, '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:27:55', NULL, '2022-02-02 00:27:55', b'0', 0); COMMIT; -- ---------------------------- --- Table structure for sys_menu +-- Table structure for system_menu -- ---------------------------- -DROP TABLE IF EXISTS `sys_menu`; -CREATE TABLE `sys_menu` ( +DROP TABLE IF EXISTS `system_menu`; +CREATE TABLE `system_menu` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID', `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '菜单名称', `permission` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '权限标识', @@ -1850,244 +2372,244 @@ CREATE TABLE `sys_menu` ( ) ENGINE=InnoDB AUTO_INCREMENT=1223 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菜单权限表'; -- ---------------------------- --- Records of sys_menu +-- Records of system_menu -- ---------------------------- BEGIN; -INSERT INTO `sys_menu` VALUES (1, '系统管理', '', 1, 10, 0, '/system', 'system', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:08', b'0', 0); -INSERT INTO `sys_menu` VALUES (2, '基础设施', '', 1, 20, 0, '/infra', 'monitor', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:18', b'0', 0); -INSERT INTO `sys_menu` VALUES (3, '研发工具', '', 1, 30, 0, '/tool', 'tool', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:13', b'0', 0); -INSERT INTO `sys_menu` VALUES (4, '若依官网', '', 1, 4, 0, 'http://ruoyi.vip', 'guide', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 21:54:28', b'1', 0); -INSERT INTO `sys_menu` VALUES (5, 'OA 示例', '', 1, 40, 1185, 'oa', 'people', NULL, 0, 'admin', '2021-09-20 16:26:19', '1', '2022-01-22 18:32:50', b'0', 0); -INSERT INTO `sys_menu` VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'user', 'system/user/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'peoples', 'system/role/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:49', b'0', 0); -INSERT INTO `sys_menu` VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'tree-table', 'system/menu/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:28', b'0', 0); -INSERT INTO `sys_menu` VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'tree', 'system/dept/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:19', b'0', 0); -INSERT INTO `sys_menu` VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'post', 'system/post/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:23', b'0', 0); -INSERT INTO `sys_menu` VALUES (105, '字典管理', '', 2, 6, 1, 'dict', 'dict', 'system/dict/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:16:58', b'0', 0); -INSERT INTO `sys_menu` VALUES (106, '配置管理', '', 2, 1, 2, 'config', 'edit', 'infra/config/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (107, '通知公告', '', 2, 8, 1, 'notice', 'message', 'system/notice/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:39', b'0', 0); -INSERT INTO `sys_menu` VALUES (108, '审计日志', '', 1, 9, 1, 'log', 'log', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-04-26 22:34:58', b'0', 0); -INSERT INTO `sys_menu` VALUES (109, '在线用户', 'system:user-session:list', 2, 10, 1, 'user-session', 'online', 'system/session/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:21:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (110, '定时任务', '', 2, 2, 2, 'job', 'job', 'infra/job/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:25:51', b'0', 0); -INSERT INTO `sys_menu` VALUES (111, 'MySQL 监控', '', 2, 4, 2, 'druid', 'druid', 'infra/druid/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:32', b'0', 0); -INSERT INTO `sys_menu` VALUES (112, 'Java 监控', '', 2, 6, 2, 'admin-server', 'server', 'infra/server', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (113, 'Redis 监控', '', 2, 5, 2, 'redis', 'redis', 'infra/redis/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:37', b'0', 0); -INSERT INTO `sys_menu` VALUES (114, '表单构建', 'tool:build:list', 2, 1, 3, 'build', 'build', 'tool/build/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (115, '代码生成', 'tool:codegen:query', 2, 0, 3, 'codegen', 'code', 'tool/codegen/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-06 03:43:14', b'0', 0); -INSERT INTO `sys_menu` VALUES (116, '系统接口', 'tool:swagger:list', 2, 3, 3, 'swagger', 'swagger', 'tool/swagger/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (500, '操作日志', '', 2, 1, 108, 'operate-log', 'form', 'system/operatelog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:42:56', b'0', 0); -INSERT INTO `sys_menu` VALUES (501, '登录日志', '', 2, 2, 108, 'login-log', 'logininfor', 'system/loginlog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:39:23', b'0', 0); -INSERT INTO `sys_menu` VALUES (1001, '用户查询', 'system:user:query', 3, 1, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1002, '用户新增', 'system:user:create', 3, 2, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:47', b'0', 0); -INSERT INTO `sys_menu` VALUES (1003, '用户修改', 'system:user:update', 3, 3, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:54', b'0', 0); -INSERT INTO `sys_menu` VALUES (1004, '用户删除', 'system:user:delete', 3, 4, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:22:03', b'0', 0); -INSERT INTO `sys_menu` VALUES (1005, '用户导出', 'system:user:export', 3, 5, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1006, '用户导入', 'system:user:import', 3, 6, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1007, '重置密码', 'system:user:update-password', 3, 7, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:20:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1008, '角色查询', 'system:role:query', 3, 1, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1009, '角色新增', 'system:role:create', 3, 2, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:24', b'0', 0); -INSERT INTO `sys_menu` VALUES (1010, '角色修改', 'system:role:update', 3, 3, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:14', b'0', 0); -INSERT INTO `sys_menu` VALUES (1011, '角色删除', 'system:role:delete', 3, 4, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:05', b'0', 0); -INSERT INTO `sys_menu` VALUES (1012, '角色导出', 'system:role:export', 3, 5, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1013, '菜单查询', 'system:menu:query', 3, 1, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1014, '菜单新增', 'system:menu:create', 3, 2, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:36', b'0', 0); -INSERT INTO `sys_menu` VALUES (1015, '菜单修改', 'system:menu:update', 3, 3, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:30', b'0', 0); -INSERT INTO `sys_menu` VALUES (1016, '菜单删除', 'system:menu:delete', 3, 4, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (1017, '部门查询', 'system:dept:query', 3, 1, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1018, '部门新增', 'system:dept:create', 3, 2, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:30', b'0', 0); -INSERT INTO `sys_menu` VALUES (1019, '部门修改', 'system:dept:update', 3, 3, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:37', b'0', 0); -INSERT INTO `sys_menu` VALUES (1020, '部门删除', 'system:dept:delete', 3, 4, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1021, '岗位查询', 'system:post:query', 3, 1, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1022, '岗位新增', 'system:post:create', 3, 2, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:34', b'0', 0); -INSERT INTO `sys_menu` VALUES (1023, '岗位修改', 'system:post:update', 3, 3, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1024, '岗位删除', 'system:post:delete', 3, 4, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:48', b'0', 0); -INSERT INTO `sys_menu` VALUES (1025, '岗位导出', 'system:post:export', 3, 5, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1026, '字典查询', 'system:dict:query', 3, 1, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1027, '字典新增', 'system:dict:create', 3, 2, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:29', b'0', 0); -INSERT INTO `sys_menu` VALUES (1028, '字典修改', 'system:dict:update', 3, 3, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:36', b'0', 0); -INSERT INTO `sys_menu` VALUES (1029, '字典删除', 'system:dict:delete', 3, 4, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (1030, '字典导出', 'system:dict:export', 3, 5, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1031, '配置查询', 'infra:config:query', 3, 1, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:00', b'0', 0); -INSERT INTO `sys_menu` VALUES (1032, '配置新增', 'infra:config:create', 3, 2, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:18', b'0', 0); -INSERT INTO `sys_menu` VALUES (1033, '配置修改', 'infra:config:update', 3, 3, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:30', b'0', 0); -INSERT INTO `sys_menu` VALUES (1034, '配置删除', 'infra:config:delete', 3, 4, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:36', b'0', 0); -INSERT INTO `sys_menu` VALUES (1035, '配置导出', 'infra:config:export', 3, 5, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:19', b'0', 0); -INSERT INTO `sys_menu` VALUES (1036, '公告查询', 'system:notice:query', 3, 1, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1037, '公告新增', 'system:notice:create', 3, 2, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:48', b'0', 0); -INSERT INTO `sys_menu` VALUES (1038, '公告修改', 'system:notice:update', 3, 3, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1039, '公告删除', 'system:notice:delete', 3, 4, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:52:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1040, '操作查询', 'system:operate-log:query', 3, 1, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (1042, '日志导出', 'system:operate-log:export', 3, 2, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:23', b'0', 0); -INSERT INTO `sys_menu` VALUES (1043, '登录查询', 'system:login-log:query', 3, 1, 501, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:26', b'0', 0); -INSERT INTO `sys_menu` VALUES (1045, '日志导出', 'system:login-log:export', 3, 3, 501, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:30', b'0', 0); -INSERT INTO `sys_menu` VALUES (1046, '在线查询', 'system:user-session:list', 3, 1, 109, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:22:37', b'0', 0); -INSERT INTO `sys_menu` VALUES (1047, '批量强退', 'monitor:online:batchLogout', 3, 2, 109, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:21:46', b'1', 0); -INSERT INTO `sys_menu` VALUES (1048, '单条强退', 'system:user-session:delete', 3, 3, 109, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:22:54', b'0', 0); -INSERT INTO `sys_menu` VALUES (1049, '任务查询', 'monitor:job:query', 3, 1, 110, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:01:42', b'1', 0); -INSERT INTO `sys_menu` VALUES (1050, '任务新增', 'infra:job:create', 3, 2, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:01:58', b'0', 0); -INSERT INTO `sys_menu` VALUES (1051, '任务修改', 'infra:job:update', 3, 3, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (1052, '任务删除', 'infra:job:delete', 3, 4, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:22', b'0', 0); -INSERT INTO `sys_menu` VALUES (1053, '状态修改', 'infra:job:update', 3, 5, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:38', b'0', 0); -INSERT INTO `sys_menu` VALUES (1054, '任务导出', 'infra:job:export', 3, 7, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:51', b'0', 0); -INSERT INTO `sys_menu` VALUES (1055, '生成查询', 'tool:gen:query', 3, 1, 115, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:25', b'1', 0); -INSERT INTO `sys_menu` VALUES (1056, '生成修改', 'tool:codegen:update', 3, 2, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1057, '生成删除', 'tool:codegen:delete', 3, 3, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:02', b'0', 0); -INSERT INTO `sys_menu` VALUES (1058, '导入代码', 'tool:codegen:create', 3, 2, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:50', b'0', 0); -INSERT INTO `sys_menu` VALUES (1059, '预览代码', 'tool:codegen:preview', 3, 4, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (1060, '生成代码', 'tool:codegen:download', 3, 5, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1063, '设置角色菜单权限', 'system:permission:assign-role-menu', 3, 6, 101, '', '', '', 0, '', '2021-01-06 17:53:44', '', '2021-01-06 17:55:23', b'0', 0); -INSERT INTO `sys_menu` VALUES (1064, '设置角色数据权限', 'system:permission:assign-role-data-scope', 3, 7, 101, '', '', '', 0, '', '2021-01-06 17:56:31', '', '2021-01-06 17:56:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', 0, '', '2021-01-07 10:23:28', '', '2021-01-07 10:23:28', b'0', 0); -INSERT INTO `sys_menu` VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', 0, '', '2021-01-26 01:02:31', '', '2021-01-26 01:02:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', 0, '', '2021-01-26 01:02:52', '', '2021-01-26 01:02:52', b'0', 0); -INSERT INTO `sys_menu` VALUES (1070, '代码生成示例', 'tool:test-demo:query', 2, 0, 3, 'test-demo', 'validCode', 'tool/testDemo/index', 0, '', '2021-02-06 12:42:49', '', '2021-03-06 03:45:22', b'0', 0); -INSERT INTO `sys_menu` VALUES (1071, '测试示例表创建', 'tool:test-demo:create', 3, 1, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:47', b'0', 0); -INSERT INTO `sys_menu` VALUES (1072, '测试示例表更新', 'tool:test-demo:update', 3, 2, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:51', b'0', 0); -INSERT INTO `sys_menu` VALUES (1073, '测试示例表删除', 'tool:test-demo:delete', 3, 3, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:58', b'0', 0); -INSERT INTO `sys_menu` VALUES (1074, '测试示例表导出', 'tool:test-demo:export', 3, 4, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:54:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1075, '任务触发', 'infra:job:trigger', 3, 8, 110, '', '', '', 0, '', '2021-02-07 13:03:10', '', '2021-02-07 13:03:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (1076, '数据库文档', '', 2, 5, 3, 'db-doc', 'table', 'tool/dbDoc/index', 0, '', '2021-02-08 01:41:47', '', '2021-02-08 01:49:00', b'0', 0); -INSERT INTO `sys_menu` VALUES (1077, '链路追踪', '', 2, 7, 2, 'skywalking', 'eye-open', 'infra/skywalking', 0, '', '2021-02-08 20:41:31', '', '2021-02-26 02:18:45', b'0', 0); -INSERT INTO `sys_menu` VALUES (1078, '访问日志', '', 2, 1, 1083, 'api-access-log', 'log', 'infra/apiAccessLog/index', 0, '', '2021-02-26 01:32:59', '1', '2021-03-10 01:28:09', b'0', 0); -INSERT INTO `sys_menu` VALUES (1079, 'API 访问日志表创建', 'system:api-access-log:create', 3, 1, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:00', b'1', 0); -INSERT INTO `sys_menu` VALUES (1080, 'API 访问日志表更新', 'system:api-access-log:update', 3, 2, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:08', b'1', 0); -INSERT INTO `sys_menu` VALUES (1081, 'API 访问日志表删除', 'system:api-access-log:delete', 3, 3, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:27', b'1', 0); -INSERT INTO `sys_menu` VALUES (1082, '日志导出', 'infra:api-access-log:export', 3, 2, 1078, '', '', '', 0, '', '2021-02-26 01:32:59', '1', '2021-03-10 01:28:13', b'0', 0); -INSERT INTO `sys_menu` VALUES (1083, 'API 日志', '', 2, 3, 2, 'log', 'log', NULL, 0, '', '2021-02-26 02:18:24', '', '2021-02-26 02:20:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1084, '错误日志', 'infra:api-error-log:query', 2, 2, 1083, 'api-error-log', 'log', 'infra/apiErrorLog/index', 0, '', '2021-02-26 07:53:20', '', '2021-02-26 07:54:40', b'0', 0); -INSERT INTO `sys_menu` VALUES (1085, '日志处理', 'infra:api-error-log:update-status', 3, 2, 1084, '', '', '', 0, '', '2021-02-26 07:53:20', '1', '2021-03-10 01:28:18', b'0', 0); -INSERT INTO `sys_menu` VALUES (1086, '日志导出', 'infra:api-error-log:export', 3, 3, 1084, '', '', '', 0, '', '2021-02-26 07:53:20', '1', '2021-03-10 01:28:21', b'0', 0); -INSERT INTO `sys_menu` VALUES (1087, '任务查询', 'infra:job:query', 3, 1, 110, '', '', '', 0, '1', '2021-03-10 01:26:19', '1', '2021-03-10 01:26:19', b'0', 0); -INSERT INTO `sys_menu` VALUES (1088, '日志查询', 'infra:api-access-log:query', 3, 1, 1078, '', '', '', 0, '1', '2021-03-10 01:28:04', '1', '2021-03-10 01:29:38', b'0', 0); -INSERT INTO `sys_menu` VALUES (1089, '日志查询', 'infra:api-error-log:query', 3, 1, 1084, '', '', '', 0, '1', '2021-03-10 01:29:09', '1', '2021-03-10 01:29:09', b'0', 0); -INSERT INTO `sys_menu` VALUES (1090, '文件管理', '', 2, 0, 2, 'file', 'upload', 'infra/file/index', 0, '', '2021-03-12 20:16:20', '1', '2021-03-13 11:07:05', b'0', 0); -INSERT INTO `sys_menu` VALUES (1091, '文件查询', 'infra:file:query', 3, 1, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1092, '文件删除', 'infra:file:delete', 3, 4, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1093, '短信管理', '', 1, 11, 1, 'sms', 'validCode', NULL, 0, '1', '2021-04-05 01:10:16', '1', '2021-04-05 01:11:38', b'0', 0); -INSERT INTO `sys_menu` VALUES (1094, '短信渠道', '', 2, 0, 1093, 'sms-channel', 'phone', 'system/sms/smsChannel', 0, '', '2021-04-01 11:07:15', '1', '2021-04-09 23:44:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1095, '短信渠道查询', 'system:sms-channel:query', 3, 1, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1096, '短信渠道创建', 'system:sms-channel:create', 3, 2, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1097, '短信渠道更新', 'system:sms-channel:update', 3, 3, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1098, '短信渠道删除', 'system:sms-channel:delete', 3, 4, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1100, '短信模板', '', 2, 1, 1093, 'sms-template', 'phone', 'system/sms/smsTemplate', 0, '', '2021-04-01 17:35:17', '1', '2021-04-11 19:34:21', b'0', 0); -INSERT INTO `sys_menu` VALUES (1101, '短信模板查询', 'system:sms-template:query', 3, 1, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1102, '短信模板创建', 'system:sms-template:create', 3, 2, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1103, '短信模板更新', 'system:sms-template:update', 3, 3, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1104, '短信模板删除', 'system:sms-template:delete', 3, 4, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1105, '短信模板导出', 'system:sms-template:export', 3, 5, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); -INSERT INTO `sys_menu` VALUES (1106, '发送测试短信', 'system:sms-template:send-sms', 3, 6, 1100, '', '', '', 0, '1', '2021-04-11 00:26:40', '1', '2021-04-11 00:26:40', b'0', 0); -INSERT INTO `sys_menu` VALUES (1107, '短信日志', '', 2, 2, 1093, 'sms-log', 'phone', 'system/sms/smsLog', 0, '', '2021-04-11 08:37:05', '1', '2021-04-11 19:34:25', b'0', 0); -INSERT INTO `sys_menu` VALUES (1108, '短信日志查询', 'system:sms-log:query', 3, 1, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0', 0); -INSERT INTO `sys_menu` VALUES (1109, '短信日志导出', 'system:sms-log:export', 3, 5, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0', 0); -INSERT INTO `sys_menu` VALUES (1110, '错误码管理', '', 2, 12, 1, 'error-code', 'code', 'system/errorCode/index', 0, '', '2021-04-13 21:46:42', '1', '2021-04-22 00:04:35', b'0', 0); -INSERT INTO `sys_menu` VALUES (1111, '错误码查询', 'system:error-code:query', 3, 1, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:37', b'0', 0); -INSERT INTO `sys_menu` VALUES (1112, '错误码创建', 'system:error-code:create', 3, 2, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1113, '错误码更新', 'system:error-code:update', 3, 3, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:47', b'0', 0); -INSERT INTO `sys_menu` VALUES (1114, '错误码删除', 'system:error-code:delete', 3, 4, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:51', b'0', 0); -INSERT INTO `sys_menu` VALUES (1115, '错误码导出', 'system:error-code:export', 3, 5, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:55', b'0', 0); -INSERT INTO `sys_menu` VALUES (1116, '日志中心', '', 2, 8, 2, 'log-center', 'log', 'infra/skywalking/log', 0, '1', '2021-04-26 22:35:45', '1', '2021-04-26 22:37:25', b'0', 0); -INSERT INTO `sys_menu` VALUES (1117, '支付管理', '', 1, 11, 0, '/pay', 'money', NULL, 0, '1', '2021-12-25 16:43:41', '1', '2021-12-25 16:46:40', b'0', 0); -INSERT INTO `sys_menu` VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'user', 'bpm/oa/leave/index', 0, '', '2021-09-20 08:51:03', '1', '2022-01-22 21:36:06', b'0', 0); -INSERT INTO `sys_menu` VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '1', '2022-01-23 00:14:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '1', '2022-01-23 00:14:49', b'0', 0); -INSERT INTO `sys_menu` VALUES (1121, '请假申请更新', 'oa:leave:update', 3, 3, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:26', b'1', 0); -INSERT INTO `sys_menu` VALUES (1122, '请假申请删除', 'oa:leave:delete', 3, 4, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:28', b'1', 0); -INSERT INTO `sys_menu` VALUES (1123, '请假申请导出', 'oa:leave:export', 3, 5, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:30', b'1', 0); -INSERT INTO `sys_menu` VALUES (1124, '待办任务', '', 2, 2, 5, 'todo', 'edit', 'oa/todo/index', 0, '1', '2021-09-20 22:10:09', '1', '2022-01-22 10:33:01', b'1', 0); -INSERT INTO `sys_menu` VALUES (1125, '流程申请', '', 2, 3, 5, 'flow', 'form', 'oa/flow/index', 0, '1', '2021-10-23 22:10:09', '1', '2022-01-22 10:33:03', b'1', 0); -INSERT INTO `sys_menu` VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 0, '', '2021-11-10 01:13:30', '1', '2021-12-25 16:56:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1127, '支付应用信息查询', 'pay:app:query', 3, 1, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1128, '支付应用信息创建', 'pay:app:create', 3, 2, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1129, '支付应用信息更新', 'pay:app:update', 3, 3, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1130, '支付应用信息删除', 'pay:app:delete', 3, 4, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1131, '支付应用信息导出', 'pay:app:export', 3, 5, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); -INSERT INTO `sys_menu` VALUES (1132, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', 0, '1', '2021-11-08 15:15:47', '1', '2021-11-08 15:15:47', b'0', 0); -INSERT INTO `sys_menu` VALUES (1133, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1134, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1135, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1136, '支付商户信息删除', 'pay:merchant:delete', 3, 4, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1137, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1138, '租户管理', '', 2, 0, 1, 'tenant', 'peoples', 'system/tenant/index', 0, '', '2021-12-14 12:31:43', '1', '2021-12-14 20:32:32', b'0', 0); -INSERT INTO `sys_menu` VALUES (1139, '租户查询', 'system:tenant:query', 3, 1, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1140, '租户创建', 'system:tenant:create', 3, 2, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1141, '租户更新', 'system:tenant:update', 3, 3, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1142, '租户删除', 'system:tenant:delete', 3, 4, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1143, '租户导出', 'system:tenant:export', 3, 5, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1144, '支付应用信息管理', '', 2, 0, 1117, 'app', '', 'pay/app/index', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:48:05', b'1', 0); -INSERT INTO `sys_menu` VALUES (1145, '支付应用信息查询', 'pay:app:query', 3, 1, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:53', b'1', 0); -INSERT INTO `sys_menu` VALUES (1146, '支付应用信息创建', 'pay:app:create', 3, 2, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:51', b'1', 0); -INSERT INTO `sys_menu` VALUES (1147, '支付应用信息更新', 'pay:app:update', 3, 3, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:48', b'1', 0); -INSERT INTO `sys_menu` VALUES (1148, '支付应用信息删除', 'pay:app:delete', 3, 4, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:46', b'1', 0); -INSERT INTO `sys_menu` VALUES (1149, '支付应用信息导出', 'pay:app:export', 3, 5, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:43', b'1', 0); -INSERT INTO `sys_menu` VALUES (1150, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', 0, '1', '2021-11-08 15:15:47', '1', '2021-11-08 15:15:47', b'0', 0); -INSERT INTO `sys_menu` VALUES (1156, '支付订单查询', 'pay:order:query', 3, 1, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1157, '支付订单创建', 'pay:order:create', 3, 2, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1158, '支付订单更新', 'pay:order:update', 3, 3, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1159, '支付订单删除', 'pay:order:delete', 3, 4, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1160, '支付订单导出', 'pay:order:export', 3, 5, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); -INSERT INTO `sys_menu` VALUES (1161, '退款订单', '', 2, 3, 1117, 'refund', 'order', 'pay/refund/index', 0, '', '2021-12-25 08:29:07', '1', '2021-12-25 19:30:22', b'0', 0); -INSERT INTO `sys_menu` VALUES (1162, '退款订单查询', 'pay:refund:query', 3, 1, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1163, '退款订单创建', 'pay:refund:create', 3, 2, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1164, '退款订单更新', 'pay:refund:update', 3, 3, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1165, '退款订单删除', 'pay:refund:delete', 3, 4, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1166, '退款订单导出', 'pay:refund:export', 3, 5, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); -INSERT INTO `sys_menu` VALUES (1173, '支付订单', '', 2, 2, 1117, 'order', 'pay', 'pay/order/index', 0, '', '2021-12-25 08:49:43', '1', '2021-12-25 19:29:54', b'0', 0); -INSERT INTO `sys_menu` VALUES (1174, '支付订单查询', 'pay:order:query', 3, 1, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1175, '支付订单创建', 'pay:order:create', 3, 2, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1176, '支付订单更新', 'pay:order:update', 3, 3, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1177, '支付订单删除', 'pay:order:delete', 3, 4, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1178, '支付订单导出', 'pay:order:export', 3, 5, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1179, '商户信息', '', 2, 0, 1117, 'merchant', 'merchant', 'pay/merchant/index', 0, '', '2021-12-25 09:01:44', '1', '2021-12-25 17:02:13', b'0', 0); -INSERT INTO `sys_menu` VALUES (1180, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1181, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1182, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1183, '支付商户信息删除', 'pay:merchant:delete', 3, 4, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1184, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); -INSERT INTO `sys_menu` VALUES (1185, '工作流程', '', 1, 50, 0, '/bpm', 'tool', NULL, 0, '1', '2021-12-30 20:26:36', '103', '2022-01-14 18:44:00', b'0', 0); -INSERT INTO `sys_menu` VALUES (1186, '流程管理', '', 1, 10, 1185, 'manager', 'nested', NULL, 0, '1', '2021-12-30 20:28:30', '1', '2021-12-30 20:28:57', b'0', 0); -INSERT INTO `sys_menu` VALUES (1187, '流程表单', '', 2, 0, 1186, 'form', 'form', 'bpm/form/index', 0, '', '2021-12-30 12:38:22', '1', '2021-12-31 23:20:38', b'0', 0); -INSERT INTO `sys_menu` VALUES (1188, '表单查询', 'bpm:form:query', 3, 1, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 18:59:53', b'0', 0); -INSERT INTO `sys_menu` VALUES (1189, '表单创建', 'bpm:form:create', 3, 2, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 18:59:59', b'0', 0); -INSERT INTO `sys_menu` VALUES (1190, '表单更新', 'bpm:form:update', 3, 3, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:21', b'0', 0); -INSERT INTO `sys_menu` VALUES (1191, '表单删除', 'bpm:form:delete', 3, 4, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:26', b'0', 0); -INSERT INTO `sys_menu` VALUES (1192, '表单导出', 'bpm:form:export', 3, 5, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:33', b'0', 0); -INSERT INTO `sys_menu` VALUES (1193, '流程模型', '', 2, 5, 1186, 'model', 'guide', 'bpm/model/index', 0, '1', '2021-12-31 23:24:58', '103', '2022-01-14 10:14:38', b'0', 0); -INSERT INTO `sys_menu` VALUES (1194, '模型查询', 'bpm:model:query', 3, 1, 1193, '', '', '', 0, '1', '2022-01-03 19:01:10', '1', '2022-01-03 19:01:10', b'0', 0); -INSERT INTO `sys_menu` VALUES (1195, '模型创建', 'bpm:model:create', 3, 2, 1193, '', '', '', 0, '1', '2022-01-03 19:01:24', '1', '2022-01-03 19:02:02', b'0', 0); -INSERT INTO `sys_menu` VALUES (1196, '模型导入', 'bpm:model:import', 3, 3, 1193, '', '', '', 0, '1', '2022-01-03 19:01:35', '1', '2022-01-03 19:02:11', b'0', 0); -INSERT INTO `sys_menu` VALUES (1197, '模型更新', 'bpm:model:update', 3, 4, 1193, '', '', '', 0, '1', '2022-01-03 19:02:28', '1', '2022-01-03 19:02:28', b'0', 0); -INSERT INTO `sys_menu` VALUES (1198, '模型删除', 'bpm:model:delete', 3, 5, 1193, '', '', '', 0, '1', '2022-01-03 19:02:43', '1', '2022-01-03 19:02:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1199, '模型发布', 'bpm:model:deploy', 3, 6, 1193, '', '', '', 0, '1', '2022-01-03 19:03:24', '1', '2022-01-03 19:03:24', b'0', 0); -INSERT INTO `sys_menu` VALUES (1200, '任务管理', '', 1, 20, 1185, 'task', 'cascader', NULL, 0, '1', '2022-01-07 23:51:48', '1', '2022-01-07 23:51:48', b'0', 0); -INSERT INTO `sys_menu` VALUES (1201, '我的流程', '', 2, 0, 1200, 'my', 'people', 'bpm/processInstance/index', 0, '', '2022-01-07 15:53:44', '1', '2022-01-08 16:44:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1202, '流程实例的查询', 'bpm:process-instance:query', 3, 1, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '1', '2022-01-07 23:56:29', b'0', 0); -INSERT INTO `sys_menu` VALUES (1203, '工作流的流程实例的拓展创建', 'bpm:process-instance-ext:create', 3, 2, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:56:08', b'1', 0); -INSERT INTO `sys_menu` VALUES (1204, '工作流的流程实例的拓展更新', 'bpm:process-instance-ext:update', 3, 3, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:56:00', b'1', 0); -INSERT INTO `sys_menu` VALUES (1205, '工作流的流程实例的拓展删除', 'bpm:process-instance-ext:delete', 3, 4, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:55:56', b'1', 0); -INSERT INTO `sys_menu` VALUES (1206, '工作流的流程实例的拓展导出', 'bpm:process-instance-ext:export', 3, 5, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:55:51', b'1', 0); -INSERT INTO `sys_menu` VALUES (1207, '待办任务', '', 2, 10, 1200, 'todo', 'eye-open', 'bpm/task/todo', 0, '1', '2022-01-08 10:33:37', '1', '2022-01-08 10:33:48', b'0', 0); -INSERT INTO `sys_menu` VALUES (1208, '已办任务', '', 2, 20, 1200, 'done', 'eye', 'bpm/task/done', 0, '1', '2022-01-08 10:34:13', '1', '2022-01-08 10:34:13', b'0', 0); -INSERT INTO `sys_menu` VALUES (1209, '用户分组', '', 2, 2, 1186, 'user-group', 'people', 'bpm/group/index', 0, '', '2022-01-14 02:14:20', '103', '2022-01-14 10:15:43', b'0', 0); -INSERT INTO `sys_menu` VALUES (1210, '用户组查询', 'bpm:user-group:query', 3, 1, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1211, '用户组创建', 'bpm:user-group:create', 3, 2, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1212, '用户组更新', 'bpm:user-group:update', 3, 3, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1213, '用户组删除', 'bpm:user-group:delete', 3, 4, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); -INSERT INTO `sys_menu` VALUES (1214, '用户组导出', 'bpm:user-group:export', 3, 5, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:58', b'1', 0); -INSERT INTO `sys_menu` VALUES (1215, '流程定义查询', 'bpm:process-definition:query', 3, 10, 1193, '', '', '', 0, '1', '2022-01-23 00:21:43', '1', '2022-01-23 00:26:30', b'0', 0); -INSERT INTO `sys_menu` VALUES (1216, '流程任务分配规则查询', 'bpm:task-assign-rule:query', 3, 20, 1193, '', '', '', 0, '1', '2022-01-23 00:26:53', '1', '2022-01-23 00:26:53', b'0', 0); -INSERT INTO `sys_menu` VALUES (1217, '流程任务分配规则创建', 'bpm:task-assign-rule:create', 3, 21, 1193, '', '', '', 0, '1', '2022-01-23 00:28:15', '1', '2022-01-23 00:28:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1218, '流程任务分配规则更新', 'bpm:task-assign-rule:update', 3, 22, 1193, '', '', '', 0, '1', '2022-01-23 00:28:41', '1', '2022-01-23 00:28:41', b'0', 0); -INSERT INTO `sys_menu` VALUES (1219, '流程实例的创建', 'bpm:process-instance:create', 3, 2, 1201, '', '', '', 0, '1', '2022-01-23 00:36:15', '1', '2022-01-23 00:36:15', b'0', 0); -INSERT INTO `sys_menu` VALUES (1220, '流程实例的取消', 'bpm:process-instance:cancel', 3, 3, 1201, '', '', '', 0, '1', '2022-01-23 00:36:33', '1', '2022-01-23 00:36:33', b'0', 0); -INSERT INTO `sys_menu` VALUES (1221, '流程任务的查询', 'bpm:task:query', 3, 1, 1207, '', '', '', 0, '1', '2022-01-23 00:38:52', '1', '2022-01-23 00:38:52', b'0', 0); -INSERT INTO `sys_menu` VALUES (1222, '流程任务的更新', 'bpm:task:update', 3, 2, 1207, '', '', '', 0, '1', '2022-01-23 00:39:24', '1', '2022-01-23 00:39:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1, '系统管理', '', 1, 10, 0, '/system', 'system', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:08', b'0', 0); +INSERT INTO `system_menu` VALUES (2, '基础设施', '', 1, 20, 0, '/infra', 'monitor', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:18', b'0', 0); +INSERT INTO `system_menu` VALUES (3, '研发工具', '', 1, 30, 0, '/tool', 'tool', NULL, 0, 'admin', '2021-01-05 17:03:48', '1', '2021-12-25 16:43:13', b'0', 0); +INSERT INTO `system_menu` VALUES (4, '若依官网', '', 1, 4, 0, 'http://ruoyi.vip', 'guide', NULL, 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 21:54:28', b'1', 0); +INSERT INTO `system_menu` VALUES (5, 'OA 示例', '', 1, 40, 1185, 'oa', 'people', NULL, 0, 'admin', '2021-09-20 16:26:19', '1', '2022-01-22 18:32:50', b'0', 0); +INSERT INTO `system_menu` VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'user', 'system/user/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); +INSERT INTO `system_menu` VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'peoples', 'system/role/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:49', b'0', 0); +INSERT INTO `system_menu` VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'tree-table', 'system/menu/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:04:28', b'0', 0); +INSERT INTO `system_menu` VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'tree', 'system/dept/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:19', b'0', 0); +INSERT INTO `system_menu` VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'post', 'system/post/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:23', b'0', 0); +INSERT INTO `system_menu` VALUES (105, '字典管理', '', 2, 6, 1, 'dict', 'dict', 'system/dict/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:16:58', b'0', 0); +INSERT INTO `system_menu` VALUES (106, '配置管理', '', 2, 1, 2, 'config', 'edit', 'infra/config/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:10', b'0', 0); +INSERT INTO `system_menu` VALUES (107, '通知公告', '', 2, 8, 1, 'notice', 'message', 'system/notice/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:39', b'0', 0); +INSERT INTO `system_menu` VALUES (108, '审计日志', '', 1, 9, 1, 'log', 'log', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-04-26 22:34:58', b'0', 0); +INSERT INTO `system_menu` VALUES (109, '在线用户', 'system:user-session:list', 2, 10, 1, 'user-session', 'online', 'system/session/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:21:20', b'0', 0); +INSERT INTO `system_menu` VALUES (110, '定时任务', '', 2, 2, 2, 'job', 'job', 'infra/job/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:25:51', b'0', 0); +INSERT INTO `system_menu` VALUES (111, 'MySQL 监控', '', 2, 4, 2, 'druid', 'druid', 'infra/druid/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:32', b'0', 0); +INSERT INTO `system_menu` VALUES (112, 'Java 监控', '', 2, 6, 2, 'admin-server', 'server', 'infra/server', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:41', b'0', 0); +INSERT INTO `system_menu` VALUES (113, 'Redis 监控', '', 2, 5, 2, 'redis', 'redis', 'infra/redis/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-26 02:18:37', b'0', 0); +INSERT INTO `system_menu` VALUES (114, '表单构建', 'tool:build:list', 2, 1, 3, 'build', 'build', 'tool/build/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); +INSERT INTO `system_menu` VALUES (115, '代码生成', 'tool:codegen:query', 2, 0, 3, 'codegen', 'code', 'tool/codegen/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-06 03:43:14', b'0', 0); +INSERT INTO `system_menu` VALUES (116, '系统接口', 'tool:swagger:list', 2, 3, 3, 'swagger', 'swagger', 'tool/swagger/index', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:45', b'0', 0); +INSERT INTO `system_menu` VALUES (500, '操作日志', '', 2, 1, 108, 'operate-log', 'form', 'system/operatelog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:42:56', b'0', 0); +INSERT INTO `system_menu` VALUES (501, '登录日志', '', 2, 2, 108, 'login-log', 'logininfor', 'system/loginlog/index', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:39:23', b'0', 0); +INSERT INTO `system_menu` VALUES (1001, '用户查询', 'system:user:query', 3, 1, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1002, '用户新增', 'system:user:create', 3, 2, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:47', b'0', 0); +INSERT INTO `system_menu` VALUES (1003, '用户修改', 'system:user:update', 3, 3, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:21:54', b'0', 0); +INSERT INTO `system_menu` VALUES (1004, '用户删除', 'system:user:delete', 3, 4, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:22:03', b'0', 0); +INSERT INTO `system_menu` VALUES (1005, '用户导出', 'system:user:export', 3, 5, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1006, '用户导入', 'system:user:import', 3, 6, 100, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1007, '重置密码', 'system:user:update-password', 3, 7, 100, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:20:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1008, '角色查询', 'system:role:query', 3, 1, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1009, '角色新增', 'system:role:create', 3, 2, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:24', b'0', 0); +INSERT INTO `system_menu` VALUES (1010, '角色修改', 'system:role:update', 3, 3, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:14', b'0', 0); +INSERT INTO `system_menu` VALUES (1011, '角色删除', 'system:role:delete', 3, 4, 101, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 22:05:05', b'0', 0); +INSERT INTO `system_menu` VALUES (1012, '角色导出', 'system:role:export', 3, 5, 101, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1013, '菜单查询', 'system:menu:query', 3, 1, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1014, '菜单新增', 'system:menu:create', 3, 2, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:36', b'0', 0); +INSERT INTO `system_menu` VALUES (1015, '菜单修改', 'system:menu:update', 3, 3, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1016, '菜单删除', 'system:menu:delete', 3, 4, 102, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-03-13 15:49:45', b'0', 0); +INSERT INTO `system_menu` VALUES (1017, '部门查询', 'system:dept:query', 3, 1, 103, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1018, '部门新增', 'system:dept:create', 3, 2, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1019, '部门修改', 'system:dept:update', 3, 3, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:37', b'0', 0); +INSERT INTO `system_menu` VALUES (1020, '部门删除', 'system:dept:delete', 3, 4, 103, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:25:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1021, '岗位查询', 'system:post:query', 3, 1, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1022, '岗位新增', 'system:post:create', 3, 2, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:34', b'0', 0); +INSERT INTO `system_menu` VALUES (1023, '岗位修改', 'system:post:update', 3, 3, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1024, '岗位删除', 'system:post:delete', 3, 4, 104, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 20:38:48', b'0', 0); +INSERT INTO `system_menu` VALUES (1025, '岗位导出', 'system:post:export', 3, 5, 104, '', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1026, '字典查询', 'system:dict:query', 3, 1, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1027, '字典新增', 'system:dict:create', 3, 2, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:29', b'0', 0); +INSERT INTO `system_menu` VALUES (1028, '字典修改', 'system:dict:update', 3, 3, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:36', b'0', 0); +INSERT INTO `system_menu` VALUES (1029, '字典删除', 'system:dict:delete', 3, 4, 105, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:19:45', b'0', 0); +INSERT INTO `system_menu` VALUES (1030, '字典导出', 'system:dict:export', 3, 5, 105, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1031, '配置查询', 'infra:config:query', 3, 1, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:00', b'0', 0); +INSERT INTO `system_menu` VALUES (1032, '配置新增', 'infra:config:create', 3, 2, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:18', b'0', 0); +INSERT INTO `system_menu` VALUES (1033, '配置修改', 'infra:config:update', 3, 3, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1034, '配置删除', 'infra:config:delete', 3, 4, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-10 01:12:36', b'0', 0); +INSERT INTO `system_menu` VALUES (1035, '配置导出', 'infra:config:export', 3, 5, 106, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-20 14:34:19', b'0', 0); +INSERT INTO `system_menu` VALUES (1036, '公告查询', 'system:notice:query', 3, 1, 107, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-05 22:36:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1037, '公告新增', 'system:notice:create', 3, 2, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:48', b'0', 0); +INSERT INTO `system_menu` VALUES (1038, '公告修改', 'system:notice:update', 3, 3, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:51:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1039, '公告删除', 'system:notice:delete', 3, 4, 107, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '1', '2021-03-14 21:52:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1040, '操作查询', 'system:operate-log:query', 3, 1, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:10', b'0', 0); +INSERT INTO `system_menu` VALUES (1042, '日志导出', 'system:operate-log:export', 3, 2, 500, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-16 18:28:23', b'0', 0); +INSERT INTO `system_menu` VALUES (1043, '登录查询', 'system:login-log:query', 3, 1, 501, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:26', b'0', 0); +INSERT INTO `system_menu` VALUES (1045, '日志导出', 'system:login-log:export', 3, 3, 501, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-18 05:29:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1046, '在线查询', 'system:user-session:list', 3, 1, 109, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:22:37', b'0', 0); +INSERT INTO `system_menu` VALUES (1047, '批量强退', 'monitor:online:batchLogout', 3, 2, 109, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:21:46', b'1', 0); +INSERT INTO `system_menu` VALUES (1048, '单条强退', 'system:user-session:delete', 3, 3, 109, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-01-26 08:22:54', b'0', 0); +INSERT INTO `system_menu` VALUES (1049, '任务查询', 'monitor:job:query', 3, 1, 110, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:01:42', b'1', 0); +INSERT INTO `system_menu` VALUES (1050, '任务新增', 'infra:job:create', 3, 2, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:01:58', b'0', 0); +INSERT INTO `system_menu` VALUES (1051, '任务修改', 'infra:job:update', 3, 3, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:10', b'0', 0); +INSERT INTO `system_menu` VALUES (1052, '任务删除', 'infra:job:delete', 3, 4, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:22', b'0', 0); +INSERT INTO `system_menu` VALUES (1053, '状态修改', 'infra:job:update', 3, 5, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:38', b'0', 0); +INSERT INTO `system_menu` VALUES (1054, '任务导出', 'infra:job:export', 3, 7, 110, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-07 13:02:51', b'0', 0); +INSERT INTO `system_menu` VALUES (1055, '生成查询', 'tool:gen:query', 3, 1, 115, '#', '#', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:25', b'1', 0); +INSERT INTO `system_menu` VALUES (1056, '生成修改', 'tool:codegen:update', 3, 2, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1057, '生成删除', 'tool:codegen:delete', 3, 3, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:02', b'0', 0); +INSERT INTO `system_menu` VALUES (1058, '导入代码', 'tool:codegen:create', 3, 2, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:23:50', b'0', 0); +INSERT INTO `system_menu` VALUES (1059, '预览代码', 'tool:codegen:preview', 3, 4, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:10', b'0', 0); +INSERT INTO `system_menu` VALUES (1060, '生成代码', 'tool:codegen:download', 3, 5, 115, '', '', '', 0, 'admin', '2021-01-05 17:03:48', '', '2021-02-06 21:24:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1063, '设置角色菜单权限', 'system:permission:assign-role-menu', 3, 6, 101, '', '', '', 0, '', '2021-01-06 17:53:44', '', '2021-01-06 17:55:23', b'0', 0); +INSERT INTO `system_menu` VALUES (1064, '设置角色数据权限', 'system:permission:assign-role-data-scope', 3, 7, 101, '', '', '', 0, '', '2021-01-06 17:56:31', '', '2021-01-06 17:56:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', 0, '', '2021-01-07 10:23:28', '', '2021-01-07 10:23:28', b'0', 0); +INSERT INTO `system_menu` VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', 0, '', '2021-01-26 01:02:31', '', '2021-01-26 01:02:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', 0, '', '2021-01-26 01:02:52', '', '2021-01-26 01:02:52', b'0', 0); +INSERT INTO `system_menu` VALUES (1070, '代码生成示例', 'tool:test-demo:query', 2, 0, 3, 'test-demo', 'validCode', 'tool/testDemo/index', 0, '', '2021-02-06 12:42:49', '', '2021-03-06 03:45:22', b'0', 0); +INSERT INTO `system_menu` VALUES (1071, '测试示例表创建', 'tool:test-demo:create', 3, 1, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:47', b'0', 0); +INSERT INTO `system_menu` VALUES (1072, '测试示例表更新', 'tool:test-demo:update', 3, 2, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:51', b'0', 0); +INSERT INTO `system_menu` VALUES (1073, '测试示例表删除', 'tool:test-demo:delete', 3, 3, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:53:58', b'0', 0); +INSERT INTO `system_menu` VALUES (1074, '测试示例表导出', 'tool:test-demo:export', 3, 4, 1070, '', '', '', 0, '', '2021-02-06 12:42:49', '', '2021-02-06 12:54:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1075, '任务触发', 'infra:job:trigger', 3, 8, 110, '', '', '', 0, '', '2021-02-07 13:03:10', '', '2021-02-07 13:03:10', b'0', 0); +INSERT INTO `system_menu` VALUES (1076, '数据库文档', '', 2, 5, 3, 'db-doc', 'table', 'tool/dbDoc/index', 0, '', '2021-02-08 01:41:47', '', '2021-02-08 01:49:00', b'0', 0); +INSERT INTO `system_menu` VALUES (1077, '链路追踪', '', 2, 7, 2, 'skywalking', 'eye-open', 'infra/skywalking', 0, '', '2021-02-08 20:41:31', '', '2021-02-26 02:18:45', b'0', 0); +INSERT INTO `system_menu` VALUES (1078, '访问日志', '', 2, 1, 1083, 'api-access-log', 'log', 'infra/apiAccessLog/index', 0, '', '2021-02-26 01:32:59', '1', '2021-03-10 01:28:09', b'0', 0); +INSERT INTO `system_menu` VALUES (1079, 'API 访问日志表创建', 'system:api-access-log:create', 3, 1, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:00', b'1', 0); +INSERT INTO `system_menu` VALUES (1080, 'API 访问日志表更新', 'system:api-access-log:update', 3, 2, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:08', b'1', 0); +INSERT INTO `system_menu` VALUES (1081, 'API 访问日志表删除', 'system:api-access-log:delete', 3, 3, 1078, '', '', '', 1, '', '2021-02-26 01:32:59', '', '2021-02-26 02:21:27', b'1', 0); +INSERT INTO `system_menu` VALUES (1082, '日志导出', 'infra:api-access-log:export', 3, 2, 1078, '', '', '', 0, '', '2021-02-26 01:32:59', '1', '2021-03-10 01:28:13', b'0', 0); +INSERT INTO `system_menu` VALUES (1083, 'API 日志', '', 2, 3, 2, 'log', 'log', NULL, 0, '', '2021-02-26 02:18:24', '', '2021-02-26 02:20:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1084, '错误日志', 'infra:api-error-log:query', 2, 2, 1083, 'api-error-log', 'log', 'infra/apiErrorLog/index', 0, '', '2021-02-26 07:53:20', '', '2021-02-26 07:54:40', b'0', 0); +INSERT INTO `system_menu` VALUES (1085, '日志处理', 'infra:api-error-log:update-status', 3, 2, 1084, '', '', '', 0, '', '2021-02-26 07:53:20', '1', '2021-03-10 01:28:18', b'0', 0); +INSERT INTO `system_menu` VALUES (1086, '日志导出', 'infra:api-error-log:export', 3, 3, 1084, '', '', '', 0, '', '2021-02-26 07:53:20', '1', '2021-03-10 01:28:21', b'0', 0); +INSERT INTO `system_menu` VALUES (1087, '任务查询', 'infra:job:query', 3, 1, 110, '', '', '', 0, '1', '2021-03-10 01:26:19', '1', '2021-03-10 01:26:19', b'0', 0); +INSERT INTO `system_menu` VALUES (1088, '日志查询', 'infra:api-access-log:query', 3, 1, 1078, '', '', '', 0, '1', '2021-03-10 01:28:04', '1', '2021-03-10 01:29:38', b'0', 0); +INSERT INTO `system_menu` VALUES (1089, '日志查询', 'infra:api-error-log:query', 3, 1, 1084, '', '', '', 0, '1', '2021-03-10 01:29:09', '1', '2021-03-10 01:29:09', b'0', 0); +INSERT INTO `system_menu` VALUES (1090, '文件管理', '', 2, 0, 2, 'file', 'upload', 'infra/file/index', 0, '', '2021-03-12 20:16:20', '1', '2021-03-13 11:07:05', b'0', 0); +INSERT INTO `system_menu` VALUES (1091, '文件查询', 'infra:file:query', 3, 1, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1092, '文件删除', 'infra:file:delete', 3, 4, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1093, '短信管理', '', 1, 11, 1, 'sms', 'validCode', NULL, 0, '1', '2021-04-05 01:10:16', '1', '2021-04-05 01:11:38', b'0', 0); +INSERT INTO `system_menu` VALUES (1094, '短信渠道', '', 2, 0, 1093, 'sms-channel', 'phone', 'system/sms/smsChannel', 0, '', '2021-04-01 11:07:15', '1', '2021-04-09 23:44:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1095, '短信渠道查询', 'system:sms-channel:query', 3, 1, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1096, '短信渠道创建', 'system:sms-channel:create', 3, 2, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1097, '短信渠道更新', 'system:sms-channel:update', 3, 3, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1098, '短信渠道删除', 'system:sms-channel:delete', 3, 4, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1100, '短信模板', '', 2, 1, 1093, 'sms-template', 'phone', 'system/sms/smsTemplate', 0, '', '2021-04-01 17:35:17', '1', '2021-04-11 19:34:21', b'0', 0); +INSERT INTO `system_menu` VALUES (1101, '短信模板查询', 'system:sms-template:query', 3, 1, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1102, '短信模板创建', 'system:sms-template:create', 3, 2, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1103, '短信模板更新', 'system:sms-template:update', 3, 3, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1104, '短信模板删除', 'system:sms-template:delete', 3, 4, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1105, '短信模板导出', 'system:sms-template:export', 3, 5, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0', 0); +INSERT INTO `system_menu` VALUES (1106, '发送测试短信', 'system:sms-template:send-sms', 3, 6, 1100, '', '', '', 0, '1', '2021-04-11 00:26:40', '1', '2021-04-11 00:26:40', b'0', 0); +INSERT INTO `system_menu` VALUES (1107, '短信日志', '', 2, 2, 1093, 'sms-log', 'phone', 'system/sms/smsLog', 0, '', '2021-04-11 08:37:05', '1', '2021-04-11 19:34:25', b'0', 0); +INSERT INTO `system_menu` VALUES (1108, '短信日志查询', 'system:sms-log:query', 3, 1, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0', 0); +INSERT INTO `system_menu` VALUES (1109, '短信日志导出', 'system:sms-log:export', 3, 5, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0', 0); +INSERT INTO `system_menu` VALUES (1110, '错误码管理', '', 2, 12, 1, 'error-code', 'code', 'system/errorCode/index', 0, '', '2021-04-13 21:46:42', '1', '2021-04-22 00:04:35', b'0', 0); +INSERT INTO `system_menu` VALUES (1111, '错误码查询', 'system:error-code:query', 3, 1, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:37', b'0', 0); +INSERT INTO `system_menu` VALUES (1112, '错误码创建', 'system:error-code:create', 3, 2, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1113, '错误码更新', 'system:error-code:update', 3, 3, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:47', b'0', 0); +INSERT INTO `system_menu` VALUES (1114, '错误码删除', 'system:error-code:delete', 3, 4, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:51', b'0', 0); +INSERT INTO `system_menu` VALUES (1115, '错误码导出', 'system:error-code:export', 3, 5, 1110, '', '', '', 0, '', '2021-04-13 21:46:42', '', '2021-04-13 22:09:55', b'0', 0); +INSERT INTO `system_menu` VALUES (1116, '日志中心', '', 2, 8, 2, 'log-center', 'log', 'infra/skywalking/log', 0, '1', '2021-04-26 22:35:45', '1', '2021-04-26 22:37:25', b'0', 0); +INSERT INTO `system_menu` VALUES (1117, '支付管理', '', 1, 11, 0, '/pay', 'money', NULL, 0, '1', '2021-12-25 16:43:41', '1', '2021-12-25 16:46:40', b'0', 0); +INSERT INTO `system_menu` VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'user', 'bpm/oa/leave/index', 0, '', '2021-09-20 08:51:03', '1', '2022-01-22 21:36:06', b'0', 0); +INSERT INTO `system_menu` VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '1', '2022-01-23 00:14:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '1', '2022-01-23 00:14:49', b'0', 0); +INSERT INTO `system_menu` VALUES (1121, '请假申请更新', 'oa:leave:update', 3, 3, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:26', b'1', 0); +INSERT INTO `system_menu` VALUES (1122, '请假申请删除', 'oa:leave:delete', 3, 4, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:28', b'1', 0); +INSERT INTO `system_menu` VALUES (1123, '请假申请导出', 'oa:leave:export', 3, 5, 1118, '', '', '', 0, '', '2021-09-20 08:51:03', '', '2022-01-22 16:14:30', b'1', 0); +INSERT INTO `system_menu` VALUES (1124, '待办任务', '', 2, 2, 5, 'todo', 'edit', 'oa/todo/index', 0, '1', '2021-09-20 22:10:09', '1', '2022-01-22 10:33:01', b'1', 0); +INSERT INTO `system_menu` VALUES (1125, '流程申请', '', 2, 3, 5, 'flow', 'form', 'oa/flow/index', 0, '1', '2021-10-23 22:10:09', '1', '2022-01-22 10:33:03', b'1', 0); +INSERT INTO `system_menu` VALUES (1126, '应用信息', '', 2, 1, 1117, 'app', 'table', 'pay/app/index', 0, '', '2021-11-10 01:13:30', '1', '2021-12-25 16:56:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1127, '支付应用信息查询', 'pay:app:query', 3, 1, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1128, '支付应用信息创建', 'pay:app:create', 3, 2, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1129, '支付应用信息更新', 'pay:app:update', 3, 3, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1130, '支付应用信息删除', 'pay:app:delete', 3, 4, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1131, '支付应用信息导出', 'pay:app:export', 3, 5, 1126, '', '', '', 0, '', '2021-11-10 01:13:31', '', '2021-11-10 01:13:31', b'0', 0); +INSERT INTO `system_menu` VALUES (1132, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', 0, '1', '2021-11-08 15:15:47', '1', '2021-11-08 15:15:47', b'0', 0); +INSERT INTO `system_menu` VALUES (1133, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1134, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1135, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1136, '支付商户信息删除', 'pay:merchant:delete', 3, 4, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1137, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1132, '', '', '', 0, '', '2021-11-10 01:13:41', '', '2021-11-10 01:13:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1138, '租户管理', '', 2, 0, 1, 'tenant', 'peoples', 'system/tenant/index', 0, '', '2021-12-14 12:31:43', '1', '2021-12-14 20:32:32', b'0', 0); +INSERT INTO `system_menu` VALUES (1139, '租户查询', 'system:tenant:query', 3, 1, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1140, '租户创建', 'system:tenant:create', 3, 2, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1141, '租户更新', 'system:tenant:update', 3, 3, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1142, '租户删除', 'system:tenant:delete', 3, 4, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1143, '租户导出', 'system:tenant:export', 3, 5, 1138, '', '', '', 0, '', '2021-12-14 12:31:44', '', '2021-12-14 12:31:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1144, '支付应用信息管理', '', 2, 0, 1117, 'app', '', 'pay/app/index', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:48:05', b'1', 0); +INSERT INTO `system_menu` VALUES (1145, '支付应用信息查询', 'pay:app:query', 3, 1, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:53', b'1', 0); +INSERT INTO `system_menu` VALUES (1146, '支付应用信息创建', 'pay:app:create', 3, 2, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:51', b'1', 0); +INSERT INTO `system_menu` VALUES (1147, '支付应用信息更新', 'pay:app:update', 3, 3, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:48', b'1', 0); +INSERT INTO `system_menu` VALUES (1148, '支付应用信息删除', 'pay:app:delete', 3, 4, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:46', b'1', 0); +INSERT INTO `system_menu` VALUES (1149, '支付应用信息导出', 'pay:app:export', 3, 5, 1144, '', '', '', 0, '', '2021-12-25 08:26:31', '', '2021-12-25 08:47:43', b'1', 0); +INSERT INTO `system_menu` VALUES (1150, '秘钥解析', 'pay:channel:parsing', 3, 6, 1129, '', '', '', 0, '1', '2021-11-08 15:15:47', '1', '2021-11-08 15:15:47', b'0', 0); +INSERT INTO `system_menu` VALUES (1156, '支付订单查询', 'pay:order:query', 3, 1, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1157, '支付订单创建', 'pay:order:create', 3, 2, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1158, '支付订单更新', 'pay:order:update', 3, 3, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1159, '支付订单删除', 'pay:order:delete', 3, 4, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1160, '支付订单导出', 'pay:order:export', 3, 5, 1155, '', '', '', 0, '', '2021-12-25 08:29:01', '', '2021-12-25 08:29:01', b'0', 0); +INSERT INTO `system_menu` VALUES (1161, '退款订单', '', 2, 3, 1117, 'refund', 'order', 'pay/refund/index', 0, '', '2021-12-25 08:29:07', '1', '2021-12-25 19:30:22', b'0', 0); +INSERT INTO `system_menu` VALUES (1162, '退款订单查询', 'pay:refund:query', 3, 1, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1163, '退款订单创建', 'pay:refund:create', 3, 2, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1164, '退款订单更新', 'pay:refund:update', 3, 3, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1165, '退款订单删除', 'pay:refund:delete', 3, 4, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1166, '退款订单导出', 'pay:refund:export', 3, 5, 1161, '', '', '', 0, '', '2021-12-25 08:29:07', '', '2021-12-25 08:29:07', b'0', 0); +INSERT INTO `system_menu` VALUES (1173, '支付订单', '', 2, 2, 1117, 'order', 'pay', 'pay/order/index', 0, '', '2021-12-25 08:49:43', '1', '2021-12-25 19:29:54', b'0', 0); +INSERT INTO `system_menu` VALUES (1174, '支付订单查询', 'pay:order:query', 3, 1, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1175, '支付订单创建', 'pay:order:create', 3, 2, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1176, '支付订单更新', 'pay:order:update', 3, 3, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1177, '支付订单删除', 'pay:order:delete', 3, 4, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1178, '支付订单导出', 'pay:order:export', 3, 5, 1173, '', '', '', 0, '', '2021-12-25 08:49:43', '', '2021-12-25 08:49:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1179, '商户信息', '', 2, 0, 1117, 'merchant', 'merchant', 'pay/merchant/index', 0, '', '2021-12-25 09:01:44', '1', '2021-12-25 17:02:13', b'0', 0); +INSERT INTO `system_menu` VALUES (1180, '支付商户信息查询', 'pay:merchant:query', 3, 1, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1181, '支付商户信息创建', 'pay:merchant:create', 3, 2, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1182, '支付商户信息更新', 'pay:merchant:update', 3, 3, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1183, '支付商户信息删除', 'pay:merchant:delete', 3, 4, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1184, '支付商户信息导出', 'pay:merchant:export', 3, 5, 1179, '', '', '', 0, '', '2021-12-25 09:01:44', '', '2021-12-25 09:01:44', b'0', 0); +INSERT INTO `system_menu` VALUES (1185, '工作流程', '', 1, 50, 0, '/bpm', 'tool', NULL, 0, '1', '2021-12-30 20:26:36', '103', '2022-01-14 18:44:00', b'0', 0); +INSERT INTO `system_menu` VALUES (1186, '流程管理', '', 1, 10, 1185, 'manager', 'nested', NULL, 0, '1', '2021-12-30 20:28:30', '1', '2021-12-30 20:28:57', b'0', 0); +INSERT INTO `system_menu` VALUES (1187, '流程表单', '', 2, 0, 1186, 'form', 'form', 'bpm/form/index', 0, '', '2021-12-30 12:38:22', '1', '2021-12-31 23:20:38', b'0', 0); +INSERT INTO `system_menu` VALUES (1188, '表单查询', 'bpm:form:query', 3, 1, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 18:59:53', b'0', 0); +INSERT INTO `system_menu` VALUES (1189, '表单创建', 'bpm:form:create', 3, 2, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 18:59:59', b'0', 0); +INSERT INTO `system_menu` VALUES (1190, '表单更新', 'bpm:form:update', 3, 3, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:21', b'0', 0); +INSERT INTO `system_menu` VALUES (1191, '表单删除', 'bpm:form:delete', 3, 4, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:26', b'0', 0); +INSERT INTO `system_menu` VALUES (1192, '表单导出', 'bpm:form:export', 3, 5, 1187, '', '', '', 0, '', '2021-12-30 12:38:22', '1', '2022-01-03 19:00:33', b'0', 0); +INSERT INTO `system_menu` VALUES (1193, '流程模型', '', 2, 5, 1186, 'model', 'guide', 'bpm/model/index', 0, '1', '2021-12-31 23:24:58', '103', '2022-01-14 10:14:38', b'0', 0); +INSERT INTO `system_menu` VALUES (1194, '模型查询', 'bpm:model:query', 3, 1, 1193, '', '', '', 0, '1', '2022-01-03 19:01:10', '1', '2022-01-03 19:01:10', b'0', 0); +INSERT INTO `system_menu` VALUES (1195, '模型创建', 'bpm:model:create', 3, 2, 1193, '', '', '', 0, '1', '2022-01-03 19:01:24', '1', '2022-01-03 19:02:02', b'0', 0); +INSERT INTO `system_menu` VALUES (1196, '模型导入', 'bpm:model:import', 3, 3, 1193, '', '', '', 0, '1', '2022-01-03 19:01:35', '1', '2022-01-03 19:02:11', b'0', 0); +INSERT INTO `system_menu` VALUES (1197, '模型更新', 'bpm:model:update', 3, 4, 1193, '', '', '', 0, '1', '2022-01-03 19:02:28', '1', '2022-01-03 19:02:28', b'0', 0); +INSERT INTO `system_menu` VALUES (1198, '模型删除', 'bpm:model:delete', 3, 5, 1193, '', '', '', 0, '1', '2022-01-03 19:02:43', '1', '2022-01-03 19:02:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1199, '模型发布', 'bpm:model:deploy', 3, 6, 1193, '', '', '', 0, '1', '2022-01-03 19:03:24', '1', '2022-01-03 19:03:24', b'0', 0); +INSERT INTO `system_menu` VALUES (1200, '任务管理', '', 1, 20, 1185, 'task', 'cascader', NULL, 0, '1', '2022-01-07 23:51:48', '1', '2022-01-07 23:51:48', b'0', 0); +INSERT INTO `system_menu` VALUES (1201, '我的流程', '', 2, 0, 1200, 'my', 'people', 'bpm/processInstance/index', 0, '', '2022-01-07 15:53:44', '1', '2022-01-08 16:44:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1202, '流程实例的查询', 'bpm:process-instance:query', 3, 1, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '1', '2022-01-07 23:56:29', b'0', 0); +INSERT INTO `system_menu` VALUES (1203, '工作流的流程实例的拓展创建', 'bpm:process-instance-ext:create', 3, 2, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:56:08', b'1', 0); +INSERT INTO `system_menu` VALUES (1204, '工作流的流程实例的拓展更新', 'bpm:process-instance-ext:update', 3, 3, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:56:00', b'1', 0); +INSERT INTO `system_menu` VALUES (1205, '工作流的流程实例的拓展删除', 'bpm:process-instance-ext:delete', 3, 4, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:55:56', b'1', 0); +INSERT INTO `system_menu` VALUES (1206, '工作流的流程实例的拓展导出', 'bpm:process-instance-ext:export', 3, 5, 1201, '', '', '', 0, '', '2022-01-07 15:53:44', '', '2022-01-07 15:55:51', b'1', 0); +INSERT INTO `system_menu` VALUES (1207, '待办任务', '', 2, 10, 1200, 'todo', 'eye-open', 'bpm/task/todo', 0, '1', '2022-01-08 10:33:37', '1', '2022-01-08 10:33:48', b'0', 0); +INSERT INTO `system_menu` VALUES (1208, '已办任务', '', 2, 20, 1200, 'done', 'eye', 'bpm/task/done', 0, '1', '2022-01-08 10:34:13', '1', '2022-01-08 10:34:13', b'0', 0); +INSERT INTO `system_menu` VALUES (1209, '用户分组', '', 2, 2, 1186, 'user-group', 'people', 'bpm/group/index', 0, '', '2022-01-14 02:14:20', '103', '2022-01-14 10:15:43', b'0', 0); +INSERT INTO `system_menu` VALUES (1210, '用户组查询', 'bpm:user-group:query', 3, 1, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1211, '用户组创建', 'bpm:user-group:create', 3, 2, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1212, '用户组更新', 'bpm:user-group:update', 3, 3, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1213, '用户组删除', 'bpm:user-group:delete', 3, 4, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:20', b'0', 0); +INSERT INTO `system_menu` VALUES (1214, '用户组导出', 'bpm:user-group:export', 3, 5, 1209, '', '', '', 0, '', '2022-01-14 02:14:20', '', '2022-01-14 02:14:58', b'1', 0); +INSERT INTO `system_menu` VALUES (1215, '流程定义查询', 'bpm:process-definition:query', 3, 10, 1193, '', '', '', 0, '1', '2022-01-23 00:21:43', '1', '2022-01-23 00:26:30', b'0', 0); +INSERT INTO `system_menu` VALUES (1216, '流程任务分配规则查询', 'bpm:task-assign-rule:query', 3, 20, 1193, '', '', '', 0, '1', '2022-01-23 00:26:53', '1', '2022-01-23 00:26:53', b'0', 0); +INSERT INTO `system_menu` VALUES (1217, '流程任务分配规则创建', 'bpm:task-assign-rule:create', 3, 21, 1193, '', '', '', 0, '1', '2022-01-23 00:28:15', '1', '2022-01-23 00:28:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1218, '流程任务分配规则更新', 'bpm:task-assign-rule:update', 3, 22, 1193, '', '', '', 0, '1', '2022-01-23 00:28:41', '1', '2022-01-23 00:28:41', b'0', 0); +INSERT INTO `system_menu` VALUES (1219, '流程实例的创建', 'bpm:process-instance:create', 3, 2, 1201, '', '', '', 0, '1', '2022-01-23 00:36:15', '1', '2022-01-23 00:36:15', b'0', 0); +INSERT INTO `system_menu` VALUES (1220, '流程实例的取消', 'bpm:process-instance:cancel', 3, 3, 1201, '', '', '', 0, '1', '2022-01-23 00:36:33', '1', '2022-01-23 00:36:33', b'0', 0); +INSERT INTO `system_menu` VALUES (1221, '流程任务的查询', 'bpm:task:query', 3, 1, 1207, '', '', '', 0, '1', '2022-01-23 00:38:52', '1', '2022-01-23 00:38:52', b'0', 0); +INSERT INTO `system_menu` VALUES (1222, '流程任务的更新', 'bpm:task:update', 3, 2, 1207, '', '', '', 0, '1', '2022-01-23 00:39:24', '1', '2022-01-23 00:39:30', b'0', 0); COMMIT; -- ---------------------------- --- Table structure for sys_notice +-- Table structure for system_notice -- ---------------------------- -DROP TABLE IF EXISTS `sys_notice`; -CREATE TABLE `sys_notice` ( +DROP TABLE IF EXISTS `system_notice`; +CREATE TABLE `system_notice` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '公告ID', `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '公告标题', `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '公告内容', @@ -2103,22 +2625,23 @@ CREATE TABLE `sys_notice` ( ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通知公告表'; -- ---------------------------- --- Records of sys_notice +-- Records of system_notice -- ---------------------------- BEGIN; -INSERT INTO `sys_notice` VALUES (1, '温馨提醒:2018-07-01 若依新版本发布啦', '新版本内容', 2, 0, 'admin', '2021-01-05 17:03:48', '', '2021-12-15 05:02:23', b'0', 1); -INSERT INTO `sys_notice` VALUES (2, '维护通知:2018-07-01 若依系统凌晨维护', '维护内容', 1, 0, 'admin', '2021-01-05 17:03:48', '', '2021-12-15 05:02:22', b'0', 1); -INSERT INTO `sys_notice` VALUES (3, '1133', '

222333

', 1, 0, '', '2021-01-13 05:24:52', '', '2021-12-15 05:02:21', b'1', 1); +INSERT INTO `system_notice` VALUES (1, '温馨提醒:2018-07-01 若依新版本发布啦', '新版本内容', 2, 0, 'admin', '2021-01-05 17:03:48', '', '2021-12-15 05:02:23', b'0', 1); +INSERT INTO `system_notice` VALUES (2, '维护通知:2018-07-01 若依系统凌晨维护', '维护内容', 1, 0, 'admin', '2021-01-05 17:03:48', '', '2021-12-15 05:02:22', b'0', 1); +INSERT INTO `system_notice` VALUES (3, '1133', '

222333

', 1, 0, '', '2021-01-13 05:24:52', '', '2021-12-15 05:02:21', b'1', 1); COMMIT; -- ---------------------------- --- Table structure for sys_operate_log +-- Table structure for system_operate_log -- ---------------------------- -DROP TABLE IF EXISTS `sys_operate_log`; -CREATE TABLE `sys_operate_log` ( +DROP TABLE IF EXISTS `system_operate_log`; +CREATE TABLE `system_operate_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志主键', `trace_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '链路追踪编号', `user_id` bigint NOT NULL COMMENT '用户编号', + `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型', `module` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模块标题', `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作名', `operate_type` bigint NOT NULL DEFAULT '0' COMMENT '操作分类', @@ -2142,28 +2665,37 @@ CREATE TABLE `sys_operate_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1099 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志记录'; +) ENGINE=InnoDB AUTO_INCREMENT=1108 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志记录'; -- ---------------------------- --- Records of sys_operate_log +-- Records of system_operate_log -- ---------------------------- BEGIN; +INSERT INTO `system_operate_log` VALUES (1099, '', 1, 0, '流程实例', '新建流程实例', 2, '', '', 'POST', '/api/bpm/process-instance/create', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', 'CommonResult cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.createProcessInstance(BpmProcessInstanceCreateReqVO)', '{\"createReqVO\":{\"processDefinitionId\":\"eee:17:f3aad03b-7ae5-11ec-a69c-a2380e71991a\",\"variables\":{\"field121\":\"AAA\",\"field122\":[1]}}}', '2022-01-23 12:41:14', 4959, 0, '', '\"b243fa82-7c06-11ec-9110-acde48001122\"', NULL, '2022-01-23 12:41:19', NULL, '2022-01-23 12:41:19', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1100, '', 1, 0, '流程实例', '新建流程实例', 2, '', '', 'POST', '/api/bpm/process-instance/create', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', 'CommonResult cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.createProcessInstance(BpmProcessInstanceCreateReqVO)', '{\"createReqVO\":{\"processDefinitionId\":\"test_001:4:3dbe6714-76b1-11ec-9c66-a2380e71991a\",\"variables\":{\"field121\":\"AAA\",\"field122\":[1]}}}', '2022-01-23 12:50:02', 4130, 0, '', '\"ecddb286-7c07-11ec-a41d-acde48001122\"', NULL, '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:06', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1101, '', 1, 0, '流程实例', '新建流程实例', 2, '', '', 'POST', '/api/bpm/process-instance/create', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', 'CommonResult cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.createProcessInstance(BpmProcessInstanceCreateReqVO)', '{\"createReqVO\":{\"processDefinitionId\":\"self:2:3a5a065e-76b1-11ec-9c66-a2380e71991a\",\"variables\":{\"field121\":\"aaa\",\"field122\":[1]}}}', '2022-01-23 12:50:46', 202, 500, 'RuntimeException: 123', 'null', NULL, '2022-01-23 12:50:46', NULL, '2022-01-23 12:50:46', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1102, '', 1, 0, '流程实例', '取消流程实例', 4, '', '', 'DELETE', '/api/bpm/process-instance/cancel', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', 'CommonResult cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.cancelProcessInstance(BpmProcessInstanceCancelReqVO)', '{\"cancelReqVO\":{\"id\":\"ecddb286-7c07-11ec-a41d-acde48001122\",\"reason\":\"aaa\"}}', '2022-01-23 12:59:40', 395, 0, '', 'true', NULL, '2022-01-23 12:59:41', NULL, '2022-01-23 12:59:41', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1103, '', 1, 0, '流程实例', '新建流程实例', 2, '', '', 'POST', '/api/bpm/process-instance/create', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', 'CommonResult cn.iocoder.yudao.adminserver.modules.bpm.controller.task.BpmProcessInstanceController.createProcessInstance(BpmProcessInstanceCreateReqVO)', '{\"createReqVO\":{\"processDefinitionId\":\"test:21:c2cd44b0-79b0-11ec-b2b8-a2380e71991a\",\"variables\":{\"field121\":\"aaa\",\"field122\":[1]}}}', '2022-01-23 12:59:57', 384, 0, '', '\"4f676a08-7c09-11ec-b8a1-acde48001122\"', NULL, '2022-01-23 12:59:57', NULL, '2022-01-23 12:59:57', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1104, '', 1, 0, '管理后台 - 用户', '修改用户', 3, '', '', 'PUT', '/admin-api/system/user/update', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', 'CommonResult cn.iocoder.yudao.module.system.controller.admin.user.UserController.updateUser(UserUpdateReqVO)', '{\"reqVO\":{\"username\":\"admin\",\"nickname\":\"芋道源码\",\"remark\":\"管理员\",\"deptId\":103,\"postIds\":[1],\"email\":\"aoteman@126.com\",\"mobile\":\"15612345678\",\"sex\":1,\"avatar\":\"http://127.0.0.1:48080/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f\",\"id\":1}}', '2022-02-01 22:58:45', 112, 0, '', 'true', NULL, '2022-02-01 22:58:45', NULL, '2022-02-01 22:58:45', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1105, '', 1, 0, '管理后台 - 认证', '取消社交绑定', 4, '', '', 'DELETE', '/admin-api/system/social-unbind', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', 'CommonResult cn.iocoder.yudao.module.system.controller.admin.auth.AuthController.socialUnbind(AuthSocialUnbindReqVO)', '{\"reqVO\":{\"type\":20,\"unionId\":\"IPRmJ0wvBptiPIlGEZiPewGwiEiE\"}}', '2022-02-01 23:00:30', 24, 0, '', 'true', NULL, '2022-02-01 23:00:30', NULL, '2022-02-01 23:00:30', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1106, '', 1, 0, '管理后台 - 定时任务', '更新定时任务的状态', 3, '', '', 'PUT', '/admin-api/infra/job/update-status', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', 'CommonResult cn.iocoder.yudao.module.infra.controller.admin.job.JobController.updateJobStatus(Long,Integer)', '{\"id\":3,\"status\":2}', '2022-02-02 01:00:08', 106, 0, '', 'true', NULL, '2022-02-02 01:00:08', NULL, '2022-02-02 01:00:08', b'0', 1); +INSERT INTO `system_operate_log` VALUES (1107, '', 1, 0, '管理后台 - 定时任务', '更新定时任务的状态', 3, '', '', 'PUT', '/admin-api/infra/job/update-status', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', 'CommonResult cn.iocoder.yudao.module.infra.controller.admin.job.JobController.updateJobStatus(Long,Integer)', '{\"id\":3,\"status\":1}', '2022-02-02 01:00:11', 58, 0, '', 'true', NULL, '2022-02-02 01:00:11', NULL, '2022-02-02 01:00:11', b'0', 1); COMMIT; -- ---------------------------- --- Table structure for sys_post +-- Table structure for system_post -- ---------------------------- -DROP TABLE IF EXISTS `sys_post`; -CREATE TABLE `sys_post` ( +DROP TABLE IF EXISTS `system_post`; +CREATE TABLE `system_post` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '岗位ID', - `code` varchar(64) NOT NULL COMMENT '岗位编码', - `name` varchar(50) NOT NULL COMMENT '岗位名称', + `code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '岗位编码', + `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '岗位名称', `sort` int NOT NULL COMMENT '显示顺序', `status` tinyint NOT NULL COMMENT '状态(0正常 1停用)', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', @@ -2171,362 +2703,374 @@ CREATE TABLE `sys_post` ( ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='岗位信息表'; -- ---------------------------- --- Records of sys_post +-- Records of system_post -- ---------------------------- BEGIN; -INSERT INTO `sys_post` VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:45', b'0', 1); -INSERT INTO `sys_post` VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:47', b'0', 1); -INSERT INTO `sys_post` VALUES (3, 'hr', '人力资源', 3, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-12-12 10:47:50', b'0', 1); -INSERT INTO `sys_post` VALUES (4, 'user', '普通员工', 4, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-12-12 10:47:51', b'0', 1); -INSERT INTO `sys_post` VALUES (5, 'test', '测试岗位', 0, 1, '132', '', '2021-01-07 15:07:44', '', '2021-12-12 10:47:53', b'1', 1); +INSERT INTO `system_post` VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:45', b'0', 1); +INSERT INTO `system_post` VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:47', b'0', 1); +INSERT INTO `system_post` VALUES (3, 'hr', '人力资源', 3, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-12-12 10:47:50', b'0', 1); +INSERT INTO `system_post` VALUES (4, 'user', '普通员工', 4, 0, '', 'admin', '2021-01-05 17:03:48', '', '2021-12-12 10:47:51', b'0', 1); +INSERT INTO `system_post` VALUES (5, 'test', '测试岗位', 0, 1, '132', '', '2021-01-07 15:07:44', '', '2021-12-12 10:47:53', b'1', 1); COMMIT; -- ---------------------------- --- Table structure for sys_role +-- Table structure for system_role -- ---------------------------- -DROP TABLE IF EXISTS `sys_role`; -CREATE TABLE `sys_role` ( +DROP TABLE IF EXISTS `system_role`; +CREATE TABLE `system_role` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID', - `name` varchar(30) NOT NULL COMMENT '角色名称', - `code` varchar(100) NOT NULL COMMENT '角色权限字符串', + `name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色名称', + `code` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色权限字符串', `sort` int NOT NULL COMMENT '显示顺序', `data_scope` tinyint NOT NULL DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', - `data_scope_dept_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '数据范围(指定部门数组)', + `data_scope_dept_ids` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '数据范围(指定部门数组)', `status` tinyint NOT NULL COMMENT '角色状态(0正常 1停用)', `type` tinyint NOT NULL COMMENT '角色类型', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色信息表'; -- ---------------------------- --- Records of sys_role +-- Records of system_role -- ---------------------------- BEGIN; -INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2021-12-15 04:52:44', b'0'); -INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 11:46:58', b'0'); -INSERT INTO `sys_role` VALUES (101, '测试账号', 'test', 0, 2, '[102,108,109]', 0, 2, '132', '', '2021-01-06 13:49:35', '1', '2021-12-16 09:27:01', b'0'); +INSERT INTO `system_role` VALUES (1, '超级管理员', 'admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2021-12-15 04:52:44', b'0'); +INSERT INTO `system_role` VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 11:46:58', b'0'); +INSERT INTO `system_role` VALUES (101, '测试账号', 'test', 0, 2, '[102,108,109]', 0, 2, '132', '', '2021-01-06 13:49:35', '1', '2021-12-16 09:27:01', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_role_menu +-- Table structure for system_role_menu -- ---------------------------- -DROP TABLE IF EXISTS `sys_role_menu`; -CREATE TABLE `sys_role_menu` ( +DROP TABLE IF EXISTS `system_role_menu`; +CREATE TABLE `system_role_menu` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增编号', `role_id` bigint NOT NULL COMMENT '角色ID', `menu_id` bigint NOT NULL COMMENT '菜单ID', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=253 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色和菜单关联表'; -- ---------------------------- --- Records of sys_role_menu +-- Records of system_role_menu -- ---------------------------- BEGIN; -INSERT INTO `sys_role_menu` VALUES (1, 2, 1, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (2, 2, 2, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (3, 2, 3, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (4, 2, 4, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (5, 2, 100, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (6, 2, 101, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (7, 2, 102, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (8, 2, 103, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (9, 2, 104, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (10, 2, 105, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (11, 2, 106, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (12, 2, 107, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (13, 2, 108, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (14, 2, 109, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (15, 2, 110, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (16, 2, 111, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (17, 2, 112, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (18, 2, 113, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (19, 2, 114, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (20, 2, 115, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (21, 2, 116, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (22, 2, 500, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (23, 2, 501, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (24, 2, 1000, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (25, 2, 1001, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (26, 2, 1002, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (27, 2, 1003, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (28, 2, 1004, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (29, 2, 1005, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (30, 2, 1006, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (31, 2, 1007, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (32, 2, 1008, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (33, 2, 1009, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (34, 2, 1010, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (35, 2, 1011, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (36, 2, 1012, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (37, 2, 1013, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (38, 2, 1014, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (39, 2, 1015, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (40, 2, 1016, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (41, 2, 1017, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (42, 2, 1018, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (43, 2, 1019, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (44, 2, 1020, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (45, 2, 1021, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (46, 2, 1022, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (47, 2, 1023, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (48, 2, 1024, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (49, 2, 1025, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (50, 2, 1026, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (51, 2, 1027, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (52, 2, 1028, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (53, 2, 1029, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (54, 2, 1030, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (55, 2, 1031, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (56, 2, 1032, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (57, 2, 1033, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (58, 2, 1034, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (59, 2, 1035, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (60, 2, 1036, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (61, 2, 1037, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (62, 2, 1038, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (63, 2, 1039, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (64, 2, 1040, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (65, 2, 1041, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (66, 2, 1042, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (67, 2, 1043, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (68, 2, 1044, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (69, 2, 1045, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (70, 2, 1046, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (71, 2, 1047, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (72, 2, 1048, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (73, 2, 1049, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (74, 2, 1050, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (75, 2, 1051, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (76, 2, 1052, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (77, 2, 1053, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (78, 2, 1054, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (79, 2, 1055, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); -INSERT INTO `sys_role_menu` VALUES (80, 2, 1056, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (81, 2, 1057, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (82, 2, 1058, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (83, 2, 1059, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (84, 2, 1060, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); -INSERT INTO `sys_role_menu` VALUES (169, 101, 1001, '', '2021-01-21 02:15:01', '', '2021-01-21 03:04:50', b'1'); -INSERT INTO `sys_role_menu` VALUES (170, 101, 1, '', '2021-01-21 02:39:45', '', '2021-01-21 03:13:11', b'1'); -INSERT INTO `sys_role_menu` VALUES (171, 101, 100, '', '2021-01-21 02:39:45', '', '2021-01-21 03:13:11', b'1'); -INSERT INTO `sys_role_menu` VALUES (172, 101, 1024, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (173, 101, 1025, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (174, 101, 1026, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (175, 101, 1027, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (176, 101, 1028, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (177, 101, 1029, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (178, 101, 1030, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (179, 101, 1036, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (180, 101, 1037, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (181, 101, 1038, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (182, 101, 1039, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (183, 101, 1040, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (184, 101, 1042, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (185, 101, 1043, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (186, 101, 1045, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (187, 101, 1063, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (188, 101, 1064, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (189, 101, 1065, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (190, 101, 1007, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (191, 101, 1008, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (192, 101, 1009, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (193, 101, 1010, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (194, 101, 1011, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (195, 101, 1012, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (196, 101, 1013, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (197, 101, 1014, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (198, 101, 1015, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (199, 101, 1016, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (200, 101, 1017, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (201, 101, 1018, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (202, 101, 1019, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (203, 101, 1020, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (204, 101, 1021, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (205, 101, 1022, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (206, 101, 1023, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); -INSERT INTO `sys_role_menu` VALUES (207, 101, 1001, '', '2021-01-21 03:07:43', '', '2021-01-21 03:13:11', b'1'); -INSERT INTO `sys_role_menu` VALUES (208, 101, 1002, '', '2021-01-21 03:07:43', '', '2021-01-21 03:10:08', b'1'); -INSERT INTO `sys_role_menu` VALUES (209, 101, 1002, '', '2021-01-21 03:11:17', '', '2021-01-21 03:13:11', b'1'); -INSERT INTO `sys_role_menu` VALUES (210, 101, 1, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:21', b'0'); -INSERT INTO `sys_role_menu` VALUES (211, 101, 1001, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:40', b'1'); -INSERT INTO `sys_role_menu` VALUES (212, 101, 100, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:40', b'1'); -INSERT INTO `sys_role_menu` VALUES (213, 101, 1008, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (214, 101, 1009, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (215, 101, 1010, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (216, 101, 1011, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (217, 101, 1012, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (218, 101, 101, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (219, 101, 1063, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (220, 101, 1064, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (221, 101, 1065, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); -INSERT INTO `sys_role_menu` VALUES (222, 101, 100, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (223, 101, 1001, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (224, 101, 1002, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (225, 101, 1003, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (226, 101, 1004, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (227, 101, 1005, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (228, 101, 1006, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (229, 101, 1007, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); -INSERT INTO `sys_role_menu` VALUES (230, 101, 1008, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (231, 101, 1009, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (232, 101, 1010, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (233, 101, 1011, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (234, 101, 1012, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (235, 101, 101, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (236, 101, 1063, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (237, 101, 1064, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (238, 101, 1065, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); -INSERT INTO `sys_role_menu` VALUES (239, 101, 100, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (240, 101, 1001, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (241, 101, 1002, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (242, 101, 1003, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (243, 101, 1004, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (244, 101, 1005, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (245, 101, 1006, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (246, 101, 1007, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (247, 101, 1138, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (248, 101, 1139, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (249, 101, 1140, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (250, 101, 1141, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (251, 101, 1142, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); -INSERT INTO `sys_role_menu` VALUES (252, 101, 1143, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (1, 2, 1, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (2, 2, 2, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (3, 2, 3, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (4, 2, 4, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (5, 2, 100, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (6, 2, 101, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (7, 2, 102, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (8, 2, 103, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (9, 2, 104, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (10, 2, 105, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (11, 2, 106, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (12, 2, 107, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (13, 2, 108, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (14, 2, 109, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (15, 2, 110, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (16, 2, 111, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (17, 2, 112, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (18, 2, 113, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (19, 2, 114, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (20, 2, 115, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (21, 2, 116, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (22, 2, 500, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (23, 2, 501, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (24, 2, 1000, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (25, 2, 1001, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (26, 2, 1002, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (27, 2, 1003, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (28, 2, 1004, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (29, 2, 1005, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (30, 2, 1006, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (31, 2, 1007, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (32, 2, 1008, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (33, 2, 1009, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (34, 2, 1010, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (35, 2, 1011, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (36, 2, 1012, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (37, 2, 1013, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (38, 2, 1014, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (39, 2, 1015, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (40, 2, 1016, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (41, 2, 1017, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (42, 2, 1018, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (43, 2, 1019, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (44, 2, 1020, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (45, 2, 1021, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (46, 2, 1022, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (47, 2, 1023, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (48, 2, 1024, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (49, 2, 1025, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (50, 2, 1026, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (51, 2, 1027, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (52, 2, 1028, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (53, 2, 1029, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (54, 2, 1030, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (55, 2, 1031, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (56, 2, 1032, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (57, 2, 1033, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (58, 2, 1034, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (59, 2, 1035, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (60, 2, 1036, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (61, 2, 1037, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (62, 2, 1038, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (63, 2, 1039, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (64, 2, 1040, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (65, 2, 1041, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (66, 2, 1042, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (67, 2, 1043, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (68, 2, 1044, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (69, 2, 1045, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (70, 2, 1046, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (71, 2, 1047, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (72, 2, 1048, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (73, 2, 1049, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (74, 2, 1050, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (75, 2, 1051, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (76, 2, 1052, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (77, 2, 1053, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (78, 2, 1054, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (79, 2, 1055, '', '2021-01-06 17:28:04', '', '2021-01-06 17:48:51', b'1'); +INSERT INTO `system_role_menu` VALUES (80, 2, 1056, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (81, 2, 1057, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (82, 2, 1058, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (83, 2, 1059, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (84, 2, 1060, '', '2021-01-06 17:28:04', '', '2021-01-06 17:28:04', b'0'); +INSERT INTO `system_role_menu` VALUES (169, 101, 1001, '', '2021-01-21 02:15:01', '', '2021-01-21 03:04:50', b'1'); +INSERT INTO `system_role_menu` VALUES (170, 101, 1, '', '2021-01-21 02:39:45', '', '2021-01-21 03:13:11', b'1'); +INSERT INTO `system_role_menu` VALUES (171, 101, 100, '', '2021-01-21 02:39:45', '', '2021-01-21 03:13:11', b'1'); +INSERT INTO `system_role_menu` VALUES (172, 101, 1024, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (173, 101, 1025, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (174, 101, 1026, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (175, 101, 1027, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (176, 101, 1028, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (177, 101, 1029, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (178, 101, 1030, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (179, 101, 1036, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (180, 101, 1037, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (181, 101, 1038, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (182, 101, 1039, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (183, 101, 1040, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (184, 101, 1042, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (185, 101, 1043, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (186, 101, 1045, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (187, 101, 1063, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (188, 101, 1064, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (189, 101, 1065, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (190, 101, 1007, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (191, 101, 1008, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (192, 101, 1009, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (193, 101, 1010, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (194, 101, 1011, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (195, 101, 1012, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (196, 101, 1013, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (197, 101, 1014, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (198, 101, 1015, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (199, 101, 1016, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (200, 101, 1017, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (201, 101, 1018, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (202, 101, 1019, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (203, 101, 1020, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (204, 101, 1021, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (205, 101, 1022, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (206, 101, 1023, '', '2021-01-21 03:04:50', '', '2021-01-21 03:07:43', b'1'); +INSERT INTO `system_role_menu` VALUES (207, 101, 1001, '', '2021-01-21 03:07:43', '', '2021-01-21 03:13:11', b'1'); +INSERT INTO `system_role_menu` VALUES (208, 101, 1002, '', '2021-01-21 03:07:43', '', '2021-01-21 03:10:08', b'1'); +INSERT INTO `system_role_menu` VALUES (209, 101, 1002, '', '2021-01-21 03:11:17', '', '2021-01-21 03:13:11', b'1'); +INSERT INTO `system_role_menu` VALUES (210, 101, 1, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:21', b'0'); +INSERT INTO `system_role_menu` VALUES (211, 101, 1001, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:40', b'1'); +INSERT INTO `system_role_menu` VALUES (212, 101, 100, '', '2021-01-21 03:13:21', '', '2021-01-21 03:13:40', b'1'); +INSERT INTO `system_role_menu` VALUES (213, 101, 1008, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (214, 101, 1009, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (215, 101, 1010, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (216, 101, 1011, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (217, 101, 1012, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (218, 101, 101, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (219, 101, 1063, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (220, 101, 1064, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (221, 101, 1065, '', '2021-01-21 03:13:40', '', '2021-01-21 03:23:14', b'1'); +INSERT INTO `system_role_menu` VALUES (222, 101, 100, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (223, 101, 1001, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (224, 101, 1002, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (225, 101, 1003, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (226, 101, 1004, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (227, 101, 1005, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (228, 101, 1006, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (229, 101, 1007, '', '2021-01-21 03:23:14', '', '2021-01-21 03:23:27', b'1'); +INSERT INTO `system_role_menu` VALUES (230, 101, 1008, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (231, 101, 1009, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (232, 101, 1010, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (233, 101, 1011, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (234, 101, 1012, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (235, 101, 101, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (236, 101, 1063, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (237, 101, 1064, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (238, 101, 1065, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0'); +INSERT INTO `system_role_menu` VALUES (239, 101, 100, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (240, 101, 1001, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (241, 101, 1002, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (242, 101, 1003, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (243, 101, 1004, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (244, 101, 1005, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (245, 101, 1006, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (246, 101, 1007, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (247, 101, 1138, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (248, 101, 1139, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (249, 101, 1140, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (250, 101, 1141, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (251, 101, 1142, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); +INSERT INTO `system_role_menu` VALUES (252, 101, 1143, '1', '2021-12-15 22:47:51', '1', '2021-12-15 22:47:51', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_sms_channel +-- Table structure for system_sms_channel -- ---------------------------- -DROP TABLE IF EXISTS `sys_sms_channel`; -CREATE TABLE `sys_sms_channel` ( +DROP TABLE IF EXISTS `system_sms_channel`; +CREATE TABLE `system_sms_channel` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `signature` varchar(10) NOT NULL COMMENT '短信签名', - `code` varchar(63) NOT NULL COMMENT '渠道编码', + `signature` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信签名', + `code` varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '渠道编码', `status` tinyint NOT NULL COMMENT '开启状态', - `remark` varchar(255) DEFAULT NULL COMMENT '备注', - `api_key` varchar(128) NOT NULL COMMENT '短信 API 的账号', - `api_secret` varchar(128) DEFAULT NULL COMMENT '短信 API 的秘钥', - `callback_url` varchar(255) DEFAULT NULL COMMENT '短信发送回调 URL', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `api_key` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信 API 的账号', + `api_secret` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信 API 的秘钥', + `callback_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信发送回调 URL', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='短信渠道'; -- ---------------------------- --- Records of sys_sms_channel +-- Records of system_sms_channel -- ---------------------------- BEGIN; -INSERT INTO `sys_sms_channel` VALUES (1, '芋道', 'YUN_PIAN', 0, '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://java.nat300.top/api/system/sms/callback/sms/yunpian', '', '2021-03-31 06:12:20', '1', '2021-04-13 01:03:19', b'0'); -INSERT INTO `sys_sms_channel` VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-14 00:08:37', b'0'); -INSERT INTO `sys_sms_channel` VALUES (3, '测试', 'YUN_PIAN', 0, '哈哈哈', '23132', NULL, 'http://www.baidu.com', '1', '2021-04-05 21:10:34', '1', '2021-04-11 16:21:58', b'1'); -INSERT INTO `sys_sms_channel` VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2021-04-14 00:07:10', b'0'); +INSERT INTO `system_sms_channel` VALUES (1, '芋道', 'YUN_PIAN', 0, '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://java.nat300.top/api/system/sms/callback/sms/yunpian', '', '2021-03-31 06:12:20', '1', '2021-04-13 01:03:19', b'0'); +INSERT INTO `system_sms_channel` VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-14 00:08:37', b'0'); +INSERT INTO `system_sms_channel` VALUES (3, '测试', 'YUN_PIAN', 0, '哈哈哈', '23132', NULL, 'http://www.baidu.com', '1', '2021-04-05 21:10:34', '1', '2021-04-11 16:21:58', b'1'); +INSERT INTO `system_sms_channel` VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2021-04-14 00:07:10', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_sms_code +-- Table structure for system_sms_code -- ---------------------------- -DROP TABLE IF EXISTS `sys_sms_code`; -CREATE TABLE `sys_sms_code` ( +DROP TABLE IF EXISTS `system_sms_code`; +CREATE TABLE `system_sms_code` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `mobile` varchar(11) NOT NULL COMMENT '手机号', - `code` varchar(6) NOT NULL COMMENT '验证码', - `create_ip` varchar(15) NOT NULL COMMENT '创建 IP', + `mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '手机号', + `code` varchar(6) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '验证码', + `create_ip` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '创建 IP', `scene` tinyint NOT NULL COMMENT '发送场景', `today_index` tinyint NOT NULL COMMENT '今日发送的第几条', `used` tinyint NOT NULL COMMENT '是否使用', `used_time` datetime DEFAULT NULL COMMENT '使用时间', - `used_ip` varchar(255) DEFAULT NULL COMMENT '使用 IP', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `used_ip` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '使用 IP', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE, KEY `idx_mobile` (`mobile`) USING BTREE COMMENT '手机号' -) ENGINE=InnoDB AUTO_INCREMENT=462 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='手机验证码'; +) ENGINE=InnoDB AUTO_INCREMENT=464 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='手机验证码'; -- ---------------------------- --- Records of sys_sms_code +-- Records of system_sms_code -- ---------------------------- BEGIN; -INSERT INTO `sys_sms_code` VALUES (445, '15601691300', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-10-10 21:46:49', NULL, '2021-10-10 21:46:49', b'0'); -INSERT INTO `sys_sms_code` VALUES (446, '15601691300', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-10-10 21:47:51', NULL, '2021-10-10 21:47:51', b'0'); -INSERT INTO `sys_sms_code` VALUES (447, '15601691300', '9999', '127.0.0.1', 1, 3, 0, NULL, NULL, NULL, '2021-10-10 21:48:55', NULL, '2021-10-10 21:48:55', b'0'); -INSERT INTO `sys_sms_code` VALUES (448, '15601691300', '9999', '127.0.0.1', 1, 4, 1, '2021-10-10 22:32:52', '127.0.0.1', NULL, '2021-10-10 22:32:49', NULL, '2021-10-10 22:32:52', b'0'); -INSERT INTO `sys_sms_code` VALUES (449, '15601691300', '9999', '127.0.0.1', 1, 5, 1, '2021-10-10 22:34:03', '127.0.0.1', NULL, '2021-10-10 22:34:01', NULL, '2021-10-10 22:34:03', b'0'); -INSERT INTO `sys_sms_code` VALUES (450, '15601691301', '9999', '127.0.0.1', 1, 1, 1, '2021-10-10 22:36:27', '127.0.0.1', NULL, '2021-10-10 22:34:12', NULL, '2021-10-10 22:36:27', b'0'); -INSERT INTO `sys_sms_code` VALUES (451, '15601691399', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-10-12 08:29:09', NULL, '2021-10-12 08:29:09', b'0'); -INSERT INTO `sys_sms_code` VALUES (452, '15601691399', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-10-12 08:42:16', NULL, '2021-10-12 08:42:16', b'0'); -INSERT INTO `sys_sms_code` VALUES (453, '15601691300', '9999', '127.0.0.1', 1, 6, 0, NULL, NULL, NULL, '2021-11-28 20:29:24', NULL, '2021-11-28 20:29:24', b'0'); -INSERT INTO `sys_sms_code` VALUES (454, '15601691300', '9999', '127.0.0.1', 1, 7, 0, NULL, NULL, NULL, '2021-11-28 20:30:33', NULL, '2021-11-28 20:30:33', b'0'); -INSERT INTO `sys_sms_code` VALUES (455, '15601691300', '9999', '127.0.0.1', 1, 8, 0, NULL, NULL, NULL, '2021-11-28 20:31:49', NULL, '2021-11-28 20:31:49', b'0'); -INSERT INTO `sys_sms_code` VALUES (456, '15601691301', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-11-28 20:32:22', NULL, '2021-11-28 20:32:22', b'0'); -INSERT INTO `sys_sms_code` VALUES (457, '15601691302', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-11-28 20:33:04', NULL, '2021-11-28 20:33:04', b'0'); -INSERT INTO `sys_sms_code` VALUES (458, '15601691322', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-11-28 20:33:24', NULL, '2021-11-28 20:33:24', b'0'); -INSERT INTO `sys_sms_code` VALUES (459, '15601691322', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-11-28 20:34:48', NULL, '2021-11-28 20:34:48', b'0'); -INSERT INTO `sys_sms_code` VALUES (460, '15601691300', '9999', '127.0.0.1', 1, 9, 1, '2021-11-28 20:37:02', '127.0.0.1', NULL, '2021-11-28 20:36:59', NULL, '2021-11-28 20:37:02', b'0'); -INSERT INTO `sys_sms_code` VALUES (461, '15601691300', '9999', '127.0.0.1', 1, 10, 1, '2021-11-28 20:47:51', '127.0.0.1', '245', '2021-11-28 20:47:49', '245', '2021-11-28 20:47:51', b'0'); +INSERT INTO `system_sms_code` VALUES (445, '15601691300', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-10-10 21:46:49', NULL, '2021-10-10 21:46:49', b'0'); +INSERT INTO `system_sms_code` VALUES (446, '15601691300', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-10-10 21:47:51', NULL, '2021-10-10 21:47:51', b'0'); +INSERT INTO `system_sms_code` VALUES (447, '15601691300', '9999', '127.0.0.1', 1, 3, 0, NULL, NULL, NULL, '2021-10-10 21:48:55', NULL, '2021-10-10 21:48:55', b'0'); +INSERT INTO `system_sms_code` VALUES (448, '15601691300', '9999', '127.0.0.1', 1, 4, 1, '2021-10-10 22:32:52', '127.0.0.1', NULL, '2021-10-10 22:32:49', NULL, '2021-10-10 22:32:52', b'0'); +INSERT INTO `system_sms_code` VALUES (449, '15601691300', '9999', '127.0.0.1', 1, 5, 1, '2021-10-10 22:34:03', '127.0.0.1', NULL, '2021-10-10 22:34:01', NULL, '2021-10-10 22:34:03', b'0'); +INSERT INTO `system_sms_code` VALUES (450, '15601691301', '9999', '127.0.0.1', 1, 1, 1, '2021-10-10 22:36:27', '127.0.0.1', NULL, '2021-10-10 22:34:12', NULL, '2021-10-10 22:36:27', b'0'); +INSERT INTO `system_sms_code` VALUES (451, '15601691399', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-10-12 08:29:09', NULL, '2021-10-12 08:29:09', b'0'); +INSERT INTO `system_sms_code` VALUES (452, '15601691399', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-10-12 08:42:16', NULL, '2021-10-12 08:42:16', b'0'); +INSERT INTO `system_sms_code` VALUES (453, '15601691300', '9999', '127.0.0.1', 1, 6, 0, NULL, NULL, NULL, '2021-11-28 20:29:24', NULL, '2021-11-28 20:29:24', b'0'); +INSERT INTO `system_sms_code` VALUES (454, '15601691300', '9999', '127.0.0.1', 1, 7, 0, NULL, NULL, NULL, '2021-11-28 20:30:33', NULL, '2021-11-28 20:30:33', b'0'); +INSERT INTO `system_sms_code` VALUES (455, '15601691300', '9999', '127.0.0.1', 1, 8, 0, NULL, NULL, NULL, '2021-11-28 20:31:49', NULL, '2021-11-28 20:31:49', b'0'); +INSERT INTO `system_sms_code` VALUES (456, '15601691301', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-11-28 20:32:22', NULL, '2021-11-28 20:32:22', b'0'); +INSERT INTO `system_sms_code` VALUES (457, '15601691302', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-11-28 20:33:04', NULL, '2021-11-28 20:33:04', b'0'); +INSERT INTO `system_sms_code` VALUES (458, '15601691322', '9999', '127.0.0.1', 1, 1, 0, NULL, NULL, NULL, '2021-11-28 20:33:24', NULL, '2021-11-28 20:33:24', b'0'); +INSERT INTO `system_sms_code` VALUES (459, '15601691322', '9999', '127.0.0.1', 1, 2, 0, NULL, NULL, NULL, '2021-11-28 20:34:48', NULL, '2021-11-28 20:34:48', b'0'); +INSERT INTO `system_sms_code` VALUES (460, '15601691300', '9999', '127.0.0.1', 1, 9, 1, '2021-11-28 20:37:02', '127.0.0.1', NULL, '2021-11-28 20:36:59', NULL, '2021-11-28 20:37:02', b'0'); +INSERT INTO `system_sms_code` VALUES (461, '15601691300', '9999', '127.0.0.1', 1, 10, 1, '2021-11-28 20:47:51', '127.0.0.1', '245', '2021-11-28 20:47:49', '245', '2021-11-28 20:47:51', b'0'); +INSERT INTO `system_sms_code` VALUES (462, '15601691399', '9999', '127.0.0.1', 1, 3, 0, NULL, NULL, NULL, '2022-01-29 11:50:26', NULL, '2022-01-29 11:50:26', b'0'); +INSERT INTO `system_sms_code` VALUES (463, '15601691399', '9999', '127.0.0.1', 1, 4, 0, NULL, NULL, NULL, '2022-01-29 13:58:06', NULL, '2022-01-29 13:58:06', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_sms_log +-- Table structure for system_sms_log -- ---------------------------- -DROP TABLE IF EXISTS `sys_sms_log`; -CREATE TABLE `sys_sms_log` ( +DROP TABLE IF EXISTS `system_sms_log`; +CREATE TABLE `system_sms_log` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `channel_id` bigint NOT NULL COMMENT '短信渠道编号', - `channel_code` varchar(63) NOT NULL COMMENT '短信渠道编码', + `channel_code` varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信渠道编码', `template_id` bigint NOT NULL COMMENT '模板编号', - `template_code` varchar(63) NOT NULL COMMENT '模板编码', + `template_code` varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模板编码', `template_type` tinyint NOT NULL COMMENT '短信类型', - `template_content` varchar(255) NOT NULL COMMENT '短信内容', - `template_params` varchar(255) NOT NULL COMMENT '短信参数', - `api_template_id` varchar(63) NOT NULL COMMENT '短信 API 的模板编号', - `mobile` varchar(11) NOT NULL COMMENT '手机号', + `template_content` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信内容', + `template_params` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信参数', + `api_template_id` varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '短信 API 的模板编号', + `mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '手机号', `user_id` bigint DEFAULT NULL COMMENT '用户编号', `user_type` tinyint DEFAULT NULL COMMENT '用户类型', `send_status` tinyint NOT NULL DEFAULT '0' COMMENT '发送状态', `send_time` datetime DEFAULT NULL COMMENT '发送时间', `send_code` int DEFAULT NULL COMMENT '发送结果的编码', - `send_msg` varchar(255) DEFAULT NULL COMMENT '发送结果的提示', - `api_send_code` varchar(63) DEFAULT NULL COMMENT '短信 API 发送结果的编码', - `api_send_msg` varchar(255) DEFAULT NULL COMMENT '短信 API 发送失败的提示', - `api_request_id` varchar(255) DEFAULT NULL COMMENT '短信 API 发送返回的唯一请求 ID', - `api_serial_no` varchar(255) DEFAULT NULL COMMENT '短信 API 发送返回的序号', + `send_msg` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发送结果的提示', + `api_send_code` varchar(63) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信 API 发送结果的编码', + `api_send_msg` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信 API 发送失败的提示', + `api_request_id` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信 API 发送返回的唯一请求 ID', + `api_serial_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '短信 API 发送返回的序号', `receive_status` tinyint NOT NULL DEFAULT '0' COMMENT '接收状态', `receive_time` datetime DEFAULT NULL COMMENT '接收时间', - `api_receive_code` varchar(63) DEFAULT NULL COMMENT 'API 接收结果的编码', - `api_receive_msg` varchar(255) DEFAULT NULL COMMENT 'API 接收结果的说明', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `api_receive_code` varchar(63) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'API 接收结果的编码', + `api_receive_msg` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'API 接收结果的说明', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=116 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='短信日志'; +) ENGINE=InnoDB AUTO_INCREMENT=126 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='短信日志'; -- ---------------------------- --- Records of sys_sms_log +-- Records of system_sms_log -- ---------------------------- BEGIN; +INSERT INTO `system_sms_log` VALUES (116, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:eeee-申请,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=b243fa82-7c06-11ec-9110-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"申请\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=b243fa82-7c06-11ec-9110-acde48001122\",\"processInstanceName\":\"eeee\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:41:21', 0, '成功', '0', NULL, NULL, 'b8b77315-6e6f-46a4-82e7-8610d198bef8', 0, NULL, NULL, NULL, '1', '2022-01-23 12:41:19', NULL, '2022-01-23 12:41:21', b'0'); +INSERT INTO `system_sms_log` VALUES (117, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:eeee-申请,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=b243fa82-7c06-11ec-9110-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"申请\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=b243fa82-7c06-11ec-9110-acde48001122\",\"processInstanceName\":\"eeee\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:41:21', 0, '成功', '0', NULL, NULL, 'b06bbd9b-912b-4d61-9dc2-a7f7e336ebe2', 0, NULL, NULL, NULL, '1', '2022-01-23 12:41:19', NULL, '2022-01-23 12:41:21', b'0'); +INSERT INTO `system_sms_log` VALUES (118, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:测试多审批人-1.1,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"1.1\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122\",\"processInstanceName\":\"测试多审批人\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:50:08', 0, '成功', '0', NULL, NULL, '97c8032c-e159-4e96-8d4a-c087a780f390', 0, NULL, NULL, NULL, '1', '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:08', b'0'); +INSERT INTO `system_sms_log` VALUES (119, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:测试多审批人-1.2,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"1.2\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122\",\"processInstanceName\":\"测试多审批人\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:50:08', 0, '成功', '0', NULL, NULL, '880a1432-2de0-409d-9e72-0e9ecbe073fb', 0, NULL, NULL, NULL, '1', '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:08', b'0'); +INSERT INTO `system_sms_log` VALUES (120, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:测试多审批人-1.2,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"1.2\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122\",\"processInstanceName\":\"测试多审批人\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:50:08', 0, '成功', '0', NULL, NULL, 'de12a261-fc48-4a0c-8b9d-8628f6697ca8', 0, NULL, NULL, NULL, '1', '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:08', b'0'); +INSERT INTO `system_sms_log` VALUES (121, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:测试多审批人-1.1,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"1.1\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=ecddb286-7c07-11ec-a41d-acde48001122\",\"processInstanceName\":\"测试多审批人\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:50:08', 0, '成功', '0', NULL, NULL, '0d482592-56c2-4855-b846-b218fafa8b2f', 0, NULL, NULL, NULL, '1', '2022-01-23 12:50:06', NULL, '2022-01-23 12:50:08', b'0'); +INSERT INTO `system_sms_log` VALUES (122, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:滔博-任务一,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=4f676a08-7c09-11ec-b8a1-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"任务一\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=4f676a08-7c09-11ec-b8a1-acde48001122\",\"processInstanceName\":\"滔博\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:59:58', 0, '成功', '0', NULL, NULL, '792d966f-a5ab-43bb-9a33-706688e1550b', 0, NULL, NULL, NULL, '1', '2022-01-23 12:59:57', NULL, '2022-01-23 12:59:58', b'0'); +INSERT INTO `system_sms_log` VALUES (123, 4, 'DEBUG_DING_TALK', 9, 'bpm_task_assigned', 2, '您收到了一条新的待办任务:滔博-任务一,申请人:芋道源码,处理链接:http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=4f676a08-7c09-11ec-b8a1-acde48001122', '{\"startUserNickname\":\"芋道源码\",\"taskName\":\"任务一\",\"detailUrl\":\"http://dashboard.yudao.iocoder.cnbpm/process-instance/detail?id=4f676a08-7c09-11ec-b8a1-acde48001122\",\"processInstanceName\":\"滔博\"}', 'suibian', '15612345678', 1, 2, 10, '2022-01-23 12:59:58', 0, '成功', '0', NULL, NULL, '54cdaa92-8d2c-4c53-826f-70397eb29531', 0, NULL, NULL, NULL, '1', '2022-01-23 12:59:57', NULL, '2022-01-23 12:59:58', b'0'); +INSERT INTO `system_sms_log` VALUES (124, 1, 'YUN_PIAN', 8, 'user-sms-login', 1, '您的验证码是9999', '{\"code\":\"9999\"}', '4372216', '15601691399', NULL, 1, 20, '2022-01-29 11:50:27', 2001000100, 'IP 不允许发送短信', '-3', 'IP没有权限 => IP 101.82.59.182 未加入白名单,可在后台‘系统设置->IP白名单设置’里添加', NULL, NULL, 0, NULL, NULL, NULL, NULL, '2022-01-29 11:50:26', NULL, '2022-01-29 11:50:27', b'0'); +INSERT INTO `system_sms_log` VALUES (125, 1, 'YUN_PIAN', 8, 'user-sms-login', 1, '您的验证码是9999', '{\"code\":\"9999\"}', '4372216', '15601691399', NULL, 1, 20, '2022-01-29 13:58:07', 2001000100, 'IP 不允许发送短信', '-3', 'IP没有权限 => IP 101.82.80.210 未加入白名单,可在后台‘系统设置->IP白名单设置’里添加', NULL, NULL, 0, NULL, NULL, NULL, NULL, '2022-01-29 13:58:07', NULL, '2022-01-29 13:58:07', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_sms_template +-- Table structure for system_sms_template -- ---------------------------- -DROP TABLE IF EXISTS `sys_sms_template`; -CREATE TABLE `sys_sms_template` ( +DROP TABLE IF EXISTS `system_sms_template`; +CREATE TABLE `system_sms_template` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `type` tinyint NOT NULL COMMENT '短信签名', `status` tinyint NOT NULL COMMENT '开启状态', @@ -2547,26 +3091,26 @@ CREATE TABLE `sys_sms_template` ( ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='短信模板'; -- ---------------------------- --- Records of sys_sms_template +-- Records of system_sms_template -- ---------------------------- BEGIN; -INSERT INTO `sys_sms_template` VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '[\"operation\",\"code\"]', NULL, '4383920', 1, 'YUN_PIAN', '', '2021-03-31 10:49:38', '1', '2021-04-10 01:22:00', b'0'); -INSERT INTO `sys_sms_template` VALUES (3, 1, 0, 'test_02', '公告通知', '您的验证码{code},该验证码5分钟内有效,请勿泄漏于他人!', '[\"code\"]', NULL, 'SMS_207945135', 2, 'ALIYUN', '', '2021-03-31 11:56:30', '1', '2021-04-10 01:22:02', b'0'); -INSERT INTO `sys_sms_template` VALUES (4, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 07:47:12', b'1'); -INSERT INTO `sys_sms_template` VALUES (5, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 08:32:22', b'1'); -INSERT INTO `sys_sms_template` VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '[\"name\"]', 'f哈哈哈', '4383920', 1, 'YUN_PIAN', '1', '2021-04-10 01:07:21', '1', '2021-04-10 01:22:05', b'0'); -INSERT INTO `sys_sms_template` VALUES (7, 3, 0, 'test-04', '测试下', '老鸡{name},牛逼{code}', '[\"name\",\"code\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2021-04-13 00:29:53', '1', '2021-04-14 00:30:38', b'0'); -INSERT INTO `sys_sms_template` VALUES (8, 1, 0, 'user-sms-login', '前台用户短信登录', '您的验证码是{code}', '[\"code\"]', NULL, '4372216', 1, 'YUN_PIAN', '1', '2021-10-11 08:10:00', '1', '2021-10-11 08:10:00', b'0'); -INSERT INTO `sys_sms_template` VALUES (9, 2, 0, 'bpm_task_assigned', '【工作流】任务被分配', '您收到了一条新的待办任务:{processInstanceName}-{taskName},申请人:{startUserNickname},处理链接:{detailUrl}', '[\"processInstanceName\",\"taskName\",\"startUserNickname\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-21 22:31:19', '1', '2022-01-22 00:03:36', b'0'); -INSERT INTO `sys_sms_template` VALUES (10, 2, 0, 'bpm_process_instance_reject', '【工作流】流程被不通过', '您的流程被审批不通过:{processInstanceName},原因:{comment},查看链接:{detailUrl}', '[\"processInstanceName\",\"comment\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:03:31', '1', '2022-01-22 00:24:31', b'0'); -INSERT INTO `sys_sms_template` VALUES (11, 2, 0, 'bpm_process_instance_approve', '【工作流】流程被通过', '您的流程被审批通过:{processInstanceName},查看链接:{detailUrl}', '[\"processInstanceName\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:04:31', '1', '2022-01-22 00:24:23', b'0'); +INSERT INTO `system_sms_template` VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '[\"operation\",\"code\"]', NULL, '4383920', 1, 'YUN_PIAN', '', '2021-03-31 10:49:38', '1', '2021-04-10 01:22:00', b'0'); +INSERT INTO `system_sms_template` VALUES (3, 1, 0, 'test_02', '公告通知', '您的验证码{code},该验证码5分钟内有效,请勿泄漏于他人!', '[\"code\"]', NULL, 'SMS_207945135', 2, 'ALIYUN', '', '2021-03-31 11:56:30', '1', '2021-04-10 01:22:02', b'0'); +INSERT INTO `system_sms_template` VALUES (4, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 07:47:12', b'1'); +INSERT INTO `system_sms_template` VALUES (5, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 08:32:22', b'1'); +INSERT INTO `system_sms_template` VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '[\"name\"]', 'f哈哈哈', '4383920', 1, 'YUN_PIAN', '1', '2021-04-10 01:07:21', '1', '2021-04-10 01:22:05', b'0'); +INSERT INTO `system_sms_template` VALUES (7, 3, 0, 'test-04', '测试下', '老鸡{name},牛逼{code}', '[\"name\",\"code\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2021-04-13 00:29:53', '1', '2021-04-14 00:30:38', b'0'); +INSERT INTO `system_sms_template` VALUES (8, 1, 0, 'user-sms-login', '前台用户短信登录', '您的验证码是{code}', '[\"code\"]', NULL, '4372216', 1, 'YUN_PIAN', '1', '2021-10-11 08:10:00', '1', '2021-10-11 08:10:00', b'0'); +INSERT INTO `system_sms_template` VALUES (9, 2, 0, 'bpm_task_assigned', '【工作流】任务被分配', '您收到了一条新的待办任务:{processInstanceName}-{taskName},申请人:{startUserNickname},处理链接:{detailUrl}', '[\"processInstanceName\",\"taskName\",\"startUserNickname\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-21 22:31:19', '1', '2022-01-22 00:03:36', b'0'); +INSERT INTO `system_sms_template` VALUES (10, 2, 0, 'bpm_process_instance_reject', '【工作流】流程被不通过', '您的流程被审批不通过:{processInstanceName},原因:{comment},查看链接:{detailUrl}', '[\"processInstanceName\",\"comment\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:03:31', '1', '2022-01-22 00:24:31', b'0'); +INSERT INTO `system_sms_template` VALUES (11, 2, 0, 'bpm_process_instance_approve', '【工作流】流程被通过', '您的流程被审批通过:{processInstanceName},查看链接:{detailUrl}', '[\"processInstanceName\",\"detailUrl\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2022-01-22 00:04:31', '1', '2022-01-22 00:24:23', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_social_user +-- Table structure for system_social_user -- ---------------------------- -DROP TABLE IF EXISTS `sys_social_user`; -CREATE TABLE `sys_social_user` ( +DROP TABLE IF EXISTS `system_social_user`; +CREATE TABLE `system_social_user` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键(自增策略)', `user_id` bigint NOT NULL COMMENT '关联的用户编号', `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型', @@ -2587,62 +3131,62 @@ CREATE TABLE `sys_social_user` ( ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='社交用户'; -- ---------------------------- --- Records of sys_social_user +-- Records of system_social_user -- ---------------------------- BEGIN; -INSERT INTO `sys_social_user` VALUES (4, 1, 2, 20, 'IPRmJ0wvBptiPIlGEZiPewGwiEiE', NULL, 'IPRmJ0wvBptiPIlGEZiPewGwiEiE', '{\"accessToken\":null,\"expireIn\":0,\"refreshToken\":null,\"refreshTokenExpireIn\":0,\"uid\":null,\"openId\":\"0TvabQWZs9g6UedEWZKSegiEiE\",\"accessCode\":null,\"unionId\":\"IPRmJ0wvBptiPIlGEZiPewGwiEiE\",\"scope\":null,\"tokenType\":null,\"idToken\":null,\"macAlgorithm\":null,\"macKey\":null,\"code\":null,\"oauthToken\":null,\"oauthTokenSecret\":null,\"userId\":null,\"screenName\":null,\"oauthCallbackConfirmed\":null}', '王文斌(芋艿)(正在输出)', NULL, '{\"nick\":\"王文斌(芋艿)(正在输出)\",\"unionid\":\"IPRmJ0wvBptiPIlGEZiPewGwiEiE\",\"dingId\":\"$:LWCP_v1:$r28ct/waSBPp5Gk7a6kDXA==\",\"openid\":\"0TvabQWZs9g6UedEWZKSegiEiE\",\"main_org_auth_high_level\":false}', NULL, '2021-10-06 00:43:17', NULL, '2021-10-06 00:43:34', b'0'); -INSERT INTO `sys_social_user` VALUES (5, 245, 1, 33, 'osFZg6JVT_mbOOXfeCSxmRv-Cs_4', NULL, 'osFZg6JVT_mbOOXfeCSxmRv-Cs_4', '{\"accessToken\":null,\"expireIn\":0,\"refreshToken\":null,\"refreshTokenExpireIn\":0,\"uid\":null,\"openId\":\"osFZg6JVT_mbOOXfeCSxmRv-Cs_4\",\"accessCode\":null,\"unionId\":null,\"scope\":null,\"tokenType\":null,\"idToken\":null,\"macAlgorithm\":null,\"macKey\":null,\"code\":null,\"oauthToken\":null,\"oauthTokenSecret\":null,\"userId\":null,\"screenName\":null,\"oauthCallbackConfirmed\":null,\"miniSessionKey\":\"7BK7xtyJleOWEXTHhW6eDg==\"}', '', '', 'null', NULL, '2021-10-30 10:08:42', NULL, '2021-10-30 10:08:42', b'0'); +INSERT INTO `system_social_user` VALUES (4, 1, 2, 20, 'IPRmJ0wvBptiPIlGEZiPewGwiEiE', NULL, 'IPRmJ0wvBptiPIlGEZiPewGwiEiE', '{\"accessToken\":null,\"expireIn\":0,\"refreshToken\":null,\"refreshTokenExpireIn\":0,\"uid\":null,\"openId\":\"0TvabQWZs9g6UedEWZKSegiEiE\",\"accessCode\":null,\"unionId\":\"IPRmJ0wvBptiPIlGEZiPewGwiEiE\",\"scope\":null,\"tokenType\":null,\"idToken\":null,\"macAlgorithm\":null,\"macKey\":null,\"code\":null,\"oauthToken\":null,\"oauthTokenSecret\":null,\"userId\":null,\"screenName\":null,\"oauthCallbackConfirmed\":null}', '王文斌(芋艿)(正在输出)', NULL, '{\"nick\":\"王文斌(芋艿)(正在输出)\",\"unionid\":\"IPRmJ0wvBptiPIlGEZiPewGwiEiE\",\"dingId\":\"$:LWCP_v1:$r28ct/waSBPp5Gk7a6kDXA==\",\"openid\":\"0TvabQWZs9g6UedEWZKSegiEiE\",\"main_org_auth_high_level\":false}', NULL, '2021-10-06 00:43:17', NULL, '2022-02-01 15:00:30', b'1'); +INSERT INTO `system_social_user` VALUES (5, 245, 1, 33, 'osFZg6JVT_mbOOXfeCSxmRv-Cs_4', NULL, 'osFZg6JVT_mbOOXfeCSxmRv-Cs_4', '{\"accessToken\":null,\"expireIn\":0,\"refreshToken\":null,\"refreshTokenExpireIn\":0,\"uid\":null,\"openId\":\"osFZg6JVT_mbOOXfeCSxmRv-Cs_4\",\"accessCode\":null,\"unionId\":null,\"scope\":null,\"tokenType\":null,\"idToken\":null,\"macAlgorithm\":null,\"macKey\":null,\"code\":null,\"oauthToken\":null,\"oauthTokenSecret\":null,\"userId\":null,\"screenName\":null,\"oauthCallbackConfirmed\":null,\"miniSessionKey\":\"7BK7xtyJleOWEXTHhW6eDg==\"}', '', '', 'null', NULL, '2021-10-30 10:08:42', NULL, '2021-10-30 10:08:42', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_tenant +-- Table structure for system_tenant -- ---------------------------- -DROP TABLE IF EXISTS `sys_tenant`; -CREATE TABLE `sys_tenant` ( +DROP TABLE IF EXISTS `system_tenant`; +CREATE TABLE `system_tenant` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '租户编号', `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '租户名', `contact_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '联系人', `contact_mobile` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系手机', `status` tinyint NOT NULL DEFAULT '0' COMMENT '租户状态(0正常 1停用)', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租户表'; -- ---------------------------- --- Records of sys_tenant +-- Records of system_tenant -- ---------------------------- BEGIN; -INSERT INTO `sys_tenant` VALUES (1, '芋道源码', '芋艿', '17321315478', 0, 'admin', '2021-01-05 17:03:47', NULL, '2021-12-05 02:22:26', b'0'); -INSERT INTO `sys_tenant` VALUES (107, '测试租户', '秃头', '15601691300', 1, '1', '2021-12-14 20:49:44', '1', '2021-12-14 20:49:49', b'0'); -INSERT INTO `sys_tenant` VALUES (108, '测试', '测试', '15601691300', 1, '1', '2021-12-14 21:02:09', '1', '2021-12-14 21:02:09', b'0'); +INSERT INTO `system_tenant` VALUES (1, '芋道源码', '芋艿', '17321315478', 0, 'admin', '2021-01-05 17:03:47', NULL, '2021-12-05 02:22:26', b'0'); +INSERT INTO `system_tenant` VALUES (107, '测试租户', '秃头', '15601691300', 1, '1', '2021-12-14 20:49:44', '1', '2021-12-14 20:49:49', b'0'); +INSERT INTO `system_tenant` VALUES (108, '测试', '测试', '15601691300', 1, '1', '2021-12-14 21:02:09', '1', '2021-12-14 21:02:09', b'0'); COMMIT; -- ---------------------------- --- Table structure for sys_user +-- Table structure for system_user -- ---------------------------- -DROP TABLE IF EXISTS `sys_user`; -CREATE TABLE `sys_user` ( +DROP TABLE IF EXISTS `system_user`; +CREATE TABLE `system_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', - `username` varchar(30) NOT NULL COMMENT '用户账号', - `password` varchar(100) NOT NULL DEFAULT '' COMMENT '密码', - `nickname` varchar(30) NOT NULL COMMENT '用户昵称', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `username` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户账号', + `password` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码', + `nickname` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户昵称', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', `dept_id` bigint DEFAULT NULL COMMENT '部门ID', - `post_ids` varchar(255) DEFAULT NULL COMMENT '岗位编号数组', - `email` varchar(50) DEFAULT '' COMMENT '用户邮箱', - `mobile` varchar(11) DEFAULT '' COMMENT '手机号码', + `post_ids` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '岗位编号数组', + `email` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '用户邮箱', + `mobile` varchar(11) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '手机号码', `sex` tinyint DEFAULT '0' COMMENT '用户性别', - `avatar` varchar(100) DEFAULT '' COMMENT '头像地址', + `avatar` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '头像地址', `status` tinyint NOT NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)', - `login_ip` varchar(50) DEFAULT '' COMMENT '最后登录IP', + `login_ip` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '最后登录IP', `login_date` datetime DEFAULT NULL COMMENT '最后登录时间', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', @@ -2650,29 +3194,29 @@ CREATE TABLE `sys_user` ( ) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表'; -- ---------------------------- --- Records of sys_user +-- Records of system_user -- ---------------------------- BEGIN; -INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', 0, '127.0.0.1', '2022-01-22 23:30:35', 'admin', '2021-01-05 17:03:47', NULL, '2022-01-22 23:30:35', b'0', 1); -INSERT INTO `sys_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '测试员', 103, '[2]', 'ry@qq.com', '15666666666', 1, '', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-12-13 01:26:34', b'1', 1); -INSERT INTO `sys_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '104', '2021-12-16 09:26:10', b'0', 1); -INSERT INTO `sys_user` VALUES (103, 'yuanma', '$2a$10$wWoPT7sqriM2O1YXRL.je.GiL538OR6ZTN8aQZr9JAGdnpCH2tpYe', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-01-18 00:33:40', '', '2021-01-13 23:50:35', NULL, '2022-01-18 00:33:40', b'0', 1); -INSERT INTO `sys_user` VALUES (104, 'test', '$2a$10$CkyM2xvzUhSWsh.JqGcSju.KjlPsaX1A76wO8O/mYtkpQvcp2jWTW', '测试号', NULL, 107, '[]', '', '15601691200', 1, '', 0, '127.0.0.1', '2021-12-16 09:27:08', '', '2021-01-21 02:13:53', NULL, '2021-12-16 09:27:08', b'0', 1); -INSERT INTO `sys_user` VALUES (105, 'hradmin', '$2a$10$JEhJOL25X1eMnFfR3PILo.MoAljf29YukpL2w6H9GvVGjmqOCuh.O', 'hr-mgr', 'hr 管理员', 109, '[3]', '', '18818260000', 1, '', 0, '127.0.0.1', '2021-10-30 21:19:36', '1', '2021-09-25 16:50:41', '1', '2021-12-16 09:26:41', b'0', 1); -INSERT INTO `sys_user` VALUES (106, 'zhijiantianya', '$2a$10$Y0hSfV2udA8quqMeWukhTuHEoKpQ5tDhclG8WUWSOH7o/MGw185Ti', '芋道源码', '', NULL, NULL, '', '', 3, 'https://portrait.gitee.com/uploads/avatars/user/0/176_zhijiantianya_1578913741.png', 0, '', NULL, NULL, '2021-09-28 09:40:59', NULL, '2021-12-15 14:44:47', b'1', 1); +INSERT INTO `system_user` VALUES (1, 'admin', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/api/infra/file/get/7e7ed694-2242-46cf-9ac9-0709debcc22f', 0, '127.0.0.1', '2022-02-02 00:27:55', 'admin', '2021-01-05 17:03:47', NULL, '2022-02-02 00:27:55', b'0', 1); +INSERT INTO `system_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '测试员', 103, '[2]', 'ry@qq.com', '15666666666', 1, '', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-12-13 01:26:34', b'1', 1); +INSERT INTO `system_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '104', '2021-12-16 09:26:10', b'0', 1); +INSERT INTO `system_user` VALUES (103, 'yuanma', '$2a$10$wWoPT7sqriM2O1YXRL.je.GiL538OR6ZTN8aQZr9JAGdnpCH2tpYe', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-01-18 00:33:40', '', '2021-01-13 23:50:35', NULL, '2022-01-18 00:33:40', b'0', 1); +INSERT INTO `system_user` VALUES (104, 'test', '$2a$10$CkyM2xvzUhSWsh.JqGcSju.KjlPsaX1A76wO8O/mYtkpQvcp2jWTW', '测试号', NULL, 107, '[]', '', '15601691200', 1, '', 0, '127.0.0.1', '2021-12-16 09:27:08', '', '2021-01-21 02:13:53', NULL, '2021-12-16 09:27:08', b'0', 1); +INSERT INTO `system_user` VALUES (105, 'hradmin', '$2a$10$JEhJOL25X1eMnFfR3PILo.MoAljf29YukpL2w6H9GvVGjmqOCuh.O', 'hr-mgr', 'hr 管理员', 109, '[3]', '', '18818260000', 1, '', 0, '127.0.0.1', '2021-10-30 21:19:36', '1', '2021-09-25 16:50:41', '1', '2021-12-16 09:26:41', b'0', 1); +INSERT INTO `system_user` VALUES (106, 'zhijiantianya', '$2a$10$Y0hSfV2udA8quqMeWukhTuHEoKpQ5tDhclG8WUWSOH7o/MGw185Ti', '芋道源码', '', NULL, NULL, '', '', 3, 'https://portrait.gitee.com/uploads/avatars/user/0/176_zhijiantianya_1578913741.png', 0, '', NULL, NULL, '2021-09-28 09:40:59', NULL, '2021-12-15 14:44:47', b'1', 1); COMMIT; -- ---------------------------- --- Table structure for sys_user_role +-- Table structure for system_user_role -- ---------------------------- -DROP TABLE IF EXISTS `sys_user_role`; -CREATE TABLE `sys_user_role` ( +DROP TABLE IF EXISTS `system_user_role`; +CREATE TABLE `system_user_role` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增编号', `user_id` bigint NOT NULL COMMENT '用户ID', `role_id` bigint NOT NULL COMMENT '角色ID', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', @@ -2680,26 +3224,26 @@ CREATE TABLE `sys_user_role` ( ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户和角色关联表'; -- ---------------------------- --- Records of sys_user_role +-- Records of system_user_role -- ---------------------------- BEGIN; -INSERT INTO `sys_user_role` VALUES (1, 1, 1, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (2, 2, 2, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (3, 100, 1, '', NULL, '', NULL, b'1', 0); -INSERT INTO `sys_user_role` VALUES (4, 100, 101, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (7, 104, 101, '', NULL, '', NULL, b'0', 0); -INSERT INTO `sys_user_role` VALUES (8, 106, 1, NULL, '2021-09-28 09:40:59', NULL, '2021-09-28 09:40:59', b'1', 0); -INSERT INTO `sys_user_role` VALUES (9, 105, 1, '1', '2021-10-30 13:40:48', '1', '2021-10-30 13:40:48', b'0', 0); -INSERT INTO `sys_user_role` VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', b'0', 0); +INSERT INTO `system_user_role` VALUES (1, 1, 1, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (2, 2, 2, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (3, 100, 1, '', NULL, '', NULL, b'1', 0); +INSERT INTO `system_user_role` VALUES (4, 100, 101, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (7, 104, 101, '', NULL, '', NULL, b'0', 0); +INSERT INTO `system_user_role` VALUES (8, 106, 1, NULL, '2021-09-28 09:40:59', NULL, '2021-09-28 09:40:59', b'1', 0); +INSERT INTO `system_user_role` VALUES (9, 105, 1, '1', '2021-10-30 13:40:48', '1', '2021-10-30 13:40:48', b'0', 0); +INSERT INTO `system_user_role` VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', b'0', 0); COMMIT; -- ---------------------------- --- Table structure for sys_user_session +-- Table structure for system_user_session -- ---------------------------- -DROP TABLE IF EXISTS `sys_user_session`; -CREATE TABLE `sys_user_session` ( +DROP TABLE IF EXISTS `system_user_session`; +CREATE TABLE `system_user_session` ( `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '会话编号', `user_id` bigint NOT NULL COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT '0' COMMENT '用户类型', @@ -2717,158 +3261,191 @@ CREATE TABLE `sys_user_session` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在线 Session'; -- ---------------------------- --- Records of sys_user_session +-- Records of system_user_session -- ---------------------------- BEGIN; -INSERT INTO `sys_user_session` VALUES ('0180929bb4b244b891253885e86ad9d1', 1, 2, '2021-12-16 09:37:48', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:07:48', NULL, '2021-12-16 09:07:48', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('01b7469337864db7a9b65747f38fa928', 1, 2, '2021-12-31 14:29:42', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 13:49:05', NULL, '2021-12-31 13:59:42', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('01f68d27b18b414ebfa7f417ffbbe185', 103, 2, '2022-01-15 21:53:10', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:23:10', NULL, '2022-01-15 13:31:15', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('04abd513bbee4a51973780f93cca16c2', 1, 2, '2022-01-03 05:59:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 05:29:14', NULL, '2022-01-03 05:29:14', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('04b9f6b2480c48deb3ea9d67c3db8cfe', 1, 2, '2022-01-16 02:47:08', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 01:37:56', NULL, '2022-01-16 02:17:08', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0558f1e97ff044609ccb7c6e7ead6a6b', 1, 2, '2022-01-19 14:07:46', 'admin', '127.0.0.1', '', NULL, '2022-01-19 12:38:45', NULL, '2022-01-19 13:37:46', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('07b0c58cd92449319522a998cf883a37', 1, 2, '2022-01-08 11:07:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 10:37:28', NULL, '2022-01-08 10:37:28', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0806e3aa2c0b446eb9b3496d9b63e51f', 103, 2, '2022-01-13 21:51:47', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 21:21:47', NULL, '2022-01-13 21:21:47', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('09c26e452a6c44129a2d495478b40d27', 1, 2, '2022-01-02 13:25:15', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 12:06:51', NULL, '2022-01-02 12:55:15', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0b03400e80544594b7e766d48b9d8aed', 1, 2, '2022-01-17 02:44:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 02:14:00', NULL, '2022-01-17 02:14:00', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0b8545465544481da4d162a3a74a552e', 1, 2, '2021-12-15 23:48:37', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:44:07', NULL, '2021-12-15 23:18:37', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0bf9cd592168451aad7b546ff085df58', 1, 2, '2022-01-03 00:00:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 23:30:30', NULL, '2022-01-02 15:39:40', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('0c5e3db754714de38ed163c3ef53fb19', 1, 2, '2022-01-17 01:20:21', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 21:33:06', NULL, '2022-01-17 00:50:21', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('0c8f02172a894f11a3d054a5811e1c5b', 1, 2, '2022-01-03 09:25:54', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 08:32:07', NULL, '2022-01-03 01:17:42', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('0fef9f0bc17047008bef199f1682dce0', 1, 2, '2022-01-21 23:22:20', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 22:29:19', NULL, '2022-01-21 22:52:20', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1645cee3484248929f406fccf8772e67', 1, 2, '2022-01-18 08:43:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 08:01:22', NULL, '2022-01-18 08:13:25', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('166cea69fca846c985c62dd365994561', 1, 2, '2022-01-03 11:36:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 09:17:50', NULL, '2022-01-03 11:06:12', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1893bfb924174e3c82f02f18be0606fd', 1, 2, '2022-01-04 00:05:19', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 23:35:19', NULL, '2022-01-03 23:35:19', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1995595036aa4652bb887c43cfd35ba8', 1, 2, '2022-01-01 00:18:24', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 22:57:57', NULL, '2021-12-31 23:48:24', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('19fdd80f6ba3491b8a5cd934694a2ddc', 103, 2, '2022-01-11 22:40:28', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 22:10:28', NULL, '2022-01-11 22:10:28', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1b6154299e1a470ebf80d2eaef72b0e2', 1, 2, '2022-01-02 11:59:52', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 09:30:29', NULL, '2022-01-02 11:29:52', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1b7c79d9d8b04b4fb826564fce41f77c', 1, 2, '2022-01-03 22:42:07', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 22:12:07', NULL, '2022-01-03 22:12:07', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1b848d99cde6448097dcedc83fda4c0a', 1, 2, '2021-12-31 10:45:09', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 08:35:36', NULL, '2021-12-31 10:15:09', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1bc6ad0827fe48099bcbdb9a206818ac', 104, 2, '2021-12-15 23:48:59', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 23:18:59', NULL, '2021-12-15 23:18:59', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('1bfa6a2ed10741fbb03996a48656f0d2', 1, 2, '2022-01-14 10:48:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 10:18:14', NULL, '2022-01-14 10:18:14', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('2150cb32189f4ccdba60a7209dac1e0d', 1, 2, '2022-01-15 22:49:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:19:10', NULL, '2022-01-15 14:20:19', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('234b1084a5574ffc920669d4d230a18b', 1, 2, '2022-01-19 00:08:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 23:38:56', NULL, '2022-01-18 23:38:56', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('251bab4618b644faa2c54083ac8b1902', 1, 2, '2022-01-08 01:34:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 00:37:26', NULL, '2022-01-07 17:10:10', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('27052d883f1047e68b0841429d234b6b', 1, 2, '2022-01-08 10:25:42', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 09:55:42', NULL, '2022-01-08 09:55:42', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('27d8ed14a6394e1f8be6fad865d8355a', 1, 2, '2022-01-11 12:58:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 12:28:28', NULL, '2022-01-11 12:28:28', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('28d90f7da308407296fface4ca68d732', 1, 2, '2022-01-01 21:54:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 21:01:18', NULL, '2022-01-01 21:24:30', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('291f36ffc1da483981845efd20e8eae4', 1, 2, '2022-01-08 00:23:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-07 23:42:43', NULL, '2022-01-07 23:53:49', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('2b49a2e3f5494cebb4a3f19080853355', 103, 2, '2022-01-17 01:26:54', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 00:56:54', NULL, '2022-01-17 00:56:54', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('2d920ad234a442cd98f5f517d50d6b60', 1, 2, '2022-01-02 16:47:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 14:34:30', NULL, '2022-01-02 16:17:41', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('2ec1ca2d0053415599fa18e6bddf710e', 104, 2, '2021-12-16 10:08:04', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:27:08', NULL, '2021-12-16 09:38:04', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('303e29836f3540c79188c835466318b2', 1, 2, '2022-01-19 10:40:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-19 08:35:23', NULL, '2022-01-19 10:10:31', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('32a043324c7541d191cdf6a8b667ad6c', 103, 2, '2022-01-15 22:44:58', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:56', NULL, '2022-01-15 14:19:00', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('32c405074a3b462681bca9afd26fdfe9', 103, 2, '2022-01-13 13:43:30', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 13:03:29', NULL, '2022-01-13 13:13:30', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('345ad9af8d0c46c8ad285b57cabfd060', 1, 2, '2021-12-25 19:57:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 19:15:06', NULL, '2021-12-25 19:27:51', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('355c57509a5643519107ec132bd85ba6', 103, 2, '2022-01-14 00:49:12', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 23:12:26', NULL, '2022-01-14 00:19:12', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('367c9c23eb4e4539be4ecc737af8fbf6', 103, 2, '2022-01-14 20:39:07', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 18:39:31', NULL, '2022-01-14 20:09:07', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('374d99e8a41b464c98f73ddbc5aa4d29', 1, 2, '2022-01-03 04:04:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 23:39:46', NULL, '2022-01-03 03:34:14', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('39647615e860424ebcc9b3f598f135be', 103, 2, '2022-01-18 01:03:40', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:40', NULL, '2022-01-17 16:33:44', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('3cc54b8687504a388b5b8c7457d16382', 1, 2, '2022-01-10 21:01:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-10 20:18:15', NULL, '2022-01-10 20:31:18', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('3d9a4ffee19c47dfbc3c807adccf4c23', 1, 2, '2022-01-20 01:43:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 00:32:48', NULL, '2022-01-20 01:13:32', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('3ec1ce407e8a4accab0b51e756ab74be', 1, 2, '2022-01-20 14:01:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 12:46:56', NULL, '2022-01-20 13:31:25', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('42c1711b9b6448c18b0cd621b20bd9e2', 1, 2, '2022-01-16 00:23:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:53:32', NULL, '2022-01-15 23:53:32', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('439e30be513e42c094a0a0296b761cc5', 1, 2, '2022-01-13 01:24:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 00:33:14', NULL, '2022-01-13 00:54:38', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('47949a90a88d4c49823d70995d980ee9', 1, 2, '2021-12-16 10:04:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:20:41', NULL, '2021-12-16 09:34:30', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('488438fbac1e490aba5fadbc5aef18c8', 1, 2, '2022-01-09 00:45:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 23:07:53', NULL, '2022-01-09 00:15:11', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('495da339c78846609991d9bc66e17dcf', 1, 2, '2021-12-31 22:54:24', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 21:47:55', NULL, '2021-12-31 22:24:24', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('4e00d142b22e4826938de31c221b6b32', 104, 2, '2021-12-16 09:54:24', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:24:24', NULL, '2021-12-16 01:27:04', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('4f18d2a257bb45148f64b5dd8a895fad', 1, 2, '2022-01-08 23:37:52', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 23:07:52', NULL, '2022-01-08 23:07:52', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('51b1fc7d18264e7e97b1992b4994551a', 1, 2, '2022-01-22 20:11:04', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 18:37:19', NULL, '2022-01-22 19:41:04', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('55d703899dc74e6881e2a52d11e155dc', 1, 2, '2022-01-16 19:10:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 17:38:41', NULL, '2022-01-16 18:40:11', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('569063f65eb24fcc92df57779ea671d5', 1, 2, '2022-01-14 23:10:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 22:23:55', NULL, '2022-01-14 22:40:22', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('5921e2838860430b80d02c2dc5bc9b14', 1, 2, '2022-01-01 18:38:17', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 17:19:06', NULL, '2022-01-01 18:08:17', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('5c8b305b180648c4919384c2204262f1', 1, 2, '2022-01-18 00:20:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:50:50', NULL, '2022-01-17 15:50:58', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('5cb75ff3873b4ee99c54ca8126b6a239', 103, 2, '2022-01-18 00:21:08', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:51:08', NULL, '2022-01-17 23:51:08', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('5d65f92a84b5497787686e513289372f', 1, 2, '2022-01-16 00:16:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:46:18', NULL, '2022-01-15 15:47:33', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('5e8984281b354935b422c95a06ac9ff8', 1, 2, '2022-01-20 14:21:17', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 13:31:17', NULL, '2022-01-20 13:51:17', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('604d98299b7243ddafa3ee0350f6edce', 1, 2, '2022-01-22 01:00:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 00:00:28', NULL, '2022-01-22 00:30:30', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('63d50b8b7e4448f98bd4ab2c084ac18f', 103, 2, '2022-01-17 13:18:45', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:48:45', NULL, '2022-01-17 12:48:45', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('63ea8e8249cb4089b4b0d10256f39ba4', 1, 2, '2022-01-11 13:52:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:22:44', NULL, '2022-01-11 05:23:14', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('64f51e60527349d6b4a0a74f3d8eca97', 104, 2, '2021-12-16 07:37:54', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:07:54', NULL, '2021-12-16 07:07:54', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('6b7d55bad59e401cb1f8d6c418bf552e', 103, 2, '2022-01-14 10:43:59', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 09:49:52', NULL, '2022-01-14 10:13:59', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('6d554dd8e0724ff9907bc1186119280c', 1, 2, '2022-01-23 01:22:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 23:30:35', NULL, '2022-01-23 00:52:38', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('6f0e4f523b13484c94d0dfe49d505d41', 103, 2, '2022-01-13 10:46:00', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 09:51:45', NULL, '2022-01-13 10:16:00', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('725e3f1407844ffebbaf02ba0673e0a4', 103, 2, '2022-01-16 12:23:58', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 11:53:58', NULL, '2022-01-16 11:53:58', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('729362aa59ed43cf9606a163883f2f2a', 103, 2, '2022-01-15 22:27:50', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:32:02', NULL, '2022-01-15 13:58:33', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('79924bcc8d594452a8ee8406d312b2c2', 1, 2, '2022-01-01 23:37:34', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 22:02:06', NULL, '2022-01-01 23:07:34', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('7aa8d8f930f34aba857c14db311a9a02', 1, 2, '2022-01-11 10:44:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 09:58:54', NULL, '2022-01-11 10:14:50', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('7b60ae1b30734903a34b9c7f8723d5e2', 103, 2, '2022-01-14 01:33:42', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 00:51:03', NULL, '2022-01-14 01:03:42', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('7bc4dca653954475b05cf233c08f783e', 103, 2, '2022-01-15 13:23:54', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 11:56:10', NULL, '2022-01-15 12:53:54', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('7d55dfdc996d4d24a0c4c6aad6065ca4', 103, 2, '2022-01-12 01:00:08', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 23:33:26', NULL, '2022-01-12 00:30:08', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('83c9839e34454f0eba630f29002d0ee3', 1, 2, '2022-01-09 23:00:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 20:59:49', NULL, '2022-01-09 22:30:41', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('845e9e7778a64200a87993db0fe6872d', 1, 2, '2022-01-21 00:12:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 23:42:44', NULL, '2022-01-20 23:42:44', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('84cc13aee41d473c987c1c0381cc05b1', 1, 2, '2022-01-09 02:01:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 01:03:29', NULL, '2022-01-09 01:31:10', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('882e89a623154797ac2a213c78da1f69', 1, 2, '2022-01-18 00:13:23', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:33:03', NULL, '2022-01-17 23:43:23', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('89bd23481c9a4b598ebea524679441b3', 103, 2, '2022-01-15 00:57:03', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 23:51:41', NULL, '2022-01-15 00:27:03', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('89cc980ca0d941109b3933c82d01d9c3', 103, 2, '2022-01-15 22:30:17', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:17', NULL, '2022-01-15 14:00:35', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('8c49cc6f52154dca9da6a2632985aa35', 1, 2, '2022-01-08 09:05:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 07:10:02', NULL, '2022-01-08 08:35:55', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('8e9599699f5141d2b041b855c7b34181', 1, 2, '2022-01-16 13:45:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 13:15:56', NULL, '2022-01-16 13:15:56', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9122b55409a94388a7b277ad808a127c', 1, 2, '2022-01-01 17:18:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 16:20:04', NULL, '2022-01-01 16:48:53', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('91b94971b7f044c8b68420e6ef7377af', 1, 2, '2022-01-02 17:32:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 17:02:50', NULL, '2022-01-02 17:02:50', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('93ada27b50d24c1a9b476c7fd4fef2ce', 1, 2, '2022-01-11 13:49:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:09:10', NULL, '2022-01-11 05:22:27', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('93caa65dbd9d480299850552067a031a', 1, 2, '2022-01-15 22:01:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:31:33', NULL, '2022-01-15 13:31:53', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('945e4bb19f4d4c28ba7135218ee3abe3', 1, 2, '2021-12-16 08:28:54', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:42:25', NULL, '2021-12-16 07:58:54', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9526809b303f489b8aab0c05e6b483dd', 1, 2, '2022-01-01 00:51:19', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 00:21:19', NULL, '2022-01-01 00:21:19', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9655c170353849dfadfdc810c6c5ca61', 1, 2, '2022-01-03 12:50:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 11:56:55', NULL, '2022-01-03 12:20:55', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9a84339c3c594140b0c3a9bfe95f7919', 1, 2, '2022-01-18 01:03:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:28', NULL, '2022-01-18 00:33:28', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9ee1349d7d3043759cb742a0fa5a3163', 1, 2, '2021-12-25 19:08:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 18:38:33', NULL, '2021-12-25 18:38:33', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('9f3266f59b8746c3bfe143361d86f6e8', 1, 2, '2022-01-08 22:31:37', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 22:01:37', NULL, '2022-01-08 22:01:37', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a09624232ed94b44a846023790e6282f', 1, 2, '2022-01-09 13:45:26', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 12:59:15', NULL, '2022-01-09 13:15:26', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a155e6dfe4b74fbaa69fcca239facc40', 1, 2, '2021-12-16 07:37:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:07:39', NULL, '2021-12-16 07:07:39', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a17d02a7c4264f7489728f510e40e823', 1, 2, '2022-01-17 13:18:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:48:31', NULL, '2022-01-17 04:48:37', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('a30e807e5db640feb92bb1eeb4ae89d0', 1, 2, '2022-01-16 12:23:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 11:53:10', NULL, '2022-01-16 11:53:10', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a4688af426e342a69c814d07bb8f7d3b', 1, 2, '2022-01-08 17:21:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 16:25:34', NULL, '2022-01-08 16:51:11', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a49e304816e0477998592c76caa9546d', 1, 2, '2022-01-16 01:20:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 00:30:18', NULL, '2022-01-16 00:50:18', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a55b31ff9e6a41fcb931d2244b4240a8', 1, 2, '2021-12-30 22:32:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-30 20:04:02', NULL, '2021-12-30 22:02:56', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a88e404ba71e41b0a16c75a8ce44bb9d', 1, 2, '2022-01-09 11:57:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 11:27:51', NULL, '2022-01-09 11:27:51', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('a9b27f95517d4ef9ae15c68bd4365d1b', 103, 2, '2022-01-11 20:37:20', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 19:35:41', NULL, '2022-01-11 20:07:20', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ab449ce8f2ea456591d23515c188c242', 1, 2, '2021-12-25 17:55:45', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 16:42:42', NULL, '2021-12-25 17:25:45', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ac730d1c96be41e5821a6de24b23bf7b', 103, 2, '2022-01-11 20:05:41', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 19:35:41', NULL, '2022-01-11 19:35:41', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ac88c6d1cb184979a015e9a8b50e21f0', 1, 2, '2022-01-03 04:59:36', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 03:39:08', NULL, '2022-01-03 04:29:36', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ae2a8c4a7df64271b0e7a2b702c378f8', 1, 2, '2022-01-18 02:18:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:58:20', NULL, '2022-01-18 01:48:53', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('b12325b8930245c09b75aa100dc1124d', 1, 2, '2022-01-01 09:12:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 08:09:05', NULL, '2022-01-01 08:42:53', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('b523e3add6e74587b247b467de677325', 1, 2, '2022-01-18 01:15:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:47', NULL, '2022-01-18 00:45:31', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('b6a02289210b4861b71a363b11b6b919', 1, 2, '2022-01-09 11:23:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 10:39:49', NULL, '2022-01-09 10:53:22', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('b883ba1582f54826b42fa073276c85cb', 1, 2, '2022-01-08 01:40:34', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 01:10:34', NULL, '2022-01-08 01:10:34', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ba1658c24b78442fb39062e31d902a5f', 1, 2, '2022-01-10 20:12:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-10 19:21:24', NULL, '2022-01-10 19:42:44', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('bb14f39f65ca41cc8ef915ad7f0c25d6', 1, 2, '2022-01-09 09:40:48', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 08:48:56', NULL, '2022-01-09 09:10:48', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('bd2b51a53b8d4046b024f43406985caf', 103, 2, '2022-01-15 23:31:38', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:20:30', NULL, '2022-01-15 23:01:38', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('bd52c43710274cd8bd888b1737cd939d', 1, 2, '2022-01-22 23:09:46', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 20:45:15', NULL, '2022-01-22 22:39:46', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('bd655254904748f79c0ad47dfb49d457', 1, 2, '2022-01-01 08:05:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 07:35:32', NULL, '2022-01-01 07:35:32', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('be98e2f02a444a4092d1cea3dc6e3073', 1, 2, '2022-01-17 13:34:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:26:04', NULL, '2022-01-17 13:04:51', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('c09baa895d79468db63417f60c65573c', 1, 2, '2022-01-01 11:33:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 10:13:48', NULL, '2022-01-01 11:03:44', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('c1797274297f4cd7b859c6c482d06005', 1, 2, '2022-01-09 10:26:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 09:44:24', NULL, '2022-01-09 09:56:00', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('c7c4d30623c84d3e88aab2f0b742e7c3', 1, 2, '2022-01-21 01:14:47', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 00:24:00', NULL, '2022-01-20 16:54:39', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('c7fc3e37d927405ebbe66df3dd5fd77e', 103, 2, '2022-01-13 01:01:29', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 22:57:04', NULL, '2022-01-13 00:31:29', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('cbd09ba52ccc47b2a639a6e28e92894f', 103, 2, '2022-01-12 01:34:01', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 01:04:01', NULL, '2022-01-12 01:04:01', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ccc85a8ee5a7407c97012b755cde979e', 1, 2, '2022-01-16 18:08:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 17:38:41', NULL, '2022-01-16 17:38:41', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('d229b8f8ef4d4df4afd05209acc87446', 1, 2, '2022-01-08 11:02:36', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 10:32:36', NULL, '2022-01-08 02:37:12', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('d46d26f08f624eb28eb665b6515587bd', 1, 2, '2022-01-16 00:19:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:49:32', NULL, '2022-01-15 23:49:32', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('d4aeab42d1934197865ce72ffe244009', 1, 2, '2022-01-16 03:11:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 02:41:56', NULL, '2022-01-16 02:41:56', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('d8550bde3c8b43a194e592b49c856c71', 1, 2, '2022-01-09 21:26:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 19:38:12', NULL, '2022-01-09 20:56:38', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('d8ebbe89793f4a829a108c4f1badbb11', 103, 2, '2022-01-13 21:18:56', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 20:38:43', NULL, '2022-01-13 20:48:56', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('da04f99dc14a4f28a8a77178861cb3ed', 104, 2, '2021-12-15 23:37:58', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:47:31', NULL, '2021-12-15 15:11:55', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('daec82cc885849a7bbab76eb9f0a4b32', 1, 2, '2022-01-15 23:31:35', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:43', NULL, '2022-01-15 23:01:35', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('dbaaa89e1659488c9693317454fe6ae2', 1, 2, '2022-01-14 22:53:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 22:23:55', NULL, '2022-01-14 22:23:55', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('dbe0f27930244ae38e0322226d6ecdbb', 1, 2, '2022-01-21 01:46:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 00:54:45', NULL, '2022-01-21 01:16:31', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('dd2e53ccf8c44b3e8556571687d4825d', 103, 2, '2022-01-12 01:34:01', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 01:04:01', NULL, '2022-01-12 01:04:01', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ddb9d3c65ee14c4a8ff1a3cf0e10e69a', 1, 2, '2022-01-19 00:52:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-19 00:22:57', NULL, '2022-01-19 00:22:57', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('ddd32e0a43d644ca95ba10e4e5b19416', 1, 2, '2022-01-03 19:28:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 17:22:27', NULL, '2022-01-03 18:58:22', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('df12a50eb8814317bb8e1003e098cbe7', 1, 2, '2022-01-09 19:04:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 16:26:16', NULL, '2022-01-09 18:34:00', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('e198f4f04da243d5b80caa0c8336d6a0', 103, 2, '2022-01-14 19:09:16', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 18:39:16', NULL, '2022-01-14 10:39:24', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('e290aebda5f34c379d0cf3e013cbcc8b', 1, 2, '2022-01-02 09:27:23', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 08:32:23', NULL, '2022-01-02 08:57:23', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('e2efa96cacbb47b580096193244a3739', 1, 2, '2022-01-14 14:24:13', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 13:44:04', NULL, '2022-01-14 13:54:13', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('e3c0319f639a481999bac6fa250af552', 1, 2, '2022-01-03 16:56:06', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 16:14:34', NULL, '2022-01-03 16:26:06', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('e42efabb61af4f5eaeea3b84693871da', 1, 2, '2022-01-15 22:28:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:58:55', NULL, '2022-01-15 14:00:08', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('e75c264df71342a59a85a6512a5a1fb7', 1, 2, '2022-01-22 19:18:46', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 18:30:58', NULL, '2022-01-22 18:48:46', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f10cabf849b245ebbaa5284b540c0bb2', 103, 2, '2022-01-11 21:51:14', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 20:54:19', NULL, '2022-01-11 21:21:14', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f49ade9038d24a73832e64efcc30b205', 103, 2, '2022-01-11 13:53:26', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:23:26', NULL, '2022-01-11 13:23:26', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f562fd12a7bb41f19ca1bf4aa5e3c9d1', 1, 2, '2022-01-22 02:42:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 01:20:59', NULL, '2022-01-22 02:12:51', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f76c8610a7e5461aac8972e21f14e734', 1, 2, '2022-01-22 21:52:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 20:29:53', NULL, '2022-01-22 21:22:44', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f974a40ea70941cdb9e04cb63bf5e557', 1, 2, '2022-01-16 02:00:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 01:30:25', NULL, '2022-01-16 01:30:25', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('f9f257cf09e640f2904696f2de35d3f6', 1, 2, '2022-01-03 21:42:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 20:59:23', NULL, '2022-01-03 21:12:44', b'0', 1); -INSERT INTO `sys_user_session` VALUES ('fe82f6ecb17449b595c7d6bd4bc1d371', 1, 2, '2021-12-15 23:16:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:46:49', NULL, '2021-12-15 14:46:53', b'1', 1); -INSERT INTO `sys_user_session` VALUES ('ffeae9ee4b8649b6b9ececaa502a934d', 1, 2, '2022-01-01 19:56:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 18:47:31', NULL, '2022-01-01 19:26:49', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0180929bb4b244b891253885e86ad9d1', 1, 2, '2021-12-16 09:37:48', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:07:48', NULL, '2021-12-16 09:07:48', b'0', 1); +INSERT INTO `system_user_session` VALUES ('01b7469337864db7a9b65747f38fa928', 1, 2, '2021-12-31 14:29:42', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 13:49:05', NULL, '2021-12-31 13:59:42', b'0', 1); +INSERT INTO `system_user_session` VALUES ('01f68d27b18b414ebfa7f417ffbbe185', 103, 2, '2022-01-15 21:53:10', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:23:10', NULL, '2022-01-15 13:31:15', b'1', 1); +INSERT INTO `system_user_session` VALUES ('04abd513bbee4a51973780f93cca16c2', 1, 2, '2022-01-03 05:59:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 05:29:14', NULL, '2022-01-03 05:29:14', b'0', 1); +INSERT INTO `system_user_session` VALUES ('04b9f6b2480c48deb3ea9d67c3db8cfe', 1, 2, '2022-01-16 02:47:08', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 01:37:56', NULL, '2022-01-16 02:17:08', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0558f1e97ff044609ccb7c6e7ead6a6b', 1, 2, '2022-01-19 14:07:46', 'admin', '127.0.0.1', '', NULL, '2022-01-19 12:38:45', NULL, '2022-01-19 13:37:46', b'0', 1); +INSERT INTO `system_user_session` VALUES ('07b0c58cd92449319522a998cf883a37', 1, 2, '2022-01-08 11:07:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 10:37:28', NULL, '2022-01-08 10:37:28', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0806e3aa2c0b446eb9b3496d9b63e51f', 103, 2, '2022-01-13 21:51:47', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 21:21:47', NULL, '2022-01-13 21:21:47', b'0', 1); +INSERT INTO `system_user_session` VALUES ('09c26e452a6c44129a2d495478b40d27', 1, 2, '2022-01-02 13:25:15', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 12:06:51', NULL, '2022-01-02 12:55:15', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0b03400e80544594b7e766d48b9d8aed', 1, 2, '2022-01-17 02:44:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 02:14:00', NULL, '2022-01-17 02:14:00', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0b8545465544481da4d162a3a74a552e', 1, 2, '2021-12-15 23:48:37', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:44:07', NULL, '2021-12-15 23:18:37', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0bf9cd592168451aad7b546ff085df58', 1, 2, '2022-01-03 00:00:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 23:30:30', NULL, '2022-01-02 15:39:40', b'1', 1); +INSERT INTO `system_user_session` VALUES ('0c5e3db754714de38ed163c3ef53fb19', 1, 2, '2022-01-17 01:20:21', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 21:33:06', NULL, '2022-01-17 00:50:21', b'0', 1); +INSERT INTO `system_user_session` VALUES ('0c8f02172a894f11a3d054a5811e1c5b', 1, 2, '2022-01-03 09:25:54', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 08:32:07', NULL, '2022-01-03 01:17:42', b'1', 1); +INSERT INTO `system_user_session` VALUES ('0fef9f0bc17047008bef199f1682dce0', 1, 2, '2022-01-21 23:22:20', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 22:29:19', NULL, '2022-01-21 22:52:20', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1168ac997c354e68a9c9a97b3ee3e621', 1, 2, '2022-02-01 23:37:40', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-01 22:57:32', NULL, '2022-02-01 23:07:40', b'0', 1); +INSERT INTO `system_user_session` VALUES ('121a386aef284bbd903188b9b6e72fe0', 1, 2, '2022-01-31 18:15:53', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:45:53', NULL, '2022-01-31 17:45:53', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1645cee3484248929f406fccf8772e67', 1, 2, '2022-01-18 08:43:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 08:01:22', NULL, '2022-01-18 08:13:25', b'0', 1); +INSERT INTO `system_user_session` VALUES ('166cea69fca846c985c62dd365994561', 1, 2, '2022-01-03 11:36:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 09:17:50', NULL, '2022-01-03 11:06:12', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1893bfb924174e3c82f02f18be0606fd', 1, 2, '2022-01-04 00:05:19', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 23:35:19', NULL, '2022-01-03 23:35:19', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1995595036aa4652bb887c43cfd35ba8', 1, 2, '2022-01-01 00:18:24', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 22:57:57', NULL, '2021-12-31 23:48:24', b'0', 1); +INSERT INTO `system_user_session` VALUES ('19fdd80f6ba3491b8a5cd934694a2ddc', 103, 2, '2022-01-11 22:40:28', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 22:10:28', NULL, '2022-01-11 22:10:28', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1b6154299e1a470ebf80d2eaef72b0e2', 1, 2, '2022-01-02 11:59:52', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 09:30:29', NULL, '2022-01-02 11:29:52', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1b7c79d9d8b04b4fb826564fce41f77c', 1, 2, '2022-01-03 22:42:07', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 22:12:07', NULL, '2022-01-03 22:12:07', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1b848d99cde6448097dcedc83fda4c0a', 1, 2, '2021-12-31 10:45:09', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 08:35:36', NULL, '2021-12-31 10:15:09', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1bc6ad0827fe48099bcbdb9a206818ac', 104, 2, '2021-12-15 23:48:59', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 23:18:59', NULL, '2021-12-15 23:18:59', b'0', 1); +INSERT INTO `system_user_session` VALUES ('1bfa6a2ed10741fbb03996a48656f0d2', 1, 2, '2022-01-14 10:48:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 10:18:14', NULL, '2022-01-14 10:18:14', b'0', 1); +INSERT INTO `system_user_session` VALUES ('2150cb32189f4ccdba60a7209dac1e0d', 1, 2, '2022-01-15 22:49:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:19:10', NULL, '2022-01-15 14:20:19', b'1', 1); +INSERT INTO `system_user_session` VALUES ('22adcacad96647bfb8c86fcd7d563be6', 1, 2, '2022-01-28 22:12:41', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:42:41', NULL, '2022-01-28 21:42:41', b'0', 1); +INSERT INTO `system_user_session` VALUES ('234b1084a5574ffc920669d4d230a18b', 1, 2, '2022-01-19 00:08:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 23:38:56', NULL, '2022-01-18 23:38:56', b'0', 1); +INSERT INTO `system_user_session` VALUES ('251bab4618b644faa2c54083ac8b1902', 1, 2, '2022-01-08 01:34:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 00:37:26', NULL, '2022-01-07 17:10:10', b'1', 1); +INSERT INTO `system_user_session` VALUES ('27052d883f1047e68b0841429d234b6b', 1, 2, '2022-01-08 10:25:42', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 09:55:42', NULL, '2022-01-08 09:55:42', b'0', 1); +INSERT INTO `system_user_session` VALUES ('27d8ed14a6394e1f8be6fad865d8355a', 1, 2, '2022-01-11 12:58:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 12:28:28', NULL, '2022-01-11 12:28:28', b'0', 1); +INSERT INTO `system_user_session` VALUES ('28c9235b81474020931acc876d054f9b', 1, 2, '2022-01-31 00:00:54', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-30 23:30:54', NULL, '2022-01-30 23:30:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('28d90f7da308407296fface4ca68d732', 1, 2, '2022-01-01 21:54:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 21:01:18', NULL, '2022-01-01 21:24:30', b'0', 1); +INSERT INTO `system_user_session` VALUES ('291f36ffc1da483981845efd20e8eae4', 1, 2, '2022-01-08 00:23:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-07 23:42:43', NULL, '2022-01-07 23:53:49', b'0', 1); +INSERT INTO `system_user_session` VALUES ('29737038cd76429cb60a279cbeb802ea', 1, 2, '2022-01-28 21:53:22', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:22', NULL, '2022-01-28 21:23:22', b'0', 1); +INSERT INTO `system_user_session` VALUES ('2b49a2e3f5494cebb4a3f19080853355', 103, 2, '2022-01-17 01:26:54', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 00:56:54', NULL, '2022-01-17 00:56:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('2d920ad234a442cd98f5f517d50d6b60', 1, 2, '2022-01-02 16:47:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 14:34:30', NULL, '2022-01-02 16:17:41', b'0', 1); +INSERT INTO `system_user_session` VALUES ('2db67457fb474cfc8a7b7099515ae2aa', 1, 2, '2022-01-23 13:54:43', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 13:24:43', NULL, '2022-01-23 13:24:43', b'0', 1); +INSERT INTO `system_user_session` VALUES ('2ec1ca2d0053415599fa18e6bddf710e', 104, 2, '2021-12-16 10:08:04', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:27:08', NULL, '2021-12-16 09:38:04', b'0', 1); +INSERT INTO `system_user_session` VALUES ('303e29836f3540c79188c835466318b2', 1, 2, '2022-01-19 10:40:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-19 08:35:23', NULL, '2022-01-19 10:10:31', b'0', 1); +INSERT INTO `system_user_session` VALUES ('32a043324c7541d191cdf6a8b667ad6c', 103, 2, '2022-01-15 22:44:58', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:56', NULL, '2022-01-15 14:19:00', b'1', 1); +INSERT INTO `system_user_session` VALUES ('32c405074a3b462681bca9afd26fdfe9', 103, 2, '2022-01-13 13:43:30', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 13:03:29', NULL, '2022-01-13 13:13:30', b'0', 1); +INSERT INTO `system_user_session` VALUES ('345ad9af8d0c46c8ad285b57cabfd060', 1, 2, '2021-12-25 19:57:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 19:15:06', NULL, '2021-12-25 19:27:51', b'0', 1); +INSERT INTO `system_user_session` VALUES ('355c57509a5643519107ec132bd85ba6', 103, 2, '2022-01-14 00:49:12', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 23:12:26', NULL, '2022-01-14 00:19:12', b'0', 1); +INSERT INTO `system_user_session` VALUES ('367c9c23eb4e4539be4ecc737af8fbf6', 103, 2, '2022-01-14 20:39:07', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 18:39:31', NULL, '2022-01-14 20:09:07', b'0', 1); +INSERT INTO `system_user_session` VALUES ('374d99e8a41b464c98f73ddbc5aa4d29', 1, 2, '2022-01-03 04:04:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 23:39:46', NULL, '2022-01-03 03:34:14', b'0', 1); +INSERT INTO `system_user_session` VALUES ('38535319952f41f9b3d94aaf71f42de6', 1, 2, '2022-01-29 17:17:54', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 16:47:54', NULL, '2022-01-29 16:47:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('39647615e860424ebcc9b3f598f135be', 103, 2, '2022-01-18 01:03:40', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:40', NULL, '2022-01-17 16:33:44', b'1', 1); +INSERT INTO `system_user_session` VALUES ('3cc54b8687504a388b5b8c7457d16382', 1, 2, '2022-01-10 21:01:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-10 20:18:15', NULL, '2022-01-10 20:31:18', b'0', 1); +INSERT INTO `system_user_session` VALUES ('3d9a4ffee19c47dfbc3c807adccf4c23', 1, 2, '2022-01-20 01:43:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 00:32:48', NULL, '2022-01-20 01:13:32', b'0', 1); +INSERT INTO `system_user_session` VALUES ('3ec1ce407e8a4accab0b51e756ab74be', 1, 2, '2022-01-20 14:01:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 12:46:56', NULL, '2022-01-20 13:31:25', b'0', 1); +INSERT INTO `system_user_session` VALUES ('3ecf0bc3d9b94cd28f0499bbeb0584b4', 1, 2, '2022-01-28 21:56:46', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:26:46', NULL, '2022-01-28 21:26:46', b'0', 1); +INSERT INTO `system_user_session` VALUES ('3fee3a4e10714d9c9df62b845db37f63', 245, 1, '2022-01-29 14:28:04', '15601691300', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 13:58:04', NULL, '2022-01-29 13:58:04', b'0', 1); +INSERT INTO `system_user_session` VALUES ('42c1711b9b6448c18b0cd621b20bd9e2', 1, 2, '2022-01-16 00:23:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:53:32', NULL, '2022-01-15 23:53:32', b'0', 1); +INSERT INTO `system_user_session` VALUES ('439e30be513e42c094a0a0296b761cc5', 1, 2, '2022-01-13 01:24:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 00:33:14', NULL, '2022-01-13 00:54:38', b'0', 1); +INSERT INTO `system_user_session` VALUES ('47949a90a88d4c49823d70995d980ee9', 1, 2, '2021-12-16 10:04:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:20:41', NULL, '2021-12-16 09:34:30', b'0', 1); +INSERT INTO `system_user_session` VALUES ('488438fbac1e490aba5fadbc5aef18c8', 1, 2, '2022-01-09 00:45:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 23:07:53', NULL, '2022-01-09 00:15:11', b'0', 1); +INSERT INTO `system_user_session` VALUES ('495da339c78846609991d9bc66e17dcf', 1, 2, '2021-12-31 22:54:24', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-31 21:47:55', NULL, '2021-12-31 22:24:24', b'0', 1); +INSERT INTO `system_user_session` VALUES ('4c92facae3a74e6bb714d2a2ce931c6b', 1, 2, '2022-01-31 18:17:25', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:47:25', NULL, '2022-01-31 17:47:25', b'0', 1); +INSERT INTO `system_user_session` VALUES ('4e00d142b22e4826938de31c221b6b32', 104, 2, '2021-12-16 09:54:24', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 09:24:24', NULL, '2021-12-16 01:27:04', b'1', 1); +INSERT INTO `system_user_session` VALUES ('4eb828d1ce434dbea637f0f6f75872bb', 1, 2, '2022-01-28 21:09:33', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 20:39:33', NULL, '2022-01-28 20:39:33', b'0', 1); +INSERT INTO `system_user_session` VALUES ('4f18d2a257bb45148f64b5dd8a895fad', 1, 2, '2022-01-08 23:37:52', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 23:07:52', NULL, '2022-01-08 23:07:52', b'0', 1); +INSERT INTO `system_user_session` VALUES ('51b1fc7d18264e7e97b1992b4994551a', 1, 2, '2022-01-22 20:11:04', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 18:37:19', NULL, '2022-01-22 19:41:04', b'0', 1); +INSERT INTO `system_user_session` VALUES ('55d703899dc74e6881e2a52d11e155dc', 1, 2, '2022-01-16 19:10:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 17:38:41', NULL, '2022-01-16 18:40:11', b'0', 1); +INSERT INTO `system_user_session` VALUES ('569063f65eb24fcc92df57779ea671d5', 1, 2, '2022-01-14 23:10:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 22:23:55', NULL, '2022-01-14 22:40:22', b'0', 1); +INSERT INTO `system_user_session` VALUES ('5921e2838860430b80d02c2dc5bc9b14', 1, 2, '2022-01-01 18:38:17', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 17:19:06', NULL, '2022-01-01 18:08:17', b'0', 1); +INSERT INTO `system_user_session` VALUES ('5c8b305b180648c4919384c2204262f1', 1, 2, '2022-01-18 00:20:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:50:50', NULL, '2022-01-17 15:50:58', b'1', 1); +INSERT INTO `system_user_session` VALUES ('5cb75ff3873b4ee99c54ca8126b6a239', 103, 2, '2022-01-18 00:21:08', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:51:08', NULL, '2022-01-17 23:51:08', b'0', 1); +INSERT INTO `system_user_session` VALUES ('5d65f92a84b5497787686e513289372f', 1, 2, '2022-01-16 00:16:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:46:18', NULL, '2022-01-15 15:47:33', b'1', 1); +INSERT INTO `system_user_session` VALUES ('5e6bd35bd4c24f1fb717d59256b937b0', 1, 2, '2022-01-23 04:14:45', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 03:21:32', NULL, '2022-01-22 20:10:37', b'1', 1); +INSERT INTO `system_user_session` VALUES ('5e8984281b354935b422c95a06ac9ff8', 1, 2, '2022-01-20 14:21:17', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 13:31:17', NULL, '2022-01-20 13:51:17', b'0', 1); +INSERT INTO `system_user_session` VALUES ('604d98299b7243ddafa3ee0350f6edce', 1, 2, '2022-01-22 01:00:30', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 00:00:28', NULL, '2022-01-22 00:30:30', b'0', 1); +INSERT INTO `system_user_session` VALUES ('6308a8a2833d4570a56cd8af3cd13367', 1, 2, '2022-01-31 14:00:40', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 13:30:40', NULL, '2022-01-31 13:30:40', b'0', 1); +INSERT INTO `system_user_session` VALUES ('63d50b8b7e4448f98bd4ab2c084ac18f', 103, 2, '2022-01-17 13:18:45', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:48:45', NULL, '2022-01-17 12:48:45', b'0', 1); +INSERT INTO `system_user_session` VALUES ('63ea8e8249cb4089b4b0d10256f39ba4', 1, 2, '2022-01-11 13:52:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:22:44', NULL, '2022-01-11 05:23:14', b'1', 1); +INSERT INTO `system_user_session` VALUES ('64f51e60527349d6b4a0a74f3d8eca97', 104, 2, '2021-12-16 07:37:54', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:07:54', NULL, '2021-12-16 07:07:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('671e9e7d2be541efa538d337f4e7752d', 1, 2, '2022-02-02 00:54:35', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:24:35', NULL, '2022-02-02 00:24:35', b'0', 1); +INSERT INTO `system_user_session` VALUES ('690be3aeef894ec3b3cef553b76082fa', 1, 2, '2022-01-28 21:54:02', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:24:02', NULL, '2022-01-28 21:24:02', b'0', 1); +INSERT INTO `system_user_session` VALUES ('6b7d55bad59e401cb1f8d6c418bf552e', 103, 2, '2022-01-14 10:43:59', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 09:49:52', NULL, '2022-01-14 10:13:59', b'0', 1); +INSERT INTO `system_user_session` VALUES ('6d554dd8e0724ff9907bc1186119280c', 1, 2, '2022-01-23 01:22:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 23:30:35', NULL, '2022-01-23 00:52:38', b'0', 1); +INSERT INTO `system_user_session` VALUES ('6f0e4f523b13484c94d0dfe49d505d41', 103, 2, '2022-01-13 10:46:00', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 09:51:45', NULL, '2022-01-13 10:16:00', b'0', 1); +INSERT INTO `system_user_session` VALUES ('725e3f1407844ffebbaf02ba0673e0a4', 103, 2, '2022-01-16 12:23:58', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 11:53:58', NULL, '2022-01-16 11:53:58', b'0', 1); +INSERT INTO `system_user_session` VALUES ('729362aa59ed43cf9606a163883f2f2a', 103, 2, '2022-01-15 22:27:50', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:32:02', NULL, '2022-01-15 13:58:33', b'1', 1); +INSERT INTO `system_user_session` VALUES ('798b6db869fb4a77802824df2811be31', 1, 2, '2022-01-28 21:55:00', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:25:00', NULL, '2022-01-28 21:25:00', b'0', 1); +INSERT INTO `system_user_session` VALUES ('79924bcc8d594452a8ee8406d312b2c2', 1, 2, '2022-01-01 23:37:34', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 22:02:06', NULL, '2022-01-01 23:07:34', b'0', 1); +INSERT INTO `system_user_session` VALUES ('7aa8d8f930f34aba857c14db311a9a02', 1, 2, '2022-01-11 10:44:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 09:58:54', NULL, '2022-01-11 10:14:50', b'0', 1); +INSERT INTO `system_user_session` VALUES ('7b60ae1b30734903a34b9c7f8723d5e2', 103, 2, '2022-01-14 01:33:42', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 00:51:03', NULL, '2022-01-14 01:03:42', b'0', 1); +INSERT INTO `system_user_session` VALUES ('7bc4dca653954475b05cf233c08f783e', 103, 2, '2022-01-15 13:23:54', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 11:56:10', NULL, '2022-01-15 12:53:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('7be6aecdb9d340609c87e29e608b886d', 1, 2, '2022-01-28 21:56:48', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:26:48', NULL, '2022-01-28 21:26:48', b'0', 1); +INSERT INTO `system_user_session` VALUES ('7d55dfdc996d4d24a0c4c6aad6065ca4', 103, 2, '2022-01-12 01:00:08', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 23:33:26', NULL, '2022-01-12 00:30:08', b'0', 1); +INSERT INTO `system_user_session` VALUES ('83b5043f08e34cd8aad97c2c798a8f00', 1, 2, '2022-01-23 02:12:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 01:42:39', NULL, '2022-01-23 01:42:39', b'0', 1); +INSERT INTO `system_user_session` VALUES ('83c9839e34454f0eba630f29002d0ee3', 1, 2, '2022-01-09 23:00:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 20:59:49', NULL, '2022-01-09 22:30:41', b'0', 1); +INSERT INTO `system_user_session` VALUES ('845e9e7778a64200a87993db0fe6872d', 1, 2, '2022-01-21 00:12:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-20 23:42:44', NULL, '2022-01-20 23:42:44', b'0', 1); +INSERT INTO `system_user_session` VALUES ('84cc13aee41d473c987c1c0381cc05b1', 1, 2, '2022-01-09 02:01:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 01:03:29', NULL, '2022-01-09 01:31:10', b'0', 1); +INSERT INTO `system_user_session` VALUES ('882e89a623154797ac2a213c78da1f69', 1, 2, '2022-01-18 00:13:23', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 23:33:03', NULL, '2022-01-17 23:43:23', b'0', 1); +INSERT INTO `system_user_session` VALUES ('89bd23481c9a4b598ebea524679441b3', 103, 2, '2022-01-15 00:57:03', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 23:51:41', NULL, '2022-01-15 00:27:03', b'0', 1); +INSERT INTO `system_user_session` VALUES ('89cc980ca0d941109b3933c82d01d9c3', 103, 2, '2022-01-15 22:30:17', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:17', NULL, '2022-01-15 14:00:35', b'1', 1); +INSERT INTO `system_user_session` VALUES ('8c49cc6f52154dca9da6a2632985aa35', 1, 2, '2022-01-08 09:05:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 07:10:02', NULL, '2022-01-08 08:35:55', b'0', 1); +INSERT INTO `system_user_session` VALUES ('8dfa794cc43840f99b2cc7ba287356ab', 1, 2, '2022-01-28 23:51:07', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 23:21:07', NULL, '2022-01-28 23:21:07', b'0', 1); +INSERT INTO `system_user_session` VALUES ('8e9599699f5141d2b041b855c7b34181', 1, 2, '2022-01-16 13:45:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 13:15:56', NULL, '2022-01-16 13:15:56', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9122b55409a94388a7b277ad808a127c', 1, 2, '2022-01-01 17:18:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 16:20:04', NULL, '2022-01-01 16:48:53', b'0', 1); +INSERT INTO `system_user_session` VALUES ('91b94971b7f044c8b68420e6ef7377af', 1, 2, '2022-01-02 17:32:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 17:02:50', NULL, '2022-01-02 17:02:50', b'0', 1); +INSERT INTO `system_user_session` VALUES ('93ada27b50d24c1a9b476c7fd4fef2ce', 1, 2, '2022-01-11 13:49:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:09:10', NULL, '2022-01-11 05:22:27', b'1', 1); +INSERT INTO `system_user_session` VALUES ('93caa65dbd9d480299850552067a031a', 1, 2, '2022-01-15 22:01:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:31:33', NULL, '2022-01-15 13:31:53', b'1', 1); +INSERT INTO `system_user_session` VALUES ('945e4bb19f4d4c28ba7135218ee3abe3', 1, 2, '2021-12-16 08:28:54', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:42:25', NULL, '2021-12-16 07:58:54', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9526809b303f489b8aab0c05e6b483dd', 1, 2, '2022-01-01 00:51:19', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 00:21:19', NULL, '2022-01-01 00:21:19', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9655c170353849dfadfdc810c6c5ca61', 1, 2, '2022-01-03 12:50:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 11:56:55', NULL, '2022-01-03 12:20:55', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9a84339c3c594140b0c3a9bfe95f7919', 1, 2, '2022-01-18 01:03:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:28', NULL, '2022-01-18 00:33:28', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9cb0aefe562d4332bd5a1188ca55552d', 1, 2, '2022-01-28 21:55:14', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:25:14', NULL, '2022-01-28 21:25:14', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9ee1349d7d3043759cb742a0fa5a3163', 1, 2, '2021-12-25 19:08:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 18:38:33', NULL, '2021-12-25 18:38:33', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9f24e48662764c6b8b3ba9b4dab24205', 1, 2, '2022-01-28 10:19:07', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 09:49:07', NULL, '2022-01-28 09:49:07', b'0', 1); +INSERT INTO `system_user_session` VALUES ('9f3266f59b8746c3bfe143361d86f6e8', 1, 2, '2022-01-08 22:31:37', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 22:01:37', NULL, '2022-01-08 22:01:37', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a09624232ed94b44a846023790e6282f', 1, 2, '2022-01-09 13:45:26', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 12:59:15', NULL, '2022-01-09 13:15:26', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a155e6dfe4b74fbaa69fcca239facc40', 1, 2, '2021-12-16 07:37:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-16 07:07:39', NULL, '2021-12-16 07:07:39', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a17d02a7c4264f7489728f510e40e823', 1, 2, '2022-01-17 13:18:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:48:31', NULL, '2022-01-17 04:48:37', b'1', 1); +INSERT INTO `system_user_session` VALUES ('a30e807e5db640feb92bb1eeb4ae89d0', 1, 2, '2022-01-16 12:23:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 11:53:10', NULL, '2022-01-16 11:53:10', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a4688af426e342a69c814d07bb8f7d3b', 1, 2, '2022-01-08 17:21:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 16:25:34', NULL, '2022-01-08 16:51:11', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a49e304816e0477998592c76caa9546d', 1, 2, '2022-01-16 01:20:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 00:30:18', NULL, '2022-01-16 00:50:18', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a55b31ff9e6a41fcb931d2244b4240a8', 1, 2, '2021-12-30 22:32:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-30 20:04:02', NULL, '2021-12-30 22:02:56', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a88e404ba71e41b0a16c75a8ce44bb9d', 1, 2, '2022-01-09 11:57:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 11:27:51', NULL, '2022-01-09 11:27:51', b'0', 1); +INSERT INTO `system_user_session` VALUES ('a9b27f95517d4ef9ae15c68bd4365d1b', 103, 2, '2022-01-11 20:37:20', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 19:35:41', NULL, '2022-01-11 20:07:20', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ab449ce8f2ea456591d23515c188c242', 1, 2, '2021-12-25 17:55:45', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-25 16:42:42', NULL, '2021-12-25 17:25:45', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ac730d1c96be41e5821a6de24b23bf7b', 103, 2, '2022-01-11 20:05:41', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 19:35:41', NULL, '2022-01-11 19:35:41', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ac88c6d1cb184979a015e9a8b50e21f0', 1, 2, '2022-01-03 04:59:36', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 03:39:08', NULL, '2022-01-03 04:29:36', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ae2a8c4a7df64271b0e7a2b702c378f8', 1, 2, '2022-01-18 02:18:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:58:20', NULL, '2022-01-18 01:48:53', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b12325b8930245c09b75aa100dc1124d', 1, 2, '2022-01-01 09:12:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 08:09:05', NULL, '2022-01-01 08:42:53', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b25e2297fca14a5e843288df2aa59c12', 1, 2, '2022-01-23 04:49:53', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 04:19:53', NULL, '2022-01-23 04:19:53', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b523e3add6e74587b247b467de677325', 1, 2, '2022-01-18 01:15:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-18 00:33:47', NULL, '2022-01-18 00:45:31', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b64443d1c4bd4f8eabdff02c47f6ae26', 1, 2, '2022-01-28 21:53:20', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:20', NULL, '2022-01-28 21:23:20', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b6a02289210b4861b71a363b11b6b919', 1, 2, '2022-01-09 11:23:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 10:39:49', NULL, '2022-01-09 10:53:22', b'0', 1); +INSERT INTO `system_user_session` VALUES ('b883ba1582f54826b42fa073276c85cb', 1, 2, '2022-01-08 01:40:34', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 01:10:34', NULL, '2022-01-08 01:10:34', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ba1658c24b78442fb39062e31d902a5f', 1, 2, '2022-01-10 20:12:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-10 19:21:24', NULL, '2022-01-10 19:42:44', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bb14f39f65ca41cc8ef915ad7f0c25d6', 1, 2, '2022-01-09 09:40:48', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 08:48:56', NULL, '2022-01-09 09:10:48', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bcd449a215fd432e8154d883f954606b', 1, 2, '2022-01-28 21:52:31', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:22:31', NULL, '2022-01-28 21:22:31', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bce9ee82f6f34159acfc26e5e994b892', 1, 2, '2022-01-23 13:42:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-23 12:40:59', NULL, '2022-01-23 13:12:55', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bd2b51a53b8d4046b024f43406985caf', 103, 2, '2022-01-15 23:31:38', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:20:30', NULL, '2022-01-15 23:01:38', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bd52c43710274cd8bd888b1737cd939d', 1, 2, '2022-01-22 23:09:46', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 20:45:15', NULL, '2022-01-22 22:39:46', b'0', 1); +INSERT INTO `system_user_session` VALUES ('bd655254904748f79c0ad47dfb49d457', 1, 2, '2022-01-01 08:05:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 07:35:32', NULL, '2022-01-01 07:35:32', b'0', 1); +INSERT INTO `system_user_session` VALUES ('be98e2f02a444a4092d1cea3dc6e3073', 1, 2, '2022-01-17 13:34:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-17 12:26:04', NULL, '2022-01-17 13:04:51', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c09baa895d79468db63417f60c65573c', 1, 2, '2022-01-01 11:33:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 10:13:48', NULL, '2022-01-01 11:03:44', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c0f2be79200f4f0b9c6304745742b468', 245, 1, '2022-01-29 01:07:51', '15601691300', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 00:37:51', NULL, '2022-01-29 00:37:51', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c1797274297f4cd7b859c6c482d06005', 1, 2, '2022-01-09 10:26:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 09:44:24', NULL, '2022-01-09 09:56:00', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c386c570da874af588fd4e64f86dadfc', 1, 2, '2022-01-31 17:45:38', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.13)', NULL, '2022-01-31 17:15:38', NULL, '2022-01-31 17:15:38', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c425763ad38c471a9f6e572ee2fd85ae', 1, 2, '2022-01-24 08:20:09', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-24 07:50:09', NULL, '2022-01-24 07:50:09', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c591d431be494e8c847a6b9ee4b0b3dc', 1, 2, '2022-02-02 01:41:58', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:27:55', NULL, '2022-02-02 01:11:58', b'0', 1); +INSERT INTO `system_user_session` VALUES ('c7c4d30623c84d3e88aab2f0b742e7c3', 1, 2, '2022-01-21 01:14:47', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 00:24:00', NULL, '2022-01-20 16:54:39', b'1', 1); +INSERT INTO `system_user_session` VALUES ('c7fc3e37d927405ebbe66df3dd5fd77e', 103, 2, '2022-01-13 01:01:29', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 22:57:04', NULL, '2022-01-13 00:31:29', b'0', 1); +INSERT INTO `system_user_session` VALUES ('cbd09ba52ccc47b2a639a6e28e92894f', 103, 2, '2022-01-12 01:34:01', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 01:04:01', NULL, '2022-01-12 01:04:01', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ccc85a8ee5a7407c97012b755cde979e', 1, 2, '2022-01-16 18:08:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 17:38:41', NULL, '2022-01-16 17:38:41', b'0', 1); +INSERT INTO `system_user_session` VALUES ('d229b8f8ef4d4df4afd05209acc87446', 1, 2, '2022-01-08 11:02:36', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-08 10:32:36', NULL, '2022-01-08 02:37:12', b'1', 1); +INSERT INTO `system_user_session` VALUES ('d46d26f08f624eb28eb665b6515587bd', 1, 2, '2022-01-16 00:19:32', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 23:49:32', NULL, '2022-01-15 23:49:32', b'0', 1); +INSERT INTO `system_user_session` VALUES ('d4aeab42d1934197865ce72ffe244009', 1, 2, '2022-01-16 03:11:56', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 02:41:56', NULL, '2022-01-16 02:41:56', b'0', 1); +INSERT INTO `system_user_session` VALUES ('d8550bde3c8b43a194e592b49c856c71', 1, 2, '2022-01-09 21:26:38', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 19:38:12', NULL, '2022-01-09 20:56:38', b'0', 1); +INSERT INTO `system_user_session` VALUES ('d8ebbe89793f4a829a108c4f1badbb11', 103, 2, '2022-01-13 21:18:56', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-13 20:38:43', NULL, '2022-01-13 20:48:56', b'0', 1); +INSERT INTO `system_user_session` VALUES ('da04f99dc14a4f28a8a77178861cb3ed', 104, 2, '2021-12-15 23:37:58', 'test', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:47:31', NULL, '2021-12-15 15:11:55', b'1', 1); +INSERT INTO `system_user_session` VALUES ('daec82cc885849a7bbab76eb9f0a4b32', 1, 2, '2022-01-15 23:31:35', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 22:00:43', NULL, '2022-01-15 23:01:35', b'0', 1); +INSERT INTO `system_user_session` VALUES ('dbaaa89e1659488c9693317454fe6ae2', 1, 2, '2022-01-14 22:53:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 22:23:55', NULL, '2022-01-14 22:23:55', b'0', 1); +INSERT INTO `system_user_session` VALUES ('dbe0f27930244ae38e0322226d6ecdbb', 1, 2, '2022-01-21 01:46:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-21 00:54:45', NULL, '2022-01-21 01:16:31', b'0', 1); +INSERT INTO `system_user_session` VALUES ('dd2e53ccf8c44b3e8556571687d4825d', 103, 2, '2022-01-12 01:34:01', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-12 01:04:01', NULL, '2022-01-12 01:04:01', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ddb9d3c65ee14c4a8ff1a3cf0e10e69a', 1, 2, '2022-01-19 00:52:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-19 00:22:57', NULL, '2022-01-19 00:22:57', b'0', 1); +INSERT INTO `system_user_session` VALUES ('ddd32e0a43d644ca95ba10e4e5b19416', 1, 2, '2022-01-03 19:28:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 17:22:27', NULL, '2022-01-03 18:58:22', b'0', 1); +INSERT INTO `system_user_session` VALUES ('df12a50eb8814317bb8e1003e098cbe7', 1, 2, '2022-01-09 19:04:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-09 16:26:16', NULL, '2022-01-09 18:34:00', b'0', 1); +INSERT INTO `system_user_session` VALUES ('e198f4f04da243d5b80caa0c8336d6a0', 103, 2, '2022-01-14 19:09:16', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 18:39:16', NULL, '2022-01-14 10:39:24', b'1', 1); +INSERT INTO `system_user_session` VALUES ('e290aebda5f34c379d0cf3e013cbcc8b', 1, 2, '2022-01-02 09:27:23', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-02 08:32:23', NULL, '2022-01-02 08:57:23', b'0', 1); +INSERT INTO `system_user_session` VALUES ('e2efa96cacbb47b580096193244a3739', 1, 2, '2022-01-14 14:24:13', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-14 13:44:04', NULL, '2022-01-14 13:54:13', b'0', 1); +INSERT INTO `system_user_session` VALUES ('e3c0319f639a481999bac6fa250af552', 1, 2, '2022-01-03 16:56:06', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 16:14:34', NULL, '2022-01-03 16:26:06', b'0', 1); +INSERT INTO `system_user_session` VALUES ('e42efabb61af4f5eaeea3b84693871da', 1, 2, '2022-01-15 22:28:55', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-15 21:58:55', NULL, '2022-01-15 14:00:08', b'1', 1); +INSERT INTO `system_user_session` VALUES ('e75c264df71342a59a85a6512a5a1fb7', 1, 2, '2022-01-22 19:18:46', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 18:30:58', NULL, '2022-01-22 18:48:46', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f0285533812349a9a6c548a9a9dda1b7', 245, 1, '2022-01-29 12:20:08', '15601691300', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-29 11:50:08', NULL, '2022-01-29 11:50:08', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f10cabf849b245ebbaa5284b540c0bb2', 103, 2, '2022-01-11 21:51:14', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 20:54:19', NULL, '2022-01-11 21:21:14', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f2dcbc8096b14903a5f66d01a8335d78', 1, 2, '2022-01-28 21:53:36', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:23:36', NULL, '2022-01-28 21:23:36', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f42ef6d30bd34349addf16b8a9edaf16', 1, 2, '2022-01-28 21:52:45', 'admin', '127.0.0.1', 'Apache-HttpClient/4.5.13 (Java/11.0.11)', NULL, '2022-01-28 21:22:45', NULL, '2022-01-28 21:22:45', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f49ade9038d24a73832e64efcc30b205', 103, 2, '2022-01-11 13:53:26', 'yuanma', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-11 13:23:26', NULL, '2022-01-11 13:23:26', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f562fd12a7bb41f19ca1bf4aa5e3c9d1', 1, 2, '2022-01-22 02:42:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 01:20:59', NULL, '2022-01-22 02:12:51', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f76c8610a7e5461aac8972e21f14e734', 1, 2, '2022-01-22 21:52:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-22 20:29:53', NULL, '2022-01-22 21:22:44', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f974a40ea70941cdb9e04cb63bf5e557', 1, 2, '2022-01-16 02:00:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36', NULL, '2022-01-16 01:30:25', NULL, '2022-01-16 01:30:25', b'0', 1); +INSERT INTO `system_user_session` VALUES ('f9f257cf09e640f2904696f2de35d3f6', 1, 2, '2022-01-03 21:42:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-03 20:59:23', NULL, '2022-01-03 21:12:44', b'0', 1); +INSERT INTO `system_user_session` VALUES ('fcac1dd7161d46cbb60fd66b898a9503', 1, 2, '2022-02-02 00:55:21', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36', NULL, '2022-02-02 00:25:21', NULL, '2022-02-01 16:26:40', b'1', 1); +INSERT INTO `system_user_session` VALUES ('fe82f6ecb17449b595c7d6bd4bc1d371', 1, 2, '2021-12-15 23:16:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2021-12-15 22:46:49', NULL, '2021-12-15 14:46:53', b'1', 1); +INSERT INTO `system_user_session` VALUES ('ffeae9ee4b8649b6b9ececaa502a934d', 1, 2, '2022-01-01 19:56:49', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36', NULL, '2022-01-01 18:47:31', NULL, '2022-01-01 19:26:49', b'0', 1); COMMIT; -- ---------------------------- @@ -2878,26 +3455,26 @@ DROP TABLE IF EXISTS `tool_codegen_column`; CREATE TABLE `tool_codegen_column` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `table_id` bigint NOT NULL COMMENT '表编号', - `column_name` varchar(200) NOT NULL COMMENT '字段名', - `column_type` varchar(100) NOT NULL COMMENT '字段类型', - `column_comment` varchar(500) NOT NULL COMMENT '字段描述', + `column_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '字段名', + `column_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '字段类型', + `column_comment` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '字段描述', `nullable` bit(1) NOT NULL COMMENT '是否允许为空', `primary_key` bit(1) NOT NULL COMMENT '是否主键', - `auto_Increment` char(1) NOT NULL COMMENT '是否自增', + `auto_Increment` char(1) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '是否自增', `ordinal_position` int NOT NULL COMMENT '排序', - `java_type` varchar(32) NOT NULL COMMENT 'Java 属性类型', - `java_field` varchar(64) NOT NULL COMMENT 'Java 属性名', - `dict_type` varchar(200) DEFAULT '' COMMENT '字典类型', - `example` varchar(64) DEFAULT NULL COMMENT '数据示例', + `java_type` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Java 属性类型', + `java_field` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Java 属性名', + `dict_type` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '字典类型', + `example` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '数据示例', `create_operation` bit(1) NOT NULL COMMENT '是否为 Create 创建操作的字段', `update_operation` bit(1) NOT NULL COMMENT '是否为 Update 更新操作的字段', `list_operation` bit(1) NOT NULL COMMENT '是否为 List 查询操作的字段', - `list_operation_condition` varchar(32) NOT NULL DEFAULT '=' COMMENT 'List 查询操作的条件类型', + `list_operation_condition` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '=' COMMENT 'List 查询操作的条件类型', `list_operation_result` bit(1) NOT NULL COMMENT '是否为 List 查询操作的返回字段', - `html_type` varchar(32) NOT NULL COMMENT '显示类型', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `html_type` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '显示类型', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -3162,19 +3739,19 @@ DROP TABLE IF EXISTS `tool_codegen_table`; CREATE TABLE `tool_codegen_table` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `import_type` tinyint NOT NULL DEFAULT '1' COMMENT '导入类型', - `table_name` varchar(200) NOT NULL DEFAULT '' COMMENT '表名称', - `table_comment` varchar(500) NOT NULL DEFAULT '' COMMENT '表描述', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', - `module_name` varchar(30) NOT NULL COMMENT '模块名', - `business_name` varchar(30) NOT NULL COMMENT '业务名', - `class_name` varchar(100) NOT NULL DEFAULT '' COMMENT '类名称', - `class_comment` varchar(50) NOT NULL COMMENT '类描述', - `author` varchar(50) NOT NULL COMMENT '作者', + `table_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '表名称', + `table_comment` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '表描述', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `module_name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '模块名', + `business_name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '业务名', + `class_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '类名称', + `class_comment` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '类描述', + `author` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '作者', `template_type` tinyint NOT NULL DEFAULT '1' COMMENT '模板类型', `parent_menu_id` bigint DEFAULT NULL COMMENT '父菜单编号', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE @@ -3210,14 +3787,14 @@ COMMIT; DROP TABLE IF EXISTS `tool_test_demo`; CREATE TABLE `tool_test_demo` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字', + `name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态', `type` tinyint NOT NULL COMMENT '类型', `category` tinyint NOT NULL COMMENT '分类', - `remark` varchar(500) DEFAULT NULL COMMENT '备注', - `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注', + `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE diff --git a/yudao-admin-server/pom.xml b/yudao-admin-server/pom.xml deleted file mode 100644 index 847e626a03..0000000000 --- a/yudao-admin-server/pom.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - cn.iocoder.boot - yudao - ${revision} - - 4.0.0 - - yudao-admin-server - jar - - yudao-admin-server - 管理后台 Server,提供其 API 接口 - https://github.com/YunaiV/ruoyi-vue-pro - - - - - cn.iocoder.boot - yudao-core-service - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-operatelog - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-dict - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-tenant - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-data-permission - - - - cn.iocoder.boot - yudao-spring-boot-starter-activiti - - - - - cn.iocoder.boot - yudao-spring-boot-starter-web - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - cn.iocoder.boot - yudao-spring-boot-starter-redis - - - - - cn.iocoder.boot - yudao-spring-boot-starter-config - - - - - cn.iocoder.boot - yudao-spring-boot-starter-job - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mq - - - - - cn.iocoder.boot - yudao-spring-boot-starter-protection - - - - - cn.iocoder.boot - yudao-spring-boot-starter-monitor - - - - de.codecentric - spring-boot-admin-starter-server - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - - - - - cn.iocoder.boot - yudao-spring-boot-starter-excel - - - - org.apache.velocity - velocity-engine-core - - - - cn.smallbun.screw - screw-core - - - - - - com.xkcoding.justauth - justauth-spring-boot-starter - - - - - - ${artifactId} - - - - org.springframework.boot - spring-boot-maven-plugin - - true - - - - - repackage - - - - - - - - diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java deleted file mode 100644 index e99c106b45..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.adminserver.framework.security; - -import cn.iocoder.yudao.framework.web.config.WebProperties; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; - -import javax.annotation.Resource; - -@Configuration -public class SecurityConfiguration { - - @Resource - private WebProperties webProperties; - - @Value("${spring.boot.admin.context-path:''}") - private String adminSeverContextPath; - - @Bean - public Customizer.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() { - return registry -> { - // 验证码的接口 - registry.antMatchers(api("/system/captcha/**")).anonymous(); - // 获得租户编号的接口 - registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous(); - // Spring Boot Admin Server 的安全配置 - registry.antMatchers(adminSeverContextPath).anonymous() - .antMatchers(adminSeverContextPath + "/**").anonymous(); - // 短信回调 API - registry.antMatchers(api("/system/sms/callback/**")).anonymous(); - }; - } - - private String api(String url) { - return webProperties.getApiPrefix() + url; - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/message/BpmMessageConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/message/BpmMessageConvert.java deleted file mode 100644 index 7d7f1518fd..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/message/BpmMessageConvert.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.message; - -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import org.activiti.api.task.model.Task; -import org.activiti.engine.runtime.ProcessInstance; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.MappingTarget; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface BpmMessageConvert { - - BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class); - - default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, SysUserDO startUser, Task task) { - BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); - copyTo(processInstance, reqDTO); - copyTo(startUser, reqDTO); - copyTo(task, reqDTO); - return reqDTO; - } - @Mapping(source = "name", target = "processInstanceName") - void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); - @Mappings({ - @Mapping(source = "id", target = "startUserId"), - @Mapping(source = "nickname", target = "startUserNickname") - }) - void copyTo(SysUserDO from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); - @Mappings({ - @Mapping(source = "id", target = "taskId"), - @Mapping(source = "name", target = "taskName"), - @Mapping(source = "assignee", target = "assigneeUserId") - }) - void copyTo(Task task, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); - - default BpmMessageSendWhenProcessInstanceRejectReqDTO convert(ProcessInstance processInstance, String comment) { - BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO = new BpmMessageSendWhenProcessInstanceRejectReqDTO(); - copyTo(processInstance, reqDTO); - reqDTO.setComment(comment); - return reqDTO; - } - @Mapping(source = "name", target = "processInstanceName") - void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenProcessInstanceRejectReqDTO to); - - @Mappings({ - @Mapping(source = "id", target = "processInstanceId"), - @Mapping(source = "name", target = "processInstanceName"), - @Mapping(source = "initiator", target = "startUserId") - }) - BpmMessageSendWhenProcessInstanceApproveReqDTO convert(org.activiti.api.process.model.ProcessInstance processInstance); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/package-info.java deleted file mode 100644 index 1b704ce3f7..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * 自定义各种 Activiti 的监听器,实现流程示例、流程任务的拓展表信息的同步 - * 例如说,{@link org.activiti.api.task.model.Task} 新建时,我们也要新建对应的 {@link cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO} 记录 - * - * @author 芋道源码 - */ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExportReqVO.java deleted file mode 100644 index 9c578e96c6..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExportReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -@ApiModel(value = "定时任务 Excel 导出 Request VO", description = "参数和 InfJobPageReqVO 是一致的") -@Data -public class InfJobExportReqVO { - - @ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配") - private String name; - - @ApiModelProperty(value = "任务状态", example = "1", notes = "参见 InfJobStatusEnum 枚举") - private Integer status; - - @ApiModelProperty(value = "处理器的名字", example = "sysUserSessionTimeoutJob", notes = "模糊匹配") - private String handlerName; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/config/InfConfigConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/config/InfConfigConvert.java deleted file mode 100644 index 4a5eaf2f73..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/config/InfConfigConvert.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.config; - -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigUpdateReqVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface InfConfigConvert { - - InfConfigConvert INSTANCE = Mappers.getMapper(InfConfigConvert.class); - - PageResult convertPage(PageResult page); - - InfConfigRespVO convert(InfConfigDO bean); - - InfConfigDO convert(InfConfigCreateReqVO bean); - - InfConfigDO convert(InfConfigUpdateReqVO bean); - - List convertList(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/file/InfFileConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/file/InfFileConvert.java deleted file mode 100644 index aedad94d92..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/file/InfFileConvert.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.file; - -import cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo.InfFileRespVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface InfFileConvert { - - InfFileConvert INSTANCE = Mappers.getMapper(InfFileConvert.class); - - InfFileRespVO convert(InfFileDO bean); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobConvert.java deleted file mode 100644 index 2b6fbc1d95..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobConvert.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.job; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 定时任务 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface InfJobConvert { - - InfJobConvert INSTANCE = Mappers.getMapper(InfJobConvert.class); - - InfJobDO convert(InfJobCreateReqVO bean); - - InfJobDO convert(InfJobUpdateReqVO bean); - - InfJobRespVO convert(InfJobDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobLogConvert.java deleted file mode 100644 index 146c7fb34a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/job/InfJobLogConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.job; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 定时任务日志 Convert - * - * @author 芋艿 - */ -@Mapper -public interface InfJobLogConvert { - - InfJobLogConvert INSTANCE = Mappers.getMapper(InfJobLogConvert.class); - - InfJobLogRespVO convert(InfJobLogDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiAccessLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiAccessLogConvert.java deleted file mode 100644 index 1b4faa0be3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiAccessLogConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.logger; - -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * API 访问日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface InfApiAccessLogConvert { - - InfApiAccessLogConvert INSTANCE = Mappers.getMapper(InfApiAccessLogConvert.class); - - InfApiAccessLogRespVO convert(InfApiAccessLogDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiErrorLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiErrorLogConvert.java deleted file mode 100644 index de10d48fc8..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/logger/InfApiErrorLogConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.logger; - -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * API 错误日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface InfApiErrorLogConvert { - - InfApiErrorLogConvert INSTANCE = Mappers.getMapper(InfApiErrorLogConvert.class); - - InfApiErrorLogRespVO convert(InfApiErrorLogDO bean); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/package-info.java deleted file mode 100644 index 3c74fe7ad2..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 POJO 类的实体转换 - * - * 目前使用 MapStruct 框架 - */ -package cn.iocoder.yudao.adminserver.modules.infra.convert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/file/InfFileMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/file/InfFileMapper.java deleted file mode 100644 index d3dfcccbbe..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/file/InfFileMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -/** - * admin 文件操作 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface InfFileMapper extends BaseMapperX { - default PageResult selectPage(InfFilePageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() - .likeIfPresent("id", reqVO.getId()) - .likeIfPresent("type", reqVO.getType()) - .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc("create_time")); - } -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobMapper.java deleted file mode 100644 index 1f4a83792d..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 定时任务 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface InfJobMapper extends BaseMapperX { - - default InfJobDO selectByHandlerName(String handlerName) { - return selectOne(InfJobDO::getHandlerName, handlerName); - } - - default PageResult selectPage(InfJobPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(InfJobDO::getName, reqVO.getName()) - .eqIfPresent(InfJobDO::getStatus, reqVO.getStatus()) - .likeIfPresent(InfJobDO::getHandlerName, reqVO.getHandlerName()) - ); - } - - default List selectList(InfJobExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(InfJobDO::getName, reqVO.getName()) - .eqIfPresent(InfJobDO::getStatus, reqVO.getStatus()) - .likeIfPresent(InfJobDO::getHandlerName, reqVO.getHandlerName()) - ); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfDictTypeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfDictTypeConstants.java deleted file mode 100644 index aabbae4f12..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfDictTypeConstants.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums; - -/** - * Infra 字典类型的枚举类 - * - * @author 芋道源码 - */ -public interface InfDictTypeConstants { - - String REDIS_TIMEOUT_TYPE = "inf_redis_timeout_type"; // Redis 超时类型 - - String JOB_STATUS = "inf_job_status"; // 定时任务状态的枚举 - String JOB_LOG_STATUS = "inf_job_log_status"; // 定时任务日志状态的枚举 - - String API_ERROR_LOG_PROCESS_STATUS = "inf_api_error_log_process_status"; // API 错误日志的处理状态的枚举 - - String ERROR_CODE_TYPE = "inf_error_code_type"; // 错误码的类型枚举 - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java deleted file mode 100644 index 106e16218b..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums.logger; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * API 异常数据的处理状态 - * - * @author 芋道源码 - */ -@AllArgsConstructor -@Getter -public enum InfApiErrorLogProcessStatusEnum { - - INIT(0, "未处理"), - DONE(1, "已处理"), - IGNORE(2, "已忽略"); - - /** - * 状态 - */ - private final Integer status; - /** - * 资源类型名 - */ - private final String name; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/package-info.java deleted file mode 100644 index f73455a304..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.consumer; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/package-info.java deleted file mode 100644 index 9db3856431..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.message; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/package-info.java deleted file mode 100644 index 0112c34857..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.producer; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/package-info.java deleted file mode 100644 index b97607f354..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 - * 例如说:定时任务的管理、服务器的信息等等 - * - * 缩写:inf - */ -package cn.iocoder.yudao.adminserver.modules.infra; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/impl/InfConfigServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/impl/InfConfigServiceImpl.java deleted file mode 100644 index 65839e20e9..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/impl/InfConfigServiceImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.config.impl; - -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.config.InfConfigConvert; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.config.InfConfigMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.config.InfConfigTypeEnum; -import cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config.InfConfigProducer; -import cn.iocoder.yudao.adminserver.modules.infra.service.config.InfConfigService; -import com.google.common.annotations.VisibleForTesting; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; - -import java.util.List; - -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.*; - -/** - * 参数配置 Service 实现类 - */ -@Service -@Slf4j -@Validated -public class InfConfigServiceImpl implements InfConfigService { - - @Resource - private InfConfigMapper configMapper; - - @Resource - private InfConfigProducer configProducer; - - @Override - public Long createConfig(InfConfigCreateReqVO reqVO) { - // 校验正确性 - checkCreateOrUpdate(null, reqVO.getKey()); - // 插入参数配置 - InfConfigDO config = InfConfigConvert.INSTANCE.convert(reqVO); - config.setType(InfConfigTypeEnum.CUSTOM.getType()); - configMapper.insert(config); - // 发送刷新消息 - configProducer.sendConfigRefreshMessage(); - return config.getId(); - } - - @Override - public void updateConfig(InfConfigUpdateReqVO reqVO) { - // 校验正确性 - checkCreateOrUpdate(reqVO.getId(), null); // 不允许更新 key - // 更新参数配置 - InfConfigDO updateObj = InfConfigConvert.INSTANCE.convert(reqVO); - configMapper.updateById(updateObj); - // 发送刷新消息 - configProducer.sendConfigRefreshMessage(); - } - - @Override - public void deleteConfig(Long id) { - // 校验配置存在 - InfConfigDO config = checkConfigExists(id); - // 内置配置,不允许删除 - if (InfConfigTypeEnum.SYSTEM.getType().equals(config.getType())) { - throw ServiceExceptionUtil.exception(CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE); - } - // 删除 - configMapper.deleteById(id); - // 发送刷新消息 - configProducer.sendConfigRefreshMessage(); - } - - @Override - public InfConfigDO getConfig(Long id) { - return configMapper.selectById(id); - } - - @Override - public InfConfigDO getConfigByKey(String key) { - return configMapper.selectByKey(key); - } - - @Override - public PageResult getConfigPage(InfConfigPageReqVO reqVO) { - return configMapper.selectPage(reqVO); - } - - @Override - public List getConfigList(InfConfigExportReqVO reqVO) { - return configMapper.selectList(reqVO); - } - - private void checkCreateOrUpdate(Long id, String key) { - // 校验自己存在 - checkConfigExists(id); - // 校验参数配置 key 的唯一性 - checkConfigKeyUnique(id, key); - } - - @VisibleForTesting - public InfConfigDO checkConfigExists(Long id) { - if (id == null) { - return null; - } - InfConfigDO config = configMapper.selectById(id); - if (config == null) { - throw ServiceExceptionUtil.exception(CONFIG_NOT_EXISTS); - } - return config; - } - - @VisibleForTesting - public void checkConfigKeyUnique(Long id, String key) { - InfConfigDO config = configMapper.selectByKey(key); - if (config == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的参数配置 - if (id == null) { - throw ServiceExceptionUtil.exception(CONFIG_KEY_DUPLICATE); - } - if (!config.getId().equals(id)) { - throw ServiceExceptionUtil.exception(CONFIG_KEY_DUPLICATE); - } - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileService.java deleted file mode 100644 index 1c8311b29c..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileService.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.file; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -/** - * 文件 Service 接口 - * - * @author 芋道源码 - */ -public interface InfFileService { - - /** - * 获得文件分页 - * - * @param pageReqVO 分页查询 - * @return 文件分页 - */ - PageResult getFilePage(InfFilePageReqVO pageReqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/impl/InfFileServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/impl/InfFileServiceImpl.java deleted file mode 100644 index b8967c638e..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/impl/InfFileServiceImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.file.impl; - -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper; -import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService; -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * 文件 Service 实现类 - * - * @author 芋道源码 - */ -@Service -public class InfFileServiceImpl implements InfFileService { - - @Resource - private InfFileMapper fileMapper; - - @Override - public PageResult getFilePage(InfFilePageReqVO pageReqVO) { - return fileMapper.selectPage(pageReqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobLogServiceImpl.java deleted file mode 100644 index e055c61589..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobLogServiceImpl.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job.impl; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job.InfJobLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobLogStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.InfJobLogService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.Date; -import java.util.List; - -/** - * Job 日志 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -@Slf4j -public class InfJobLogServiceImpl implements InfJobLogService { - - @Resource - private InfJobLogMapper jobLogMapper; - - @Override - public Long createJobLog(Long jobId, Date beginTime, String jobHandlerName, String jobHandlerParam, Integer executeIndex) { - InfJobLogDO log = InfJobLogDO.builder().jobId(jobId).handlerName(jobHandlerName).handlerParam(jobHandlerParam).executeIndex(executeIndex) - .beginTime(beginTime).status(InfJobLogStatusEnum.RUNNING.getStatus()).build(); - jobLogMapper.insert(log); - return log.getId(); - } - - @Override - @Async - public void updateJobLogResultAsync(Long logId, Date endTime, Integer duration, boolean success, String result) { - try { - InfJobLogDO updateObj = InfJobLogDO.builder().id(logId).endTime(endTime).duration(duration) - .status(success ? InfJobLogStatusEnum.SUCCESS.getStatus() : InfJobLogStatusEnum.FAILURE.getStatus()).result(result).build(); - jobLogMapper.updateById(updateObj); - } catch (Exception ex) { - log.error("[updateJobLogResultAsync][logId({}) endTime({}) duration({}) success({}) result({})]", - logId, endTime, duration, success, result); - } - } - - @Override - public InfJobLogDO getJobLog(Long id) { - return jobLogMapper.selectById(id); - } - - @Override - public List getJobLogList(Collection ids) { - return jobLogMapper.selectBatchIds(ids); - } - - @Override - public PageResult getJobLogPage(InfJobLogPageReqVO pageReqVO) { - return jobLogMapper.selectPage(pageReqVO); - } - - @Override - public List getJobLogList(InfJobLogExportReqVO exportReqVO) { - return jobLogMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogService.java deleted file mode 100644 index 347372bb4b..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogService.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import java.util.List; - -/** - * API 访问日志 Service 接口 - * - * @author 芋道源码 - */ -public interface InfApiAccessLogService { - - /** - * 获得 API 访问日志分页 - * - * @param pageReqVO 分页查询 - * @return API 访问日志分页 - */ - PageResult getApiAccessLogPage(InfApiAccessLogPageReqVO pageReqVO); - - /** - * 获得 API 访问日志列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return API 访问日志分页 - */ - List getApiAccessLogList(InfApiAccessLogExportReqVO exportReqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java deleted file mode 100644 index 207b3d1527..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiAccessLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.InfApiAccessLogService; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.List; - -/** - * API 访问日志 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class InfApiAccessLogServiceImpl implements InfApiAccessLogService { - - @Resource - private InfApiAccessLogMapper apiAccessLogMapper; - - @Override - public PageResult getApiAccessLogPage(InfApiAccessLogPageReqVO pageReqVO) { - return apiAccessLogMapper.selectPage(pageReqVO); - } - - @Override - public List getApiAccessLogList(InfApiAccessLogExportReqVO exportReqVO) { - return apiAccessLogMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java deleted file mode 100644 index 6918aec067..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl; - -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.InfApiErrorLogService; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.List; - -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * API 错误日志 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { - - @Resource - private InfApiErrorLogMapper apiErrorLogMapper; - - @Override - public PageResult getApiErrorLogPage(InfApiErrorLogPageReqVO pageReqVO) { - return apiErrorLogMapper.selectPage(pageReqVO); - } - - @Override - public List getApiErrorLogList(InfApiErrorLogExportReqVO exportReqVO) { - return apiErrorLogMapper.selectList(exportReqVO); - } - - @Override - public void updateApiErrorLogProcess(Long id, Integer processStatus, Long processUserId) { - InfApiErrorLogDO errorLog = apiErrorLogMapper.selectById(id); - if (errorLog == null) { - throw exception(API_ERROR_LOG_NOT_FOUND); - } - if (!InfApiErrorLogProcessStatusEnum.INIT.getStatus().equals(errorLog.getProcessStatus())) { - throw exception(API_ERROR_LOG_PROCESSED); - } - // 标记处理 - apiErrorLogMapper.updateById(InfApiErrorLogDO.builder().id(id).processStatus(processStatus) - .processUserId(processUserId).processTime(new Date()).build()); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderExtensionMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderExtensionMapper.java deleted file mode 100755 index 47baabb317..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderExtensionMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -/** - * 支付订单 Mapper - * - * @author aquan - */ -@Mapper -public interface PayOrderExtensionMapper extends BaseMapperX { - - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/enums/PayErrorCodeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/enums/PayErrorCodeConstants.java deleted file mode 100644 index df39d9efc2..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/enums/PayErrorCodeConstants.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.enums; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/package-info.java deleted file mode 100644 index 3db5697897..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.job; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/package-info.java deleted file mode 100644 index a113b9beb6..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * pay 包下,我们放支付业务,提供业务的支付能力。 - * 例如说:商户、应用、支付、退款等等 - * - * 缩写:pay - */ -package cn.iocoder.yudao.adminserver.modules.pay; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java deleted file mode 100644 index 6ba21f8c3c..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java +++ /dev/null @@ -1,161 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; -import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import javax.validation.Validator; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_EXIST_SAME_CHANNEL_ERROR; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 支付渠道 Service 实现类 - * - * @author aquan - */ -@Service -@Slf4j -@Validated -public class PayChannelServiceImpl implements PayChannelService { - - @Resource - private PayChannelMapper channelMapper; - - @Resource - private Validator validator; - - @Override - public Long createChannel(PayChannelCreateReqVO reqVO) { - // 断言是否有重复的 - PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); - if (ObjectUtil.isNotNull(channelDO)) { - throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR); - } - - // 新增渠道 - PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); - settingConfigAndCheckParam(channel, reqVO.getConfig()); - channelMapper.insert(channel); - return channel.getId(); - } - - @Override - public void updateChannel(PayChannelUpdateReqVO updateReqVO) { - // 校验存在 - this.validateChannelExists(updateReqVO.getId()); - // 更新 - PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO); - settingConfigAndCheckParam(channel, updateReqVO.getConfig()); - channelMapper.updateById(channel); - } - - @Override - public void deleteChannel(Long id) { - // 校验存在 - this.validateChannelExists(id); - // 删除 - channelMapper.deleteById(id); - } - - private void validateChannelExists(Long id) { - if (channelMapper.selectById(id) == null) { - throw exception(CHANNEL_NOT_EXISTS); - } - } - - @Override - public PayChannelDO getChannel(Long id) { - return channelMapper.selectById(id); - } - - @Override - public List getChannelList(Collection ids) { - return channelMapper.selectBatchIds(ids); - } - - @Override - public PageResult getChannelPage(PayChannelPageReqVO pageReqVO) { - return channelMapper.selectPage(pageReqVO); - } - - @Override - public List getChannelList(PayChannelExportReqVO exportReqVO) { - return channelMapper.selectList(exportReqVO); - } - - /** - * 根据支付应用ID集合获得支付渠道列表 - * - * @param appIds 应用编号集合 - * @return 支付渠道列表 - */ - @Override - public List getChannelListByAppIds(Collection appIds) { - return channelMapper.getChannelListByAppIds(appIds); - } - - - /** - * 根据条件获取通道数量 - * - * @param merchantId 商户编号 - * @param appid 应用编号 - * @param code 通道编码 - * @return 数量 - */ - @Override - public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) { - return this.channelMapper.selectCount(merchantId, appid, code); - } - - /** - * 根据条件获取通道 - * - * @param merchantId 商户编号 - * @param appid 应用编号 - * @param code 通道编码 - * @return 数量 - */ - @Override - public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) { - return this.channelMapper.selectOne(merchantId, appid, code); - } - - /** - * 设置渠道配置以及参数校验 - * - * @param channel 渠道 - * @param configStr 配置 - */ - private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { - // 得到这个渠道是微信的还是支付宝的 - Class payClass = PayChannelEnum.getByCode(channel.getCode()).getConfigClass(); - if (ObjectUtil.isNull(payClass)) { - throw exception(CHANNEL_NOT_EXISTS); - } - PayClientConfig config = JSONUtil.toBean(configStr, payClass); - - // 验证参数 - config.validate(validator); - channel.setConfig(config); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayRefundService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayRefundService.java deleted file mode 100755 index 1412bdefea..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayRefundService.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order; - -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import java.util.List; - -/** - * 退款订单 Service 接口 - * - * @author aquan - */ -public interface PayRefundService { - - /** - * 获得退款订单 - * - * @param id 编号 - * @return 退款订单 - */ - PayRefundDO getRefund(Long id); - - /** - * 获得退款订单分页 - * - * @param pageReqVO 分页查询 - * @return 退款订单分页 - */ - PageResult getRefundPage(PayRefundPageReqVO pageReqVO); - - /** - * 获得退款订单列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 退款订单列表 - */ - List getRefundList(PayRefundExportReqVO exportReqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderServiceImpl.java deleted file mode 100755 index dd6d0a8bd2..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderServiceImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; - -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; - -/** - * 支付订单 Service 实现类 - * - * @author aquan - */ -@Service -@Validated -public class PayOrderServiceImpl implements PayOrderService { - - @Resource - private PayOrderMapper orderMapper; - - @Override - public PayOrderDO getOrder(Long id) { - return orderMapper.selectById(id); - } - - @Override - public PageResult getOrderPage(PayOrderPageReqVO pageReqVO) { - return orderMapper.selectPage(pageReqVO); - } - - @Override - public List getOrderList(PayOrderExportReqVO exportReqVO) { - return orderMapper.selectList(exportReqVO); - } - - /** - * 根据 ID 集合获取只包含商品名称的订单集合 - * - * @param idList 订单 ID 集合 - * @return 只包含商品名称的订单集合 - */ - @Override - public List getOrderSubjectList(Collection idList) { - return orderMapper.findByIdListQueryOrderSubject(idList); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayRefundServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayRefundServiceImpl.java deleted file mode 100755 index 00f42ebcde..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayRefundServiceImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; - -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 退款订单 Service 实现类 - * - * @author aquan - */ -@Service -@Validated -public class PayRefundServiceImpl implements PayRefundService { - - @Resource - private PayRefundMapper refundMapper; - - @Override - public PayRefundDO getRefund(Long id) { - return refundMapper.selectById(id); - } - - @Override - public PageResult getRefundPage(PayRefundPageReqVO pageReqVO) { - return refundMapper.selectPage(pageReqVO); - } - - @Override - public List getRefundList(PayRefundExportReqVO exportReqVO) { - return refundMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostCreateReqVO.java deleted file mode 100644 index 72be88dd55..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostCreateReqVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@ApiModel("岗位创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class SysPostCreateReqVO extends SysPostBaseVO { -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataCreateReqVO.java deleted file mode 100644 index 5c964991ca..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@ApiModel("字典数据创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class SysDictDataCreateReqVO extends SysDictDataBaseVO { - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeCreateReqVO.java deleted file mode 100644 index 15190abfe1..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@ApiModel("错误码创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SysErrorCodeCreateReqVO extends SysErrorCodeBaseVO { - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeCreateReqVO.java deleted file mode 100644 index cf86f2164a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeCreateReqVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@ApiModel("通知公告创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class SysNoticeCreateReqVO extends SysNoticeBaseVO { -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuCreateReqVO.java deleted file mode 100644 index e50c73f2f4..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuCreateReqVO.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; - -import io.swagger.annotations.ApiModel; -import lombok.*; - -@ApiModel("菜单创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class SysMenuCreateReqVO extends SysMenuBaseVO { -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleCreateReqVO.java deleted file mode 100644 index f16c3adf97..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@ApiModel("角色创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class SysRoleCreateReqVO extends SysRoleBaseVO { - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateCreateReqVO.java deleted file mode 100644 index 6d5931565e..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; - -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@ApiModel("短信模板创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SysSmsTemplateCreateReqVO extends SysSmsTemplateBaseVO { - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java deleted file mode 100755 index 4b90bc5c35..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; - -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; -import javax.validation.constraints.*; - -@ApiModel("租户创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SysTenantCreateReqVO extends SysTenantBaseVO { - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java deleted file mode 100644 index 4b47d3c55a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java +++ /dev/null @@ -1,110 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.io.IOException; -import java.util.List; - -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_IS_EMPTY; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Api(tags = "用户个人中心") -@RestController -@RequestMapping("/system/user/profile") -@Validated -@Slf4j -public class SysUserProfileController { - - @Resource - private SysUserService userService; - @Resource - private SysUserCoreService userCoreService; - @Resource - private SysDeptService deptService; - @Resource - private SysPostService postService; - @Resource - private SysPermissionService permissionService; - @Resource - private SysRoleService roleService; - @Resource - private SysSocialCoreService socialService; - - @GetMapping("/get") - @ApiOperation("获得登录用户信息") - public CommonResult profile() { - // 获得用户基本信息 - SysUserDO user = userCoreService.getUser(getLoginUserId()); - SysUserProfileRespVO resp = SysUserConvert.INSTANCE.convert03(user); - // 获得用户角色 - List userRoles = roleService.getRolesFromCache(permissionService.getUserRoleIdListByUserId(user.getId())); - resp.setRoles(SysUserConvert.INSTANCE.convertList(userRoles)); - // 获得部门信息 - if (user.getDeptId() != null) { - SysDeptDO dept = deptService.getDept(user.getDeptId()); - resp.setDept(SysUserConvert.INSTANCE.convert02(dept)); - } - // 获得岗位信息 - if (CollUtil.isNotEmpty(user.getPostIds())) { - List posts = postService.getPosts(user.getPostIds()); - resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts)); - } - // 获得社交用户信息 - List socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN); - resp.setSocialUsers(SysUserConvert.INSTANCE.convertList03(socialUsers)); - return success(resp); - } - - @PutMapping("/update") - @ApiOperation("修改用户个人信息") - public CommonResult updateUserProfile(@Valid @RequestBody SysUserProfileUpdateReqVO reqVO) { - userService.updateUserProfile(getLoginUserId(), reqVO); - return success(true); - } - - @PutMapping("/update-password") - @ApiOperation("修改用户个人密码") - public CommonResult updateUserProfilePassword(@Valid @RequestBody SysUserProfileUpdatePasswordReqVO reqVO) { - userService.updateUserPassword(getLoginUserId(), reqVO); - return success(true); - } - - @PutMapping("/update-avatar") - @ApiOperation("上传用户个人头像") - public CommonResult updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException { - if (file.isEmpty()) { - throw ServiceExceptionUtil.exception(FILE_IS_EMPTY); - } - String avatar = userService.updateUserAvatar(getLoginUserId(), file.getInputStream()); - return success(avatar); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java deleted file mode 100644 index dfe3ac3eab..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.auth; - -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.security.core.LoginUser; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; -import org.slf4j.LoggerFactory; - -import java.util.*; - -@Mapper -public interface SysAuthConvert { - - SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); - - @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略 - LoginUser convert0(SysUserDO bean); - - default LoginUser convert(SysUserDO bean) { - // 目的,为了设置 UserTypeEnum.ADMIN.getValue() - return convert0(bean).setUserType(UserTypeEnum.ADMIN.getValue()); - } - - default SysAuthPermissionInfoRespVO convert(SysUserDO user, List roleList, List menuList) { - return SysAuthPermissionInfoRespVO.builder() - .user(SysAuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) - .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode)) - .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission)) - .build(); - } - - SysAuthMenuRespVO convertTreeNode(SysMenuDO menu); - - /** - * 将菜单列表,构建成菜单树 - * - * @param menuList 菜单列表 - * @return 菜单树 - */ - default List buildMenuTree(List menuList) { - // 排序,保证菜单的有序性 - menuList.sort(Comparator.comparing(SysMenuDO::getSort)); - // 构建菜单树 - // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 - Map treeNodeMap = new LinkedHashMap<>(); - menuList.forEach(menu -> treeNodeMap.put(menu.getId(), SysAuthConvert.INSTANCE.convertTreeNode(menu))); - // 处理父子关系 - treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach(childNode -> { - // 获得父节点 - SysAuthMenuRespVO parentNode = treeNodeMap.get(childNode.getParentId()); - if (parentNode == null) { - LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", - childNode.getId(), childNode.getParentId()); - return; - } - // 将自己添加到父节点中 - if (parentNode.getChildren() == null) { - parentNode.setChildren(new ArrayList<>()); - } - parentNode.getChildren().add(childNode); - }); - // 获得到所有的根节点 - return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysUserSessionConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysUserSessionConvert.java deleted file mode 100644 index 0defeed97a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysUserSessionConvert.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.auth; - -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SysUserSessionConvert { - - SysUserSessionConvert INSTANCE = Mappers.getMapper(SysUserSessionConvert.class); - - SysUserSessionPageItemRespVO convert(SysUserSessionDO session); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/common/SysCaptchaConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/common/SysCaptchaConvert.java deleted file mode 100644 index 0931a54dee..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/common/SysCaptchaConvert.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.common; - -import cn.hutool.captcha.AbstractCaptcha; -import cn.hutool.captcha.ICaptcha; -import cn.iocoder.yudao.adminserver.modules.system.controller.common.vo.SysCaptchaImageRespVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SysCaptchaConvert { - - SysCaptchaConvert INSTANCE = Mappers.getMapper(SysCaptchaConvert.class); - - default SysCaptchaImageRespVO convert(String uuid, AbstractCaptcha captcha) { - return SysCaptchaImageRespVO.builder().uuid(uuid).img(captcha.getImageBase64()).build(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysDeptConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysDeptConvert.java deleted file mode 100644 index 364b034afe..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysDeptConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.dept; - -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysDeptConvert { - - SysDeptConvert INSTANCE = Mappers.getMapper(SysDeptConvert.class); - - List convertList(List list); - - List convertList02(List list); - - SysDeptRespVO convert(SysDeptDO bean); - - SysDeptDO convert(SysDeptCreateReqVO bean); - - SysDeptDO convert(SysDeptUpdateReqVO bean); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysPostConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysPostConvert.java deleted file mode 100644 index 934a31dba1..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dept/SysPostConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.dept; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysPostConvert { - - SysPostConvert INSTANCE = Mappers.getMapper(SysPostConvert.class); - - List convertList02(List list); - - PageResult convertPage(PageResult page); - - SysPostRespVO convert(SysPostDO id); - - SysPostDO convert(SysPostCreateReqVO bean); - - SysPostDO convert(SysPostUpdateReqVO reqVO); - - List convertList03(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictDataConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictDataConvert.java deleted file mode 100644 index e916def4f3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictDataConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.dict; - -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.*; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SysDictDataConvert { - - SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class); - - List convertList(List list); - - SysDictDataRespVO convert(SysDictDataDO bean); - - PageResult convertPage(PageResult page); - - SysDictDataDO convert(SysDictDataUpdateReqVO bean); - - SysDictDataDO convert(SysDictDataCreateReqVO bean); - - List convertList02(List bean); - - DictDataRespDTO convert02(SysDictDataDO bean); - - List convertList03(Collection list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictTypeConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictTypeConvert.java deleted file mode 100644 index e20451c25b..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/dict/SysDictTypeConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.dict; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysDictTypeConvert { - - SysDictTypeConvert INSTANCE = Mappers.getMapper(SysDictTypeConvert.class); - - PageResult convertPage(PageResult bean); - - SysDictTypeRespVO convert(SysDictTypeDO bean); - - SysDictTypeDO convert(SysDictTypeCreateReqVO bean); - - SysDictTypeDO convert(SysDictTypeUpdateReqVO bean); - - List convertList(List list); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/errorcode/SysErrorCodeConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/errorcode/SysErrorCodeConvert.java deleted file mode 100644 index a7b8eade2b..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/errorcode/SysErrorCodeConvert.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.errorcode; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 错误码 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SysErrorCodeConvert { - - SysErrorCodeConvert INSTANCE = Mappers.getMapper(SysErrorCodeConvert.class); - - SysErrorCodeDO convert(SysErrorCodeCreateReqVO bean); - - SysErrorCodeDO convert(SysErrorCodeUpdateReqVO bean); - - SysErrorCodeRespVO convert(SysErrorCodeDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - SysErrorCodeDO convert(ErrorCodeAutoGenerateReqDTO bean); - - List convertList03(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysLoginLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysLoginLogConvert.java deleted file mode 100644 index d6226491c9..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysLoginLogConvert.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.logger; - -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysLoginLogConvert { - - SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class); - - PageResult convertPage(PageResult page); - - List convertList(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysOperateLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysOperateLogConvert.java deleted file mode 100644 index 51e08f1dc5..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/logger/SysOperateLogConvert.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.logger; - -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogRespVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; - -@Mapper -public interface SysOperateLogConvert { - - SysOperateLogConvert INSTANCE = Mappers.getMapper(SysOperateLogConvert.class); - - SysOperateLogDO convert(OperateLogCreateReqDTO bean); - - PageResult convertPage(PageResult page); - - SysOperateLogRespVO convert(SysOperateLogDO bean); - - default List convertList(List list, Map userMap) { - return list.stream().map(operateLog -> { - SysOperateLogExcelVO excelVO = convert02(operateLog); - MapUtils.findAndThen(userMap, operateLog.getId(), user -> excelVO.setUserNickname(user.getNickname())); - excelVO.setSuccessStr(SUCCESS.getCode().equals(operateLog.getResultCode()) ? "成功" : "失败"); - return excelVO; - }).collect(Collectors.toList()); - } - - SysOperateLogExcelVO convert02(SysOperateLogDO bean); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/notice/SysNoticeConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/notice/SysNoticeConvert.java deleted file mode 100644 index ccba20e77c..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/notice/SysNoticeConvert.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.notice; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice.SysNoticeDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SysNoticeConvert { - - SysNoticeConvert INSTANCE = Mappers.getMapper(SysNoticeConvert.class); - - PageResult convertPage(PageResult page); - - SysNoticeRespVO convert(SysNoticeDO bean); - - SysNoticeDO convert(SysNoticeUpdateReqVO bean); - - SysNoticeDO convert(SysNoticeCreateReqVO bean); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/package-info.java deleted file mode 100644 index d4052eb095..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 POJO 类的实体转换 - * - * 目前使用 MapStruct 框架 - */ -package cn.iocoder.yudao.adminserver.modules.system.convert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysMenuConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysMenuConvert.java deleted file mode 100644 index c8ef1496be..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysMenuConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.permission; - -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysMenuConvert { - - SysMenuConvert INSTANCE = Mappers.getMapper(SysMenuConvert.class); - - List convertList(List list); - - SysMenuDO convert(SysMenuCreateReqVO bean); - - SysMenuDO convert(SysMenuUpdateReqVO bean); - - SysMenuRespVO convert(SysMenuDO bean); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysRoleConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysRoleConvert.java deleted file mode 100644 index 59e4d59b40..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/permission/SysRoleConvert.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.permission; - -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysRoleConvert { - - SysRoleConvert INSTANCE = Mappers.getMapper(SysRoleConvert.class); - - SysRoleDO convert(SysRoleUpdateReqVO bean); - - SysRoleRespVO convert(SysRoleDO bean); - - SysRoleDO convert(SysRoleCreateReqVO bean); - - List convertList02(List list); - - List convertList03(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsChannelConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsChannelConvert.java deleted file mode 100644 index cc3b27b640..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsChannelConvert.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 短信渠道 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SysSmsChannelConvert { - - SysSmsChannelConvert INSTANCE = Mappers.getMapper(SysSmsChannelConvert.class); - - SysSmsChannelDO convert(SysSmsChannelCreateReqVO bean); - - SysSmsChannelDO convert(SysSmsChannelUpdateReqVO bean); - - SysSmsChannelRespVO convert(SysSmsChannelDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - List convertList03(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsLogConvert.java deleted file mode 100644 index afcd9443d6..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsLogConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogRespVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 短信日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SysSmsLogConvert { - - SysSmsLogConvert INSTANCE = Mappers.getMapper(SysSmsLogConvert.class); - - SysSmsLogRespVO convert(SysSmsLogDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsTemplateConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsTemplateConvert.java deleted file mode 100644 index 4d1e0dc40d..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/sms/SysSmsTemplateConvert.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysSmsTemplateConvert { - - SysSmsTemplateConvert INSTANCE = Mappers.getMapper(SysSmsTemplateConvert.class); - - SysSmsTemplateDO convert(SysSmsTemplateCreateReqVO bean); - - SysSmsTemplateDO convert(SysSmsTemplateUpdateReqVO bean); - - SysSmsTemplateRespVO convert(SysSmsTemplateDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java deleted file mode 100755 index 3df63f30b5..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.tenant; - -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 租户 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SysTenantConvert { - - SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class); - - SysTenantDO convert(SysTenantCreateReqVO bean); - - SysTenantDO convert(SysTenantUpdateReqVO bean); - - SysTenantRespVO convert(SysTenantDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java deleted file mode 100644 index 7567bba080..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.convert.user; - -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SysUserConvert { - - SysUserConvert INSTANCE = Mappers.getMapper(SysUserConvert.class); - - SysUserPageItemRespVO convert(SysUserDO bean); - - SysUserPageItemRespVO.Dept convert(SysDeptDO bean); - - SysUserDO convert(SysUserCreateReqVO bean); - - SysUserDO convert(SysUserUpdateReqVO bean); - - SysUserExcelVO convert02(SysUserDO bean); - - SysUserDO convert(SysUserImportExcelVO bean); - - SysUserProfileRespVO convert03(SysUserDO bean); - - List convertList(List list); - - SysUserProfileRespVO.Dept convert02(SysDeptDO bean); - - SysUserDO convert(SysUserProfileUpdateReqVO bean); - - SysUserDO convert(SysUserProfileUpdatePasswordReqVO bean); - - List convertList02(List list); - - List convertList03(List list); - - List convertList04(List list); -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/auth/SysUserSessionMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/auth/SysUserSessionMapper.java deleted file mode 100644 index f5ae670b06..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/auth/SysUserSessionMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth; - -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.Date; -import java.util.List; - -@Mapper -public interface SysUserSessionMapper extends BaseMapperX { - - default PageResult selectPage(SysUserSessionPageReqVO reqVO, Collection userIds) { - return selectPage(reqVO, new QueryWrapperX() - .inIfPresent("user_id", userIds) - .likeIfPresent("user_ip", reqVO.getUserIp())); - } - - default List selectListBySessionTimoutLt() { - return selectList(new QueryWrapperX().lt("session_timeout",new Date())); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java deleted file mode 100644 index 831e25ef93..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept; - -import cn.iocoder.yudao.adminserver.modules.tool.enums.SqlConstants; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Date; -import java.util.List; - -@Mapper -public interface SysDeptMapper extends BaseMapperX { - - default List selectList(SysDeptListReqVO reqVO) { - return selectList(new LambdaQueryWrapperX().likeIfPresent(SysDeptDO::getName, reqVO.getName()) - .eqIfPresent(SysDeptDO::getStatus, reqVO.getStatus())); - } - - default SysDeptDO selectByParentIdAndName(Long parentId, String name) { - return selectOne(new LambdaQueryWrapper().eq(SysDeptDO::getParentId, parentId) - .eq(SysDeptDO::getName, name)); - } - - default Integer selectCountByParentId(Long parentId) { - return selectCount(SysDeptDO::getParentId, parentId); - } - - default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { - return selectOne(new LambdaQueryWrapper().select(SysDeptDO::getId) - .gt(SysDeptDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysPostMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysPostMapper.java deleted file mode 100644 index 457b4a990d..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysPostMapper.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SysPostMapper extends BaseMapperX { - - default List selectList(Collection ids, Collection statuses) { - return selectList(new QueryWrapperX().inIfPresent("id", ids) - .inIfPresent("status", statuses)); - } - - default PageResult selectPage(SysPostPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() - .likeIfPresent("code", reqVO.getCode()) - .likeIfPresent("name", reqVO.getName()) - .eqIfPresent("status", reqVO.getStatus())); - } - - default List selectList(SysPostExportReqVO reqVO) { - return selectList(new QueryWrapperX() - .likeIfPresent("code", reqVO.getCode()) - .likeIfPresent("name", reqVO.getName()) - .eqIfPresent("status", reqVO.getStatus())); - } - - default SysPostDO selectByName(String name) { - return selectOne(new QueryWrapper().eq("name", name)); - } - - default SysPostDO selectByCode(String code) { - return selectOne(new QueryWrapper().eq("code", code)); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictDataMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictDataMapper.java deleted file mode 100644 index 5cf5a732fb..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictDataMapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict; - -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.enums.SqlConstants; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.List; - -@Mapper -public interface SysDictDataMapper extends BaseMapperX { - - default SysDictDataDO selectByDictTypeAndValue(String dictType, String value) { - return selectOne(new LambdaQueryWrapper().eq(SysDictDataDO::getDictType, dictType) - .eq(SysDictDataDO::getValue, value)); - } - - default List selectByDictTypeAndValues(String dictType, Collection values) { - return selectList(new LambdaQueryWrapper().eq(SysDictDataDO::getDictType, dictType) - .in(SysDictDataDO::getValue, values)); - } - - default int selectCountByDictType(String dictType) { - return selectCount(SysDictDataDO::getDictType, dictType); - } - - default PageResult selectPage(SysDictDataPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(SysDictDataDO::getLabel, reqVO.getLabel()) - .likeIfPresent(SysDictDataDO::getDictType, reqVO.getDictType()) - .eqIfPresent(SysDictDataDO::getStatus, reqVO.getStatus()) - .orderByAsc(Arrays.asList(SysDictDataDO::getDictType, SysDictDataDO::getSort))); - } - - default List selectList(SysDictDataExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX().likeIfPresent(SysDictDataDO::getLabel, reqVO.getLabel()) - .likeIfPresent(SysDictDataDO::getDictType, reqVO.getDictType()) - .eqIfPresent(SysDictDataDO::getStatus, reqVO.getStatus())); - } - - default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { - return selectOne(new LambdaQueryWrapper().select(SysDictDataDO::getId) - .gt(SysDictDataDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictTypeMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictTypeMapper.java deleted file mode 100644 index 90b125690f..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dict/SysDictTypeMapper.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SysDictTypeMapper extends BaseMapperX { - - default PageResult selectPage(SysDictTypePageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() - .likeIfPresent("name", reqVO.getName()) - .likeIfPresent("`type`", reqVO.getType()) - .eqIfPresent("status", reqVO.getStatus()) - .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())); - } - - default List selectList(SysDictTypeExportReqVO reqVO) { - return selectList(new QueryWrapperX() - .likeIfPresent("name", reqVO.getName()) - .likeIfPresent("`type`", reqVO.getType()) - .eqIfPresent("status", reqVO.getStatus()) - .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())); - } - - default SysDictTypeDO selectByType(String type) { - return selectOne(new QueryWrapperX().eq("`type`", type)); - } - - default SysDictTypeDO selectByName(String name) { - return selectOne(new QueryWrapperX().eq("name", name)); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/notice/SysNoticeMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/notice/SysNoticeMapper.java deleted file mode 100644 index 52a484a1e3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/notice/SysNoticeMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.notice; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice.SysNoticeDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface SysNoticeMapper extends BaseMapperX { - - default PageResult selectPage(SysNoticePageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() - .likeIfPresent("title", reqVO.getTitle()) - .eqIfPresent("status", reqVO.getStatus())); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java deleted file mode 100644 index ea55e2165d..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission; - -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.tool.enums.SqlConstants; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Date; -import java.util.List; - -@Mapper -public interface SysMenuMapper extends BaseMapperX { - - default SysMenuDO selectByParentIdAndName(Long parentId, String name) { - return selectOne(new LambdaQueryWrapper().eq(SysMenuDO::getParentId, parentId) - .eq(SysMenuDO::getName, name)); - } - - default Integer selectCountByParentId(Long parentId) { - return selectCount(SysMenuDO::getParentId, parentId); - } - - default List selectList(SysMenuListReqVO reqVO) { - return selectList(new LambdaQueryWrapperX().likeIfPresent(SysMenuDO::getName, reqVO.getName()) - .eqIfPresent(SysMenuDO::getStatus, reqVO.getStatus())); - } - - default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { - return selectOne(new LambdaQueryWrapper().select(SysMenuDO::getId) - .gt(SysMenuDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMapper.java deleted file mode 100644 index 7d3ab59dec..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRolePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; -import org.springframework.lang.Nullable; - -import java.util.Collection; -import java.util.Date; -import java.util.List; - -@Mapper -public interface SysRoleMapper extends BaseMapperX { - - default PageResult selectPage(SysRolePageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX().likeIfPresent("name", reqVO.getName()) - .likeIfPresent("code", reqVO.getCode()) - .eqIfPresent("status", reqVO.getStatus()) - .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())); - } - - default List listRoles(SysRoleExportReqVO reqVO) { - return selectList(new QueryWrapperX().likeIfPresent("name", reqVO.getName()) - .likeIfPresent("code", reqVO.getCode()) - .eqIfPresent("status", reqVO.getStatus()) - .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())); - } - - default SysRoleDO selectByName(String name) { - return selectOne(new QueryWrapperX().eq("name", name)); - } - - default SysRoleDO selectByCode(String code) { - return selectOne(new QueryWrapperX().eq("code", code)); - } - - default List selectListByStatus(@Nullable Collection statuses) { - return selectList(new QueryWrapperX().in("status", statuses)); - } - - default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { - return selectOne(new QueryWrapper().select("id") - .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null; - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysUserRoleMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysUserRoleMapper.java deleted file mode 100644 index 9a2c990c67..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysUserRoleMapper.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -@Mapper -public interface SysUserRoleMapper extends BaseMapperX { - - default List selectListByUserId(Long userId) { - return selectList(new QueryWrapper().eq("user_id", userId)); - } - - default List selectListByRoleId(Long roleId) { - return selectList(new QueryWrapper().eq("role_id", roleId)); - } - - default List selectListByRoleIds(Collection roleIds) { - return selectList("role_id", roleIds); - } - - default void insertList(Long userId, Collection roleIds) { - List list = roleIds.stream().map(roleId -> { - SysUserRoleDO entity = new SysUserRoleDO(); - entity.setUserId(userId); - entity.setRoleId(roleId); - return entity; - }).collect(Collectors.toList()); - insertBatch(list); - } - - default void deleteListByUserIdAndRoleIdIds(Long userId, Collection roleIds) { - delete(new QueryWrapper().eq("user_id", userId) - .in("role_id", roleIds)); - } - - default void deleteListByUserId(Long userId) { - delete(new QueryWrapper().eq("user_id", userId)); - } - - default void deleteListByRoleId(Long roleId) { - delete(new QueryWrapper().eq("role_id", roleId)); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsTemplateMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsTemplateMapper.java deleted file mode 100644 index 60d99a0a3f..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsTemplateMapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SysSmsTemplateMapper extends BaseMapperX { - - default SysSmsTemplateDO selectByCode(String code) { - return selectOne(SysSmsTemplateDO::getCode, code); - } - - // TODO 这种参数都一样的得想办法封装一下 - default PageResult selectPage(SysSmsTemplatePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(SysSmsTemplateDO::getType, reqVO.getType()) - .eqIfPresent(SysSmsTemplateDO::getStatus, reqVO.getStatus()) - .likeIfPresent(SysSmsTemplateDO::getCode, reqVO.getCode()) - .likeIfPresent(SysSmsTemplateDO::getContent, reqVO.getContent()) - .likeIfPresent(SysSmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId()) - .eqIfPresent(SysSmsTemplateDO::getChannelId, reqVO.getChannelId()) - .betweenIfPresent(SysSmsTemplateDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc(SysSmsTemplateDO::getId)); - } - - default List selectList(SysSmsTemplateExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(SysSmsTemplateDO::getType, reqVO.getType()) - .eqIfPresent(SysSmsTemplateDO::getStatus, reqVO.getStatus()) - .likeIfPresent(SysSmsTemplateDO::getCode, reqVO.getCode()) - .likeIfPresent(SysSmsTemplateDO::getContent, reqVO.getContent()) - .likeIfPresent(SysSmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId()) - .eqIfPresent(SysSmsTemplateDO::getChannelId, reqVO.getChannelId()) - .betweenIfPresent(SysSmsTemplateDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc(SysSmsTemplateDO::getId)); - } - - default Integer selectCountByChannelId(Long channelId) { - return selectCount(SysSmsTemplateDO::getChannelId, channelId); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java deleted file mode 100755 index 999d5c59b5..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant; - -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 租户 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface SysTenantMapper extends BaseMapperX { - - default PageResult selectPage(SysTenantPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(SysTenantDO::getName, reqVO.getName()) - .likeIfPresent(SysTenantDO::getContactName, reqVO.getContactName()) - .likeIfPresent(SysTenantDO::getContactMobile, reqVO.getContactMobile()) - .eqIfPresent(SysTenantDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(SysTenantDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc(SysTenantDO::getId)); - } - - default List selectList(SysTenantExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(SysTenantDO::getName, reqVO.getName()) - .likeIfPresent(SysTenantDO::getContactName, reqVO.getContactName()) - .likeIfPresent(SysTenantDO::getContactMobile, reqVO.getContactMobile()) - .eqIfPresent(SysTenantDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(SysTenantDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc(SysTenantDO::getId)); - } - - default SysTenantDO selectByName(String name) { - return selectOne(SysTenantDO::getName, name); - } -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/user/SysUserMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/user/SysUserMapper.java deleted file mode 100644 index 8739301afe..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/user/SysUserMapper.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user; - -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import jodd.util.StringPool; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -@Mapper -public interface SysUserMapper extends BaseMapperX { - - default SysUserDO selectByUsername(String username) { - return selectOne(new LambdaQueryWrapper().eq(SysUserDO::getUsername, username)); - } - - default SysUserDO selectByEmail(String email) { - return selectOne(new LambdaQueryWrapper().eq(SysUserDO::getEmail, email)); - } - - default SysUserDO selectByMobile(String mobile) { - return selectOne(new LambdaQueryWrapper().eq(SysUserDO::getMobile, mobile)); - } - - default PageResult selectPage(SysUserPageReqVO reqVO, Collection deptIds) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(SysUserDO::getUsername, reqVO.getUsername()) - .likeIfPresent(SysUserDO::getMobile, reqVO.getMobile()) - .eqIfPresent(SysUserDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(SysUserDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()) - .inIfPresent(SysUserDO::getDeptId, deptIds)); - } - - default List selectList(SysUserExportReqVO reqVO, Collection deptIds) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(SysUserDO::getUsername, reqVO.getUsername()) - .likeIfPresent(SysUserDO::getMobile, reqVO.getMobile()) - .eqIfPresent(SysUserDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(SysUserDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()) - .inIfPresent(SysUserDO::getDeptId, deptIds)); - } - - default List selectListByNickname(String nickname) { - return selectList(new LambdaQueryWrapperX().like(SysUserDO::getNickname, nickname)); - } - - default List selectListByUsername(String username) { - return selectList(new LambdaQueryWrapperX().like(SysUserDO::getUsername, username)); - } - - // TODO 芋艿:可废弃该方法 - default List selectListByDepartIdAndPostId(Long departId, Long postId) { - return selectList(new LambdaQueryWrapperX() - .eq(SysUserDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) - .eq(SysUserDO::getDeptId, departId) - // TODO @jason: 封装一个 StringUtils .toString 。如果空的时候,设置为 null。会更简洁 - .likeIfPresent(SysUserDO::getPostIds, Optional.ofNullable(postId).map(t -> String.valueOf(postId)).orElse(StringPool.EMPTY))); - } - - default List selectListByStatus(Integer status) { - return selectList(SysUserDO::getStatus, status); - } - - default List selectListByDeptIds(Collection deptIds) { - return selectList(SysUserDO::getDeptId, deptIds); - } - -} - diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java deleted file mode 100644 index e9d3373b25..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.redis; - -import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; -import cn.iocoder.yudao.framework.security.core.LoginUser; -import me.zhyd.oauth.model.AuthUser; - -import java.time.Duration; - -import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; - -/** - * System Redis Key 枚举类 - * - * @author 芋道源码 - */ -public interface SysRedisKeyConstants { - - RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("验证码的缓存", - "captcha_code:%s", // 参数为 uuid - STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); - - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java deleted file mode 100644 index cc7ae83f8a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysDictTypeConstants.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums; - -/** - * System 字典类型的枚举类 - * - * @author 芋道源码 - */ -public interface SysDictTypeConstants { - - String USER_TYPE = "user_type"; // 用户类型 - String COMMON_STATUS = "sys_common_status"; // 系统状态 - - String USER_SEX = "sys_user_sex"; // 用户性别 - String OPERATE_TYPE = "sys_operate_type"; // 操作类型 - String LOGIN_TYPE = "sys_login_type"; // 登录日志的类型 - String LOGIN_RESULT = "sys_login_result"; // 登录结果 - String CONFIG_TYPE = "sys_config_type"; // 参数配置类型 - String BOOLEAN_STRING = "sys_boolean_string"; // Boolean 是否类型 - - String SMS_CHANNEL_CODE = "sys_sms_channel_code"; // 短信渠道编码 - String SMS_TEMPLATE_TYPE = "sys_sms_template_type"; // 短信模板类型 - String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态 - String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态 - - /** - * 支付-订单-订单状态 - */ - String PAY_ORDER_STATUS = "pay_order_status"; - - /** - * 支付-订单-订单回调商户状态 - */ - String PAY_ORDER_NOTIFY_STATUS = "pay_order_notify_status"; - - /** - * 支付-订单-订单退款状态 - */ - String PAY_ORDER_REFUND_STATUS = "pay_order_refund_status"; - - /** - * 支付-退款订单-退款状态 - */ - String PAY_REFUND_ORDER_STATUS = "pay_refund_order_status"; - - /** - * 支付-退款订单-退款类别 - */ - String PAY_REFUND_ORDER_TYPE = "pay_refund_order_type"; - - String BPM_TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型 - String BPM_TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本 - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/package-info.java deleted file mode 100644 index 039431db36..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 基于 Hutool captcha 库,实现验证码功能 - */ -package cn.iocoder.yudao.adminserver.modules.system.framework.captcha; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/package-info.java deleted file mode 100644 index e700260a86..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 代码生成器 - */ -package cn.iocoder.yudao.adminserver.modules.system.framework.codegen; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java deleted file mode 100644 index cdd6173e2f..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * system 模块的数据权限配置 - */ -package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/package-info.java deleted file mode 100644 index b745ae838a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 属于 system 模块的 framework 封装 - * - * @author 芋道源码 - */ -package cn.iocoder.yudao.adminserver.modules.system.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/package-info.java deleted file mode 100644 index b5c66a51bd..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.job; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java deleted file mode 100644 index 81bed50839..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dept/SysDeptRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.dept; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysDeptRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysDeptRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysDeptService deptService; - - @Override - public void onMessage(SysDeptRefreshMessage message) { - log.info("[onMessage][收到 Dept 刷新消息]"); - deptService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java deleted file mode 100644 index 33f00e077e..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/dict/SysDictDataRefreshConsumer.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.dict; - -import cn.iocoder.yudao.coreservice.modules.system.service.dict.SysDictDataCoreService; -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysDictDataRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysDictDataRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysDictDataCoreService dictDataCoreService; - - @Override - public void onMessage(SysDictDataRefreshMessage message) { - log.info("[onMessage][收到 DictData 刷新消息]"); - dictDataCoreService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/mail/SysMailSendConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/mail/SysMailSendConsumer.java deleted file mode 100644 index ff3b017a98..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/mail/SysMailSendConsumer.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.mail; - -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.mail.SysMailSendMessage; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class SysMailSendConsumer extends AbstractStreamMessageListener { - - @Override - public void onMessage(SysMailSendMessage message) { - log.info("[onMessage][消息内容({})]", message); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java deleted file mode 100644 index 9048e3ccb2..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysMenuRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.permission; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysMenuRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysMenuRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysMenuService menuService; - - @Override - public void onMessage(SysMenuRefreshMessage message) { - log.info("[onMessage][收到 Menu 刷新消息]"); - menuService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java deleted file mode 100644 index 5cdaeef00e..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleMenuRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.permission; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysRoleMenuRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysRoleMenuRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysPermissionService permissionService; - - @Override - public void onMessage(SysRoleMenuRefreshMessage message) { - log.info("[onMessage][收到 Role 与 Menu 的关联刷新消息]"); - permissionService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java deleted file mode 100644 index a2f4cc5284..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/permission/SysRoleRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.permission; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysRoleRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysRoleRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysRoleService roleService; - - @Override - public void onMessage(SysRoleRefreshMessage message) { - log.info("[onMessage][收到 Role 刷新消息]"); - roleService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java deleted file mode 100644 index 540ff17e7a..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsChannelRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.sms; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsChannelService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysSmsChannelRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysSmsChannelRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysSmsChannelService smsChannelService; - - @Override - public void onMessage(SysSmsChannelRefreshMessage message) { - log.info("[onMessage][收到 SmsChannel 刷新消息]"); - smsChannelService.initSmsClients(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsSendConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsSendConsumer.java deleted file mode 100644 index b8ad6ad309..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsSendConsumer.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.sms; - -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; -import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysSmsSendMessage} 的消费者 - * - * @author zzf - * @date 2021/3/9 16:35 - */ -@Component -@Slf4j -public class SysSmsSendConsumer extends AbstractStreamMessageListener { - - @Resource - private SysSmsCoreService smsCoreService; - - @Override - public void onMessage(SysSmsSendMessage message) { - log.info("[onMessage][消息内容({})]", message); - smsCoreService.doSendSms(message); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java deleted file mode 100644 index 305672bc7e..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/consumer/sms/SysSmsTemplateRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.sms; - -import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsTemplateCoreService; -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link SysSmsTemplateRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class SysSmsTemplateRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private SysSmsTemplateCoreService smsTemplateCoreService; - - @Override - public void onMessage(SysSmsTemplateRefreshMessage message) { - log.info("[onMessage][收到 SmsTemplate 刷新消息]"); - smsTemplateCoreService.initLocalCache(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java deleted file mode 100644 index acc4fee7a9..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms; - -import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage; -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * Sms 短信相关消息的 Producer - * - * @author zzf - * @date 2021/3/9 16:35 - */ -@Slf4j -@Component -public class SysSmsProducer { - - @Resource - private RedisMQTemplate redisMQTemplate; - - /** - * 发送 {@link SysSmsChannelRefreshMessage} 消息 - */ - public void sendSmsChannelRefreshMessage() { - SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage(); - redisMQTemplate.send(message); - } - - /** - * 发送 {@link SysSmsTemplateRefreshMessage} 消息 - */ - public void sendSmsTemplateRefreshMessage() { - SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage(); - redisMQTemplate.send(message); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/package-info.java deleted file mode 100644 index f043c0f2af..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * system 包下,我们放通用业务,支撑上层的核心业务。 - * 例如说:用户、部门、权限、数据字典等等 - * - * 缩写:sys - */ -package cn.iocoder.yudao.adminserver.modules.system; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java deleted file mode 100644 index ebfa6606d2..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth; - -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -/** - * 在线用户 Session Service 接口 - * - * @author 芋道源码 - */ -public interface SysUserSessionService { - - /** - * 获得在线用户分页列表 - * - * @param reqVO 分页条件 - * @return 份额与列表 - */ - PageResult getUserSessionPage(SysUserSessionPageReqVO reqVO); - - /** - * 移除超时的在线用户 - * - * @return {@link Long } 移出的超时用户数量 - **/ - long clearSessionTimeout(); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java deleted file mode 100644 index 6e2623b286..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import com.google.common.collect.Lists; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; - -/** - * 在线用户 Session Service 实现类 - * - * @author 芋道源码 - */ -@Slf4j -@Service -public class SysUserSessionServiceImpl implements SysUserSessionService { - - @Resource - private SysUserSessionMapper userSessionMapper; - @Resource - private SysUserService userService; - @Resource - private SysLoginLogCoreService loginLogCoreService; - - @Resource - private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO; - - @Override - public PageResult getUserSessionPage(SysUserSessionPageReqVO reqVO) { - // 处理基于用户昵称的查询 - Collection userIds = null; - if (StrUtil.isNotEmpty(reqVO.getUsername())) { - userIds = convertSet(userService.getUsersByUsername(reqVO.getUsername()), SysUserDO::getId); - if (CollUtil.isEmpty(userIds)) { - return PageResult.empty(); - } - } - return userSessionMapper.selectPage(reqVO, userIds); - } - - // TODO @芋艿:优化下该方法 - @Override - public long clearSessionTimeout() { - // 获取db里已经超时的用户列表 - List sessionTimeoutDOS = userSessionMapper.selectListBySessionTimoutLt(); - Map timeoutSessionDOMap = sessionTimeoutDOS - .stream() - .filter(sessionDO -> loginUserCoreRedisDAO.get(sessionDO.getId()) == null) - .collect(Collectors.toMap(SysUserSessionDO::getId, o -> o)); - // 确认已经超时,按批次移出在线用户列表 - if (CollUtil.isNotEmpty(timeoutSessionDOMap)) { - Lists.partition(new ArrayList<>(timeoutSessionDOMap.keySet()), 100) - .forEach(userSessionMapper::deleteBatchIds); - // 记录用户超时退出日志 - createTimeoutLogoutLog(timeoutSessionDOMap.values()); - } - return timeoutSessionDOMap.size(); - } - - private void createTimeoutLogoutLog(Collection timeoutSessionDOS) { - for (SysUserSessionDO timeoutSessionDO : timeoutSessionDOS) { - SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); - reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_TIMEOUT.getType()); - reqDTO.setTraceId(TracerUtils.getTraceId()); - reqDTO.setUserId(timeoutSessionDO.getUserId()); - reqDTO.setUserType(timeoutSessionDO.getUserType()); - reqDTO.setUsername(timeoutSessionDO.getUsername()); - reqDTO.setUserAgent(timeoutSessionDO.getUserAgent()); - reqDTO.setUserIp(timeoutSessionDO.getUserIp()); - reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult()); - loginLogCoreService.createLoginLog(reqDTO); - } - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictDataServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictDataServiceImpl.java deleted file mode 100644 index 60fb103328..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictDataServiceImpl.java +++ /dev/null @@ -1,203 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictDataConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictDataMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict.SysDictDataProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictTypeService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import com.google.common.annotations.VisibleForTesting; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.*; - -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 字典数据 Service 实现类 - * - * @author ruoyi - */ -@Service -@Slf4j -public class SysDictDataServiceImpl implements SysDictDataService { - - /** - * 排序 dictType > sort - */ - private static final Comparator COMPARATOR_TYPE_AND_SORT = Comparator - .comparing(SysDictDataDO::getDictType) - .thenComparingInt(SysDictDataDO::getSort); - - @Resource - private SysDictTypeService dictTypeService; - - @Resource - private SysDictDataMapper dictDataMapper; - - @Resource - private SysDictDataProducer dictDataProducer; - - /** - * 如果字典数据发生变化,从数据库中获取最新的全量字典数据。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前字典数据的最大更新时间 - * @return 字典数据列表 - */ - private List loadDictDataIfUpdate(Date maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadDictDataIfUpdate][首次加载全量字典数据]"); - } else { // 判断数据库中是否有更新的字典数据 - if (!dictDataMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) { - return null; - } - log.info("[loadDictDataIfUpdate][增量加载全量字典数据]"); - } - // 第二步,如果有更新,则从数据库加载所有字典数据 - return dictDataMapper.selectList(); - } - - @Override - public List getDictDatas() { - List list = dictDataMapper.selectList(); - list.sort(COMPARATOR_TYPE_AND_SORT); - return list; - } - - @Override - public PageResult getDictDataPage(SysDictDataPageReqVO reqVO) { - return dictDataMapper.selectPage(reqVO); - } - - @Override - public List getDictDatas(SysDictDataExportReqVO reqVO) { - List list = dictDataMapper.selectList(reqVO); - list.sort(COMPARATOR_TYPE_AND_SORT); - return list; - } - - @Override - public SysDictDataDO getDictData(Long id) { - return dictDataMapper.selectById(id); - } - - @Override - public Long createDictData(SysDictDataCreateReqVO reqVO) { - // 校验正确性 - this.checkCreateOrUpdate(null, reqVO.getValue(), reqVO.getDictType()); - // 插入字典类型 - SysDictDataDO dictData = SysDictDataConvert.INSTANCE.convert(reqVO); - dictDataMapper.insert(dictData); - // 发送刷新消息 - dictDataProducer.sendDictDataRefreshMessage(); - return dictData.getId(); - } - - @Override - public void updateDictData(SysDictDataUpdateReqVO reqVO) { - // 校验正确性 - this.checkCreateOrUpdate(reqVO.getId(), reqVO.getValue(), reqVO.getDictType()); - // 更新字典类型 - SysDictDataDO updateObj = SysDictDataConvert.INSTANCE.convert(reqVO); - dictDataMapper.updateById(updateObj); - // 发送刷新消息 - dictDataProducer.sendDictDataRefreshMessage(); - } - - @Override - public void deleteDictData(Long id) { - // 校验是否存在 - this.checkDictDataExists(id); - // 删除字典数据 - dictDataMapper.deleteById(id); - // 发送刷新消息 - dictDataProducer.sendDictDataRefreshMessage(); - } - - @Override - public int countByDictType(String dictType) { - return dictDataMapper.selectCountByDictType(dictType); - } - - @Override - public void validDictDatas(String dictType, Collection values) { - if (CollUtil.isEmpty(values)) { - return; - } - // 获得字典数据信息 - List dictDatas = dictDataMapper.selectByDictTypeAndValues(dictType, values); - Map dictDataMap = CollectionUtils.convertMap(dictDatas, SysDictDataDO::getValue); - // 校验 - values.forEach(value -> { - SysDictDataDO dictData = dictDataMap.get(value); - if (dictData == null) { - throw exception(DICT_DATA_NOT_EXISTS); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(dictData.getStatus())) { - throw exception(DICT_DATA_NOT_ENABLE, dictData.getLabel()); - } - }); - } - - private void checkCreateOrUpdate(Long id, String value, String dictType) { - // 校验自己存在 - checkDictDataExists(id); - // 校验字典类型有效 - checkDictTypeValid(dictType); - // 校验字典数据的值的唯一性 - checkDictDataValueUnique(id, dictType, value); - } - - @VisibleForTesting - public void checkDictDataValueUnique(Long id, String dictType, String value) { - SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndValue(dictType, value); - if (dictData == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的字典数据 - if (id == null) { - throw exception(DICT_DATA_VALUE_DUPLICATE); - } - if (!dictData.getId().equals(id)) { - throw exception(DICT_DATA_VALUE_DUPLICATE); - } - } - - @VisibleForTesting - public void checkDictDataExists(Long id) { - if (id == null) { - return; - } - SysDictDataDO dictData = dictDataMapper.selectById(id); - if (dictData == null) { - throw exception(DICT_DATA_NOT_EXISTS); - } - } - - @VisibleForTesting - public void checkDictTypeValid(String type) { - SysDictTypeDO dictType = dictTypeService.getDictType(type); - if (dictType == null) { - throw exception(DICT_TYPE_NOT_EXISTS); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) { - throw exception(DICT_TYPE_NOT_ENABLE); - } - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeService.java deleted file mode 100644 index 4bcfb97762..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeService.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.errorcode; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; - -import javax.validation.Valid; -import java.util.List; - -/** - * 错误码 Service 接口 - * - * @author 芋道源码 - */ -public interface SysErrorCodeService extends ErrorCodeFrameworkService { - - /** - * 创建错误码 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createErrorCode(@Valid SysErrorCodeCreateReqVO createReqVO); - - /** - * 更新错误码 - * - * @param updateReqVO 更新信息 - */ - void updateErrorCode(@Valid SysErrorCodeUpdateReqVO updateReqVO); - - /** - * 删除错误码 - * - * @param id 编号 - */ - void deleteErrorCode(Long id); - - /** - * 获得错误码 - * - * @param id 编号 - * @return 错误码 - */ - SysErrorCodeDO getErrorCode(Long id); - - /** - * 获得错误码分页 - * - * @param pageReqVO 分页查询 - * @return 错误码分页 - */ - PageResult getErrorCodePage(SysErrorCodePageReqVO pageReqVO); - - /** - * 获得错误码列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 错误码列表 - */ - List getErrorCodeList(SysErrorCodeExportReqVO exportReqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java deleted file mode 100644 index b7b30e1984..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogService.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger; - -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import java.util.List; - -/** - * 登录日志 Service 接口 - */ -public interface SysLoginLogService { - - /** - * 获得登录日志分页 - * - * @param reqVO 分页条件 - * @return 登录日志分页 - */ - PageResult getLoginLogPage(SysLoginLogPageReqVO reqVO); - - /** - * 获得登录日志列表 - * - * @param reqVO 列表条件 - * @return 登录日志列表 - */ - List getLoginLogList(SysLoginLogExportReqVO reqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogService.java deleted file mode 100644 index cf3379b398..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogService.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; - -import java.util.List; - -/** - * 操作日志 Service 接口 - */ -public interface SysOperateLogService extends OperateLogFrameworkService { - - /** - * 获得操作日志分页列表 - * - * @param reqVO 分页条件 - * @return 操作日志分页列表 - */ - PageResult getOperateLogPage(SysOperateLogPageReqVO reqVO); - - /** - * 获得操作日志列表 - * - * @param reqVO 列表条件 - * @return 日志列表 - */ - List getOperateLogs(SysOperateLogExportReqVO reqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java deleted file mode 100644 index fc651469d4..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysLoginLogServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl; - -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 登录日志 Service 实现 - */ -@Service -public class SysLoginLogServiceImpl implements SysLoginLogService { - - @Resource - private SysLoginLogMapper loginLogMapper; - - @Override - public PageResult getLoginLogPage(SysLoginLogPageReqVO reqVO) { - return loginLogMapper.selectPage(reqVO); - } - - @Override - public List getLoginLogList(SysLoginLogExportReqVO reqVO) { - return loginLogMapper.selectList(reqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/impl/SysNoticeServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/impl/SysNoticeServiceImpl.java deleted file mode 100644 index 2cb770b06c..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/impl/SysNoticeServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.notice.impl; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.notice.SysNoticeConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.notice.SysNoticeMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice.SysNoticeDO; -import cn.iocoder.yudao.adminserver.modules.system.service.notice.SysNoticeService; -import com.google.common.annotations.VisibleForTesting; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.NOTICE_NOT_FOUND; - -/** - * 通知公告 Service 实现类 - * - * @author 芋道源码 - */ -@Service -public class SysNoticeServiceImpl implements SysNoticeService { - - @Resource - private SysNoticeMapper noticeMapper; - - @Override - public Long createNotice(SysNoticeCreateReqVO reqVO) { - SysNoticeDO notice = SysNoticeConvert.INSTANCE.convert(reqVO); - noticeMapper.insert(notice); - return notice.getId(); - } - - @Override - public void updateNotice(SysNoticeUpdateReqVO reqVO) { - // 校验是否存在 - this.checkNoticeExists(reqVO.getId()); - // 更新通知公告 - SysNoticeDO updateObj = SysNoticeConvert.INSTANCE.convert(reqVO); - noticeMapper.updateById(updateObj); - } - - @Override - public void deleteNotice(Long id) { - // 校验是否存在 - this.checkNoticeExists(id); - // 删除通知公告 - noticeMapper.deleteById(id); - } - - @Override - public PageResult pageNotices(SysNoticePageReqVO reqVO) { - return noticeMapper.selectPage(reqVO); - } - - @Override - public SysNoticeDO getNotice(Long id) { - return noticeMapper.selectById(id); - } - - @VisibleForTesting - public void checkNoticeExists(Long id) { - if (id == null) { - return; - } - SysNoticeDO notice = noticeMapper.selectById(id); - if (notice == null) { - throw ServiceExceptionUtil.exception(NOTICE_NOT_FOUND); - } - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogService.java deleted file mode 100644 index 75bc3a6cc3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogService.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import java.util.List; - -/** - * 短信日志 Service 接口 - * - * @author zzf - * @date 13:48 2021/3/2 - */ -public interface SysSmsLogService { - - /** - * 获得短信日志分页 - * - * @param pageReqVO 分页查询 - * @return 短信日志分页 - */ - PageResult getSmsLogPage(SysSmsLogPageReqVO pageReqVO); - - /** - * 获得短信日志列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 短信日志列表 - */ - List getSmsLogList(SysSmsLogExportReqVO exportReqVO); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateService.java deleted file mode 100644 index 723eef1ffc..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateService.java +++ /dev/null @@ -1,92 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import javax.validation.Valid; -import java.util.Collection; -import java.util.List; - -/** - * 短信模板 Service 接口 - * - * @author zzf - * @date 2021/1/25 9:24 - */ -public interface SysSmsTemplateService { - - /** - * 获得短信模板 - * - * @param code 模板编码 - * @return 短信模板 - */ - SysSmsTemplateDO getSmsTemplateByCode(String code); - - /** - * 创建短信模板 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createSmsTemplate(@Valid SysSmsTemplateCreateReqVO createReqVO); - - /** - * 更新短信模板 - * - * @param updateReqVO 更新信息 - */ - void updateSmsTemplate(@Valid SysSmsTemplateUpdateReqVO updateReqVO); - - /** - * 删除短信模板 - * - * @param id 编号 - */ - void deleteSmsTemplate(Long id); - - /** - * 获得短信模板 - * - * @param id 编号 - * @return 短信模板 - */ - SysSmsTemplateDO getSmsTemplate(Long id); - - /** - * 获得短信模板列表 - * - * @param ids 编号 - * @return 短信模板列表 - */ - List getSmsTemplateList(Collection ids); - - /** - * 获得短信模板分页 - * - * @param pageReqVO 分页查询 - * @return 短信模板分页 - */ - PageResult getSmsTemplatePage(SysSmsTemplatePageReqVO pageReqVO); - - /** - * 获得短信模板列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 短信模板分页 - */ - List getSmsTemplateList(SysSmsTemplateExportReqVO exportReqVO); - - /** - * 获得指定短信渠道下的短信模板数量 - * - * @param channelId 短信渠道编号 - * @return 数量 - */ - Integer countByChannelId(Long channelId); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsLogServiceImpl.java deleted file mode 100644 index 866e607290..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsLogServiceImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms.impl; - -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsLogService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 短信日志 Service 实现类 - * - * @author zzf - * @date 2021/1/25 9:25 - */ -@Slf4j -@Service -public class SysSmsLogServiceImpl implements SysSmsLogService { - - @Resource - private SysSmsLogMapper smsLogMapper; - - @Override - public PageResult getSmsLogPage(SysSmsLogPageReqVO pageReqVO) { - return smsLogMapper.selectPage(pageReqVO); - } - - @Override - public List getSmsLogList(SysSmsLogExportReqVO exportReqVO) { - return smsLogMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsTemplateServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsTemplateServiceImpl.java deleted file mode 100644 index d8c5b99130..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsTemplateServiceImpl.java +++ /dev/null @@ -1,196 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms.impl; - -import cn.hutool.core.util.ReUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.sms.SysSmsTemplateConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsTemplateMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsChannelService; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsTemplateService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import com.google.common.annotations.VisibleForTesting; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.util.Assert; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.regex.Pattern; - -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 短信模板 Service 实现类 - * - * @author zzf - * @date 2021/1/25 9:25 - */ -@Service -@Slf4j -public class SysSmsTemplateServiceImpl implements SysSmsTemplateService { - - /** - * 正则表达式,匹配 {} 中的变量 - */ - private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); - - @Resource - private SysSmsTemplateMapper smsTemplateMapper; - - @Resource - private SysSmsChannelService smsChannelService; - - @Resource - private SmsClientFactory smsClientFactory; - - @Resource - private SysSmsProducer smsProducer; - - @Override - public SysSmsTemplateDO getSmsTemplateByCode(String code) { - return smsTemplateMapper.selectByCode(code); - } - - @VisibleForTesting - public List parseTemplateContentParams(String content) { - return ReUtil.findAllGroup1(PATTERN_PARAMS, content); - } - - @Override - public Long createSmsTemplate(SysSmsTemplateCreateReqVO createReqVO) { - // 校验短信渠道 - SysSmsChannelDO channelDO = checkSmsChannel(createReqVO.getChannelId()); - // 校验短信编码是否重复 - checkSmsTemplateCodeDuplicate(null, createReqVO.getCode()); - // 校验短信模板 - checkApiTemplate(createReqVO.getChannelId(), createReqVO.getApiTemplateId()); - - // 插入 - SysSmsTemplateDO template = SysSmsTemplateConvert.INSTANCE.convert(createReqVO); - template.setParams(parseTemplateContentParams(template.getContent())); - template.setChannelCode(channelDO.getCode()); - smsTemplateMapper.insert(template); - // 发送刷新消息 - smsProducer.sendSmsTemplateRefreshMessage(); - // 返回 - return template.getId(); - } - - @Override - public void updateSmsTemplate(SysSmsTemplateUpdateReqVO updateReqVO) { - // 校验存在 - this.validateSmsTemplateExists(updateReqVO.getId()); - // 校验短信渠道 - SysSmsChannelDO channelDO = checkSmsChannel(updateReqVO.getChannelId()); - // 校验短信编码是否重复 - checkSmsTemplateCodeDuplicate(updateReqVO.getId(), updateReqVO.getCode()); - // 校验短信模板 - checkApiTemplate(updateReqVO.getChannelId(), updateReqVO.getApiTemplateId()); - - // 更新 - SysSmsTemplateDO updateObj = SysSmsTemplateConvert.INSTANCE.convert(updateReqVO); - updateObj.setParams(parseTemplateContentParams(updateObj.getContent())); - updateObj.setChannelCode(channelDO.getCode()); - smsTemplateMapper.updateById(updateObj); - // 发送刷新消息 - smsProducer.sendSmsTemplateRefreshMessage(); - } - - @Override - public void deleteSmsTemplate(Long id) { - // 校验存在 - this.validateSmsTemplateExists(id); - // 更新 - smsTemplateMapper.deleteById(id); - // 发送刷新消息 - smsProducer.sendSmsTemplateRefreshMessage(); - } - - private void validateSmsTemplateExists(Long id) { - if (smsTemplateMapper.selectById(id) == null) { - throw exception(SMS_TEMPLATE_NOT_EXISTS); - } - } - - @Override - public SysSmsTemplateDO getSmsTemplate(Long id) { - return smsTemplateMapper.selectById(id); - } - - @Override - public List getSmsTemplateList(Collection ids) { - return smsTemplateMapper.selectBatchIds(ids); - } - - @Override - public PageResult getSmsTemplatePage(SysSmsTemplatePageReqVO pageReqVO) { - return smsTemplateMapper.selectPage(pageReqVO); - } - - @Override - public List getSmsTemplateList(SysSmsTemplateExportReqVO exportReqVO) { - return smsTemplateMapper.selectList(exportReqVO); - } - - @Override - public Integer countByChannelId(Long channelId) { - return smsTemplateMapper.selectCountByChannelId(channelId); - } - - @VisibleForTesting - public SysSmsChannelDO checkSmsChannel(Long channelId) { - SysSmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId); - if (channelDO == null) { - throw exception(SMS_CHANNEL_NOT_EXISTS); - } - if (!Objects.equals(channelDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { - throw exception(SMS_CHANNEL_DISABLE); - } - return channelDO; - } - - @VisibleForTesting - public void checkSmsTemplateCodeDuplicate(Long id, String code) { - SysSmsTemplateDO template = smsTemplateMapper.selectByCode(code); - if (template == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 - if (id == null) { - throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code); - } - if (!template.getId().equals(id)) { - throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code); - } - } - - /** - * 校验 API 短信平台的模板是否有效 - * - * @param channelId 渠道编号 - * @param apiTemplateId API 模板编号 - */ - @VisibleForTesting - public void checkApiTemplate(Long channelId, String apiTemplateId) { - // 获得短信模板 - SmsClient smsClient = smsClientFactory.getSmsClient(channelId); - Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); - SmsCommonResult templateResult = smsClient.getSmsTemplate(apiTemplateId); - // 校验短信模板是否正确 - templateResult.checkError(); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java deleted file mode 100755 index 80701affb3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl; - -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 租户 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class SysTenantServiceImpl implements SysTenantService { - - @Resource - private SysTenantMapper tenantMapper; - - @Override - public Long createTenant(SysTenantCreateReqVO createReqVO) { - // 插入 - SysTenantDO tenant = SysTenantConvert.INSTANCE.convert(createReqVO); - tenantMapper.insert(tenant); - // 返回 - return tenant.getId(); - } - - @Override - public void updateTenant(SysTenantUpdateReqVO updateReqVO) { - // 校验存在 - this.validateTenantExists(updateReqVO.getId()); - // 更新 - SysTenantDO updateObj = SysTenantConvert.INSTANCE.convert(updateReqVO); - tenantMapper.updateById(updateObj); - } - - @Override - public void deleteTenant(Long id) { - // 校验存在 - this.validateTenantExists(id); - // 删除 - tenantMapper.deleteById(id); - } - - private void validateTenantExists(Long id) { - if (tenantMapper.selectById(id) == null) { - throw exception(TENANT_NOT_EXISTS); - } - } - - @Override - public SysTenantDO getTenant(Long id) { - return tenantMapper.selectById(id); - } - - @Override - public List getTenantList(Collection ids) { - return tenantMapper.selectBatchIds(ids); - } - - @Override - public PageResult getTenantPage(SysTenantPageReqVO pageReqVO) { - return tenantMapper.selectPage(pageReqVO); - } - - @Override - public List getTenantList(SysTenantExportReqVO exportReqVO) { - return tenantMapper.selectList(exportReqVO); - } - - @Override - public SysTenantDO getTenantByName(String name) { - return tenantMapper.selectByName(name); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenDetailRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenDetailRespVO.java deleted file mode 100644 index 4a1b10c517..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenDetailRespVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo; - -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.column.ToolCodegenColumnRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTableRespVO; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.util.List; - -@ApiModel("代码生成表和字段的明细 Response VO") -@Data -public class ToolCodegenDetailRespVO { - - @ApiModelProperty("表定义") - private ToolCodegenTableRespVO table; - - @ApiModelProperty("字段定义") - private List columns; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnRespVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnRespVO.java deleted file mode 100644 index c7d556427d..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnRespVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.column; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.util.Date; - -@ApiModel("代码生成字段定义 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ToolCodegenColumnRespVO extends ToolCodegenColumnBaseVO { - - @ApiModelProperty(value = "编号", required = true, example = "1") - private Long id; - - @ApiModelProperty(value = "创建时间", required = true) - private Date createTime; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.http b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.http deleted file mode 100644 index b10a3d293b..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.http +++ /dev/null @@ -1,7 +0,0 @@ -### 请求 /tool/test-demo/get 接口 => 成功 -GET {{baseUrl}}/tool/test-demo/get?id=1 -Authorization: Bearer {{token}} - -### 请求 /tool/test-demo/list 接口 => 成功 -GET {{baseUrl}}/tool/test-demo/list?ids=1 -Authorization: Bearer {{token}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.java deleted file mode 100644 index 2249af538c..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/ToolTestDemoController.java +++ /dev/null @@ -1,108 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test; - -import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.tracer.core.annotation.BizTrace; -import cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo.*; -import cn.iocoder.yudao.adminserver.modules.tool.convert.test.ToolTestDemoConvert; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test.ToolTestDemoDO; -import cn.iocoder.yudao.adminserver.modules.tool.service.test.ToolTestDemoService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Api(tags = "测试示例") -@RestController -@RequestMapping("/tool/test-demo") -@Validated -public class ToolTestDemoController { - - @Resource - private ToolTestDemoService testDemoService; - - @PostMapping("/create") - @ApiOperation("创建测试示例") - @PreAuthorize("@ss.hasPermission('tool:test-demo:create')") - public CommonResult createTestDemo(@Valid @RequestBody ToolTestDemoCreateReqVO createReqVO) { - return success(testDemoService.createTestDemo(createReqVO)); - } - - @PutMapping("/update") - @ApiOperation("更新测试示例") - @PreAuthorize("@ss.hasPermission('tool:test-demo:update')") - public CommonResult updateTestDemo(@Valid @RequestBody ToolTestDemoUpdateReqVO updateReqVO) { - testDemoService.updateTestDemo(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @ApiOperation("删除测试示例") - @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) - @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')") - public CommonResult deleteTestDemo(@RequestParam("id") Long id) { - testDemoService.deleteTestDemo(id); - return success(true); - } - - @GetMapping("/get") - @ApiOperation("获得测试示例") - @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) - @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") -// @Lock4j // 分布式锁 - public CommonResult getTestDemo(@RequestParam("id") Long id) { - if (true) { // 测试分布式锁 - ThreadUtil.sleep(5, TimeUnit.SECONDS); - } - ToolTestDemoDO testDemo = testDemoService.getTestDemo(id); - return success(ToolTestDemoConvert.INSTANCE.convert(testDemo)); - } - - @GetMapping("/list") - @ApiOperation("获得测试示例列表") - @ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class) - @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") -// @RateLimiter(name = "backendA") - @BizTrace(id = "#ids", type = "'user'") - public CommonResult> getTestDemoList(@RequestParam("ids") Collection ids) { - List list = testDemoService.getTestDemoList(ids); - return success(ToolTestDemoConvert.INSTANCE.convertList(list)); - } - - @GetMapping("/page") - @ApiOperation("获得测试示例分页") - @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") - public CommonResult> getTestDemoPage(@Valid ToolTestDemoPageReqVO pageVO) { - PageResult pageResult = testDemoService.getTestDemoPage(pageVO); - return success(ToolTestDemoConvert.INSTANCE.convertPage(pageResult)); - } - - @GetMapping("/export-excel") - @ApiOperation("导出测试示例 Excel") - @PreAuthorize("@ss.hasPermission('tool:test-demo:export')") - @OperateLog(type = EXPORT) - public void exportTestDemoExcel(@Valid ToolTestDemoExportReqVO exportReqVO, - HttpServletResponse response) throws IOException { - List list = testDemoService.getTestDemoList(exportReqVO); - // 导出 Excel - List datas = ToolTestDemoConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "测试示例.xls", "数据", ToolTestDemoExcelVO.class, datas); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoBaseVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoBaseVO.java deleted file mode 100644 index 0e1af3c281..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoBaseVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** -* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class ToolTestDemoBaseVO { - - @ApiModelProperty(value = "名字", required = true, example = "芋道") - @NotNull(message = "名字不能为空") - private String name; - - @ApiModelProperty(value = "状态", required = true, example = "1") - @NotNull(message = "状态不能为空") - private Integer status; - - @ApiModelProperty(value = "类型", required = true, example = "2") - @NotNull(message = "类型不能为空") - private Integer type; - - @ApiModelProperty(value = "分类", required = true, example = "3") - @NotNull(message = "分类不能为空") - private Integer category; - - @ApiModelProperty(value = "备注", example = "我是备注") - private String remark; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java deleted file mode 100644 index bfb9170200..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExcelVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.util.Date; - -/** - * 测试示例 Excel VO - * - * @author 芋艿 - */ -@Data -public class ToolTestDemoExcelVO { - - @ExcelProperty("编号") - private Long id; - - @ExcelProperty("名字") - private String name; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) - private Integer status; - - @ExcelProperty(value = "类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.OPERATE_TYPE) - private Integer type; - - @ExcelProperty(value = "分类", converter = DictConvert.class) - @DictFormat(InfDictTypeConstants.REDIS_TIMEOUT_TYPE) - private Integer category; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("创建时间") - private Date createTime; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java deleted file mode 100644 index 84bce9e946..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoExportReqVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.util.Date; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@ApiModel(value = "字典类型 Excel 导出 Request VO", description = "参数和 ToolTestDemoPageReqVO 是一致的") -@Data -public class ToolTestDemoExportReqVO { - - @ApiModelProperty(value = "名字", example = "芋道") - private String name; - - @ApiModelProperty(value = "状态", example = "1") - private Integer status; - - @ApiModelProperty(value = "类型", example = "2") - private Integer type; - - @ApiModelProperty(value = "分类", example = "3") - private Integer category; - - @ApiModelProperty(value = "备注", example = "我是备注") - private String remark; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ApiModelProperty(value = "开始创建时间") - private Date beginCreateTime; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ApiModelProperty(value = "结束创建时间") - private Date endCreateTime; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java deleted file mode 100644 index 05fa1573e4..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoPageReqVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.util.Date; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@ApiModel("字典类型分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ToolTestDemoPageReqVO extends PageParam { - - @ApiModelProperty(value = "名字", example = "芋道") - private String name; - - @ApiModelProperty(value = "状态", example = "1") - private Integer status; - - @ApiModelProperty(value = "类型", example = "2") - private Integer type; - - @ApiModelProperty(value = "分类", example = "3") - private Integer category; - - @ApiModelProperty(value = "备注", example = "我是备注") - private String remark; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ApiModelProperty(value = "开始创建时间") - private Date beginCreateTime; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ApiModelProperty(value = "结束创建时间") - private Date endCreateTime; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoUpdateReqVO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoUpdateReqVO.java deleted file mode 100644 index ef05d44c65..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoUpdateReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@ApiModel("字典类型更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ToolTestDemoUpdateReqVO extends ToolTestDemoBaseVO { - - @ApiModelProperty(value = "编号", required = true, example = "1") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/codegen/ToolCodegenConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/codegen/ToolCodegenConvert.java deleted file mode 100644 index 65bf461000..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/codegen/ToolCodegenConvert.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.convert.codegen; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenDetailRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenPreviewRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.column.ToolCodegenColumnRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTableRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolSchemaTableRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Mapper -public interface ToolCodegenConvert { - - ToolCodegenConvert INSTANCE = Mappers.getMapper(ToolCodegenConvert.class); - - // ========== ToolInformationSchemaTableDO 和 ToolInformationSchemaColumnDO 相关 ========== - - ToolCodegenTableDO convert(ToolSchemaTableDO bean); - - List convertList(List list); - - ToolCodegenTableRespVO convert(ToolSchemaColumnDO bean); - - // ========== ToolCodegenTableDO 相关 ========== - -// List convertList02(List list); - - ToolCodegenTableRespVO convert(ToolCodegenTableDO bean); - - PageResult convertPage(PageResult page); - - // ========== ToolCodegenTableDO 相关 ========== - - List convertList02(List list); - - ToolCodegenTableDO convert(ToolCodegenUpdateReqVO.Table bean); - - List convertList03(List columns); - - List convertList04(List list); - - // ========== 其它 ========== - - default ToolCodegenDetailRespVO convert(ToolCodegenTableDO table, List columns) { - ToolCodegenDetailRespVO respVO = new ToolCodegenDetailRespVO(); - respVO.setTable(convert(table)); - respVO.setColumns(convertList02(columns)); - return respVO; - } - - default List convert(Map codes) { - return codes.entrySet().stream().map(entry -> { - ToolCodegenPreviewRespVO respVO = new ToolCodegenPreviewRespVO(); - respVO.setFilePath(entry.getKey()); - respVO.setCode(entry.getValue()); - return respVO; - }).collect(Collectors.toList()); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/test/ToolTestDemoConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/test/ToolTestDemoConvert.java deleted file mode 100644 index 8e88c59f4f..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/convert/test/ToolTestDemoConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.convert.test; - -import java.util.*; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo.*; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test.ToolTestDemoDO; - -/** - * 字典类型 Convert - * - * @author 芋艿 - */ -@Mapper -public interface ToolTestDemoConvert { - - ToolTestDemoConvert INSTANCE = Mappers.getMapper(ToolTestDemoConvert.class); - - ToolTestDemoDO convert(ToolTestDemoCreateReqVO bean); - - ToolTestDemoDO convert(ToolTestDemoUpdateReqVO bean); - - ToolTestDemoRespVO convert(ToolTestDemoDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenColumnMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenColumnMapper.java deleted file mode 100644 index 2fae426917..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenColumnMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface ToolCodegenColumnMapper extends BaseMapperX { - - default List selectListByTableId(Long tableId) { - return selectList(new QueryWrapper().eq("table_id", tableId) - .orderByAsc("ordinal_position")); - } - - default void deleteListByTableId(Long tableId) { - delete(new QueryWrapper().eq("table_id", tableId)); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenTableMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenTableMapper.java deleted file mode 100644 index 31ce16f7b0..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolCodegenTableMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTablePageReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface ToolCodegenTableMapper extends BaseMapperX { - - default ToolCodegenTableDO selectByTableName(String tableName) { - return selectOne(new QueryWrapper().eq("table_name", tableName)); - } - - default PageResult selectPage(ToolCodegenTablePageReqVO pageReqVO) { - return selectPage(pageReqVO, new QueryWrapperX() - .likeIfPresent("table_name", pageReqVO.getTableName()) - .likeIfPresent("table_comment", pageReqVO.getTableComment()) - .betweenIfPresent("create_time", pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime())); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaColumnMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaColumnMapper.java deleted file mode 100644 index 4778da065f..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaColumnMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface ToolSchemaColumnMapper extends BaseMapperX { - - default List selectListByTableName(String tableSchema, String tableName) { - return selectList(new QueryWrapper().eq("table_name", tableName) - .eq("table_schema", tableSchema) - .orderByAsc("ordinal_position")); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaTableMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaTableMapper.java deleted file mode 100644 index 7430ef69e3..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolSchemaTableMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface ToolSchemaTableMapper extends BaseMapperX { - - default List selectList(Collection tableSchemas, String tableName, String tableComment) { - return selectList(new QueryWrapperX().in("table_schema", tableSchemas) - .likeIfPresent("table_name", tableName) - .likeIfPresent("table_comment", tableComment)); - } - - default ToolSchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) { - return selectOne(new QueryWrapper().eq("table_schema",tableSchema) - .eq("table_name", tableName)); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/test/ToolTestDemoMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/test/ToolTestDemoMapper.java deleted file mode 100644 index 4bee17eb19..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/test/ToolTestDemoMapper.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.test; - -import java.util.*; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test.ToolTestDemoDO; -import org.apache.ibatis.annotations.Mapper; -import cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo.*; - -/** - * 字典类型 Mapper - * - * @author 芋艿 - */ -@Mapper -public interface ToolTestDemoMapper extends BaseMapperX { - - default PageResult selectPage(ToolTestDemoPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() - .likeIfPresent("name", reqVO.getName()) - .eqIfPresent("status", reqVO.getStatus()) - .eqIfPresent("type", reqVO.getType()) - .eqIfPresent("category", reqVO.getCategory()) - .eqIfPresent("remark", reqVO.getRemark()) - .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc("id")); - } - - default List selectList(ToolTestDemoExportReqVO reqVO) { - return selectList(new QueryWrapperX() - .likeIfPresent("name", reqVO.getName()) - .eqIfPresent("status", reqVO.getStatus()) - .eqIfPresent("type", reqVO.getType()) - .eqIfPresent("category", reqVO.getCategory()) - .eqIfPresent("remark", reqVO.getRemark()) - .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) - .orderByDesc("id")); - } - -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/package-info.java deleted file mode 100644 index f1e361d134..0000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * tool 包下,我们放研发工具,提升研发效率与质量。 - * 例如说:代码生成器、接口文档等等 - * - * 缩写:tool - */ -package cn.iocoder.yudao.adminserver.modules.tool; diff --git a/yudao-admin-server/src/main/resources/codegen/java/convert/convert.vm b/yudao-admin-server/src/main/resources/codegen/java/convert/convert.vm deleted file mode 100644 index 4302bd2c5c..0000000000 --- a/yudao-admin-server/src/main/resources/codegen/java/convert/convert.vm +++ /dev/null @@ -1,34 +0,0 @@ -package ${basePackage}.modules.${table.moduleName}.convert.${table.businessName}; - -import java.util.*; - -import ${PageResultClassName}; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; - -/** - * ${table.classComment} Convert - * - * @author ${table.author} - */ -@Mapper -public interface ${table.className}Convert { - - ${table.className}Convert INSTANCE = Mappers.getMapper(${table.className}Convert.class); - - ${table.className}DO convert(${table.className}CreateReqVO bean); - - ${table.className}DO convert(${table.className}UpdateReqVO bean); - - ${table.className}RespVO convert(${table.className}DO bean); - - List<${table.className}RespVO> convertList(List<${table.className}DO> list); - - PageResult<${table.className}RespVO> convertPage(PageResult<${table.className}DO> page); - - List<${table.className}ExcelVO> convertList02(List<${table.className}DO> list); - -} diff --git a/yudao-admin-server/src/main/resources/codegen/java/dal/mapper.vm b/yudao-admin-server/src/main/resources/codegen/java/dal/mapper.vm deleted file mode 100644 index 2452ca8f66..0000000000 --- a/yudao-admin-server/src/main/resources/codegen/java/dal/mapper.vm +++ /dev/null @@ -1,66 +0,0 @@ -package ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}; - -import java.util.*; - -import ${PageResultClassName}; -import ${QueryWrapperClassName}; -import ${BaseMapperClassName}; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; -import org.apache.ibatis.annotations.Mapper; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; - -## 字段模板 -#macro(listCondition) -#foreach ($column in $columns) -#if (${column.listOperation}) -#set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 -#if (${column.listOperationCondition} == "=")##情况一,= 的时候 - .eqIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == "!=")##情况二,!= 的时候 - .neIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == ">")##情况三,> 的时候 - .gtIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == ">=")##情况四,>= 的时候 - .geIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == "<")##情况五,< 的时候 - .ltIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == "<=")##情况五,<= 的时候 - .leIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == "LIKE")##情况七,Like 的时候 - .likeIfPresent("${column.columnName}", reqVO.get${JavaField}()) -#end -#if (${column.listOperationCondition} == "BETWEEN")##情况八,Between 的时候 - .betweenIfPresent("${column.columnName}", reqVO.getBegin${JavaField}(), reqVO.getEnd${JavaField}()) -#end -#end -#end -#end -/** - * ${table.classComment} Mapper - * - * @author ${table.author} - */ -@Mapper -public interface ${table.className}Mapper extends BaseMapperX<${table.className}DO> { - - default PageResult<${table.className}DO> selectPage(${table.className}PageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX<${table.className}DO>() - #listCondition() - .orderByDesc("id")## 大多数情况下,id 倒序 - ); - } - - default List<${table.className}DO> selectList(${table.className}ExportReqVO reqVO) { - return selectList(new QueryWrapperX<${table.className}DO>() - #listCondition() - .orderByDesc("id")## 大多数情况下,id 倒序 - ); - } - -} diff --git a/yudao-admin-server/src/main/resources/processes/oa-leave.bpmn b/yudao-admin-server/src/main/resources/processes/oa-leave.bpmn deleted file mode 100644 index fcaa1fcb48..0000000000 --- a/yudao-admin-server/src/main/resources/processes/oa-leave.bpmn +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - ${day>3} - - - ${day<=3} - - - - - - - - - - ${approved =='false'} - - - - - - - ${approved =='false'} - - - - ${approved =='true'} - - - ${approved =='true'} - - - - - - - - ${approved =='false'} - - - - - - ${approved =='true'} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/package-info.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/package-info.java deleted file mode 100644 index b6bd21477b..0000000000 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java deleted file mode 100644 index 1e86eb5d82..0000000000 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import org.junit.jupiter.api.Test; - -import javax.annotation.Resource; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class ToolInformationSchemaColumnMapperTest extends BaseDbUnitTest { - - @Resource - private ToolSchemaColumnMapper toolInformationSchemaColumnMapper; - - @Test - public void testSelectListByTableName() { - List columns = toolInformationSchemaColumnMapper - .selectListByTableName("", "inf_config"); - assertTrue(columns.size() > 0); - } - -} diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java deleted file mode 100644 index 35d91b8c45..0000000000 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen; - -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; - -import javax.annotation.Resource; - -class ToolInformationSchemaTableMapperTest extends BaseDbUnitTest { - - @Resource - private ToolSchemaTableMapper toolInformationSchemaTableMapper; - -} diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenEngineTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenEngineTest.java deleted file mode 100644 index a8a7857e97..0000000000 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenEngineTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen; - -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolCodegenColumnMapper; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolCodegenTableMapper; -import cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl.ToolCodegenEngine; -import org.junit.jupiter.api.Test; - -import javax.annotation.Resource; -import java.util.List; -import java.util.Map; - -public class ToolCodegenEngineTest extends BaseDbUnitTest { - - @Resource - private ToolCodegenTableMapper codegenTableMapper; - @Resource - private ToolCodegenColumnMapper codegenColumnMapper; - - @Resource - private ToolCodegenEngine codegenEngine; - - @Test - public void testExecute() { - ToolCodegenTableDO table = codegenTableMapper.selectById(20); - List columns = codegenColumnMapper.selectListByTableId(table.getId()); - Map result = codegenEngine.execute(table, columns); - result.forEach((s, s2) -> System.out.println(s2)); -// System.out.println(result.get("vue/views/system/test/index.vue")); - } - -} diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenServiceImplTest.java b/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenServiceImplTest.java deleted file mode 100644 index 87661a3cd8..0000000000 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenServiceImplTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen; - -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl.ToolCodegenServiceImpl; -import org.junit.jupiter.api.Test; - -import javax.annotation.Resource; - -class ToolCodegenServiceImplTest extends BaseDbUnitTest { - - @Resource - private ToolCodegenServiceImpl toolCodegenService; - - @Test - public void tetCreateCodegenTable() { - toolCodegenService.createCodegen("tool_test_demo"); -// toolCodegenService.createCodegenTable("tool_codegen_table"); -// toolCodegenService.createCodegen("tool_codegen_column"); - } - -} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/package-info.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/package-info.java deleted file mode 100644 index cdde7ccc4a..0000000000 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java deleted file mode 100644 index a5d4d8e955..0000000000 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.file; - -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.service.file.impl.InfFileServiceImpl; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; - -@Import({InfFileServiceImpl.class, FileProperties.class}) -public class InfFileServiceTest extends BaseDbUnitTest { - - @Resource - private InfFileService fileService; - - @MockBean - private FileProperties fileProperties; - - @Resource - private InfFileCoreMapper fileMapper; - - @Test - public void testGetFilePage() { - // mock 数据 - InfFileDO dbFile = randomPojo(InfFileDO.class, o -> { // 等会查询到 - o.setId("yudao"); - o.setType("jpg"); - o.setCreateTime(buildTime(2021, 1, 15)); - }); - fileMapper.insert(dbFile); - // 测试 id 不匹配 - fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setId("tudou"))); - // 测试 type 不匹配 - fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { - o.setId("yudao02"); - o.setType("png"); - })); - // 测试 createTime 不匹配 - fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { - o.setId("yudao03"); - o.setCreateTime(buildTime(2020, 1, 15)); - })); - // 准备参数 - InfFilePageReqVO reqVO = new InfFilePageReqVO(); - reqVO.setId("yudao"); - reqVO.setType("jp"); - reqVO.setBeginCreateTime(buildTime(2021, 1, 10)); - reqVO.setEndCreateTime(buildTime(2021, 1, 20)); - - // 调用 - PageResult pageResult = fileService.getFilePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbFile, pageResult.getList().get(0), "content"); - } - -} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelConfig.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelConfig.java deleted file mode 100644 index bff90e6e08..0000000000 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.channel; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.validation.Validation; -import javax.validation.Validator; - -/** - * 用于初始化 validator Bean 对象 - * @author aquan - */ -@Configuration -public class PayChannelConfig { - - @Bean - public Validator validator(){ - return Validation.buildDefaultValidatorFactory().getValidator(); - } -} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java deleted file mode 100644 index 164cd90d7d..0000000000 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth; - -import cn.hutool.core.date.DateUtil; -import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysUserSessionServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.test.core.util.AssertUtils; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -/** - * {@link SysUserSessionServiceImpl} 的单元测试 - * - * @author Lyon - */ -@Import({SysUserSessionServiceImpl.class}) -public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest { - - @Resource - private SysUserSessionServiceImpl userSessionService; - - @Resource - private SysUserSessionMapper userSessionMapper; - - @MockBean - private SysUserService userService; - @MockBean - private SysLoginLogCoreService loginLogCoreService; - @MockBean - private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO; - - @Test - public void testGetUserSessionPage_success() { - // mock 数据 - SysUserDO dbUser = randomPojo(SysUserDO.class, o -> { - o.setSex(randomEle(SysSexEnum.values()).getSex()); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - }); - when(userService.getUsersByUsername(eq(dbUser.getUsername()))).thenReturn(singletonList(dbUser)); - // 插入可被查询到的数据 - String userIp = randomString(); - SysUserSessionDO dbSession = randomPojo(SysUserSessionDO.class, o -> { - o.setUserId(dbUser.getId()); - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); - o.setUserIp(userIp); - }); - userSessionMapper.insert(dbSession); - // 测试 username 不匹配 - userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> { - o.setId(randomString()); - o.setUserId(123456L); - })); - // 测试 userIp 不匹配 - userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> { - o.setId(randomString()); - o.setUserIp("testUserIp"); - })); - // 准备参数 - SysUserSessionPageReqVO reqVO = new SysUserSessionPageReqVO(); - reqVO.setUsername(dbUser.getUsername()); - reqVO.setUserIp(userIp); - - // 调用 - PageResult pageResult = userSessionService.getUserSessionPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSession, pageResult.getList().get(0)); - } - - // TODO 芋艿:单测写的有问题 - @Test - public void testClearSessionTimeout_success() { - // 准备超时数据 120 条, 在线用户 1 条 - int expectedTimeoutCount = 120, expectedTotal = 1; - - // 准备数据 - List prepareData = Stream - .iterate(0, i -> i) - .limit(expectedTimeoutCount) - .map(i -> randomPojo(SysUserSessionDO.class, o -> { - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); - o.setSessionTimeout(DateUtil.offsetSecond(new Date(), -1)); - })) - .collect(Collectors.toList()); - SysUserSessionDO sessionDO = randomPojo(SysUserSessionDO.class, o -> { - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); - o.setSessionTimeout(DateUtil.offsetMinute(new Date(), 30)); - }); - prepareData.add(sessionDO); - prepareData.forEach(userSessionMapper::insert); - - // 清空超时数据 - long actualTimeoutCount = userSessionService.clearSessionTimeout(); - // 校验 - assertEquals(expectedTimeoutCount, actualTimeoutCount); - List userSessionDOS = userSessionMapper.selectList(); - assertEquals(expectedTotal, userSessionDOS.size()); - AssertUtils.assertPojoEquals(sessionDO, userSessionDOS.get(0), "updateTime"); - } - -} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java deleted file mode 100644 index fdeed2aa87..0000000000 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; - -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsLogServiceImpl; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsReceiveStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsSendStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsTemplateTypeEnum; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** -* {@link SysSmsLogServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysSmsLogServiceImpl.class) -public class SysSmsLogServiceTest extends BaseDbUnitTest { - - @Resource - private SysSmsLogServiceImpl smsLogService; - - @Resource - private SysSmsLogMapper smsLogMapper; - - @Test - public void testGetSmsLogPage() { - // mock 数据 - SysSmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 - o.setChannelId(1L); - o.setTemplateId(10L); - o.setMobile("15601691300"); - o.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildTime(2020, 11, 11)); - o.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildTime(2021, 11, 11)); - }); - smsLogMapper.insert(dbSmsLog); - // 测试 channelId 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); - // 测试 templateId 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); - // 测试 mobile 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); - // 测试 sendStatus 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus()))); - // 测试 sendTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); - // 测试 receiveStatus 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus()))); - // 测试 receiveTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); - // 准备参数 - SysSmsLogPageReqVO reqVO = new SysSmsLogPageReqVO(); - reqVO.setChannelId(1L); - reqVO.setTemplateId(10L); - reqVO.setMobile("156"); - reqVO.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); - reqVO.setBeginSendTime(buildTime(2020, 11, 1)); - reqVO.setEndSendTime(buildTime(2020, 11, 30)); - reqVO.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); - reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); - - // 调用 - PageResult pageResult = smsLogService.getSmsLogPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); - } - - @Test - public void testGetSmsLogList() { - // mock 数据 - SysSmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 - o.setChannelId(1L); - o.setTemplateId(10L); - o.setMobile("15601691300"); - o.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildTime(2020, 11, 11)); - o.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildTime(2021, 11, 11)); - }); - smsLogMapper.insert(dbSmsLog); - // 测试 channelId 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); - // 测试 templateId 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); - // 测试 mobile 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); - // 测试 sendStatus 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus()))); - // 测试 sendTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); - // 测试 receiveStatus 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus()))); - // 测试 receiveTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); - // 准备参数 - SysSmsLogExportReqVO reqVO = new SysSmsLogExportReqVO(); - reqVO.setChannelId(1L); - reqVO.setTemplateId(10L); - reqVO.setMobile("156"); - reqVO.setSendStatus(SysSmsSendStatusEnum.INIT.getStatus()); - reqVO.setBeginSendTime(buildTime(2020, 11, 1)); - reqVO.setEndSendTime(buildTime(2020, 11, 30)); - reqVO.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); - reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); - - // 调用 - List list = smsLogService.getSmsLogList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSmsLog, list.get(0)); - } - - // ========== 随机对象 ========== - - @SafeVarargs - private static SysSmsLogDO randomSmsLogDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setTemplateParams(randomTemplateParams()); - o.setTemplateType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 templateType 的范围 - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); // 保证 userType 的范围 - o.setSendStatus(randomEle(SysSmsSendStatusEnum.values()).getStatus()); // 保证 sendStatus 的范围 - o.setReceiveStatus(randomEle(SysSmsReceiveStatusEnum.values()).getStatus()); // 保证 receiveStatus 的范围 - }; - return randomPojo(SysSmsLogDO.class, ArrayUtils.append(consumer, consumers)); - } - - - private static Map randomTemplateParams() { - return MapUtil.builder().put(randomString(), randomString()) - .put(randomString(), randomString()).build(); - } -} diff --git a/yudao-admin-server/src/test/resources/logback.xml b/yudao-admin-server/src/test/resources/logback.xml deleted file mode 100644 index 1e4bb6caf6..0000000000 --- a/yudao-admin-server/src/test/resources/logback.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - -       - - - ${PATTERN_DEFAULT} - - - - - - - - - diff --git a/yudao-admin-server/src/test/resources/sql/clean.sql b/yudao-admin-server/src/test/resources/sql/clean.sql deleted file mode 100644 index b565553f24..0000000000 --- a/yudao-admin-server/src/test/resources/sql/clean.sql +++ /dev/null @@ -1,38 +0,0 @@ --- inf 开头的 DB -DELETE FROM "inf_config"; -DELETE FROM "inf_file"; -DELETE FROM "inf_job"; -DELETE FROM "inf_job_log"; -DELETE FROM "inf_api_access_log"; -DELETE FROM "inf_api_error_log"; - --- sys 开头的 DB -DELETE FROM "sys_dept"; -DELETE FROM "sys_dict_data"; -DELETE FROM "sys_role"; -DELETE FROM "sys_role_menu"; -DELETE FROM "sys_menu"; -DELETE FROM "sys_user_role"; -DELETE FROM "sys_dict_type"; -DELETE FROM "sys_user_session"; -DELETE FROM "sys_post"; -DELETE FROM "sys_login_log"; -DELETE FROM "sys_operate_log"; -DELETE FROM "sys_user"; -DELETE FROM "sys_sms_channel"; -DELETE FROM "sys_sms_template"; -DELETE FROM "sys_sms_log"; -DELETE FROM "sys_error_code"; -DELETE FROM "sys_social_user"; -DELETE FROM "sys_tenant"; - --- pay 开头的 DB -DELETE FROM pay_merchant; -DELETE FROM pay_app; -DELETE FROM pay_channel; -DELETE FROM pay_order; -DELETE FROM pay_refund; - --- bpm 开头的 DB -DELETE FROM "bpm_form"; -DELETE FROM "bpm_user_group"; diff --git a/yudao-admin-ui/.env.demo1024 b/yudao-admin-ui/.env.demo1024 deleted file mode 100644 index ffeadbf8c8..0000000000 --- a/yudao-admin-ui/.env.demo1024 +++ /dev/null @@ -1,7 +0,0 @@ -NODE_ENV = production - -# 测试环境配置 -ENV = 'staging' - -# 芋道管理系统/测试环境 -VUE_APP_BASE_API = 'http://127.0.0.1:48080' diff --git a/yudao-admin-ui/src/utils/dict.js b/yudao-admin-ui/src/utils/dict.js deleted file mode 100644 index e10414d405..0000000000 --- a/yudao-admin-ui/src/utils/dict.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Created by 芋道源码 - * - * 数据字典工具类 - */ -import store from '@/store' - -export const DICT_TYPE = { - USER_TYPE: 'user_type', - - // system - SYS_COMMON_STATUS: 'sys_common_status', - SYS_MENU_TYPE: 'sys_menu_type', - SYS_ROLE_TYPE: 'sys_role_type', - SYS_DATA_SCOPE: 'sys_data_scope', - SYS_USER_SEX: 'sys_user_sex', - SYS_NOTICE_TYPE: 'sys_notice_type', - SYS_OPERATE_TYPE: 'sys_operate_type', - SYS_LOGIN_TYPE: 'sys_login_type', - SYS_LOGIN_RESULT: 'sys_login_result', - SYS_CONFIG_TYPE: 'sys_config_type', - SYS_SMS_CHANNEL_CODE: 'sys_sms_channel_code', - SYS_SMS_TEMPLATE_TYPE: 'sys_sms_template_type', - SYS_SMS_SEND_STATUS: 'sys_sms_send_status', - SYS_SMS_RECEIVE_STATUS: 'sys_sms_receive_status', - SYS_ERROR_CODE_TYPE: 'sys_error_code_type', - - // infra - INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type', - INF_JOB_STATUS: 'inf_job_status', - INF_JOB_LOG_STATUS: 'inf_job_log_status', - INF_API_ERROR_LOG_PROCESS_STATUS: 'inf_api_error_log_process_status', - - // tool - TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', - - // bpm - BPM_MODEL_CATEGORY: 'bpm_model_category', - BPM_MODEL_FORM_TYPE: 'bpm_model_form_type', - BPM_TASK_ASSIGN_RULE_TYPE: 'bpm_task_assign_rule_type', - BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status', - BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result', - BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script', - BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type', - - // pay - // 微信渠道版本 - PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version', - // 支付渠道支付宝算法类型 - PAY_CHANNEL_ALIPAY_SIGN_TYPE:'pay_channel_alipay_sign_type', - // 支付宝公钥类型 - PAY_CHANNEL_ALIPAY_MODE:'pay_channel_alipay_mode', - // 支付宝网关地址 - PAY_CHANNEL_ALIPAY_SERVER_TYPE:'pay_channel_alipay_server_type', - // 支付渠道编码类型 - PAY_CHANNEL_CODE_TYPE: 'pay_channel_code_type', - // 商户支付订单回调状态 - PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status', - // 商户支付订单状态 - PAY_ORDER_STATUS: 'pay_order_status', - // 商户支付订单退款状态 - PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', - // 退款订单状态 - PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', - // 退款订单类别 - PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', -} - -/** - * 获取 dictType 对应的数据字典数组 - * - * @param dictType 数据类型 - * @returns {*|Array} 数据字典数组 - */ -export function getDictDatas(dictType) { - // if (dictType === 'bpm_task_assign_script') { - // console.log(store.getters.dict_datas[dictType]); - // debugger - // } - return store.getters.dict_datas[dictType] || [] -} - -export function getDictDataLabel(dictType, value) { - // 获取 dictType 对应的数据字典数组 - const dictDatas = getDictDatas(dictType) - if (!dictDatas || dictDatas.length === 0) { - return '' - } - // 获取 value 对应的展示名 - value = value + '' // 强制转换成字符串,因为 DictData 小类数值,是字符串 - for (const dictData of dictDatas) { - if (dictData.value === value) { - return dictData.label - } - } - return '' -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiAccessLogCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiAccessLogCoreConvert.java deleted file mode 100644 index f5152f7109..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiAccessLogCoreConvert.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.convert.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface InfApiAccessLogCoreConvert { - - InfApiAccessLogCoreConvert INSTANCE = Mappers.getMapper(InfApiAccessLogCoreConvert.class); - - InfApiAccessLogDO convert(ApiAccessLogCreateReqDTO bean); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiErrorLogCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiErrorLogCoreConvert.java deleted file mode 100644 index 0c130a28b9..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/logger/InfApiErrorLogCoreConvert.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.convert.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface InfApiErrorLogCoreConvert { - - InfApiErrorLogCoreConvert INSTANCE = Mappers.getMapper(InfApiErrorLogCoreConvert.class); - - InfApiErrorLogDO convert(ApiErrorLogCreateReqDTO bean); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/package-info.java deleted file mode 100644 index bdb8ce7a3a..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 POJO 类的实体转换 - * - * 目前使用 MapStruct 框架 - */ -package cn.iocoder.yudao.coreservice.modules.infra.convert; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java deleted file mode 100644 index 8075608af0..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface InfFileCoreMapper extends BaseMapperX { - - default Integer selectCountById(String id) { - return selectCount(InfFileDO::getId, id); - } - - /** - * 基于 Path 获取文件 - * 实际上,是基于 ID 查询 - * 由于前端使用 的方式获取图片,所以需要忽略租户的查询 - * - * @param path 路径 - * @return 文件 - */ - @InterceptorIgnore(tenantLine = "true") - default InfFileDO selectByPath(String path) { - return selectById(path); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiAccessLogCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiAccessLogCoreMapper.java deleted file mode 100644 index a189254899..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiAccessLogCoreMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * API 访问日志 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface InfApiAccessLogCoreMapper extends BaseMapperX { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiErrorLogCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiErrorLogCoreMapper.java deleted file mode 100644 index 1776c78873..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/logger/InfApiErrorLogCoreMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface InfApiErrorLogCoreMapper extends BaseMapperX { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/package-info.java deleted file mode 100644 index 6231dae910..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位类,可以无视 - */ -package cn.iocoder.yudao.coreservice.modules.infra.enums; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/package-info.java deleted file mode 100644 index 1f011d6a1e..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 - * 例如说:定时任务的管理、服务器的信息等等 - * - * 缩写:inf - */ -package cn.iocoder.yudao.coreservice.modules.infra; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreService.java deleted file mode 100644 index a594bcef4a..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreService.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.file; - -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; - -/** - * core service 文件接口 - * - * @author 宋天 - */ -public interface InfFileCoreService { - - - /** - * 保存文件,并返回文件的访问路径 - * - * @param path 文件路径 - * @param content 文件内容 - * @return 文件路径 - */ - String createFile(String path, byte[] content); - - /** - * 删除文件 - * - * @param id 编号 - */ - void deleteFile(String id); - - /** - * 获得文件 - * - * @param path 文件路径 - * @return 文件 - */ - InfFileDO getFile(String path); -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreService.java deleted file mode 100644 index f5480572d5..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreService.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; - -/** - * API 访问日志 Service 接口 - * - * @author 芋道源码 - */ -public interface InfApiAccessLogCoreService extends ApiAccessLogFrameworkService { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreService.java deleted file mode 100644 index 6c8d692018..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreService.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; - -/** - * API 错误日志 Service 接口 - * - * @author 芋道源码 - */ -public interface InfApiErrorLogCoreService extends ApiErrorLogFrameworkService { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiAccessLogCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiAccessLogCoreServiceImpl.java deleted file mode 100644 index 6327b8b967..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiAccessLogCoreServiceImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl; - -import cn.iocoder.yudao.coreservice.modules.infra.convert.logger.InfApiAccessLogCoreConvert; -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiAccessLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.service.logger.InfApiAccessLogCoreService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; - -/** - * API 访问日志 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -@Slf4j -public class InfApiAccessLogCoreServiceImpl implements InfApiAccessLogCoreService { - - @Resource - private InfApiAccessLogCoreMapper apiAccessLogMapper; - - @Override - @Async - public void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) { - InfApiAccessLogDO apiAccessLog = InfApiAccessLogCoreConvert.INSTANCE.convert(createDTO); - apiAccessLogMapper.insert(apiAccessLog); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiErrorLogCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiErrorLogCoreServiceImpl.java deleted file mode 100644 index 4004ea7f66..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/impl/InfApiErrorLogCoreServiceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl; - -import cn.iocoder.yudao.coreservice.modules.infra.convert.logger.InfApiErrorLogCoreConvert; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiErrorLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; -import cn.iocoder.yudao.coreservice.modules.infra.service.logger.InfApiErrorLogCoreService; -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; - -/** - * API 错误日志 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -@Slf4j -public class InfApiErrorLogCoreServiceImpl implements InfApiErrorLogCoreService { - - @Resource - private InfApiErrorLogCoreMapper apiErrorLogMapper; - - @Override - @Async - public void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) { - InfApiErrorLogDO apiErrorLog = InfApiErrorLogCoreConvert.INSTANCE.convert(createDTO); - apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); - apiErrorLogMapper.insert(apiErrorLog); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/package-info.java deleted file mode 100644 index 230bbc0922..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 POJO 类的实体转换 - * - * 目前使用 MapStruct 框架 - */ -package cn.iocoder.yudao.coreservice.modules.member.convert; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md deleted file mode 100644 index 8153487b72..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/mysql/user/MbrUserCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/mysql/user/MbrUserCoreMapper.java deleted file mode 100644 index 27c0c95097..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/mysql/user/MbrUserCoreMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.member.dal.mysql.user; - -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface MbrUserCoreMapper extends BaseMapperX { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/package-info.java deleted file mode 100644 index 17abe90bd5..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * member 包下,我们放会员业务. - * 例如说:会员中心等等 - * - * 缩写:mbr - */ -package cn.iocoder.yudao.coreservice.modules.member; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/MbrUserCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/MbrUserCoreService.java deleted file mode 100644 index 934413956b..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/MbrUserCoreService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.member.service.user; - -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; - -/** - * 前台用户 Core Service 接口 - * - * @author 芋道源码 - */ -public interface MbrUserCoreService { - /** - * 通过用户 ID 查询用户 - * - * @param id 用户ID - * @return 用户对象信息 - */ - MbrUserDO getUser(Long id); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/impl/MbrUserCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/impl/MbrUserCoreServiceImpl.java deleted file mode 100644 index 08ee22c76c..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/impl/MbrUserCoreServiceImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.member.service.user.impl; - -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; -import cn.iocoder.yudao.coreservice.modules.member.dal.mysql.user.MbrUserCoreMapper; -import cn.iocoder.yudao.coreservice.modules.member.service.user.MbrUserCoreService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * User Core Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Slf4j -public class MbrUserCoreServiceImpl implements MbrUserCoreService { - - @Resource - private MbrUserCoreMapper userCoreMapper; - - @Override - public MbrUserDO getUser(Long id) { - return userCoreMapper.selectById(id); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayOrderCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayOrderCoreConvert.java deleted file mode 100644 index 3e5215cd87..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayOrderCoreConvert.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.convert.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; -import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface PayOrderCoreConvert { - - PayOrderCoreConvert INSTANCE = Mappers.getMapper(PayOrderCoreConvert.class); - - PayOrderDO convert(PayOrderCreateReqDTO bean); - - PayOrderExtensionDO convert(PayOrderSubmitReqDTO bean); - - PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayRefundCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayRefundCoreConvert.java deleted file mode 100644 index 4a4ada555f..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/order/PayRefundCoreConvert.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.convert.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface PayRefundCoreConvert { - - PayRefundCoreConvert INSTANCE = Mappers.getMapper(PayRefundCoreConvert.class); - - //TODO 太多需要处理了, 暂时不用 - @Mappings(value = { - @Mapping(source = "amount", target = "payAmount"), - @Mapping(source = "id", target = "orderId"), - @Mapping(target = "status",ignore = true) - }) - PayRefundDO convert(PayOrderDO orderDO); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md deleted file mode 100644 index 8153487b72..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayAppCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayAppCoreMapper.java deleted file mode 100644 index 603ff4609c..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayAppCoreMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface PayAppCoreMapper extends BaseMapperX { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapper.java deleted file mode 100644 index 767a16b24e..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapper.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -import java.util.Date; - -@Mapper -public interface PayChannelCoreMapper extends BaseMapperX { - - default PayChannelDO selectByAppIdAndCode(Long appId, String code) { - return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code); - } - - @Select("SELECT id FROM pay_channel WHERE update_time > #{maxUpdateTime} LIMIT 1") - Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderCoreMapper.java deleted file mode 100644 index 1ed34d549b..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderCoreMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface PayOrderCoreMapper extends BaseMapperX { - - default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) { - return selectOne(new QueryWrapper().eq("app_id", appId) - .eq("merchant_order_id", merchantOrderId)); - } - - default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) { - return update(update, new QueryWrapper() - .eq("id", id).eq("status", status)); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundCoreMapper.java deleted file mode 100644 index 8de1396dde..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayRefundCoreMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - - -/** - * 退款订单 Mapper - * - */ -@Mapper -public interface PayRefundCoreMapper extends BaseMapperX { - - default PayRefundDO selectByReqNo(String reqNo) { - return selectOne("req_no", reqNo); - } - - default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){ - return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/PayRedisKeyCoreConstants.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/PayRedisKeyCoreConstants.java deleted file mode 100644 index 99384ec126..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/PayRedisKeyCoreConstants.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.redis; - -import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; -import org.redisson.api.RLock; - -import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH; - -/** - * Lock4j Redis Key 枚举类 - * - * @author 芋道源码 - */ -public interface PayRedisKeyCoreConstants { - - RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁", - "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类 - HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/package-info.java deleted file mode 100644 index 8f5ba6ac30..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * pay 包下,我们放支付业务,提供业务的支付能力。 - * 例如说:商户、应用、支付、退款等等 - * - * 缩写:pay - */ -package cn.iocoder.yudao.coreservice.modules.pay; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayAppCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayAppCoreService.java deleted file mode 100644 index ab6f3f27f0..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayAppCoreService.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.merchant; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.framework.common.exception.ServiceException; - -/** - * 支付应用 Core Service 接口 - * - * @author 芋道源码 - */ -public interface PayAppCoreService { - - /** - * 支付应用的合法性 - * - * 如果不合法,抛出 {@link ServiceException} 业务异常 - * - * @param id 应用编号 - * @return 应用信息 - */ - PayAppDO validPayApp(Long id); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayChannelCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayChannelCoreService.java deleted file mode 100644 index 76d4678759..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/PayChannelCoreService.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.merchant; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.framework.common.exception.ServiceException; - -/** - * 支付渠道 Core Service 接口 - * - * @author 芋道源码 - */ -public interface PayChannelCoreService { - - /** - * 初始化支付客户端 - */ - void initPayClients(); - - /** - * 支付渠道的合法性 - * - * 如果不合法,抛出 {@link ServiceException} 业务异常 - * - * @param id 渠道编号 - * @return 渠道信息 - */ - PayChannelDO validPayChannel(Long id); - - /** - * 支付渠道的合法性 - * - * 如果不合法,抛出 {@link ServiceException} 业务异常 - * - * @param appId 应用编号 - * @param code 支付渠道 - * @return 渠道信息 - */ - PayChannelDO validPayChannel(Long appId, String code); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayAppCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayAppCoreServiceImpl.java deleted file mode 100644 index 916b501377..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayAppCoreServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant.PayAppCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import javax.validation.Valid; - -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 支付应用 Core Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Valid -@Slf4j -public class PayAppCoreServiceImpl implements PayAppCoreService { - - @Resource - private PayAppCoreMapper payAppCoreMapper; - - @Override - public PayAppDO validPayApp(Long id) { - PayAppDO app = payAppCoreMapper.selectById(id); - // 校验是否存在 - if (app == null) { - throw exception(PAY_APP_NOT_FOUND); - } - // 校验是否禁用 - if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { - throw exception(PAY_APP_IS_DISABLE); - } - return app; - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayChannelCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayChannelCoreServiceImpl.java deleted file mode 100644 index 5029b6ebd7..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/merchant/impl/PayChannelCoreServiceImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant.PayChannelCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import javax.validation.Valid; - -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 支付渠道 Core Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Valid -@Slf4j -public class PayChannelCoreServiceImpl implements PayChannelCoreService { - - /** - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 - */ - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; - - /** - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 - */ - private volatile Date maxUpdateTime; - - @Resource - private PayChannelCoreMapper payChannelCoreMapper; - - @Resource - private PayClientFactory payClientFactory; - - @Override - @PostConstruct - public void initPayClients() { - // 获取支付渠道,如果有更新 - List payChannels = this.loadPayChannelIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(payChannels)) { - return; - } - - // 创建或更新支付 Client - payChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), - payChannel.getCode(), payChannel.getConfig())); - - // 写入缓存 - assert payChannels.size() > 0; // 断言,避免告警 - maxUpdateTime = payChannels.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); - log.info("[initPayClients][初始化 PayChannel 数量为 {}]", payChannels.size()); - } - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initPayClients(); - } - - /** - * 如果支付渠道发生变化,从数据库中获取最新的全量支付渠道。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前支付渠道的最大更新时间 - * @return 支付渠道列表 - */ - private List loadPayChannelIfUpdate(Date maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadPayChannelIfUpdate][首次加载全量支付渠道]"); - } else { // 判断数据库中是否有更新的支付渠道 - if (payChannelCoreMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) { - return null; - } - log.info("[loadPayChannelIfUpdate][增量加载全量支付渠道]"); - } - // 第二步,如果有更新,则从数据库加载所有支付渠道 - return payChannelCoreMapper.selectList(); - } - - @Override - public PayChannelDO validPayChannel(Long id) { - PayChannelDO channel = payChannelCoreMapper.selectById(id); - this.validPayChannel(channel); - return channel; - } - - @Override - public PayChannelDO validPayChannel(Long appId, String code) { - PayChannelDO channel = payChannelCoreMapper.selectByAppIdAndCode(appId, code); - this.validPayChannel(channel); - return channel; - } - - private void validPayChannel(PayChannelDO channel) { - if (channel == null) { - throw exception(PAY_CHANNEL_NOT_FOUND); - } - if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) { - throw exception(PayErrorCodeCoreConstants.PAY_CHANNEL_IS_DISABLE); - } - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/package-info.java deleted file mode 100644 index 78667d3ce9..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 这里的 VO 包有点特殊,是提供给接入支付模块的业务,提供回调接口时,可以直接使用 VO - * - * 例如说,支付单的回调,使用 - */ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java deleted file mode 100644 index 07e659229b..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order; - -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; - -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.*; -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; - -import javax.validation.Valid; - -/** - * 支付订单 Core Service - * - * @author 芋道源码 - */ -public interface PayOrderCoreService { - - /** - * 获得支付单 - * - * @param id 支付单编号 - * @return 支付单 - */ - PayOrderDO getPayOrder(Long id); - - /** - * 创建支付单 - * - * @param reqDTO 创建请求 - * @return 支付单编号 - */ - Long createPayOrder(@Valid PayOrderCreateReqDTO reqDTO); - - /** - * 提交支付 - * 此时,会发起支付渠道的调用 - * - * @param reqDTO 提交请求 - * @return 提交结果 - */ - PayOrderSubmitRespDTO submitPayOrder(@Valid PayOrderSubmitReqDTO reqDTO); - - /** - * 通知支付单成功 - * - * @param channelId 渠道编号 - * @param notifyData 通知数据 - */ - void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception; - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java deleted file mode 100644 index b56384ed67..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayRefundCoreService.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order; - -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; - -/** - * 退款单 Core Service - * - * @author jason - */ -public interface PayRefundCoreService { - - /** - * 提交退款申请 - * - * @param reqDTO 退款申请信息 - * @return 退款申请返回信息 - */ - PayRefundRespDTO submitRefundOrder(PayRefundReqDTO reqDTO); - - /** - * 渠道的退款通知 - * - * @param channelId 渠道编号 - * @param notifyData 通知数据 - * @throws Exception 退款通知异常 - */ - void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) throws Exception; - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java deleted file mode 100644 index 13b4863a5b..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/dict/SysDictDataCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/dict/SysDictDataCoreConvert.java deleted file mode 100644 index e68e165d37..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/dict/SysDictDataCoreConvert.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.convert.dict; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SysDictDataCoreConvert { - - SysDictDataCoreConvert INSTANCE = Mappers.getMapper(SysDictDataCoreConvert.class); - - DictDataRespDTO convert02(SysDictDataDO bean); - - List convertList03(Collection list); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/logger/SysLoginLogCoreConvert.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/logger/SysLoginLogCoreConvert.java deleted file mode 100644 index 9c19927385..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/logger/SysLoginLogCoreConvert.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.convert.logger; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SysLoginLogCoreConvert { - - SysLoginLogCoreConvert INSTANCE = Mappers.getMapper(SysLoginLogCoreConvert.class); - - SysLoginLogDO convert(SysLoginLogCreateReqDTO bean); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/package-info.java deleted file mode 100644 index 87914750ae..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 POJO 类的实体转换 - * - * 目前使用 MapStruct 框架 - */ -package cn.iocoder.yudao.coreservice.modules.system.convert; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md deleted file mode 100644 index 8153487b72..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/package-info.java deleted file mode 100644 index f2ed88035c..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/auth/SysUserSessionCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/auth/SysUserSessionCoreMapper.java deleted file mode 100644 index 69b5c5acbb..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/auth/SysUserSessionCoreMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface SysUserSessionCoreMapper extends BaseMapperX { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/dict/SysDictDataCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/dict/SysDictDataCoreMapper.java deleted file mode 100644 index bda1a9142c..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/dict/SysDictDataCoreMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict; - - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Date; - -@Mapper -public interface SysDictDataCoreMapper extends BaseMapperX { - - default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { - return selectOne(new QueryWrapper().select("id") - .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null; - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/logger/SysLoginLogCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/logger/SysLoginLogCoreMapper.java deleted file mode 100644 index e6dd1ff51c..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/logger/SysLoginLogCoreMapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface SysLoginLogCoreMapper extends BaseMapperX { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/package-info.java deleted file mode 100644 index 144a054070..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsLogCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsLogCoreMapper.java deleted file mode 100644 index d09554575e..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsLogCoreMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SysSmsLogCoreMapper extends BaseMapperX { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsTemplateCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsTemplateCoreMapper.java deleted file mode 100644 index 4e064b40db..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/sms/SysSmsTemplateCoreMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -import java.util.Date; - -@Mapper -public interface SysSmsTemplateCoreMapper extends BaseMapperX { - - @Select("SELECT id FROM sys_sms_template WHERE update_time > #{maxUpdateTime} LIMIT 1") - Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserCoreMapper.java deleted file mode 100644 index 727c38e678..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserCoreMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SysSocialUserCoreMapper extends BaseMapperX { - - default List selectListByTypeAndUnionId(Integer userType, Collection types, String unionId) { - return selectList(new QueryWrapper().eq("user_type", userType) - .in("type", types).eq("union_id", unionId)); - } - - default List selectListByTypeAndUserId(Integer userType, Collection types, Long userId) { - return selectList(new QueryWrapper().eq("user_type", userType) - .in("type", types).eq("user_id", userId)); - } - - default List selectListByUserId(Integer userType, Long userId) { - return selectList(new QueryWrapper().eq("user_type", userType).eq("user_id", userId)); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java deleted file mode 100644 index 197f893fac..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.tenant; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface SysTenantCoreMapper extends BaseMapperX { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/user/SysUserCoreMapper.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/user/SysUserCoreMapper.java deleted file mode 100644 index a59275b39e..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/user/SysUserCoreMapper.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.user; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface SysUserCoreMapper extends BaseMapperX { - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/SysErrorCodeConstants.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/SysErrorCodeConstants.java deleted file mode 100644 index 173287e522..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/SysErrorCodeConstants.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * System 错误码枚举类 - * - * system 系统,使用 1-006-000-000 段 - */ -public interface SysErrorCodeConstants { - - // ========== 短信发送 1006000000 ========== - ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1006000000, "手机号不存在"); - ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1006000001, "模板参数({})缺失"); - ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1006000000, "短信模板不存在"); - - // ========= 文件相关 1006001000================= - ErrorCode FILE_PATH_EXISTS = new ErrorCode(1006001000, "文件路径已存在"); - ErrorCode FILE_NOT_EXISTS = new ErrorCode(1006001002, "文件不存在"); - - // ========== 社交模块 1006002000 ========== - ErrorCode SOCIAL_AUTH_FAILURE = new ErrorCode(1006002000, "社交授权失败,原因是:{}"); - ErrorCode SOCIAL_UNBIND_NOT_SELF = new ErrorCode(1006002001, "社交解绑失败,非当前用户绑定"); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/package-info.java deleted file mode 100644 index 2e18f1adf6..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.coreservice.modules.system.mq.message; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/package-info.java deleted file mode 100644 index 2fe4aa305d..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.coreservice.modules.system.mq.producer; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/sms/SysSmsCoreProducer.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/sms/SysSmsCoreProducer.java deleted file mode 100644 index 9ecf647062..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/sms/SysSmsCoreProducer.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.mq.producer.sms; - -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.List; - -/** - * Sms 短信相关消息的 Core Producer - * - * @author zzf - * @date 2021/3/9 16:35 - */ -@Slf4j -@Component -public class SysSmsCoreProducer { - - @Resource - private RedisMQTemplate redisMQTemplate; - - /** - * 发送 {@link SysSmsSendMessage} 消息 - * - * @param logId 短信日志编号 - * @param mobile 手机号 - * @param channelId 渠道编号 - * @param apiTemplateId 短信模板编号 - * @param templateParams 短信模板参数 - */ - public void sendSmsSendMessage(Long logId, String mobile, - Long channelId, String apiTemplateId, List> templateParams) { - SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile); - message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams); - redisMQTemplate.send(message); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/package-info.java deleted file mode 100644 index 3b87779357..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * system 包下,我们放通用业务,支撑上层的核心业务。 - * 例如说:用户、部门、权限、数据字典等等 - * - * 缩写:sys - */ -package cn.iocoder.yudao.coreservice.modules.system; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/impl/SysUserSessionCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/impl/SysUserSessionCoreServiceImpl.java deleted file mode 100644 index f26c6afc39..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/impl/SysUserSessionCoreServiceImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.auth.impl; - -import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth.SysUserSessionCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; -import cn.iocoder.yudao.framework.security.config.SecurityProperties; -import cn.iocoder.yudao.framework.security.core.LoginUser; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.time.Duration; -import java.util.Date; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; - -/** - * 在线用户 Session Core Service 实现类 - * - * @author 芋道源码 - */ -@Service -public class SysUserSessionCoreServiceImpl implements SysUserSessionCoreService { - - @Resource - private SysUserSessionCoreMapper userSessionCoreMapper; - - @Resource - private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO; - - @Resource - private SecurityProperties securityProperties; - - @Override - public String createUserSession(LoginUser loginUser, String userIp, String userAgent) { - // 生成 Session 编号 - String sessionId = generateSessionId(); - // 写入 Redis 缓存 - loginUser.setUpdateTime(new Date()); - loginUserCoreRedisDAO.set(sessionId, loginUser); - // 写入 DB 中 - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId) - .userId(loginUser.getId()).userType(loginUser.getUserType()) - .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername()) - .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis()))) - .build(); - userSessionCoreMapper.insert(userSession); - // 返回 Session 编号 - return sessionId; - } - - @Override - public void refreshUserSession(String sessionId, LoginUser loginUser) { - // 写入 Redis 缓存 - loginUser.setUpdateTime(new Date()); - loginUserCoreRedisDAO.set(sessionId, loginUser); - // 更新 DB 中 - SysUserSessionDO updateObj = SysUserSessionDO.builder().id(sessionId).build(); - updateObj.setUsername(loginUser.getUsername()); - updateObj.setUpdateTime(new Date()); - updateObj.setSessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis()))); - userSessionCoreMapper.updateById(updateObj); - } - - @Override - public void deleteUserSession(String sessionId) { - // 删除 Redis 缓存 - loginUserCoreRedisDAO.delete(sessionId); - // 删除 DB 记录 - userSessionCoreMapper.deleteById(sessionId); - } - - @Override - public LoginUser getLoginUser(String sessionId) { - return loginUserCoreRedisDAO.get(sessionId); - } - - @Override - public Long getSessionTimeoutMillis() { - return securityProperties.getSessionTimeout().toMillis(); - } - - /** - * 生成 Session 编号,目前采用 UUID 算法 - * - * @return Session 编号 - */ - private static String generateSessionId() { - return IdUtil.fastSimpleUUID(); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreService.java deleted file mode 100644 index d886956219..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreService.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.dict; - -import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService; - -/** - * 字典数据 Service 接口 - * - * @author 芋道源码 - */ -public interface SysDictDataCoreService extends DictDataFrameworkService { - - /** - * 初始化字典数据的本地缓存 - */ - void initLocalCache(); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/impl/SysDictDataCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/impl/SysDictDataCoreServiceImpl.java deleted file mode 100644 index 98607163d2..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/impl/SysDictDataCoreServiceImpl.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.dict.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.coreservice.modules.system.convert.dict.SysDictDataCoreConvert; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict.SysDictDataCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.dict.SysDictDataCoreService; -import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.google.common.collect.ImmutableTable; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -/** - * 字典数据 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Slf4j -public class SysDictDataCoreServiceImpl implements SysDictDataCoreService { - - /** - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 - */ - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; - - /** - * 字典数据缓存,第二个 key 使用 label - * - * key1:字典类型 dictType - * key2:字典标签 label - */ - private ImmutableTable labelDictDataCache; - /** - * 字典数据缓存,第二个 key 使用 value - * - * key1:字典类型 dictType - * key2:字典值 value - */ - private ImmutableTable valueDictDataCache; - /** - * 缓存字典数据的最大更新时间,用于后续的增量轮询,判断是否有更新 - */ - private volatile Date maxUpdateTime; - - @Resource - private SysDictDataCoreMapper dictDataCoreMapper; - - @Override - @PostConstruct - public synchronized void initLocalCache() { - // 获取字典数据列表,如果有更新 - List dataList = this.loadDictDataIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(dataList)) { - return; - } - - // 构建缓存 - ImmutableTable.Builder labelDictDataBuilder = ImmutableTable.builder(); - ImmutableTable.Builder valueDictDataBuilder = ImmutableTable.builder(); - dataList.forEach(dictData -> { - labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData); - valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData); - }); - labelDictDataCache = labelDictDataBuilder.build(); - valueDictDataCache = valueDictDataBuilder.build(); - assert dataList.size() > 0; // 断言,避免告警 - maxUpdateTime = dataList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); - log.info("[initLocalCache][缓存字典数据,数量为:{}]", dataList.size()); - } - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initLocalCache(); - } - - /** - * 如果字典数据发生变化,从数据库中获取最新的全量字典数据。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前字典数据的最大更新时间 - * @return 字典数据列表 - */ - private List loadDictDataIfUpdate(Date maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadDictDataIfUpdate][首次加载全量字典数据]"); - } else { // 判断数据库中是否有更新的字典数据 - if (!dictDataCoreMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) { - return null; - } - log.info("[loadDictDataIfUpdate][增量加载全量字典数据]"); - } - // 第二步,如果有更新,则从数据库加载所有字典数据 - return dictDataCoreMapper.selectList(); - } - - @Override - public DictDataRespDTO getDictDataFromCache(String type, String value) { - return SysDictDataCoreConvert.INSTANCE.convert02(valueDictDataCache.get(type, value)); - } - - @Override - public DictDataRespDTO parseDictDataFromCache(String type, String label) { - return SysDictDataCoreConvert.INSTANCE.convert02(labelDictDataCache.get(type, label)); - } - - @Override - public List listDictDatasFromCache(String type) { - return SysDictDataCoreConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values()); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogCoreService.java deleted file mode 100644 index decc2739e8..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogCoreService.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.logger; - -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; - -/** - * 登录日志 Core Service 接口 - */ -public interface SysLoginLogCoreService { - - /** - * 创建登录日志 - * - * @param reqDTO 日志信息 - */ - void createLoginLog(SysLoginLogCreateReqDTO reqDTO); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/impl/SysLoginLogCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/impl/SysLoginLogCoreServiceImpl.java deleted file mode 100644 index 7c866e8d66..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/impl/SysLoginLogCoreServiceImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.logger.impl; - -import cn.iocoder.yudao.coreservice.modules.system.convert.logger.SysLoginLogCoreConvert; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger.SysLoginLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * 登录日志 Service Core 实现 - * - * @author 芋道源码 - */ -@Service -public class SysLoginLogCoreServiceImpl implements SysLoginLogCoreService { - - @Resource - private SysLoginLogCoreMapper loginLogMapper; - - @Override - public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) { - SysLoginLogDO loginLog = SysLoginLogCoreConvert.INSTANCE.convert(reqDTO); - // 插入 - loginLogMapper.insert(loginLog); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateCoreService.java deleted file mode 100644 index 9a3a16099f..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateCoreService.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; - -import java.util.Map; - -/** - * 短信模板 Core Service 接口 - * - * @author 芋道源码 - */ -public interface SysSmsTemplateCoreService { - - /** - * 初始化短信模板的本地缓存 - */ - void initLocalCache(); - - /** - * 获得短信模板,从缓存中 - * - * @param code 模板编码 - * @return 短信模板 - */ - SysSmsTemplateDO getSmsTemplateByCodeFromCache(String code); - - /** - * 格式化短信内容 - * - * @param content 短信模板的内容 - * @param params 内容的参数 - * @return 格式化后的内容 - */ - String formatSmsTemplateContent(String content, Map params); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsLogCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsLogCoreServiceImpl.java deleted file mode 100644 index de318ed62a..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsLogCoreServiceImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms.impl; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms.SysSmsLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsReceiveStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsSendStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsLogCoreService; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.Map; -import java.util.Objects; - -/** - * 短信日志 Core Service 实现类 - * - * @author zzf - * @date 2021/1/25 9:25 - */ -@Slf4j -@Service -public class SysSmsLogCoreServiceImpl implements SysSmsLogCoreService { - - @Resource - private SysSmsLogCoreMapper smsLogCoreMapper; - - @Override - public Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend, - SysSmsTemplateDO template, String templateContent, Map templateParams) { - SysSmsLogDO.SysSmsLogDOBuilder logBuilder = SysSmsLogDO.builder(); - // 根据是否要发送,设置状态 - logBuilder.sendStatus(Objects.equals(isSend, true) ? SysSmsSendStatusEnum.INIT.getStatus() - : SysSmsSendStatusEnum.IGNORE.getStatus()); - // 设置手机相关字段 - logBuilder.mobile(mobile).userId(userId).userType(userType); - // 设置模板相关字段 - logBuilder.templateId(template.getId()).templateCode(template.getCode()).templateType(template.getType()); - logBuilder.templateContent(templateContent).templateParams(templateParams).apiTemplateId(template.getApiTemplateId()); - // 设置渠道相关字段 - logBuilder.channelId(template.getChannelId()).channelCode(template.getChannelCode()); - // 设置接收相关字段 - logBuilder.receiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus()); - - // 插入数据库 - SysSmsLogDO logDO = logBuilder.build(); - smsLogCoreMapper.insert(logDO); - return logDO.getId(); - } - - @Override - public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, - String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { - SysSmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? SysSmsSendStatusEnum.SUCCESS - : SysSmsSendStatusEnum.FAILURE; - smsLogCoreMapper.updateById(SysSmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()).sendTime(new Date()) - .sendCode(sendCode).sendMsg(sendMsg).apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) - .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); - } - - @Override - public void updateSmsReceiveResult(Long id, Boolean success, Date receiveTime, String apiReceiveCode, String apiReceiveMsg) { - SysSmsReceiveStatusEnum receiveStatus = Objects.equals(success, true) ? SysSmsReceiveStatusEnum.SUCCESS - : SysSmsReceiveStatusEnum.FAILURE; - smsLogCoreMapper.updateById(SysSmsLogDO.builder().id(id).receiveStatus(receiveStatus.getStatus()).receiveTime(receiveTime) - .apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build()); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsTemplateCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsTemplateCoreServiceImpl.java deleted file mode 100644 index aa1a28b388..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsTemplateCoreServiceImpl.java +++ /dev/null @@ -1,105 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms.SysSmsTemplateCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsTemplateCoreService; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import com.google.common.collect.ImmutableMap; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; -import javax.annotation.Resource; -import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * 短信模板 Core Service 接口 - * - * @author 芋道源码 - */ -@Service -@Slf4j -public class SysSmsTemplateCoreServiceImpl implements SysSmsTemplateCoreService { - - /** - * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 - * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 - */ - private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; - - /** - * 短信模板缓存 - * key:短信模板编码 {@link SysSmsTemplateDO#getCode()} - * - * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 - */ - private volatile Map smsTemplateCache; - /** - * 缓存短信模板的最大更新时间,用于后续的增量轮询,判断是否有更新 - */ - private volatile Date maxUpdateTime; - - @Resource - private SysSmsTemplateCoreMapper smsTemplateCoreMapper; - - @Override - @PostConstruct - public void initLocalCache() { - // 获取短信模板列表,如果有更新 - List smsTemplateList = this.loadSmsTemplateIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(smsTemplateList)) { - return; - } - - // 写入缓存 - ImmutableMap.Builder builder = ImmutableMap.builder(); - smsTemplateList.forEach(sysSmsTemplateDO -> builder.put(sysSmsTemplateDO.getCode(), sysSmsTemplateDO)); - smsTemplateCache = builder.build(); - assert smsTemplateList.size() > 0; // 断言,避免告警 - maxUpdateTime = smsTemplateList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); - log.info("[initLocalCache][初始化 SmsTemplate 数量为 {}]", smsTemplateList.size()); - } - - /** - * 如果短信模板发生变化,从数据库中获取最新的全量短信模板。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前短信模板的最大更新时间 - * @return 短信模板列表 - */ - private List loadSmsTemplateIfUpdate(Date maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadSmsTemplateIfUpdate][首次加载全量短信模板]"); - } else { // 判断数据库中是否有更新的短信模板 - if (smsTemplateCoreMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) { - return null; - } - log.info("[loadSmsTemplateIfUpdate][增量加载全量短信模板]"); - } - // 第二步,如果有更新,则从数据库加载所有短信模板 - return smsTemplateCoreMapper.selectList(); - } - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initLocalCache(); - } - - @Override - public SysSmsTemplateDO getSmsTemplateByCodeFromCache(String code) { - return smsTemplateCache.get(code); - } - - @Override - public String formatSmsTemplateContent(String content, Map params) { - return StrUtil.format(content, params); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreService.java deleted file mode 100644 index 17634b320a..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreService.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.social; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import me.zhyd.oauth.model.AuthUser; - -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * 社交 Service 接口,例如说社交平台的授权登录 - * - * @author 芋道源码 - */ -public interface SysSocialCoreService { - - /** - * 获得社交平台的授权 URL - * - * @param type 社交平台的类型 {@link SysSocialTypeEnum} - * @param redirectUri 重定向 URL - * @return 社交平台的授权 URL - */ - String getAuthorizeUrl(Integer type, String redirectUri); - - /** - * 获得授权的用户 - * 如果授权失败,则会抛出 {@link ServiceException} 异常 - * - * @param type 社交平台的类型 {@link SysSocialTypeEnum} - * @param code 授权码 - * @param state state - * @return 授权用户 - */ - @NotNull - AuthUser getAuthUser(Integer type, String code, String state); - - default String getAuthUserUnionId(AuthUser authUser) { - return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid()); - } - - /** - * 获得 unionId 对应的某个社交平台的“所有”社交用户 - * 注意,这里的“所有”,指的是类似【微信】平台,包括了小程序、公众号、PC 网站,他们的 unionId 是一致的 - * - * @param type 社交平台的类型 {@link SysSocialTypeEnum} - * @param unionId 社交平台的 unionId - * @return 社交用户列表 - * @param userTypeEnum 全局用户类型 - */ - List getAllSocialUserList(Integer type, String unionId, UserTypeEnum userTypeEnum); - - /** - * 获得指定用户的社交用户列表 - * - * @param userId 用户编号 - * @return 社交用户列表 - * @param userTypeEnum 全局用户类型 - */ - List getSocialUserList(Long userId, UserTypeEnum userTypeEnum); - - /** - * 绑定社交用户 - * - * @param userId 用户编号 - * @param type 社交平台的类型 {@link SysSocialTypeEnum} - * @param authUser 授权用户 - * @param userTypeEnum 全局用户类型 - */ - void bindSocialUser(Long userId, Integer type, AuthUser authUser, UserTypeEnum userTypeEnum); - - /** - * 取消绑定社交用户 - * - * @param userId 用户编号 - * @param type 社交平台的类型 {@link SysSocialTypeEnum} - * @param unionId 社交平台的 unionId - * @param userTypeEnum 全局用户类型 - */ - void unbindSocialUser(Long userId, Integer type, String unionId, UserTypeEnum userTypeEnum); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/SysTenantCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/SysTenantCoreService.java deleted file mode 100644 index f7bbab6ef8..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/SysTenantCoreService.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.tenant; - -import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; - -/** - * 租户 Service 接口 - * - * @author 芋道源码 - */ -public interface SysTenantCoreService extends TenantFrameworkService { -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/impl/SysTenantCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/impl/SysTenantCoreServiceImpl.java deleted file mode 100644 index 046e4187cb..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/tenant/impl/SysTenantCoreServiceImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.tenant.impl; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.tenant.SysTenantCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.tenant.SysTenantCoreService; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 租户 Service 实现类 - * - * @author 芋道源码 - */ -@Service -public class SysTenantCoreServiceImpl implements SysTenantCoreService { - - @Resource - private SysTenantCoreMapper tenantCoreMapper; - - @Override - public List getTenantIds() { - List tenants = tenantCoreMapper.selectList(); - return CollectionUtils.convertList(tenants, SysTenantDO::getId); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/SysUserCoreService.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/SysUserCoreService.java deleted file mode 100644 index bc95e343e3..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/SysUserCoreService.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.user; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; - -/** - * 后台用户 Service Core 接口 - * - * @author 芋道源码 - */ -public interface SysUserCoreService { - - /** - * 通过用户 ID 查询用户 - * - * @param id 用户ID - * @return 用户对象信息 - */ - SysUserDO getUser(Long id); - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/impl/SysUserCoreServiceImpl.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/impl/SysUserCoreServiceImpl.java deleted file mode 100644 index ff203bdc44..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/user/impl/SysUserCoreServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.user.impl; - -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.user.SysUserCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * 后台用户 Service Core 实现 - * - * @author 芋道源码 - */ -@Service -public class SysUserCoreServiceImpl implements SysUserCoreService { - - @Resource - private SysUserCoreMapper userCoreMapper; - - @Override - public SysUserDO getUser(Long id) { - return userCoreMapper.selectById(id); - } - -} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/tool/package-info.java b/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/tool/package-info.java deleted file mode 100644 index dd3c3e9138..0000000000 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/tool/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * tool 包下,我们放研发工具,提升研发效率与质量。 - * 例如说:代码生成器、接口文档等等 - * - * 缩写:tool - */ -package cn.iocoder.yudao.coreservice.modules.tool; diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java b/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java deleted file mode 100644 index 13b4863a5b..0000000000 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service; diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreServiceTest.java deleted file mode 100644 index ce3d693959..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreServiceTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.file; - -import cn.hutool.core.io.resource.ResourceUtil; -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.impl.InfFileCoreServiceImpl; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.FILE_NOT_EXISTS; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; -import static org.junit.jupiter.api.Assertions.*; - -@Import({InfFileCoreServiceImpl.class, FileProperties.class}) -public class InfFileCoreServiceTest extends BaseDbUnitTest { - - @Resource - private InfFileCoreService fileCoreService; - - @MockBean - private FileProperties fileProperties; - - @Resource - private InfFileCoreMapper fileMapper; - - @Test - public void testCreateFile_success() { - // 准备参数 - String path = randomString(); - byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - - // 调用 - String url = fileCoreService.createFile(path, content); - // 断言 - assertEquals(fileProperties.getBasePath() + path, url); - // 校验数据 - InfFileDO file = fileMapper.selectById(path); - assertEquals(path, file.getId()); - assertEquals("jpg", file.getType()); - assertArrayEquals(content, file.getContent()); - } - - @Test - public void testCreateFile_exists() { - // mock 数据 - InfFileDO dbFile = randomPojo(InfFileDO.class); - fileMapper.insert(dbFile); - // 准备参数 - String path = dbFile.getId(); // 模拟已存在 - byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - - // 调用,并断言异常 - assertServiceException(() -> fileCoreService.createFile(path, content), FILE_PATH_EXISTS); - } - - @Test - public void testDeleteFile_success() { - // mock 数据 - InfFileDO dbFile = randomPojo(InfFileDO.class); - fileMapper.insert(dbFile);// @Sql: 先插入出一条存在的数据 - // 准备参数 - String id = dbFile.getId(); - - // 调用 - fileCoreService.deleteFile(id); - // 校验数据不存在了 - assertNull(fileMapper.selectById(id)); - } - - @Test - public void testDeleteFile_notExists() { - // 准备参数 - String id = randomString(); - - // 调用, 并断言异常 - assertServiceException(() -> fileCoreService.deleteFile(id), FILE_NOT_EXISTS); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreServiceTest.java deleted file mode 100644 index c7b2620eb0..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiAccessLogCoreServiceTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger; - -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiAccessLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl.InfApiAccessLogCoreServiceImpl; -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * {@link InfApiAccessLogCoreServiceImpl} 单元测试 - */ -@Import(InfApiAccessLogCoreServiceImpl.class) -public class InfApiAccessLogCoreServiceTest extends BaseDbUnitTest { - - @Resource - private InfApiAccessLogCoreService apiAccessLogCoreService; - - @Resource - private InfApiAccessLogCoreMapper apiAccessLogCoreMapper; - - @Test - public void testCreateApiAccessLogAsync() { - // 准备参数 - ApiAccessLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiAccessLogCreateReqDTO.class, - dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue())); - - // 调用 - apiAccessLogCoreService.createApiAccessLogAsync(createDTO); - // 断言 - InfApiAccessLogDO infApiAccessLogDO = apiAccessLogCoreMapper.selectOne(null); - assertNotNull(infApiAccessLogDO); - assertPojoEquals(createDTO, infApiAccessLogDO); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreServiceTest.java deleted file mode 100644 index 6379ab32a1..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/logger/InfApiErrorLogCoreServiceTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.logger; - -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiErrorLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl.InfApiErrorLogCoreServiceImpl; -import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * {@link InfApiErrorLogCoreServiceImpl} 单元测试 - */ -@Import(InfApiErrorLogCoreServiceImpl.class) -public class InfApiErrorLogCoreServiceTest extends BaseDbUnitTest { - - @Resource - private InfApiErrorLogCoreService apiErrorLogCoreService; - - @Resource - private InfApiErrorLogCoreMapper infApiErrorLogCoreMapper; - - @Test - public void testCreateApiErrorLogAsync() { - // 准备参数 - ApiErrorLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiErrorLogCreateReqDTO.class, - dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue())); - - // 调用 - apiErrorLogCoreService.createApiErrorLogAsync(createDTO); - // 断言 - InfApiErrorLogDO infApiErrorLogDO = infApiErrorLogCoreMapper.selectOne(null); - assertNotNull(infApiErrorLogDO); - assertPojoEquals(createDTO, infApiErrorLogDO); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/package-info.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/package-info.java deleted file mode 100644 index c3da3526cf..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/infra/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service; diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreServiceTest.java deleted file mode 100644 index d8aada3588..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreServiceTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.auth; - -import cn.iocoder.yudao.coreservice.BaseDbAndRedisUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth.SysUserSessionCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.impl.SysUserSessionCoreServiceImpl; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.security.config.SecurityProperties; -import cn.iocoder.yudao.framework.security.core.LoginUser; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.time.Duration; -import java.util.Date; - -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - -@Import({SysUserSessionCoreServiceImpl.class, SysLoginUserCoreRedisDAO.class}) -public class SysUserSessionCoreServiceTest extends BaseDbAndRedisUnitTest { - - @Resource - private SysUserSessionCoreServiceImpl userSessionCoreService; - - @Resource - private SysUserSessionCoreMapper userSessionCoreMapper; - @Resource - private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO; - - @MockBean - private SecurityProperties securityProperties; - - @Test - public void testCreateUserSession_success() { - // 准备参数 - String userIp = randomString(); - String userAgent = randomString(); - LoginUser loginUser = randomPojo(LoginUser.class, o -> { - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); - o.setTenantId(0L); // 租户设置为 0,因为暂未启用多租户组件 - }); - // mock 方法 - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); - - // 调用 - String sessionId = userSessionCoreService.createUserSession(loginUser, userIp, userAgent); - // 校验 SysUserSessionDO 记录 - SysUserSessionDO userSessionDO = userSessionCoreMapper.selectById(sessionId); - assertPojoEquals(loginUser, userSessionDO, "id", "updateTime"); - assertEquals(sessionId, userSessionDO.getId()); - assertEquals(userIp, userSessionDO.getUserIp()); - assertEquals(userAgent, userSessionDO.getUserAgent()); - // 校验 LoginUser 缓存 - LoginUser redisLoginUser = loginUserCoreRedisDAO.get(sessionId); - assertPojoEquals(loginUser, redisLoginUser, "username", "password"); - } - - @Test - public void testCreateRefreshUserSession_success() { - // 准备参数 - String sessionId = randomString(); - String userIp = randomString(); - String userAgent = randomString(); - long timeLong = randomLongId(); - String userName = randomString(); - Date date = randomDate(); - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue())); - // mock 方法 - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); - // mock 数据 - loginUser.setUpdateTime(date); - loginUserCoreRedisDAO.set(sessionId, loginUser); - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId) - .userId(loginUser.getId()).userType(loginUser.getUserType()) - .userIp(userIp).userAgent(userAgent).username(userName) - .sessionTimeout(addTime(Duration.ofMillis(timeLong))) - .build(); - userSessionCoreMapper.insert(userSession); - - // 调用 - userSessionCoreService.refreshUserSession(sessionId, loginUser); - // 校验 LoginUser 缓存 - LoginUser redisLoginUser = loginUserCoreRedisDAO.get(sessionId); - assertNotEquals(redisLoginUser.getUpdateTime(), date); - // 校验 SysUserSessionDO 记录 - SysUserSessionDO updateDO = userSessionCoreMapper.selectById(sessionId); - assertEquals(updateDO.getUsername(), loginUser.getUsername()); - assertNotEquals(updateDO.getUpdateTime(), userSession.getUpdateTime()); - assertNotEquals(updateDO.getSessionTimeout(), addTime(Duration.ofMillis(timeLong))); - } - - @Test - public void testDeleteUserSession_success() { - // 准备参数 - String sessionId = randomString(); - String userIp = randomString(); - String userAgent = randomString(); - Long timeLong = randomLongId(); - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue())); - // mock 存入 Redis - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); - // mock 数据 - loginUserCoreRedisDAO.set(sessionId, loginUser); - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId) - .userId(loginUser.getId()).userType(loginUser.getUserType()) - .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername()) - .sessionTimeout(addTime(Duration.ofMillis(timeLong))) - .build(); - userSessionCoreMapper.insert(userSession); - - // 调用 - userSessionCoreService.deleteUserSession(sessionId); - // 校验数据不存在了 - assertNull(loginUserCoreRedisDAO.get(sessionId)); - assertNull(userSessionCoreMapper.selectById(sessionId)); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreServiceTest.java deleted file mode 100644 index 410c592f59..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/dict/SysDictDataCoreServiceTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.dict; - -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict.SysDictDataCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.service.dict.impl.SysDictDataCoreServiceImpl; -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import com.google.common.collect.ImmutableTable; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.function.Consumer; - -import static cn.hutool.core.bean.BeanUtil.getFieldValue; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomCommonStatus; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** -* {@link SysDictDataCoreServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysDictDataCoreServiceImpl.class) -public class SysDictDataCoreServiceTest extends BaseDbUnitTest { - - @Resource - private SysDictDataCoreServiceImpl dictDataCoreService; - - @Resource - private SysDictDataCoreMapper dictDataMapper; - - /** - * 测试加载到新的字典数据的情况 - */ - @Test - @SuppressWarnings("unchecked") - public void testInitLocalCache() { - // mock 数据 - SysDictDataDO dictData01 = randomDictDataDO(); - dictDataMapper.insert(dictData01); - SysDictDataDO dictData02 = randomDictDataDO(); - dictDataMapper.insert(dictData02); - - // 调用 - dictDataCoreService.initLocalCache(); - // 断言 labelDictDataCache 缓存 - ImmutableTable labelDictDataCache = - (ImmutableTable) getFieldValue(dictDataCoreService, "labelDictDataCache"); - assertEquals(2, labelDictDataCache.size()); - assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel())); - assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel())); - // 断言 valueDictDataCache 缓存 - ImmutableTable valueDictDataCache = - (ImmutableTable) getFieldValue(dictDataCoreService, "valueDictDataCache"); - assertEquals(2, valueDictDataCache.size()); - assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue())); - assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue())); - // 断言 maxUpdateTime 缓存 - Date maxUpdateTime = (Date) getFieldValue(dictDataCoreService, "maxUpdateTime"); - assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime); - } - - // ========== 随机对象 ========== - - @SafeVarargs - private static SysDictDataDO randomDictDataDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setStatus(randomCommonStatus()); // 保证 status 的范围 - }; - return randomPojo(SysDictDataDO.class, ArrayUtils.append(consumer, consumers)); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogServiceImplTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogServiceImplTest.java deleted file mode 100644 index 1da56c2644..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/SysLoginLogServiceImplTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.logger; - -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger.SysLoginLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.impl.SysLoginLogCoreServiceImpl; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; - -@Import(SysLoginLogCoreServiceImpl.class) -public class SysLoginLogServiceImplTest extends BaseDbUnitTest { - - @Resource - private SysLoginLogCoreServiceImpl loginLogCoreService; - - @Resource - private SysLoginLogCoreMapper loginLogCoreMapper; - - @Test - public void testCreateLoginLog() { - SysLoginLogCreateReqDTO reqDTO = RandomUtils.randomPojo(SysLoginLogCreateReqDTO.class, vo -> { - // 指定随机的范围,避免超出范围入库失败 - vo.setUserType(randomEle(UserTypeEnum.values()).getValue()); - vo.setLogType(randomEle(SysLoginLogTypeEnum.values()).getType()); - vo.setResult(randomEle(SysLoginResultEnum.values()).getResult()); - vo.setTraceId(TracerUtils.getTraceId()); - }); - - // 调用 - loginLogCoreService.createLoginLog(reqDTO); - // 断言,忽略基本字段 - SysLoginLogDO sysLoginLogDO = loginLogCoreMapper.selectOne(null); - assertPojoEquals(reqDTO, sysLoginLogDO); - } - -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/package-info.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/package-info.java deleted file mode 100644 index 8b5f8b0109..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service; diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreServiceTest.java deleted file mode 100644 index 896f0c6d3e..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreServiceTest.java +++ /dev/null @@ -1,149 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; - -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms.SysSmsLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsReceiveStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsSendStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsTemplateTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.impl.SysSmsLogCoreServiceImpl; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.Map; -import java.util.function.Consumer; - -import static cn.hutool.core.util.RandomUtil.randomBoolean; -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** -* {@link SysSmsLogCoreServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysSmsLogCoreServiceImpl.class) -public class SysSmsLogCoreServiceTest extends BaseDbUnitTest { - - @Resource - private SysSmsLogCoreServiceImpl smsLogCoreService; - - @Resource - private SysSmsLogCoreMapper smsLogCoreMapper; - - @Test - public void testCreateSmsLog() { - // 准备参数 - String mobile = randomString(); - Long userId = randomLongId(); - Integer userType = randomEle(UserTypeEnum.values()).getValue(); - Boolean isSend = randomBoolean(); - SysSmsTemplateDO templateDO = randomPojo(SysSmsTemplateDO.class, - o -> o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType())); - String templateContent = randomString(); - Map templateParams = randomTemplateParams(); - // mock 方法 - - // 调用 - Long logId = smsLogCoreService.createSmsLog(mobile, userId, userType, isSend, - templateDO, templateContent, templateParams); - // 断言 - SysSmsLogDO logDO = smsLogCoreMapper.selectById(logId); - assertEquals(isSend ? SysSmsSendStatusEnum.INIT.getStatus() : SysSmsSendStatusEnum.IGNORE.getStatus(), - logDO.getSendStatus()); - assertEquals(mobile, logDO.getMobile()); - assertEquals(userType, logDO.getUserType()); - assertEquals(userId, logDO.getUserId()); - assertEquals(templateDO.getId(), logDO.getTemplateId()); - assertEquals(templateDO.getCode(), logDO.getTemplateCode()); - assertEquals(templateDO.getType(), logDO.getTemplateType()); - assertEquals(templateDO.getChannelId(), logDO.getChannelId()); - assertEquals(templateDO.getChannelCode(), logDO.getChannelCode()); - assertEquals(templateContent, logDO.getTemplateContent()); - assertEquals(templateParams, logDO.getTemplateParams()); - assertEquals(SysSmsReceiveStatusEnum.INIT.getStatus(), logDO.getReceiveStatus()); - } - - @Test - public void testUpdateSmsSendResult() { - // mock 数据 - SysSmsLogDO dbSmsLog = randomSmsLogDO( - o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())); - smsLogCoreMapper.insert(dbSmsLog); - // 准备参数 - Long id = dbSmsLog.getId(); - Integer sendCode = randomInteger(); - String sendMsg = randomString(); - String apiSendCode = randomString(); - String apiSendMsg = randomString(); - String apiRequestId = randomString(); - String apiSerialNo = randomString(); - - // 调用 - smsLogCoreService.updateSmsSendResult(id, sendCode, sendMsg, - apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); - // 断言 - dbSmsLog = smsLogCoreMapper.selectById(id); - assertEquals(CommonResult.isSuccess(sendCode) ? SysSmsSendStatusEnum.SUCCESS.getStatus() - : SysSmsSendStatusEnum.FAILURE.getStatus(), dbSmsLog.getSendStatus()); - assertNotNull(dbSmsLog.getSendTime()); - assertEquals(sendMsg, dbSmsLog.getSendMsg()); - assertEquals(apiSendCode, dbSmsLog.getApiSendCode()); - assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg()); - assertEquals(apiRequestId, dbSmsLog.getApiRequestId()); - assertEquals(apiSerialNo, dbSmsLog.getApiSerialNo()); - } - - @Test - public void testUpdateSmsReceiveResult() { - // mock 数据 - SysSmsLogDO dbSmsLog = randomSmsLogDO( - o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.INIT.getStatus())); - smsLogCoreMapper.insert(dbSmsLog); - // 准备参数 - Long id = dbSmsLog.getId(); - Boolean success = randomBoolean(); - Date receiveTime = randomDate(); - String apiReceiveCode = randomString(); - String apiReceiveMsg = randomString(); - - // 调用 - smsLogCoreService.updateSmsReceiveResult(id, success, receiveTime, apiReceiveCode, apiReceiveMsg); - // 断言 - dbSmsLog = smsLogCoreMapper.selectById(id); - assertEquals(success ? SysSmsReceiveStatusEnum.SUCCESS.getStatus() - : SysSmsReceiveStatusEnum.FAILURE.getStatus(), dbSmsLog.getReceiveStatus()); - assertEquals(receiveTime, dbSmsLog.getReceiveTime()); - assertEquals(apiReceiveCode, dbSmsLog.getApiReceiveCode()); - assertEquals(apiReceiveMsg, dbSmsLog.getApiReceiveMsg()); - } - - // ========== 随机对象 ========== - - @SafeVarargs - private static SysSmsLogDO randomSmsLogDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setTemplateParams(randomTemplateParams()); - o.setTemplateType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 templateType 的范围 - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); // 保证 userType 的范围 - o.setSendStatus(randomEle(SysSmsSendStatusEnum.values()).getStatus()); // 保证 sendStatus 的范围 - o.setReceiveStatus(randomEle(SysSmsReceiveStatusEnum.values()).getStatus()); // 保证 receiveStatus 的范围 - }; - return randomPojo(SysSmsLogDO.class, ArrayUtils.append(consumer, consumers)); - } - - - private static Map randomTemplateParams() { - return MapUtil.builder().put(randomString(), randomString()) - .put(randomString(), randomString()).build(); - } -} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateServiceTest.java b/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateServiceTest.java deleted file mode 100644 index 1bcdb442de..0000000000 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsTemplateServiceTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; - -import cn.iocoder.yudao.coreservice.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.sms.SysSmsTemplateCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsTemplateTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.impl.SysSmsTemplateCoreServiceImpl; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.util.Date; -import java.util.Map; -import java.util.function.Consumer; - -import static cn.hutool.core.bean.BeanUtil.getFieldValue; -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** -* {@link SysSmsTemplateCoreServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysSmsTemplateCoreServiceImpl.class) -public class SysSmsTemplateServiceTest extends BaseDbUnitTest { - - @Resource - private SysSmsTemplateCoreServiceImpl smsTemplateCoreService; - - @Resource - private SysSmsTemplateCoreMapper smsTemplateCoreMapper; - - @Test - @SuppressWarnings("unchecked") - void testInitLocalCache() { - // mock 数据 - SysSmsTemplateDO smsTemplate01 = randomSmsTemplateDO(); - smsTemplateCoreMapper.insert(smsTemplate01); - SysSmsTemplateDO smsTemplate02 = randomSmsTemplateDO(); - smsTemplateCoreMapper.insert(smsTemplate02); - - // 调用 - smsTemplateCoreService.initLocalCache(); - // 断言 deptCache 缓存 - Map smsTemplateCache = (Map) getFieldValue(smsTemplateCoreService, "smsTemplateCache"); - assertEquals(2, smsTemplateCache.size()); - assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode())); - assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode())); - // 断言 maxUpdateTime 缓存 - Date maxUpdateTime = (Date) getFieldValue(smsTemplateCoreService, "maxUpdateTime"); - assertEquals(max(smsTemplate01.getUpdateTime(), smsTemplate02.getUpdateTime()), maxUpdateTime); - } - - // ========== 随机对象 ========== - - @SafeVarargs - private static SysSmsTemplateDO randomSmsTemplateDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 - }; - return randomPojo(SysSmsTemplateDO.class, ArrayUtils.append(consumer, consumers)); - } - -} diff --git a/yudao-core-service/src/test/resources/application.yaml b/yudao-core-service/src/test/resources/application.yaml deleted file mode 100644 index 4db8b273cd..0000000000 --- a/yudao-core-service/src/test/resources/application.yaml +++ /dev/null @@ -1,35 +0,0 @@ -spring: - application: - name: yudao-core-service - - # Jackson 配置项 - jackson: - serialization: - write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 - write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 - write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 - fail-on-empty-beans: false # 允许序列化无属性的 Bean - -# MyBatis Plus 的配置项 -mybatis-plus: - configuration: - map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 - global-config: - db-config: - id-type: AUTO # 自增 ID - logic-delete-value: 1 # 逻辑已删除值(默认为 1) - logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) - mapper-locations: classpath*:mapper/*.xml - type-aliases-package: ${yudao.core-service.base-package}.modules.*.dal.dataobject - ---- #################### 芋道相关配置 #################### - -yudao: - info: - version: 1.0.0 - base-package: cn.iocoder.yudao.coreservice - core-service: - base-package: cn.iocoder.yudao.coreservice - -debug: false diff --git a/yudao-core-service/src/test/resources/sql/clean.sql b/yudao-core-service/src/test/resources/sql/clean.sql deleted file mode 100644 index b11f374ef9..0000000000 --- a/yudao-core-service/src/test/resources/sql/clean.sql +++ /dev/null @@ -1,11 +0,0 @@ --- inf 开头的 DB -DELETE FROM "inf_api_access_log"; -DELETE FROM "inf_file"; -DELETE FROM "inf_api_error_log"; - --- sys 开头的 DB -DELETE FROM "sys_user_session"; -DELETE FROM "sys_dict_data"; -DELETE FROM "sys_sms_template"; -DELETE FROM "sys_sms_log"; -DELETE FROM "sys_social_user"; diff --git a/yudao-core-service/src/test/resources/sql/create_tables.sql b/yudao-core-service/src/test/resources/sql/create_tables.sql deleted file mode 100644 index 633c0d9368..0000000000 --- a/yudao-core-service/src/test/resources/sql/create_tables.sql +++ /dev/null @@ -1,199 +0,0 @@ --- inf 开头的 DB - -CREATE TABLE IF NOT EXISTS "inf_file" ( - "id" varchar(188) NOT NULL, - "type" varchar(63) DEFAULT NULL, - "content" blob NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY ("id") -) COMMENT '文件表'; - --- sys 开头的 DB - -CREATE TABLE IF NOT EXISTS `sys_user_session` ( - `id` varchar(32) NOT NULL, - `user_id` bigint DEFAULT NULL, - "user_type" tinyint NOT NULL, - `username` varchar(50) NOT NULL DEFAULT '', - `user_ip` varchar(50) DEFAULT NULL, - `user_agent` varchar(512) DEFAULT NULL, - `session_timeout` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updater` varchar(64) DEFAULT '' , - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY (`id`) -) COMMENT '用户在线 Session'; - -CREATE TABLE IF NOT EXISTS "sys_dict_data" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "sort" int NOT NULL DEFAULT '0', - "label" varchar(100) NOT NULL DEFAULT '', - "value" varchar(100) NOT NULL DEFAULT '', - "dict_type" varchar(100) NOT NULL DEFAULT '', - "status" tinyint NOT NULL DEFAULT '0', - "remark" varchar(500) DEFAULT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '字典数据表'; - -CREATE TABLE IF NOT EXISTS "inf_api_access_log" ( - "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, - "trace_id" varchar(64) not null default '', - "user_id" bigint not null default '0', - "user_type" tinyint not null default '0', - "application_name" varchar(50) not null, - "request_method" varchar(16) not null default '', - "request_url" varchar(255) not null default '', - "request_params" varchar(8000) not null default '', - "user_ip" varchar(50) not null, - "user_agent" varchar(512) not null, - "begin_time" timestamp not null, - "end_time" timestamp not null, - "duration" integer not null, - "result_code" integer not null default '0', - "result_msg" varchar(512) default '', - "creator" varchar(64) default '', - "create_time" timestamp not null default current_timestamp, - "updater" varchar(64) default '', - "update_time" timestamp not null default current_timestamp, - "deleted" bit not null default false, - "tenant_id" bigint not null default '0', - primary key ("id") -) COMMENT 'API 访问日志表'; - -CREATE TABLE IF NOT EXISTS "inf_api_error_log" ( - "id" integer not null GENERATED BY DEFAULT AS IDENTITY, - "trace_id" varchar(64) not null, - "user_id" bigint not null default '0', - "user_type" tinyint not null default '0', - "application_name" varchar(50) not null, - "request_method" varchar(16) not null, - "request_url" varchar(255) not null, - "request_params" varchar(8000) not null, - "user_ip" varchar(50) not null, - "user_agent" varchar(512) not null, - "exception_time" timestamp not null, - "exception_name" varchar(128) not null default '', - "exception_message" clob not null, - "exception_root_cause_message" clob not null, - "exception_stack_trace" clob not null, - "exception_class_name" varchar(512) not null, - "exception_file_name" varchar(512) not null, - "exception_method_name" varchar(512) not null, - "exception_line_number" integer not null, - "process_status" tinyint not null, - "process_time" timestamp default null, - "process_user_id" bigint default '0', - "creator" varchar(64) default '', - "create_time" timestamp not null default current_timestamp, - "updater" varchar(64) default '', - "update_time" timestamp not null default current_timestamp, - "deleted" bit not null default false, - "tenant_id" bigint not null default '0', - primary key ("id") -) COMMENT '系统异常日志'; - -CREATE TABLE IF NOT EXISTS "sys_sms_template" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "type" tinyint NOT NULL, - "status" tinyint NOT NULL, - "code" varchar(63) NOT NULL, - "name" varchar(63) NOT NULL, - "content" varchar(255) NOT NULL, - "params" varchar(255) NOT NULL, - "remark" varchar(255) DEFAULT NULL, - "api_template_id" varchar(63) NOT NULL, - "channel_id" bigint NOT NULL, - "channel_code" varchar(63) NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '短信模板'; - -CREATE TABLE IF NOT EXISTS "sys_sms_log" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "channel_id" bigint NOT NULL, - "channel_code" varchar(63) NOT NULL, - "template_id" bigint NOT NULL, - "template_code" varchar(63) NOT NULL, - "template_type" tinyint NOT NULL, - "template_content" varchar(255) NOT NULL, - "template_params" varchar(255) NOT NULL, - "api_template_id" varchar(63) NOT NULL, - "mobile" varchar(11) NOT NULL, - "user_id" bigint DEFAULT '0', - "user_type" tinyint DEFAULT '0', - "send_status" tinyint NOT NULL DEFAULT '0', - "send_time" timestamp DEFAULT NULL, - "send_code" int DEFAULT NULL, - "send_msg" varchar(255) DEFAULT NULL, - "api_send_code" varchar(63) DEFAULT NULL, - "api_send_msg" varchar(255) DEFAULT NULL, - "api_request_id" varchar(255) DEFAULT NULL, - "api_serial_no" varchar(255) DEFAULT NULL, - "receive_status" tinyint NOT NULL DEFAULT '0', - "receive_time" timestamp DEFAULT NULL, - "api_receive_code" varchar(63) DEFAULT NULL, - "api_receive_msg" varchar(255) DEFAULT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY ("id") -) COMMENT '短信日志'; - -CREATE TABLE IF NOT EXISTS `sys_login_log` ( - `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `log_type` bigint(4) NOT NULL, - "user_id" bigint not null default '0', - "user_type" tinyint NOT NULL, - `trace_id` varchar(64) NOT NULL DEFAULT '', - `username` varchar(50) NOT NULL DEFAULT '', - `result` tinyint(4) NOT NULL, - `user_ip` varchar(50) NOT NULL, - `user_agent` varchar(512) NOT NULL, - `creator` varchar(64) DEFAULT '', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updater` varchar(64) DEFAULT '', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `deleted` bit(1) NOT NULL DEFAULT '0', - "tenant_id" bigint not null default '0', - PRIMARY KEY (`id`) -) COMMENT ='系统访问记录'; - -CREATE TABLE IF NOT EXISTS "sys_social_user" ( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "user_id" bigint NOT NULL, - "user_type" tinyint NOT NULL DEFAULT '0', - "type" tinyint NOT NULL, - "openid" varchar(32) NOT NULL, - "token" varchar(256) DEFAULT NULL, - "union_id" varchar(32) NOT NULL, - "raw_token_info" varchar(1024) NOT NULL, - "nickname" varchar(32) NOT NULL, - "avatar" varchar(255) DEFAULT NULL, - "raw_user_info" varchar(1024) NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '社交用户'; diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 5e057116e8..4b994eab72 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,9 +14,9 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.3.0-snapshot + 1.4.0-snapshot - 2.4.12 + 2.5.9 3.0.2 1.5.22 @@ -35,14 +35,15 @@ 1.7.0 8.7.0 - 2.3.1 + 2.6.2 0.31.0 7.2.6.RELEASE 0.1.16 - 3.6.28 + 3.9.0 7.1.0.M6 + 6.7.0 1.18.20 1.4.1.Final @@ -77,11 +78,6 @@ - - cn.iocoder.boot - yudao-core-service - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog @@ -397,6 +393,24 @@ ${activiti.version} + + cn.iocoder.boot + yudao-spring-boot-starter-activiti + ${revision} + + + + org.flowable + flowable-spring-boot-starter-basic + ${flowable.version} + + + org.flowable + flowable-spring-boot-starter-actuator + ${flowable.version} + + + cn.iocoder.boot @@ -454,6 +468,12 @@ cn.smallbun.screw screw-core ${screw.version} + + + org.freemarker + freemarker + + @@ -504,13 +524,6 @@ ${justauth.version} - - - cn.iocoder.boot - yudao-spring-boot-starter-activiti - ${revision} - - diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/UserTypeEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/UserTypeEnum.java index 7318fb045b..c950c529db 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/UserTypeEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/UserTypeEnum.java @@ -1,18 +1,24 @@ package cn.iocoder.yudao.framework.common.enums; +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 全局用户类型枚举 */ @AllArgsConstructor @Getter -public enum UserTypeEnum { +public enum UserTypeEnum implements IntArrayValuable { MEMBER(1, "会员"), // 面向 c 端,普通用户 ADMIN(2, "管理员"); // 面向 b 端,管理后台 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray(); + /** * 类型 */ @@ -22,4 +28,12 @@ public enum UserTypeEnum { */ private final String name; + public static UserTypeEnum valueOf(Integer value) { + return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values()); + } + + @Override + public int[] array() { + return ARRAYS; + } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java index a7f23a3912..cb5dc0d005 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java @@ -4,6 +4,7 @@ import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; @@ -81,6 +82,12 @@ public class OperateLogAspect { } private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { + // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 + Integer userType = WebFrameworkUtils.getLoginUserType(); + if (!Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) { + return joinPoint.proceed(); + } + // 记录开始时间 Date startTime = new Date(); try { @@ -149,6 +156,7 @@ public class OperateLogAspect { private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + operateLogDTO.setUserType(WebFrameworkUtils.getLoginUserType()); } private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java index 1c8f49a264..d676001f28 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java @@ -21,6 +21,9 @@ public class OperateLogCreateReqDTO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "用户编号不能为空") private Long userId; + @ApiModelProperty(value = "用户类型", required = true, example = "1") + @NotNull(message = "用户类型不能为空") + private Integer userType; @ApiModelProperty(value = "操作模块", required = true, example = "订单") @NotEmpty(message = "操作模块不能为空") diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java index 418676fca2..f8a4971a14 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java @@ -17,10 +17,7 @@ import lombok.Getter; @AllArgsConstructor public enum PayChannelEnum { - /** - * 公众号网页 - */ - WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), + WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), // 公众号网页 WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class), WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class), @@ -34,16 +31,16 @@ public enum PayChannelEnum { *

* 参考 https://www.pingxx.com/api/支付渠道属性值.html */ - private String code; + private final String code; /** * 名字 */ - private String name; + private final String name; /** * 配置类 */ - private Class configClass; + private final Class configClass; /** * 微信支付 @@ -58,6 +55,6 @@ public enum PayChannelEnum { public static PayChannelEnum getByCode(String code) { return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); } - + } diff --git a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/yudao/framework/apollo/internals/DBConfigRepository.java b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/yudao/framework/apollo/internals/DBConfigRepository.java index c88038da97..08573d33d6 100644 --- a/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/yudao/framework/apollo/internals/DBConfigRepository.java +++ b/yudao-framework/yudao-spring-boot-starter-config/src/main/java/cn/iocoder/yudao/framework/apollo/internals/DBConfigRepository.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.function.Predicate; @Slf4j public class DBConfigRepository extends AbstractConfigRepository { @@ -135,7 +136,7 @@ public class DBConfigRepository extends AbstractConfigRepository { private Properties buildProperties(List configs) { Properties properties = propertiesFactory.getPropertiesInstance(); - configs.stream().filter(ConfigRespDTO::getDeleted) // 过滤掉被删除的配置 + configs.stream().filter(config -> !config.getDeleted()) // 过滤掉被删除的配置 .forEach(config -> properties.put(config.getKey(), config.getValue())); return properties; } diff --git a/yudao-framework/yudao-spring-boot-starter-job/pom.xml b/yudao-framework/yudao-spring-boot-starter-job/pom.xml index 4a1cd04a6b..b9c030d2a3 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-job/pom.xml @@ -35,6 +35,8 @@ jakarta.validation jakarta.validation-api + + diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java index b03fc58e4c..f8eeeef87e 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java @@ -15,7 +15,7 @@ import org.springframework.context.annotation.Configuration; * @author 芋道源码 */ @Configuration -@MapperScan(value = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"}, annotationClass = Mapper.class, +@MapperScan(value = "${yudao.info.base-package}", annotationClass = Mapper.class, lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试 public class YudaoMybatisAutoConfiguration { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/SqlConstants.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/SqlConstants.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/SqlConstants.java rename to yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/SqlConstants.java index a33b1b854c..cad1d6c966 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/SqlConstants.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/SqlConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums; +package cn.iocoder.yudao.framework.mybatis.core.enums; /** * SQL相关常量类 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java new file mode 100644 index 0000000000..5c86290761 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.framework.security.config; + +import cn.iocoder.yudao.framework.web.config.WebProperties; +import org.springframework.core.Ordered; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; + +import javax.annotation.Resource; + +/** + * 自定义的 URL 的安全配置 + * 目的:每个 Maven Module 可以自定义规则! + * + * @author 芋道源码 + */ +public abstract class AuthorizeRequestsCustomizer + implements Customizer.ExpressionInterceptUrlRegistry>, Ordered { + + @Resource + private WebProperties webProperties; + + protected String buildAdminApi(String url) { + return webProperties.getAdminApi().getPrefix() + url; + } + + protected String buildAppApi(String url) { + return webProperties.getAppApi().getPrefix() + url; + } + + @Override + public int getOrder() { + return 0; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index 684cfed9a4..d5953823a2 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.framework.security.config; import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy; import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter; import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -20,6 +22,7 @@ import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; +import java.util.List; /** * Spring Security 自动配置类,主要用于相关组件的配置 @@ -29,7 +32,7 @@ import javax.annotation.Resource; * * @author 芋道源码 */ -@Configuration +@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(SecurityProperties.class) public class YudaoSecurityAutoConfiguration { @@ -64,8 +67,8 @@ public class YudaoSecurityAutoConfiguration { * 退出处理类 Bean */ @Bean - public LogoutSuccessHandler logoutSuccessHandler(SecurityAuthFrameworkService securityFrameworkService) { - return new LogoutSuccessHandlerImpl(securityProperties, securityFrameworkService); + public LogoutSuccessHandler logoutSuccessHandler(MultiUserDetailsAuthenticationProvider authenticationProvider) { + return new LogoutSuccessHandlerImpl(securityProperties, authenticationProvider); } /** @@ -83,9 +86,19 @@ public class YudaoSecurityAutoConfiguration { * Token 认证过滤器 Bean */ @Bean - public JWTAuthenticationTokenFilter authenticationTokenFilter(SecurityAuthFrameworkService securityFrameworkService, + public JWTAuthenticationTokenFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider, GlobalExceptionHandler globalExceptionHandler) { - return new JWTAuthenticationTokenFilter(securityProperties, securityFrameworkService, globalExceptionHandler); + return new JWTAuthenticationTokenFilter(securityProperties, authenticationProvider, globalExceptionHandler); + } + + /** + * 身份验证的 Provider Bean,通过它实现账号 + 密码的认证 + */ + @Bean + public MultiUserDetailsAuthenticationProvider authenticationProvider( + List securityFrameworkServices, + WebProperties webProperties, PasswordEncoder passwordEncoder) { + return new MultiUserDetailsAuthenticationProvider(securityFrameworkServices, webProperties, passwordEncoder); } /** diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index a0f1c87cc9..0374944754 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -1,27 +1,26 @@ package cn.iocoder.yudao.framework.security.config; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter; -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.yudao.framework.web.config.WebProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; +import java.util.List; /** * 自定义的 Spring Security 配置适配器实现 @@ -35,16 +34,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @Resource private WebProperties webProperties; - /** - * 自定义用户【认证】逻辑 - */ @Resource - private SecurityAuthFrameworkService userDetailsService; - /** - * Spring Security 加密器 - */ - @Resource - private PasswordEncoder passwordEncoder; + private MultiUserDetailsAuthenticationProvider authenticationProvider; /** * 认证失败处理类 Bean */ @@ -65,13 +56,14 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap */ @Resource private JWTAuthenticationTokenFilter authenticationTokenFilter; + /** - * 自定义的权限映射 Bean + * 自定义的权限映射 Bean 们 * * @see #configure(HttpSecurity) */ @Resource - private Customizer.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer; + private List authorizeRequestsCustomizers; /** * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 @@ -89,8 +81,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService) - .passwordEncoder(passwordEncoder); + auth.authenticationProvider(authenticationProvider); } /** @@ -112,6 +103,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap */ @Override protected void configure(HttpSecurity httpSecurity) throws Exception { + // 登出 httpSecurity // 开启跨域 .cors().and() @@ -123,41 +115,38 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap // 一堆自定义的 Spring Security 处理器 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler).and() - .logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出 + // 登出地址的配置 + .logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出 + StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"), + buildAppApi("/member/logout"))); - // 设置每个请求的权限 ①:全局共享规则 - httpSecurity.authorizeRequests() - // 登录的接口,可匿名访问 - .antMatchers(api("/login")).anonymous() + // 设置每个请求的权限 + httpSecurity + // ①:全局共享规则 + .authorizeRequests() // 静态资源,可匿名访问 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 文件的获取接口,可匿名访问 - .antMatchers(api("/infra/file/get/**")).anonymous() - // Swagger 接口文档 - .antMatchers("/swagger-ui.html").anonymous() - .antMatchers("/swagger-resources/**").anonymous() - .antMatchers("/webjars/**").anonymous() - .antMatchers("/*/api-docs").anonymous() - // Spring Boot Actuator 的安全配置 - .antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous() - // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。 - .antMatchers("/druid/**").anonymous() - // oAuth2 auth2/login/gitee - .antMatchers(api("/auth2/login/**")).anonymous() - .antMatchers(api("/auth2/authorization/**")).anonymous() - .antMatchers("/api/callback/**").anonymous() - // 设置每个请求的权限 ②:每个项目的自定义规则 - .and().authorizeRequests(authorizeRequestsCustomizer) - // 设置每个请求的权限 ③:兜底规则,必须认证 - .authorizeRequests().anyRequest().authenticated() + .antMatchers(HttpMethod.GET, "/admin-ui/**").permitAll() + // 设置 App API 无需认证 + .antMatchers(buildAppApi("/**")).permitAll() + // ②:每个项目的自定义规则 + .and().authorizeRequests(registry -> // 下面,循环设置自定义规则 + authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry))) + // ③:兜底规则,必须认证 + .authorizeRequests() + .anyRequest().authenticated() ; + // 添加 JWT Filter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); } - private String api(String url) { - return webProperties.getApiPrefix() + url; + private String buildAdminApi(String url) { + return webProperties.getAdminApi().getPrefix() + url; + } + + private String buildAppApi(String url) { + return webProperties.getAppApi().getPrefix() + url; } } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java new file mode 100644 index 0000000000..dc8533f964 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java @@ -0,0 +1,149 @@ +package cn.iocoder.yudao.framework.security.core.authentication; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.web.config.WebProperties; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 支持多用户类型的 AuthenticationProvider 实现类 + * + * 为什么不用 {@link org.springframework.security.authentication.ProviderManager} 呢? + * 原因是,需要每个用户类型实现对应的 {@link AuthenticationProvider} + authentication,略显麻烦。实际,也是可以实现的。 + * + * 另外,额外支持 verifyTokenAndRefresh 校验令牌、logout 登出、mockLogin 模拟登陆等操作。 + * 实际上,它就是 {@link SecurityAuthFrameworkService} 定义的三个接口。 + * 因为需要支持多种类型,所以需要根据请求的 URL,判断出对应的用户类型,从而使用对应的 SecurityAuthFrameworkService 是吸纳 + * + * @see cn.iocoder.yudao.framework.common.enums.UserTypeEnum + * @author 芋道源码 + */ +public class MultiUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + + private final Map services = new HashMap<>(); + + private final WebProperties properties; + + private final PasswordEncoder passwordEncoder; + + public MultiUserDetailsAuthenticationProvider(List serviceList, + WebProperties properties, PasswordEncoder passwordEncoder) { + serviceList.forEach(service -> services.put(service.getUserType(), service)); + this.properties = properties; + this.passwordEncoder = passwordEncoder; + } + + // ========== AuthenticationProvider 相关 ========== + + @Override + protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) + throws AuthenticationException { + // 执行用户的加载 + return selectService(authentication).loadUserByUsername(username); + } + + private SecurityAuthFrameworkService selectService(UsernamePasswordAuthenticationToken authentication) { + // 第一步,获得用户类型 + UserTypeEnum userType = getUserType(authentication); + // 第二步,获得 SecurityAuthFrameworkService + SecurityAuthFrameworkService service = services.get(userType); + Assert.notNull(service, "用户类型({}) 找不到 SecurityAuthFrameworkService 实现类", userType); + return service; + } + + private UserTypeEnum getUserType(UsernamePasswordAuthenticationToken authentication) { + Assert.isInstanceOf(MultiUsernamePasswordAuthenticationToken.class, authentication); + MultiUsernamePasswordAuthenticationToken multiAuthentication = (MultiUsernamePasswordAuthenticationToken) authentication; + UserTypeEnum userType = multiAuthentication.getUserType(); + Assert.notNull(userType, "用户类型不能为空"); + return userType; + } + + @Override // copy 自 DaoAuthenticationProvider 的 additionalAuthenticationChecks 方法 + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) + throws AuthenticationException { + // 校验 credentials + if (authentication.getCredentials() == null) { + this.logger.debug("Failed to authenticate since no credentials provided"); + throw new BadCredentialsException(this.messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); + } + // 校验 password + String presentedPassword = authentication.getCredentials().toString(); + if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { + this.logger.debug("Failed to authenticate since password does not match stored value"); + throw new BadCredentialsException(this.messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); + } + } + + // ========== SecurityAuthFrameworkService 相关 ========== + + /** + * 校验 token 的有效性,并获取用户信息 + * 通过后,刷新 token 的过期时间 + * + * @param request 请求 + * @param token token + * @return 用户信息 + */ + public LoginUser verifyTokenAndRefresh(HttpServletRequest request, String token) { + return selectService(request).verifyTokenAndRefresh(token); + } + + /** + * 模拟指定用户编号的 LoginUser + * + * @param request 请求 + * @param userId 用户编号 + * @return 登录用户 + */ + public LoginUser mockLogin(HttpServletRequest request, Long userId) { + return selectService(request).mockLogin(userId); + } + + /** + * 基于 token 退出登录 + * + * @param request 请求 + * @param token token + */ + public void logout(HttpServletRequest request, String token) { + selectService(request).logout(token); + } + + private SecurityAuthFrameworkService selectService(HttpServletRequest request) { + // 第一步,获得用户类型 + UserTypeEnum userType = getUserType(request); + // 第二步,获得 SecurityAuthFrameworkService + SecurityAuthFrameworkService service = services.get(userType); + Assert.notNull(service, "URI({}) 用户类型({}) 找不到 SecurityAuthFrameworkService 实现类", + request.getRequestURI(), userType); + return service; + } + + private UserTypeEnum getUserType(HttpServletRequest request) { + if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix())) { + return UserTypeEnum.ADMIN; + } + if (request.getRequestURI().startsWith(properties.getAppApi().getPrefix())) { + return UserTypeEnum.MEMBER; + } + throw new IllegalArgumentException(StrUtil.format("URI({}) 找不到匹配的用户类型", request.getRequestURI())); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java new file mode 100644 index 0000000000..f0bc8dfac4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.framework.security.core.authentication; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import lombok.Getter; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * 支持多用户的 UsernamePasswordAuthenticationToken 实现类 + * + * @author 芋道源码 + */ +@Getter +public class MultiUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { + + /** + * 用户类型 + */ + private UserTypeEnum userType; + + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } + + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(principal, credentials, authorities); + } + + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, UserTypeEnum userType) { + super(principal, credentials); + this.userType = userType; + } + + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, + Collection authorities, UserTypeEnum userType) { + super(principal, credentials, authorities); + this.userType = userType; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java index c83318b0d7..804c88d35f 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java @@ -2,17 +2,15 @@ package cn.iocoder.yudao.framework.security.core.filter; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.security.config.SecurityProperties; import cn.iocoder.yudao.framework.security.core.LoginUser; -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; +import lombok.RequiredArgsConstructor; import org.springframework.web.filter.OncePerRequestFilter; -import javax.annotation.Resource; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -25,12 +23,12 @@ import java.io.IOException; * * @author 芋道源码 */ -@AllArgsConstructor +@RequiredArgsConstructor public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { private final SecurityProperties securityProperties; - private final SecurityAuthFrameworkService authService; + private final MultiUserDetailsAuthenticationProvider authenticationProvider; private final GlobalExceptionHandler globalExceptionHandler; @@ -42,10 +40,10 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { if (StrUtil.isNotEmpty(token)) { try { // 验证 token 有效性 - LoginUser loginUser = authService.verifyTokenAndRefresh(token); + LoginUser loginUser = authenticationProvider.verifyTokenAndRefresh(request, token); // 模拟 Login 功能,方便日常开发调试 if (loginUser == null) { - loginUser = this.mockLoginUser(token); + loginUser = this.mockLoginUser(request, token); } // 设置当前用户 if (loginUser != null) { @@ -67,10 +65,11 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { * * 注意,在线上环境下,一定要关闭该功能!!! * + * @param request 请求 * @param token 模拟的 token,格式为 {@link SecurityProperties#getTokenSecret()} + 用户编号 * @return 模拟的 LoginUser */ - private LoginUser mockLoginUser(String token) { + private LoginUser mockLoginUser(HttpServletRequest request, String token) { if (!securityProperties.getMockEnable()) { return null; } @@ -79,7 +78,7 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { return null; } Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length())); - return authService.mockLogin(userId); + return authenticationProvider.mockLogin(request, userId); } } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java deleted file mode 100644 index 01fdf08887..0000000000 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * MIT License - * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) - * - * 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. - */ -package cn.iocoder.yudao.framework.security.core.handler; - -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.security.web.savedrequest.HttpSessionRequestCache; -import org.springframework.security.web.savedrequest.RequestCache; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author weir - */ -public class AbstractSignUpUrlAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { - private RequestCache requestCache = new HttpSessionRequestCache(); - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - if (requestCache.getRequest(request, response) != null) { - requestCache.getRequest(request, response); - } - super.onAuthenticationSuccess(request,response,authentication); - } - - @Override - public void setRequestCache(RequestCache requestCache) { - this.requestCache = requestCache; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java index 1bf8091be6..1a642304ca 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java @@ -2,16 +2,14 @@ package cn.iocoder.yudao.framework.security.core.handler; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.security.config.SecurityProperties; -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import lombok.AllArgsConstructor; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.stereotype.Component; -import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -26,14 +24,14 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { private final SecurityProperties securityProperties; - private final SecurityAuthFrameworkService securityFrameworkService; + private final MultiUserDetailsAuthenticationProvider authenticationProvider; @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { // 执行退出 String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); if (StrUtil.isNotBlank(token)) { - securityFrameworkService.logout(token); + authenticationProvider.logout(request, token); } // 返回成功 ServletUtils.writeJSON(response, CommonResult.success(null)); diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java index 28c8f6dc0c..1f76e161f8 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.framework.security.core.service; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.security.core.LoginUser; import org.springframework.security.core.userdetails.UserDetailsService; /** - * Security 框架 Auth Service 接口,定义 security 组件需要的功能 + * Security 框架 Auth Service 接口,定义不同用户类型的 {@link UserTypeEnum} 需要实现的方法 * * @author 芋道源码 */ @@ -34,4 +35,11 @@ public interface SecurityAuthFrameworkService extends UserDetailsService { */ void logout(String token); + /** + * 获得用户类型。每个用户类型,对应一个 SecurityAuthFrameworkService 实现类。 + * + * @return 用户类型 + */ + UserTypeEnum getUserType(); + } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java index 93f163086b..562c6ed9f6 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -41,6 +41,19 @@ public class SecurityFrameworkUtils { return authorization.substring(index + 7).trim(); } + /** + * 获得当前认证信息 + * + * @return 认证信息 + */ + public static Authentication getAuthentication() { + SecurityContext context = SecurityContextHolder.getContext(); + if (context == null) { + return null; + } + return context.getAuthentication(); + } + /** * 获取当前用户 * @@ -48,11 +61,7 @@ public class SecurityFrameworkUtils { */ @Nullable public static LoginUser getLoginUser() { - SecurityContext context = SecurityContextHolder.getContext(); - if (context == null) { - return null; - } - Authentication authentication = context.getAuthentication(); + Authentication authentication = getAuthentication(); if (authentication == null) { return null; } @@ -88,16 +97,22 @@ public class SecurityFrameworkUtils { * @param request 请求 */ public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { - // 创建 UsernamePasswordAuthenticationToken 对象 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - loginUser, null, loginUser.getAuthorities()); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - // 设置到上下文 - SecurityContextHolder.getContext().setAuthentication(authenticationToken); + // 创建 Authentication,并设置到上下文 + Authentication authentication = buildAuthentication(loginUser, request); + SecurityContextHolder.getContext().setAuthentication(authentication); + // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号; // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); } + private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) { + // 创建 UsernamePasswordAuthenticationToken 对象 + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( + loginUser, null, loginUser.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + return authenticationToken; + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java index a0ee60c420..aa2f18c768 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.test.core.util; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import uk.co.jemos.podam.api.PodamFactory; import uk.co.jemos.podam.api.PodamFactoryImpl; @@ -21,6 +22,9 @@ public class RandomUtils { private static final int RANDOM_STRING_LENGTH = 10; + private static final Set TINYINT_FIELDS = SetUtils.asSet("type", "category"); + private static final int TINYINT_MAX = 127; + private static final int RANDOM_DATE_MAX = 30; private static final int RANDOM_COLLECTION_LENGTH = 5; @@ -37,6 +41,10 @@ public class RandomUtils { if (attributeMetadata.getAttributeName().equals("status")) { return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); } + // 针对部分字段,使用 tinyint 范围 + if (TINYINT_FIELDS.contains(attributeMetadata.getAttributeName())) { + return RandomUtil.randomInt(1, TINYINT_MAX + 1); + } return RandomUtil.randomInt(); }); // Boolean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 57133c8409..3295e34c15 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.apilog.core.filter; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -25,6 +26,8 @@ import java.io.IOException; import java.util.Date; import java.util.Map; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.*; + /** * API 访问日志 Filter * @@ -42,7 +45,8 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { @Override protected boolean shouldNotFilter(HttpServletRequest request) { // 只过滤 API 请求的地址 - return !request.getRequestURI().startsWith(webProperties.getApiPrefix()); + return !StrUtil.startWithAny(request.getRequestURI(), webProperties.getAppApi().getPrefix(), + webProperties.getAppApi().getPrefix()); } @Override @@ -73,7 +77,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog); } catch (Throwable th) { - log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), JsonUtils.toJsonString(accessLog), th); + log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); } } @@ -99,7 +103,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { accessLog.setApplicationName(applicationName); accessLog.setRequestUrl(request.getRequestURI()); Map requestParams = MapUtil.builder().put("query", queryString).put("body", requestBody).build(); - accessLog.setRequestParams(JsonUtils.toJsonString(requestParams)); + accessLog.setRequestParams(toJsonString(requestParams)); accessLog.setRequestMethod(request.getMethod()); accessLog.setUserAgent(ServletUtils.getUserAgent(request)); accessLog.setUserIp(ServletUtil.getClientIP(request)); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java index d1376fd836..3a8e79fd6b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java @@ -8,6 +8,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; +import springfox.documentation.RequestHandler; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.service.ApiInfo; @@ -23,6 +24,7 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; @@ -56,6 +58,7 @@ public class YudaoSwaggerAutoConfiguration { // 设置扫描指定 package 包下的 .select() .apis(basePackage(properties.getBasePackage())) +// .apis(basePackage("cn.iocoder.yudao.module.infra")) // 可用于 swagger 无法展示时使用 .paths(PathSelectors.any()) .build() .securitySchemes(securitySchemes()) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java index 2edc3e883c..173a67042e 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java @@ -5,6 +5,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @ConfigurationProperties(prefix = "yudao.web") @@ -12,26 +14,49 @@ import javax.validation.constraints.NotNull; @Data public class WebProperties { - /** - * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀 - * - * - * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题 - * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。 - * - * @see YudaoWebAutoConfiguration#configurePathMatch(PathMatchConfigurer) - */ - @NotNull(message = "API 前缀不能为空") - private String apiPrefix; + @NotNull(message = "APP API 不能为空") + private Api appApi; + @NotNull(message = "Admin API 不能为空") + private Api adminApi; - /** - * Controller 所在包 - * - * 主要目的是,给该 Controller 设置指定的 {@link #apiPrefix} - * - * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.yudao 这样的层级 - */ - @NotNull(message = "Controller 所在包不能为空") - private String controllerPackage; + @NotNull(message = "Admin UI 不能为空") + private Ui adminUi; + + @Data + @Valid + public static class Api { + + /** + * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀 + * + * + * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题 + * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。 + * + * @see YudaoWebAutoConfiguration#configurePathMatch(PathMatchConfigurer) + */ + @NotEmpty(message = "API 前缀不能为空") + private String prefix; + + /** + * Controller 所在包的 Ant 路径规则 + * + * 主要目的是,给该 Controller 设置指定的 {@link #prefix} + */ + @NotEmpty(message = "Controller 所在包不能为空") + private String controller; + + } + + @Data + @Valid + public static class Ui { + + /** + * 访问地址 + */ + private String url; + + } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 5d390cdb17..a6f932dd07 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -13,6 +13,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.cors.CorsConfiguration; @@ -38,10 +39,20 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { - // 设置 API 前缀,仅仅匹配 controller 包下的 - configurer.addPathPrefix(webProperties.getApiPrefix(), clazz -> - clazz.isAnnotationPresent(RestController.class) - && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); // 仅仅匹配 controller 包 + configurePathMatch(configurer, webProperties.getAdminApi()); + configurePathMatch(configurer, webProperties.getAppApi()); + } + + /** + * 设置 API 前缀,仅仅匹配 controller 包下的 + * + * @param configurer 配置 + * @param api API 配置 + */ + private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) { + AntPathMatcher antPathMatcher = new AntPathMatcher("."); + configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class) + && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包 } @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java index acbfb9c2ba..273f34072d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java @@ -55,6 +55,11 @@ public class WebFrameworkUtils { return (Integer) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_TYPE); } + public static Integer getLoginUserType() { + HttpServletRequest request = getRequest(); + return getLoginUserType(request); + } + public static Long getLoginUserId() { HttpServletRequest request = getRequest(); return getLoginUserId(request); diff --git a/yudao-module-bpm/pom.xml b/yudao-module-bpm/pom.xml new file mode 100644 index 0000000000..4dee14b6f7 --- /dev/null +++ b/yudao-module-bpm/pom.xml @@ -0,0 +1,32 @@ + + + + yudao + cn.iocoder.boot + ${revision} + + 4.0.0 + + yudao-module-bpm-api + yudao-module-bpm-base + yudao-module-bpm-impl-flowable + yudao-module-bpm-impl-activiti + + yudao-module-bpm + pom + + ${artifactId} + + bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能。 + 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等 + bpm 解释:https://baike.baidu.com/item/BPM/1933 + + 目前提供两套实现方案: + 1. 基于 Activiti 7 实现的 yudao-module-bpm-impl-activiti + 2. 基于 Flowable 6 实现的 yudao-module-bpm-impl-flowable + 两套实现会存在共享的逻辑,所以会继承 yudao-module-impl-base + + + diff --git a/yudao-module-bpm/yudao-module-bpm-api/pom.xml b/yudao-module-bpm/yudao-module-bpm-api/pom.xml new file mode 100644 index 0000000000..91cd35be85 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.boot + yudao-module-bpm + ${revision} + + 4.0.0 + yudao-module-bpm-api + jar + + ${artifactId} + + bpm 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java new file mode 100644 index 0000000000..37a92219f9 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java @@ -0,0 +1,4 @@ +/** + * bpm API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.bpm.api; diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java new file mode 100644 index 0000000000..e94a2c84fe --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.bpm.api.task; + +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; + +import javax.validation.Valid; + +/** + * 流程实例 Api 接口 + * + * @author 芋道源码 + */ +public interface BpmProcessInstanceApi { + + /** + * 创建流程实例(提供给内部) + * + * @param userId 用户编号 + * @param reqDTO 创建信息 + * @return 实例的编号 + */ + String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/dto/BpmProcessInstanceCreateReqDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCreateReqDTO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/dto/BpmProcessInstanceCreateReqDTO.java rename to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCreateReqDTO.java index 9729721078..5d7edbe804 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/dto/BpmProcessInstanceCreateReqDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCreateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task.dto; +package cn.iocoder.yudao.module.bpm.api.task.dto; import lombok.Data; diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java new file mode 100644 index 0000000000..7abb3e1dbc --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.bpm.enums; + +/** + * BPM 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String TASK_ASSIGN_RULE_TYPE = "bpm_task_assign_rule_type"; // 任务分配规则类型 + String TASK_ASSIGN_SCRIPT = "bpm_task_assign_script"; // 任务分配自定义脚本 + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java similarity index 97% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java rename to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index e2a0ff3d7a..45fa3fa877 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums; +package cn.iocoder.yudao.module.bpm.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; * * 工作流系统,使用 1-009-000-000 段 */ -public interface BpmErrorCodeConstants { +public interface ErrorCodeConstants { // ========== 通用流程处理 模块 1-009-000-000 ========== ErrorCode HIGHLIGHT_IMG_ERROR = new ErrorCode(1009000002, "获取高亮流程图异常"); diff --git a/yudao-module-bpm/yudao-module-bpm-base/pom.xml b/yudao-module-bpm/yudao-module-bpm-base/pom.xml new file mode 100644 index 0000000000..8889428445 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/pom.xml @@ -0,0 +1,59 @@ + + + + cn.iocoder.boot + yudao-module-bpm + ${revision} + + 4.0.0 + yudao-module-bpm-base + + ${artifactId} + + bpm-base 模块,实现公用的工作流的逻辑,提供给 bpm-activiti 和 bpm-flowable 复用 + + + + + cn.iocoder.boot + yudao-module-bpm-api + ${revision} + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmFormController.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmFormController.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java index cb22db3427..217067f313 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmFormController.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; +package cn.iocoder.yudao.module.bpm.controller.admin.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.*; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmFormConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.*; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import io.swagger.annotations.Api; @@ -19,7 +19,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "动态表单") +@Api(tags = "管理后台 - 动态表单") @RestController @RequestMapping("/bpm/form") @Validated diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmUserGroupController.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmUserGroupController.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java index 00a31e8b88..4267f09027 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmUserGroupController.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java @@ -1,15 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; +package cn.iocoder.yudao.module.bpm.controller.admin.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmUserGroupConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmUserGroupConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -22,12 +19,11 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; - import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "用户组") +@Api(tags = "管理后台 - 用户组") @RestController @RequestMapping("/bpm/user-group") @Validated diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormBaseVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormBaseVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormBaseVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormBaseVO.java index f57c80c94e..11fee5c00f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import lombok.*; import io.swagger.annotations.*; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormCreateReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormCreateReqVO.java index 70da000627..d9a6281258 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import lombok.*; import io.swagger.annotations.*; @@ -6,7 +6,7 @@ import io.swagger.annotations.*; import javax.validation.constraints.NotNull; import java.util.List; -@ApiModel("动态表单创建 Request VO") +@ApiModel("管理后台 - 动态表单创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java index 6001b59ff1..a8097c4372 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -7,7 +7,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("动态表单分页 Request VO") +@ApiModel("管理后台 - 动态表单分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java index 89c2eb9303..76cf620466 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull; import java.util.Date; import java.util.List; -@ApiModel("动态表单 Response VO") +@ApiModel("管理后台 - 动态表单 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormSimpleRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSimpleRespVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormSimpleRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSimpleRespVO.java index 4459bf6abb..3a6b3c0932 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormSimpleRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSimpleRespVO.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel("流程表单精简 Response VO") +@ApiModel("管理后台 - 流程表单精简 Response VO") @Data public class BpmFormSimpleRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormUpdateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormUpdateReqVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormUpdateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormUpdateReqVO.java index 1ca527ac10..55b9976798 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/form/BpmFormUpdateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormUpdateReqVO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form; import lombok.*; import io.swagger.annotations.*; import javax.validation.constraints.*; import java.util.List; -@ApiModel("动态表单更新 Request VO") +@ApiModel("管理后台 - 动态表单更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupBaseVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupBaseVO.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupBaseVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupBaseVO.java index 9914260d37..e0dfe568e4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import lombok.*; import java.util.*; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupCreateReqVO.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupCreateReqVO.java index 44114ac144..48b44d38b7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupCreateReqVO.java @@ -1,11 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import lombok.*; -import java.util.*; import io.swagger.annotations.*; -import javax.validation.constraints.*; -@ApiModel("用户组创建 Request VO") +@ApiModel("管理后台 - 用户组创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java new file mode 100644 index 0000000000..44631737fe --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@ApiModel("管理后台 - 用户组分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmUserGroupPageReqVO extends PageParam { + + @ApiModelProperty(value = "组名", example = "芋道") + private String name; + + @ApiModelProperty(value = "状态", example = "1") + private Integer status; + + @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始创建时间") + private Date beginCreateTime; + + @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束创建时间") + private Date endCreateTime; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java index 523bb60a3b..55018d5026 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import lombok.*; import java.util.*; import io.swagger.annotations.*; -@ApiModel("用户组 Response VO") +@ApiModel("管理后台 - 用户组 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupSimpleRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSimpleRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupSimpleRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSimpleRespVO.java index fb427d0f68..0b47f447e3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupSimpleRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("用户组精简信息 Response VO") +@ApiModel("管理后台 - 用户组精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupUpdateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupUpdateReqVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupUpdateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupUpdateReqVO.java index 00a32bdac6..14aa25c5b5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupUpdateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupUpdateReqVO.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("用户组更新 Request VO") +@ApiModel("管理后台 - 用户组更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModeImportReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeImportReqVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModeImportReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeImportReqVO.java index 18b9b5b6fb..7240ba15c3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModeImportReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeImportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,7 +9,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotNull; -@ApiModel(value = "流程模型的导入 Request VO", description = "相比流程模型的新建来说,只是多了一个 bpmnFile 文件") +@ApiModel(value = "管理后台 - 流程模型的导入 Request VO", description = "相比流程模型的新建来说,只是多了一个 bpmnFile 文件") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelBaseVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelBaseVO.java similarity index 95% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelBaseVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelBaseVO.java index 7246a272d1..542a177e48 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelCreateReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelCreateReqVO.java index 4a3c19e4fe..c85ef3ae40 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import javax.validation.constraints.NotEmpty; -@ApiModel("流程模型的创建 Request VO") +@ApiModel("管理后台 - 流程模型的创建 Request VO") @Data public class BpmModelCreateReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelPageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java index af498d8270..7442b5ab03 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("流程模型的分页的每一项 Response VO") +@ApiModel("管理后台 - 流程模型的分页的每一项 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/ModelPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageReqVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/ModelPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageReqVO.java index 70b2b2ff33..945da139ca 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/ModelPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -8,11 +8,11 @@ import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("流程模型分页 Request VO") +@ApiModel("管理后台 - 流程模型分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ModelPageReqVO extends PageParam { +public class BpmModelPageReqVO extends PageParam { @ApiModelProperty(value = "标识", example = "process1641042089407", notes = "精准匹配") private String key; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java index a448e620be..bce0f9100a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("流程模型的创建 Request VO") +@ApiModel("管理后台 - 流程模型的创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateReqVO.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateReqVO.java index 8cac65ae95..972aa31bbc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; -@ApiModel("流程模型的更新 Request VO") +@ApiModel("管理后台 - 流程模型的更新 Request VO") @Data public class BpmModelUpdateReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateStateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateStateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java index 1536e9042b..9cfcebbdcf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/model/BpmModelUpdateStateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("流程模型更新状态 Request VO") +@ApiModel("管理后台 - 流程模型更新状态 Request VO") @Data public class BpmModelUpdateStateReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionListReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionListReqVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionListReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionListReqVO.java index dae4a9b503..5e45b8bde6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionListReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionListReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -7,10 +7,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +@ApiModel("管理后台 - 流程定义列表 Request VO") @Data @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) -@ApiModel("流程定义列表 Request VO") public class BpmProcessDefinitionListReqVO extends PageParam { @ApiModelProperty(value = "中断状态", example = "1", notes = "参见 SuspensionState 枚举") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java index 967aac8d40..75990f08a9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("流程定义的分页的每一项 Response VO") +@ApiModel("管理后台 - 流程定义的分页的每一项 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java index 70fa41d8f0..a9657e9a24 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -7,10 +7,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +@ApiModel("管理后台 - 流程定义分页 Request VO") @Data @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) -@ApiModel("流程定义分页 Request VO") public class BpmProcessDefinitionPageReqVO extends PageParam { @ApiModelProperty(value = "标识", example = "process1641042089407", notes = "精准匹配") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java index 4e0f518645..6f8fd4e5b4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/process/BpmProcessDefinitionRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; -@ApiModel("流程定义 Response VO") +@ApiModel("管理后台 - 流程定义 Response VO") @Data public class BpmProcessDefinitionRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleBaseVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleBaseVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleBaseVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleBaseVO.java index 935c9b4108..bcb9fc0f03 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java index b29bc0b2f8..cbbc108c06 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import javax.validation.constraints.NotEmpty; -@ApiModel("流程任务分配规则的创建 Request VO") +@ApiModel("管理后台 - 流程任务分配规则的创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleRespVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleRespVO.java index d9c36aad96..c0786e52b4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("流程任务分配规则的 Response VO") +@ApiModel("管理后台 - 流程任务分配规则的 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java index 48388a9447..8f1c12701b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/rule/BpmTaskAssignRuleUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule; +package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,9 +7,8 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import javax.validation.constraints.NotNull; -import java.util.Set; -@ApiModel("流程任务分配规则的更新 Request VO") +@ApiModel("管理后台 - 流程任务分配规则的更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/BpmOALeaveController.http b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.http similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/BpmOALeaveController.http rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.http diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/BpmOALeaveController.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/BpmOALeaveController.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java index 4f8a394c81..dd66580d3b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/BpmOALeaveController.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa; +package cn.iocoder.yudao.module.bpm.controller.admin.oa; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeaveCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeavePageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeaveRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.oa.BpmOALeaveConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.BpmOALeaveDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.BpmOALeaveService; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveRespVO; +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -27,7 +27,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti * @author jason * @author 芋道源码 */ -@Api(tags = "OA 请假申请") +@Api(tags = "管理后台 - OA 请假申请") @RestController @RequestMapping("/bpm/oa/leave") @Validated diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java new file mode 100644 index 0000000000..7028708b1e --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java @@ -0,0 +1,5 @@ +/** + * OA 示例,用于演示外部业务接入 BPM 工作流的示例 + * 一般的接入方式,只需要调用 接口,后续 Admin 用户在管理后台的【待办事务】进行审批 + */ +package cn.iocoder.yudao.module.bpm.controller.admin.oa; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveBaseVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveBaseVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java index e7128b50d3..cbc568a11c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveBaseVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo; +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo; import lombok.*; import java.util.*; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java index f36e924b17..2ebab63e93 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo; +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo; import io.swagger.annotations.ApiModel; import lombok.Data; @@ -7,7 +7,7 @@ import lombok.ToString; import javax.validation.constraints.AssertTrue; -@ApiModel("请假申请创建 Request VO") +@ApiModel("管理后台 - 请假申请创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeavePageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeavePageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java index 7b81455a25..0443d44f55 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeavePageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo; +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("请假申请分页 Request VO") +@ApiModel("管理后台 - 请假申请分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java index 2b386d8ced..908c48e06b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/oa/vo/BpmOALeaveRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo; +package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo; import lombok.*; import io.swagger.annotations.*; @@ -9,7 +9,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("请假申请 Response VO") +@ApiModel("管理后台 - 请假申请 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/package-info.java new file mode 100644 index 0000000000..6cf7f955b5 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.task; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java index 447c590006..ef9d11ac1e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.activity; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import java.util.Date; -@ApiModel("流程活动的 Response VO") +@ApiModel("管理后台 - 流程活动的 Response VO") @Data public class BpmActivityRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCancelReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCancelReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java index 74f0a86b4a..928f187e79 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCancelReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.Map; -@ApiModel("流程实例的取消 Request VO") +@ApiModel("管理后台 - 流程实例的取消 Request VO") @Data public class BpmProcessInstanceCancelReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCreateReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java index e4fbc95bba..2085253d30 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,7 +7,7 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; import java.util.Map; -@ApiModel("流程实例的创建 Request VO") +@ApiModel("管理后台 - 流程实例的创建 Request VO") @Data public class BpmProcessInstanceCreateReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceMyPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceMyPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java index 38965dd88e..e1e4327ea5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceMyPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceMyPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,7 +12,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("流程实例的分页 Item Response VO") +@ApiModel("管理后台 - 流程实例的分页 Item Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstancePageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstancePageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java index 14a2625701..5b5d5797ac 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstancePageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,7 +7,7 @@ import lombok.Data; import java.util.Date; import java.util.List; -@ApiModel("流程实例的分页 Item Response VO") +@ApiModel("管理后台 - 流程实例的分页 Item Response VO") @Data public class BpmProcessInstancePageItemRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java similarity index 96% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java index de6999c65a..a1547b1750 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/instance/BpmProcessInstanceRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import java.util.Date; import java.util.List; import java.util.Map; -@ApiModel("流程实例的 Response VO") +@ApiModel("管理后台 - 流程实例的 Response VO") @Data public class BpmProcessInstanceRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskApproveReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskApproveReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java index 356581a96d..6effcc8a74 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskApproveReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,7 +10,7 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.Map; -@ApiModel("通过流程任务的 Request VO") +@ApiModel("管理后台 - 通过流程任务的 Request VO") @Data public class BpmTaskApproveReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java index b932c4e073..6d1865576f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("流程任务的 Done 已完成的分页项 Response VO") +@ApiModel("管理后台 - 流程任务的 Done 已完成的分页项 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java index c3d3c6ead5..99145b4348 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskDonePageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,7 +12,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("流程任务的 Done 已办的分页 Request VO") +@ApiModel("管理后台 - 流程任务的 Done 已办的分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRejectReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRejectReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java index 4ad4983577..7196718f26 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRejectReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; -@ApiModel("不通过流程任务的 Request VO") +@ApiModel("管理后台 - 不通过流程任务的 Request VO") @Data public class BpmTaskRejectReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java index a66c9f2afc..9100eb3cd2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,9 +6,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.List; - -@ApiModel("流程任务的 Response VO") +@ApiModel("管理后台 - 流程任务的 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java index 2703b96902..e25e3aa494 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import java.util.Date; -@ApiModel("流程任务的 Running 进行中的分页项 Response VO") +@ApiModel("管理后台 - 流程任务的 Running 进行中的分页项 Response VO") @Data public class BpmTaskTodoPageItemRespVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java index d89e582f1a..9f248e1981 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskTodoPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTodoPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,7 +12,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("流程任务的 TODO 待办的分页 Request VO") +@ApiModel("管理后台 - 流程任务的 TODO 待办的分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskUpdateAssigneeReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskUpdateAssigneeReqVO.java index 0ad6fbedcf..0dd0ffed4f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/BpmTaskUpdateAssigneeReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskUpdateAssigneeReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,7 +10,7 @@ import net.bytebuddy.implementation.bind.annotation.Empty; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("流程任务的更新负责人的 Request VO") +@ApiModel("管理后台 - 流程任务的更新负责人的 Request VO") @Data public class BpmTaskUpdateAssigneeReqVO { diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java new file mode 100644 index 0000000000..e8d285e359 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.bpm.controller.app; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java new file mode 100644 index 0000000000..d1930bd6ac --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.bpm.controller; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmFormConvert.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmFormConvert.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java index 10e77f1e82..6ba7574170 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmFormConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmFormConvert.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; +package cn.iocoder.yudao.module.bpm.convert.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSimpleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmUserGroupConvert.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmUserGroupConvert.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java index 4e7cd997f2..bbf00ba524 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmUserGroupConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmUserGroupConvert.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; +package cn.iocoder.yudao.module.bpm.convert.definition; import java.util.*; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.mapstruct.Mapper; @@ -34,4 +34,5 @@ public interface BpmUserGroupConvert { @Named("convertList2") List convertList2(List list); + } diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java new file mode 100644 index 0000000000..92683f4c94 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.bpm.convert.message; + +import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.Map; + +@Mapper +public interface BpmMessageConvert { + + BpmMessageConvert INSTANCE = Mappers.getMapper(BpmMessageConvert.class); + + SmsSendSingleToUserReqDTO convert(Long userId, String templateCode, Map templateParams); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/oa/BpmOALeaveConvert.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/oa/BpmOALeaveConvert.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java index 8c7c1d8bfc..f87531bfc5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/oa/BpmOALeaveConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/oa/BpmOALeaveConvert.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.oa; +package cn.iocoder.yudao.module.bpm.convert.oa; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeaveCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeaveRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.BpmOALeaveDO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/package-info.java new file mode 100644 index 0000000000..6a53114a8c --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bpm.convert.task; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmFormDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmFormDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java index 2c23b8dcc8..76bf777e5d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmFormDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java index 007ad43f34..57abc0b99b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionExtDO.java @@ -1,14 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.*; -import org.activiti.engine.repository.Model; -import org.activiti.engine.repository.ProcessDefinition; import java.util.List; @@ -35,13 +33,13 @@ public class BpmProcessDefinitionExtDO extends BaseDO { /** * 流程定义的编号 * - * 关联 {@link ProcessDefinition#getId()} + * 关联 ProcessDefinition 的 id 属性 */ private String processDefinitionId; /** * 流程模型的编号 * - * 关联 {@link Model#getId()} + * 关联 Model 的 id 属性 */ private String modelId; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java index 08b80c4a94..e65764f1a8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskAssignRuleDO.java @@ -1,16 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import org.activiti.engine.repository.Model; -import org.activiti.engine.repository.ProcessDefinition; -import org.activiti.engine.task.Task; import java.util.Set; @@ -46,19 +43,19 @@ public class BpmTaskAssignRuleDO extends BaseDO { /** * 流程模型编号 * - * 关联 {@link Model#getId()} + * 关联 Model 的 id 属性 */ private String modelId; /** * 流程定义编号 * - * 关联 {@link ProcessDefinition#getId()} + * 关联 ProcessDefinition 的 id 属性 */ private String processDefinitionId; /** * 流程任务的定义 Key * - * 关联 {@link Task#getTaskDefinitionKey()} + * 关联 Task 的 taskDefinitionKey 属性 */ private String taskDefinitionKey; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java index 04f357931f..db204c0273 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmTaskMessageRuleDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; // TODO 芋艿:先埋个坑。任务消息的配置规则。说白了,就是不同的 public class BpmTaskMessageRuleDO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmUserGroupDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java similarity index 93% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmUserGroupDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java index d433c65f6d..ec11681805 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmUserGroupDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition; +package cn.iocoder.yudao.module.bpm.dal.dataobject.definition; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/leave/BpmOALeaveDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/leave/BpmOALeaveDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java index 53f8b7d753..31381a5568 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/leave/BpmOALeaveDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave; +package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import lombok.*; import java.util.*; import com.baomidou.mybatisplus.annotation.*; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import org.activiti.engine.runtime.ProcessInstance; /** * OA 请假申请 DO @@ -32,7 +31,7 @@ public class BpmOALeaveDO extends BaseDO { /** * 申请人的用户编号 * - * 关联 {@link SysUserDO#getId()} + * 关联 AdminUserDO 的 id 属性 */ private Long userId; /** @@ -59,7 +58,7 @@ public class BpmOALeaveDO extends BaseDO { /** * 请假的结果 * - * 枚举 {@link cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum} + * 枚举 {@link BpmProcessInstanceResultEnum} * 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈 */ private Integer result; @@ -67,7 +66,7 @@ public class BpmOALeaveDO extends BaseDO { /** * 对应的流程编号 * - * 关联 {@link ProcessInstance#getId()} + * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java index 8618387497..b37709962d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task; +package cn.iocoder.yudao.module.bpm.dal.dataobject.task; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -10,16 +10,13 @@ import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.activiti.engine.history.HistoricProcessInstance; -import org.activiti.engine.repository.ProcessDefinition; -import org.activiti.engine.runtime.ProcessInstance; import java.util.Date; import java.util.Map; /** * Bpm 流程实例的拓展表 - * 主要解决 Activiti {@link ProcessInstance} 和 {@link HistoricProcessInstance} 不支持拓展字段,所以新建拓展表 + * 主要解决 Activiti ProcessInstance 和 HistoricProcessInstance 不支持拓展字段,所以新建拓展表 * * @author 芋道源码 */ @@ -27,9 +24,6 @@ import java.util.Map; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -//@Builder -//@NoArgsConstructor -//@AllArgsConstructor public class BpmProcessInstanceExtDO extends BaseDO { /** @@ -40,31 +34,31 @@ public class BpmProcessInstanceExtDO extends BaseDO { /** * 发起流程的用户编号 * - * 冗余 {@link HistoricProcessInstance#getStartUserId()} + * 冗余 HistoricProcessInstance 的 startUserId 属性 */ private Long startUserId; /** * 流程实例的名字 * - * 冗余 {@link ProcessInstance#getName()} 为了筛选 + * 冗余 ProcessInstance 的 name 属性,用于筛选 */ private String name; /** * 流程实例的编号 * - * 关联 {@link ProcessInstance#getId()} + * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; /** * 流程定义的编号 * - * 关联 {@link ProcessDefinition#getId()} + * 关联 ProcessDefinition 的 id 属性 */ private String processDefinitionId; /** * 流程分类 * - * 冗余 {@link ProcessDefinition#getCategory()} + * 冗余 ProcessDefinition 的 category 属性 * 数据字典 bpm_model_category */ private String category; @@ -83,7 +77,7 @@ public class BpmProcessInstanceExtDO extends BaseDO { /** * 结束时间 * - * 冗余 {@link HistoricProcessInstance#getEndTime()} + * 冗余 HistoricProcessInstance 的 endTime 属性 */ private Date endTime; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmTaskExtDO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmTaskExtDO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java index e3b31ec33a..9cd12ee3c7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmTaskExtDO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java @@ -1,21 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task; +package cn.iocoder.yudao.module.bpm.dal.dataobject.task; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.activiti.engine.history.HistoricTaskInstance; -import org.activiti.engine.repository.ProcessDefinition; -import org.activiti.engine.runtime.ProcessInstance; -import org.activiti.engine.task.Task; import java.util.Date; /** * Bpm 流程任务的拓展表 - * 主要解决 Activiti {@link Task} 和 {@link HistoricTaskInstance} 不支持拓展字段,所以新建拓展表 + * 主要解决 Activiti Task 和 HistoricTaskInstance 不支持拓展字段,所以新建拓展表 * * @author 芋道源码 */ @@ -23,27 +19,24 @@ import java.util.Date; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -//@Builder -//@NoArgsConstructor -//@AllArgsConstructor public class BpmTaskExtDO extends BaseDO { /** * 任务的审批人 * - * 冗余 {@link Task#getAssignee()} + * 冗余 Task 的 assignee 属性 */ private Long assigneeUserId; /** * 任务的名字 * - * 冗余 {@link Task#getName()} 为了筛选 + * 冗余 Task 的 name 属性,为了筛选 */ private String name; /** * 任务的编号 * - * 关联 {@link Task#getId()} + * 关联 Task 的 id 属性 */ private String taskId; // /** @@ -65,20 +58,20 @@ public class BpmTaskExtDO extends BaseDO { /** * 任务的结束时间 * - * 冗余 {@link HistoricTaskInstance#getEndTime()} + * 冗余 HistoricTaskInstance 的 endTime 属性 */ private Date endTime; /** * 流程实例的编号 * - * 关联 {@link ProcessInstance#getId()} + * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; /** * 流程定义的编号 * - * 关联 {@link ProcessDefinition#getId()} + * 关联 ProcessDefinition 的 id 属性 */ private String processDefinitionId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmFormMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmFormMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java index f4b052877c..53c01d92e5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmFormMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition; +package cn.iocoder.yudao.module.bpm.dal.mysql.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java index 2a347eee43..d857e145c3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java @@ -1,9 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition; +package cn.iocoder.yudao.module.bpm.dal.mysql.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java index 14459c80cf..1205d30e1f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmTaskAssignRuleMapper.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition; +package cn.iocoder.yudao.module.bpm.dal.mysql.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmUserGroupMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmUserGroupMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java index f524fef69c..982e678bfe 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/definition/BpmUserGroupMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition; +package cn.iocoder.yudao.module.bpm.dal.mysql.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/oa/BpmOALeaveMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/oa/BpmOALeaveMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java index 1941744e60..ba781e3501 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/oa/BpmOALeaveMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa; +package cn.iocoder.yudao.module.bpm.dal.mysql.oa; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.BpmOALeavePageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.BpmOALeaveDO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java index 0fbb455a64..ee31b08ca3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceExtMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task; +package cn.iocoder.yudao.module.bpm.dal.mysql.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceMyPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmTaskExtMapper.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmTaskExtMapper.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java index 2ac2995dfb..b2927a65e0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/mysql/task/BpmTaskExtMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task; +package cn.iocoder.yudao.module.bpm.dal.mysql.task; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmModelFormTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmModelFormTypeEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java index 917ec0f29c..c21d6f9991 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmModelFormTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.definition; +package cn.iocoder.yudao.module.bpm.enums.definition; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java index 8b3d8e48fa..de3c351620 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskAssignRuleTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.definition; +package cn.iocoder.yudao.module.bpm.enums.definition; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskRuleScriptEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskRuleScriptEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java index 571d37f871..7fc0e3b8bc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/definition/BpmTaskRuleScriptEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTaskRuleScriptEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.definition; +package cn.iocoder.yudao.module.bpm.enums.definition; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/message/BpmMessageEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/message/BpmMessageEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java index 79afd41cb7..79001fccd3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/message/BpmMessageEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.message; +package cn.iocoder.yudao.module.bpm.enums.message; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; import lombok.AllArgsConstructor; import lombok.Getter; @@ -20,9 +19,8 @@ public enum BpmMessageEnum { /** * 短信模板的标识 * - * 关联 {@link SysSmsTemplateDO#getCode()} + * 关联 SmsTemplateDO 的 code 属性 */ - private final String smsCode; - + private final String smsTemplateCode; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java index 65b2e953bb..e41930bb8f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceDeleteReasonEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.task; +package cn.iocoder.yudao.module.bpm.enums.task; import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceResultEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceResultEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java index 01916f51a9..39bf22ada7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceResultEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceResultEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.task; +package cn.iocoder.yudao.module.bpm.enums.task; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceStatusEnum.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceStatusEnum.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java index f7a1b110b4..70a31dd342 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/BpmProcessInstanceStatusEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums.task; +package cn.iocoder.yudao.module.bpm.enums.task; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCommonConfiguration.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCommonConfiguration.java new file mode 100644 index 0000000000..8915fc6b5a --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCommonConfiguration.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.bpm.framework.bpm.config; + +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable + */ +@Configuration +public class BpmCommonConfiguration { + + @Bean + public BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher(ApplicationEventPublisher publisher) { + return new BpmProcessInstanceResultEventPublisher(publisher); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEvent.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEvent.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java index d9f9524a3a..9fccbab8e6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEvent.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEvent.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event; +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import lombok.Data; import org.springframework.context.ApplicationEvent; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventListener.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventListener.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java index 6134a14cbc..c2b2153942 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventListener.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event; +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; import cn.hutool.core.util.StrUtil; import org.springframework.context.ApplicationListener; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventPublisher.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventPublisher.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java index dba448a9c4..dc5c21b755 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/BpmProcessInstanceResultEventPublisher.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/BpmProcessInstanceResultEventPublisher.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event; +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; import lombok.AllArgsConstructor; import org.springframework.context.ApplicationEventPublisher; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/package-info.java similarity index 56% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/package-info.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/package-info.java index 5a05170f95..c4a1311289 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/event/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/event/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event; +package cn.iocoder.yudao.module.bpm.framework.bpm.core.event; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/package-info.java new file mode 100644 index 0000000000..b97cb4c8ae --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.bpm.framework.bpm.core; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/package-info.java new file mode 100644 index 0000000000..9a5e3ea962 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供给 Activiti 和 Flowable 的通用封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.bpm.framework.bpm; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/package-info.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java index cec0edd207..52fdb7f935 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.bpm.framework; +package cn.iocoder.yudao.module.bpm.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/package-info.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java index 2757e578b7..6d399cf2a9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java @@ -1,9 +1,10 @@ /** - * bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 activiti 7 版本实现。 + * bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能。 * 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等 * * bpm 解释:https://baike.baidu.com/item/BPM/1933 * - * 缩写:bpm + * 1. Controller URL:以 /bpm/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 bpm_ 开头,方便在数据库中区分 */ -package cn.iocoder.yudao.adminserver.modules.bpm; +package cn.iocoder.yudao.module.bpm; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormService.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java index 6b872d4d75..a90fc9760b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormService.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmFormServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmFormServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java index e7ba8dfa98..42f1b145c3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmFormServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java @@ -1,14 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmFormConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmFormMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmFormFieldRespDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper; +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import org.springframework.stereotype.Service; @@ -20,10 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.FORM_FIELD_REPEAT; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.FORM_NOT_EXISTS; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - /** * 动态表单 Service 实现类 * @@ -66,7 +63,7 @@ public class BpmFormServiceImpl implements BpmFormService { private void validateFormExists(Long id) { if (formMapper.selectById(id) == null) { - throw exception(FORM_NOT_EXISTS); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_NOT_EXISTS); } } @@ -106,7 +103,7 @@ public class BpmFormServiceImpl implements BpmFormService { continue; } // 如果存在,则报错 - throw exception(FORM_FIELD_REPEAT, oldLabel, fieldDTO.getLabel(), fieldDTO.getVModel()); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_FIELD_REPEAT, oldLabel, fieldDTO.getLabel(), fieldDTO.getVModel()); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupService.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java index f1fd4debe1..da185105e2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupService.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; import java.util.*; import javax.validation.*; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmUserGroupServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmUserGroupServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java index 3e68290817..e6a93b45d6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmUserGroupServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java @@ -1,15 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmUserGroupConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmUserGroupMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmUserGroupConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.springframework.stereotype.Service; @@ -21,11 +20,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.USER_GROUP_IS_DISABLE; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.USER_GROUP_NOT_EXISTS; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.USER_IS_DISABLE; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.USER_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 用户组 Service 实现类 @@ -67,7 +63,7 @@ public class BpmUserGroupServiceImpl implements BpmUserGroupService { private void validateUserGroupExists(Long id) { if (userGroupMapper.selectById(id) == null) { - throw exception(USER_GROUP_NOT_EXISTS); + throw ServiceExceptionUtil.exception(USER_GROUP_NOT_EXISTS); } } @@ -81,6 +77,7 @@ public class BpmUserGroupServiceImpl implements BpmUserGroupService { return userGroupMapper.selectBatchIds(ids); } + @Override public List getUserGroupListByStatus(Integer status) { return userGroupMapper.selectListByStatus(status); @@ -103,7 +100,7 @@ public class BpmUserGroupServiceImpl implements BpmUserGroupService { ids.forEach(id -> { BpmUserGroupDO userGroup = userGroupMap.get(id); if (userGroup == null) { - throw exception(USER_GROUP_NOT_EXISTS); + throw ServiceExceptionUtil.exception(USER_GROUP_NOT_EXISTS); } if (!CommonStatusEnum.ENABLE.getStatus().equals(userGroup.getStatus())) { throw exception(USER_GROUP_IS_DISABLE, userGroup.getName()); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmFormFieldRespDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmFormFieldRespDTO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java index 2001974a5d..1606192ce7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmFormFieldRespDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto; +package cn.iocoder.yudao.module.bpm.service.definition.dto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/BpmMessageService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/BpmMessageService.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java index 20a25abe0d..8905893b47 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/BpmMessageService.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.message; +package cn.iocoder.yudao.module.bpm.service.message; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; import javax.validation.Valid; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/impl/BpmMessageServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java similarity index 56% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/impl/BpmMessageServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java index c16fd476fb..61b3c57d42 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/impl/BpmMessageServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.message.impl; +package cn.iocoder.yudao.module.bpm.service.message; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.message.BpmMessageEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; +import cn.iocoder.yudao.framework.web.config.WebProperties; +import cn.iocoder.yudao.module.bpm.convert.message.BpmMessageConvert; +import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; +import cn.iocoder.yudao.module.system.api.sms.SmsSendApi; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -26,18 +26,18 @@ import java.util.Map; public class BpmMessageServiceImpl implements BpmMessageService { @Resource - private SysSmsCoreService smsCoreService; + private SmsSendApi smsSendApi; - @Value("${yudao.url.admin-ui}") - private String adminUiUrl; + @Resource + private WebProperties webProperties; @Override public void sendMessageWhenProcessInstanceApprove(BpmMessageSendWhenProcessInstanceApproveReqDTO reqDTO) { Map templateParams = new HashMap<>(); templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); - smsCoreService.sendSingleSmsToAdmin(null, reqDTO.getStartUserId(), - BpmMessageEnum.PROCESS_INSTANCE_APPROVE.getSmsCode(), templateParams); + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), + BpmMessageEnum.PROCESS_INSTANCE_APPROVE.getSmsTemplateCode(), templateParams)); } @Override @@ -46,8 +46,8 @@ public class BpmMessageServiceImpl implements BpmMessageService { templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); templateParams.put("comment", reqDTO.getComment()); templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); - smsCoreService.sendSingleSmsToAdmin(null, reqDTO.getStartUserId(), - BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsCode(), templateParams); + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), + BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsTemplateCode(), templateParams)); } @Override @@ -57,12 +57,12 @@ public class BpmMessageServiceImpl implements BpmMessageService { templateParams.put("taskName", reqDTO.getTaskName()); templateParams.put("startUserNickname", reqDTO.getStartUserNickname()); templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); - smsCoreService.sendSingleSmsToAdmin(null, reqDTO.getAssigneeUserId(), - BpmMessageEnum.TASK_ASSIGNED.getSmsCode(), templateParams); + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), + BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams)); } private String getProcessInstanceDetailUrl(String taskId) { - return adminUiUrl + "bpm/process-instance/detail?id=" + taskId; + return webProperties.getAdminUi().getUrl() + "/bpm/process-instance/detail?id=" + taskId; } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java index ca46631f83..7c37734f97 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto; +package cn.iocoder.yudao.module.bpm.service.message.dto; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java index ae444ad34e..0194d03a5d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto; +package cn.iocoder.yudao.module.bpm.service.message.dto; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java index 51d3dc8307..bf9528f664 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.message.dto; +package cn.iocoder.yudao.module.bpm.service.message.dto; import lombok.Data; @@ -22,7 +22,7 @@ public class BpmMessageSendWhenTaskCreatedReqDTO { @NotEmpty(message = "流程实例的名字不能为空") private String processInstanceName; @NotEmpty(message = "发起人的用户编号") - private String startUserId; + private Long startUserId; @NotEmpty(message = "发起人的昵称") private String startUserNickname; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/BpmOALeaveService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/BpmOALeaveService.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java index 62d991d84f..a851f403cb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/BpmOALeaveService.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java @@ -1,9 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.oa; +package cn.iocoder.yudao.module.bpm.service.oa; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.*; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.BpmOALeaveDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; import javax.validation.Valid; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/BpmOALeaveServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/BpmOALeaveServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java index f55836d6e3..d0aadd95e6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/BpmOALeaveServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java @@ -1,24 +1,25 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.oa.impl; +package cn.iocoder.yudao.module.bpm.service.oa; import cn.hutool.core.date.DateUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.*; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.oa.BpmOALeaveConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.BpmOALeaveDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.BpmOALeaveMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.BpmOALeaveService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeaveCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOALeavePageReqVO; +import cn.iocoder.yudao.module.bpm.convert.oa.BpmOALeaveConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; +import java.util.HashMap; +import java.util.Map; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_LEAVE_NOT_EXISTS; /** * OA 请假申请 Service 实现类 @@ -39,7 +40,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService { private BpmOALeaveMapper leaveMapper; @Resource - private BpmProcessInstanceService processInstanceService; + private BpmProcessInstanceApi processInstanceApi; @Override @Transactional(rollbackFor = Exception.class) @@ -53,7 +54,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService { // 发起 BPM 流程 Map processInstanceVariables = new HashMap<>(); processInstanceVariables.put("day", day); - String processInstanceId = processInstanceService.createProcessInstance(userId, + String processInstanceId = processInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))); @@ -64,6 +65,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService { @Override public void updateLeaveResult(Long id, Integer result) { + validateLeaveExists(id); leaveMapper.updateById(new BpmOALeaveDO().setId(id).setResult(result)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/listener/BpmOALeaveResultListener.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/listener/BpmOALeaveResultListener.java rename to yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java index fcc716db94..2354070f09 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/listener/BpmOALeaveResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveResultListener.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.oa.listener; +package cn.iocoder.yudao.module.bpm.service.oa.listener; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventListener; -import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.BpmOALeaveService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.impl.BpmOALeaveServiceImpl; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService; +import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveServiceImpl; import org.springframework.stereotype.Component; import javax.annotation.Resource; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java new file mode 100644 index 0000000000..eaa615302a --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bpm.service.task; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormServiceTest.java b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java similarity index 81% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormServiceTest.java rename to yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java index c04d41d444..51073e865c 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmFormServiceTest.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java @@ -1,31 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.form.BpmFormUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmFormMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmFormFieldRespDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl.BpmFormServiceImpl; +import cn.iocoder.yudao.module.bpm.test.BaseDbUnitTest; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.FORM_NOT_EXISTS; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FORM_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java similarity index 58% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupServiceTest.java rename to yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java index a8704dd611..713e74ed2b 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmUserGroupServiceTest.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java @@ -1,28 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; -import cn.hutool.core.date.DateUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group.BpmUserGroupUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmUserGroupMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl.BpmUserGroupServiceImpl; +import cn.iocoder.yudao.module.bpm.test.BaseDbUnitTest; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.test.core.util.AssertUtils; +import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.USER_GROUP_NOT_EXISTS; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.*; /** * {@link BpmUserGroupServiceImpl} 的单元测试类 @@ -41,24 +37,24 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { @Test public void testCreateUserGroup_success() { // 准备参数 - BpmUserGroupCreateReqVO reqVO = randomPojo(BpmUserGroupCreateReqVO.class); + BpmUserGroupCreateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupCreateReqVO.class); // 调用 Long userGroupId = userGroupService.createUserGroup(reqVO); // 断言 - assertNotNull(userGroupId); + Assertions.assertNotNull(userGroupId); // 校验记录的属性是否正确 BpmUserGroupDO userGroup = userGroupMapper.selectById(userGroupId); - assertPojoEquals(reqVO, userGroup); + AssertUtils.assertPojoEquals(reqVO, userGroup); } @Test public void testUpdateUserGroup_success() { // mock 数据 - BpmUserGroupDO dbUserGroup = randomPojo(BpmUserGroupDO.class); + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class); userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据 // 准备参数 - BpmUserGroupUpdateReqVO reqVO = randomPojo(BpmUserGroupUpdateReqVO.class, o -> { + BpmUserGroupUpdateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupUpdateReqVO.class, o -> { o.setId(dbUserGroup.getId()); // 设置更新的 ID }); @@ -66,22 +62,22 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { userGroupService.updateUserGroup(reqVO); // 校验是否更新正确 BpmUserGroupDO userGroup = userGroupMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, userGroup); + AssertUtils.assertPojoEquals(reqVO, userGroup); } @Test public void testUpdateUserGroup_notExists() { // 准备参数 - BpmUserGroupUpdateReqVO reqVO = randomPojo(BpmUserGroupUpdateReqVO.class); + BpmUserGroupUpdateReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> userGroupService.updateUserGroup(reqVO), USER_GROUP_NOT_EXISTS); + AssertUtils.assertServiceException(() -> userGroupService.updateUserGroup(reqVO), USER_GROUP_NOT_EXISTS); } @Test public void testDeleteUserGroup_success() { // mock 数据 - BpmUserGroupDO dbUserGroup = randomPojo(BpmUserGroupDO.class); + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class); userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbUserGroup.getId(); @@ -89,22 +85,22 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { // 调用 userGroupService.deleteUserGroup(id); // 校验数据不存在了 - assertNull(userGroupMapper.selectById(id)); + Assertions.assertNull(userGroupMapper.selectById(id)); } @Test public void testDeleteUserGroup_notExists() { // 准备参数 - Long id = randomLongId(); + Long id = RandomUtils.randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> userGroupService.deleteUserGroup(id), USER_GROUP_NOT_EXISTS); + AssertUtils.assertServiceException(() -> userGroupService.deleteUserGroup(id), USER_GROUP_NOT_EXISTS); } @Test public void testGetUserGroupPage() { // mock 数据 - BpmUserGroupDO dbUserGroup = randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setCreateTime(DateUtils.buildTime(2021, 11, 11)); @@ -126,9 +122,9 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { // 调用 PageResult pageResult = userGroupService.getUserGroupPage(reqVO); // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbUserGroup, pageResult.getList().get(0)); + Assertions.assertEquals(1, pageResult.getTotal()); + Assertions.assertEquals(1, pageResult.getList().size()); + AssertUtils.assertPojoEquals(dbUserGroup, pageResult.getList().get(0)); } } diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java new file mode 100644 index 0000000000..86efb85986 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.bpm.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +/** + * 依赖内存 DB 的单元测试 + * + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB +public class BaseDbUnitTest { + + @Import({ + // DB 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类 + SqlInitializationAutoConfiguration.class, + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + }) + public static class Application { + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/application-unit-test.yaml b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000000..03f350677f --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/application-unit-test.yaml @@ -0,0 +1,40 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-core-service/src/test/resources/logback-spring.xml b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/logback.xml similarity index 100% rename from yudao-core-service/src/test/resources/logback-spring.xml rename to yudao-module-bpm/yudao-module-bpm-base/src/test/resources/logback.xml diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/clean.sql b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..43c1cc535b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/clean.sql @@ -0,0 +1,3 @@ +-- bpm 开头的 DB +DELETE FROM "bpm_form"; +DELETE FROM "bpm_user_group"; diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/create_tables.sql b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000000..92d2500645 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/test/resources/sql/create_tables.sql @@ -0,0 +1,29 @@ +-- bpm 开头的 DB +CREATE TABLE IF NOT EXISTS "bpm_user_group" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(63) NOT NULL, + "description" varchar(255) NOT NULL, + "status" tinyint NOT NULL, + "member_user_ids" varchar(255) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") + ) COMMENT '用户组'; + +CREATE TABLE IF NOT EXISTS "bpm_form" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(63) NOT NULL, + "status" tinyint NOT NULL, + "fields" varchar(255) NOT NULL, + "conf" varchar(255) NOT NULL, + "remark" varchar(255), + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '动态表单'; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/pom.xml b/yudao-module-bpm/yudao-module-bpm-impl-activiti/pom.xml new file mode 100644 index 0000000000..d130d12f7e --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/pom.xml @@ -0,0 +1,38 @@ + + + + cn.iocoder.boot + yudao-module-bpm + ${revision} + + 4.0.0 + yudao-module-bpm-impl-activiti + + ${artifactId} + + bpm-activiti 模块,基于 Activiti 7 实现工作流 + + + + + cn.iocoder.boot + yudao-module-bpm-base + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-activiti + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java new file mode 100644 index 0000000000..2137e22031 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java @@ -0,0 +1,4 @@ +/** + * bpm API 实现类,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.bpm.api; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java new file mode 100644 index 0000000000..a1d05e4fc2 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.bpm.api.task; + +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 流程实例 Api 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi { + + @Resource + private BpmProcessInstanceService processInstanceService; + + @Override + public String createProcessInstance(Long userId, BpmProcessInstanceCreateReqDTO reqDTO) { + return processInstanceService.createProcessInstance(userId, reqDTO); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmModelController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index c432f6804b..4a570d1fcd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; +package cn.iocoder.yudao.module.bpm.controller.admin.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmModelConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; +import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.io.IoUtils; @@ -19,7 +19,7 @@ import java.io.IOException; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "流程模型") +@Api(tags = "管理后台 - 流程模型") @RestController @RequestMapping("/bpm/model") @Validated @@ -30,7 +30,7 @@ public class BpmModelController { @GetMapping("/page") @ApiOperation(value = "获得模型分页") - public CommonResult> getModelPage(ModelPageReqVO pageVO) { + public CommonResult> getModelPage(BpmModelPageReqVO pageVO) { return success(bpmModelService.getModelPage(pageVO)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.http b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.http similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.http rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.http diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java index 4e38294c39..769e53ec55 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmProcessDefinitionController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; +package cn.iocoder.yudao.module.bpm.controller.admin.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import io.swagger.annotations.Api; @@ -23,7 +23,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "流程定义") +@Api(tags = "管理后台 - 流程定义") @RestController @RequestMapping("/bpm/process-definition") @Validated diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmTaskAssignRuleController.http b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.http similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmTaskAssignRuleController.http rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.http diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmTaskAssignRuleController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmTaskAssignRuleController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java index b1f3186fd1..1be0b74870 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/BpmTaskAssignRuleController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition; +package cn.iocoder.yudao.module.bpm.controller.admin.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -19,7 +19,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "任务分配规则") +@Api(tags = "管理后台 - 任务分配规则") @RestController @RequestMapping("/bpm/task-assign-rule") @Validated diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmActivityController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmActivityController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java index b5b7f59d98..224a942fb9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmActivityController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.activity.BpmActivityRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; +import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.swagger.annotations.Api; @@ -22,7 +22,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "流程活动实例") +@Api(tags = "管理后台 - 流程活动实例") @RestController @RequestMapping("/bpm/activity") @Validated @@ -34,7 +34,7 @@ public class BpmActivityController { @GetMapping("/list") @ApiOperation(value = "生成指定流程实例的高亮流程图", notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成") - @ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class) + @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class) @PreAuthorize("@ss.hasPermission('bpm:task:query')") public CommonResult> getActivityList( @RequestParam("processInstanceId") String processInstanceId) { @@ -44,7 +44,7 @@ public class BpmActivityController { @GetMapping("/generate-highlight-diagram") @ApiOperation(value = "生成指定流程实例的高亮流程图", notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成") - @ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class) + @ApiImplicitParam(name = "processInstanceId", value = "流程实例的编号", required = true, dataTypeClass = String.class) @PreAuthorize("@ss.hasPermission('bpm:task:query')") public void generateHighlightDiagram(@RequestParam("processInstanceId") String processInstanceId, HttpServletResponse response) throws IOException { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.http b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.http rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java index 4240e39af2..e859968ed0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.*; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import io.swagger.annotations.Api; @@ -17,7 +17,7 @@ import javax.validation.Valid; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Api(tags = "流程实例") // 流程实例,通过流程定义创建的一次“申请” +@Api(tags = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请” @RestController @RequestMapping("/bpm/process-instance") @Validated @@ -25,7 +25,7 @@ public class BpmProcessInstanceController { @Resource private BpmProcessInstanceService processInstanceService; - + @PostMapping("/create") @ApiOperation("新建流程实例") @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.http b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.http similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.http rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.http diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java index 3ad59a7aa1..3c3542aa34 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task; +package cn.iocoder.yudao.module.bpm.controller.admin.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -13,15 +12,13 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; -@Api(tags = "流程任务实例") +@Api(tags = "管理后台 - 流程任务实例") @RestController @RequestMapping("/bpm/task") @Validated diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java new file mode 100644 index 0000000000..e8d285e359 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.bpm.controller.app; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java new file mode 100644 index 0000000000..d1930bd6ac --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.bpm.controller; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java similarity index 93% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index eb3362ac62..445911c8ca 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; +package cn.iocoder.yudao.module.bpm.convert.definition; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import org.activiti.engine.impl.persistence.entity.SuspensionState; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.Model; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java index fb11704e67..17a4fb1446 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; +package cn.iocoder.yudao.module.bpm.convert.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.activiti.engine.impl.persistence.entity.SuspensionState; import org.activiti.engine.repository.Deployment; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmTaskAssignRuleConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmTaskAssignRuleConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java index a0f9528932..4be54fe7ac 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmTaskAssignRuleConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; +package cn.iocoder.yudao.module.bpm.convert.definition; -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.activiti.bpmn.model.UserTask; import org.mapstruct.Mapper; @@ -12,7 +11,6 @@ import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -import java.util.function.Function; @Mapper public interface BpmTaskAssignRuleConvert { diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java similarity index 57% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/package-info.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java index 3f27f0b4b9..6db6ebc461 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/convert/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java @@ -3,4 +3,4 @@ * * 目前使用 MapStruct 框架 */ -package cn.iocoder.yudao.userserver.modules.pay.convert; +package cn.iocoder.yudao.module.bpm.convert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java similarity index 67% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java index b72e28ac64..02bfaa24e8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java @@ -1,8 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.task; +package cn.iocoder.yudao.module.bpm.convert.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.activity.BpmActivityRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; import org.activiti.engine.history.HistoricActivityInstance; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -10,7 +8,6 @@ import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Map; /** * BPM 活动 Convert diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmProcessInstanceConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmProcessInstanceConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java index 88405027f5..abc94d89a0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmProcessInstanceConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java @@ -1,13 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.task; +package cn.iocoder.yudao.module.bpm.convert.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstancePageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.BpmProcessInstanceRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.repository.ProcessDefinition; @@ -19,10 +20,8 @@ import org.mapstruct.MappingTarget; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; -import java.sql.SQLXML; import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * 流程实例 Convert @@ -74,7 +73,7 @@ public interface BpmProcessInstanceConvert { default BpmProcessInstanceRespVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt, ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt, - String bpmnXml, SysUserDO startUser, SysDeptDO dept) { + String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) { BpmProcessInstanceRespVO respVO = convert2(processInstance); copyTo(processInstanceExt, respVO); // definition @@ -97,7 +96,7 @@ public interface BpmProcessInstanceConvert { BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean); @Mapping(source = "from.id", target = "to.id", ignore = true) void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessInstanceRespVO.ProcessDefinition to); - BpmProcessInstanceRespVO.User convert2(SysUserDO bean); + BpmProcessInstanceRespVO.User convert2(AdminUserRespDTO bean); default BpmProcessInstanceResultEvent convert(Object source, ProcessInstance instance, Integer result) { BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source); @@ -117,4 +116,20 @@ public interface BpmProcessInstanceConvert { return event; } + default BpmMessageSendWhenProcessInstanceRejectReqDTO convert(ProcessInstance processInstance, String comment) { + BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO = new BpmMessageSendWhenProcessInstanceRejectReqDTO(); + copyTo(processInstance, reqDTO); + reqDTO.setComment(comment); + return reqDTO; + } + @Mapping(source = "name", target = "processInstanceName") + void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenProcessInstanceRejectReqDTO to); + + @Mappings({ + @Mapping(source = "id", target = "processInstanceId"), + @Mapping(source = "name", target = "processInstanceName"), + @Mapping(source = "initiator", target = "startUserId") + }) + BpmMessageSendWhenProcessInstanceApproveReqDTO convert2(org.activiti.api.process.model.ProcessInstance processInstance); + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index 303a3d00ec..a8f499e1be 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -1,11 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.convert.task; +package cn.iocoder.yudao.module.bpm.convert.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskDonePageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.BpmTaskTodoPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskDonePageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; +import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import org.activiti.engine.history.HistoricProcessInstance; @@ -30,12 +31,12 @@ public interface BpmTaskConvert { BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class); default List convertList1(List tasks, Map processInstanceMap, - Map userMap) { + Map userMap) { return CollectionUtils.convertList(tasks, task -> { BpmTaskTodoPageItemRespVO respVO = convert1(task); ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId()); if (processInstance != null) { - SysUserDO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); respVO.setProcessInstance(convert(processInstance, startUser)); } return respVO; @@ -53,14 +54,14 @@ public interface BpmTaskConvert { default List convertList2(List tasks, Map bpmTaskExtDOMap, Map historicProcessInstanceMap, - Map userMap) { + Map userMap) { return CollectionUtils.convertList(tasks, task -> { BpmTaskDonePageItemRespVO respVO = convert2(task); BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId()); copyTo(taskExtDO, respVO); HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId()); if (processInstance != null) { - SysUserDO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); respVO.setProcessInstance(convert(processInstance, startUser)); } return respVO; @@ -77,20 +78,20 @@ public interface BpmTaskConvert { BpmTaskExtDO convert(org.activiti.api.task.model.Task bean); default List convertList3(List tasks, Map bpmTaskExtDOMap, - HistoricProcessInstance processInstance, Map userMap, - Map deptMap) { + HistoricProcessInstance processInstance, Map userMap, + Map deptMap) { return CollectionUtils.convertList(tasks, task -> { BpmTaskRespVO respVO = convert3(task); BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId()); copyTo(taskExtDO, respVO); if (processInstance != null) { - SysUserDO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); + AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId())); respVO.setProcessInstance(convert(processInstance, startUser)); } - SysUserDO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee())); + AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee())); if (assignUser != null) { respVO.setAssigneeUser(convert3(assignUser)); - SysDeptDO dept = deptMap.get(assignUser.getDeptId()); + DeptRespDTO dept = deptMap.get(assignUser.getDeptId()); if (dept != null) { respVO.getAssigneeUser().setDeptName(dept.getName()); } @@ -101,7 +102,7 @@ public interface BpmTaskConvert { @Mapping(source = "taskDefinitionKey", target = "definitionKey") BpmTaskRespVO convert3(HistoricTaskInstance bean); - BpmTaskRespVO.User convert3(SysUserDO bean); + BpmTaskRespVO.User convert3(AdminUserRespDTO bean); void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to); @@ -112,7 +113,7 @@ public interface BpmTaskConvert { @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), @Mapping(source = "startUser.nickname", target = "startUserNickname") }) - BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, SysUserDO startUser); + BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser); @Mappings({ @Mapping(source = "processInstance.id", target = "id"), @@ -121,6 +122,26 @@ public interface BpmTaskConvert { @Mapping(source = "processInstance.processDefinitionId", target = "processDefinitionId"), @Mapping(source = "startUser.nickname", target = "startUserNickname") }) - BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, SysUserDO startUser); + BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance, AdminUserRespDTO startUser); + default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, org.activiti.api.task.model.Task task) { + BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); + copyTo(processInstance, reqDTO); + copyTo(startUser, reqDTO); + copyTo(task, reqDTO); + return reqDTO; + } + @Mapping(source = "name", target = "processInstanceName") + void copyTo(ProcessInstance from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); + @Mappings({ + @Mapping(source = "id", target = "startUserId"), + @Mapping(source = "nickname", target = "startUserNickname") + }) + void copyTo(AdminUserRespDTO from, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); + @Mappings({ + @Mapping(source = "id", target = "taskId"), + @Mapping(source = "name", target = "taskName"), + @Mapping(source = "assignee", target = "assigneeUserId") + }) + void copyTo(org.activiti.api.task.model.Task task, @MappingTarget BpmMessageSendWhenTaskCreatedReqDTO to); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java similarity index 59% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java index ccb7cad788..181cc2d573 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java @@ -1,18 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.config; +package cn.iocoder.yudao.module.bpm.framework.activiti.config; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.BpmActivityBehaviorFactory; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventPublisher; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.identity.EmptyUserGroupManager; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener.BpmTackActivitiEventListener; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.BpmActivityBehaviorFactory; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.identity.EmptyUserGroupManager; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.listener.BpmTackActivitiEventListener; +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.activiti.api.runtime.shared.identity.UserGroupManager; import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -28,7 +26,15 @@ import static org.activiti.spring.boot.ProcessEngineAutoConfiguration.BEHAVIOR_F public class BpmActivitiConfiguration { /** - * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类,主要设置各种监听器、用户组管理 + * 空用户组的 Bean + */ + @Bean + public UserGroupManager userGroupManager() { + return new EmptyUserGroupManager(); + } + + /** + * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类,主要设置各种监听器 */ @Bean public ProcessEngineConfigurationConfigurer bpmProcessEngineConfigurationConfigurer( @@ -36,8 +42,6 @@ public class BpmActivitiConfiguration { return configuration -> { // 注册监听器,例如说 BpmActivitiEventListener configuration.setEventListeners(Collections.singletonList(taskActivitiEventListener)); - // 用户组 - configuration.setUserGroupManager(new EmptyUserGroupManager()); }; } @@ -58,24 +62,19 @@ public class BpmActivitiConfiguration { @Bean public BpmActivityBehaviorFactory bpmActivityBehaviorFactory(BpmTaskAssignRuleService taskRuleService, - SysPermissionService permissionService, - SysDeptService deptService, BpmUserGroupService userGroupService, - SysUserService userService, + PermissionApi permissionApi, + DeptApi deptApi, + AdminUserApi adminUserApi, List scripts) { BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory(); bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService); - bpmActivityBehaviorFactory.setPermissionService(permissionService); - bpmActivityBehaviorFactory.setDeptService(deptService); bpmActivityBehaviorFactory.setUserGroupService(userGroupService); - bpmActivityBehaviorFactory.setUserService(userService); + bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi); + bpmActivityBehaviorFactory.setPermissionApi(permissionApi); + bpmActivityBehaviorFactory.setDeptApi(deptApi); bpmActivityBehaviorFactory.setScripts(scripts); return bpmActivityBehaviorFactory; } - @Bean - public BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher(ApplicationEventPublisher publisher) { - return new BpmProcessInstanceResultEventPublisher(publisher); - } - } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java index 1e3f542fae..d394f8631e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Setter; @@ -14,7 +14,6 @@ import org.activiti.bpmn.model.UserTask; import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory; -import javax.annotation.Resource; import java.util.List; /** @@ -31,13 +30,15 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { @Setter private BpmTaskAssignRuleService bpmTaskRuleService; @Setter - private SysPermissionService permissionService; - @Setter - private SysDeptService deptService; - @Setter private BpmUserGroupService userGroupService; + @Setter - private SysUserService userService; + private PermissionApi permissionApi; + @Setter + private DeptApi deptApi; + @Setter + private AdminUserApi adminUserApi; + @Setter private List scripts; @@ -45,10 +46,10 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) { BpmUserTaskActivitiBehavior userTaskActivityBehavior = new BpmUserTaskActivitiBehavior(userTask); userTaskActivityBehavior.setBpmTaskRuleService(bpmTaskRuleService); - userTaskActivityBehavior.setPermissionService(permissionService); - userTaskActivityBehavior.setDeptService(deptService); + userTaskActivityBehavior.setPermissionApi(permissionApi); + userTaskActivityBehavior.setDeptApi(deptApi); userTaskActivityBehavior.setUserGroupService(userGroupService); - userTaskActivityBehavior.setUserService(userService); + userTaskActivityBehavior.setAdminUserApi(adminUserApi); userTaskActivityBehavior.setScripts(scripts); return userTaskActivityBehavior; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java index 55c426db03..9fb1f5abb4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehavior.java @@ -1,20 +1,20 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.google.common.annotations.VisibleForTesting; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -28,12 +28,12 @@ import org.activiti.engine.impl.persistence.entity.TaskEntityManager; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; /** * 自定义的流程任务的 assignee 负责人的分配 @@ -48,14 +48,17 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { @Setter private BpmTaskAssignRuleService bpmTaskRuleService; - @Setter - private SysPermissionService permissionService; - @Setter - private SysDeptService deptService; + @Setter private BpmUserGroupService userGroupService; + @Setter - private SysUserService userService; + private DeptApi deptApi; + @Setter + private AdminUserApi adminUserApi; + @Setter + private PermissionApi permissionApi; + /** * 任务分配脚本 */ @@ -133,22 +136,22 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { } private Set calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) { - return permissionService.getUserRoleIdListByRoleIds(rule.getOptions()); + return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions()); } private Set calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) { - List users = userService.getUsersByDeptIds(rule.getOptions()); - return convertSet(users, SysUserDO::getId); + List users = adminUserApi.getUsersByDeptIds(rule.getOptions()); + return convertSet(users, AdminUserRespDTO::getId); } private Set calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) { - List depts = deptService.getDepts(rule.getOptions()); - return convertSet(depts, SysDeptDO::getLeaderUserId); + List depts = deptApi.getDepts(rule.getOptions()); + return convertSet(depts, DeptRespDTO::getLeaderUserId); } private Set calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) { - List users = userService.getUsersByPostIds(rule.getOptions()); - return convertSet(users, SysUserDO::getId); + List users = adminUserApi.getUsersByPostIds(rule.getOptions()); + return convertSet(users, AdminUserRespDTO::getId); } private Set calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) { @@ -158,7 +161,7 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { private Set calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) { List userGroups = userGroupService.getUserGroupList(rule.getOptions()); Set userIds = new HashSet<>(); - userGroups.forEach(bpmUserGroupDO -> userIds.addAll(bpmUserGroupDO.getMemberUserIds())); + userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds())); return userIds; } @@ -183,9 +186,9 @@ public class BpmUserTaskActivitiBehavior extends UserTaskActivityBehavior { if (CollUtil.isEmpty(assigneeUserIds)) { return; } - Map userMap = userService.getUserMap(assigneeUserIds); + Map userMap = adminUserApi.getUserMap(assigneeUserIds); assigneeUserIds.removeIf(id -> { - SysUserDO user = userMap.get(id); + AdminUserRespDTO user = userMap.get(id); return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus()); }); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/package-info.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java index eaf54d5ddb..e627479a5b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java @@ -1,7 +1,7 @@ /** - * 拓展 {@link org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior} 实现,基于 {@link cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO} 实现自定义的任务分配规则。 + * 拓展 {@link org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior} 实现,基于 {@link cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO} 实现自定义的任务分配规则。 * 原因:BPMN 默认的 assign、candidateUsers、candidateGroups 拓展起来有一定的难度,所以选择放弃它们,使用自己定义的规则。 * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java index b70b1ce722..eee0d3f408 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; import org.activiti.engine.impl.persistence.entity.TaskEntity; -import java.util.List; import java.util.Set; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java index cfb3b2a22c..c27567018a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java @@ -1,10 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; + +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.springframework.util.Assert; @@ -23,16 +24,16 @@ import static java.util.Collections.emptySet; public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript { @Resource - private SysUserService userService; + private AdminUserApi adminUserApi; @Resource - private SysDeptService deptService; + private DeptApi deptApi; protected Set calculateTaskCandidateUsers(TaskEntity task, int level) { Assert.isTrue(level > 0, "level 必须大于 0"); // 获得发起人 Long startUserId = Long.parseLong(task.getProcessInstance().getStartUserId()); // 获得对应 leve 的部门 - SysDeptDO dept = null; + DeptRespDTO dept = null; for (int i = 0; i < level; i++) { // 获得 level 对应的部门 if (dept == null) { @@ -41,7 +42,7 @@ public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssign return emptySet(); } } else { - SysDeptDO parentDept = deptService.getDept(dept.getParentId()); + DeptRespDTO parentDept = deptApi.getDept(dept.getParentId()); if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少 break; } @@ -51,12 +52,12 @@ public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssign return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); } - private SysDeptDO getStartUserDept(Long startUserId) { - SysUserDO startUser = userService.getUser(startUserId); + private DeptRespDTO getStartUserDept(Long startUserId) { + AdminUserRespDTO startUser = adminUserApi.getUser(startUserId); if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则 return null; } - return deptService.getDept(startUser.getDeptId()); + return deptApi.getDept(startUser.getDeptId()); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java index d29029bb3d..e0714731a5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java index 35d7f73568..7ad928c8d3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java index 3f7617fdb2..af8846cbe6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java index b4b86b228a..22786da10c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.identity; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.identity; import org.activiti.api.runtime.shared.identity.UserGroupManager; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java index 90c1f3ef1a..6ed7297d72 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java @@ -1,14 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.listener; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import org.activiti.api.model.shared.event.RuntimeEvent; import org.activiti.api.process.model.ProcessInstance; import org.activiti.api.process.model.events.ProcessRuntimeEvent; import org.activiti.api.process.runtime.events.ProcessCancelledEvent; -import org.activiti.api.process.runtime.events.listener.ProcessEventListener; import org.activiti.api.process.runtime.events.listener.ProcessRuntimeEventListener; -import org.activiti.api.task.model.events.TaskRuntimeEvent; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java index 307263e0c5..4b6c21cfde 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java @@ -1,8 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.listener; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import org.activiti.api.process.runtime.events.listener.ProcessRuntimeEventListener; +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import org.activiti.api.task.runtime.events.listener.TaskEventListener; import org.activiti.engine.delegate.event.ActivitiEvent; import org.activiti.engine.delegate.event.ActivitiEventListener; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTaskEventListener.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java index b03f6b8021..da8c6238df 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java @@ -1,13 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.listener; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.listener; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import org.activiti.api.model.shared.event.RuntimeEvent; -import org.activiti.api.process.model.ProcessInstance; -import org.activiti.api.process.model.events.ProcessRuntimeEvent; import org.activiti.api.task.model.Task; import org.activiti.api.task.model.events.TaskRuntimeEvent; -import org.activiti.api.task.runtime.events.listener.TaskEventListener; import org.activiti.api.task.runtime.events.listener.TaskRuntimeEventListener; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java new file mode 100644 index 0000000000..eca41904cc --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java @@ -0,0 +1,7 @@ +/** + * 自定义各种 Activiti 的监听器,实现流程示例、流程任务的拓展表信息的同步 + * 例如说,{@link org.activiti.api.task.model.Task} 新建时,我们也要新建对应的 {@link cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO} 记录 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.bpm.framework.activiti.core.listener; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java new file mode 100644 index 0000000000..52fdb7f935 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 bpm 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.bpm.framework; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java new file mode 100644 index 0000000000..5713e495c7 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java @@ -0,0 +1,12 @@ +/** + * bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 activiti 7 版本实现。 + * 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等 + * + * bpm 解释:https://baike.baidu.com/item/BPM/1933 + * + * 1. Controller URL:以 /bpm/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 bpm_ 开头,方便在数据库中区分 + * + * 注意,由于 Bpm 模块下,容易和其它模块重名,所以类名都加载 Pay 的前缀~ + */ +package cn.iocoder.yudao.module.bpm; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmModelService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java index 496f9a45f9..ec2d6a0c93 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmModelService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; import org.activiti.bpmn.model.BpmnModel; import javax.validation.Valid; @@ -19,7 +19,7 @@ public interface BpmModelService { * @param pageVO 分页查询 * @return 流程模型分页 */ - PageResult getModelPage(ModelPageReqVO pageVO); + PageResult getModelPage(BpmModelPageReqVO pageVO); /** * 获得流程模块 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 60a3138639..3626bd58c8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -1,25 +1,21 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmModelConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.BpmnModel; import org.activiti.engine.RepositoryService; @@ -37,10 +33,9 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程定义实现 @@ -57,7 +52,7 @@ public class BpmModelServiceImpl implements BpmModelService { @Resource private RepositoryService repositoryService; @Resource - private BpmFormService formService; + private BpmFormService bpmFormService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource @@ -65,7 +60,7 @@ public class BpmModelServiceImpl implements BpmModelService { private BpmTaskAssignRuleService taskAssignRuleService; @Override - public PageResult getModelPage(ModelPageReqVO pageVO) { + public PageResult getModelPage(BpmModelPageReqVO pageVO) { ModelQuery modelQuery = repositoryService.createModelQuery(); if (StrUtil.isNotBlank(pageVO.getKey())) { modelQuery.modelKey(pageVO.getKey()); @@ -85,7 +80,7 @@ public class BpmModelServiceImpl implements BpmModelService { BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class); return metaInfo != null ? metaInfo.getFormId() : null; }); - Map formMap = formService.getFormMap(formIds); + Map formMap = bpmFormService.getFormMap(formIds); // 获得 Deployment Map Set deploymentIds = new HashSet<>(); @@ -232,7 +227,7 @@ public class BpmModelServiceImpl implements BpmModelService { } // 校验表单存在 if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) { - BpmFormDO form = formService.getForm(metaInfo.getFormId()); + BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId()); if (form == null) { throw exception(FORM_NOT_EXISTS); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java index b4a04a101d..7fe2a28de5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.activiti.bpmn.model.BpmnModel; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 289cd4d639..538e2a05cf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -1,22 +1,20 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmProcessDefinitionConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert; +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.BpmnModel; import org.activiti.engine.RepositoryService; @@ -31,9 +29,10 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; import static java.util.Collections.emptyList; /** @@ -54,7 +53,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @Resource private RepositoryService repositoryService; @Resource - private BpmFormService bpmFormService; + private BpmFormService formService; @Resource private BpmProcessDefinitionExtMapper processDefinitionMapper; @@ -85,7 +84,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ // 获得 Form Map Set formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId); - Map formMap = bpmFormService.getFormMap(formIds); + Map formMap = formService.getFormMap(formIds); // 拼接结果 long definitionCount = definitionQuery.count(); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java index 1105ddaa7e..19e7f9684a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition; +package cn.iocoder.yudao.module.bpm.service.definition; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; -import org.activiti.engine.repository.ProcessDefinition; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import org.springframework.lang.Nullable; import javax.validation.Valid; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java index 16ae1859a9..2f4eaa3108 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java @@ -1,30 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; +package cn.iocoder.yudao.module.bpm.service.definition; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmTaskAssignRuleConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; +import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; +import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.PostApi; +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; +import cn.iocoder.yudao.module.system.api.permission.RoleApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.UserTask; @@ -35,9 +29,8 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants.BPM_TASK_ASSIGN_RULE_TYPE; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * BPM 任务分配规则 Service 实现类 @@ -57,17 +50,17 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @Lazy // 解决循环依赖 private BpmProcessDefinitionService processDefinitionService; @Resource - private SysRoleService roleService; - @Resource - private SysDeptService deptService; - @Resource - private SysPostService postService; - @Resource - private SysUserService userService; - @Resource private BpmUserGroupService userGroupService; @Resource - private SysDictDataService dictDataService; + private RoleApi roleApi; + @Resource + private DeptApi deptApi; + @Resource + private PostApi postApi; + @Resource + private AdminUserApi adminUserApi; + @Resource + private DictDataApi dictDataApi; @Override public List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, @@ -182,18 +175,18 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { private void validTaskAssignRuleOptions(Integer type, Set options) { if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) { - roleService.validRoles(options); + roleApi.validRoles(options); } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) { - deptService.validDepts(options); + deptApi.validDepts(options); } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) { - postService.validPosts(options); + postApi.validPosts(options); } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) { - userService.validUsers(options); + adminUserApi.validUsers(options); } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) { userGroupService.validUserGroups(options); } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) { - dictDataService.validDictDatas(SysDictTypeConstants.BPM_TASK_ASSIGN_SCRIPT, + dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT, CollectionUtils.convertSet(options, String::valueOf)); } else { throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type)); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java index 5ff8f18151..e50dae3c36 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmModelMetaInfoRespDTO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto; +package cn.iocoder.yudao.module.bpm.service.definition.dto; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import lombok.Data; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java index 11a8245d5a..8b2d22ad58 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto; +package cn.iocoder.yudao.module.bpm.service.definition.dto; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import lombok.Data; import javax.validation.constraints.AssertTrue; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmActivityService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmActivityService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java index 8fb15f5ba2..e7c28648a4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmActivityService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task; +package cn.iocoder.yudao.module.bpm.service.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.activity.BpmActivityRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; import java.util.List; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java index 7c4253ec6e..2db1dc3e5c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java @@ -1,20 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.io.IoUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.activity.BpmActivityRespVO; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmActivityConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert; +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO; import lombok.extern.slf4j.Slf4j; import org.activiti.bpmn.model.BpmnModel; import org.activiti.engine.HistoryService; -import org.activiti.engine.RepositoryService; -import org.activiti.engine.RuntimeService; import org.activiti.engine.history.HistoricActivityInstance; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.task.Task; @@ -26,11 +19,9 @@ import javax.annotation.Resource; import java.io.InputStream; import java.util.Collections; import java.util.List; -import java.util.Map; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * BPM 活动实例 Service 实现类 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java index 8defdd23de..6dcacac1f8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task; +package cn.iocoder.yudao.module.bpm.service.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.*; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.activiti.engine.history.HistoricProcessInstance; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 7c87142d0e..190170b387 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1,31 +1,26 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.instance.*; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.message.BpmMessageConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmProcessInstanceConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceStatusEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEvent; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventListener; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.event.BpmProcessInstanceResultEventPublisher; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.dto.BpmProcessInstanceCreateReqDTO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; +import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; +import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.activiti.engine.HistoryService; import org.activiti.engine.RuntimeService; @@ -41,9 +36,9 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 @@ -68,9 +63,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService private HistoryService historyService; @Resource - private SysUserService userService; + private AdminUserApi adminUserApi; @Resource - private SysDeptService deptService; + private DeptApi deptApi; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @@ -192,10 +187,10 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User - SysUserDO startUser = userService.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); - SysDeptDO dept = null; + AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); + DeptRespDTO dept = null; if (startUser != null) { - dept = deptService.getDept(startUser.getDeptId()); + dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 @@ -282,7 +277,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 - messageService.sendMessageWhenProcessInstanceApprove(BpmMessageConvert.INSTANCE.convert(instance)); + messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( @@ -305,7 +300,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 - messageService.sendMessageWhenProcessInstanceReject(BpmMessageConvert.INSTANCE.convert(processInstance, comment)); + messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert(processInstance, comment)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index cad468a2e3..025ee461fc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task; +package cn.iocoder.yudao.module.bpm.service.task; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import org.activiti.engine.task.Task; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index b9a0ec3448..b4cb99fb1a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1,24 +1,22 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.*; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.message.BpmMessageConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.convert.task.BpmTaskConvert; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task.BpmTaskExtDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.task.BpmTaskExtMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.service.message.BpmMessageService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; +import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; +import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; + import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.activiti.engine.HistoryService; import org.activiti.engine.TaskService; @@ -38,10 +36,10 @@ import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程任务实例 Service 实现类 @@ -59,9 +57,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { private HistoryService historyService; @Resource - private SysUserService userService; + private AdminUserApi adminUserApi; @Resource - private SysDeptService deptService; + private DeptApi deptApi; @Resource @Lazy // 解决循环依赖 private BpmProcessInstanceService processInstanceService; @@ -95,9 +93,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 获得 User Map Set userIds = convertSet(tasks, task -> NumberUtils.parseLong(task.getAssignee())); userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); - Map userMap = userService.getUserMap(userIds); + Map userMap = adminUserApi.getUserMap(userIds); // 获得 Dept Map - Map deptMap = deptService.getDeptMap(convertSet(userMap.values(), SysUserDO::getDeptId)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); // 拼接数据 return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap); @@ -144,7 +142,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { Map processInstanceMap = processInstanceService.getProcessInstanceMap( convertSet(tasks, Task::getProcessInstanceId)); // 获得 User Map - Map userMap = userService.getUserMap( + Map userMap = adminUserApi.getUserMap( convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); // 拼接结果 return new PageResult<>(BpmTaskConvert.INSTANCE.convertList1(tasks, processInstanceMap, userMap), @@ -180,7 +178,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { Map historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap( convertSet(tasks, HistoricTaskInstance::getProcessInstanceId)); // 获得 User Map - Map userMap = userService.getUserMap( + Map userMap = adminUserApi.getUserMap( convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId()))); // 拼接结果 return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap), @@ -291,8 +289,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { @Override public void afterCommit() { ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); - SysUserDO startUser = userService.getUser(Long.valueOf(processInstance.getStartUserId())); - messageService.sendMessageWhenTaskAssigned(BpmMessageConvert.INSTANCE.convert(processInstance, startUser, task)); + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId())); + messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); } }); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/package-info.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java index 01ecbf3a26..0ffb3a8949 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/package-info.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java @@ -9,4 +9,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.bpm.service.task; +package cn.iocoder.yudao.module.bpm.service.task; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java similarity index 68% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java index 8111823a88..b05b712a30 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivitiBehaviorTest.java @@ -1,34 +1,35 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior; import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmUserGroupDO; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum; -import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.activiti.engine.impl.persistence.entity.TaskEntity; -import org.activiti.engine.impl.persistence.entity.TaskEntityImpl; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -39,13 +40,14 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { @Mock private BpmTaskAssignRuleService bpmTaskRuleService; @Mock - private SysPermissionService permissionService; - @Mock - private SysDeptService deptService; - @Mock private BpmUserGroupService userGroupService; + @Mock - private SysUserService userService; + private DeptApi deptApi; + @Mock + private AdminUserApi adminUserApi; + @Mock + private PermissionApi permissionApi; @Test public void testCalculateTaskCandidateUsers_Role() { @@ -53,7 +55,7 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L)) .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType()); // mock 方法 - when(permissionService.getUserRoleIdListByRoleIds(eq(rule.getOptions()))) + when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions()))) .thenReturn(asSet(11L, 22L)); mockGetUserMap(asSet(11L, 22L)); @@ -69,9 +71,9 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L)) .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType()); // mock 方法 - List users = CollectionUtils.convertList(asSet(11L, 22L), - id -> new SysUserDO().setId(id)); - when(userService.getUsersByDeptIds(eq(rule.getOptions()))).thenReturn(users); + List users = CollectionUtils.convertList(asSet(11L, 22L), + id -> new AdminUserRespDTO().setId(id)); + when(adminUserApi.getUsersByDeptIds(eq(rule.getOptions()))).thenReturn(users); mockGetUserMap(asSet(11L, 22L)); // 调用 @@ -86,9 +88,9 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L)) .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType()); // mock 方法 - SysDeptDO dept1 = randomPojo(SysDeptDO.class, o -> o.setLeaderUserId(11L)); - SysDeptDO dept2 = randomPojo(SysDeptDO.class, o -> o.setLeaderUserId(22L)); - when(deptService.getDepts(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2)); + DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L)); + DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L)); + when(deptApi.getDepts(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2)); mockGetUserMap(asSet(11L, 22L)); // 调用 @@ -103,9 +105,9 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L)) .setType(BpmTaskAssignRuleTypeEnum.POST.getType()); // mock 方法 - List users = CollectionUtils.convertList(asSet(11L, 22L), - id -> new SysUserDO().setId(id)); - when(userService.getUsersByPostIds(eq(rule.getOptions()))).thenReturn(users); + List users = CollectionUtils.convertList(asSet(11L, 22L), + id -> new AdminUserRespDTO().setId(id)); + when(adminUserApi.getUsersByPostIds(eq(rule.getOptions()))).thenReturn(users); mockGetUserMap(asSet(11L, 22L)); // 调用 @@ -189,13 +191,13 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到 Set assigneeUserIds = asSet(1L, 2L, 3L); // mock 方法 - SysUserDO user1 = randomPojo(SysUserDO.class, o -> o.setId(1L) + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L) .setStatus(CommonStatusEnum.ENABLE.getStatus())); - SysUserDO user2 = randomPojo(SysUserDO.class, o -> o.setId(2L) + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L) .setStatus(CommonStatusEnum.DISABLE.getStatus())); - Map userMap = MapUtil.builder(user1.getId(), user1) + Map userMap = MapUtil.builder(user1.getId(), user1) .put(user2.getId(), user2).build(); - when(userService.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); // 调用 behavior.removeDisableUsers(assigneeUserIds); @@ -204,9 +206,9 @@ public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest { } private void mockGetUserMap(Set assigneeUserIds) { - Map userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id, - id -> new SysUserDO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(userService.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); + Map userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id, + id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus())); + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java similarity index 59% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java index ec12b5467a..d44c5c8067 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java @@ -1,26 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl; +package cn.iocoder.yudao.module.bpm.framework.activiti.core.behavior.script.impl; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.persistence.entity.TaskEntityImpl; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; - -import javax.annotation.Resource; +import org.springframework.boot.test.mock.mockito.MockBean; import java.util.Set; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { @@ -29,17 +27,17 @@ class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { private BpmTaskAssignLeaderX2Script script; @Mock - private SysUserService userService; + private AdminUserApi adminUserApi; @Mock - private SysDeptService deptService; + private DeptApi deptApi; @Test public void testCalculateTaskCandidateUsers_noDept() { // 准备参数 TaskEntity task = buildTaskEntity(1L); // mock 方法(startUser) - SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L)); - when(userService.getUser(eq(1L))).thenReturn(startUser); + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L)); + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser); // 调用 Set result = script.calculateTaskCandidateUsers(task); @@ -52,11 +50,11 @@ class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { // 准备参数 TaskEntity task = buildTaskEntity(1L); // mock 方法(startUser) - SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L)); - when(userService.getUser(eq(1L))).thenReturn(startUser); - SysDeptDO startUserDept = randomPojo(SysDeptDO.class, o -> o.setId(10L).setParentId(100L) + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L)); + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser); + DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L) .setLeaderUserId(20L)); - when(deptService.getDept(eq(10L))).thenReturn(startUserDept); + when(deptApi.getDept(eq(10L))).thenReturn(startUserDept); // 调用 Set result = script.calculateTaskCandidateUsers(task); @@ -69,15 +67,15 @@ class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest { // 准备参数 TaskEntity task = buildTaskEntity(1L); // mock 方法(startUser) - SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L)); - when(userService.getUser(eq(1L))).thenReturn(startUser); - SysDeptDO startUserDept = randomPojo(SysDeptDO.class, o -> o.setId(10L).setParentId(100L) + AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L)); + when(adminUserApi.getUser(eq(1L))).thenReturn(startUser); + DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L) .setLeaderUserId(20L)); - when(deptService.getDept(eq(10L))).thenReturn(startUserDept); + when(deptApi.getDept(eq(10L))).thenReturn(startUserDept); // mock 方法(父 dept) - SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setId(100L).setParentId(1000L) + DeptRespDTO parentDept = randomPojo(DeptRespDTO.class, o -> o.setId(100L).setParentId(1000L) .setLeaderUserId(200L)); - when(deptService.getDept(eq(100L))).thenReturn(parentDept); + when(deptApi.getDept(eq(100L))).thenReturn(parentDept); // 调用 Set result = script.calculateTaskCandidateUsers(task); diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java new file mode 100644 index 0000000000..bda0cb8cae --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bpm.service; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbUnitTest.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java similarity index 91% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbUnitTest.java rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java index 5f7daeded1..171ea883f8 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbUnitTest.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/test/BaseDbUnitTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.module.bpm.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; @@ -20,6 +20,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbUnitTest { diff --git a/yudao-admin-server/src/test/resources/application-unit-test.yaml b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/application-unit-test.yaml similarity index 92% rename from yudao-admin-server/src/test/resources/application-unit-test.yaml rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/application-unit-test.yaml index d306a7af43..9f36ec4ac9 100644 --- a/yudao-admin-server/src/test/resources/application-unit-test.yaml +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/application-unit-test.yaml @@ -13,7 +13,6 @@ spring: driver-class-name: org.h2.Driver username: sa password: - schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具 druid: async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 initial-size: 1 # 单元测试,配置为 1,提升启动速度 @@ -42,3 +41,6 @@ mybatis: --- #################### 芋道相关配置 #################### # 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-user-server/src/test/resources/logback-spring.xml b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/logback.xml similarity index 100% rename from yudao-user-server/src/test/resources/logback-spring.xml rename to yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/logback.xml diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/clean.sql b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..c14acfe995 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/clean.sql @@ -0,0 +1,2 @@ +-- bpm 开头的 DB +DELETE FROM "bpm_form"; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/create_tables.sql b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000000..54e6ab622a --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/create_tables.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS "bpm_form" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(63) NOT NULL, + "status" tinyint NOT NULL, + "fields" varchar(255) NOT NULL, + "conf" varchar(255) NOT NULL, + "remark" varchar(255), + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") + ) COMMENT '动态表单'; + +CREATE TABLE IF NOT EXISTS "bpm_user_group" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(63) NOT NULL, + "description" varchar(255) NOT NULL, + "status" tinyint NOT NULL, + "member_user_ids" varchar(255) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") + ) COMMENT '用户组'; diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml new file mode 100644 index 0000000000..6c83994edc --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml @@ -0,0 +1,30 @@ + + + + cn.iocoder.boot + yudao-module-bpm + ${revision} + + 4.0.0 + yudao-module-bpm-impl-flowable + + ${artifactId} + + bpm-flowable 模块,基于 Flowable 6 实现工作流 + + + + + + org.flowable + flowable-spring-boot-starter-basic + + + org.flowable + flowable-spring-boot-starter-actuator + + + + diff --git a/yudao-module-infra/pom.xml b/yudao-module-infra/pom.xml new file mode 100644 index 0000000000..49376974e2 --- /dev/null +++ b/yudao-module-infra/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-module-infra-api + yudao-module-infra-impl + + yudao-module-infra + pom + + ${artifactId} + + infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 + 例如说:定时任务的管理、服务器的信息等等 + + + diff --git a/yudao-module-infra/yudao-module-infra-api/pom.xml b/yudao-module-infra/yudao-module-infra-api/pom.xml new file mode 100644 index 0000000000..b1c79c2d24 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/pom.xml @@ -0,0 +1,26 @@ + + + + cn.iocoder.boot + yudao-module-infra + ${revision} + + 4.0.0 + yudao-module-infra-api + jar + + ${artifactId} + + infra 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java new file mode 100644 index 0000000000..5d55c57316 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApi.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.infra.api.file; + +import cn.hutool.core.util.IdUtil; + +/** + * 文件 API 接口 + * + * @author 芋道源码 + */ +public interface FileApi { + + /** + * 保存文件,并返回文件的访问路径 + * + * @param content 文件内容 + * @return 文件路径 + */ + default String createFile(byte[] content) { + return createFile(IdUtil.fastUUID(), content); + } + + /** + * 保存文件,并返回文件的访问路径 + * + * @param path 文件路径 + * @param content 文件内容 + * @return 文件路径 + */ + String createFile(String path, byte[] content); + +} diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java new file mode 100644 index 0000000000..9ed9a778e9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java @@ -0,0 +1,4 @@ +/** + * infra API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.infra.api; diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/DictTypeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/DictTypeConstants.java new file mode 100644 index 0000000000..53ab807cbc --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/DictTypeConstants.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.enums; + +/** + * Infra 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String REDIS_TIMEOUT_TYPE = "infra_redis_timeout_type"; // Redis 超时类型 + + String JOB_STATUS = "infra_job_status"; // 定时任务状态的枚举 + String JOB_LOG_STATUS = "infra_job_log_status"; // 定时任务日志状态的枚举 + + String API_ERROR_LOG_PROCESS_STATUS = "infra_api_error_log_process_status"; // API 错误日志的处理状态的枚举 + + String CONFIG_TYPE = "infra_config_type"; // 参数配置类型 + String BOOLEAN_STRING = "infra_boolean_string"; // Boolean 是否类型 + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfErrorCodeConstants.java rename to yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index 98155e7236..03eefe17f1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums; +package cn.iocoder.yudao.module.infra.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; * * infra 系统,使用 1-001-000-000 段 */ -public interface InfErrorCodeConstants { +public interface ErrorCodeConstants { // ========== 参数配置 1001000000 ========== ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1001000001, "参数配置不存在"); @@ -27,4 +27,8 @@ public interface InfErrorCodeConstants { ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在"); ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理"); + // ========= 文件相关 1001003000================= + ErrorCode FILE_PATH_EXISTS = new ErrorCode(1001003000, "文件路径已存在"); + ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003001, "文件不存在"); + } diff --git a/yudao-user-server/pom.xml b/yudao-module-infra/yudao-module-infra-impl/pom.xml similarity index 62% rename from yudao-user-server/pom.xml rename to yudao-module-infra/yudao-module-infra-impl/pom.xml index be40058354..67dda6647c 100644 --- a/yudao-user-server/pom.xml +++ b/yudao-module-infra/yudao-module-infra-impl/pom.xml @@ -4,44 +4,47 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> cn.iocoder.boot - yudao + yudao-module-infra ${revision} 4.0.0 - - yudao-user-server + yudao-module-infra-impl jar - yudao-user-server - 用户前台 Server,提供其 API 接口 - https://github.com/YunaiV/ruoyi-vue-pro + ${artifactId} + + infra 模块,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 + 例如说:定时任务的管理、服务器的信息等等 + + + cn.iocoder.boot + yudao-module-member-api + ${revision} + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-infra-api + ${revision} + + cn.iocoder.boot - yudao-core-service - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-dict + yudao-spring-boot-starter-biz-operatelog cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-weixin + yudao-spring-boot-starter-biz-tenant - - cn.iocoder.boot - yudao-spring-boot-starter-web - - cn.iocoder.boot yudao-spring-boot-starter-security @@ -64,56 +67,40 @@ yudao-spring-boot-starter-config - - cn.iocoder.boot yudao-spring-boot-starter-mq - - - cn.iocoder.boot - yudao-spring-boot-starter-protection - - - - - cn.iocoder.boot - yudao-spring-boot-starter-monitor - - cn.iocoder.boot yudao-spring-boot-starter-test test - + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + cn.smallbun.screw + screw-core + + + + + cn.iocoder.boot + yudao-spring-boot-starter-monitor + + + + de.codecentric + spring-boot-admin-starter-server + - - - ${artifactId} - - - - org.springframework.boot - spring-boot-maven-plugin - - true - - - - - repackage - - - - - - - diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java new file mode 100644 index 0000000000..c5ce8db198 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.infra.api.file; + +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.infra.service.file.FileService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 文件 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class FileApiImpl implements FileApi { + + @Resource + private FileService fileService; + + @Override + public String createFile(String path, byte[] content) { + return fileService.createFile(path, content); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java new file mode 100644 index 0000000000..af01680f6a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/api/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.infra.api; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/InfConfigController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/InfConfigController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java index 3167a09d17..73c3a2e528 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/InfConfigController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java @@ -1,13 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config; +package cn.iocoder.yudao.module.infra.controller.admin.config; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.*; -import cn.iocoder.yudao.adminserver.modules.infra.convert.config.InfConfigConvert; -import cn.iocoder.yudao.adminserver.modules.infra.service.config.InfConfigService; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.*; +import cn.iocoder.yudao.module.infra.convert.config.ConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; +import cn.iocoder.yudao.module.infra.service.config.ConfigService; +import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -21,31 +23,29 @@ import javax.validation.Valid; import java.io.IOException; import java.util.List; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE; -@Api(tags = "参数配置") +@Api(tags = "管理后台 - 参数配置") @RestController @RequestMapping("/infra/config") @Validated -public class InfConfigController { +public class ConfigController { @Resource - private InfConfigService configService; + private ConfigService configService; @PostMapping("/create") @ApiOperation("创建参数配置") @PreAuthorize("@ss.hasPermission('infra:config:create')") - public CommonResult createConfig(@Valid @RequestBody InfConfigCreateReqVO reqVO) { + public CommonResult createConfig(@Valid @RequestBody ConfigCreateReqVO reqVO) { return success(configService.createConfig(reqVO)); } @PutMapping("/update") @ApiOperation("修改参数配置") @PreAuthorize("@ss.hasPermission('infra:config:update')") - public CommonResult updateConfig(@Valid @RequestBody InfConfigUpdateReqVO reqVO) { + public CommonResult updateConfig(@Valid @RequestBody ConfigUpdateReqVO reqVO) { configService.updateConfig(reqVO); return success(true); } @@ -63,20 +63,20 @@ public class InfConfigController { @ApiOperation("获得参数配置") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('infra:config:query')") - public CommonResult getConfig(@RequestParam("id") Long id) { - return success(InfConfigConvert.INSTANCE.convert(configService.getConfig(id))); + public CommonResult getConfig(@RequestParam("id") Long id) { + return success(ConfigConvert.INSTANCE.convert(configService.getConfig(id))); } @GetMapping(value = "/get-value-by-key") @ApiOperation(value = "根据参数键名查询参数值", notes = "敏感配置,不允许返回给前端") @ApiImplicitParam(name = "key", value = "参数键", required = true, example = "yunai.biz.username", dataTypeClass = String.class) public CommonResult getConfigKey(@RequestParam("key") String key) { - InfConfigDO config = configService.getConfigByKey(key); + ConfigDO config = configService.getConfigByKey(key); if (config == null) { return null; } if (config.getSensitive()) { - throw exception(CONFIG_GET_VALUE_ERROR_IF_SENSITIVE); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE); } return success(config.getValue()); } @@ -84,22 +84,22 @@ public class InfConfigController { @GetMapping("/page") @ApiOperation("获取参数配置分页") @PreAuthorize("@ss.hasPermission('infra:config:query')") - public CommonResult> getConfigPage(@Valid InfConfigPageReqVO reqVO) { - PageResult page = configService.getConfigPage(reqVO); - return success(InfConfigConvert.INSTANCE.convertPage(page)); + public CommonResult> getConfigPage(@Valid ConfigPageReqVO reqVO) { + PageResult page = configService.getConfigPage(reqVO); + return success(ConfigConvert.INSTANCE.convertPage(page)); } @GetMapping("/export") @ApiOperation("导出参数配置") @PreAuthorize("@ss.hasPermission('infra:config:export')") @OperateLog(type = EXPORT) - public void exportSysConfig(@Valid InfConfigExportReqVO reqVO, + public void exportSysConfig(@Valid ConfigExportReqVO reqVO, HttpServletResponse response) throws IOException { - List list = configService.getConfigList(reqVO); + List list = configService.getConfigList(reqVO); // 拼接数据 - List datas = InfConfigConvert.INSTANCE.convertList(list); + List datas = ConfigConvert.INSTANCE.convertList(list); // 输出 - ExcelUtils.write(response, "参数配置.xls", "数据", InfConfigExcelVO.class, datas); + ExcelUtils.write(response, "参数配置.xls", "数据", ConfigExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java similarity index 93% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigBaseVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java index 82b0f48edb..bf1c26d73d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -13,7 +13,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class InfConfigBaseVO { +public class ConfigBaseVO { @ApiModelProperty(value = "参数分组", required = true, example = "biz") @NotEmpty(message = "参数分组不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigCreateReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java index ee2b90abc6..7a2118ae1c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigCreateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,10 +8,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; -@ApiModel("参数配置创建 Request VO") +@ApiModel("管理后台 - 参数配置创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class InfConfigCreateReqVO extends InfConfigBaseVO { +public class ConfigCreateReqVO extends ConfigBaseVO { @ApiModelProperty(value = "参数键名", required = true, example = "yunai.db.username") @NotBlank(message = "参数键名长度不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExcelVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExcelVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java index 2a5c044988..908981e0ae 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import java.util.Date; * 参数配置 Excel 导出响应 VO */ @Data -public class InfConfigExcelVO { +public class ConfigExcelVO { @ExcelProperty("参数配置序号") private Long id; @@ -30,11 +30,11 @@ public class InfConfigExcelVO { private String value; @ExcelProperty(value = "参数类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.CONFIG_TYPE) + @DictFormat(DictTypeConstants.CONFIG_TYPE) private Integer type; @ExcelProperty(value = "是否敏感", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.BOOLEAN_STRING) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) private Boolean sensitive; @ExcelProperty("备注") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExportReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExportReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java index 550a5dfc4c..2e328e6d97 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("参数配置导出 Request VO") +@ApiModel("管理后台 - 参数配置导出 Request VO") @Data -public class InfConfigExportReqVO { +public class ConfigExportReqVO { @ApiModelProperty(value = "参数名称", example = "模糊匹配") private String name; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigPageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java index 3f031fa2cb..87d4ce9282 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("参数配置分页 Request VO") +@ApiModel("管理后台 - 参数配置分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfConfigPageReqVO extends PageParam { +public class ConfigPageReqVO extends PageParam { @ApiModelProperty(value = "参数名称", example = "模糊匹配") private String name; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java index 84689b70b7..03196e0609 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,10 +9,10 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import java.util.Date; -@ApiModel("参数配置信息 Response VO") +@ApiModel("管理后台 - 参数配置信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) -public class InfConfigRespVO extends InfConfigBaseVO { +public class ConfigRespVO extends ConfigBaseVO { @ApiModelProperty(value = "参数配置序号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigUpdateReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java index 7e9d49ca79..2335d61699 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/config/vo/InfConfigUpdateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo; +package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("参数配置创建 Request VO") +@ApiModel("管理后台 - 参数配置创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfConfigUpdateReqVO extends InfConfigBaseVO { +public class ConfigUpdateReqVO extends ConfigBaseVO { @ApiModelProperty(value = "参数配置序号", required = true, example = "1024") @NotNull(message = "参数配置编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index f0c85ddce3..32789f1aff 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.file; +package cn.iocoder.yudao.module.infra.controller.admin.file; import cn.hutool.core.io.IoUtil; -import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService; -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo.InfFileRespVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FileRespVO; +import cn.iocoder.yudao.module.infra.convert.file.FileConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import cn.iocoder.yudao.module.infra.service.file.FileService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -29,17 +28,15 @@ import java.io.IOException; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "文件存储") +@Api(tags = "管理后台 - 文件存储") @RestController @RequestMapping("/infra/file") @Validated @Slf4j -public class InfFileController { +public class FileController { @Resource - private InfFileService fileService; - @Resource - private InfFileCoreService fileCoreService; + private FileService fileService; @PostMapping("/upload") @ApiOperation("上传文件") @@ -49,7 +46,7 @@ public class InfFileController { }) public CommonResult uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("path") String path) throws IOException { - return success(fileCoreService.createFile(path, IoUtil.readBytes(file.getInputStream()))); + return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream()))); } @DeleteMapping("/delete") @@ -57,7 +54,7 @@ public class InfFileController { @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = String.class) @PreAuthorize("@ss.hasPermission('infra:file:delete')") public CommonResult deleteFile(@RequestParam("id") String id) { - fileCoreService.deleteFile(id); + fileService.deleteFile(id); return success(true); } @@ -66,7 +63,7 @@ public class InfFileController { @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class) public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException { TenantContextHolder.setNullTenantId(); - InfFileDO file = fileCoreService.getFile(path); + FileDO file = fileService.getFile(path); if (file == null) { log.warn("[getFile][path({}) 文件不存在]", path); response.setStatus(HttpStatus.NOT_FOUND.value()); @@ -78,9 +75,9 @@ public class InfFileController { @GetMapping("/page") @ApiOperation("获得文件分页") @PreAuthorize("@ss.hasPermission('infra:file:query')") - public CommonResult> getFilePage(@Valid InfFilePageReqVO pageVO) { - PageResult pageResult = fileService.getFilePage(pageVO); - return success(InfFileConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getFilePage(@Valid FilePageReqVO pageVO) { + PageResult pageResult = fileService.getFilePage(pageVO); + return success(FileConvert.INSTANCE.convertPage(pageResult)); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/vo/InfFilePageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FilePageReqVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/vo/InfFilePageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FilePageReqVO.java index 152466a19c..bf67300ab2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/vo/InfFilePageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FilePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo; +package cn.iocoder.yudao.module.infra.controller.admin.file.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("文件分页 Request VO") +@ApiModel("管理后台 - 文件分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfFilePageReqVO extends PageParam { +public class FilePageReqVO extends PageParam { @ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配") private String id; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/controller/file/vo/InfFileRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FileRespVO.java similarity index 69% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/controller/file/vo/InfFileRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FileRespVO.java index e264a3fd27..838f3272b3 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/controller/file/vo/InfFileRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/FileRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo; +package cn.iocoder.yudao.module.infra.controller.admin.file.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,9 +6,9 @@ import lombok.Data; import java.util.Date; -@ApiModel(value = "文件 Response VO", description = "不返回 content 字段,太大") +@ApiModel(value = "管理后台 - 文件 Response VO", description = "不返回 content 字段,太大") @Data -public class InfFileRespVO { +public class FileRespVO { @ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg") private String id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobController.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobController.java index 1cd3c8dc7c..47ef687dde 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobController.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job; +package cn.iocoder.yudao.module.infra.controller.admin.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.quartz.core.util.CronUtils; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.*; -import cn.iocoder.yudao.adminserver.modules.infra.convert.job.InfJobConvert; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.InfJobService; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.*; +import cn.iocoder.yudao.module.infra.convert.job.JobConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; +import cn.iocoder.yudao.module.infra.service.job.JobService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -30,19 +30,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "定时任务") +@Api(tags = "管理后台 - 定时任务") @RestController @RequestMapping("/infra/job") @Validated -public class InfJobController { +public class JobController { @Resource - private InfJobService jobService; + private JobService jobService; @PostMapping("/create") @ApiOperation("创建定时任务") @PreAuthorize("@ss.hasPermission('infra:job:create')") - public CommonResult createJob(@Valid @RequestBody InfJobCreateReqVO createReqVO) + public CommonResult createJob(@Valid @RequestBody JobCreateReqVO createReqVO) throws SchedulerException { return success(jobService.createJob(createReqVO)); } @@ -50,7 +50,7 @@ public class InfJobController { @PutMapping("/update") @ApiOperation("更新定时任务") @PreAuthorize("@ss.hasPermission('infra:job:update')") - public CommonResult updateJob(@Valid @RequestBody InfJobUpdateReqVO updateReqVO) + public CommonResult updateJob(@Valid @RequestBody JobUpdateReqVO updateReqVO) throws SchedulerException { jobService.updateJob(updateReqVO); return success(true); @@ -92,38 +92,38 @@ public class InfJobController { @ApiOperation("获得定时任务") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult getJob(@RequestParam("id") Long id) { - InfJobDO job = jobService.getJob(id); - return success(InfJobConvert.INSTANCE.convert(job)); + public CommonResult getJob(@RequestParam("id") Long id) { + JobDO job = jobService.getJob(id); + return success(JobConvert.INSTANCE.convert(job)); } @GetMapping("/list") @ApiOperation("获得定时任务列表") @ApiImplicitParam(name = "ids", value = "编号列表", required = true, dataTypeClass = List.class) @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult> getJobList(@RequestParam("ids") Collection ids) { - List list = jobService.getJobList(ids); - return success(InfJobConvert.INSTANCE.convertList(list)); + public CommonResult> getJobList(@RequestParam("ids") Collection ids) { + List list = jobService.getJobList(ids); + return success(JobConvert.INSTANCE.convertList(list)); } @GetMapping("/page") @ApiOperation("获得定时任务分页") @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult> getJobPage(@Valid InfJobPageReqVO pageVO) { - PageResult pageResult = jobService.getJobPage(pageVO); - return success(InfJobConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getJobPage(@Valid JobPageReqVO pageVO) { + PageResult pageResult = jobService.getJobPage(pageVO); + return success(JobConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出定时任务 Excel") @PreAuthorize("@ss.hasPermission('infra:job:export')") @OperateLog(type = EXPORT) - public void exportJobExcel(@Valid InfJobExportReqVO exportReqVO, + public void exportJobExcel(@Valid JobExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = jobService.getJobList(exportReqVO); + List list = jobService.getJobList(exportReqVO); // 导出 Excel - List datas = InfJobConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "定时任务.xls", "数据", InfJobExcelVO.class, datas); + List datas = JobConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "定时任务.xls", "数据", JobExcelVO.class, datas); } @GetMapping("/get_next_times") @@ -135,7 +135,7 @@ public class InfJobController { @PreAuthorize("@ss.hasPermission('infra:job:query')") public CommonResult> getJobNextTimes(@RequestParam("id") Long id, @RequestParam(value = "count", required = false, defaultValue = "5") Integer count) { - InfJobDO job = jobService.getJob(id); + JobDO job = jobService.getJob(id); if (job == null) { return success(Collections.emptyList()); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobLogController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobLogController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java index d6e263980c..40de986cf9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/InfJobLogController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job; +package cn.iocoder.yudao.module.infra.controller.admin.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.job.InfJobLogConvert; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.InfJobLogService; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogRespVO; +import cn.iocoder.yudao.module.infra.convert.job.JobLogConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; +import cn.iocoder.yudao.module.infra.service.job.JobLogService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -31,51 +31,51 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "定时任务日志") +@Api(tags = "管理后台 - 定时任务日志") @RestController @RequestMapping("/infra/job-log") @Validated -public class InfJobLogController { +public class JobLogController { @Resource - private InfJobLogService jobLogService; + private JobLogService jobLogService; @GetMapping("/get") @ApiOperation("获得定时任务日志") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult getJobLog(@RequestParam("id") Long id) { - InfJobLogDO jobLog = jobLogService.getJobLog(id); - return success(InfJobLogConvert.INSTANCE.convert(jobLog)); + public CommonResult getJobLog(@RequestParam("id") Long id) { + JobLogDO jobLog = jobLogService.getJobLog(id); + return success(JobLogConvert.INSTANCE.convert(jobLog)); } @GetMapping("/list") @ApiOperation("获得定时任务日志列表") @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult> getJobLogList(@RequestParam("ids") Collection ids) { - List list = jobLogService.getJobLogList(ids); - return success(InfJobLogConvert.INSTANCE.convertList(list)); + public CommonResult> getJobLogList(@RequestParam("ids") Collection ids) { + List list = jobLogService.getJobLogList(ids); + return success(JobLogConvert.INSTANCE.convertList(list)); } @GetMapping("/page") @ApiOperation("获得定时任务日志分页") @PreAuthorize("@ss.hasPermission('infra:job:query')") - public CommonResult> getJobLogPage(@Valid InfJobLogPageReqVO pageVO) { - PageResult pageResult = jobLogService.getJobLogPage(pageVO); - return success(InfJobLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getJobLogPage(@Valid JobLogPageReqVO pageVO) { + PageResult pageResult = jobLogService.getJobLogPage(pageVO); + return success(JobLogConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出定时任务日志 Excel") @PreAuthorize("@ss.hasPermission('infra:job:export')") @OperateLog(type = EXPORT) - public void exportJobLogExcel(@Valid InfJobLogExportReqVO exportReqVO, + public void exportJobLogExcel(@Valid JobLogExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = jobLogService.getJobLogList(exportReqVO); + List list = jobLogService.getJobLogList(exportReqVO); // 导出 Excel - List datas = InfJobLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "任务日志.xls", "数据", InfJobLogExcelVO.class, datas); + List datas = JobLogConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "任务日志.xls", "数据", JobLogExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobBaseVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobBaseVO.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobBaseVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobBaseVO.java index 2d7b51f24c..db3fcac1d9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class InfJobBaseVO { +public class JobBaseVO { @ApiModelProperty(value = "任务名称", required = true, example = "测试任务") @NotNull(message = "任务名称不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobCreateReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobCreateReqVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobCreateReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobCreateReqVO.java index b2325d7414..0e9f457410 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobCreateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("定时任务创建 Request VO") +@ApiModel("管理后台 - 定时任务创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobCreateReqVO extends InfJobBaseVO { +public class JobCreateReqVO extends JobBaseVO { @ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob") @NotNull(message = "处理器的名字不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExcelVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExcelVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExcelVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExcelVO.java index 0d9daf8ebe..6b5a6a0b17 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Date; * @author 芋道源码 */ @Data -public class InfJobExcelVO { +public class JobExcelVO { @ExcelProperty("任务编号") private Long id; @@ -23,7 +23,7 @@ public class InfJobExcelVO { private String name; @ExcelProperty(value = "任务状态", converter = DictConvert.class) - @DictFormat(InfDictTypeConstants.JOB_STATUS) + @DictFormat(DictTypeConstants.JOB_STATUS) private Integer status; @ExcelProperty("处理器的名字") diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExportReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExportReqVO.java new file mode 100644 index 0000000000..ec393a6045 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobExportReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel(value = "管理后台 - 定时任务 Excel 导出 Request VO", description = "参数和 JobPageReqVO 是一致的") +@Data +public class JobExportReqVO { + + @ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配") + private String name; + + @ApiModelProperty(value = "任务状态", example = "1", notes = "参见 JobStatusEnum 枚举") + private Integer status; + + @ApiModelProperty(value = "处理器的名字", example = "UserSessionTimeoutJob", notes = "模糊匹配") + private String handlerName; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobPageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobPageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java index eec31e9b3b..02d3a7e2bb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -7,16 +7,16 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("定时任务分页 Request VO") +@ApiModel("管理后台 - 定时任务分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobPageReqVO extends PageParam { +public class JobPageReqVO extends PageParam { @ApiModelProperty(value = "任务名称", example = "测试任务", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "任务状态", example = "1", notes = "参见 InfJobStatusEnum 枚举") + @ApiModelProperty(value = "任务状态", example = "1", notes = "参见 JobStatusEnum 枚举") private Integer status; @ApiModelProperty(value = "处理器的名字", example = "sysUserSessionTimeoutJob", notes = "模糊匹配") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java index ffe3a69145..5861342783 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,11 +9,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; import java.util.Date; -@ApiModel("定时任务 Response VO") +@ApiModel("管理后台 - 定时任务 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobRespVO extends InfJobBaseVO { +public class JobRespVO extends JobBaseVO { @ApiModelProperty(value = "任务编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobUpdateReqVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobUpdateReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobUpdateReqVO.java index d741a98e4e..f26cd226ca 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/job/InfJobUpdateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("定时任务更新 Request VO") +@ApiModel("管理后台 - 定时任务更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobUpdateReqVO extends InfJobBaseVO { +public class JobUpdateReqVO extends JobBaseVO { @ApiModelProperty(value = "任务编号", required = true, example = "1024") @NotNull(message = "任务编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java index 0dbd67e9c0..761921349f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class InfJobLogBaseVO { +public class JobLogBaseVO { @ApiModelProperty(value = "任务编号", required = true, example = "1024") @NotNull(message = "任务编号不能为空") @@ -43,7 +43,7 @@ public class InfJobLogBaseVO { @ApiModelProperty(value = "执行时长", example = "123") private Integer duration; - @ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 InfJobLogStatusEnum 枚举") + @ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 JobLogStatusEnum 枚举") @NotNull(message = "任务状态不能为空") private Integer status; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExcelVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExcelVO.java index fd7078b70e..25eed2a3f2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Date; * @author 芋艿 */ @Data -public class InfJobLogExcelVO { +public class JobLogExcelVO { @ExcelProperty("日志编号") private Long id; @@ -41,7 +41,7 @@ public class InfJobLogExcelVO { private Integer duration; @ExcelProperty(value = "任务状态", converter = DictConvert.class) - @DictFormat(InfDictTypeConstants.JOB_STATUS) + @DictFormat(DictTypeConstants.JOB_STATUS) private Integer status; @ExcelProperty("结果数据") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java index 3e3e85b58d..df482c9d22 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "定时任务 Excel 导出 Request VO", description = "参数和 InfJobLogPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 定时任务 Excel 导出 Request VO", description = "参数和 JobLogPageReqVO 是一致的") @Data -public class InfJobLogExportReqVO { +public class JobLogExportReqVO { @ApiModelProperty(value = "任务编号", example = "10") private Long jobId; @@ -27,7 +27,7 @@ public class InfJobLogExportReqVO { @ApiModelProperty(value = "结束执行时间") private Date endTime; - @ApiModelProperty(value = "任务状态", notes = "参见 InfJobLogStatusEnum 枚举") + @ApiModelProperty(value = "任务状态", notes = "参见 JobLogStatusEnum 枚举") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java index 0c5b558671..055cfc56c1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("定时任务日志分页 Request VO") +@ApiModel("管理后台 - 定时任务日志分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobLogPageReqVO extends PageParam { +public class JobLogPageReqVO extends PageParam { @ApiModelProperty(value = "任务编号", example = "10") private Long jobId; @@ -32,7 +32,7 @@ public class InfJobLogPageReqVO extends PageParam { @ApiModelProperty(value = "结束执行时间") private Date endTime; - @ApiModelProperty(value = "任务状态", notes = "参见 InfJobLogStatusEnum 枚举") + @ApiModelProperty(value = "任务状态", notes = "参见 JobLogStatusEnum 枚举") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java index 497e6913d9..c806a209af 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/job/vo/log/InfJobLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log; +package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("定时任务日志 Response VO") +@ApiModel("管理后台 - 定时任务日志 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfJobLogRespVO extends InfJobLogBaseVO { +public class JobLogRespVO extends JobLogBaseVO { @ApiModelProperty(value = "日志编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiAccessLogController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiAccessLogController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java index 3aec60d4fe..5046ea5af6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiAccessLogController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger; +package cn.iocoder.yudao.module.infra.controller.admin.logger; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.logger.InfApiAccessLogConvert; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.InfApiAccessLogService; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO; +import cn.iocoder.yudao.module.infra.convert.logger.ApiAccessLogConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; +import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; @@ -28,33 +28,33 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "API 访问日志") +@Api(tags = "管理后台 - API 访问日志") @RestController @RequestMapping("/infra/api-access-log") @Validated -public class InfApiAccessLogController { +public class ApiAccessLogController { @Resource - private InfApiAccessLogService apiAccessLogService; + private ApiAccessLogService apiAccessLogService; @GetMapping("/page") @ApiOperation("获得API 访问日志分页") @PreAuthorize("@ss.hasPermission('infra:api-access-log:query')") - public CommonResult> getApiAccessLogPage(@Valid InfApiAccessLogPageReqVO pageVO) { - PageResult pageResult = apiAccessLogService.getApiAccessLogPage(pageVO); - return success(InfApiAccessLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageVO) { + PageResult pageResult = apiAccessLogService.getApiAccessLogPage(pageVO); + return success(ApiAccessLogConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出API 访问日志 Excel") @PreAuthorize("@ss.hasPermission('infra:api-access-log:export')") @OperateLog(type = EXPORT) - public void exportApiAccessLogExcel(@Valid InfApiAccessLogExportReqVO exportReqVO, + public void exportApiAccessLogExcel(@Valid ApiAccessLogExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = apiAccessLogService.getApiAccessLogList(exportReqVO); + List list = apiAccessLogService.getApiAccessLogList(exportReqVO); // 导出 Excel - List datas = InfApiAccessLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "API 访问日志.xls", "数据", InfApiAccessLogExcelVO.class, datas); + List datas = ApiAccessLogConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "API 访问日志.xls", "数据", ApiAccessLogExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiErrorLogController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiErrorLogController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java index 7b83022ca1..d592836b2e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/InfApiErrorLogController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger; +package cn.iocoder.yudao.module.infra.controller.admin.logger; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.logger.InfApiErrorLogConvert; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.InfApiErrorLogService; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO; +import cn.iocoder.yudao.module.infra.convert.logger.ApiErrorLogConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; +import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -29,14 +29,14 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Api(tags = "API 错误日志") +@Api(tags = "管理后台 - API 错误日志") @RestController @RequestMapping("/infra/api-error-log") @Validated -public class InfApiErrorLogController { +public class ApiErrorLogController { @Resource - private InfApiErrorLogService apiErrorLogService; + private ApiErrorLogService apiErrorLogService; @PutMapping("/update-status") @ApiOperation("更新 API 错误日志的状态") @@ -54,21 +54,21 @@ public class InfApiErrorLogController { @GetMapping("/page") @ApiOperation("获得 API 错误日志分页") @PreAuthorize("@ss.hasPermission('infra:api-error-log:query')") - public CommonResult> getApiErrorLogPage(@Valid InfApiErrorLogPageReqVO pageVO) { - PageResult pageResult = apiErrorLogService.getApiErrorLogPage(pageVO); - return success(InfApiErrorLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageVO) { + PageResult pageResult = apiErrorLogService.getApiErrorLogPage(pageVO); + return success(ApiErrorLogConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出 API 错误日志 Excel") @PreAuthorize("@ss.hasPermission('infra:api-error-log:export')") @OperateLog(type = EXPORT) - public void exportApiErrorLogExcel(@Valid InfApiErrorLogExportReqVO exportReqVO, + public void exportApiErrorLogExcel(@Valid ApiErrorLogExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = apiErrorLogService.getApiErrorLogList(exportReqVO); + List list = apiErrorLogService.getApiErrorLogList(exportReqVO); // 导出 Excel - List datas = InfApiErrorLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "API 错误日志.xls", "数据", InfApiErrorLogExcelVO.class, datas); + List datas = ApiErrorLogConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "API 错误日志.xls", "数据", ApiErrorLogExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java similarity index 95% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java index d5e300f629..619dea65a5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class InfApiAccessLogBaseVO { +public class ApiAccessLogBaseVO { @ApiModelProperty(value = "链路追踪编号", required = true, example = "66600cb6-7852-11eb-9439-0242ac130002") @NotNull(message = "链路追踪编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java index d0265351f9..5c1995c6a1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Date; * @author 芋道源码 */ @Data -public class InfApiAccessLogExcelVO { +public class ApiAccessLogExcelVO { @ExcelProperty("日志主键") private Long id; @@ -26,7 +26,7 @@ public class InfApiAccessLogExcelVO { private Long userId; @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.USER_TYPE) + @DictFormat(DictTypeConstants.USER_TYPE) private Integer userType; @ExcelProperty("应用名") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java index 8e9dc409de..83eefabd60 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "API 访问日志 Excel 导出 Request VO", description = "参数和 InfApiAccessLogPageReqVO 是一致的") +@ApiModel(value = "管理后台 - API 访问日志 Excel 导出 Request VO", description = "参数和 ApiAccessLogPageReqVO 是一致的") @Data -public class InfApiAccessLogExportReqVO { +public class ApiAccessLogExportReqVO { @ApiModelProperty(value = "用户编号", example = "666") private Long userId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java index c04520528b..d318bfa920 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("API 访问日志分页 Request VO") +@ApiModel("管理后台 - API 访问日志分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfApiAccessLogPageReqVO extends PageParam { +public class ApiAccessLogPageReqVO extends PageParam { @ApiModelProperty(value = "用户编号", example = "666") private Long userId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 15dbed3e14..0458affb03 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apiaccesslog/InfApiAccessLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("API 访问日志 Response VO") +@ApiModel("管理后台 - API 访问日志 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfApiAccessLogRespVO extends InfApiAccessLogBaseVO { +public class ApiAccessLogRespVO extends ApiAccessLogBaseVO { @ApiModelProperty(value = "日志主键", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java similarity index 96% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java index 87eb2ddd66..08fbdace87 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class InfApiErrorLogBaseVO { +public class ApiErrorLogBaseVO { @ApiModelProperty(value = "链路追踪编号", required = true, example = "66600cb6-7852-11eb-9439-0242ac130002") @NotNull(message = "链路追踪编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java index 3224a3017e..7e1e2ef0c4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExcelVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -15,7 +14,7 @@ import java.util.Date; * @author 芋道源码 */ @Data -public class InfApiErrorLogExcelVO { +public class ApiErrorLogExcelVO { @ExcelProperty("编号") private Integer id; @@ -27,7 +26,7 @@ public class InfApiErrorLogExcelVO { private Integer userId; @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.USER_TYPE) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_TYPE) private Integer userType; @ExcelProperty("应用名") @@ -79,7 +78,7 @@ public class InfApiErrorLogExcelVO { private Date createTime; @ExcelProperty(value = "处理状态", converter = DictConvert.class) - @DictFormat(InfDictTypeConstants.API_ERROR_LOG_PROCESS_STATUS) + @DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS) private Integer processStatus; @ExcelProperty("处理时间") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java index a86288e1cd..b799a3238a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "API 错误日志 Excel 导出 Request VO", description = "参数和 InfApiErrorLogPageReqVO 是一致的") +@ApiModel(value = "管理后台 - API 错误日志 Excel 导出 Request VO", description = "参数和 ApiErrorLogPageReqVO 是一致的") @Data -public class InfApiErrorLogExportReqVO { +public class ApiErrorLogExportReqVO { @ApiModelProperty(value = "用户编号", example = "666") private Long userId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java index cc47dd8d3a..e9a36af965 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("API 错误日志分页 Request VO") +@ApiModel("管理后台 - API 错误日志分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfApiErrorLogPageReqVO extends PageParam { +public class ApiErrorLogPageReqVO extends PageParam { @ApiModelProperty(value = "用户编号", example = "666") private Long userId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index 9e4521c119..0f0c2724dd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog; +package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("API 错误日志 Response VO") +@ApiModel("管理后台 - API 错误日志 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfApiErrorLogRespVO extends InfApiErrorLogBaseVO { +public class ApiErrorLogRespVO extends ApiErrorLogBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1024") private Integer id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.http b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.http rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http index 1c474e93f3..0310dea58f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.http +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.http @@ -1,7 +1,9 @@ ### 请求 /infra/redis/get-monitor-info 接口 => 成功 GET {{baseUrl}}/infra/redis/get-monitor-info Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} ### 请求 /infra/redis/get-key-list 接口 => 成功 GET {{baseUrl}}/infra/redis/get-key-list Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.java index f39a38b2e1..303e671848 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/RedisController.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.redis; +package cn.iocoder.yudao.module.infra.controller.admin.redis; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry; -import cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo.InfRedisKeyRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo.InfRedisMonitorRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.redis.RedisConvert; +import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; +import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.data.redis.connection.RedisServerCommands; @@ -22,7 +22,7 @@ import java.util.Properties; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "Redis 监控") +@Api(tags = "管理后台 - Redis 监控") @RestController @RequestMapping("/infra/redis") public class RedisController { @@ -33,7 +33,7 @@ public class RedisController { @GetMapping("/get-monitor-info") @ApiOperation("获得 Redis 监控信息") @PreAuthorize("@ss.hasPermission('infra:redis:get-monitor-info')") - public CommonResult getRedisMonitorInfo() { + public CommonResult getRedisMonitorInfo() { // 获得 Redis 统计信息 Properties info = stringRedisTemplate.execute((RedisCallback) RedisServerCommands::info); Long dbSize = stringRedisTemplate.execute(RedisServerCommands::dbSize); @@ -47,7 +47,7 @@ public class RedisController { @GetMapping("/get-key-list") @ApiOperation("获得 Redis Key 列表") @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") - public CommonResult> getKeyList() { + public CommonResult> getKeyList() { List keyDefines = RedisKeyRegistry.list(); return success(RedisConvert.INSTANCE.convertList(keyDefines)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisKeyRespVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisKeyRespVO.java index 60a14cf409..6fb71fe9a4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisKeyRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisKeyRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo; +package cn.iocoder.yudao.module.infra.controller.admin.redis.vo; import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import io.swagger.annotations.ApiModel; @@ -9,11 +9,11 @@ import lombok.Data; import java.time.Duration; -@ApiModel("Redis Key 信息 Response VO") +@ApiModel("管理后台 - Redis Key 信息 Response VO") @Data @Builder @AllArgsConstructor -public class InfRedisKeyRespVO { +public class RedisKeyRespVO { @ApiModelProperty(value = "login_user:%s", required = true, example = "String") private String keyTemplate; @@ -22,7 +22,7 @@ public class InfRedisKeyRespVO { private RedisKeyDefine.KeyTypeEnum keyType; @ApiModelProperty(value = "Value 类型", required = true, example = "java.lang.String") - private Class valueType; + private Class valueType; @ApiModelProperty(value = "超时类型", required = true, example = "1") private RedisKeyDefine.TimeoutTypeEnum timeoutType; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisMonitorRespVO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisMonitorRespVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisMonitorRespVO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisMonitorRespVO.java index 16a7c6c9d4..703a697dc3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/redis/vo/InfRedisMonitorRespVO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisMonitorRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo; +package cn.iocoder.yudao.module.infra.controller.admin.redis.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,11 +9,11 @@ import lombok.Data; import java.util.List; import java.util.Properties; -@ApiModel("Redis 监控信息 Response VO") +@ApiModel("管理后台 - Redis 监控信息 Response VO") @Data @Builder @AllArgsConstructor -public class InfRedisMonitorRespVO { +public class RedisMonitorRespVO { @ApiModelProperty(value = "Redis info 指令结果", required = true, notes = "具体字段,查看 Redis 文档") private Properties info; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/app/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/app/package-info.java new file mode 100644 index 0000000000..d0f921f5c0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.infra.controller.app; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/package-info.java new file mode 100644 index 0000000000..04fde2f433 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.infra.controller; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java new file mode 100644 index 0000000000..8e16af1a34 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.infra.convert.config; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface ConfigConvert { + + ConfigConvert INSTANCE = Mappers.getMapper(ConfigConvert.class); + + PageResult convertPage(PageResult page); + + ConfigRespVO convert(ConfigDO bean); + + ConfigDO convert(ConfigCreateReqVO bean); + + ConfigDO convert(ConfigUpdateReqVO bean); + + List convertList(List list); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java new file mode 100644 index 0000000000..affeddba4b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.infra.convert.file; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FileRespVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface FileConvert { + + FileConvert INSTANCE = Mappers.getMapper(FileConvert.class); + + FileRespVO convert(FileDO bean); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobConvert.java new file mode 100644 index 0000000000..2c7aa02973 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.infra.convert.job; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 定时任务 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface JobConvert { + + JobConvert INSTANCE = Mappers.getMapper(JobConvert.class); + + JobDO convert(JobCreateReqVO bean); + + JobDO convert(JobUpdateReqVO bean); + + JobRespVO convert(JobDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobLogConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobLogConvert.java new file mode 100644 index 0000000000..3f32c526d6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/job/JobLogConvert.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.convert.job; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogRespVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 定时任务日志 Convert + * + * @author 芋艿 + */ +@Mapper +public interface JobLogConvert { + + JobLogConvert INSTANCE = Mappers.getMapper(JobLogConvert.class); + + JobLogRespVO convert(JobLogDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java new file mode 100644 index 0000000000..7162d4d9ac --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.infra.convert.logger; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * API 访问日志 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ApiAccessLogConvert { + + ApiAccessLogConvert INSTANCE = Mappers.getMapper(ApiAccessLogConvert.class); + + ApiAccessLogRespVO convert(ApiAccessLogDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + ApiAccessLogDO convert(ApiAccessLogCreateReqDTO bean); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java new file mode 100644 index 0000000000..8eef7463ab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.infra.convert.logger; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExcelVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * API 错误日志 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ApiErrorLogConvert { + + ApiErrorLogConvert INSTANCE = Mappers.getMapper(ApiErrorLogConvert.class); + + ApiErrorLogRespVO convert(ApiErrorLogDO bean); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + ApiErrorLogDO convert(ApiErrorLogCreateReqDTO bean); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/package-info.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/package-info.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/package-info.java index da39733908..8e27593088 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/package-info.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/package-info.java @@ -3,4 +3,4 @@ * * 目前使用 MapStruct 框架 */ -package cn.iocoder.yudao.adminserver.modules.pay.convert; +package cn.iocoder.yudao.module.infra.convert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/redis/RedisConvert.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/redis/RedisConvert.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/redis/RedisConvert.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/redis/RedisConvert.java index df76fce242..e1c9311849 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/redis/RedisConvert.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/redis/RedisConvert.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.infra.convert.redis; +package cn.iocoder.yudao.module.infra.convert.redis; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; -import cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo.InfRedisKeyRespVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.redis.vo.InfRedisMonitorRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -16,11 +16,11 @@ public interface RedisConvert { RedisConvert INSTANCE = Mappers.getMapper(RedisConvert.class); - default InfRedisMonitorRespVO build(Properties info, Long dbSize, Properties commandStats) { - InfRedisMonitorRespVO respVO = InfRedisMonitorRespVO.builder().info(info).dbSize(dbSize) + default RedisMonitorRespVO build(Properties info, Long dbSize, Properties commandStats) { + RedisMonitorRespVO respVO = RedisMonitorRespVO.builder().info(info).dbSize(dbSize) .commandStats(new ArrayList<>(commandStats.size())).build(); commandStats.forEach((key, value) -> { - respVO.getCommandStats().add(InfRedisMonitorRespVO.CommandStat.builder() + respVO.getCommandStats().add(RedisMonitorRespVO.CommandStat.builder() .command(StrUtil.subAfter((String) key, "cmdstat_", false)) .calls(Integer.valueOf(StrUtil.subBetween((String) value, "calls=", ","))) .usec(Long.valueOf(StrUtil.subBetween((String) value, "usec=", ","))) @@ -29,6 +29,6 @@ public interface RedisConvert { return respVO; } - List convertList(List list); + List convertList(List list); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/config/InfConfigDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/config/ConfigDO.java similarity index 82% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/config/InfConfigDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/config/ConfigDO.java index c8d58196ee..4542c2a3ac 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/config/InfConfigDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/config/ConfigDO.java @@ -1,6 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config; +package cn.iocoder.yudao.module.infra.dal.dataobject.config; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -13,11 +14,11 @@ import lombok.ToString; * * @author 芋道源码 */ -@TableName("inf_config") +@TableName("infra_config") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class InfConfigDO extends BaseDO { +public class ConfigDO extends BaseDO { /** * 参数主键 @@ -45,7 +46,7 @@ public class InfConfigDO extends BaseDO { /** * 参数类型 * - * 枚举 {@link InfConfigTypeEnum} + * 枚举 {@link ConfigTypeEnum} */ @TableField("`type`") private Integer type; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java similarity index 80% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java index 83a03b3caa..47eb2403e6 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileDO.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file; +package cn.iocoder.yudao.module.infra.dal.dataobject.file; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; @@ -16,13 +15,13 @@ import java.io.InputStream; * @author 芋道源码 */ @Data -@TableName("inf_file") +@TableName("infra_file") @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class InfFileDO extends TenantBaseDO { +public class FileDO extends TenantBaseDO { /** * 文件路径 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobDO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobDO.java index 4eb95ca201..c419b1fdbb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobDO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job; +package cn.iocoder.yudao.module.infra.dal.dataobject.job; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobStatusEnum; +import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -11,14 +11,14 @@ import lombok.*; * * @author 芋道源码 */ -@TableName("inf_job") +@TableName("infra_job") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class InfJobDO extends BaseDO { +public class JobDO extends BaseDO { /** * 任务编号 @@ -32,7 +32,7 @@ public class InfJobDO extends BaseDO { /** * 任务状态 * - * 枚举 {@link InfJobStatusEnum} + * 枚举 {@link JobStatusEnum} */ private Integer status; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobLogDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobLogDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobLogDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobLogDO.java index 49916802c6..fa79b9b64d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/dataobject/job/InfJobLogDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/job/JobLogDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job; +package cn.iocoder.yudao.module.infra.dal.dataobject.job; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobLogStatusEnum; +import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -13,14 +13,14 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName("inf_job_log") +@TableName("infra_job_log") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class InfJobLogDO extends BaseDO { +public class JobLogDO extends BaseDO { /** * 日志编号 @@ -29,19 +29,19 @@ public class InfJobLogDO extends BaseDO { /** * 任务编号 * - * 关联 {@link InfJobDO#getId()} + * 关联 {@link JobDO#getId()} */ private Long jobId; /** * 处理器的名字 * - * 冗余字段 {@link InfJobDO#getHandlerName()} + * 冗余字段 {@link JobDO#getHandlerName()} */ private String handlerName; /** * 处理器的参数 * - * 冗余字段 {@link InfJobDO#getHandlerParam()} + * 冗余字段 {@link JobDO#getHandlerParam()} */ private String handlerParam; /** @@ -66,7 +66,7 @@ public class InfJobLogDO extends BaseDO { /** * 状态 * - * 枚举 {@link InfJobLogStatusEnum} + * 枚举 {@link JobLogStatusEnum} */ private Integer status; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java similarity index 92% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java index 32e28c4727..2ad8a326da 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger; +package cn.iocoder.yudao.module.infra.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -14,14 +14,14 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName("inf_api_access_log") +@TableName("infra_api_access_log") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class InfApiAccessLogDO extends TenantBaseDO { +public class ApiAccessLogDO extends TenantBaseDO { /** * 编号 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java similarity index 91% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java index 7f8094caf6..1ed7df4120 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiErrorLogDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger; +package cn.iocoder.yudao.module.infra.dal.dataobject.logger; -import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -14,14 +14,14 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName("inf_api_error_log") +@TableName("infra_api_error_log") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class InfApiErrorLogDO extends TenantBaseDO { +public class ApiErrorLogDO extends TenantBaseDO { /** * 编号 @@ -137,7 +137,7 @@ public class InfApiErrorLogDO extends TenantBaseDO { /** * 处理状态 * - * 枚举 {@link InfApiErrorLogProcessStatusEnum} + * 枚举 {@link ApiErrorLogProcessStatusEnum} */ private Integer processStatus; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/config/InfConfigCoreDAOImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigDAOImpl.java similarity index 81% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/config/InfConfigCoreDAOImpl.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigDAOImpl.java index f3d32513be..e16b59e955 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/config/InfConfigCoreDAOImpl.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigDAOImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.config; +package cn.iocoder.yudao.module.infra.dal.mysql.config; import cn.iocoder.yudao.framework.apollo.internals.ConfigFrameworkDAO; import cn.iocoder.yudao.framework.apollo.internals.dto.ConfigRespDTO; @@ -12,15 +12,15 @@ import java.util.Date; import java.util.List; /** - * ConfigFrameworkDAO Core 实现类 + * ConfigDAOImpl 实现类 * * @author 芋道源码 */ -public class InfConfigCoreDAOImpl implements ConfigFrameworkDAO { +public class ConfigDAOImpl implements ConfigFrameworkDAO { private final JdbcTemplate jdbcTemplate; - public InfConfigCoreDAOImpl(String jdbcUrl, String username, String password) { + public ConfigDAOImpl(String jdbcUrl, String username, String password) { DataSource dataSource = new DriverManagerDataSource(jdbcUrl, username, password); this.jdbcTemplate = new JdbcTemplate(dataSource); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/config/InfConfigMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/config/InfConfigMapper.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java index e7960eaefd..aad99ccba6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/config/InfConfigMapper.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java @@ -1,33 +1,33 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.config; +package cn.iocoder.yudao.module.infra.dal.mysql.config; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper -public interface InfConfigMapper extends BaseMapperX { +public interface ConfigMapper extends BaseMapperX { - default InfConfigDO selectByKey(String key) { - return selectOne(new QueryWrapper().eq("`key`", key)); + default ConfigDO selectByKey(String key) { + return selectOne(new QueryWrapper().eq("`key`", key)); } - default PageResult selectPage(InfConfigPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(ConfigPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .likeIfPresent("name", reqVO.getName()) .likeIfPresent("`key`", reqVO.getKey()) .eqIfPresent("`type`", reqVO.getType()) .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())); } - default List selectList(InfConfigExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(ConfigExportReqVO reqVO) { + return selectList(new QueryWrapperX() .likeIfPresent("name", reqVO.getName()) .likeIfPresent("`key`", reqVO.getKey()) .eqIfPresent("`type`", reqVO.getType()) diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java new file mode 100644 index 0000000000..06e887dde5 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.file; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +/** + * 文件操作 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface FileMapper extends BaseMapperX { + + default PageResult selectPage(FilePageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .likeIfPresent("id", reqVO.getId()) + .likeIfPresent("type", reqVO.getType()) + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc("create_time")); + } + + default Integer selectCountById(String id) { + return selectCount(FileDO::getId, id); + } + + /** + * 基于 Path 获取文件 + * 实际上,是基于 ID 查询 + * 由于前端使用 的方式获取图片,所以需要忽略租户的查询 + * + * @param path 路径 + * @return 文件 + */ + @InterceptorIgnore(tenantLine = "true") + default FileDO selectByPath(String path) { + return selectById(path); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobLogMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobLogMapper.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobLogMapper.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobLogMapper.java index 4b1b920bea..fe196df359 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/job/InfJobLogMapper.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobLogMapper.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job; +package cn.iocoder.yudao.module.infra.dal.mysql.job; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -16,10 +16,10 @@ import java.util.List; * @author 芋道源码 */ @Mapper -public interface InfJobLogMapper extends BaseMapperX { +public interface JobLogMapper extends BaseMapperX { - default PageResult selectPage(InfJobLogPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(JobLogPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("job_id", reqVO.getJobId()) .likeIfPresent("handler_name", reqVO.getHandlerName()) .geIfPresent("begin_time", reqVO.getBeginTime()) @@ -29,8 +29,8 @@ public interface InfJobLogMapper extends BaseMapperX { ); } - default List selectList(InfJobLogExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(JobLogExportReqVO reqVO) { + return selectList(new QueryWrapperX() .eqIfPresent("job_id", reqVO.getJobId()) .likeIfPresent("handler_name", reqVO.getHandlerName()) .geIfPresent("begin_time", reqVO.getBeginTime()) diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobMapper.java new file mode 100644 index 0000000000..883906a013 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/job/JobMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.job; + +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 定时任务 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface JobMapper extends BaseMapperX { + + default JobDO selectByHandlerName(String handlerName) { + return selectOne(JobDO::getHandlerName, handlerName); + } + + default PageResult selectPage(JobPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(JobDO::getName, reqVO.getName()) + .eqIfPresent(JobDO::getStatus, reqVO.getStatus()) + .likeIfPresent(JobDO::getHandlerName, reqVO.getHandlerName()) + ); + } + + default List selectList(JobExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(JobDO::getName, reqVO.getName()) + .eqIfPresent(JobDO::getStatus, reqVO.getStatus()) + .likeIfPresent(JobDO::getHandlerName, reqVO.getHandlerName()) + ); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java index 4552762fc0..8f00fbebc9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger; +package cn.iocoder.yudao.module.infra.dal.mysql.logger; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -16,10 +16,10 @@ import java.util.List; * @author 芋道源码 */ @Mapper -public interface InfApiAccessLogMapper extends BaseMapperX { +public interface ApiAccessLogMapper extends BaseMapperX { - default PageResult selectPage(InfApiAccessLogPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(ApiAccessLogPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("user_id", reqVO.getUserId()) .eqIfPresent("user_type", reqVO.getUserType()) .eqIfPresent("application_name", reqVO.getApplicationName()) @@ -31,8 +31,8 @@ public interface InfApiAccessLogMapper extends BaseMapperX { ); } - default List selectList(InfApiAccessLogExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(ApiAccessLogExportReqVO reqVO) { + return selectList(new QueryWrapperX() .eqIfPresent("user_id", reqVO.getUserId()) .eqIfPresent("user_type", reqVO.getUserType()) .eqIfPresent("application_name", reqVO.getApplicationName()) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java index d96e5fc3b6..7e4ab62c39 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger; +package cn.iocoder.yudao.module.infra.dal.mysql.logger; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @@ -16,10 +16,10 @@ import java.util.List; * @author 芋道源码 */ @Mapper -public interface InfApiErrorLogMapper extends BaseMapperX { +public interface ApiErrorLogMapper extends BaseMapperX { - default PageResult selectPage(InfApiErrorLogPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(ApiErrorLogPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("user_id", reqVO.getUserId()) .eqIfPresent("user_type", reqVO.getUserType()) .eqIfPresent("application_name", reqVO.getApplicationName()) @@ -30,8 +30,8 @@ public interface InfApiErrorLogMapper extends BaseMapperX { ); } - default List selectList(InfApiErrorLogExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(ApiErrorLogExportReqVO reqVO) { + return selectList(new QueryWrapperX() .eqIfPresent("user_id", reqVO.getUserId()) .eqIfPresent("user_type", reqVO.getUserType()) .eqIfPresent("application_name", reqVO.getApplicationName()) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/config/InfConfigTypeEnum.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/config/ConfigTypeEnum.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/config/InfConfigTypeEnum.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/config/ConfigTypeEnum.java index 6e9fd4d35d..15c20152f0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/config/InfConfigTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/config/ConfigTypeEnum.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums.config; +package cn.iocoder.yudao.module.infra.enums.config; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor -public enum InfConfigTypeEnum { +public enum ConfigTypeEnum { /** * 系统配置 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobLogStatusEnum.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobLogStatusEnum.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobLogStatusEnum.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobLogStatusEnum.java index e904e674fb..95670539e9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobLogStatusEnum.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobLogStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums.job; +package cn.iocoder.yudao.module.infra.enums.job; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum InfJobLogStatusEnum { +public enum JobLogStatusEnum { RUNNING(0), // 运行中 SUCCESS(1), // 成功 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobStatusEnum.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobStatusEnum.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobStatusEnum.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobStatusEnum.java index 1a7c984bbb..3d9ec3f755 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/job/InfJobStatusEnum.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/job/JobStatusEnum.java @@ -1,14 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.infra.enums.job; +package cn.iocoder.yudao.module.infra.enums.job; import com.google.common.collect.Sets; import lombok.AllArgsConstructor; import lombok.Getter; +import org.quartz.impl.jdbcjobstore.Constants; import java.util.Collections; import java.util.Set; -import static org.quartz.impl.jdbcjobstore.Constants.*; - /** * 任务状态的枚举 * @@ -16,7 +15,7 @@ import static org.quartz.impl.jdbcjobstore.Constants.*; */ @Getter @AllArgsConstructor -public enum InfJobStatusEnum { +public enum JobStatusEnum { /** * 初始化中 @@ -25,11 +24,11 @@ public enum InfJobStatusEnum { /** * 开启 */ - NORMAL(1, Sets.newHashSet(STATE_WAITING, STATE_ACQUIRED, STATE_BLOCKED)), + NORMAL(1, Sets.newHashSet(Constants.STATE_WAITING, Constants.STATE_ACQUIRED, Constants.STATE_BLOCKED)), /** * 暂停 */ - STOP(2, Sets.newHashSet(STATE_PAUSED, STATE_PAUSED_BLOCKED)); + STOP(2, Sets.newHashSet(Constants.STATE_PAUSED, Constants.STATE_PAUSED_BLOCKED)); /** * 状态 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/logger/ApiErrorLogProcessStatusEnum.java similarity index 77% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/logger/ApiErrorLogProcessStatusEnum.java index cba1d02dd8..b3097534ce 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/enums/logger/ApiErrorLogProcessStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.enums.logger; +package cn.iocoder.yudao.module.infra.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum InfApiErrorLogProcessStatusEnum { +public enum ApiErrorLogProcessStatusEnum { INIT(0, "未处理"), DONE(1, "已处理"), diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileConfiguration.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileConfiguration.java similarity index 78% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileConfiguration.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileConfiguration.java index a10c7a7aff..f944daa231 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileConfiguration.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config; +package cn.iocoder.yudao.module.infra.framework.file.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileProperties.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileProperties.java similarity index 77% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileProperties.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileProperties.java index 0d8ed7cda5..c112802b07 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileProperties.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/config/FileProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config; +package cn.iocoder.yudao.module.infra.framework.file.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull; public class FileProperties { /** - * 对应 InfFileController 的 getFile 方法 + * 对应 FileController 的 getFile 方法 */ @NotNull(message = "基础文件路径不能为空") private String basePath; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/package-info.java similarity index 92% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/package-info.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/package-info.java index 2c2798ee62..ee21b922eb 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/package-info.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/file/package-info.java @@ -13,4 +13,4 @@ * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。 * 随着文件的量级大了之后,还是推荐采用云服务。 */ -package cn.iocoder.yudao.coreservice.modules.infra.framework.file; +package cn.iocoder.yudao.module.infra.framework.file; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/config/AdminServerConfiguration.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/config/AdminServerConfiguration.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/config/AdminServerConfiguration.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/config/AdminServerConfiguration.java index c9614410dd..697426e449 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/config/AdminServerConfiguration.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/config/AdminServerConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.framework.monitor.config; +package cn.iocoder.yudao.module.infra.framework.monitor.config; import de.codecentric.boot.admin.server.config.EnableAdminServer; import org.springframework.context.annotation.Configuration; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/package-info.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/package-info.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/package-info.java index 0d380cfaa3..f52e72c76f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/package-info.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/package-info.java @@ -1,4 +1,4 @@ /** * 使用 Spring Boot Admin 实现简单的监控平台 */ -package cn.iocoder.yudao.adminserver.framework.monitor; +package cn.iocoder.yudao.module.infra.framework.monitor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/package-info.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/package-info.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/package-info.java index c04bc96df0..77a646af83 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/package-info.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.infra.framework; +package cn.iocoder.yudao.module.infra.framework; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java new file mode 100644 index 0000000000..3b2a5501ee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.infra.framework.security.config; + +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; + +/** + * Infra 模块的 Security 配置 + */ +@Configuration("infraSecurityConfiguration") +public class SecurityConfiguration { + + @Value("${spring.boot.admin.context-path:''}") + private String adminSeverContextPath; + + @Bean("infraAuthorizeRequestsCustomizer") + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { + return new AuthorizeRequestsCustomizer() { + + @Override + public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + // Swagger 接口文档 + registry.antMatchers("/swagger-ui.html").anonymous() + .antMatchers("/swagger-resources/**").anonymous() + .antMatchers("/webjars/**").anonymous() + .antMatchers("/*/api-docs").anonymous(); + // Spring Boot Actuator 的安全配置 + registry.antMatchers("/actuator").anonymous() + .antMatchers("/actuator/**").anonymous(); + // Druid 监控 + registry.antMatchers("/druid/**").anonymous(); + // Spring Boot Admin Server 的安全配置 + registry.antMatchers(adminSeverContextPath).anonymous() + .antMatchers(adminSeverContextPath + "/**").anonymous(); + // 文件的获取接口,可匿名访问 + registry.antMatchers(buildAdminApi("/infra/file/get/**"), buildAppApi("/infra/file/get/**")).anonymous(); + } + + }; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/core/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/core/package-info.java new file mode 100644 index 0000000000..7762626c9d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.infra.framework.security.core; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/config/ConfigRefreshConsumer.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/config/ConfigRefreshConsumer.java index 35d3f791b8..d13003afbb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/consumer/config/InfConfigRefreshConsumer.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/config/ConfigRefreshConsumer.java @@ -1,22 +1,22 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.consumer.config; +package cn.iocoder.yudao.module.infra.mq.consumer.config; import cn.iocoder.yudao.framework.apollo.internals.DBConfigRepository; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage; +import cn.iocoder.yudao.module.infra.mq.message.config.ConfigRefreshMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** - * 针对 {@link InfConfigRefreshMessage} 的消费者 + * 针对 {@link ConfigRefreshMessage} 的消费者 * * @author 芋道源码 */ @Component @Slf4j -public class InfConfigRefreshConsumer extends AbstractChannelMessageListener { +public class ConfigRefreshConsumer extends AbstractChannelMessageListener { @Override - public void onMessage(InfConfigRefreshMessage message) { + public void onMessage(ConfigRefreshMessage message) { log.info("[onMessage][收到 Config 刷新消息]"); DBConfigRepository.noticeSync(); } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/package-info.java new file mode 100644 index 0000000000..aa5028bec1 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/consumer/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.infra.mq.consumer; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/config/ConfigRefreshMessage.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/config/ConfigRefreshMessage.java index 4846d9b900..380a1736b9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/config/ConfigRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config; +package cn.iocoder.yudao.module.infra.mq.message.config; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -7,7 +7,7 @@ import lombok.Data; * 配置数据刷新 Message */ @Data -public class InfConfigRefreshMessage extends AbstractChannelMessage { +public class ConfigRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/package-info.java new file mode 100644 index 0000000000..997752c34b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/message/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.infra.mq.message; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/config/ConfigProducer.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/config/ConfigProducer.java index 2a0dc66fde..92d0e34b6e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/config/ConfigProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config; +package cn.iocoder.yudao.module.infra.mq.producer.config; -import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage; +import cn.iocoder.yudao.module.infra.mq.message.config.ConfigRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * Config 配置相关消息的 Producer */ @Component -public class InfConfigProducer { +public class ConfigProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link InfConfigRefreshMessage} 消息 + * 发送 {@link ConfigRefreshMessage} 消息 */ public void sendConfigRefreshMessage() { - InfConfigRefreshMessage message = new InfConfigRefreshMessage(); + ConfigRefreshMessage message = new ConfigRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/package-info.java new file mode 100644 index 0000000000..5bd8d7cc53 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/mq/producer/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.infra.mq.producer; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/package-info.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/package-info.java new file mode 100644 index 0000000000..da6d4aae8a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/package-info.java @@ -0,0 +1,8 @@ +/** + * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 + * 例如说:定时任务的管理、服务器的信息等等 + * + * 1. Controller URL:以 /infra/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 infra_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.infra; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigService.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java index 166ebdbd14..abd82e54ac 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigService.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.config; +package cn.iocoder.yudao.module.infra.service.config; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import javax.validation.Valid; import java.util.List; @@ -15,7 +15,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface InfConfigService { +public interface ConfigService { /** * 创建参数配置 @@ -23,14 +23,14 @@ public interface InfConfigService { * @param reqVO 创建信息 * @return 配置编号 */ - Long createConfig(@Valid InfConfigCreateReqVO reqVO); + Long createConfig(@Valid ConfigCreateReqVO reqVO); /** * 更新参数配置 * * @param reqVO 更新信息 */ - void updateConfig(@Valid InfConfigUpdateReqVO reqVO); + void updateConfig(@Valid ConfigUpdateReqVO reqVO); /** * 删除参数配置 @@ -45,7 +45,7 @@ public interface InfConfigService { * @param id 配置编号 * @return 参数配置 */ - InfConfigDO getConfig(Long id); + ConfigDO getConfig(Long id); /** * 根据参数键,获得参数配置 @@ -53,7 +53,7 @@ public interface InfConfigService { * @param key 配置键 * @return 参数配置 */ - InfConfigDO getConfigByKey(String key); + ConfigDO getConfigByKey(String key); /** * 获得参数配置分页列表 @@ -61,7 +61,7 @@ public interface InfConfigService { * @param reqVO 分页条件 * @return 分页列表 */ - PageResult getConfigPage(@Valid InfConfigPageReqVO reqVO); + PageResult getConfigPage(@Valid ConfigPageReqVO reqVO); /** * 获得参数配置列表 @@ -69,7 +69,7 @@ public interface InfConfigService { * @param reqVO 列表 * @return 列表 */ - List getConfigList(@Valid InfConfigExportReqVO reqVO); + List getConfigList(@Valid ConfigExportReqVO reqVO); } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java new file mode 100644 index 0000000000..f6eb43cd5a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java @@ -0,0 +1,129 @@ +package cn.iocoder.yudao.module.infra.service.config; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.config.ConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigMapper; +import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum; +import cn.iocoder.yudao.module.infra.mq.producer.config.ConfigProducer; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 参数配置 Service 实现类 + */ +@Service +@Slf4j +@Validated +public class ConfigServiceImpl implements ConfigService { + + @Resource + private ConfigMapper configMapper; + + @Resource + private ConfigProducer configProducer; + + @Override + public Long createConfig(ConfigCreateReqVO reqVO) { + // 校验正确性 + checkCreateOrUpdate(null, reqVO.getKey()); + // 插入参数配置 + ConfigDO config = ConfigConvert.INSTANCE.convert(reqVO); + config.setType(ConfigTypeEnum.CUSTOM.getType()); + configMapper.insert(config); + // 发送刷新消息 + configProducer.sendConfigRefreshMessage(); + return config.getId(); + } + + @Override + public void updateConfig(ConfigUpdateReqVO reqVO) { + // 校验正确性 + checkCreateOrUpdate(reqVO.getId(), null); // 不允许更新 key + // 更新参数配置 + ConfigDO updateObj = ConfigConvert.INSTANCE.convert(reqVO); + configMapper.updateById(updateObj); + // 发送刷新消息 + configProducer.sendConfigRefreshMessage(); + } + + @Override + public void deleteConfig(Long id) { + // 校验配置存在 + ConfigDO config = checkConfigExists(id); + // 内置配置,不允许删除 + if (ConfigTypeEnum.SYSTEM.getType().equals(config.getType())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE); + } + // 删除 + configMapper.deleteById(id); + // 发送刷新消息 + configProducer.sendConfigRefreshMessage(); + } + + @Override + public ConfigDO getConfig(Long id) { + return configMapper.selectById(id); + } + + @Override + public ConfigDO getConfigByKey(String key) { + return configMapper.selectByKey(key); + } + + @Override + public PageResult getConfigPage(ConfigPageReqVO reqVO) { + return configMapper.selectPage(reqVO); + } + + @Override + public List getConfigList(ConfigExportReqVO reqVO) { + return configMapper.selectList(reqVO); + } + + private void checkCreateOrUpdate(Long id, String key) { + // 校验自己存在 + checkConfigExists(id); + // 校验参数配置 key 的唯一性 + checkConfigKeyUnique(id, key); + } + + @VisibleForTesting + public ConfigDO checkConfigExists(Long id) { + if (id == null) { + return null; + } + ConfigDO config = configMapper.selectById(id); + if (config == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_NOT_EXISTS); + } + return config; + } + + @VisibleForTesting + public void checkConfigKeyUnique(Long id, String key) { + ConfigDO config = configMapper.selectByKey(key); + if (config == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的参数配置 + if (id == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_KEY_DUPLICATE); + } + if (!config.getId().equals(id)) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_KEY_DUPLICATE); + } + } + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java new file mode 100644 index 0000000000..4fb658aa5a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.infra.service.file; + +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; + +/** + * 文件 Service 接口 + * + * @author 芋道源码 + */ +public interface FileService { + + /** + * 获得文件分页 + * + * @param pageReqVO 分页查询 + * @return 文件分页 + */ + PageResult getFilePage(FilePageReqVO pageReqVO); + + /** + * 保存文件,并返回文件的访问路径 + * + * @param path 文件路径 + * @param content 文件内容 + * @return 文件路径 + */ + String createFile(String path, byte[] content); + + /** + * 删除文件 + * + * @param id 编号 + */ + void deleteFile(String id); + + /** + * 获得文件 + * + * @param path 文件路径 + * @return 文件 + */ + FileDO getFile(String path); + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/impl/InfFileCoreServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java similarity index 59% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/impl/InfFileCoreServiceImpl.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 3e2c7ead44..1f1724ecd1 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/impl/InfFileCoreServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -1,39 +1,45 @@ -package cn.iocoder.yudao.coreservice.modules.infra.service.file.impl; +package cn.iocoder.yudao.module.infra.service.file; import cn.hutool.core.io.FileTypeUtil; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper; -import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; +import cn.iocoder.yudao.module.infra.framework.file.config.FileProperties; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.ByteArrayInputStream; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; /** - * core service 文件实现类 + * 文件 Service 实现类 * - * @author 宋天 + * @author 芋道源码 */ @Service -public class InfFileCoreServiceImpl implements InfFileCoreService { +public class FileServiceImpl implements FileService { @Resource - private InfFileCoreMapper fileMapper; + private FileMapper fileMapper; @Resource private FileProperties fileProperties; + @Override + public PageResult getFilePage(FilePageReqVO pageReqVO) { + return fileMapper.selectPage(pageReqVO); + } + @Override public String createFile(String path, byte[] content) { if (fileMapper.selectCountById(path) > 0) { throw exception(FILE_PATH_EXISTS); } // 保存到数据库 - InfFileDO file = new InfFileDO(); + FileDO file = new FileDO(); file.setId(path); file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content))); file.setContent(content); @@ -57,7 +63,7 @@ public class InfFileCoreServiceImpl implements InfFileCoreService { } @Override - public InfFileDO getFile(String path) { + public FileDO getFile(String path) { return fileMapper.selectByPath(path); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogService.java similarity index 54% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogService.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogService.java index e4b93d2610..e2e9e73e4e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogService.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogService.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job; +package cn.iocoder.yudao.module.infra.service.job; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.quartz.core.service.JobLogFrameworkService; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; import java.util.Collection; import java.util.List; @@ -14,7 +14,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface InfJobLogService extends JobLogFrameworkService { +public interface JobLogService extends JobLogFrameworkService { /** * 获得定时任务 @@ -22,7 +22,7 @@ public interface InfJobLogService extends JobLogFrameworkService { * @param id 编号 * @return 定时任务 */ - InfJobLogDO getJobLog(Long id); + JobLogDO getJobLog(Long id); /** * 获得定时任务列表 @@ -30,7 +30,7 @@ public interface InfJobLogService extends JobLogFrameworkService { * @param ids 编号 * @return 定时任务列表 */ - List getJobLogList(Collection ids); + List getJobLogList(Collection ids); /** * 获得定时任务分页 @@ -38,7 +38,7 @@ public interface InfJobLogService extends JobLogFrameworkService { * @param pageReqVO 分页查询 * @return 定时任务分页 */ - PageResult getJobLogPage(InfJobLogPageReqVO pageReqVO); + PageResult getJobLogPage(JobLogPageReqVO pageReqVO); /** * 获得定时任务列表, 用于 Excel 导出 @@ -46,6 +46,6 @@ public interface InfJobLogService extends JobLogFrameworkService { * @param exportReqVO 查询条件 * @return 定时任务分页 */ - List getJobLogList(InfJobLogExportReqVO exportReqVO); + List getJobLogList(JobLogExportReqVO exportReqVO); } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceImpl.java new file mode 100644 index 0000000000..8b3c2ef884 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceImpl.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.infra.service.job; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; +import cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper; +import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * Job 日志 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class JobLogServiceImpl implements JobLogService { + + @Resource + private JobLogMapper jobLogMapper; + + @Override + public Long createJobLog(Long jobId, Date beginTime, String jobHandlerName, String jobHandlerParam, Integer executeIndex) { + JobLogDO log = JobLogDO.builder().jobId(jobId).handlerName(jobHandlerName).handlerParam(jobHandlerParam).executeIndex(executeIndex) + .beginTime(beginTime).status(JobLogStatusEnum.RUNNING.getStatus()).build(); + jobLogMapper.insert(log); + return log.getId(); + } + + @Override + @Async + public void updateJobLogResultAsync(Long logId, Date endTime, Integer duration, boolean success, String result) { + try { + JobLogDO updateObj = JobLogDO.builder().id(logId).endTime(endTime).duration(duration) + .status(success ? JobLogStatusEnum.SUCCESS.getStatus() : JobLogStatusEnum.FAILURE.getStatus()).result(result).build(); + jobLogMapper.updateById(updateObj); + } catch (Exception ex) { + log.error("[updateJobLogResultAsync][logId({}) endTime({}) duration({}) success({}) result({})]", + logId, endTime, duration, success, result); + } + } + + @Override + public JobLogDO getJobLog(Long id) { + return jobLogMapper.selectById(id); + } + + @Override + public List getJobLogList(Collection ids) { + return jobLogMapper.selectBatchIds(ids); + } + + @Override + public PageResult getJobLogPage(JobLogPageReqVO pageReqVO) { + return jobLogMapper.selectPage(pageReqVO); + } + + @Override + public List getJobLogList(JobLogExportReqVO exportReqVO) { + return jobLogMapper.selectList(exportReqVO); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobService.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobService.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobService.java index ba90a3b6a9..bd5dd646d6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobService.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job; +package cn.iocoder.yudao.module.infra.service.job; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; import org.quartz.SchedulerException; import javax.validation.Valid; @@ -17,7 +17,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface InfJobService { +public interface JobService { /** * 创建定时任务 @@ -25,14 +25,14 @@ public interface InfJobService { * @param createReqVO 创建信息 * @return 编号 */ - Long createJob(@Valid InfJobCreateReqVO createReqVO) throws SchedulerException; + Long createJob(@Valid JobCreateReqVO createReqVO) throws SchedulerException; /** * 更新定时任务 * * @param updateReqVO 更新信息 */ - void updateJob(@Valid InfJobUpdateReqVO updateReqVO) throws SchedulerException; + void updateJob(@Valid JobUpdateReqVO updateReqVO) throws SchedulerException; /** * 更新定时任务的状态 @@ -62,7 +62,7 @@ public interface InfJobService { * @param id 编号 * @return 定时任务 */ - InfJobDO getJob(Long id); + JobDO getJob(Long id); /** * 获得定时任务列表 @@ -70,7 +70,7 @@ public interface InfJobService { * @param ids 编号 * @return 定时任务列表 */ - List getJobList(Collection ids); + List getJobList(Collection ids); /** * 获得定时任务分页 @@ -78,7 +78,7 @@ public interface InfJobService { * @param pageReqVO 分页查询 * @return 定时任务分页 */ - PageResult getJobPage(InfJobPageReqVO pageReqVO); + PageResult getJobPage(JobPageReqVO pageReqVO); /** * 获得定时任务列表, 用于 Excel 导出 @@ -86,6 +86,6 @@ public interface InfJobService { * @param exportReqVO 查询条件 * @return 定时任务分页 */ - List getJobList(InfJobExportReqVO exportReqVO); + List getJobList(JobExportReqVO exportReqVO); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobServiceImpl.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java index 3597727579..e0a245750c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/impl/InfJobServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java @@ -1,17 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job.impl; +package cn.iocoder.yudao.module.infra.service.job; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; import cn.iocoder.yudao.framework.quartz.core.util.CronUtils; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.job.InfJobConvert; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job.InfJobMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.InfJobService; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.job.JobConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; +import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; +import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; import org.quartz.SchedulerException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,7 +21,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.containsAny; /** @@ -32,25 +31,25 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. */ @Service @Validated -public class InfJobServiceImpl implements InfJobService { +public class JobServiceImpl implements JobService { @Resource - private InfJobMapper jobMapper; + private JobMapper jobMapper; @Resource private SchedulerManager schedulerManager; @Override @Transactional(rollbackFor = Exception.class) - public Long createJob(InfJobCreateReqVO createReqVO) throws SchedulerException { + public Long createJob(JobCreateReqVO createReqVO) throws SchedulerException { validateCronExpression(createReqVO.getCronExpression()); // 校验唯一性 if (jobMapper.selectByHandlerName(createReqVO.getHandlerName()) != null) { throw exception(JOB_HANDLER_EXISTS); } // 插入 - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.INIT.getStatus()); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.INIT.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); @@ -58,7 +57,7 @@ public class InfJobServiceImpl implements InfJobService { schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(), createReqVO.getRetryCount(), createReqVO.getRetryInterval()); // 更新 - InfJobDO updateObj = InfJobDO.builder().id(job.getId()).status(InfJobStatusEnum.NORMAL.getStatus()).build(); + JobDO updateObj = JobDO.builder().id(job.getId()).status(JobStatusEnum.NORMAL.getStatus()).build(); jobMapper.updateById(updateObj); // 返回 @@ -67,16 +66,16 @@ public class InfJobServiceImpl implements InfJobService { @Override @Transactional(rollbackFor = Exception.class) - public void updateJob(InfJobUpdateReqVO updateReqVO) throws SchedulerException { + public void updateJob(JobUpdateReqVO updateReqVO) throws SchedulerException { validateCronExpression(updateReqVO.getCronExpression()); // 校验存在 - InfJobDO job = this.validateJobExists(updateReqVO.getId()); + JobDO job = this.validateJobExists(updateReqVO.getId()); // 只有开启状态,才可以修改.原因是,如果出暂停状态,修改 Quartz Job 时,会导致任务又开始执行 - if (!job.getStatus().equals(InfJobStatusEnum.NORMAL.getStatus())) { + if (!job.getStatus().equals(JobStatusEnum.NORMAL.getStatus())) { throw exception(JOB_UPDATE_ONLY_NORMAL_STATUS); } // 更新 - InfJobDO updateObj = InfJobConvert.INSTANCE.convert(updateReqVO); + JobDO updateObj = JobConvert.INSTANCE.convert(updateReqVO); fillJobMonitorTimeoutEmpty(updateObj); jobMapper.updateById(updateObj); @@ -89,21 +88,21 @@ public class InfJobServiceImpl implements InfJobService { @Transactional(rollbackFor = Exception.class) public void updateJobStatus(Long id, Integer status) throws SchedulerException { // 校验 status - if (!containsAny(status, InfJobStatusEnum.NORMAL.getStatus(), InfJobStatusEnum.STOP.getStatus())) { + if (!containsAny(status, JobStatusEnum.NORMAL.getStatus(), JobStatusEnum.STOP.getStatus())) { throw exception(JOB_CHANGE_STATUS_INVALID); } // 校验存在 - InfJobDO job = this.validateJobExists(id); + JobDO job = this.validateJobExists(id); // 校验是否已经为当前状态 if (job.getStatus().equals(status)) { throw exception(JOB_CHANGE_STATUS_EQUALS); } // 更新 Job 状态 - InfJobDO updateObj = InfJobDO.builder().id(id).status(status).build(); + JobDO updateObj = JobDO.builder().id(id).status(status).build(); jobMapper.updateById(updateObj); // 更新状态 Job 到 Quartz 中 - if (InfJobStatusEnum.NORMAL.getStatus().equals(status)) { // 开启 + if (JobStatusEnum.NORMAL.getStatus().equals(status)) { // 开启 schedulerManager.resumeJob(job.getHandlerName()); } else { // 暂停 schedulerManager.pauseJob(job.getHandlerName()); @@ -113,7 +112,7 @@ public class InfJobServiceImpl implements InfJobService { @Override public void triggerJob(Long id) throws SchedulerException { // 校验存在 - InfJobDO job = this.validateJobExists(id); + JobDO job = this.validateJobExists(id); // 触发 Quartz 中的 Job schedulerManager.triggerJob(job.getId(), job.getHandlerName(), job.getHandlerParam()); @@ -123,7 +122,7 @@ public class InfJobServiceImpl implements InfJobService { @Transactional(rollbackFor = Exception.class) public void deleteJob(Long id) throws SchedulerException { // 校验存在 - InfJobDO job = this.validateJobExists(id); + JobDO job = this.validateJobExists(id); // 更新 jobMapper.deleteById(id); @@ -131,8 +130,8 @@ public class InfJobServiceImpl implements InfJobService { schedulerManager.deleteJob(job.getHandlerName()); } - private InfJobDO validateJobExists(Long id) { - InfJobDO job = jobMapper.selectById(id); + private JobDO validateJobExists(Long id) { + JobDO job = jobMapper.selectById(id); if (job == null) { throw exception(JOB_NOT_EXISTS); } @@ -146,26 +145,26 @@ public class InfJobServiceImpl implements InfJobService { } @Override - public InfJobDO getJob(Long id) { + public JobDO getJob(Long id) { return jobMapper.selectById(id); } @Override - public List getJobList(Collection ids) { + public List getJobList(Collection ids) { return jobMapper.selectBatchIds(ids); } @Override - public PageResult getJobPage(InfJobPageReqVO pageReqVO) { + public PageResult getJobPage(JobPageReqVO pageReqVO) { return jobMapper.selectPage(pageReqVO); } @Override - public List getJobList(InfJobExportReqVO exportReqVO) { + public List getJobList(JobExportReqVO exportReqVO) { return jobMapper.selectList(exportReqVO); } - private static void fillJobMonitorTimeoutEmpty(InfJobDO job) { + private static void fillJobMonitorTimeoutEmpty(JobDO job) { if (job.getMonitorTimeout() == null) { job.setMonitorTimeout(0); } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java new file mode 100644 index 0000000000..22aea79b41 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.service.logger; + +import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; + +import java.util.List; + +/** + * API 访问日志 Service 接口 + * + * @author 芋道源码 + */ +public interface ApiAccessLogService extends ApiAccessLogFrameworkService { + + /** + * 获得 API 访问日志分页 + * + * @param pageReqVO 分页查询 + * @return API 访问日志分页 + */ + PageResult getApiAccessLogPage(ApiAccessLogPageReqVO pageReqVO); + + /** + * 获得 API 访问日志列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return API 访问日志分页 + */ + List getApiAccessLogList(ApiAccessLogExportReqVO exportReqVO); + +} diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java new file mode 100644 index 0000000000..64df85ac04 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.infra.service.logger; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; +import cn.iocoder.yudao.module.infra.convert.logger.ApiAccessLogConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; +import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * API 访问日志 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ApiAccessLogServiceImpl implements ApiAccessLogService { + + @Resource + private ApiAccessLogMapper apiAccessLogMapper; + + @Override + public PageResult getApiAccessLogPage(ApiAccessLogPageReqVO pageReqVO) { + return apiAccessLogMapper.selectPage(pageReqVO); + } + + @Override + public List getApiAccessLogList(ApiAccessLogExportReqVO exportReqVO) { + return apiAccessLogMapper.selectList(exportReqVO); + } + + @Override + @Async + public void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) { + ApiAccessLogDO apiAccessLog = ApiAccessLogConvert.INSTANCE.convert(createDTO); + apiAccessLogMapper.insert(apiAccessLog); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogService.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogService.java rename to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java index c778eee310..2ad0479fe4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogService.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java @@ -1,9 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger; +package cn.iocoder.yudao.module.infra.service.logger; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; +import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import java.util.List; @@ -12,7 +13,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface InfApiErrorLogService { +public interface ApiErrorLogService extends ApiErrorLogFrameworkService { /** * 获得 API 错误日志分页 @@ -20,7 +21,7 @@ public interface InfApiErrorLogService { * @param pageReqVO 分页查询 * @return API 错误日志分页 */ - PageResult getApiErrorLogPage(InfApiErrorLogPageReqVO pageReqVO); + PageResult getApiErrorLogPage(ApiErrorLogPageReqVO pageReqVO); /** * 获得 API 错误日志列表, 用于 Excel 导出 @@ -28,7 +29,7 @@ public interface InfApiErrorLogService { * @param exportReqVO 查询条件 * @return API 错误日志分页 */ - List getApiErrorLogList(InfApiErrorLogExportReqVO exportReqVO); + List getApiErrorLogList(ApiErrorLogExportReqVO exportReqVO); /** * 更新 API 错误日志已处理 diff --git a/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java new file mode 100644 index 0000000000..038f47a381 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.infra.service.logger; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.convert.logger.ApiErrorLogConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; +import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * API 错误日志 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ApiErrorLogServiceImpl implements ApiErrorLogService { + + @Resource + private ApiErrorLogMapper apiErrorLogMapper; + + @Override + public PageResult getApiErrorLogPage(ApiErrorLogPageReqVO pageReqVO) { + return apiErrorLogMapper.selectPage(pageReqVO); + } + + @Override + public List getApiErrorLogList(ApiErrorLogExportReqVO exportReqVO) { + return apiErrorLogMapper.selectList(exportReqVO); + } + + @Override + public void updateApiErrorLogProcess(Long id, Integer processStatus, Long processUserId) { + ApiErrorLogDO errorLog = apiErrorLogMapper.selectById(id); + if (errorLog == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.API_ERROR_LOG_NOT_FOUND); + } + if (!ApiErrorLogProcessStatusEnum.INIT.getStatus().equals(errorLog.getProcessStatus())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.API_ERROR_LOG_PROCESSED); + } + // 标记处理 + apiErrorLogMapper.updateById(ApiErrorLogDO.builder().id(id).processStatus(processStatus) + .processUserId(processUserId).processTime(new Date()).build()); + } + + @Override + @Async + public void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) { + ApiErrorLogDO apiErrorLog = ApiErrorLogConvert.INSTANCE.convert(createDTO); + apiErrorLog.setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); + apiErrorLogMapper.insert(apiErrorLog); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java similarity index 65% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java index ac37cf20cc..1eeae4199a 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java @@ -1,18 +1,19 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.config; +package cn.iocoder.yudao.module.infra.service.config; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.config.InfConfigDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.config.vo.InfConfigUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.config.InfConfigMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.config.InfConfigTypeEnum; -import cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config.InfConfigProducer; -import cn.iocoder.yudao.adminserver.modules.infra.service.config.impl.InfConfigServiceImpl; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigMapper; +import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum; +import cn.iocoder.yudao.module.infra.mq.producer.config.ConfigProducer; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -22,44 +23,39 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -/** - * {@link InfConfigServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(InfConfigServiceImpl.class) -public class InfConfigServiceTest extends BaseDbUnitTest { +@Import(ConfigServiceImpl.class) +public class ConfigServiceTest extends BaseDbUnitTest { @Resource - private InfConfigServiceImpl configService; + private ConfigServiceImpl configService; @Resource - private InfConfigMapper configMapper; + private ConfigMapper configMapper; @MockBean - private InfConfigProducer configProducer; + private ConfigProducer configProducer; @Test public void testCreateConfig_success() { // 准备参数 - InfConfigCreateReqVO reqVO = randomPojo(InfConfigCreateReqVO.class); + ConfigCreateReqVO reqVO = randomPojo(ConfigCreateReqVO.class); // 调用 Long configId = configService.createConfig(reqVO); // 断言 assertNotNull(configId); // 校验记录的属性是否正确 - InfConfigDO config = configMapper.selectById(configId); + ConfigDO config = configMapper.selectById(configId); assertPojoEquals(reqVO, config); - assertEquals(InfConfigTypeEnum.CUSTOM.getType(), config.getType()); + Assertions.assertEquals(ConfigTypeEnum.CUSTOM.getType(), config.getType()); // 校验调用 verify(configProducer, times(1)).sendConfigRefreshMessage(); } @@ -67,17 +63,17 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testUpdateConfig_success() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(); + ConfigDO dbConfig = randomConfigDO(); configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 // 准备参数 - InfConfigUpdateReqVO reqVO = randomPojo(InfConfigUpdateReqVO.class, o -> { + ConfigUpdateReqVO reqVO = randomPojo(ConfigUpdateReqVO.class, o -> { o.setId(dbConfig.getId()); // 设置更新的 ID }); // 调用 configService.updateConfig(reqVO); // 校验是否更新正确 - InfConfigDO config = configMapper.selectById(reqVO.getId()); // 获取最新的 + ConfigDO config = configMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, config); // 校验调用 verify(configProducer, times(1)).sendConfigRefreshMessage(); @@ -86,8 +82,8 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testDeleteConfig_success() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(o -> { - o.setType(InfConfigTypeEnum.CUSTOM.getType()); // 只能删除 CUSTOM 类型 + ConfigDO dbConfig = randomConfigDO(o -> { + o.setType(ConfigTypeEnum.CUSTOM.getType()); // 只能删除 CUSTOM 类型 }); configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 // 准备参数 @@ -104,8 +100,8 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testDeleteConfig_canNotDeleteSystemType() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(o -> { - o.setType(InfConfigTypeEnum.SYSTEM.getType()); // SYSTEM 不允许删除 + ConfigDO dbConfig = randomConfigDO(o -> { + o.setType(ConfigTypeEnum.SYSTEM.getType()); // SYSTEM 不允许删除 }); configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 // 准备参数 @@ -118,7 +114,7 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testCheckConfigExists_success() { // mock 数据 - InfConfigDO dbConfigDO = randomInfConfigDO(); + ConfigDO dbConfigDO = randomConfigDO(); configMapper.insert(dbConfigDO);// @Sql: 先插入出一条存在的数据 // 调用成功 @@ -141,7 +137,7 @@ public class InfConfigServiceTest extends BaseDbUnitTest { // 准备参数 String key = randomString(); // mock 数据 - configMapper.insert(randomInfConfigDO(o -> o.setKey(key))); + configMapper.insert(randomConfigDO(o -> o.setKey(key))); // 调用,校验异常 assertServiceException(() -> configService.checkConfigKeyUnique(null, key), @@ -154,7 +150,7 @@ public class InfConfigServiceTest extends BaseDbUnitTest { Long id = randomLongId(); String key = randomString(); // mock 数据 - configMapper.insert(randomInfConfigDO(o -> o.setKey(key))); + configMapper.insert(randomConfigDO(o -> o.setKey(key))); // 调用,校验异常 assertServiceException(() -> configService.checkConfigKeyUnique(id, key), @@ -164,10 +160,10 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testGetConfigPage() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(o -> { // 等会查询到 + ConfigDO dbConfig = randomConfigDO(o -> { // 等会查询到 o.setName("芋艿"); o.setKey("yunai"); - o.setType(InfConfigTypeEnum.SYSTEM.getType()); + o.setType(ConfigTypeEnum.SYSTEM.getType()); o.setCreateTime(buildTime(2021, 2, 1)); }); configMapper.insert(dbConfig); @@ -176,19 +172,19 @@ public class InfConfigServiceTest extends BaseDbUnitTest { // 测试 key 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou"))); // 测试 type 不匹配 - configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType()))); + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType()))); // 测试 createTime 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 - InfConfigPageReqVO reqVO = new InfConfigPageReqVO(); + ConfigPageReqVO reqVO = new ConfigPageReqVO(); reqVO.setName("艿"); reqVO.setKey("nai"); - reqVO.setType(InfConfigTypeEnum.SYSTEM.getType()); + reqVO.setType(ConfigTypeEnum.SYSTEM.getType()); reqVO.setBeginTime(buildTime(2021, 1, 15)); reqVO.setEndTime(buildTime(2021, 2, 15)); // 调用 - PageResult pageResult = configService.getConfigPage(reqVO); + PageResult pageResult = configService.getConfigPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -198,10 +194,10 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testGetConfigList() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(o -> { // 等会查询到 + ConfigDO dbConfig = randomConfigDO(o -> { // 等会查询到 o.setName("芋艿"); o.setKey("yunai"); - o.setType(InfConfigTypeEnum.SYSTEM.getType()); + o.setType(ConfigTypeEnum.SYSTEM.getType()); o.setCreateTime(buildTime(2021, 2, 1)); }); configMapper.insert(dbConfig); @@ -210,19 +206,19 @@ public class InfConfigServiceTest extends BaseDbUnitTest { // 测试 key 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou"))); // 测试 type 不匹配 - configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType()))); + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType()))); // 测试 createTime 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 - InfConfigExportReqVO reqVO = new InfConfigExportReqVO(); + ConfigExportReqVO reqVO = new ConfigExportReqVO(); reqVO.setName("艿"); reqVO.setKey("nai"); - reqVO.setType(InfConfigTypeEnum.SYSTEM.getType()); + reqVO.setType(ConfigTypeEnum.SYSTEM.getType()); reqVO.setBeginTime(buildTime(2021, 1, 15)); reqVO.setEndTime(buildTime(2021, 2, 15)); // 调用 - List list = configService.getConfigList(reqVO); + List list = configService.getConfigList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbConfig, list.get(0)); @@ -231,13 +227,13 @@ public class InfConfigServiceTest extends BaseDbUnitTest { @Test public void testGetConfigByKey() { // mock 数据 - InfConfigDO dbConfig = randomInfConfigDO(); + ConfigDO dbConfig = randomConfigDO(); configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据 // 准备参数 String key = dbConfig.getKey(); // 调用 - InfConfigDO config = configService.getConfigByKey(key); + ConfigDO config = configService.getConfigByKey(key); // 断言 assertNotNull(config); assertPojoEquals(dbConfig, config); @@ -246,11 +242,11 @@ public class InfConfigServiceTest extends BaseDbUnitTest { // ========== 随机对象 ========== @SafeVarargs - private static InfConfigDO randomInfConfigDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setType(randomEle(InfConfigTypeEnum.values()).getType()); // 保证 key 的范围 + private static ConfigDO randomConfigDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setType(randomEle(ConfigTypeEnum.values()).getType()); // 保证 key 的范围 }; - return randomPojo(InfConfigDO.class, ArrayUtils.append(consumer, consumers)); + return RandomUtils.randomPojo(ConfigDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java new file mode 100644 index 0000000000..8356957e46 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.infra.service.file; + +import cn.hutool.core.io.resource.ResourceUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.test.core.util.AssertUtils; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.FilePageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; +import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; +import cn.iocoder.yudao.module.infra.framework.file.config.FileProperties; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; + +@Import({FileServiceImpl.class, FileProperties.class}) +public class FileServiceTest extends BaseDbUnitTest { + + @Resource + private FileService fileService; + + @MockBean + private FileProperties fileProperties; + + @Resource + private FileMapper fileMapper; + + @Test + public void testGetFilePage() { + // mock 数据 + FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到 + o.setId("yudao"); + o.setType("jpg"); + o.setCreateTime(buildTime(2021, 1, 15)); + }); + fileMapper.insert(dbFile); + // 测试 id 不匹配 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setId("tudou"))); + // 测试 type 不匹配 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { + o.setId("yudao02"); + o.setType("png"); + })); + // 测试 createTime 不匹配 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { + o.setId("yudao03"); + o.setCreateTime(buildTime(2020, 1, 15)); + })); + // 准备参数 + FilePageReqVO reqVO = new FilePageReqVO(); + reqVO.setId("yudao"); + reqVO.setType("jp"); + reqVO.setBeginCreateTime(buildTime(2021, 1, 10)); + reqVO.setEndCreateTime(buildTime(2021, 1, 20)); + + // 调用 + PageResult pageResult = fileService.getFilePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + AssertUtils.assertPojoEquals(dbFile, pageResult.getList().get(0), "content"); + } + + @Test + public void testCreateFile_success() { + // 准备参数 + String path = randomString(); + byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); + + // 调用 + String url = fileService.createFile(path, content); + // 断言 + assertEquals(fileProperties.getBasePath() + path, url); + // 校验数据 + FileDO file = fileMapper.selectById(path); + assertEquals(path, file.getId()); + assertEquals("jpg", file.getType()); + assertArrayEquals(content, file.getContent()); + } + + @Test + public void testCreateFile_exists() { + // mock 数据 + FileDO dbFile = randomPojo(FileDO.class); + fileMapper.insert(dbFile); + // 准备参数 + String path = dbFile.getId(); // 模拟已存在 + byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); + + // 调用,并断言异常 + assertServiceException(() -> fileService.createFile(path, content), FILE_PATH_EXISTS); + } + + @Test + public void testDeleteFile_success() { + // mock 数据 + FileDO dbFile = randomPojo(FileDO.class); + fileMapper.insert(dbFile);// @Sql: 先插入出一条存在的数据 + // 准备参数 + String id = dbFile.getId(); + + // 调用 + fileService.deleteFile(id); + // 校验数据不存在了 + assertNull(fileMapper.selectById(id)); + } + + @Test + public void testDeleteFile_notExists() { + // 准备参数 + String id = randomString(); + + // 调用, 并断言异常 + assertServiceException(() -> fileService.deleteFile(id), FILE_NOT_EXISTS); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java similarity index 64% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java index 3946953fa5..27bda4965d 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job; +package cn.iocoder.yudao.module.infra.service.job; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -14,36 +14,30 @@ import java.util.List; import javax.annotation.Resource; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobLogDO; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobLogDO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job.InfJobLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobLogStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.impl.InfJobLogServiceImpl; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper; +import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -/** - * {@link InfJobLogServiceImpl} 的单元测试 - * - * @author neilz - */ -@Import(InfJobLogServiceImpl.class) -public class InfJobLogServiceTest extends BaseDbUnitTest { +@Import(JobLogServiceImpl.class) +public class JobLogServiceTest extends BaseDbUnitTest { @Resource - private InfJobLogServiceImpl jobLogService; + private JobLogServiceImpl jobLogService; @Resource - private InfJobLogMapper jobLogMapper; + private JobLogMapper jobLogMapper; @Test public void testCreateJobLog_success() { // 准备参数 - InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> { + JobLogDO reqVO = randomPojo(JobLogDO.class, o -> { o.setExecuteIndex(1); }); // 调用 @@ -51,40 +45,40 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { // 断言 assertNotNull(jobLogId); // 校验记录的属性是否正确 - InfJobLogDO job = jobLogMapper.selectById(jobLogId); - assertEquals(InfJobLogStatusEnum.RUNNING.getStatus(), job.getStatus()); + JobLogDO job = jobLogMapper.selectById(jobLogId); + assertEquals(JobLogStatusEnum.RUNNING.getStatus(), job.getStatus()); } @Test public void testUpdateJobLogResultAsync_success() { // 准备参数 - InfJobLogDO reqVO = randomPojo(InfJobLogDO.class, o -> { + JobLogDO reqVO = randomPojo(JobLogDO.class, o -> { o.setExecuteIndex(1); }); - InfJobLogDO log = InfJobLogDO.builder().jobId(reqVO.getJobId()).handlerName(reqVO.getHandlerName()).handlerParam(reqVO.getHandlerParam()).executeIndex(reqVO.getExecuteIndex()) - .beginTime(reqVO.getBeginTime()).status(InfJobLogStatusEnum.RUNNING.getStatus()).build(); + JobLogDO log = JobLogDO.builder().jobId(reqVO.getJobId()).handlerName(reqVO.getHandlerName()).handlerParam(reqVO.getHandlerParam()).executeIndex(reqVO.getExecuteIndex()) + .beginTime(reqVO.getBeginTime()).status(JobLogStatusEnum.RUNNING.getStatus()).build(); jobLogMapper.insert(log); // 调用 jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), true,reqVO.getResult()); // 校验记录的属性是否正确 - InfJobLogDO job = jobLogMapper.selectById(log.getId()); - assertEquals(InfJobLogStatusEnum.SUCCESS.getStatus(), job.getStatus()); + JobLogDO job = jobLogMapper.selectById(log.getId()); + assertEquals(JobLogStatusEnum.SUCCESS.getStatus(), job.getStatus()); // 调用 jobLogService.updateJobLogResultAsync(log.getId(), reqVO.getBeginTime(), reqVO.getDuration(), false,reqVO.getResult()); // 校验记录的属性是否正确 - InfJobLogDO job2 = jobLogMapper.selectById(log.getId()); - assertEquals(InfJobLogStatusEnum.FAILURE.getStatus(), job2.getStatus()); + JobLogDO job2 = jobLogMapper.selectById(log.getId()); + assertEquals(JobLogStatusEnum.FAILURE.getStatus(), job2.getStatus()); } @Test public void testGetJobLogListByIds_success() { // mock 数据 - InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { + JobLogDO dbJobLog = randomPojo(JobLogDO.class, o -> { o.setExecuteIndex(1); - o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围 + o.setStatus(randomEle(JobLogStatusEnum.values()).getStatus()); // 保证 status 的范围 }); - InfJobLogDO cloneJobLog = ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())); + JobLogDO cloneJobLog = ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())); jobLogMapper.insert(dbJobLog); // 测试 handlerName 不匹配 jobLogMapper.insert(cloneJobLog); @@ -93,7 +87,7 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { ids.add(dbJobLog.getId()); ids.add(cloneJobLog.getId()); // 调用 - List list = jobLogService.getJobLogList(ids); + List list = jobLogService.getJobLogList(ids); // 断言 assertEquals(2, list.size()); assertPojoEquals(dbJobLog, list.get(0)); @@ -102,10 +96,10 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { @Test public void testGetJobPage_success() { // mock 数据 - InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { + JobLogDO dbJobLog = randomPojo(JobLogDO.class, o -> { o.setExecuteIndex(1); o.setHandlerName("handlerName 单元测试"); - o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); + o.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); o.setBeginTime(buildTime(2021, 1, 8)); o.setEndTime(buildTime(2021, 1, 8)); }); @@ -119,16 +113,16 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { // 测试 endTime 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); // 测试 status 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus()))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus()))); // 准备参数 - InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO(); + JobLogPageReqVO reqVo = new JobLogPageReqVO(); reqVo.setJobId(dbJobLog.getJobId()); reqVo.setHandlerName("单元"); reqVo.setBeginTime(dbJobLog.getBeginTime()); reqVo.setEndTime(dbJobLog.getEndTime()); - reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); + reqVo.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); // 调用 - PageResult pageResult = jobLogService.getJobLogPage(reqVo); + PageResult pageResult = jobLogService.getJobLogPage(reqVo); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -138,10 +132,10 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { @Test public void testGetJobListForExport_success() { // mock 数据 - InfJobLogDO dbJobLog = randomPojo(InfJobLogDO.class, o -> { + JobLogDO dbJobLog = randomPojo(JobLogDO.class, o -> { o.setExecuteIndex(1); o.setHandlerName("handlerName 单元测试"); - o.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); + o.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); o.setBeginTime(buildTime(2021, 1, 8)); o.setEndTime(buildTime(2021, 1, 8)); }); @@ -155,16 +149,16 @@ public class InfJobLogServiceTest extends BaseDbUnitTest { // 测试 endTime 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); // 测试 status 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus()))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus()))); // 准备参数 - InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO(); + JobLogExportReqVO reqVo = new JobLogExportReqVO(); reqVo.setJobId(dbJobLog.getJobId()); reqVo.setHandlerName("单元"); reqVo.setBeginTime(dbJobLog.getBeginTime()); reqVo.setEndTime(dbJobLog.getEndTime()); - reqVo.setStatus(InfJobLogStatusEnum.SUCCESS.getStatus()); + reqVo.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); // 调用 - List list = jobLogService.getJobLogList(reqVo); + List list = jobLogService.getJobLogList(reqVo); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbJobLog, list.get(0)); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceTest.java similarity index 59% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceTest.java index 538d4340cc..cfbeb307bf 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobServiceTest.java @@ -1,12 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.job; +package cn.iocoder.yudao.module.infra.service.job; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_EQUALS; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_CHANGE_STATUS_INVALID; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_CRON_EXPRESSION_VALID; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_HANDLER_EXISTS; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_NOT_EXISTS; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.JOB_UPDATE_ONLY_NORMAL_STATUS; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; @@ -23,44 +18,38 @@ import java.util.List; import javax.annotation.Resource; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.job.JobConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.quartz.SchedulerException; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.job.vo.job.InfJobUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.convert.job.InfJobConvert; -import cn.iocoder.yudao.adminserver.modules.infra.dal.dataobject.job.InfJobDO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.job.InfJobMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.job.InfJobStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.job.impl.InfJobServiceImpl; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.job.vo.job.JobPageReqVO; +import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper; +import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -/** - * {@link InfJobServiceImpl} 的单元测试 - * - * @author neilz - */ -@Import(InfJobServiceImpl.class) -public class InfJobServiceTest extends BaseDbUnitTest { +@Import(JobServiceImpl.class) +public class JobServiceTest extends BaseDbUnitTest { @Resource - private InfJobServiceImpl jobService; + private JobServiceImpl jobService; @Resource - private InfJobMapper jobMapper; + private JobMapper jobMapper; @MockBean private SchedulerManager schedulerManager; @Test public void testCreateJob_cronExpressionValid() { // 准备参数。Cron 表达式为 String 类型,默认随机字符串。 - InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class); + JobCreateReqVO reqVO = randomPojo(JobCreateReqVO.class); // 调用,并断言异常 assertServiceException(() -> jobService.createJob(reqVO), JOB_CRON_EXPRESSION_VALID); } @@ -68,7 +57,7 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testCreateJob_jobHandlerExists() throws SchedulerException { // 准备参数 指定 Cron 表达式 - InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobCreateReqVO reqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); // 调用 jobService.createJob(reqVO); // 调用,并断言异常 @@ -78,15 +67,15 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testCreateJob_success() throws SchedulerException { // 准备参数 指定 Cron 表达式 - InfJobCreateReqVO reqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobCreateReqVO reqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); // 调用 Long jobId = jobService.createJob(reqVO); // 断言 assertNotNull(jobId); // 校验记录的属性是否正确 - InfJobDO job = jobMapper.selectById(jobId); + JobDO job = jobMapper.selectById(jobId); assertPojoEquals(reqVO, job); - assertEquals(InfJobStatusEnum.NORMAL.getStatus(), job.getStatus()); + assertEquals(JobStatusEnum.NORMAL.getStatus(), job.getStatus()); // 校验调用 verify(schedulerManager, times(1)).addJob(eq(job.getId()), eq(job.getHandlerName()), eq(job.getHandlerParam()), eq(job.getCronExpression()), eq(reqVO.getRetryCount()), eq(reqVO.getRetryInterval())); @@ -95,7 +84,7 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJob_jobNotExists(){ // 准备参数 - InfJobUpdateReqVO reqVO = randomPojo(InfJobUpdateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobUpdateReqVO reqVO = randomPojo(JobUpdateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); // 调用,并断言异常 assertServiceException(() -> jobService.updateJob(reqVO), JOB_NOT_EXISTS); } @@ -103,13 +92,13 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJob_onlyNormalStatus(){ // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.INIT.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.INIT.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 准备参数 - InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> { + JobUpdateReqVO updateReqVO = randomPojo(JobUpdateReqVO.class, o -> { o.setId(job.getId()); o.setName(createReqVO.getName()); o.setCronExpression(createReqVO.getCronExpression()); @@ -121,13 +110,13 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJob_success() throws SchedulerException { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.NORMAL.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 准备参数 - InfJobUpdateReqVO updateReqVO = randomPojo(InfJobUpdateReqVO.class, o -> { + JobUpdateReqVO updateReqVO = randomPojo(JobUpdateReqVO.class, o -> { o.setId(job.getId()); o.setName(createReqVO.getName()); o.setCronExpression(createReqVO.getCronExpression()); @@ -135,7 +124,7 @@ public class InfJobServiceTest extends BaseDbUnitTest { // 调用 jobService.updateJob(updateReqVO); // 校验记录的属性是否正确 - InfJobDO updateJob = jobMapper.selectById(updateReqVO.getId()); + JobDO updateJob = jobMapper.selectById(updateReqVO.getId()); assertPojoEquals(updateReqVO, updateJob); // 校验调用 verify(schedulerManager, times(1)).updateJob(eq(job.getHandlerName()), eq(updateReqVO.getHandlerParam()), eq(updateReqVO.getCronExpression()), @@ -145,15 +134,15 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJobStatus_changeStatusInvalid() { // 调用,并断言异常 - assertServiceException(() -> jobService.updateJobStatus(1l, InfJobStatusEnum.INIT.getStatus()), JOB_CHANGE_STATUS_INVALID); + assertServiceException(() -> jobService.updateJobStatus(1L, JobStatusEnum.INIT.getStatus()), JOB_CHANGE_STATUS_INVALID); } @Test public void testUpdateJobStatus_changeStatusEquals() { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.NORMAL.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 调用,并断言异常 @@ -163,16 +152,16 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJobStatus_NormalToStop_success() throws SchedulerException { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.NORMAL.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 调用 - jobService.updateJobStatus(job.getId(), InfJobStatusEnum.STOP.getStatus()); + jobService.updateJobStatus(job.getId(), JobStatusEnum.STOP.getStatus()); // 校验记录的属性是否正确 - InfJobDO updateJob = jobMapper.selectById(job.getId()); - assertEquals(InfJobStatusEnum.STOP.getStatus(), updateJob.getStatus()); + JobDO updateJob = jobMapper.selectById(job.getId()); + assertEquals(JobStatusEnum.STOP.getStatus(), updateJob.getStatus()); // 校验调用 verify(schedulerManager, times(1)).pauseJob(eq(job.getHandlerName())); } @@ -180,16 +169,16 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testUpdateJobStatus_StopToNormal_success() throws SchedulerException { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.STOP.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.STOP.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 调用 - jobService.updateJobStatus(job.getId(), InfJobStatusEnum.NORMAL.getStatus()); + jobService.updateJobStatus(job.getId(), JobStatusEnum.NORMAL.getStatus()); // 校验记录的属性是否正确 - InfJobDO updateJob = jobMapper.selectById(job.getId()); - assertEquals(InfJobStatusEnum.NORMAL.getStatus(), updateJob.getStatus()); + JobDO updateJob = jobMapper.selectById(job.getId()); + assertEquals(JobStatusEnum.NORMAL.getStatus(), updateJob.getStatus()); // 校验调用 verify(schedulerManager, times(1)).resumeJob(eq(job.getHandlerName())); } @@ -197,9 +186,9 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testTriggerJob_success() throws SchedulerException { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.NORMAL.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 调用 @@ -211,9 +200,9 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testDeleteJob_success() throws SchedulerException { // mock 数据 - InfJobCreateReqVO createReqVO = randomPojo(InfJobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); - InfJobDO job = InfJobConvert.INSTANCE.convert(createReqVO); - job.setStatus(InfJobStatusEnum.NORMAL.getStatus()); + JobCreateReqVO createReqVO = randomPojo(JobCreateReqVO.class, o -> o.setCronExpression("0 0/1 * * * ? *")); + JobDO job = JobConvert.INSTANCE.convert(createReqVO); + job.setStatus(JobStatusEnum.NORMAL.getStatus()); fillJobMonitorTimeoutEmpty(job); jobMapper.insert(job); // 调用 UPDATE inf_job SET deleted=1 WHERE id=? AND deleted=0 @@ -227,19 +216,19 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testGetJobListByIds_success() { // mock 数据 - InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { - o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围 + JobDO dbJob = randomPojo(JobDO.class, o -> { + o.setStatus(randomEle(JobStatusEnum.values()).getStatus()); // 保证 status 的范围 }); - InfJobDO cloneJob = ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())); + JobDO cloneJob = ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())); jobMapper.insert(dbJob); // 测试 handlerName 不匹配 jobMapper.insert(cloneJob); // 准备参数 - ArrayList ids = new ArrayList<>(); + ArrayList ids = new ArrayList<>(); ids.add(dbJob.getId()); ids.add(cloneJob.getId()); // 调用 - List list = jobService.getJobList(ids); + List list = jobService.getJobList(ids); // 断言 assertEquals(2, list.size()); assertPojoEquals(dbJob, list.get(0)); @@ -248,25 +237,25 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testGetJobPage_success() { // mock 数据 - InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { + JobDO dbJob = randomPojo(JobDO.class, o -> { o.setName("定时任务测试"); o.setHandlerName("handlerName 单元测试"); - o.setStatus(InfJobStatusEnum.INIT.getStatus()); + o.setStatus(JobStatusEnum.INIT.getStatus()); }); jobMapper.insert(dbJob); // 测试 name 不匹配 jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆"))); // 测试 status 不匹配 - jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus()))); + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(JobStatusEnum.NORMAL.getStatus()))); // 测试 handlerName 不匹配 jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString()))); // 准备参数 - InfJobPageReqVO reqVo = new InfJobPageReqVO(); + JobPageReqVO reqVo = new JobPageReqVO(); reqVo.setName("定时"); - reqVo.setStatus(InfJobStatusEnum.INIT.getStatus()); + reqVo.setStatus(JobStatusEnum.INIT.getStatus()); reqVo.setHandlerName("单元"); // 调用 - PageResult pageResult = jobService.getJobPage(reqVo); + PageResult pageResult = jobService.getJobPage(reqVo); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -276,31 +265,31 @@ public class InfJobServiceTest extends BaseDbUnitTest { @Test public void testGetJobListForExport_success() { // mock 数据 - InfJobDO dbJob = randomPojo(InfJobDO.class, o -> { + JobDO dbJob = randomPojo(JobDO.class, o -> { o.setName("定时任务测试"); o.setHandlerName("handlerName 单元测试"); - o.setStatus(InfJobStatusEnum.INIT.getStatus()); + o.setStatus(JobStatusEnum.INIT.getStatus()); }); jobMapper.insert(dbJob); // 测试 name 不匹配 jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆"))); // 测试 status 不匹配 - jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus()))); + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(JobStatusEnum.NORMAL.getStatus()))); // 测试 handlerName 不匹配 jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString()))); // 准备参数 - InfJobExportReqVO reqVo = new InfJobExportReqVO(); + JobExportReqVO reqVo = new JobExportReqVO(); reqVo.setName("定时"); - reqVo.setStatus(InfJobStatusEnum.INIT.getStatus()); + reqVo.setStatus(JobStatusEnum.INIT.getStatus()); reqVo.setHandlerName("单元"); // 调用 - List list = jobService.getJobList(reqVo); + List list = jobService.getJobList(reqVo); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbJob, list.get(0)); } - private static void fillJobMonitorTimeoutEmpty(InfJobDO job) { + private static void fillJobMonitorTimeoutEmpty(JobDO job) { if (job.getMonitorTimeout() == null) { job.setMonitorTimeout(0); } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java similarity index 52% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java index 0c401dd2f0..0b1b3d9327 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java @@ -1,16 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger; +package cn.iocoder.yudao.module.infra.service.logger; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiAccessLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl.InfApiAccessLogServiceImpl; -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; +import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -18,22 +19,19 @@ import javax.annotation.Resource; import java.util.Date; import java.util.List; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -/** - * {@link InfApiAccessLogServiceImpl} 单元测试 - */ -@Import(InfApiAccessLogServiceImpl.class) -public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { +@Import(ApiAccessLogServiceImpl.class) +public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { @Resource - private InfApiAccessLogService infApiAccessLogServiceImpl; + private ApiAccessLogService apiAccessLogService; @Resource - private InfApiAccessLogMapper infApiAccessLogMapper; + private ApiAccessLogMapper apiAccessLogMapper; @Test public void testGetApiAccessLogPage() { @@ -46,7 +44,7 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { int duration = 1000; int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); - InfApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(InfApiAccessLogDO.class, dto -> { + ApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(ApiAccessLogDO.class, dto -> { dto.setUserId(userId); dto.setUserType(userType); dto.setApplicationName(applicationName); @@ -55,26 +53,26 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { dto.setDuration(duration); dto.setResultCode(resultCode); }); - infApiAccessLogMapper.insert(infApiAccessLogDO); + apiAccessLogMapper.insert(infApiAccessLogDO); // 下面几个都是不匹配的数据 // userId 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); // userType - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); // applicationName 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); // requestUrl 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); // duration 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); // resultCode 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); // 构造调用参数 - InfApiAccessLogPageReqVO reqVO = new InfApiAccessLogPageReqVO(); + ApiAccessLogPageReqVO reqVO = new ApiAccessLogPageReqVO(); reqVO.setUserId(userId); reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); @@ -85,7 +83,7 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { reqVO.setResultCode(resultCode); // 调用service方法 - PageResult pageResult = infApiAccessLogServiceImpl.getApiAccessLogPage(reqVO); + PageResult pageResult = apiAccessLogService.getApiAccessLogPage(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, pageResult.getTotal()); @@ -104,7 +102,7 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { int duration = 1000; int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); - InfApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(InfApiAccessLogDO.class, dto -> { + ApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(ApiAccessLogDO.class, dto -> { dto.setUserId(userId); dto.setUserType(userType); dto.setApplicationName(applicationName); @@ -113,26 +111,26 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { dto.setDuration(duration); dto.setResultCode(resultCode); }); - infApiAccessLogMapper.insert(infApiAccessLogDO); + apiAccessLogMapper.insert(infApiAccessLogDO); // 下面几个都是不匹配的数据 // userId 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); // userType - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); // applicationName 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); // requestUrl 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); // duration 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); // resultCode 不同的 - infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); // 构造调用参数 - InfApiAccessLogExportReqVO reqVO = new InfApiAccessLogExportReqVO(); + ApiAccessLogExportReqVO reqVO = new ApiAccessLogExportReqVO(); reqVO.setUserId(userId); reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); @@ -143,11 +141,26 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { reqVO.setResultCode(resultCode); // 调用service方法 - List list = infApiAccessLogServiceImpl.getApiAccessLogList(reqVO); + List list = apiAccessLogService.getApiAccessLogList(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, list.size()); assertPojoEquals(infApiAccessLogDO, list.get(0)); } + @Test + public void testCreateApiAccessLogAsync() { + // 准备参数 + ApiAccessLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiAccessLogCreateReqDTO.class, + dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue())); + + // 调用 + apiAccessLogService.createApiAccessLogAsync(createDTO); + // 断言 + ApiAccessLogDO infApiAccessLogDO = apiAccessLogMapper.selectOne(null); + assertNotNull(infApiAccessLogDO); + assertPojoEquals(createDTO, infApiAccessLogDO); + } + + } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java similarity index 62% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java index f7c9eb3367..9b24d59875 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java @@ -1,16 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.infra.service.logger; +package cn.iocoder.yudao.module.infra.service.logger; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; -import cn.iocoder.yudao.adminserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; -import cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl; -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; +import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper; +import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; +import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -18,24 +20,22 @@ import javax.annotation.Resource; import java.util.Date; import java.util.List; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_LOG_PROCESSED; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; -/** - * {@link InfApiErrorLogServiceImpl} 单元测试 - */ -@Import(InfApiErrorLogServiceImpl.class) -public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { +@Import(ApiErrorLogServiceImpl.class) +public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { @Resource - private InfApiErrorLogService infApiErrorLogServiceImpl; + private ApiErrorLogServiceImpl apiErrorLogService; @Resource - private InfApiErrorLogMapper infApiErrorLogMapper; + private ApiErrorLogMapper infApiErrorLogMapper; @Test public void testGetApiErrorLogPage() { @@ -45,9 +45,9 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { String applicationName = "yudao-test"; String requestUrl = "foo"; Date beginTime = buildTime(2021, 3, 13); - int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus(); + int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus(); - InfApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { logDO.setUserId(userId); logDO.setUserType(userType); logDO.setApplicationName(applicationName); @@ -69,10 +69,10 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { // 构造一个早期时间 2021-02-06 00:00:00 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); // progressStatus 不同的 - infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()))); + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus()))); // 构造调用参数 - InfApiErrorLogPageReqVO reqVO = new InfApiErrorLogPageReqVO(); + ApiErrorLogPageReqVO reqVO = new ApiErrorLogPageReqVO(); reqVO.setUserId(userId); reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); @@ -82,7 +82,7 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { reqVO.setProcessStatus(progressStatus); // 调用service方法 - PageResult pageResult = infApiErrorLogServiceImpl.getApiErrorLogPage(reqVO); + PageResult pageResult = apiErrorLogService.getApiErrorLogPage(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, pageResult.getTotal()); @@ -98,9 +98,9 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { String applicationName = "yudao-test"; String requestUrl = "foo"; Date beginTime = buildTime(2021, 3, 13); - int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus(); + int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus(); - InfApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { logDO.setUserId(userId); logDO.setUserType(userType); logDO.setApplicationName(applicationName); @@ -122,10 +122,10 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { // 构造一个早期时间 2021-02-06 00:00:00 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); // progressStatus 不同的 - infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()))); + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus()))); // 构造调用参数 - InfApiErrorLogExportReqVO reqVO = new InfApiErrorLogExportReqVO(); + ApiErrorLogExportReqVO reqVO = new ApiErrorLogExportReqVO(); reqVO.setUserId(userId); reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); @@ -135,7 +135,7 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { reqVO.setProcessStatus(progressStatus); // 调用service方法 - List list = infApiErrorLogServiceImpl.getApiErrorLogList(reqVO); + List list = apiErrorLogService.getApiErrorLogList(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, list.size()); @@ -143,22 +143,23 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { } + // TODO 芋艿:单元测试,可以拆小一点 @Test public void testUpdateApiErrorLogProcess() { // 先构造两条数据,第一条用于抛出异常,第二条用于正常的执行update操作 Long processUserId = 2233L; - InfApiErrorLogDO first = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + ApiErrorLogDO first = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { logDO.setProcessUserId(processUserId); logDO.setUserType(UserTypeEnum.ADMIN.getValue()); - logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()); + logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus()); }); infApiErrorLogMapper.insert(first); - InfApiErrorLogDO second = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + ApiErrorLogDO second = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { logDO.setProcessUserId(1122L); logDO.setUserType(UserTypeEnum.ADMIN.getValue()); - logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); + logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); }); infApiErrorLogMapper.insert(second); @@ -166,17 +167,31 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { Long secondId = second.getId(); // 执行正常的 update 操作 - infApiErrorLogServiceImpl.updateApiErrorLogProcess(secondId, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId); - InfApiErrorLogDO secondSelect = infApiErrorLogMapper.selectOne("id", secondId); + apiErrorLogService.updateApiErrorLogProcess(secondId, ApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId); + ApiErrorLogDO secondSelect = infApiErrorLogMapper.selectOne("id", secondId); // id 为 0 查询不到,应该抛出异常 API_ERROR_LOG_NOT_FOUND - assertServiceException(() -> infApiErrorLogServiceImpl.updateApiErrorLogProcess(0L, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_NOT_FOUND); + assertServiceException(() -> apiErrorLogService.updateApiErrorLogProcess(0L, ApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_NOT_FOUND); // id 为 first 的 progressStatus 为 DONE ,应该抛出 API_ERROR_LOG_PROCESSED - assertServiceException(() -> infApiErrorLogServiceImpl.updateApiErrorLogProcess(firstId, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_PROCESSED); + assertServiceException(() -> apiErrorLogService.updateApiErrorLogProcess(firstId, ApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_PROCESSED); // 验证 progressStatus 是否修改成功 - assertEquals(InfApiErrorLogProcessStatusEnum.DONE.getStatus(), secondSelect.getProcessStatus()); + Assertions.assertEquals(ApiErrorLogProcessStatusEnum.DONE.getStatus(), secondSelect.getProcessStatus()); // 验证 progressUserId 是否修改成功 - assertEquals(processUserId, secondSelect.getProcessUserId()); + Assertions.assertEquals(processUserId, secondSelect.getProcessUserId()); + } + + @Test + public void testCreateApiErrorLogAsync() { + // 准备参数 + ApiErrorLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiErrorLogCreateReqDTO.class, + dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue())); + + // 调用 + apiErrorLogService.createApiErrorLogAsync(createDTO); + // 断言 + ApiErrorLogDO infApiErrorLogDO = infApiErrorLogMapper.selectOne(null); + assertNotNull(infApiErrorLogDO); + assertPojoEquals(createDTO, infApiErrorLogDO); } } diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisUnitTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbAndRedisUnitTest.java similarity index 92% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisUnitTest.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbAndRedisUnitTest.java index 8b9177cf51..6ab6ad4adf 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisUnitTest.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbAndRedisUnitTest.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.infra.test; -import cn.iocoder.yudao.coreservice.config.RedisTestConfiguration; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; @@ -24,6 +23,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbAndRedisUnitTest { diff --git a/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbUnitTest.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbUnitTest.java new file mode 100644 index 0000000000..812dd12082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/BaseDbUnitTest.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.infra.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +/** + * 依赖内存 DB 的单元测试 + * + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB +public class BaseDbUnitTest { + + @Import({ + // DB 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类 + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + }) + public static class Application { + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/QuartzTestConfiguration.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/QuartzTestConfiguration.java similarity index 87% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/QuartzTestConfiguration.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/QuartzTestConfiguration.java index 0bbce19085..2dd12f1a60 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/QuartzTestConfiguration.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/QuartzTestConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.config; +package cn.iocoder.yudao.module.infra.test; import org.mockito.Mockito; import org.quartz.Scheduler; diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/config/RedisTestConfiguration.java b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/RedisTestConfiguration.java similarity index 96% rename from yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/config/RedisTestConfiguration.java rename to yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/RedisTestConfiguration.java index 7164efd874..aa2ea6f101 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/config/RedisTestConfiguration.java +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/java/cn/iocoder/yudao/module/infra/test/RedisTestConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.config; +package cn.iocoder.yudao.module.infra.test; import com.github.fppt.jedismock.RedisServer; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; diff --git a/yudao-user-server/src/test/resources/application-unit-test.yaml b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/application-unit-test.yaml similarity index 92% rename from yudao-user-server/src/test/resources/application-unit-test.yaml rename to yudao-module-infra/yudao-module-infra-impl/src/test/resources/application-unit-test.yaml index d306a7af43..9f36ec4ac9 100644 --- a/yudao-user-server/src/test/resources/application-unit-test.yaml +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/application-unit-test.yaml @@ -13,7 +13,6 @@ spring: driver-class-name: org.h2.Driver username: sa password: - schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具 druid: async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 initial-size: 1 # 单元测试,配置为 1,提升启动速度 @@ -42,3 +41,6 @@ mybatis: --- #################### 芋道相关配置 #################### # 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-core-service/src/test/resources/file/erweima.jpg b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/file/erweima.jpg similarity index 100% rename from yudao-core-service/src/test/resources/file/erweima.jpg rename to yudao-module-infra/yudao-module-infra-impl/src/test/resources/file/erweima.jpg diff --git a/yudao-module-infra/yudao-module-infra-impl/src/test/resources/logback.xml b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/logback.xml new file mode 100644 index 0000000000..daf756bff0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/clean.sql b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..b416d4d81a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/clean.sql @@ -0,0 +1,9 @@ +DELETE FROM "infra_config"; +DELETE FROM "infra_file"; +DELETE FROM "infra_job"; +DELETE FROM "infra_job_log"; +DELETE FROM "infra_api_access_log"; +DELETE FROM "infra_api_error_log"; +DELETE FROM "infra_api_access_log"; +DELETE FROM "infra_file"; +DELETE FROM "infra_api_error_log"; diff --git a/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/create_tables.sql b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000000..c203865f21 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-impl/src/test/resources/sql/create_tables.sql @@ -0,0 +1,137 @@ + +CREATE TABLE IF NOT EXISTS "infra_config" ( + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "group" varchar(50) NOT NULL, + "type" tinyint NOT NULL, + "name" varchar(100) NOT NULL DEFAULT '', + "key" varchar(100) NOT NULL DEFAULT '', + "value" varchar(500) NOT NULL DEFAULT '', + "sensitive" bit NOT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '参数配置表'; + +CREATE TABLE IF NOT EXISTS "infra_file" ( + "id" varchar(188) NOT NULL, + "type" varchar(63) DEFAULT NULL, + "content" blob NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") +) COMMENT '文件表'; + +CREATE TABLE IF NOT EXISTS "infra_job" ( + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '任务编号', + "name" varchar(32) NOT NULL COMMENT '任务名称', + "status" tinyint(4) NOT NULL COMMENT '任务状态', + "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', + "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', + "cron_expression" varchar(32) NOT NULL COMMENT 'CRON 表达式', + "retry_count" int(11) NOT NULL DEFAULT '0' COMMENT '重试次数', + "retry_interval" int(11) NOT NULL DEFAULT '0' COMMENT '重试间隔', + "monitor_timeout" int(11) NOT NULL DEFAULT '0' COMMENT '监控超时时间', + "creator" varchar(64) DEFAULT '' COMMENT '创建者', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + "updater" varchar(64) DEFAULT '' COMMENT '更新者', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + "deleted" bit NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY ("id") +) COMMENT='定时任务表'; + +CREATE TABLE IF NOT EXISTS "infra_job_log" ( + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '日志编号', + "job_id" bigint(20) NOT NULL COMMENT '任务编号', + "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', + "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', + "execute_index" tinyint(4) NOT NULL DEFAULT '1' COMMENT '第几次执行', + "begin_time" datetime NOT NULL COMMENT '开始执行时间', + "end_time" datetime DEFAULT NULL COMMENT '结束执行时间', + "duration" int(11) DEFAULT NULL COMMENT '执行时长', + "status" tinyint(4) NOT NULL COMMENT '任务状态', + "result" varchar(4000) DEFAULT '' COMMENT '结果数据', + "creator" varchar(64) DEFAULT '' COMMENT '创建者', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + "updater" varchar(64) DEFAULT '' COMMENT '更新者', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + "deleted" bit(1) NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY ("id") +)COMMENT='定时任务日志表'; + +CREATE TABLE IF NOT EXISTS "inf_file" ( + "id" varchar(188) NOT NULL, + "type" varchar(63) DEFAULT NULL, + "content" blob NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', + PRIMARY KEY ("id") + ) COMMENT '文件表'; + +CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( + "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, + "trace_id" varchar(64) not null default '', + "user_id" bigint not null default '0', + "user_type" tinyint not null default '0', + "application_name" varchar(50) not null, + "request_method" varchar(16) not null default '', + "request_url" varchar(255) not null default '', + "request_params" varchar(8000) not null default '', + "user_ip" varchar(50) not null, + "user_agent" varchar(512) not null, + "begin_time" timestamp not null, + "end_time" timestamp not null, + "duration" integer not null, + "result_code" integer not null default '0', + "result_msg" varchar(512) default '', + "creator" varchar(64) default '', + "create_time" timestamp not null default current_timestamp, + "updater" varchar(64) default '', + "update_time" timestamp not null default current_timestamp, + "deleted" bit not null default false, + "tenant_id" bigint not null default '0', + primary key ("id") + ) COMMENT 'API 访问日志表'; + +CREATE TABLE IF NOT EXISTS "infra_api_error_log" ( + "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, + "trace_id" varchar(64) not null, + "user_id" bigint not null default '0', + "user_type" tinyint not null default '0', + "application_name" varchar(50) not null, + "request_method" varchar(16) not null, + "request_url" varchar(255) not null, + "request_params" varchar(8000) not null, + "user_ip" varchar(50) not null, + "user_agent" varchar(512) not null, + "exception_time" timestamp not null, + "exception_name" varchar(128) not null default '', + "exception_message" clob not null, + "exception_root_cause_message" clob not null, + "exception_stack_trace" clob not null, + "exception_class_name" varchar(512) not null, + "exception_file_name" varchar(512) not null, + "exception_method_name" varchar(512) not null, + "exception_line_number" integer not null, + "process_status" tinyint not null, + "process_time" timestamp default null, + "process_user_id" bigint default '0', + "creator" varchar(64) default '', + "create_time" timestamp not null default current_timestamp, + "updater" varchar(64) default '', + "update_time" timestamp not null default current_timestamp, + "deleted" bit not null default false, + "tenant_id" bigint not null default '0', + primary key ("id") +) COMMENT '系统异常日志'; diff --git a/yudao-module-member/pom.xml b/yudao-module-member/pom.xml new file mode 100644 index 0000000000..cf150725a2 --- /dev/null +++ b/yudao-module-member/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-module-member-api + yudao-module-member-impl + + yudao-module-member + pom + + ${artifactId} + + member 模块,我们放会员业务。 + 例如说:会员中心等等 + + + diff --git a/yudao-module-member/yudao-module-member-api/pom.xml b/yudao-module-member/yudao-module-member-api/pom.xml new file mode 100644 index 0000000000..914d910825 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/pom.xml @@ -0,0 +1,26 @@ + + + + cn.iocoder.boot + yudao-module-member + ${revision} + + 4.0.0 + yudao-module-member-api + jar + + ${artifactId} + + member 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java new file mode 100644 index 0000000000..56cd9857f8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java @@ -0,0 +1,4 @@ +/** + * member API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.member.api; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java new file mode 100644 index 0000000000..c6c37f9352 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.member.api.user; + +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; + +/** + * 会员用户的 API 接口 + * + * @author 芋道源码 + */ +public interface MemberUserApi { + + /** + * 获得会员用户信息 + * + * @param id 用户编号 + * @return 用户信息 + */ + UserRespDTO getUser(Long id); + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java new file mode 100644 index 0000000000..e7a5aba9a0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.member.api.user.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +/** + * 用户信息 Response DTO + * + * @author 芋道源码 + */ +@Data +public class UserRespDTO { + + /** + * 用户ID + */ + private Long id; + /** + * 用户昵称 + */ + private String nickname; + /** + * 帐号状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + /** + * 手机 + */ + private String mobile; + +} diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java new file mode 100644 index 0000000000..260a0d12f7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.member.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * Member 错误码枚举类 + * + * member 系统,使用 1-004-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 用户相关 1004001000============ + ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); + ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1004001001, "密码校验失败"); + + // ========== 文件相关 1004002000 =========== + // TODO 芋艿:可以删除 + ErrorCode FILE_IS_EMPTY = new ErrorCode(1004002000, "文件为空"); + + // ========== AUTH 模块 1004003000 ========== + ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); + ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1004003001, "登录失败,账号被禁用"); + ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1004003002, "登录失败"); // 登录失败的兜底,未知原因 + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期"); + ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定"); + +} diff --git a/yudao-module-member/yudao-module-member-impl/pom.xml b/yudao-module-member/yudao-module-member-impl/pom.xml new file mode 100644 index 0000000000..6029a8b2b7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/pom.xml @@ -0,0 +1,84 @@ + + + + cn.iocoder.boot + yudao-module-member + ${revision} + + 4.0.0 + yudao-module-member-impl + jar + + ${artifactId} + + member 模块,我们放会员业务。 + 例如说:会员中心等等 + + + + + cn.iocoder.boot + yudao-module-member-api + ${revision} + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-infra-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-weixin + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mq + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + + diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java new file mode 100644 index 0000000000..5f97979b88 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.api; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java new file mode 100644 index 0000000000..35e7b51cec --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.member.api.user; + +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.convert.user.UserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 会员用户的 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MemberUserApiImpl implements MemberUserApi { + + @Resource + private MemberUserService userService; + + @Override + public UserRespDTO getUser(Long id) { + MemberUserDO user = userService.getUser(id); + return UserConvert.INSTANCE.convert2(user); + } + +} diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java new file mode 100644 index 0000000000..652bbb6f19 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.controller.admin.address; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/package-info.java new file mode 100644 index 0000000000..23b3c23c4f --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.controller.admin.user; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/package-info.java new file mode 100644 index 0000000000..c8c1021861 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.controller.app.address; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http similarity index 67% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http index c9cadedccd..d609e8f0c2 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http @@ -1,6 +1,7 @@ ### 请求 /login 接口 => 成功 -POST {{userServerUrl}}/login +POST {{appApi}}/member/login Content-Type: application/json +tenant-id: {{appTenentId}} { "mobile": "15601691300", @@ -8,8 +9,9 @@ Content-Type: application/json } ### 请求 /send-sms-code 接口 => 成功 -POST {{userServerUrl}}/send-sms-code +POST {{appApi}}/member/send-sms-code Content-Type: application/json +tenant-id: {{appTenentId}} { "mobile": "15601691399", @@ -17,8 +19,9 @@ Content-Type: application/json } ### 请求 /sms-login 接口 => 成功 -POST {{userServerUrl}}/sms-login +POST {{appApi}}/member/sms-login Content-Type: application/json +tenant-id: {{appTenentId}} { "mobile": "15601691301", @@ -26,6 +29,7 @@ Content-Type: application/json } ### 请求 /logout 接口 => 成功 -POST {{userServerUrl}}/logout +POST {{appApi}}/member/logout Content-Type: application/json Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66 +tenant-id: {{appTenentId}} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java similarity index 58% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java index 2c0d49307d..d55d44dd79 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java @@ -1,12 +1,10 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth; +package cn.iocoder.yudao.module.member.controller.app.auth; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*; -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.service.auth.MemberAuthService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -23,54 +21,47 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Api(tags = "认证") +@Api(tags = "用户 APP - 认证") @RestController -@RequestMapping("/") +@RequestMapping("/member/") @Validated @Slf4j -public class SysAuthController { +public class AppAuthController { @Resource - private SysAuthService authService; - @Resource - private SysSmsCodeService smsCodeService; - @Resource - private SysSocialCoreService socialService; + private MemberAuthService authService; @PostMapping("/login") @ApiOperation("使用手机 + 密码登录") - public CommonResult login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult login(@RequestBody @Valid AppAuthLoginReqVO reqVO) { String token = authService.login(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AppAuthLoginRespVO.builder().token(token).build()); } @PostMapping("/sms-login") @ApiOperation("使用手机 + 验证码登录") - public CommonResult smsLogin(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) { + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) { String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AppAuthLoginRespVO.builder().token(token).build()); } @PostMapping("/send-sms-code") @ApiOperation(value = "发送手机验证码") - public CommonResult sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) { - smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP()); - return success(true); - } - - @GetMapping("/send-sms-code-login") - @ApiOperation(value = "向已登录用户发送验证码",notes = "修改手机时验证原手机号使用") - public CommonResult sendSmsCodeLogin() { - smsCodeService.sendSmsCodeLogin(getLoginUserId()); + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult sendSmsCode(@RequestBody @Valid AppAuthSendSmsReqVO reqVO) { + authService.sendSmsCode(getLoginUserId(), reqVO); return success(true); } @PostMapping("/reset-password") @ApiOperation(value = "重置密码", notes = "用户忘记密码时使用") @PreAuthenticated - public CommonResult resetPassword(@RequestBody @Valid MbrAuthResetPasswordReqVO reqVO) { + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult resetPassword(@RequestBody @Valid AppAuthResetPasswordReqVO reqVO) { authService.resetPassword(reqVO); return success(true); } @@ -78,12 +69,11 @@ public class SysAuthController { @PostMapping("/update-password") @ApiOperation(value = "修改用户密码",notes = "用户修改密码时使用") @PreAuthenticated - public CommonResult updatePassword(@RequestBody @Valid MbrAuthUpdatePasswordReqVO reqVO) { + public CommonResult updatePassword(@RequestBody @Valid AppAuthUpdatePasswordReqVO reqVO) { authService.updatePassword(getLoginUserId(), reqVO); return success(true); } - // ========== 社交登录相关 ========== @GetMapping("/social-auth-redirect") @@ -94,36 +84,37 @@ public class SysAuthController { }) public CommonResult socialAuthRedirect(@RequestParam("type") Integer type, @RequestParam("redirectUri") String redirectUri) { - return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri)); + return CommonResult.success(authService.getSocialAuthorizeUrl(type, redirectUri)); } - @PostMapping("/social-login") - @ApiOperation("社交登录,使用 code 授权码") - public CommonResult socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) { + @ApiOperation(value = "社交登录,使用 code 授权码", notes = "适合未登录的用户,但是社交账号已绑定用户") + public CommonResult socialLogin(@RequestBody @Valid AppAuthSocialLoginReqVO reqVO) { String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent()); - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AppAuthLoginRespVO.builder().token(token).build()); } - @PostMapping("/social-login2") - @ApiOperation("社交登录,使用 手机号 + 手机验证码") - public CommonResult socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { + @ApiOperation(value = "社交登录,使用 手机号 + 手机验证码", notes = "适合未登录的用户,进行登录 + 绑定") + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult socialLogin2(@RequestBody @Valid AppAuthSocialLogin2ReqVO reqVO) { String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AppAuthLoginRespVO.builder().token(token).build()); } @PostMapping("/social-bind") - @ApiOperation("社交绑定,使用 code 授权码") - public CommonResult socialBind(@RequestBody @Valid MbrAuthSocialBindReqVO reqVO) { + @ApiOperation(value = "社交绑定,使用 code 授权码", notes = "使用在用户已经登录的情况下") + @PreAuthenticated + public CommonResult socialBind(@RequestBody @Valid AppAuthSocialBindReqVO reqVO) { authService.socialBind(getLoginUserId(), reqVO); return CommonResult.success(true); } @DeleteMapping("/social-unbind") @ApiOperation("取消社交绑定") - public CommonResult socialUnbind(@RequestBody MbrAuthSocialUnbindReqVO reqVO) { - socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.MEMBER); + @PreAuthenticated + public CommonResult socialUnbind(@RequestBody AppAuthSocialUnbindReqVO reqVO) { + authService.unbindSocialUser(getLoginUserId(), reqVO); return CommonResult.success(true); } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthCheckCodeReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java similarity index 78% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthCheckCodeReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java index 89f1f501e5..dd050147e4 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthCheckCodeReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -15,12 +15,13 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; -@ApiModel("校验验证码 Request VO") +// TODO 芋艿:code review 相关逻辑 +@ApiModel("用户 APP - 校验验证码 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthCheckCodeReqVO { +public class AppAuthCheckCodeReqVO { @ApiModelProperty(value = "手机号", example = "15601691234") @NotBlank(message = "手机号不能为空") @@ -33,8 +34,9 @@ public class SysAuthCheckCodeReqVO { @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") private String code; - @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举") + @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 SmsSceneEnum 枚举") @NotNull(message = "发送场景不能为空") - @InEnum(SysSmsSceneEnum.class) + @InEnum(SmsSceneEnum.class) private Integer scene; + } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java similarity index 83% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java index 1d51f80012..1055e979b4 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import io.swagger.annotations.ApiModel; @@ -11,12 +11,12 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; -@ApiModel("手机 + 密码登录 Request VO") +@ApiModel("用户 APP - 手机 + 密码登录 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthLoginReqVO { +public class AppAuthLoginReqVO { @ApiModelProperty(value = "手机号", required = true, example = "15601691300") @NotEmpty(message = "手机号不能为空") diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java similarity index 70% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java index 95c69c754e..07ad43118e 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,12 +7,12 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("手机密码登录 Response VO") +@ApiModel("用户 APP - 手机密码登录 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthLoginRespVO { +public class AppAuthLoginRespVO { @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma") private String token; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthResetPasswordReqVO.java similarity index 86% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthResetPasswordReqVO.java index 8160174559..a6d6ebea4f 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthResetPasswordReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import io.swagger.annotations.ApiModel; @@ -13,12 +13,13 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; -@ApiModel("重置密码 Request VO") +// TODO 芋艿:code review 相关逻辑 +@ApiModel("用户 APP - 重置密码 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthResetPasswordReqVO { +public class AppAuthResetPasswordReqVO { @ApiModelProperty(value = "新密码", required = true, example = "buzhidao") @NotEmpty(message = "新密码不能为空") @@ -35,4 +36,5 @@ public class MbrAuthResetPasswordReqVO { @NotBlank(message = "手机号不能为空") @Mobile private String mobile; + } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSendSmsReqVO.java similarity index 66% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSendSmsReqVO.java index d8c6c983f5..b8c4824d19 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSendSmsReqVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,18 +10,18 @@ import lombok.experimental.Accessors; import javax.validation.constraints.NotNull; -@ApiModel("发送手机验证码 Response VO") +@ApiModel("用户 APP - 发送手机验证码 Response VO") @Data @Accessors(chain = true) -public class SysAuthSendSmsReqVO { +public class AppAuthSendSmsReqVO { @ApiModelProperty(value = "手机号", example = "15601691234") @Mobile private String mobile; - @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举") + @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 SmsSceneEnum 枚举") @NotNull(message = "发送场景不能为空") - @InEnum(SysSmsSceneEnum.class) + @InEnum(SmsSceneEnum.class) private Integer scene; } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java similarity index 85% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java index a7b36bb546..063caf80dc 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import io.swagger.annotations.ApiModel; @@ -12,12 +12,12 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; -@ApiModel("手机 + 验证码登录 Request VO") +@ApiModel("用户 APP - 手机 + 验证码登录 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthSmsLoginReqVO { +public class AppAuthSmsLoginReqVO { @ApiModelProperty(value = "手机号", required = true, example = "15601691300") @NotEmpty(message = "手机号不能为空") diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialBindReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialBindReqVO.java similarity index 76% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialBindReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialBindReqVO.java index 767446b5f0..3ca4083185 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialBindReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialBindReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("社交绑定 Request VO,使用 code 授权码") +@ApiModel("用户 APP - 社交绑定 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthSocialBindReqVO { +public class AppAuthSocialBindReqVO { @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLogin2ReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLogin2ReqVO.java similarity index 84% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLogin2ReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLogin2ReqVO.java index 1da763ed36..b9a854ec1d 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLogin2ReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLogin2ReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -14,15 +14,15 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; -@ApiModel("社交登录 Request VO,使用 code 授权码 + 账号密码") +@ApiModel("用户 APP - 社交登录 Request VO,使用 code 授权码 + 账号密码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthSocialLogin2ReqVO { +public class AppAuthSocialLogin2ReqVO { @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLoginReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java similarity index 76% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLoginReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java index cb430231a0..e262765a94 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("社交登录 Request VO,使用 code 授权码") +@ApiModel("用户 APP - 社交登录 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthSocialLoginReqVO { +public class AppAuthSocialLoginReqVO { @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialUnbindReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialUnbindReqVO.java similarity index 73% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialUnbindReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialUnbindReqVO.java index 75e31701d1..245417820b 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialUnbindReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialUnbindReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("取消社交绑定 Request VO,使用 code 授权码") +@ApiModel("用户 APP - 取消社交绑定 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthSocialUnbindReqVO { +public class AppAuthSocialUnbindReqVO { @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthUpdatePasswordReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthUpdatePasswordReqVO.java similarity index 81% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthUpdatePasswordReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthUpdatePasswordReqVO.java index b5cc0c7850..9addb10460 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthUpdatePasswordReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthUpdatePasswordReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; +package cn.iocoder.yudao.module.member.controller.app.auth.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -11,12 +11,13 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; -@ApiModel("修改密码 Request VO") +// TODO 芋艿:code review 相关逻辑 +@ApiModel("用户 APP - 修改密码 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrAuthUpdatePasswordReqVO { +public class AppAuthUpdatePasswordReqVO { @ApiModelProperty(value = "用户旧密码", required = true, example = "123456") @NotBlank(message = "旧密码不能为空") diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.http b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.http new file mode 100644 index 0000000000..4e4be2a4d4 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.http @@ -0,0 +1,14 @@ +### 请求 /member/user/profile/get 接口 => 没有权限 +GET {{appApi}}/member/user/get +Authorization: Bearer test245 +tenant-id: {{appTenentId}} + +### 请求 /member/user/profile/revise-nickname 接口 成功 +PUT {{appApi}}/member/user/update-nickname?nickname=yunai222 +Authorization: Bearer test245 +tenant-id: {{appTenentId}} + +### 请求 /member/user/get-user-info 接口 成功 +GET {{appApi}}/member/user/get-user-info?id=245 +Authorization: Bearer test245 +tenant-id: {{appTenentId}} diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.java new file mode 100644 index 0000000000..94d67d4cfc --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.member.controller.app.user; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.convert.user.UserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.io.IOException; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.FILE_IS_EMPTY; + +@Api(tags = "用户 APP - 用户个人中心") +@RestController +@RequestMapping("/member/user") +@Validated +@Slf4j +public class AppUserController { + + @Resource + private MemberUserService userService; + + @PutMapping("/update-nickname") + @ApiOperation("修改用户昵称") + @PreAuthenticated + public CommonResult updateUserNickname(@RequestParam("nickname") String nickname) { + userService.updateUserNickname(getLoginUserId(), nickname); + return success(true); + } + + @PutMapping("/update-avatar") + @ApiOperation("修改用户头像") + @PreAuthenticated + public CommonResult updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException { + if (file.isEmpty()) { + throw exception(FILE_IS_EMPTY); + } + String avatar = userService.updateUserAvatar(getLoginUserId(), file.getInputStream()); + return success(avatar); + } + + @GetMapping("/get") + @ApiOperation("获得基本信息") + @PreAuthenticated + public CommonResult getUserInfo() { + MemberUserDO user = userService.getUser(getLoginUserId()); + return success(UserConvert.INSTANCE.convert(user)); + } + + @PostMapping("/update-mobile") + @ApiOperation(value = "修改用户手机") + @PreAuthenticated + public CommonResult updateMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) { + userService.updateUserMobile(getLoginUserId(), reqVO); + return success(true); + } + +} + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserInfoRespVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserInfoRespVO.java similarity index 76% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserInfoRespVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserInfoRespVO.java index 697c4085d3..32e684c849 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserInfoRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.member.controller.user.vo; +package cn.iocoder.yudao.module.member.controller.app.user.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("用户个人信息 Response VO") +@ApiModel("用户 APP - 用户个人信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class MbrUserInfoRespVO { +public class AppUserInfoRespVO { @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") private String nickname; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserUpdateMobileReqVO.java similarity index 89% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserUpdateMobileReqVO.java index 8593302d79..1ab6e7c843 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserUpdateMobileReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.member.controller.user.vo; +package cn.iocoder.yudao.module.member.controller.app.user.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import io.swagger.annotations.ApiModel; @@ -13,12 +13,12 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; -@ApiModel("修改手机 Request VO") +@ApiModel("用户 APP - 修改手机 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class MbrUserUpdateMobileReqVO { +public class AppUserUpdateMobileReqVO { @ApiModelProperty(value = "手机验证码", required = true, example = "1024") @NotEmpty(message = "手机验证码不能为空") @@ -38,11 +38,12 @@ public class MbrUserUpdateMobileReqVO { @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") private String oldCode; + // TODO @芋艿:oldMobile 应该不用传递 + @ApiModelProperty(value = "原手机号",required = true,example = "15823654487") @NotBlank(message = "手机号不能为空") @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位") @Mobile private String oldMobile; - } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.http b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.http similarity index 100% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.http rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.http diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.java similarity index 90% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.java index decd907a0d..5b33d44e6d 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.weixin.controller.mp; +package cn.iocoder.yudao.module.member.controller.app.weixin; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import io.swagger.annotations.Api; @@ -19,10 +19,10 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Api(tags = "微信公众号") @RestController -@RequestMapping("/wx/mp") +@RequestMapping("/member/wx-mp") @Validated @Slf4j -public class WxMpController { +public class AppWxMpController { @Resource private WxMpService mpService; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java new file mode 100644 index 0000000000..9e2888c69c --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.member.controller; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java new file mode 100644 index 0000000000..f443765cd5 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.member.convert.auth; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AuthConvert { + + AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); + + @Mapping(source = "mobile", target = "username") + LoginUser convert0(MemberUserDO bean); + + default LoginUser convert(MemberUserDO bean) { + // 目的,为了设置 UserTypeEnum.MEMBER.getValue() + return convert0(bean).setUserType(UserTypeEnum.MEMBER.getValue()); + } + + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialBindReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialLogin2ReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialLoginReqVO reqVO); + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppAuthSocialUnbindReqVO reqVO); + + SmsCodeSendReqDTO convert(AppAuthSendSmsReqVO reqVO); + SmsCodeUseReqDTO convert(AppAuthResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); + SmsCodeUseReqDTO convert(AppAuthSmsLoginReqVO reqVO, Integer scene, String userIp); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/package-info.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java index 497d7afa00..6523a66567 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/package-info.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java @@ -3,4 +3,4 @@ * * 目前使用 MapStruct 框架 */ -package cn.iocoder.yudao.adminserver.modules.bpm.convert; +package cn.iocoder.yudao.module.member.convert; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java new file mode 100644 index 0000000000..b72051d63a --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.member.convert.user; + +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserConvert { + + UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); + + AppUserInfoRespVO convert(MemberUserDO bean); + + UserRespDTO convert2(MemberUserDO bean); +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/package-info.java new file mode 100644 index 0000000000..c318d2c941 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.member.dal.dataobject.address; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java similarity index 86% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 02efd598b0..155505292d 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user; +package cn.iocoder.yudao.module.member.dal.dataobject.user; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; @@ -10,19 +10,19 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.util.Date; /** - * 会员中心的用户 DO + * 会员用户 DO * * uk_mobile 索引:基于 {@link #mobile} 字段 * * @author 芋道源码 */ -@TableName(value = "mbr_user", autoResultMap = true) +@TableName(value = "member_user", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class MbrUserDO extends TenantBaseDO { +public class MemberUserDO extends TenantBaseDO { /** * 用户ID diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java new file mode 100644 index 0000000000..9ba09a111c --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.dal.mysql.user; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 会员 User Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MemberUserMapper extends BaseMapperX { + + default MemberUserDO selectByMobile(String mobile) { + return selectOne(MemberUserDO::getMobile, mobile); + } + +} diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java new file mode 100644 index 0000000000..a45c2a1613 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java @@ -0,0 +1,9 @@ +/** + * DAL = Data Access Layer 数据访问层 + * 1. data object:数据对象 + * 2. redis:Redis 的 CRUD 操作 + * 3. mysql:MySQL 的 CRUD 操作 + * + * 其中,MySQL 的表以 member_ 作为前缀 + */ +package cn.iocoder.yudao.module.member.dal; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java new file mode 100644 index 0000000000..8dfa9fb20d --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位,后续有类后,可以删除,避免 package 无法提交到 Git 上 + */ +package cn.iocoder.yudao.module.member.dal.redis; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java new file mode 100644 index 0000000000..9e136937a0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.member.enums; diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/package-info.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/package-info.java new file mode 100644 index 0000000000..405aa4cbf6 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/package-info.java @@ -0,0 +1,8 @@ +/** + * member 模块,我们放会员业务。 + * 例如说:会员中心等等 + * + * 1. Controller URL:以 /member/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 member_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.member; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java similarity index 54% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java index 0145821d55..b72ac5ee77 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java @@ -1,18 +1,18 @@ -package cn.iocoder.yudao.userserver.modules.system.service.auth; +package cn.iocoder.yudao.module.member.service.auth; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; import javax.validation.Valid; /** - * 用户前台的认证 Service 接口 + * 会员的认证 Service 接口 * * 提供用户的账号密码登录、token 的校验等认证相关的功能 * * @author 芋道源码 */ -public interface SysAuthService extends SecurityAuthFrameworkService { +public interface MemberAuthService extends SecurityAuthFrameworkService { /** * 手机 + 密码登录 @@ -22,7 +22,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent); + String login(@Valid AppAuthLoginReqVO reqVO, String userIp, String userAgent); /** * 手机 + 验证码登陆 @@ -32,7 +32,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent); + String smsLogin(@Valid AppAuthSmsLoginReqVO reqVO, String userIp, String userAgent); /** @@ -43,7 +43,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String socialLogin(@Valid MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent); + String socialLogin(@Valid AppAuthSocialLoginReqVO reqVO, String userIp, String userAgent); /** * 社交登录,使用 手机号 + 手机验证码 @@ -53,7 +53,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String socialLogin2(@Valid MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); + String socialLogin2(@Valid AppAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); /** * 社交绑定,使用 code 授权码 @@ -61,18 +61,44 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userId 用户编号 * @param reqVO 绑定信息 */ - void socialBind(Long userId, @Valid MbrAuthSocialBindReqVO reqVO); + void socialBind(Long userId, @Valid AppAuthSocialBindReqVO reqVO); + + /** + * 取消社交绑定 + * + * @param userId 用户编号 + * @param reqVO 解绑信息 + */ + void unbindSocialUser(Long userId, @Valid AppAuthSocialUnbindReqVO reqVO); + + /** + * 获得社交认证 URL + * + * @param type 社交平台类型 + * @param redirectUri 跳转地址 + * @return 认证 URL + */ + String getSocialAuthorizeUrl(Integer type, String redirectUri); /** * 修改用户密码 * @param userId 用户id * @param userReqVO 用户请求实体类 */ - void updatePassword(Long userId,MbrAuthUpdatePasswordReqVO userReqVO); + void updatePassword(Long userId, AppAuthUpdatePasswordReqVO userReqVO); /** * 忘记密码 * @param userReqVO 用户请求实体类 */ - void resetPassword(MbrAuthResetPasswordReqVO userReqVO); + void resetPassword(AppAuthResetPasswordReqVO userReqVO); + + /** + * 给用户发送短信验证码 + * + * @param userId 用户编号 + * @param reqVO 发送信息 + */ + void sendSmsCode(Long userId, AppAuthSendSmsReqVO reqVO); + } diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java new file mode 100644 index 0000000000..b95408afc3 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -0,0 +1,351 @@ +package cn.iocoder.yudao.module.member.service.auth; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; +import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.system.api.auth.UserSessionApi; +import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.social.SocialUserApi; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; + +/** + * 会员的认证 Service 接口 + * + * @author 芋道源码 + */ +@Service +@Slf4j +public class MemberAuthServiceImpl implements MemberAuthService { + + @Resource + @Lazy // 延迟加载,因为存在相互依赖的问题 + private AuthenticationManager authenticationManager; + + @Resource + private MemberUserService userService; + @Resource + private SmsCodeApi smsCodeApi; + @Resource + private LoginLogApi loginLogApi; + @Resource + private UserSessionApi userSessionApi; + @Resource + private SocialUserApi socialUserApi; + + @Resource + private PasswordEncoder passwordEncoder; + @Resource + private MemberUserMapper userMapper; + + @Override + public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { + // 获取 username 对应的 SysUserDO + MemberUserDO user = userService.getUserByMobile(mobile); + if (user == null) { + throw new UsernameNotFoundException(mobile); + } + // 创建 LoginUser 对象 + return AuthConvert.INSTANCE.convert(user); + } + + @Override + public String login(AppAuthLoginReqVO reqVO, String userIp, String userAgent) { + // 使用手机 + 密码,进行登录。 + LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword()); + + // 缓存登录用户到 Redis 中,返回 sessionId 编号 + return userSessionApi.createUserSession(loginUser, userIp, userAgent); + } + + @Override + @Transactional + public String smsLogin(AppAuthSmsLoginReqVO reqVO, String userIp, String userAgent) { + // 校验验证码 + smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)); + + // 获得获得注册用户 + MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp); + Assert.notNull(user, "获取用户失败,结果为空"); + + // 执行登陆 + this.createLoginLog(user.getMobile(), LoginLogTypeEnum.LOGIN_SMS, LoginResultEnum.SUCCESS); + LoginUser loginUser = AuthConvert.INSTANCE.convert(user); + + // 缓存登录用户到 Redis 中,返回 sessionId 编号 + return userSessionApi.createUserSession(loginUser, userIp, userAgent); + } + + @Override + public String socialLogin(AppAuthSocialLoginReqVO reqVO, String userIp, String userAgent) { + // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 + Long userId = socialUserApi.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + reqVO.getCode(), reqVO.getState()); + if (userId == null) { + throw exception(AUTH_THIRD_LOGIN_NOT_BIND); + } + + // 自动登录 + MemberUserDO user = userService.getUser(userId); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + this.createLoginLog(user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, LoginResultEnum.SUCCESS); + + // 创建 LoginUser 对象 + LoginUser loginUser = AuthConvert.INSTANCE.convert(user); + + // 绑定社交用户(更新) + socialUserApi.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); + + // 缓存登录用户到 Redis 中,返回 sessionId 编号 + return userSessionApi.createUserSession(loginUser, userIp, userAgent); + } + + @Override + public String socialLogin2(AppAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { + // 校验社交平台的认证信息是否正确 + socialUserApi.checkSocialUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); + + // 使用手机号、手机验证码登录 + AppAuthSmsLoginReqVO loginReqVO = AppAuthSmsLoginReqVO.builder() + .mobile(reqVO.getMobile()).code(reqVO.getSmsCode()).build(); + String sessionId = this.smsLogin(loginReqVO, userIp, userAgent); + LoginUser loginUser = userSessionApi.getLoginUser(sessionId); + + // 绑定社交用户(新增) + socialUserApi.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); + return sessionId; + } + + @Override + public void socialBind(Long userId, AppAuthSocialBindReqVO reqVO) { + // 绑定社交用户(新增) + socialUserApi.bindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO)); + } + + @Override + public void unbindSocialUser(Long userId, AppAuthSocialUnbindReqVO reqVO) { + socialUserApi.unbindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO)); + } + + @Override + public String getSocialAuthorizeUrl(Integer type, String redirectUri) { + return socialUserApi.getAuthorizeUrl(type, redirectUri); + } + + private LoginUser login0(String username, String password) { + final LoginLogTypeEnum logType = LoginLogTypeEnum.LOGIN_USERNAME; + // 用户验证 + Authentication authentication; + try { + // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证 + // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 + authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken( + username, password, getUserType())); + } catch (BadCredentialsException badCredentialsException) { + this.createLoginLog(username, logType, LoginResultEnum.BAD_CREDENTIALS); + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } catch (DisabledException disabledException) { + this.createLoginLog(username, logType, LoginResultEnum.USER_DISABLED); + throw exception(AUTH_LOGIN_USER_DISABLED); + } catch (AuthenticationException authenticationException) { + log.error("[login0][username({}) 发生未知异常]", username, authenticationException); + this.createLoginLog(username, logType, LoginResultEnum.UNKNOWN_ERROR); + throw exception(AUTH_LOGIN_FAIL_UNKNOWN); + } + // 登录成功的日志 + Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); + this.createLoginLog(username, logType, LoginResultEnum.SUCCESS); + return (LoginUser) authentication.getPrincipal(); + } + + private void createLoginLog(String mobile, LoginLogTypeEnum logType, LoginResultEnum loginResult) { + // 获得用户 + MemberUserDO user = userService.getUserByMobile(mobile); + // 插入登录日志 + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(logType.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + if (user != null) { + reqDTO.setUserId(user.getId()); + } + reqDTO.setUserType(getUserType().getValue()); + reqDTO.setUsername(mobile); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(getClientIP()); + reqDTO.setResult(loginResult.getResult()); + loginLogApi.createLoginLog(reqDTO); + // 更新最后登录时间 + if (user != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { + userService.updateUserLogin(user.getId(), getClientIP()); + } + } + + @Override + public LoginUser verifyTokenAndRefresh(String token) { + // 获得 LoginUser + LoginUser loginUser = userSessionApi.getLoginUser(token); + if (loginUser == null) { + return null; + } + // 刷新 LoginUser 缓存 + this.refreshLoginUserCache(token, loginUser); + return loginUser; + } + + private void refreshLoginUserCache(String token, LoginUser loginUser) { + // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存 + if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() < + userSessionApi.getSessionTimeoutMillis() / 3) { + return; + } + + // 重新加载 UserDO 信息 + MemberUserDO user = userService.getUser(loginUser.getId()); + if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { + // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 + throw exception(AUTH_TOKEN_EXPIRED); + } + + // 刷新 LoginUser 缓存 + userSessionApi.refreshUserSession(token, loginUser); + } + + @Override + public LoginUser mockLogin(Long userId) { + // 获取用户编号对应的 UserDO + MemberUserDO user = userService.getUser(userId); + if (user == null) { + throw new UsernameNotFoundException(String.valueOf(userId)); + } + + // 执行登陆 + this.createLoginLog(user.getMobile(), LoginLogTypeEnum.LOGIN_MOCK, LoginResultEnum.SUCCESS); + + // 创建 LoginUser 对象 + return AuthConvert.INSTANCE.convert(user); + } + + @Override + public void logout(String token) { + // 查询用户信息 + LoginUser loginUser = userSessionApi.getLoginUser(token); + if (loginUser == null) { + return; + } + // 删除 session + userSessionApi.deleteUserSession(token); + // 记录登出日志 + this.createLogoutLog(loginUser.getId(), loginUser.getUsername()); + } + + @Override + public UserTypeEnum getUserType() { + return UserTypeEnum.MEMBER; + } + + @Override + public void updatePassword(Long userId, AppAuthUpdatePasswordReqVO reqVO) { + // 检验旧密码 + MemberUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword()); + + // 更新用户密码 + userMapper.updateById(MemberUserDO.builder().id(userDO.getId()) + .password(passwordEncoder.encode(reqVO.getPassword())).build()); + } + + @Override + public void resetPassword(AppAuthResetPasswordReqVO reqVO) { + // 检验用户是否存在 + MemberUserDO userDO = checkUserIfExists(reqVO.getMobile()); + + // 使用验证码 + smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_FORGET_PASSWORD, + getClientIP())); + + // 更新密码 + userMapper.updateById(MemberUserDO.builder().id(userDO.getId()) + .password(passwordEncoder.encode(reqVO.getPassword())).build()); + } + + @Override + public void sendSmsCode(Long userId, AppAuthSendSmsReqVO reqVO) { + // TODO 要根据不同的场景,校验是否有用户 + smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO)); + } + + /** + * 校验旧密码 + * + * @param id 用户 id + * @param oldPassword 旧密码 + * @return MemberUserDO 用户实体 + */ + @VisibleForTesting + public MemberUserDO checkOldPassword(Long id, String oldPassword) { + MemberUserDO user = userMapper.selectById(id); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + // 参数:未加密密码,编码后的密码 + if (!passwordEncoder.matches(oldPassword,user.getPassword())) { + throw exception(USER_PASSWORD_FAILED); + } + return user; + } + + public MemberUserDO checkUserIfExists(String mobile) { + MemberUserDO user = userMapper.selectByMobile(mobile); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + return user; + } + + private void createLogoutLog(Long userId, String username) { + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(getUserType().getValue()); + reqDTO.setUsername(username); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(getClientIP()); + reqDTO.setResult(LoginResultEnum.SUCCESS.getResult()); + loginLogApi.createLoginLog(reqDTO); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java similarity index 54% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java rename to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index e33978bfe2..1a38e61af1 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -1,18 +1,17 @@ -package cn.iocoder.yudao.userserver.modules.member.service.user; +package cn.iocoder.yudao.module.member.service.user; -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO; import cn.iocoder.yudao.framework.common.validation.Mobile; -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import java.io.InputStream; /** - * 前台用户 Service 接口 + * 会员用户 Service 接口 * * @author 芋道源码 */ -public interface MbrUserService { +public interface MemberUserService { /** * 通过手机查询用户 @@ -20,7 +19,7 @@ public interface MbrUserService { * @param mobile 手机 * @return 用户对象 */ - MbrUserDO getUserByMobile(String mobile); + MemberUserDO getUserByMobile(String mobile); /** * 基于手机号创建用户。 @@ -30,7 +29,7 @@ public interface MbrUserService { * @param registerIp 注册 IP * @return 用户对象 */ - MbrUserDO createUserIfAbsent(@Mobile String mobile, String registerIp); + MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp); /** * 更新用户的最后登陆信息 @@ -46,14 +45,14 @@ public interface MbrUserService { * @param id 用户ID * @return 用户对象信息 */ - MbrUserDO getUser(Long id); + MemberUserDO getUser(Long id); /** * 修改用户昵称 * @param userId 用户id * @param nickname 用户新昵称 */ - void updateNickname(Long userId, String nickname); + void updateUserNickname(Long userId, String nickname); /** * 修改用户头像 @@ -61,21 +60,13 @@ public interface MbrUserService { * @param inputStream 头像文件 * @return 头像url */ - String updateAvatar(Long userId, InputStream inputStream); - - /** - * 根据用户id,获取用户头像与昵称 - * - * @param userId 用户id - * @return 用户响应实体类 - */ - MbrUserInfoRespVO getUserInfo(Long userId); + String updateUserAvatar(Long userId, InputStream inputStream); /** * 修改手机 * @param userId 用户id * @param reqVO 请求实体 */ - void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO); + void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO); } diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java new file mode 100644 index 0000000000..fcfe3ae511 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.member.service.user; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.io.InputStream; +import java.util.Date; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_NOT_EXISTS; + +/** + * 会员 User Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Valid +@Slf4j +public class MemberUserServiceImpl implements MemberUserService { + + @Resource + private MemberUserMapper memberUserMapper; + + @Resource + private FileApi fileApi; + @Resource + private SmsCodeApi smsCodeApi; + + @Resource + private PasswordEncoder passwordEncoder; + + @Override + public MemberUserDO getUserByMobile(String mobile) { + return memberUserMapper.selectByMobile(mobile); + } + + @Override + public MemberUserDO createUserIfAbsent(String mobile, String registerIp) { + // 用户已经存在 + MemberUserDO user = memberUserMapper.selectByMobile(mobile); + if (user != null) { + return user; + } + // 用户不存在,则进行创建 + return this.createUser(mobile, registerIp); + } + + private MemberUserDO createUser(String mobile, String registerIp) { + // 生成密码 + String password = IdUtil.fastSimpleUUID(); + // 插入用户 + MemberUserDO user = new MemberUserDO(); + user.setMobile(mobile); + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 + user.setPassword(passwordEncoder.encode(password)); // 加密密码 + user.setRegisterIp(registerIp); + memberUserMapper.insert(user); + return user; + } + + @Override + public void updateUserLogin(Long id, String loginIp) { + memberUserMapper.updateById(new MemberUserDO().setId(id) + .setLoginIp(loginIp).setLoginDate(new Date())); + } + + @Override + public MemberUserDO getUser(Long id) { + return memberUserMapper.selectById(id); + } + + @Override + public void updateUserNickname(Long userId, String nickname) { + MemberUserDO user = this.checkUserExists(userId); + // 仅当新昵称不等于旧昵称时进行修改 + if (nickname.equals(user.getNickname())){ + return; + } + MemberUserDO userDO = new MemberUserDO(); + userDO.setId(user.getId()); + userDO.setNickname(nickname); + memberUserMapper.updateById(userDO); + } + + @Override + public String updateUserAvatar(Long userId, InputStream avatarFile) { + this.checkUserExists(userId); + // 创建文件 + String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile)); + // 更新头像路径 + memberUserMapper.updateById(MemberUserDO.builder().id(userId).avatar(avatar).build()); + return avatar; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO) { + // 检测用户是否存在 + checkUserExists(userId); + // TODO 芋艿:oldMobile 应该不用传递 + + // 校验旧手机和旧验证码 + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getOldMobile()).setCode(reqVO.getOldCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); + // 使用新验证码 + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); + + // 更新用户手机 + memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build()); + } + + @VisibleForTesting + public MemberUserDO checkUserExists(Long id) { + if (id == null) { + return null; + } + MemberUserDO user = memberUserMapper.selectById(id); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + return user; + } + +} diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java similarity index 51% rename from yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java rename to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java index 4c8b953c6b..3b17af712b 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java +++ b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceTest.java @@ -1,24 +1,21 @@ -package cn.iocoder.yudao.userserver.modules.system.service; +package cn.iocoder.yudao.module.member.service.auth; -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; -import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest; -import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper; -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthResetPasswordReqVO; -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthUpdatePasswordReqVO; -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; -import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl; -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.AppAuthResetPasswordReqVO; +import cn.iocoder.yudao.module.member.controller.app.auth.vo.AppAuthUpdatePasswordReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.member.test.BaseDbAndRedisUnitTest; +import cn.iocoder.yudao.module.system.api.auth.UserSessionApi; +import cn.iocoder.yudao.module.system.api.logger.LoginLogApi; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import cn.iocoder.yudao.module.system.api.social.SocialUserApi; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.crypto.password.PasswordEncoder; @@ -34,45 +31,43 @@ import static org.mockito.Mockito.when; // TODO @芋艿:单测的 review,等逻辑都达成一致后 /** - * {@link SysAuthService} 的单元测试类 + * {@link MemberAuthService} 的单元测试类 * * @author 宋天 */ -@Import({SysAuthServiceImpl.class, YudaoRedisAutoConfiguration.class}) -public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { +@Import({MemberAuthServiceImpl.class, YudaoRedisAutoConfiguration.class}) +public class MemberAuthServiceTest extends BaseDbAndRedisUnitTest { @MockBean private AuthenticationManager authenticationManager; @MockBean - private MbrUserService userService; + private MemberUserService userService; @MockBean - private SysSmsCodeService smsCodeService; + private SmsCodeApi smsCodeApi; @MockBean - private SysLoginLogCoreService loginLogCoreService; + private LoginLogApi loginLogApi; @MockBean - private SysUserSessionCoreService userSessionCoreService; + private UserSessionApi userSessionApi; @MockBean - private SysSocialCoreService socialService; - @Resource - private StringRedisTemplate stringRedisTemplate; + private SocialUserApi socialUserApi; @MockBean private PasswordEncoder passwordEncoder; @Resource - private MbrUserMapper mbrUserMapper; + private MemberUserMapper memberUserMapper; @Resource - private SysAuthServiceImpl authService; + private MemberAuthServiceImpl authService; @Test public void testUpdatePassword_success(){ // 准备参数 - MbrUserDO userDO = randomMbrUserDO(); - mbrUserMapper.insert(userDO); + MemberUserDO userDO = randomUserDO(); + memberUserMapper.insert(userDO); // 新密码 String newPassword = randomString(); // 请求实体 - MbrAuthUpdatePasswordReqVO reqVO = MbrAuthUpdatePasswordReqVO.builder() + AppAuthUpdatePasswordReqVO reqVO = AppAuthUpdatePasswordReqVO.builder() .oldPassword(userDO.getPassword()) .password(newPassword) .build(); @@ -83,15 +78,15 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { when(passwordEncoder.encode(newPassword)).thenReturn(newPassword); // 更新用户密码 - authService.updatePassword(userDO.getId(),reqVO); - assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),newPassword); + authService.updatePassword(userDO.getId(), reqVO); + assertEquals(memberUserMapper.selectById(userDO.getId()).getPassword(),newPassword); } @Test public void testResetPassword_success(){ // 准备参数 - MbrUserDO userDO = randomMbrUserDO(); - mbrUserMapper.insert(userDO); + MemberUserDO userDO = randomUserDO(); + memberUserMapper.insert(userDO); // 随机密码 String password = randomNumbers(11); @@ -102,25 +97,25 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { when(passwordEncoder.encode(password)).thenReturn(password); // 更新用户密码 - MbrAuthResetPasswordReqVO reqVO = new MbrAuthResetPasswordReqVO(); + AppAuthResetPasswordReqVO reqVO = new AppAuthResetPasswordReqVO(); reqVO.setMobile(userDO.getMobile()); reqVO.setPassword(password); reqVO.setCode(code); authService.resetPassword(reqVO); - assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password); + assertEquals(memberUserMapper.selectById(userDO.getId()).getPassword(),password); } // ========== 随机对象 ========== @SafeVarargs - private static MbrUserDO randomMbrUserDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static MemberUserDO randomUserDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 o.setPassword(randomString()); }; - return randomPojo(MbrUserDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers)); } diff --git a/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java new file mode 100644 index 0000000000..46d72091ce --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.module.member.service.user; + +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO; +import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; +import cn.iocoder.yudao.module.member.service.auth.MemberAuthServiceImpl; +import cn.iocoder.yudao.module.member.test.BaseDbAndRedisUnitTest; +import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.annotation.Resource; +import java.io.ByteArrayInputStream; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +// TODO @芋艿:单测的 review,等逻辑都达成一致后 +/** + * {@link MemberUserServiceImpl} 的单元测试类 + * + * @author 宋天 + */ +@Import({MemberUserServiceImpl.class, YudaoRedisAutoConfiguration.class}) +public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest { + + @Resource + private MemberUserServiceImpl memberUserService; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private MemberUserMapper userMapper; + + @MockBean + private MemberAuthServiceImpl authService; + + @MockBean + private PasswordEncoder passwordEncoder; + + @MockBean + private SmsCodeApi smsCodeApi; + @MockBean + private FileApi fileApi; + + @Test + public void testUpdateNickName_success(){ + // mock 数据 + MemberUserDO userDO = randomUserDO(); + userMapper.insert(userDO); + + // 随机昵称 + String newNickName = randomString(); + + // 调用接口修改昵称 + memberUserService.updateUserNickname(userDO.getId(),newNickName); + // 查询新修改后的昵称 + String nickname = memberUserService.getUser(userDO.getId()).getNickname(); + // 断言 + assertEquals(newNickName,nickname); + } + + @Test + public void testUpdateAvatar_success(){ + // mock 数据 + MemberUserDO dbUser = randomUserDO(); + userMapper.insert(dbUser); + + // 准备参数 + Long userId = dbUser.getId(); + byte[] avatarFileBytes = randomBytes(10); + ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes); + // mock 方法 + String avatar = randomString(); + when(fileApi.createFile(eq(avatarFileBytes))).thenReturn(avatar); + // 调用 + String str = memberUserService.updateUserAvatar(userId, avatarFile); + // 断言 + assertEquals(avatar, str); + } + + @Test + public void updateMobile_success(){ + // mock数据 + String oldMobile = randomNumbers(11); + MemberUserDO userDO = randomUserDO(); + userDO.setMobile(oldMobile); + userMapper.insert(userDO); + + // TODO 芋艿:需要修复该单元测试,重构多模块带来的 + // 旧手机和旧验证码 +// SmsCodeDO codeDO = new SmsCodeDO(); + String oldCode = RandomUtil.randomString(4); +// codeDO.setMobile(userDO.getMobile()); +// codeDO.setCode(oldCode); +// codeDO.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()); +// codeDO.setUsed(Boolean.FALSE); +// when(smsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO); + + // 更新手机号 + String newMobile = randomNumbers(11); + String newCode = randomNumbers(4); + AppUserUpdateMobileReqVO reqVO = new AppUserUpdateMobileReqVO(); + reqVO.setMobile(newMobile); + reqVO.setCode(newCode); + reqVO.setOldMobile(oldMobile); + reqVO.setOldCode(oldCode); + memberUserService.updateUserMobile(userDO.getId(),reqVO); + + assertEquals(memberUserService.getUser(userDO.getId()).getMobile(),newMobile); + } + + // ========== 随机对象 ========== + + @SafeVarargs + private static MemberUserDO randomUserDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 + }; + return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers)); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisUnitTest.java b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbAndRedisUnitTest.java similarity index 92% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisUnitTest.java rename to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbAndRedisUnitTest.java index 2cc60cc30c..b8cf0aff18 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisUnitTest.java +++ b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbAndRedisUnitTest.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.module.member.test; -import cn.iocoder.yudao.adminserver.config.RedisTestConfiguration; -import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; @@ -24,6 +23,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbAndRedisUnitTest { diff --git a/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbUnitTest.java b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbUnitTest.java new file mode 100644 index 0000000000..c6345ccb13 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbUnitTest.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.member.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +/** + * 依赖内存 DB 的单元测试 + * + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB +public class BaseDbUnitTest { + + @Import({ + // DB 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类 + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + }) + public static class Application { + } + +} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/config/RedisTestConfiguration.java b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/RedisTestConfiguration.java similarity index 96% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/config/RedisTestConfiguration.java rename to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/RedisTestConfiguration.java index eb0791974c..99838337bb 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/config/RedisTestConfiguration.java +++ b/yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/RedisTestConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.config; +package cn.iocoder.yudao.module.member.test; import com.github.fppt.jedismock.RedisServer; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; diff --git a/yudao-core-service/src/test/resources/application-unit-test.yaml b/yudao-module-member/yudao-module-member-impl/src/test/resources/application-unit-test.yaml similarity index 83% rename from yudao-core-service/src/test/resources/application-unit-test.yaml rename to yudao-module-member/yudao-module-member-impl/src/test/resources/application-unit-test.yaml index d360045b9c..9f36ec4ac9 100644 --- a/yudao-core-service/src/test/resources/application-unit-test.yaml +++ b/yudao-module-member/yudao-module-member-impl/src/test/resources/application-unit-test.yaml @@ -6,12 +6,6 @@ spring: --- #################### 数据库相关配置 #################### spring: -# sql: -# init: -# schema-locations: classpath:sql/create_tables.sql -# username: sa -# password: -# enabled: true # 数据源配置项 datasource: name: ruoyi-vue-pro @@ -19,7 +13,6 @@ spring: driver-class-name: org.h2.Driver username: sa password: - schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具 druid: async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 initial-size: 1 # 单元测试,配置为 1,提升启动速度 @@ -29,9 +22,6 @@ spring: host: 127.0.0.1 # 地址 port: 16379 # 端口(单元测试,使用 16379 端口) database: 0 # 数据库索引 - integration: - jdbc: - initialize-schema: mybatis: lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 @@ -51,3 +41,6 @@ mybatis: --- #################### 芋道相关配置 #################### # 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-module-member/yudao-module-member-impl/src/test/resources/logback.xml b/yudao-module-member/yudao-module-member-impl/src/test/resources/logback.xml new file mode 100644 index 0000000000..daf756bff0 --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-member/yudao-module-member-impl/src/test/resources/sql/clean.sql b/yudao-module-member/yudao-module-member-impl/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..92f559dc1d --- /dev/null +++ b/yudao-module-member/yudao-module-member-impl/src/test/resources/sql/clean.sql @@ -0,0 +1 @@ +DELETE FROM "member_user"; diff --git a/yudao-user-server/src/test/resources/sql/create_tables.sql b/yudao-module-member/yudao-module-member-impl/src/test/resources/sql/create_tables.sql similarity index 96% rename from yudao-user-server/src/test/resources/sql/create_tables.sql rename to yudao-module-member/yudao-module-member-impl/src/test/resources/sql/create_tables.sql index c9dfd8c318..85925f30b2 100644 --- a/yudao-user-server/src/test/resources/sql/create_tables.sql +++ b/yudao-module-member/yudao-module-member-impl/src/test/resources/sql/create_tables.sql @@ -1,5 +1,4 @@ --- mbr 开头的 DB -CREATE TABLE IF NOT EXISTS "mbr_user" ( +CREATE TABLE IF NOT EXISTS "member_user" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号', "nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称', "avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像', diff --git a/yudao-module-pay/pom.xml b/yudao-module-pay/pom.xml new file mode 100644 index 0000000000..36fd9edb30 --- /dev/null +++ b/yudao-module-pay/pom.xml @@ -0,0 +1,25 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + yudao-module-pay + pom + + yudao-module-pay-api + yudao-module-pay-impl + + + ${artifactId} + + pay 模块,我们放支付业务,提供业务的支付能力。 + 例如说:商户、应用、支付、退款等等 + + + + diff --git a/yudao-module-pay/yudao-module-pay-api/pom.xml b/yudao-module-pay/yudao-module-pay-api/pom.xml new file mode 100644 index 0000000000..389aaa3fc2 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/pom.xml @@ -0,0 +1,26 @@ + + + + yudao-module-pay + cn.iocoder.boot + ${revision} + + 4.0.0 + yudao-module-pay-api + jar + + ${artifactId} + + pay 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java new file mode 100644 index 0000000000..58eb776d36 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.pay.enums; + +/** + * Pay 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String ORDER_STATUS = "pay_order_status"; // 支付-订单-订单状态 + String ORDER_NOTIFY_STATUS = "pay_order_notify_status"; // 支付-订单-订单回调商户状态 + + String ORDER_REFUND_STATUS = "pay_order_refund_status"; // 支付-订单-订单退款状态 + String REFUND_ORDER_STATUS = "pay_refund_order_status"; // 支付-退款订单-退款状态 + String REFUND_ORDER_TYPE = "pay_refund_order_type"; // 支付-退款订单-退款类别 + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java similarity index 97% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java rename to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index f5133ad05c..203cb07038 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums; +package cn.iocoder.yudao.module.pay.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; * * pay 系统,使用 1-007-000-000 段 */ -public interface PayErrorCodeCoreConstants { +public interface ErrorCodeConstants { /** * ========== APP 模块 1-007-000-000 ========== diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/package-info.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/package-info.java new file mode 100644 index 0000000000..756410aa84 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay; diff --git a/yudao-module-pay/yudao-module-pay-impl/pom.xml b/yudao-module-pay/yudao-module-pay-impl/pom.xml new file mode 100644 index 0000000000..55a254484b --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/pom.xml @@ -0,0 +1,81 @@ + + + + yudao-module-pay + cn.iocoder.boot + ${revision} + + 4.0.0 + yudao-module-pay-impl + jar + + ${artifactId} + + pay 模块,我们放支付业务,提供业务的支付能力。 + 例如说:商户、应用、支付、退款等等 + + + + + cn.iocoder.boot + yudao-module-pay-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-pay + + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-job + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mq + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayAppController.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayAppController.java index 3446243929..47cc3a4db1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayAppController.java @@ -1,20 +1,20 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app; +package cn.iocoder.yudao.module.pay.controller.admin.merchant; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*; -import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; -import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; -import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.*; +import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; +import cn.iocoder.yudao.module.pay.service.merchant.PayMerchantService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -33,7 +33,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Slf4j -@Api(tags = "支付应用信息") +@Api(tags = "管理后台 - 支付应用信息") @RestController @RequestMapping("/pay/app") @Validated @@ -106,7 +106,7 @@ public class PayAppController { return success(new PageResult<>(pageResult.getTotal())); } - // 得到所有的应用编号,查出所有的通道 + // 得到所有的应用编号,查出所有的渠道 Collection payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId); List channels = channelService.getChannelListByAppIds(payAppIds); // TODO @aquan:可以基于 appId 简历一个 multiMap。这样下面,直接 get 到之后,CollUtil buildSet 即可 @@ -116,7 +116,7 @@ public class PayAppController { Collection merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId); Map deptMap = merchantService.getMerchantMap(merchantIds); - // 利用反射将通道数据复制到返回的数据结构中去 + // 利用反射将渠道数据复制到返回的数据结构中去 List appList = new ArrayList<>(pageResult.getList().size()); pageResult.getList().forEach(app -> { // 写入应用信息的数据 @@ -155,7 +155,7 @@ public class PayAppController { @ApiOperation("根据商户 ID 查询支付应用信息") @ApiImplicitParam(name = "merchantId", value = "商户ID", required = true, example = "1", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('pay:merchant:query')") - public CommonResult> getMerchantListByName(@RequestParam String merchantId) { + public CommonResult> getMerchantListByName(@RequestParam Long merchantId) { List appListDO = appService.getListByMerchantId(merchantId); return success(PayAppConvert.INSTANCE.convertList(appListDO)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayChannelController.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayChannelController.java index ae83ef9cc2..82d3a354e3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/PayChannelController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayChannelController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel; +package cn.iocoder.yudao.module.pay.controller.admin.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; -import cn.iocoder.yudao.adminserver.modules.pay.convert.channel.PayChannelConvert; -import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.*; +import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -26,11 +26,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -/** - * 支付渠道 controller 组件 - * @author aquan - */ -@Api(tags = "支付渠道") +@Api(tags = "管理后台 - 支付渠道") @RestController @RequestMapping("/pay/channel") @Validated @@ -39,7 +35,6 @@ public class PayChannelController { @Resource private PayChannelService channelService; - @PostMapping("/create") @ApiOperation("创建支付渠道 ") @PreAuthorize("@ss.hasPermission('pay:channel:create')") @@ -116,7 +111,6 @@ public class PayChannelController { @PreAuthorize("@ss.hasPermission('pay:channel:query')") public CommonResult getChannel( @RequestParam Long merchantId, @RequestParam Long appId, @RequestParam String code) { - // 獲取渠道 PayChannelDO channel = channelService.getChannelByConditions(merchantId, appId, code); if (channel == null) { @@ -126,4 +120,5 @@ public class PayChannelController { PayChannelRespVO respVo = PayChannelConvert.INSTANCE.convert(channel); return success(respVo); } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayMerchantController.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayMerchantController.java index ae0235efc1..19bdfc86d2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/PayMerchantController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant; +package cn.iocoder.yudao.module.pay.controller.admin.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*; -import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.*; +import cn.iocoder.yudao.module.pay.convert.merchant.PayMerchantConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.service.merchant.PayMerchantService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -77,7 +77,7 @@ public class PayMerchantController { @GetMapping("/list-by-name") @ApiOperation("根据商户名称获得支付商户信息列表") - @ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = Long.class) + @ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = String.class) @PreAuthorize("@ss.hasPermission('pay:merchant:query')") public CommonResult> getMerchantListByName(@RequestParam(required = false) String name) { List merchantListDO = merchantService.getMerchantListByName(name); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppBaseVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppBaseVO.java index 6ffe565ec4..795b3c6438 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppBaseVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import lombok.*; import io.swagger.annotations.*; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppCreateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppCreateReqVO.java new file mode 100644 index 0000000000..a66a719632 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; + +import lombok.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 支付应用信息创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PayAppCreateReqVO extends PayAppBaseVO { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExcelVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExcelVO.java index f81b53bd08..3fc274a03a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExcelVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExcelVO.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; - -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.util.Date; /** * 支付应用信息 Excel VO diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExportReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExportReqVO.java index b5d284447f..d8b4642503 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppExportReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "支付应用信息 Excel 导出 Request VO", description = "参数和 PayAppPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 支付应用信息 Excel 导出 Request VO", description = "参数和 PayAppPageReqVO 是一致的") @Data public class PayAppExportReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageItemRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageItemRespVO.java index 6d8144afe2..e5ad0825f3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,7 @@ import lombok.ToString; import java.util.Date; import java.util.Set; -/** - * 支付应用信息分页查询 Response VO - * - * @author aquan - */ -@ApiModel(value = "支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息") +@ApiModel(value = "管理后台 - 支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageReqVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageReqVO.java index 62156e9934..62af7e19f5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("支付应用信息分页 Request VO") +@ApiModel("管理后台 - 支付应用信息分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppRespVO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppRespVO.java index 565491f926..e0ac450a2d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppRespVO.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import lombok.*; import java.util.*; import io.swagger.annotations.*; -@ApiModel("支付应用信息 Response VO") +@ApiModel("管理后台 - 支付应用信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateReqVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateReqVO.java index 426366fc15..9bdd042543 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateReqVO.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("支付应用信息更新 Request VO") +@ApiModel("管理后台 - 支付应用信息更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateStatusReqVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateStatusReqVO.java index 28a3218ae4..2ccce684cb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppUpdateStatusReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/app/PayAppUpdateStatusReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("应用更新状态 Request VO") +@ApiModel("管理后台 - 应用更新状态 Request VO") @Data public class PayAppUpdateStatusReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelBaseVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelBaseVO.java index 42a98b972f..8b9f534904 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelBaseVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelBaseVO.java @@ -1,13 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; /** -* 支付渠道 - Base VO,提供给添加、修改、详细的子 VO 使用 +* 支付渠道 Base VO,提供给添加、修改、详细的子 VO 使用 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelCreateReqVO.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelCreateReqVO.java index a814b7b863..5852f9bb17 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelCreateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,14 +8,14 @@ import lombok.ToString; import javax.validation.constraints.NotBlank; -@ApiModel("支付渠道 创建 Request VO") +@ApiModel("管理后台 - 支付渠道 创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class PayChannelCreateReqVO extends PayChannelBaseVO { - @ApiModelProperty(value = "通道配置的 json 字符串") - @NotBlank(message = "通道配置不能为空") + @ApiModelProperty(value = "渠道配置的 json 字符串") + @NotBlank(message = "渠道配置不能为空") private String config; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExcelVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExcelVO.java index a4618780ab..780abb18f0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExcelVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExcelVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; import java.util.*; @@ -7,8 +7,7 @@ import io.swagger.annotations.*; import com.alibaba.excel.annotation.ExcelProperty; /** - * 支付渠道 - Excel VO + * 支付渠道 Excel VO * * @author 芋艿 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExportReqVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExportReqVO.java index 29e3acdaf4..d4d6e66532 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelExportReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "支付渠道 Excel 导出 Request VO", description = "参数和 PayChannelPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 支付渠道 Excel 导出 Request VO", description = "参数和 PayChannelPageReqVO 是一致的") @Data public class PayChannelExportReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelPageReqVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelPageReqVO.java index 83851f944c..29995d07ab 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelPageReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("支付渠道 分页 Request VO") +@ApiModel("管理后台 - 支付渠道 分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelRespVO.java index 02873b9f52..b2644f4d0e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelRespVO.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; import java.util.*; import io.swagger.annotations.*; -@ApiModel("支付渠道 Response VO") +@ApiModel("管理后台 - 支付渠道 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelUpdateReqVO.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelUpdateReqVO.java index fdefc7badc..c216de9aea 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/channel/vo/PayChannelUpdateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/channel/PayChannelUpdateReqVO.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("支付渠道 更新 Request VO") +@ApiModel("管理后台 - 支付渠道 更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @@ -15,7 +14,7 @@ public class PayChannelUpdateReqVO extends PayChannelBaseVO { @NotNull(message = "商户编号不能为空") private Long id; - @ApiModelProperty(value = "通道配置的json字符串") - @NotBlank(message = "通道配置不能为空") + @ApiModelProperty(value = "渠道配置的json字符串") + @NotBlank(message = "渠道配置不能为空") private String config; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantBaseVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantBaseVO.java index ed7b69a3f8..1052fdd03e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantBaseVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantCreateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantCreateReqVO.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantCreateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantCreateReqVO.java index 2128de88bf..018db180be 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantCreateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantCreateReqVO.java @@ -1,11 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import lombok.*; -import java.util.*; import io.swagger.annotations.*; -import javax.validation.constraints.*; -@ApiModel("支付商户信息创建 Request VO") +@ApiModel("管理后台 - 支付商户信息创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExcelVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExcelVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExcelVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExcelVO.java index cb229fb115..b399a111d7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExcelVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExcelVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExportReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExportReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExportReqVO.java index c6c3222828..680b04b353 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExportReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "支付商户信息 Excel 导出 Request VO", description = "参数和 PayMerchantPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 支付商户信息 Excel 导出 Request VO", description = "参数和 PayMerchantPageReqVO 是一致的") @Data public class PayMerchantExportReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantPageReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantPageReqVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantPageReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantPageReqVO.java index 8a66ac9531..241287c986 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantPageReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import lombok.*; import java.util.*; @@ -8,7 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("支付商户信息分页 Request VO") +@ApiModel("管理后台 - 支付商户信息分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantRespVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantRespVO.java index d5b194359c..a27c591a14 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("支付商户信息 Response VO") +@ApiModel("管理后台 - 支付商户信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @@ -20,11 +20,7 @@ public class PayMerchantRespVO extends PayMerchantBaseVO { @ApiModelProperty(value = "创建时间", required = true) private Date createTime; - /** - * 商户号 - * 例如说,M233666999 - * 只有新增时插入,不允许修改 - */ + @ApiModelProperty(value = "商户号", required = true, example = "M233666999") private String no; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateReqVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateReqVO.java index 031d34fd5d..d270a3d845 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateReqVO.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("支付商户信息更新 Request VO") +@ApiModel("管理后台 - 支付商户信息更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateStatusReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateStatusReqVO.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateStatusReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateStatusReqVO.java index 635876954e..39e26b8b74 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantUpdateStatusReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/merchant/vo/merchant/PayMerchantUpdateStatusReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; +package cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,7 +6,7 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("商户更新状态 Request VO") +@ApiModel("管理后台 - 商户更新状态 Request VO") @Data public class PayMerchantUpdateStatusReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayOrderController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java index 2ac44c66e1..2219204c43 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order; +package cn.iocoder.yudao.module.pay.controller.admin.order; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.*; -import cn.iocoder.yudao.adminserver.modules.pay.convert.order.PayOrderConvert; -import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; +import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayMerchantService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -39,38 +39,18 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -/** - * 支付订单 controller 组件 - * - * @author aquan - */ -@Api(tags = "支付订单") +@Api(tags = "管理后台 - 支付订单") @RestController @RequestMapping("/pay/order") @Validated public class PayOrderController { - /** - * 订单 service 组件 - */ @Resource private PayOrderService orderService; - - /** - * 订单扩展 service 组件 - */ @Resource private PayOrderExtensionService orderExtensionService; - - /** - * 商户 service 组件 - */ @Resource private PayMerchantService merchantService; - - /** - * 应用 service 组件 - */ @Resource private PayAppService appService; @@ -88,6 +68,7 @@ public class PayOrderController { PayAppDO appDO = appService.getApp(order.getAppId()); PayChannelEnum channelEnum = PayChannelEnum.getByCode(order.getChannelCode()); + // TODO @aquan:文案,都是前端 format; PayOrderDetailsRespVO respVO = PayOrderConvert.INSTANCE.orderDetailConvert(order); respVO.setMerchantName(ObjectUtil.isNotNull(merchantDO) ? merchantDO.getName() : "未知商户"); respVO.setAppName(ObjectUtil.isNotNull(appDO) ? appDO.getName() : "未知应用"); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderBaseVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderBaseVO.java similarity index 95% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderBaseVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderBaseVO.java index 320125a403..1064720fba 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderBaseVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,8 +10,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; /** - * 支付订单 - * Base VO,提供给添加、修改、详细的子 VO 使用 + * 支付订单 Base VO,提供给添加、修改、详细的子 VO 使用 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 * * @author aquan diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderDetailsRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderDetailsRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java index d85a9bcb1c..6bf7152b54 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderDetailsRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderDetailsRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,12 +8,7 @@ import lombok.ToString; import java.util.Date; -/** - * 支付订单详细信息,由支付订单和支付订单扩展信息组成 - * - * @author aquan - */ -@ApiModel("支付订单详细信息 Response VO") +@ApiModel("管理后台 - 支付订单详细信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExcelVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExcelVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java index 48d69c4903..992cac2d26 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExcelVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -46,11 +46,11 @@ public class PayOrderExcelVO { @ExcelProperty("渠道手续费,单位:百分比") private String channelFeeRate; - @DictFormat(SysDictTypeConstants.PAY_ORDER_STATUS) + @DictFormat(DictTypeConstants.ORDER_STATUS) @ExcelProperty(value = "支付状态", converter = DictConvert.class) private Integer status; - @DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS) + @DictFormat(DictTypeConstants.ORDER_NOTIFY_STATUS) @ExcelProperty(value = "通知商户支付结果的回调状态", converter = DictConvert.class) private Integer notifyStatus; @@ -75,7 +75,7 @@ public class PayOrderExcelVO { @ExcelProperty("用户 IP") private String userIp; - @DictFormat(SysDictTypeConstants.PAY_ORDER_REFUND_STATUS) + @DictFormat(DictTypeConstants.ORDER_REFUND_STATUS) @ExcelProperty(value = "退款状态", converter = DictConvert.class) private Integer refundStatus; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExportReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExportReqVO.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExportReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExportReqVO.java index 3445c86b99..c079ea144a 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderExportReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,11 +9,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -/** - * 支付订单 Excel 导出 Request VO - * @author aquan - */ -@ApiModel(value = "支付订单 Excel 导出 Request VO", description = "参数和 PayOrderPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 支付订单 Excel 导出 Request VO", description = "参数和 PayOrderPageReqVO 是一致的") @Data public class PayOrderExportReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageItemRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageItemRespVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageItemRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageItemRespVO.java index b24b27a470..3c0b4e6351 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageItemRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,12 +8,7 @@ import lombok.ToString; import java.util.Date; -/** - * 支付订单分页 Request VO - * - * @author aquan - */ -@ApiModel("支付订单分页 Request VO") +@ApiModel("管理后台 - 支付订单分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageReqVO.java similarity index 95% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageReqVO.java index 07fa6a8204..5787ba285a 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderPageReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,12 +12,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -/** - * 支付订单分页 Request VO - * - * @author aquan - */ -@ApiModel("支付订单分页 Request VO") +@ApiModel("管理后台 - 支付订单分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderRespVO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderRespVO.java index c466936350..29d0cb611d 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order; +package cn.iocoder.yudao.module.pay.controller.admin.order.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,12 +8,7 @@ import lombok.ToString; import java.util.Date; -/** - * 支付订单 Response VO - * - * @author aquan - */ -@ApiModel("支付订单 Response VO") +@ApiModel("管理后台 - 支付订单 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayRefundController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/PayRefundController.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayRefundController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/PayRefundController.java index 912d352543..58cb24fa3a 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/PayRefundController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/PayRefundController.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order; +package cn.iocoder.yudao.module.pay.controller.admin.refund; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*; -import cn.iocoder.yudao.adminserver.modules.pay.convert.refund.PayRefundConvert; -import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderService; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayRefundService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; +import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayMerchantService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -39,12 +39,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -/** - * 退款订单 Controller 组件 - * - * @author aquan - */ -@Api(tags = "退款订单") +@Api(tags = "管理后台 - 退款订单") @RestController @RequestMapping("/pay/refund") @Validated @@ -52,26 +47,13 @@ public class PayRefundController { @Resource private PayRefundService refundService; - - /** - * 商户 service 组件 - */ @Resource private PayMerchantService merchantService; - - /** - * 应用 service 组件 - */ @Resource private PayAppService appService; - - /** - * 订单 service 组件 - */ @Resource private PayOrderService orderService; - @GetMapping("/get") @ApiOperation("获得退款订单") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundBaseVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundBaseVO.java similarity index 98% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundBaseVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundBaseVO.java index c8421b0359..594496c773 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundBaseVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundCreateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundCreateReqVO.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundCreateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundCreateReqVO.java index 79b05c6253..cc09111ef0 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundCreateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundCreateReqVO.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import lombok.*; import io.swagger.annotations.*; -@ApiModel("退款订单创建 Request VO") +@ApiModel("管理后台 - 退款订单创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundDetailsRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundDetailsRespVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundDetailsRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundDetailsRespVO.java index d1d6739eea..e8a70ecd85 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundDetailsRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundDetailsRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,7 @@ import lombok.ToString; import javax.validation.constraints.NotNull; import java.util.Date; -/** - * 退款订单详情 Response VO - * - * @author aquan - */ -@ApiModel("退款订单详情 Response VO") +@ApiModel("管理后台 - 退款订单详情 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExcelVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExcelVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java index be90f1a612..c56fb76042 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExcelVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -43,15 +43,15 @@ public class PayRefundExcelVO { @ExcelProperty("异步通知商户地址") private String notifyUrl; - @DictFormat(SysDictTypeConstants.PAY_ORDER_NOTIFY_STATUS) + @DictFormat(DictTypeConstants.ORDER_NOTIFY_STATUS) @ExcelProperty(value = "商户退款结果回调状态", converter = DictConvert.class) private Integer notifyStatus; - @DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_STATUS) + @DictFormat(DictTypeConstants.REFUND_ORDER_STATUS) @ExcelProperty(value = "退款状态", converter = DictConvert.class) private Integer status; - @DictFormat(SysDictTypeConstants.PAY_REFUND_ORDER_TYPE) + @DictFormat(DictTypeConstants.REFUND_ORDER_TYPE) @ExcelProperty(value = "退款类型", converter = DictConvert.class) private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExportReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExportReqVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExportReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExportReqVO.java index 5a0e9c4e01..c0498239ff 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExportReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,7 +9,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "退款订单 Excel 导出 Request VO", description = "参数和 PayRefundPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 退款订单 Excel 导出 Request VO", description = "参数和 PayRefundPageReqVO 是一致的") @Data public class PayRefundExportReqVO { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageItemRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageItemRespVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageItemRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageItemRespVO.java index 69e881bced..03fe650eed 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageItemRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,7 @@ import lombok.ToString; import java.util.Date; -/** - * 退款订单分页查询 Response VO - * @author aquan - */ -@ApiModel("退款订单分页查询 Response VO") +@ApiModel("管理后台 - 退款订单分页查询 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageReqVO.java similarity index 96% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageReqVO.java index 103a7a27c6..78272009f8 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,7 +12,7 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("退款订单分页 Request VO") +@ApiModel("管理后台 - 退款订单分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundRespVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundRespVO.java index 901a0fe85e..97445d77fb 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,7 +8,7 @@ import lombok.ToString; import java.util.Date; -@ApiModel("退款订单 Response VO") +@ApiModel("管理后台 - 退款订单 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundUpdateReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundUpdateReqVO.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundUpdateReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundUpdateReqVO.java index 8cb2dcf67e..b7d5555637 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundUpdateReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundUpdateReqVO.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo; +package cn.iocoder.yudao.module.pay.controller.admin.refund.vo; import lombok.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("退款订单更新 Request VO") +@ApiModel("管理后台 - 退款订单更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java similarity index 69% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java index fb022b106a..e01f7f4f48 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order; +package cn.iocoder.yudao.module.pay.controller.app.order; import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; -import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO; -import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO; +import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; +import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -21,52 +21,52 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Map; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_CHANNEL_CLIENT_NOT_FOUND; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; -@Api(tags = "支付订单") +@Api(tags = "用户 APP - 支付订单") @RestController @RequestMapping("/pay/order") @Validated @Slf4j -public class PayOrderController { +public class AppPayOrderController { @Resource - private PayOrderCoreService payOrderCoreService; + private PayOrderService orderService; @Resource - private PayRefundCoreService payRefundCoreService; + private PayRefundService refundService; @Resource private PayClientFactory payClientFactory; - @PostMapping("/submit") @ApiOperation("提交支付订单") // @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好 - public CommonResult submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) { + public CommonResult submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) { // 获得订单 - PayOrderDO payOrder = payOrderCoreService.getPayOrder(reqVO.getId()); + PayOrderDO payOrder = orderService.getOrder(reqVO.getId()); // 提交支付 PayOrderSubmitReqDTO reqDTO = new PayOrderSubmitReqDTO(); BeanUtil.copyProperties(reqVO, reqDTO, false); reqDTO.setUserIp(getClientIP()); reqDTO.setAppId(payOrder.getAppId()); - PayOrderSubmitRespDTO respDTO = payOrderCoreService.submitPayOrder(reqDTO); + PayOrderSubmitRespDTO respDTO = orderService.submitPayOrder(reqDTO); // 拼接返回 - return success(PayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build()); + return success(AppPayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build()); } // ========== 支付渠道的回调 ========== + // TODO @芋艿:是不是放到 notify 模块更合适 //TODO 芋道源码 换成了统一的地址了 /notify/{channelId},测试通过可以删除 @PostMapping("/notify/wx-pub/{channelId}") @ApiOperation("通知微信公众号支付的结果") public String notifyWxPayOrder(@PathVariable("channelId") Long channelId, @RequestBody String xmlData) throws Exception { - payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().body(xmlData).build()); + orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().body(xmlData).build()); return "success"; } @@ -110,12 +110,12 @@ public class PayOrderController { // 如果是退款,则发起退款通知 if (payClient.isRefundNotify(notifyData)) { - payRefundCoreService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); + refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); return "success"; } // 如果非退款,则发起支付通知 - payOrderCoreService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); + orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); return "success"; } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitReqVO.java similarity index 83% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitReqVO.java index 407edb1717..6834c3838e 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; +package cn.iocoder.yudao.module.pay.controller.app.order.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,10 +9,10 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.Map; -@ApiModel("支付订单提交 Request VO") +@ApiModel("用户 APP - 支付订单提交 Request VO") @Data @Accessors(chain = true) -public class PayOrderSubmitReqVO { +public class AppPayOrderSubmitReqVO { @ApiModelProperty(value = "支付单编号", required = true, example = "1024") @NotNull(message = "支付单编号不能为空") diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitRespVO.java similarity index 69% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitRespVO.java index 907a979467..7fcffd0975 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayOrderSubmitRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/vo/AppPayOrderSubmitRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; +package cn.iocoder.yudao.module.pay.controller.app.order.vo; import io.swagger.annotations.ApiModel; import lombok.AllArgsConstructor; @@ -7,13 +7,13 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -@ApiModel("支付订单提交 Response VO") +@ApiModel("用户 APP - 支付订单提交 Response VO") @Data @Accessors(chain = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class PayOrderSubmitRespVO { +public class AppPayOrderSubmitRespVO { /** * 调用支付渠道的响应结果 diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/package-info.java new file mode 100644 index 0000000000..333cbe6594 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay.controller.app; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/AppPayRefundController.java similarity index 51% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/AppPayRefundController.java index ba62bdd8ab..42fdc5dcb9 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayRefundController.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/AppPayRefundController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order; +package cn.iocoder.yudao.module.pay.controller.app.refund; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundReqVO; -import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayRefundRespVO; -import cn.iocoder.yudao.userserver.modules.pay.convert.order.PayRefundConvert; +import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundReqVO; +import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundRespVO; +import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import cn.iocoder.yudao.module.pay.util.PaySeqUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -19,28 +19,29 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; -@Api(tags = "退款订单") +@Api(tags = "用户 APP - 退款订单") @RestController -@RequestMapping("/pay/order") +@RequestMapping("/pay/refund") @Validated @Slf4j -public class PayRefundController { +public class AppPayRefundController { @Resource - private PayRefundCoreService payRefundCoreService; + private PayRefundService refundService; @PostMapping("/refund") @ApiOperation("提交退款订单") - public CommonResult submitRefundOrder(@RequestBody PayRefundReqVO reqVO){ + public CommonResult submitRefundOrder(@RequestBody AppPayRefundReqVO reqVO){ PayRefundReqDTO req = PayRefundConvert.INSTANCE.convert(reqVO); req.setUserIp(getClientIP()); - //TODO 测试暂时模拟生成商户退款订单 + // TODO 测试暂时模拟生成商户退款订单 if(StrUtil.isEmpty(reqVO.getMerchantRefundId())) { req.setMerchantRefundId(PaySeqUtils.genMerchantRefundNo()); } - return CommonResult.success( PayRefundConvert.INSTANCE.convert(payRefundCoreService.submitRefundOrder(req))); + return success(PayRefundConvert.INSTANCE.convert(refundService.submitRefundOrder(req))); } } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundReqVO.java similarity index 87% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundReqVO.java index 8287ba0360..c810f3829c 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; +package cn.iocoder.yudao.module.pay.controller.app.refund.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; -@ApiModel("退款订单 Req VO") +@ApiModel("用户 APP - 退款订单 Req VO") @Data @NoArgsConstructor @AllArgsConstructor -public class PayRefundReqVO { +public class AppPayRefundReqVO { @ApiModelProperty(value = "支付订单编号自增", required = true, example = "10") @NotEmpty(message = "支付订单编号自增") diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundRespVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundRespVO.java similarity index 51% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundRespVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundRespVO.java index 29059ab285..5342432812 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/vo/PayRefundRespVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/app/refund/vo/AppPayRefundRespVO.java @@ -1,22 +1,22 @@ -package cn.iocoder.yudao.userserver.modules.pay.controller.order.vo; +package cn.iocoder.yudao.module.pay.controller.app.refund.vo; import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -@ApiModel("提交退款订单 Response VO") +@ApiModel("用户 APP - 提交退款订单 Response VO") @Data @Accessors(chain = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class PayRefundRespVO { +public class AppPayRefundRespVO { - /** - * 支付退款单编号, 自增 - */ + @ApiModelProperty(value = "退款订单编号", required = true, example = "10") private Long refundId; + } diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/package-info.java new file mode 100644 index 0000000000..652122752d --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.pay.controller; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java index 15da37cbf0..432699bc2d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/app/PayAppConvert.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java @@ -1,16 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.pay.convert.app; +package cn.iocoder.yudao.module.pay.convert.app; import java.util.*; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.*; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*; /** * 支付应用信息 Convert diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/channel/PayChannelConvert.java similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/channel/PayChannelConvert.java index ee0473c237..2535008ea8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/channel/PayChannelConvert.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/channel/PayChannelConvert.java @@ -1,22 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.pay.convert.channel; +package cn.iocoder.yudao.module.pay.convert.channel; import java.util.*; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExcelVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelUpdateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; -/** - * 支付渠道 - Convert - * - * @author 芋艿 - */ @Mapper public interface PayChannelConvert { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/merchant/PayMerchantConvert.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/merchant/PayMerchantConvert.java similarity index 56% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/merchant/PayMerchantConvert.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/merchant/PayMerchantConvert.java index 9483ff120d..1cb51a2bbf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/merchant/PayMerchantConvert.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/merchant/PayMerchantConvert.java @@ -1,19 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.pay.convert.merchant; +package cn.iocoder.yudao.module.pay.convert.merchant; import java.util.*; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantExcelVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantUpdateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.*; -/** - * 支付商户信息 Convert - * - * @author 芋艿 - */ @Mapper public interface PayMerchantConvert { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/order/PayOrderConvert.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/order/PayOrderConvert.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java index 308298ac68..49df1ea644 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/order/PayOrderConvert.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java @@ -1,12 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.pay.convert.order; +package cn.iocoder.yudao.module.pay.convert.order; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderDetailsRespVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExcelVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderRespVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderDetailsRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExcelVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageItemRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -24,24 +27,10 @@ public interface PayOrderConvert { PayOrderConvert INSTANCE = Mappers.getMapper(PayOrderConvert.class); - - PayOrderRespVO convert(PayOrderDO bean); - /** - * 订单DO 转换为 详细订单 RespVO - * - * @param bean 订单DO - * @return 详细订单 RespVO - */ PayOrderDetailsRespVO orderDetailConvert(PayOrderDO bean); - /** - * 订单扩展DO 转换为 详细订单扩展 RespVO - * - * @param bean 订单扩展DO - * @return 详细订单扩展 RespVO - */ PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean); List convertList(List list); @@ -58,12 +47,6 @@ public interface PayOrderConvert { */ PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean); - /** - * 订单DO 转 订单导出excel VO - * - * @param bean 订单 DO - * @return 订单导出excel VO - */ default PayOrderExcelVO excelConvert(PayOrderDO bean) { if (bean == null) { return null; @@ -101,4 +84,12 @@ public interface PayOrderConvert { return payOrderExcelVO; } + + + PayOrderDO convert(PayOrderCreateReqDTO bean); + + PayOrderExtensionDO convert(PayOrderSubmitReqDTO bean); + + PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean); + } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/package-info.java similarity index 57% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/package-info.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/package-info.java index b10c090290..df43d5ac3e 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/convert/package-info.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/package-info.java @@ -3,4 +3,4 @@ * * 目前使用 MapStruct 框架 */ -package cn.iocoder.yudao.coreservice.modules.pay.convert; +package cn.iocoder.yudao.module.pay.convert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/refund/PayRefundConvert.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/refund/PayRefundConvert.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java index 8f5ee66d31..2e034c63e8 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/refund/PayRefundConvert.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java @@ -1,9 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.pay.convert.refund; +package cn.iocoder.yudao.module.pay.convert.refund; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.*; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.*; +import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundReqVO; +import cn.iocoder.yudao.module.pay.controller.app.refund.vo.AppPayRefundRespVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.math.BigDecimal; @@ -87,4 +94,16 @@ public interface PayRefundConvert { return payRefundExcelVO; } + //TODO 太多需要处理了, 暂时不用 + @Mappings(value = { + @Mapping(source = "amount", target = "payAmount"), + @Mapping(source = "id", target = "orderId"), + @Mapping(target = "status",ignore = true) + }) + PayRefundDO convert(PayOrderDO orderDO); + + PayRefundReqDTO convert(AppPayRefundReqVO bean); + + AppPayRefundRespVO convert(PayRefundRespDTO bean); + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md similarity index 100% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayAppDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayAppDO.java similarity index 94% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayAppDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayAppDO.java index acc849cbc6..371a92b399 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayAppDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayAppDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant; +package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java similarity index 95% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java index 5275dd4288..a670db4634 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant; +package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayMerchantDO.java similarity index 94% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayMerchantDO.java index a0c72b9ec0..ebd735b039 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayMerchantDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayMerchantDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant; +package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java similarity index 86% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index 85626006cf..92ecc39e63 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify; +package cn.iocoder.yudao.module.pay.dal.dataobject.notify; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java similarity index 78% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyTaskDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 3d10ac83a4..3884f152fc 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify; +package cn.iocoder.yudao.module.pay.dal.dataobject.notify; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java similarity index 84% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java index 65cf94bf24..931b856519 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order; +package cn.iocoder.yudao.module.pay.dal.dataobject.order; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderExtensionDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java similarity index 89% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderExtensionDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java index 5a6b8431a4..8606e082bb 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayOrderExtensionDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderExtensionDO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order; +package cn.iocoder.yudao.module.pay.dal.dataobject.order; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayRefundDO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java similarity index 90% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayRefundDO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java index fc897a5e08..f5e3a1f7ca 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/order/PayRefundDO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java @@ -1,10 +1,11 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order; +package cn.iocoder.yudao.module.pay.dal.dataobject.refund; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayAppMapper.java similarity index 66% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayAppMapper.java index c6e3b38e93..a8801d38c1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayAppMapper.java @@ -1,32 +1,20 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app; +package cn.iocoder.yudao.module.pay.dal.mysql.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; import java.util.List; -/** - * 支付应用信息 Mapper - * - * @author aquan - */ @Mapper public interface PayAppMapper extends BaseMapperX { - /** - * 分页查询 - * - * @param reqVO 支付应用信息分页查询条件 - * @param merchantIds 商户 ID 集合 - * @return 支付应用信息 - */ default PageResult selectPage(PayAppPageReqVO reqVO, Collection merchantIds) { return selectPage(reqVO, new QueryWrapperX() .likeIfPresent("name", reqVO.getName()) @@ -39,13 +27,6 @@ public interface PayAppMapper extends BaseMapperX { .orderByDesc("id")); } - /** - * 列表查询 - * - * @param reqVO 支付应用信息 Excel 导出查询条件 - * @param merchantIds 商户 ID 集合 - * @return 支付应用信息 - */ default List selectList(PayAppExportReqVO reqVO, Collection merchantIds) { return selectList(new QueryWrapperX() .likeIfPresent("name", reqVO.getName()) @@ -58,24 +39,13 @@ public interface PayAppMapper extends BaseMapperX { .orderByDesc("id")); } - /** - * 根据 商户 ID 查询支付应用信息 - * - * @param merchantId 商户 ID - * @return 支付应用信息列表 - */ - default List getListByMerchantId(String merchantId) { + default List getListByMerchantId(Long merchantId) { return selectList(new LambdaQueryWrapper() .select(PayAppDO::getId, PayAppDO::getName) .eq(PayAppDO::getMerchantId, merchantId)); } - /** - * 根据商户号统计存在的支付应用数量 - * - * @param merchantId 商户 ID - * @return 支付应用数量 - */ + // TODO @aquan:方法名补充 ByMerchantId default Long selectCount(Long merchantId) { return selectCount(new LambdaQueryWrapper().eq(PayAppDO::getMerchantId, merchantId)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapper.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapper.java index 54a4829a99..c1871531e4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapper.java @@ -1,26 +1,29 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel; +package cn.iocoder.yudao.module.pay.dal.mysql.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; import java.util.Collection; +import java.util.Date; import java.util.List; -/** - * 支付渠道 - Mapper - * - * @author 芋艿 - */ @Mapper public interface PayChannelMapper extends BaseMapperX { + default PayChannelDO selectByAppIdAndCode(Long appId, String code) { + return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code); + } + + @Select("SELECT id FROM pay_channel WHERE update_time > #{maxUpdateTime} LIMIT 1") + Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); + default PageResult selectPage(PayChannelPageReqVO reqVO) { return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("code", reqVO.getCode()) @@ -48,11 +51,11 @@ public interface PayChannelMapper extends BaseMapperX { } /** - * 根据条件获取通道数量 + * 根据条件获取渠道数量 * * @param merchantId 商户编号 * @param appid 应用编号 - * @param code 通道编码 + * @param code 渠道编码 * @return 数量 */ default Integer selectCount(Long merchantId, Long appid, String code) { @@ -63,11 +66,11 @@ public interface PayChannelMapper extends BaseMapperX { } /** - * 根据条件获取通道 + * 根据条件获取渠道 * * @param merchantId 商户编号 - * @param appid 应用编号 - * @param code 通道编码 + * @param appid 应用编号 // TODO @aquan:appid =》appId + * @param code 渠道编码 * @return 数量 */ default PayChannelDO selectOne(Long merchantId, Long appid, String code) { @@ -78,6 +81,7 @@ public interface PayChannelMapper extends BaseMapperX { )); } + // TODO @aquan:select 命名 /** * 根据支付应用ID集合获得支付渠道列表 * @@ -88,4 +92,5 @@ public interface PayChannelMapper extends BaseMapperX { return this.selectList(new QueryWrapper().lambda() .in(PayChannelDO::getAppId, appIds)); } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/merchant/PayMerchantMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayMerchantMapper.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/merchant/PayMerchantMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayMerchantMapper.java index f143b18578..050302b4c4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/merchant/PayMerchantMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayMerchantMapper.java @@ -1,20 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant; +package cn.iocoder.yudao.module.pay.dal.mysql.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; -/** - * 支付商户信息 Mapper - * - * @author 芋艿 - */ @Mapper public interface PayMerchantMapper extends BaseMapperX { diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java similarity index 56% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java index e3f90d614f..c956219339 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogCoreMapper.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify; +package cn.iocoder.yudao.module.pay.dal.mysql.notify; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java similarity index 79% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java index 276c6710b6..1107a19f46 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskCoreMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify; +package cn.iocoder.yudao.module.pay.dal.mysql.notify; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderExtensionCoreMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java old mode 100644 new mode 100755 similarity index 70% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderExtensionCoreMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java index 08c95cea67..a8918f441c --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/order/PayOrderExtensionCoreMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order; +package cn.iocoder.yudao.module.pay.dal.mysql.order; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @Mapper -public interface PayOrderExtensionCoreMapper extends BaseMapperX { +public interface PayOrderExtensionMapper extends BaseMapperX { default PayOrderExtensionDO selectByNo(String no) { return selectOne(PayOrderExtensionDO::getNo, no); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java index 1fb9e870af..4ff345dae5 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java @@ -1,22 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; +package cn.iocoder.yudao.module.pay.dal.mysql.order; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; import java.util.List; -/** - * 支付订单 Mapper 组件 - * - * @author aquan - */ @Mapper public interface PayOrderMapper extends BaseMapperX { @@ -50,12 +46,6 @@ public interface PayOrderMapper extends BaseMapperX { .orderByDesc("id")); } - /** - * 根据订单 ID 集合查询订单商品名称 - * - * @param idList 订单 ID 集合 - * @return 只包含商品名称和标题的订单集合对象 - */ default List findByIdListQueryOrderSubject(Collection idList) { return selectList(new LambdaQueryWrapper() .select(PayOrderDO::getId, PayOrderDO::getSubject) @@ -70,10 +60,19 @@ public interface PayOrderMapper extends BaseMapperX { * @return 条数 */ default Long selectCount(Long appId, Integer status) { - return selectCount(new LambdaQueryWrapper() .eq(PayOrderDO::getAppId, appId) .in(PayOrderDO::getStatus, status)); } + default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) { + return selectOne(new QueryWrapper().eq("app_id", appId) + .eq("merchant_order_id", merchantOrderId)); + } + + default int updateByIdAndStatus(Long id, Integer status, PayOrderDO update) { + return update(update, new QueryWrapper() + .eq("id", id).eq("status", status)); + } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayRefundMapper.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayRefundMapper.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java index 2fd3f22996..ba8f521e9d 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayRefundMapper.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java @@ -1,21 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order; +package cn.iocoder.yudao.module.pay.dal.mysql.refund; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; -/** - * 退款订单 Mapper - * - * @author aquan - */ @Mapper public interface PayRefundMapper extends BaseMapperX { @@ -45,17 +40,18 @@ public interface PayRefundMapper extends BaseMapperX { .orderByDesc("id")); } - /** - * 查询符合的订单数量 - * - * @param appId 应用编号 - * @param status 订单状态 - * @return 条数 - */ default Long selectCount(Long appId, Integer status) { return selectCount(new LambdaQueryWrapper() .eq(PayRefundDO::getAppId, appId) .eq(PayRefundDO::getStatus, status)); } + + default PayRefundDO selectByReqNo(String reqNo) { + return selectOne("req_no", reqNo); + } + + default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){ + return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo); + } } diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java new file mode 100644 index 0000000000..4f5aaf750a --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.pay.dal.redis; + +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; +import org.redisson.api.RLock; + +/** + * 支付 Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁", + "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类 + RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/notify/PayNotifyLockCoreRedisDAO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/notify/PayNotifyLockRedisDAO.java similarity index 79% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/notify/PayNotifyLockCoreRedisDAO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/notify/PayNotifyLockRedisDAO.java index 5ce6b44b32..2d1f13f163 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/dal/redis/notify/PayNotifyLockCoreRedisDAO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/notify/PayNotifyLockRedisDAO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify; +package cn.iocoder.yudao.module.pay.dal.redis.notify; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; @@ -7,7 +7,7 @@ import org.springframework.stereotype.Repository; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; -import static cn.iocoder.yudao.coreservice.modules.pay.dal.redis.PayRedisKeyCoreConstants.PAY_NOTIFY_LOCK; +import static cn.iocoder.yudao.module.pay.dal.redis.RedisKeyConstants.PAY_NOTIFY_LOCK; /** * 支付通知的锁 Redis DAO @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.coreservice.modules.pay.dal.redis.PayRedisKeyCore * @author 芋道源码 */ @Repository -public class PayNotifyLockCoreRedisDAO { +public class PayNotifyLockRedisDAO { @Resource private RedissonClient redissonClient; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyStatusEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyStatusEnum.java similarity index 89% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyStatusEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyStatusEnum.java index 2c3c6b5921..d1b7c1015b 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.notify; +package cn.iocoder.yudao.module.pay.enums.notify; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyTypeEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java similarity index 85% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyTypeEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java index a501bc55f9..8c259d93c1 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/notify/PayNotifyTypeEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/notify/PayNotifyTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.notify; +package cn.iocoder.yudao.module.pay.enums.notify; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderNotifyStatusEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderNotifyStatusEnum.java similarity index 89% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderNotifyStatusEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderNotifyStatusEnum.java index 4bda485d2a..b7161a9f4e 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderNotifyStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderNotifyStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.order; +package cn.iocoder.yudao.module.pay.enums.order; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderStatusEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java similarity index 90% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderStatusEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java index b61c0400ce..ab542a97c3 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayOrderStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.order; +package cn.iocoder.yudao.module.pay.enums.order; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundStatusEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java similarity index 83% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundStatusEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java index 2a28ae9fc5..390804dd3a 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.order; +package cn.iocoder.yudao.module.pay.enums.refund; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundTypeEnum.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundTypeEnum.java similarity index 89% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundTypeEnum.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundTypeEnum.java index ba7ee2fcc8..5fb10a399d 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/order/PayRefundTypeEnum.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.enums.order; +package cn.iocoder.yudao.module.pay.enums.refund; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/notify/PayNotifyJob.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/notify/PayNotifyJob.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java index 58685f1b56..820bca4718 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/job/notify/PayNotifyJob.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.pay.job.notify; +package cn.iocoder.yudao.module.pay.job.notify; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -18,7 +18,7 @@ import javax.annotation.Resource; public class PayNotifyJob implements JobHandler { @Resource - private PayNotifyCoreService payNotifyCoreService; + private PayNotifyService payNotifyCoreService; @Override public String execute(String param) throws Exception { diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/package-info.java new file mode 100644 index 0000000000..c45bf497fb --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/job/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay.job; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/package-info.java new file mode 100644 index 0000000000..1421e4e654 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/package-info.java @@ -0,0 +1,10 @@ +/** + * pay 模块,我们放支付业务,提供业务的支付能力。 + * 例如说:商户、应用、支付、退款等等 + * + * 1. Controller URL:以 /member/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 member_ 开头,方便在数据库中区分 + * + * 注意,由于 Pay 模块和 Trade 模块,容易重名,所以类名都加载 Pay 的前缀~ + */ +package cn.iocoder.yudao.module.pay; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppService.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppService.java index da83ca825f..feb03e0a95 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppService.java @@ -1,12 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.app; +package cn.iocoder.yudao.module.pay.service.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppUpdateReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; import javax.validation.Valid; import java.util.Collection; @@ -88,7 +89,7 @@ public interface PayAppService { * @param merchantId 商户 ID * @return 支付应用信息列表 */ - List getListByMerchantId(String merchantId); + List getListByMerchantId(Long merchantId); /** * 获得指定编号的商户 Map @@ -100,4 +101,16 @@ public interface PayAppService { List list = this.getAppList(appIdList); return CollectionUtils.convertMap(list, PayAppDO::getId); } + + + /** + * 支付应用的合法性 + * + * 如果不合法,抛出 {@link ServiceException} 业务异常 + * + * @param id 应用编号 + * @return 应用信息 + */ + PayAppDO validPayApp(Long id); + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceImpl.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceImpl.java index bb6e765b3b..1a7e2bebfd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceImpl.java @@ -1,23 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.app.impl; +package cn.iocoder.yudao.module.pay.service.merchant; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppUpdateReqVO; +import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayAppMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayMerchantMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import com.google.common.annotations.VisibleForTesting; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -25,9 +26,9 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; /** * 支付应用信息 Service 实现类 @@ -40,17 +41,14 @@ public class PayAppServiceImpl implements PayAppService { @Resource private PayAppMapper appMapper; - + // TODO @aquan:使用对方的 Service。模块与模块之间,避免直接调用对方的 mapper @Resource private PayMerchantMapper merchantMapper; - @Resource private PayOrderMapper orderMapper; - @Resource private PayRefundMapper refundMapper; - @Override public Long createApp(PayAppCreateReqVO createReqVO) { // 插入 @@ -126,12 +124,6 @@ public class PayAppServiceImpl implements PayAppService { return convertSet(merchantMapper.getMerchantListByName(merchantName), PayMerchantDO::getId); } - /** - * 修改应用信息状态 - * - * @param id 应用编号 - * @param status 状态{@link CommonStatusEnum} - */ @Override public void updateAppStatus(Long id, Integer status) { // 校验商户存在 @@ -143,14 +135,8 @@ public class PayAppServiceImpl implements PayAppService { appMapper.updateById(app); } - /** - * 根据商户 ID 获得支付应用信息列表, - * - * @param merchantId 商户 ID - * @return 支付应用信息列表 - */ @Override - public List getListByMerchantId(String merchantId) { + public List getListByMerchantId(Long merchantId) { return appMapper.getListByMerchantId(merchantId); } @@ -186,4 +172,18 @@ public class PayAppServiceImpl implements PayAppService { } } + @Override + public PayAppDO validPayApp(Long id) { + PayAppDO app = appMapper.selectById(id); + // 校验是否存在 + if (app == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_APP_NOT_FOUND); + } + // 校验是否禁用 + if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_APP_IS_DISABLE); + } + return app; + } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java similarity index 59% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java index 1eeb567dd4..3907b0eca6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java @@ -1,9 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.channel; +package cn.iocoder.yudao.module.pay.service.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelUpdateReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.springframework.web.multipart.MultipartFile; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; import javax.validation.Valid; import java.util.Collection; @@ -16,6 +19,11 @@ import java.util.List; */ public interface PayChannelService { + /** + * 初始化支付客户端 + */ + void initPayClients(); + /** * 创建支付渠道 * @@ -47,8 +55,7 @@ public interface PayChannelService { PayChannelDO getChannel(Long id); /** - * 获得支付渠道 - * 列表 + * 获得支付渠道列表 * * @param ids 编号 * @return 支付渠道 @@ -57,8 +64,7 @@ public interface PayChannelService { List getChannelList(Collection ids); /** - * 获得支付渠道 - * 分页 + * 获得支付渠道分页 * * @param pageReqVO 分页查询 * @return 支付渠道 @@ -84,24 +90,44 @@ public interface PayChannelService { List getChannelListByAppIds(Collection appIds); /** - * 根据条件获取通道数量 + * 根据条件获取渠道数量 * * @param merchantId 商户编号 * @param appid 应用编号 - * @param code 通道编码 + * @param code 渠道编码 * @return 数量 */ Integer getChannelCountByConditions(Long merchantId, Long appid, String code); /** - * 根据条件获取通道 + * 根据条件获取渠道 * * @param merchantId 商户编号 * @param appid 应用编号 - * @param code 通道编码 + * @param code 渠道编码 * @return 数量 */ PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code); + /** + * 支付渠道的合法性 + * + * 如果不合法,抛出 {@link ServiceException} 业务异常 + * + * @param id 渠道编号 + * @return 渠道信息 + */ + PayChannelDO validPayChannel(Long id); + + /** + * 支付渠道的合法性 + * + * 如果不合法,抛出 {@link ServiceException} 业务异常 + * + * @param appId 应用编号 + * @param code 支付渠道 + * @return 渠道信息 + */ + PayChannelDO validPayChannel(Long appId, String code); } diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java new file mode 100644 index 0000000000..68b6ff10db --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java @@ -0,0 +1,250 @@ +package cn.iocoder.yudao.module.pay.service.merchant; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelUpdateReqVO; +import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; +import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.validation.Validator; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; + +/** + * 支付渠道 Service 实现类 + * + * @author aquan + */ +@Service +@Slf4j +@Validated +public class PayChannelServiceImpl implements PayChannelService { + + /** + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 + */ + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; + + /** + * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private volatile Date maxUpdateTime; + + @Resource + private PayClientFactory payClientFactory; + + @Resource + private PayChannelMapper channelMapper; + + @Resource + private Validator validator; + + @Override + @PostConstruct + public void initPayClients() { + // 获取支付渠道,如果有更新 + List payChannels = this.loadPayChannelIfUpdate(maxUpdateTime); + if (CollUtil.isEmpty(payChannels)) { + return; + } + + // 创建或更新支付 Client + payChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), + payChannel.getCode(), payChannel.getConfig())); + + // 写入缓存 + assert payChannels.size() > 0; // 断言,避免告警 + maxUpdateTime = payChannels.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); + log.info("[initPayClients][初始化 PayChannel 数量为 {}]", payChannels.size()); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initPayClients(); + } + + /** + * 如果支付渠道发生变化,从数据库中获取最新的全量支付渠道。 + * 如果未发生变化,则返回空 + * + * @param maxUpdateTime 当前支付渠道的最大更新时间 + * @return 支付渠道列表 + */ + private List loadPayChannelIfUpdate(Date maxUpdateTime) { + // 第一步,判断是否要更新。 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 + log.info("[loadPayChannelIfUpdate][首次加载全量支付渠道]"); + } else { // 判断数据库中是否有更新的支付渠道 + if (channelMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) { + return null; + } + log.info("[loadPayChannelIfUpdate][增量加载全量支付渠道]"); + } + // 第二步,如果有更新,则从数据库加载所有支付渠道 + return channelMapper.selectList(); + } + + @Override + public Long createChannel(PayChannelCreateReqVO reqVO) { + // 断言是否有重复的 + PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); + if (ObjectUtil.isNotNull(channelDO)) { + throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR); + } + + // 新增渠道 + PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); + settingConfigAndCheckParam(channel, reqVO.getConfig()); + channelMapper.insert(channel); + return channel.getId(); + } + + @Override + public void updateChannel(PayChannelUpdateReqVO updateReqVO) { + // 校验存在 + this.validateChannelExists(updateReqVO.getId()); + // 更新 + PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO); + settingConfigAndCheckParam(channel, updateReqVO.getConfig()); + channelMapper.updateById(channel); + } + + @Override + public void deleteChannel(Long id) { + // 校验存在 + this.validateChannelExists(id); + // 删除 + channelMapper.deleteById(id); + } + + private void validateChannelExists(Long id) { + if (channelMapper.selectById(id) == null) { + throw exception(CHANNEL_NOT_EXISTS); + } + } + + @Override + public PayChannelDO getChannel(Long id) { + return channelMapper.selectById(id); + } + + @Override + public List getChannelList(Collection ids) { + return channelMapper.selectBatchIds(ids); + } + + @Override + public PageResult getChannelPage(PayChannelPageReqVO pageReqVO) { + return channelMapper.selectPage(pageReqVO); + } + + @Override + public List getChannelList(PayChannelExportReqVO exportReqVO) { + return channelMapper.selectList(exportReqVO); + } + + /** + * 根据支付应用ID集合获得支付渠道列表 + * + * @param appIds 应用编号集合 + * @return 支付渠道列表 + */ + @Override + public List getChannelListByAppIds(Collection appIds) { + return channelMapper.getChannelListByAppIds(appIds); + } + + + /** + * 根据条件获取渠道数量 + * + * @param merchantId 商户编号 + * @param appid 应用编号 + * @param code 渠道编码 + * @return 数量 + */ + @Override + public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) { + return this.channelMapper.selectCount(merchantId, appid, code); + } + + /** + * 根据条件获取渠道 + * + * @param merchantId 商户编号 + * @param appid 应用编号 + * @param code 渠道编码 + * @return 数量 + */ + @Override + public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) { + return this.channelMapper.selectOne(merchantId, appid, code); + } + + /** + * 设置渠道配置以及参数校验 + * + * @param channel 渠道 + * @param configStr 配置 + */ + private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { + // 得到这个渠道是微信的还是支付宝的 + Class payClass = PayChannelEnum.getByCode(channel.getCode()).getConfigClass(); + if (ObjectUtil.isNull(payClass)) { + throw exception(CHANNEL_NOT_EXISTS); + } + PayClientConfig config = JSONUtil.toBean(configStr, payClass); + + // 验证参数 + config.validate(validator); + channel.setConfig(config); + } + + @Override + public PayChannelDO validPayChannel(Long id) { + PayChannelDO channel = channelMapper.selectById(id); + this.validPayChannel(channel); + return channel; + } + + @Override + public PayChannelDO validPayChannel(Long appId, String code) { + PayChannelDO channel = channelMapper.selectByAppIdAndCode(appId, code); + this.validPayChannel(channel); + return channel; + } + + private void validPayChannel(PayChannelDO channel) { + if (channel == null) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_NOT_FOUND); + } + if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_IS_DISABLE); + } + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantService.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantService.java index b8e74dd757..40f02b99cb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantService.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.merchant; +package cn.iocoder.yudao.module.pay.service.merchant; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantUpdateReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; import javax.validation.Valid; import java.util.Collection; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceImpl.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceImpl.java index b80132a1f1..c14a87d7d7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceImpl.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl; +package cn.iocoder.yudao.module.pay.service.merchant; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantUpdateReqVO; +import cn.iocoder.yudao.module.pay.convert.merchant.PayMerchantConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayAppMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayMerchantMapper; import cn.iocoder.yudao.framework.common.pojo.PageResult; import com.google.common.annotations.VisibleForTesting; import org.springframework.stereotype.Service; @@ -21,9 +20,8 @@ import java.time.LocalDateTime; import java.util.Collection; import java.util.List; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_EXIST_APP_CANT_DELETE; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; /** * 支付商户信息 Service 实现类 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/PayNotifyCoreService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java similarity index 66% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/PayNotifyCoreService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java index 4683757099..92358e4713 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/PayNotifyCoreService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java @@ -1,15 +1,15 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify; +package cn.iocoder.yudao.module.pay.service.notify; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; import javax.validation.Valid; /** - * 支付通知 Core Service 接口 + * 支付通知 Service 接口 * * @author 芋道源码 */ -public interface PayNotifyCoreService { +public interface PayNotifyService { /** * 创建支付通知任务 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java similarity index 77% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java index dff6de7fc6..1d5091a5bc 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/impl/PayNotifyCoreServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java @@ -1,25 +1,25 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify.impl; +package cn.iocoder.yudao.module.pay.service.notify; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.http.HttpUtil; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyLogDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyLogCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyTaskCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.redis.notify.PayNotifyLockCoreRedisDAO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayNotifyOrderReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayRefundOrderReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogCoreMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskCoreMapper; +import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; +import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO; +import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; @@ -36,10 +36,6 @@ import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.SECOND_MILLIS; -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; - /** * 支付通知 Core Service 实现类 * @@ -48,7 +44,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString @Service @Valid @Slf4j -public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { +public class PayNotifyServiceImpl implements PayNotifyService { /** * 通知超时时间,单位:秒 @@ -57,11 +53,14 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { /** * {@link #NOTIFY_TIMEOUT} 的毫秒 */ - public static final long NOTIFY_TIMEOUT_MILLIS = 120 * SECOND_MILLIS; + public static final long NOTIFY_TIMEOUT_MILLIS = 120 * DateUtils.SECOND_MILLIS; @Resource @Lazy // 循环依赖,避免报错 - private PayOrderCoreService payOrderCoreService; + private PayOrderService orderService; + @Resource + @Lazy // 循环依赖,避免报错 + private PayRefundService refundService; @Resource private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper; @@ -72,14 +71,11 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿:未来提供独立的线程池 @Resource - private PayNotifyLockCoreRedisDAO payNotifyLockCoreRedisDAO; - - @Resource - private PayRefundCoreMapper payRefundCoreMapper; + private PayNotifyLockRedisDAO payNotifyLockCoreRedisDAO; @Resource @Lazy // 循环依赖(自己依赖自己),避免报错 - private PayNotifyCoreServiceImpl self; + private PayNotifyServiceImpl self; @Override public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) { @@ -89,12 +85,11 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { .setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1); // 补充 merchantId + appId + notifyUrl 字段 if (Objects.equals(task.getType(), PayNotifyTypeEnum.ORDER.getType())) { - PayOrderDO order = payOrderCoreService.getPayOrder(task.getDataId()); // 不进行非空判断,有问题直接异常 + PayOrderDO order = orderService.getOrder(task.getDataId()); // 不进行非空判断,有问题直接异常 task.setMerchantId(order.getMerchantId()).setAppId(order.getAppId()). setMerchantOrderId(order.getMerchantOrderId()).setNotifyUrl(order.getNotifyUrl()); } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) { - // TODO 芋艿,需要实现下哈 - PayRefundDO refundDO = payRefundCoreMapper.selectById(task.getDataId()); + PayRefundDO refundDO = refundService.getRefund(task.getDataId()); task.setMerchantId(refundDO.getMerchantId()).setAppId(refundDO.getAppId()) .setMerchantOrderId(refundDO.getMerchantOrderId()).setNotifyUrl(refundDO.getNotifyUrl()); } @@ -169,7 +164,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 PayNotifyTaskDO dbTask = payNotifyTaskCoreMapper.selectById(task.getId()); if (DateUtils.afterNow(dbTask.getNextNotifyTime())) { - log.info("[executeNotify][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", toJsonString(dbTask)); + log.info("[executeNotify][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", JsonUtils.toJsonString(dbTask)); return; } @@ -193,7 +188,7 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { Integer newStatus = this.processNotifyResult(task, invokeResult, invokeException); // 记录 PayNotifyLog 日志 - String response = invokeException != null ? getRootCauseMessage(invokeException) : toJsonString(invokeResult); + String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : JsonUtils.toJsonString(invokeResult); payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); } @@ -214,10 +209,10 @@ public class PayNotifyCoreServiceImpl implements PayNotifyCoreService { request = PayRefundOrderReqVO.builder().merchantOrderId(task.getMerchantOrderId()) .payRefundId(task.getDataId()).build(); } else { - throw new RuntimeException("未知的通知任务类型:" + toJsonString(task)); + throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task)); } // 请求地址 - String response = HttpUtil.post(task.getNotifyUrl(), toJsonString(request), + String response = HttpUtil.post(task.getNotifyUrl(), JsonUtils.toJsonString(request), (int) NOTIFY_TIMEOUT_MILLIS); // 解析结果 return JsonUtils.parseObject(response, CommonResult.class); diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java similarity index 88% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java index 8d40ffb91e..49d570d4e6 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto; +package cn.iocoder.yudao.module.pay.service.notify.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayNotifyOrderReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java similarity index 92% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayNotifyOrderReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java index 94b1fec563..d4f6c1eaec 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayNotifyOrderReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo; +package cn.iocoder.yudao.module.pay.service.notify.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayRefundOrderReqVO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java similarity index 93% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayRefundOrderReqVO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java index d436d759b7..978283d1b4 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/notify/vo/PayRefundOrderReqVO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo; +package cn.iocoder.yudao.module.pay.service.notify.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java new file mode 100644 index 0000000000..fb006dd689 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java @@ -0,0 +1,6 @@ +/** + * 这里的 VO 包有点特殊,是提供给接入支付模块的业务,提供回调接口时,可以直接使用 VO + * + * 例如说,支付单的回调,使用 TODO 芋艿:想下怎么优化下 + */ +package cn.iocoder.yudao.module.pay.service.notify.vo; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderExtensionService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionService.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderExtensionService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionService.java index a139956b4e..f707bc0dfc 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderExtensionService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionService.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order; +package cn.iocoder.yudao.module.pay.service.order; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; import java.util.Collection; import java.util.List; @@ -32,7 +32,6 @@ public interface PayOrderExtensionService { */ List getOrderExtensionList(Collection ids); - /** * 根据订单成功的 扩展订单ID 查询所有的扩展订单转 成 map 返回 * @@ -40,9 +39,8 @@ public interface PayOrderExtensionService { * @return 订单扩展 map 集合 */ default Map getOrderExtensionMap(Collection successExtensionIdList) { - List list = this.getOrderExtensionList(successExtensionIdList); + List list = getOrderExtensionList(successExtensionIdList); return CollectionUtils.convertMap(list, PayOrderExtensionDO::getId); } - } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderExtensionServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionServiceImpl.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderExtensionServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionServiceImpl.java index 1972756571..a97e3beff9 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/impl/PayOrderExtensionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderExtensionServiceImpl.java @@ -1,8 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order.impl; +package cn.iocoder.yudao.module.pay.service.order; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderExtensionMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.PayOrderExtensionService; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderService.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index ebdf7e3401..40ed287fcc 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -1,11 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order; +package cn.iocoder.yudao.module.pay.service.order; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; @@ -64,4 +69,29 @@ public interface PayOrderService { return CollectionUtils.convertMap(list, PayOrderDO::getId); } + /** + * 创建支付单 + * + * @param reqDTO 创建请求 + * @return 支付单编号 + */ + Long createPayOrder(@Valid PayOrderCreateReqDTO reqDTO); + + /** + * 提交支付 + * 此时,会发起支付渠道的调用 + * + * @param reqDTO 提交请求 + * @return 提交结果 + */ + PayOrderSubmitRespDTO submitPayOrder(@Valid PayOrderSubmitReqDTO reqDTO); + + /** + * 通知支付单成功 + * + * @param channelId 渠道编号 + * @param notifyData 通知数据 + */ + void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception; + } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayOrderCoreServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java old mode 100644 new mode 100755 similarity index 63% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayOrderCoreServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 50229b140d..72bfac0234 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayOrderCoreServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -1,25 +1,8 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl; +package cn.iocoder.yudao.module.pay.service.order; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayOrderCoreConvert; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensionCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.pay.config.PayProperties; @@ -28,58 +11,94 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; +import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderExtensionMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; +import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; +import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.Collection; import java.util.Date; +import java.util.List; import java.util.Objects; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - /** - * 支付订单 Core Service 实现类 + * 支付订单 Service 实现类 * - * @author 芋道源码 + * @author aquan */ @Service @Validated @Slf4j -public class PayOrderCoreServiceImpl implements PayOrderCoreService { +public class PayOrderServiceImpl implements PayOrderService { @Resource private PayProperties payProperties; - @Resource - private PayAppCoreService payAppCoreService; - @Resource - private PayChannelCoreService payChannelCoreService; - @Resource - private PayNotifyCoreService payNotifyCoreService; - @Resource private PayClientFactory payClientFactory; @Resource - private PayOrderCoreMapper payOrderCoreMapper; + private PayOrderMapper orderMapper; @Resource - private PayOrderExtensionCoreMapper payOrderExtensionCoreMapper; + private PayOrderExtensionMapper orderExtensionMapper; + + @Resource + private PayAppService appService; + @Resource + private PayChannelService channelService; + @Resource + private PayNotifyService notifyService; @Override - public PayOrderDO getPayOrder(Long id) { - return payOrderCoreMapper.selectById(id); + public PayOrderDO getOrder(Long id) { + return orderMapper.selectById(id); + } + + @Override + public PageResult getOrderPage(PayOrderPageReqVO pageReqVO) { + return orderMapper.selectPage(pageReqVO); + } + + @Override + public List getOrderList(PayOrderExportReqVO exportReqVO) { + return orderMapper.selectList(exportReqVO); + } + + // TODO @艿艿:需要优化。不确定这个方法的作用 + @Override + public List getOrderSubjectList(Collection idList) { + return orderMapper.findByIdListQueryOrderSubject(idList); } @Override public Long createPayOrder(PayOrderCreateReqDTO reqDTO) { // 校验 App - PayAppDO app = payAppCoreService.validPayApp(reqDTO.getAppId()); + PayAppDO app = appService.validPayApp(reqDTO.getAppId()); // 查询对应的支付交易单是否已经存在。如果是,则直接返回 - PayOrderDO order = payOrderCoreMapper.selectByAppIdAndMerchantOrderId( + PayOrderDO order = orderMapper.selectByAppIdAndMerchantOrderId( reqDTO.getAppId(), reqDTO.getMerchantOrderId()); if (order != null) { log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(), @@ -88,7 +107,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { } // 创建支付交易单 - order = PayOrderCoreConvert.INSTANCE.convert(reqDTO) + order = PayOrderConvert.INSTANCE.convert(reqDTO) .setMerchantId(app.getMerchantId()).setAppId(app.getId()); // 商户相关字段 order.setNotifyUrl(app.getPayNotifyUrl()) @@ -99,7 +118,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { // todo @芋艿 创建支付的订单的退款状态枚举是不是有问题,应该是 PayRefundTypeEnum 吧 您这填写的是 PayOrderNotifyStatusEnum 回调状态枚举 order.setRefundStatus(PayOrderNotifyStatusEnum.NO.getStatus()) .setRefundTimes(0).setRefundAmount(0L); - payOrderCoreMapper.insert(order); + orderMapper.insert(order); // 最终返回 return order.getId(); } @@ -107,34 +126,34 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @Override public PayOrderSubmitRespDTO submitPayOrder(PayOrderSubmitReqDTO reqDTO) { // 校验 App - payAppCoreService.validPayApp(reqDTO.getAppId()); + appService.validPayApp(reqDTO.getAppId()); // 校验支付渠道是否有效 - PayChannelDO channel = payChannelCoreService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode()); + PayChannelDO channel = channelService.validPayChannel(reqDTO.getAppId(), reqDTO.getChannelCode()); // 校验支付客户端是否正确初始化 PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[submitPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } // 获得 PayOrderDO ,并校验其是否存在 - PayOrderDO order = payOrderCoreMapper.selectById(reqDTO.getId()); + PayOrderDO order = orderMapper.selectById(reqDTO.getId()); if (order == null || !Objects.equals(order.getAppId(), reqDTO.getAppId())) { // 是否存在 - throw exception(PAY_ORDER_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); } // 插入 PayOrderExtensionDO - PayOrderExtensionDO orderExtension = PayOrderCoreConvert.INSTANCE.convert(reqDTO) + PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqDTO) .setOrderId(order.getId()).setNo(generateOrderExtensionNo()) .setChannelId(channel.getId()).setChannelCode(channel.getCode()) .setStatus(PayOrderStatusEnum.WAITING.getStatus()); - payOrderExtensionCoreMapper.insert(orderExtension); + orderExtensionMapper.insert(orderExtension); // 调用三方接口 - PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO); + PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderConvert.INSTANCE.convert2(reqDTO); // 商户相关字段 //TODO jason @芋艿 是否加一个属性 如tradeNo 支付订单号, 用这个merchantOrderId让人迷糊 unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性! @@ -197,12 +216,12 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); // 校验支付渠道是否有效 - PayChannelDO channel = payChannelCoreService.validPayChannel(channelId); + PayChannelDO channel = channelService.validPayChannel(channelId); // 校验支付客户端是否正确初始化 PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } // 解析支付结果 @@ -210,45 +229,44 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { // TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。 // 1.1 查询 PayOrderExtensionDO - PayOrderExtensionDO orderExtension = payOrderExtensionCoreMapper.selectByNo( - notifyRespDTO.getOrderExtensionNo()); + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notifyRespDTO.getOrderExtensionNo()); if (orderExtension == null) { - throw exception(PAY_ORDER_EXTENSION_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(orderExtension.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } // 1.2 更新 PayOrderExtensionDO //TODO 支付宝交易超时 TRADE_FINISHED 需要更新交易关闭 - int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(), + int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId()) .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData.getBody()).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); } log.info("[notifyPayOrder][支付拓展单({}) 更新为已支付]", orderExtension.getId()); // 2.1 判断 PayOrderDO 是否处于待支付 - PayOrderDO order = payOrderCoreMapper.selectById(orderExtension.getOrderId()); + PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); if (order == null) { - throw exception(PAY_ORDER_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); } // 2.2 更新 PayOrderDO - updateCounts = payOrderCoreMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), + updateCounts = orderMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelId(channelId).channelCode(channel.getCode()) .successTime(notifyRespDTO.getSuccessTime()).successExtensionId(orderExtension.getId()) .channelOrderNo(notifyRespDTO.getChannelOrderNo()).channelUserId(notifyRespDTO.getChannelUserId()) .notifyTime(new Date()).build()); if (updateCounts == 0) { // 校验状态,必须是待支付 - throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); } log.info("[notifyPayOrder][支付订单({}) 更新为已支付]", order.getId()); // 3. 插入支付通知记录 - payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() + notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() .type(PayNotifyTypeEnum.ORDER.getType()).dataId(order.getId()).build()); } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java similarity index 95% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderCreateReqDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java index a5d2b0f4e2..62bf511de4 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderCreateReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.service.order.dto; import lombok.Data; import org.hibernate.validator.constraints.Length; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitReqDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitReqDTO.java similarity index 92% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitReqDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitReqDTO.java index eb08fbb3e1..20f6ab2643 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.service.order.dto; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitRespDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitRespDTO.java similarity index 83% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitRespDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitRespDTO.java index 2bcb504e85..a594253f55 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayOrderSubmitRespDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderSubmitRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.service.order.dto; import lombok.Data; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundReqDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java similarity index 93% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundReqDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java index 6ec3fb13d1..0eb24dbe25 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.service.order.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundRespDTO.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundRespDTO.java similarity index 85% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundRespDTO.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundRespDTO.java index d065f3852f..2e1a6fcd46 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/dto/PayRefundRespDTO.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.service.order.dto; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java new file mode 100644 index 0000000000..2cad91ebaa --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay.service; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java new file mode 100755 index 0000000000..7ffd52b10f --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.pay.service.refund; + +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO; + +import java.util.List; + +/** + * 退款订单 Service 接口 + * + * @author aquan + */ +public interface PayRefundService { + + /** + * 获得退款订单 + * + * @param id 编号 + * @return 退款订单 + */ + PayRefundDO getRefund(Long id); + + /** + * 获得退款订单分页 + * + * @param pageReqVO 分页查询 + * @return 退款订单分页 + */ + PageResult getRefundPage(PayRefundPageReqVO pageReqVO); + + /** + * 获得退款订单列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 退款订单列表 + */ + List getRefundList(PayRefundExportReqVO exportReqVO); + + /** + * 提交退款申请 + * + * @param reqDTO 退款申请信息 + * @return 退款申请返回信息 + */ + PayRefundRespDTO submitRefundOrder(PayRefundReqDTO reqDTO); + + /** + * 渠道的退款通知 + * + * @param channelId 渠道编号 + * @param notifyData 通知数据 + * @throws Exception 退款通知异常 + */ + void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) throws Exception; + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java old mode 100644 new mode 100755 similarity index 62% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index 944c62aa6e..4e3a151fbe --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayRefundCoreServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -1,26 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl; +package cn.iocoder.yudao.module.pay.service.refund; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensionCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayRefundCoreMapper; -import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayRefundCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayRefundRespDTO; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; @@ -29,56 +10,102 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundNotifyDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; import cn.iocoder.yudao.framework.pay.core.enums.PayNotifyRefundStatusEnum; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; +import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayRefundRespDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Date; +import java.util.List; import java.util.Objects; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; - +/** + * 退款订单 Service 实现类 + * + * @author aquan + */ @Service @Slf4j -public class PayRefundCoreServiceImpl implements PayRefundCoreService { - - @Resource - private PayOrderCoreMapper payOrderCoreMapper; - @Resource - private PayRefundCoreMapper payRefundCoreMapper; - @Resource - private PayOrderExtensionCoreMapper payOrderExtensionCoreMapper; - - @Resource - private PayAppCoreService payAppCoreService; - @Resource - private PayChannelCoreService payChannelCoreService; - @Resource - private PayNotifyCoreService payNotifyCoreService; +@Validated +public class PayRefundServiceImpl implements PayRefundService { @Resource private PayClientFactory payClientFactory; + @Resource + private PayRefundMapper refundMapper; + @Resource + private PayOrderMapper orderMapper; // TODO @jason:需要改成不直接操作 db; + + @Resource + private PayOrderService orderService; + @Resource + private PayOrderExtensionService orderExtensionService; + @Resource + private PayAppService appService; + @Resource + private PayChannelService channelService; + @Resource + private PayNotifyService notifyService; + + @Override + public PayRefundDO getRefund(Long id) { + return refundMapper.selectById(id); + } + + @Override + public PageResult getRefundPage(PayRefundPageReqVO pageReqVO) { + return refundMapper.selectPage(pageReqVO); + } + + @Override + public List getRefundList(PayRefundExportReqVO exportReqVO) { + return refundMapper.selectList(exportReqVO); + } + @Override @Transactional(rollbackFor = Exception.class) public PayRefundRespDTO submitRefundOrder(PayRefundReqDTO req) { // 获得 PayOrderDO - PayOrderDO order = payOrderCoreMapper.selectById(req.getPayOrderId()); + PayOrderDO order = orderService.getOrder(req.getPayOrderId()); // 校验订单是否存在 if (Objects.isNull(order) ) { - throw exception(PAY_ORDER_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); } // 校验 App - PayAppDO app = payAppCoreService.validPayApp(order.getAppId()); + PayAppDO app = appService.validPayApp(order.getAppId()); // 校验支付渠道是否有效 - PayChannelDO channel = payChannelCoreService.validPayChannel(order.getChannelId()); + PayChannelDO channel = channelService.validPayChannel(order.getChannelId()); // 校验支付客户端是否正确初始化 PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[refund][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } // 校验退款的条件 @@ -88,19 +115,19 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { if (Objects.equals(req.getAmount(), order.getAmount())) { refundType = PayRefundTypeEnum.ALL; } - PayOrderExtensionDO orderExtensionDO = payOrderExtensionCoreMapper.selectById(order.getSuccessExtensionId()); - PayRefundDO payRefundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundId()); + PayOrderExtensionDO orderExtensionDO = orderExtensionService.getOrderExtension(order.getSuccessExtensionId()); + PayRefundDO payRefundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(orderExtensionDO.getNo(), req.getMerchantRefundId()); if(Objects.nonNull(payRefundDO)){ // 退款订单已经提交过。 //TODO 校验相同退款单的金额 // TODO @jason:咱要不封装一个 ObjectUtils.equalsAny if (Objects.equals(PayRefundStatusEnum.SUCCESS.getStatus(), payRefundDO.getStatus()) - || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())) { + || Objects.equals(PayRefundStatusEnum.CLOSE.getStatus(), payRefundDO.getStatus())) { //已成功退款 - throw exception(PAY_REFUND_SUCCEED); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_SUCCEED); } //可以重复提交,保证 退款请求号 一致,由渠道保证幂等 - }else { + } else { // 成功,插入退款单 状态为生成.没有和渠道交互 // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo()) @@ -122,7 +149,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { .notifyStatus(PayOrderNotifyStatusEnum.NO.getStatus()) .type(refundType.getStatus()) .build(); - payRefundCoreMapper.insert(payRefundDO); + refundMapper.insert(payRefundDO); } // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO(); @@ -142,18 +169,17 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { return PayRefundRespDTO.builder().refundId(payRefundDO.getId()).build(); } - @Override @Transactional(rollbackFor = Exception.class) public void notifyPayRefund(Long channelId, PayNotifyDataDTO notifyData) { log.info("[notifyPayRefund][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); // 校验支付渠道是否有效 - PayChannelDO channel = payChannelCoreService.validPayChannel(channelId); + PayChannelDO channel = channelService.validPayChannel(channelId); // 校验支付客户端是否正确初始化 PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } // 解析渠道退款通知数据, 统一处理 PayRefundNotifyDTO refundNotify = client.parseRefundNotify(notifyData); @@ -167,14 +193,14 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { private void payRefundSuccess(PayRefundNotifyDTO refundNotify) { // 校验退款单存在 - PayRefundDO refundDO = payRefundCoreMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo()); + PayRefundDO refundDO = refundMapper.selectByTradeNoAndMerchantRefundNo(refundNotify.getTradeNo(), refundNotify.getReqNo()); if (refundDO == null) { log.error("[payRefundSuccess][不存在 seqNo 为{} 的支付退款单]", refundNotify.getReqNo()); - throw exception(PAY_REFUND_NOT_FOUND); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_NOT_FOUND); } // 得到已退金额 - PayOrderDO payOrderDO = payOrderCoreMapper.selectById(refundDO.getOrderId()); + PayOrderDO payOrderDO = orderService.getOrder(refundDO.getOrderId()); Long refundedAmount = payOrderDO.getRefundAmount(); PayOrderStatusEnum orderStatus = PayOrderStatusEnum.SUCCESS; @@ -189,7 +215,7 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { .setStatus(orderStatus.getStatus()) .setRefundTimes(payOrderDO.getRefundTimes() + 1) .setRefundStatus(refundDO.getType()); - payOrderCoreMapper.updateById(updateOrderDO); + orderMapper.updateById(updateOrderDO); // 更新退款订单 PayRefundDO updateRefundDO = new PayRefundDO(); @@ -199,11 +225,11 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { .setTradeNo(refundNotify.getTradeNo()) .setNotifyTime(new Date()) .setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); - payRefundCoreMapper.updateById(updateRefundDO); + refundMapper.updateById(updateRefundDO); // 插入退款通知记录 // TODO 通知商户成功或者失败. 现在通知似乎没有实现, 只是回调 - payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() + notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refundDO.getId()).build()); } @@ -215,19 +241,19 @@ public class PayRefundCoreServiceImpl implements PayRefundCoreService { private void validatePayRefund(PayRefundReqDTO req, PayOrderDO order) { // 校验状态,必须是支付状态 if (!PayOrderStatusEnum.SUCCESS.getStatus().equals(order.getStatus())) { - throw exception(PAY_ORDER_STATUS_IS_NOT_SUCCESS); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_SUCCESS); } // 是否已经全额退款 if (PayRefundTypeEnum.ALL.getStatus().equals(order.getRefundStatus())) { - throw exception(PAY_REFUND_ALL_REFUNDED); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_ALL_REFUNDED); } // 校验金额 退款金额不能大于 原定的金额 if (req.getAmount() + order.getRefundAmount() > order.getAmount()){ - throw exception(PAY_REFUND_AMOUNT_EXCEED); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_AMOUNT_EXCEED); } // 校验渠道订单号 if (StrUtil.isEmpty(order.getChannelOrderNo())) { - throw exception(PAY_REFUND_CHN_ORDER_NO_IS_NULL); + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_REFUND_CHN_ORDER_NO_IS_NULL); } //TODO 退款的期限 退款次数的控制 } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/util/PaySeqUtils.java b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/util/PaySeqUtils.java similarity index 94% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/util/PaySeqUtils.java rename to yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/util/PaySeqUtils.java index 959cef7460..e6409e9603 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/util/PaySeqUtils.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/util/PaySeqUtils.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.util; +package cn.iocoder.yudao.module.pay.util; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; @@ -10,6 +10,7 @@ import java.util.concurrent.atomic.AtomicLong; /** * 支付相关编号的生产 */ +// TODO @jason:需要改造,基于 db; public class PaySeqUtils { private static final AtomicLong REFUND_REQ_NO_SEQ = new AtomicLong(0L); @@ -47,4 +48,5 @@ public class PaySeqUtils { DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), (int) MER_ORDER_NO_SEQ.getAndIncrement() % 10000); } + } diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDOTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDOTest.java similarity index 92% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDOTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDOTest.java index c0fb7d5bd6..2818cb12d0 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/dataobject/merchant/PayChannelDOTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDOTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant; +package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapperTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapperIntegrationTest.java similarity index 89% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapperTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapperIntegrationTest.java index 18445a4ec9..b869163a2f 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/dal/mysql/merchant/PayChannelCoreMapperTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/dal/mysql/merchant/PayChannelMapperIntegrationTest.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant; +package cn.iocoder.yudao.module.pay.dal.mysql.merchant; import cn.hutool.core.io.IoUtil; -import cn.iocoder.yudao.coreservice.BaseDbAndRedisIntegrationTest; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.test.BaseDbIntegrationTest; import org.junit.jupiter.api.Test; import javax.annotation.Resource; @@ -15,10 +15,10 @@ import java.io.FileNotFoundException; import java.util.List; @Resource -public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { +public class PayChannelMapperIntegrationTest extends BaseDbIntegrationTest { @Resource - private PayChannelCoreMapper payChannelCoreMapper; + private PayChannelMapper payChannelMapper; /** * 插入 {@link PayChannelEnum#WX_PUB} 初始配置 @@ -42,7 +42,7 @@ public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { config.setApiV3Key("joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase"); payChannelDO.setConfig(config); // 执行插入 - payChannelCoreMapper.insert(payChannelDO); + payChannelMapper.insert(payChannelDO); } // TODO @ouyang:Zfb 改成 AlipayQr @@ -67,7 +67,7 @@ public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { // 创建客户端 payChannelDO.setConfig(config); // 执行插入 - payChannelCoreMapper.insert(payChannelDO); + payChannelMapper.insert(payChannelDO); } /** @@ -75,7 +75,7 @@ public class PayChannelCoreMapperTest extends BaseDbAndRedisIntegrationTest { */ @Test public void testSelectList() { - List payChannels = payChannelCoreMapper.selectList(); + List payChannels = payChannelMapper.selectList(); System.out.println(payChannels.size()); } diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceIntegrationTest.java similarity index 55% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceIntegrationTest.java index 2a5e137412..f6f953635a 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceIntegrationTest.java @@ -1,11 +1,10 @@ -package cn.iocoder.yudao.coreservice.modules.pay.service.order; +package cn.iocoder.yudao.module.pay.service.order; -import cn.iocoder.yudao.coreservice.BaseDbIntegrationTest; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl.PayAppCoreServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl.PayChannelCoreServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.impl.PayOrderCoreServiceImpl; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppServiceImpl; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelServiceImpl; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; +import cn.iocoder.yudao.module.pay.test.BaseDbIntegrationTest; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.pay.config.YudaoPayAutoConfiguration; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; @@ -15,12 +14,12 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.time.Duration; -@Import({PayOrderCoreServiceImpl.class, PayAppCoreServiceImpl.class, - PayChannelCoreServiceImpl.class, YudaoPayAutoConfiguration.class}) -public class PayOrderCoreServiceTest extends BaseDbIntegrationTest { +@Import({PayOrderServiceImpl.class, PayAppServiceImpl.class, + PayChannelServiceImpl.class, YudaoPayAutoConfiguration.class}) +public class PayOrderServiceIntegrationTest extends BaseDbIntegrationTest { @Resource - private PayOrderCoreService payOrderCoreService; + private PayOrderService payOrderService; @Test public void testCreatePayOrder() { @@ -34,7 +33,7 @@ public class PayOrderCoreServiceTest extends BaseDbIntegrationTest { reqDTO.setAmount(100); reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); // 发起请求 - payOrderCoreService.createPayOrder(reqDTO); + payOrderService.createPayOrder(reqDTO); } @Test @@ -46,7 +45,7 @@ public class PayOrderCoreServiceTest extends BaseDbIntegrationTest { reqDTO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); reqDTO.setUserIp("127.0.0.1"); // 发起请求 - payOrderCoreService.submitPayOrder(reqDTO); + payOrderService.submitPayOrder(reqDTO); } } diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/package-info.java new file mode 100644 index 0000000000..2cad91ebaa --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay.service; diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisIntegrationTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisIntegrationTest.java similarity index 98% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisIntegrationTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisIntegrationTest.java index dc15808943..2ee19ebf91 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisIntegrationTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.pay.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbIntegrationTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbIntegrationTest.java similarity index 97% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbIntegrationTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbIntegrationTest.java index c0ebe98738..380efa3f40 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseDbIntegrationTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseDbIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.pay.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; diff --git a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseRedisIntegrationTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseRedisIntegrationTest.java similarity index 95% rename from yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseRedisIntegrationTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseRedisIntegrationTest.java index 16b5e98f14..d01353d725 100644 --- a/yudao-core-service/src/test-integration/java/cn/iocoder/yudao/coreservice/BaseRedisIntegrationTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/java/cn/iocoder/yudao/module/pay/test/BaseRedisIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.pay.test; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; diff --git a/yudao-core-service/src/test-integration/resources/application-integration-test.yaml b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/resources/application-integration-test.yaml similarity index 95% rename from yudao-core-service/src/test-integration/resources/application-integration-test.yaml rename to yudao-module-pay/yudao-module-pay-impl/src/test-integration/resources/application-integration-test.yaml index 9f87b5ca7c..c8e34e4765 100644 --- a/yudao-core-service/src/test-integration/resources/application-integration-test.yaml +++ b/yudao-module-pay/yudao-module-pay-impl/src/test-integration/resources/application-integration-test.yaml @@ -60,7 +60,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) mapper-locations: classpath*:mapper/*.xml - type-aliases-package: ${yudao.core-service.base-package}.modules.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject --- #################### 定时任务相关配置 #################### @@ -87,9 +87,7 @@ resilience4j: yudao: info: version: 1.0.0 - base-package: cn.iocoder.yudao.adminserver - core-service: - base-package: cn.iocoder.yudao.coreservice + base-package: cn.iocoder.yudao.module pay: pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java similarity index 89% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java index 7dee064027..a0da136bc1 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java @@ -1,18 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.app; +package cn.iocoder.yudao.module.pay.service.merchant; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.app.impl.PayAppServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.app.PayAppUpdateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayAppMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayMerchantMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.MockBean; @@ -22,20 +22,15 @@ import javax.annotation.Resource; import java.util.Collections; import java.util.List; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_APP_NOT_FOUND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; -/** - * {@link PayAppServiceImpl} 的单元测试类 - * - * @author 芋艿 - */ @Import(PayAppServiceImpl.class) public class PayAppServiceTest extends BaseDbUnitTest { diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java similarity index 93% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java index b8d2bc917f..f6335d0913 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java @@ -1,43 +1,37 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.channel; +package cn.iocoder.yudao.module.pay.service.merchant; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl.PayChannelServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelUpdateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; +import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest; import com.alibaba.fastjson.JSON; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; +import javax.validation.Validator; import java.util.List; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.CHANNEL_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; -/** - * {@link PayChannelServiceImpl} 的单元测试类 - * - * @author 芋艿 - */ -@Import({ - PayChannelServiceImpl.class, - PayChannelConfig.class -}) +@Import({PayChannelServiceImpl.class}) public class PayChannelServiceTest extends BaseDbUnitTest { @Resource @@ -46,6 +40,11 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @Resource private PayChannelMapper channelMapper; + @MockBean + private PayClientFactory payClientFactory; + @MockBean + private Validator validator; + @Test public void testCreateWechatVersion2Channel_success() { // 准备参数 @@ -66,7 +65,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { assertPojoEquals(reqVO, channel, "config"); // 关于config 对象应该拿出来重新对比 assertPojoEquals(v2Config, channel.getConfig()); - } @Test @@ -350,7 +348,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { assertPojoEquals(payClientConfig, list.get(0).getConfig()); } - public WXPayClientConfig getV2Config() { return new WXPayClientConfig() .setAppId("APP00001") @@ -400,5 +397,4 @@ public class PayChannelServiceTest extends BaseDbUnitTest { .setRootCertContent("13321321321dsad"); } - } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java similarity index 89% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java index 0e7cf135dc..08d097083c 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java @@ -1,29 +1,28 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.merchant; +package cn.iocoder.yudao.module.pay.service.merchant; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl.PayMerchantServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantCreateReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.merchant.PayMerchantUpdateReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayMerchantDO; +import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayMerchantMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.List; -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java similarity index 86% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java index 85b00a2d0e..cacee1681d 100755 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/order/PayOrderServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java @@ -1,20 +1,25 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.order; +package cn.iocoder.yudao.module.pay.service.order; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.order.PayOrderPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayOrderServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.pay.config.PayProperties; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; +import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; @@ -31,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; * * @author 芋艿 */ -@Import(PayOrderServiceImpl.class) +@Import({PayOrderServiceImpl.class}) public class PayOrderServiceTest extends BaseDbUnitTest { @Resource @@ -40,6 +45,17 @@ public class PayOrderServiceTest extends BaseDbUnitTest { @Resource private PayOrderMapper orderMapper; + @MockBean + private PayClientFactory payClientFactory; + @MockBean + private PayProperties properties; + @MockBean + private PayAppService appService; + @MockBean + private PayChannelService channelService; + @MockBean + private PayNotifyService notifyService; + public String generateNo() { return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); } diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/package-info.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/package-info.java new file mode 100644 index 0000000000..2cad91ebaa --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.pay.service; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/refund/PayRefundServiceTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java similarity index 84% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/refund/PayRefundServiceTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java index ee19dba14e..844c0ca009 100755 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/refund/PayRefundServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java @@ -1,18 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.pay.service.refund; +package cn.iocoder.yudao.module.pay.service.refund; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundExportReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.controller.order.vo.refund.vo.PayRefundPageReqVO; -import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper; -import cn.iocoder.yudao.adminserver.modules.pay.service.order.impl.PayRefundServiceImpl; -import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum; -import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundPageReqVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; +import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderNotifyStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundTypeEnum; +import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; +import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderExtensionService; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; @@ -23,12 +29,6 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link PayRefundServiceImpl} 的单元测试类 - * - * @author aquan - */ @Import(PayRefundServiceImpl.class) public class PayRefundServiceTest extends BaseDbUnitTest { @@ -38,6 +38,18 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @Resource private PayRefundMapper refundMapper; + @MockBean + private PayClientFactory payClientFactory; + @MockBean + private PayOrderService orderService; + @MockBean + private PayOrderExtensionService orderExtensionService; + @MockBean + private PayAppService appService; + @MockBean + private PayChannelService channelService; + @MockBean + private PayNotifyService notifyService; @Test public void testGetRefundPage() { diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbAndRedisUnitTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisUnitTest.java similarity index 93% rename from yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbAndRedisUnitTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisUnitTest.java index 2669ef49c9..215c7d235d 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbAndRedisUnitTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbAndRedisUnitTest.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.userserver; +package cn.iocoder.yudao.module.pay.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; -import cn.iocoder.yudao.userserver.config.RedisTestConfiguration; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; @@ -24,6 +23,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbAndRedisUnitTest { diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbUnitTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbUnitTest.java similarity index 91% rename from yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbUnitTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbUnitTest.java index af8d71a0cb..4d820ea65a 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbUnitTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseDbUnitTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver; +package cn.iocoder.yudao.module.pay.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; @@ -20,6 +20,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbUnitTest { diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseRedisUnitTest.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseRedisUnitTest.java similarity index 91% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseRedisUnitTest.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseRedisUnitTest.java index e95e6d787d..11933c9fdd 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseRedisUnitTest.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/BaseRedisUnitTest.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.pay.test; -import cn.iocoder.yudao.coreservice.config.RedisTestConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/RedisTestConfiguration.java b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/RedisTestConfiguration.java similarity index 96% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/RedisTestConfiguration.java rename to yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/RedisTestConfiguration.java index 15a39f7570..c8742129a0 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/config/RedisTestConfiguration.java +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/java/cn/iocoder/yudao/module/pay/test/RedisTestConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.config; +package cn.iocoder.yudao.module.pay.test; import com.github.fppt.jedismock.RedisServer; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test/resources/application-unit-test.yaml b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000000..9f36ec4ac9 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/application-unit-test.yaml @@ -0,0 +1,46 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test/resources/logback.xml b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/logback.xml new file mode 100644 index 0000000000..daf756bff0 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/clean.sql b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..7430b6bfe3 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/clean.sql @@ -0,0 +1,5 @@ +DELETE FROM pay_merchant; +DELETE FROM pay_app; +DELETE FROM pay_channel; +DELETE FROM pay_order; +DELETE FROM pay_refund; diff --git a/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/create_tables.sql b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000000..890fb77002 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-impl/src/test/resources/sql/create_tables.sql @@ -0,0 +1,114 @@ +CREATE TABLE IF NOT EXISTS "pay_merchant" ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar(32) NOT NULL, + "name" varchar(64) NOT NULL, + "short_name" varchar(64) NOT NULL, + "status" tinyint NOT NULL, + "remark" varchar(255) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '支付商户信息'; + +CREATE TABLE IF NOT EXISTS "pay_app" ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(64) NOT NULL, + "status" tinyint NOT NULL, + "remark" varchar(255) DEFAULT NULL, + `pay_notify_url` varchar(1024) NOT NULL, + `refund_notify_url` varchar(1024) NOT NULL, + `merchant_id` bigint(20) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '支付应用信息'; + +CREATE TABLE IF NOT EXISTS "pay_channel" ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(32) NOT NULL, + "status" tinyint(4) NOT NULL, + "remark" varchar(255) DEFAULT NULL, + "fee_rate" double NOT NULL DEFAULT 0, + "merchant_id" bigint(20) NOT NULL, + "app_id" bigint(20) NOT NULL, + "config" varchar(10240) NOT NULL, + "creator" varchar(64) NULL DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) NULL DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '支付渠道'; + +CREATE TABLE IF NOT EXISTS `pay_order` ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `merchant_id` bigint(20) NOT NULL, + `app_id` bigint(20) NOT NULL, + `channel_id` bigint(20) DEFAULT NULL, + `channel_code` varchar(32) DEFAULT NULL, + `merchant_order_id` varchar(64) NOT NULL, + `subject` varchar(32) NOT NULL, + `body` varchar(128) NOT NULL, + `notify_url` varchar(1024) NOT NULL, + `notify_status` tinyint(4) NOT NULL, + `amount` bigint(20) NOT NULL, + `channel_fee_rate` double DEFAULT 0, + `channel_fee_amount` bigint(20) DEFAULT 0, + `status` tinyint(4) NOT NULL, + `user_ip` varchar(50) NOT NULL, + `expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, + `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, + `success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号', + `refund_status` tinyint(4) NOT NULL, + `refund_times` tinyint(4) NOT NULL, + `refund_amount` bigint(20) NOT NULL, + `channel_user_id` varchar(255) DEFAULT NULL, + `channel_order_no` varchar(64) DEFAULT NULL, + `creator` varchar(64) DEFAULT '', + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updater` varchar(64) DEFAULT '', + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '支付订单'; + +CREATE TABLE IF NOT EXISTS `pay_refund` ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `merchant_id` bigint(20) NOT NULL, + `app_id` bigint(20) NOT NULL, + `channel_id` bigint(20) NOT NULL, + `channel_code` varchar(32) NOT NULL, + `order_id` bigint(20) NOT NULL, + `trade_no` varchar(64) NOT NULL, + `merchant_order_id` varchar(64) NOT NULL, + `merchant_refund_no` varchar(64) NOT NULL, + `notify_url` varchar(1024) NOT NULL, + `notify_status` tinyint(4) NOT NULL, + `status` tinyint(4) NOT NULL, + `type` tinyint(4) NOT NULL, + `pay_amount` bigint(20) NOT NULL, + `refund_amount` bigint(20) NOT NULL, + `reason` varchar(256) NOT NULL, + `user_ip` varchar(50) NULL DEFAULT NULL, + `channel_order_no` varchar(64) NOT NULL, + `channel_refund_no` varchar(64) NULL DEFAULT NULL, + `channel_error_code` varchar(128) NULL DEFAULT NULL, + `channel_error_msg` varchar(256) NULL DEFAULT NULL, + `channel_extras` varchar(1024) NULL DEFAULT NULL, + `expire_time` datetime(0) NULL DEFAULT NULL, + `success_time` datetime(0) NULL DEFAULT NULL, + `notify_time` datetime(0) NULL DEFAULT NULL, + `creator` varchar(64) NULL DEFAULT '', + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updater` varchar(64) NULL DEFAULT '', + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '退款订单'; diff --git a/yudao-module-system/pom.xml b/yudao-module-system/pom.xml new file mode 100644 index 0000000000..470f1cc2bc --- /dev/null +++ b/yudao-module-system/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-module-system-api + yudao-module-system-impl + + yudao-module-system + pom + + ${artifactId} + + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 + + + diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml new file mode 100644 index 0000000000..40e97dc4bf --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -0,0 +1,41 @@ + + + + cn.iocoder.boot + yudao-module-system + ${revision} + + 4.0.0 + yudao-module-system-api + jar + + ${artifactId} + + system 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + true + + + + + diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreService.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApi.java similarity index 63% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreService.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApi.java index 5106af7a32..a35dfae382 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreService.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApi.java @@ -1,13 +1,16 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.auth; +package cn.iocoder.yudao.module.system.api.auth; import cn.iocoder.yudao.framework.security.core.LoginUser; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + /** - * 在线用户 Session Core Service 接口 + * 在线用户 Session API 接口 * * @author 芋道源码 */ -public interface SysUserSessionCoreService { +public interface UserSessionApi { /** * 创建在线用户 Session @@ -17,7 +20,7 @@ public interface SysUserSessionCoreService { * @param userAgent 用户 UA * @return Session 编号 */ - String createUserSession(LoginUser loginUser, String userIp, String userAgent); + String createUserSession(@NotNull(message = "登录用户不能为空") LoginUser loginUser, String userIp, String userAgent); /** * 刷新在线用户 Session 的更新时间 @@ -25,7 +28,8 @@ public interface SysUserSessionCoreService { * @param sessionId Session 编号 * @param loginUser 登录用户 */ - void refreshUserSession(String sessionId, LoginUser loginUser); + void refreshUserSession(@NotEmpty(message = "Session编号不能为空") String sessionId, + @NotNull(message = "登录用户不能为空") LoginUser loginUser); /** * 删除在线用户 Session diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java new file mode 100644 index 0000000000..d228fc3b71 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.system.api.dept; + +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 部门 API 接口 + * + * @author 芋道源码 + */ +public interface DeptApi { + + /** + * 获得部门信息 + * + * @param id 部门编号 + * @return 部门信息 + */ + DeptRespDTO getDept(Long id); + + /** + * 获得部门信息数组 + * + * @param ids 部门编号数组 + * @return 部门信息数组 + */ + List getDepts(Collection ids); + + /** + * 校验部门们是否有效。如下情况,视为无效: + * 1. 部门编号不存在 + * 2. 部门被禁用 + * + * @param ids 角色编号数组 + */ + void validDepts(Collection ids); + + /** + * 获得指定编号的部门 Map + * + * @param ids 部门编号数组 + * @return 部门 Map + */ + Map getDeptMap(Set ids); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApi.java new file mode 100644 index 0000000000..d1e3d47a1d --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApi.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.api.dept; + +import java.util.Collection; + +/** + * 岗位 API 接口 + * + * @author 芋道源码 + */ +public interface PostApi { + + /** + * 校验岗位们是否有效。如下情况,视为无效: + * 1. 岗位编号不存在 + * 2. 岗位被禁用 + * + * @param ids 岗位编号数组 + */ + void validPosts(Collection ids); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/dto/DeptRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/dto/DeptRespDTO.java new file mode 100644 index 0000000000..d3e66fdd83 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/dto/DeptRespDTO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.system.api.dept.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +/** + * 部门 Response DTO + * + * @author 芋道源码 + */ +@Data +public class DeptRespDTO { + + /** + * 部门编号 + */ + private Long id; + /** + * 部门名称 + */ + private String name; + /** + * 父部门编号 + */ + private Long parentId; + /** + * 负责人的用户编号 + */ + private Long leaderUserId; + /** + * 部门状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java new file mode 100644 index 0000000000..35393a04a2 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApi.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.system.api.dict; + +import java.util.Collection; + +/** + * 字典数据 API 接口 + * + * @author 芋道源码 + */ +public interface DictDataApi { + + /** + * 校验字典数据们是否有效。如下情况,视为无效: + * 1. 字典数据不存在 + * 2. 字典数据被禁用 + * + * @param dictType 字典类型 + * @param values 字典数据值的数组 + */ + void validDictDatas(String dictType, Collection values); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApi.java new file mode 100644 index 0000000000..4ff596c68a --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApi.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.api.logger; + +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; + +import javax.validation.Valid; + +/** + * 登录日志的 API 接口 + * + * @author 芋道源码 + */ +public interface LoginLogApi { + + /** + * 创建登录日志 + * + * @param reqDTO 日志信息 + */ + void createLoginLog(@Valid LoginLogCreateReqDTO reqDTO); + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/dto/SysLoginLogCreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java similarity index 87% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/dto/SysLoginLogCreateReqDTO.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java index 4dddf9df81..d3ae4fb4fb 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/logger/dto/SysLoginLogCreateReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.logger.dto; +package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; @@ -13,7 +13,7 @@ import javax.validation.constraints.Size; * @author 芋道源码 */ @Data -public class SysLoginLogCreateReqDTO { +public class LoginLogCreateReqDTO { /** * 日志类型 @@ -23,7 +23,6 @@ public class SysLoginLogCreateReqDTO { /** * 链路追踪编号 */ - @NotEmpty(message = "链路追踪编号不能为空") private String traceId; /** diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/package-info.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/package-info.java new file mode 100644 index 0000000000..25bfc44416 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/package-info.java @@ -0,0 +1,4 @@ +/** + * System API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.system.api; diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java new file mode 100644 index 0000000000..04e9638696 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApi.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.api.permission; + +import java.util.Collection; +import java.util.Set; + +/** + * 权限 API 接口 + * + * @author 芋道源码 + */ +public interface PermissionApi { + + /** + * 获得拥有多个角色的用户编号集合 + * + * @param roleIds 角色编号集合 + * @return 用户编号集合 + */ + Set getUserRoleIdListByRoleIds(Collection roleIds); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApi.java new file mode 100644 index 0000000000..14133e9d90 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApi.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.api.permission; + +import java.util.Collection; + +/** + * 角色 API 接口 + * + * @author 芋道源码 + */ +public interface RoleApi { + + /** + * 校验角色们是否有效。如下情况,视为无效: + * 1. 角色编号不存在 + * 2. 角色被禁用 + * + * @param ids 角色编号数组 + */ + void validRoles(Collection ids); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java new file mode 100644 index 0000000000..ffcf46dc08 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.system.api.sms; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; + +import javax.validation.Valid; + +/** + * 短信验证码 API 接口 + * + * @author 芋道源码 + */ +public interface SmsCodeApi { + + /** + * 创建短信验证码,并进行发送 + * + * @param reqDTO 发送请求 + */ + void sendSmsCode(@Valid SmsCodeSendReqDTO reqDTO); + + /** + * 验证短信验证码,并进行使用 + * 如果正确,则将验证码标记成已使用 + * 如果错误,则抛出 {@link ServiceException} 异常 + * + * @param reqDTO 使用请求 + */ + void useSmsCode(@Valid SmsCodeUseReqDTO reqDTO); + + /** + * 检查验证码是否有效 + * + * @param reqDTO 校验请求 + */ + void checkSmsCode(@Valid SmsCodeCheckReqDTO reqDTO); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApi.java new file mode 100644 index 0000000000..c86bbf503f --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApi.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.api.sms; + +import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO; + +import javax.validation.Valid; + +/** + * 短信发送 API 接口 + * + * @author 芋道源码 + */ +public interface SmsSendApi { + + /** + * 发送单条短信给 Admin 用户 + * + * 在 mobile 为空时,使用 userId 加载对应 Admin 的手机号 + * + * @param reqDTO 发送请求 + * @return 发送日志编号 + */ + Long sendSingleSmsToAdmin(@Valid SmsSendSingleToUserReqDTO reqDTO); + + /** + * 发送单条短信给 Member 用户 + * + * 在 mobile 为空时,使用 userId 加载对应 Member 的手机号 + * + * @param reqDTO 发送请求 + * @return 发送日志编号 + */ + Long sendSingleSmsToMember(@Valid SmsSendSingleToUserReqDTO reqDTO); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java new file mode 100644 index 0000000000..d6ca3c6983 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.api.sms.dto.code; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * 短信验证码的校验 Request DTO + * + * @author 芋道源码 + */ +@Data +public class SmsCodeCheckReqDTO { + + /** + * 手机号 + */ + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; + /** + * 发送场景 + */ + @NotEmpty(message = "发送场景不能为空") + @InEnum(SmsSceneEnum.class) + private Integer scene; + /** + * 验证码 + */ + @NotEmpty(message = "验证码") + private String code; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java new file mode 100644 index 0000000000..2d2a4c7e39 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.api.sms.dto.code; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * 短信验证码的发送 Request DTO + * + * @author 芋道源码 + */ +@Data +public class SmsCodeSendReqDTO { + + /** + * 手机号 + */ + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; + /** + * 发送场景 + */ + @NotEmpty(message = "发送场景不能为空") + @InEnum(SmsSceneEnum.class) + private Integer scene; + /** + * 发送 IP + */ + @NotEmpty(message = "发送 IP 不能为空") + private String createIp; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java new file mode 100644 index 0000000000..3a639f46e1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.system.api.sms.dto.code; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * 短信验证码的使用 Request DTO + * + * @author 芋道源码 + */ +@Data +public class SmsCodeUseReqDTO { + + /** + * 手机号 + */ + @Mobile + @NotEmpty(message = "手机号不能为空") + private String mobile; + /** + * 发送场景 + */ + @NotEmpty(message = "发送场景不能为空") + @InEnum(SmsSceneEnum.class) + private Integer scene; + /** + * 验证码 + */ + @NotEmpty(message = "验证码") + private String code; + /** + * 使用 IP + */ + @NotEmpty(message = "使用 IP 不能为空") + private String usedIp; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java new file mode 100644 index 0000000000..7701f714e3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.system.api.sms.dto.send; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Map; + +/** + * 短信发送给 Admin 或者 Member 用户 + * + * @author 芋道源码 + */ +@Data +public class SmsSendSingleToUserReqDTO { + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 手机号 + */ + @Mobile + private String mobile; + /** + * 短信模板编号 + */ + @NotEmpty(message = "短信模板编号不能为空") + private String templateCode; + /** + * 短信模板参数 + */ + private Map templateParams; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java new file mode 100644 index 0000000000..720712108c --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.system.api.social; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; + +import javax.validation.Valid; + +/** + * 社交用户的 API 接口 + * + * @author 芋道源码 + */ +public interface SocialUserApi { + + /** + * 获得社交平台的授权 URL + * + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param redirectUri 重定向 URL + * @return 社交平台的授权 URL + */ + String getAuthorizeUrl(Integer type, String redirectUri); + + /** + * 绑定社交用户 + * + * @param reqDTO 绑定信息 + */ + void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); + + /** + * 取消绑定社交用户 + * + * @param reqDTO 解绑 + */ + void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO); + + /** + * 校验社交用户的认证信息是否正确 + * 如果校验不通过,则抛出 {@link ServiceException} 业务异常 + * + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + */ + void checkSocialUser(Integer type, String code, String state); + + /** + * 获得社交用户的绑定用户编号 + * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 该方法会执行和 {@link #checkSocialUser(Integer, String, String)} 一样的逻辑。 + * 所以在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 + * + * @param userType 用户类型 + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + * @return 绑定用户编号 + */ + Long getBindUserId(Integer userType, Integer type, String code, String state); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java new file mode 100644 index 0000000000..ccc1c62ae5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.system.api.social.dto; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 取消绑定社交用户 Request DTO + * + * @author 芋道源码 + */ +@Data +public class SocialUserBindReqDTO { + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + @NotNull(message = "用户类型不能为空") + private Integer userType; + + /** + * 社交平台的类型 + */ + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平台的类型不能为空") + private Integer type; + /** + * 授权码 + */ + @NotEmpty(message = "授权码不能为空") + private String code; + /** + * state + */ + @NotEmpty(message = "state 不能为空") + private String state; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java new file mode 100644 index 0000000000..56398a8aef --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.system.api.social.dto; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 社交绑定 Request DTO,使用 code 授权码 + * + * @author 芋道源码 + */ +@Data +public class SocialUserUnbindReqDTO { + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + @NotNull(message = "用户类型不能为空") + private Integer userType; + + /** + * 社交平台的类型 + */ + @InEnum(SocialTypeEnum.class) + @NotNull(message = "社交平台的类型不能为空") + private Integer type; + + /** + * 社交平台的 unionId + */ + @NotEmpty(message = "社交平台的 unionId 不能为空") + private String unionId; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java new file mode 100644 index 0000000000..d994b0cb33 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.system.api.user; + +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Admin 用户 API 接口 + * + * @author 芋道源码 + */ +public interface AdminUserApi { + + /** + * 通过用户 ID 查询用户 + * + * @param id 用户ID + * @return 用户对象信息 + */ + AdminUserRespDTO getUser(Long id); + + /** + * 获得指定部门的用户数组 + * + * @param deptIds 部门数组 + * @return 用户数组 + */ + List getUsersByDeptIds(Collection deptIds); + + /** + * 获得指定岗位的用户数组 + * + * @param postIds 岗位数组 + * @return 用户数组 + */ + List getUsersByPostIds(Collection postIds); + + /** + * 获得用户 Map + * + * @param ids 用户编号数组 + * @return 用户 Map + */ + Map getUserMap(Collection ids); + + /** + * 校验用户们是否有效。如下情况,视为无效: + * 1. 用户编号不存在 + * 2. 用户被禁用 + * + * @param ids 用户编号数组 + */ + void validUsers(Set ids); + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java new file mode 100644 index 0000000000..ac13c3a8b0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.system.api.user.dto; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import lombok.Data; + +import java.util.Set; + +/** + * Admin 用户 Response DTO + * + * @author 芋道源码 + */ +@Data +public class AdminUserRespDTO { + + /** + * 用户ID + */ + private Long id; + /** + * 用户昵称 + */ + private String nickname; + /** + * 帐号状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + /** + * 部门ID + */ + private Long deptId; + /** + * 岗位编号数组 + */ + private Set postIds; + /** + * 手机号码 + */ + private String mobile; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/DictTypeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/DictTypeConstants.java new file mode 100644 index 0000000000..c49524245c --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/DictTypeConstants.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.enums; + +/** + * System 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String USER_TYPE = "user_type"; // 用户类型 + String COMMON_STATUS = "common_status"; // 系统状态 + + // ========== SYSTEM 模块 ========== + + String USER_SEX = "system_user_sex"; // 用户性别 + + String OPERATE_TYPE = "sys_operate_type"; // 操作类型 + + String LOGIN_TYPE = "sys_login_type"; // 登录日志的类型 + String LOGIN_RESULT = "sys_login_result"; // 登录结果 + + String ERROR_CODE_TYPE = "system_error_code_type"; // 错误码的类型枚举 + + String SMS_CHANNEL_CODE = "sys_sms_channel_code"; // 短信渠道编码 + String SMS_TEMPLATE_TYPE = "sys_sms_template_type"; // 短信模板类型 + String SMS_SEND_STATUS = "sys_sms_send_status"; // 短信发送状态 + String SMS_RECEIVE_STATUS = "sys_sms_receive_status"; // 短信接收状态 + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 867f8e3594..4529c5145a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums; +package cn.iocoder.yudao.module.system.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; * * system 系统,使用 1-002-000-000 段 */ -public interface SysErrorCodeConstants { +public interface ErrorCodeConstants { // ========== AUTH 模块 1002000000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确"); @@ -87,12 +87,31 @@ public interface SysErrorCodeConstants { ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在"); ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板"); - // ========== 租户模块 1002012000 ========== - ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002012000, "租户不存在"); + // ========== 短信发送 1002012000 ========== + ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002012000, "手机号不存在"); + ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1002012001, "模板参数({})缺失"); + ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1002012002, "短信模板不存在"); - // ========== 错误码模块 1002013000 ========== - ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在"); - ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码"); + // ========== 短信验证码 1002013000 ========== + ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1002013000, "验证码不存在"); + ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1002013001, "验证码已过期"); + ErrorCode SMS_CODE_USED = new ErrorCode(1002013002, "验证码已使用"); + ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1002013004, "验证码不正确"); + ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1002013005, "超过每日短信发送数量"); + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1002013006, "短信发送过于频率"); + ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1002013007, "手机号已被使用"); + ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1002013008, "验证码未被使用"); + // ========== 租户模块 1002014000 ========== + ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002014000, "租户不存在"); + + // ========== 错误码模块 1002015000 ========== + ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002015000, "错误码不存在"); + ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002015001, "已经存在编码为【{}】的错误码"); + + // ========== 社交用户 1002015000 ========== + ErrorCode SOCIAL_USER_AUTH_FAILURE = new ErrorCode(1002015000, "社交授权失败,原因是:{}"); + ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002015001, "社交解绑失败,非当前用户绑定"); + ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002015001, "社交授权失败,找不到对应的用户"); } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginLogTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java similarity index 84% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginLogTypeEnum.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java index 5a844f1818..2f845fd105 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginLogTypeEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.logger; +package cn.iocoder.yudao.module.system.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysLoginLogTypeEnum { +public enum LoginLogTypeEnum { LOGIN_USERNAME(100), // 使用账号登录 LOGIN_SOCIAL(101), // 使用社交登录 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java index 218b2d97f6..7084e13da1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginResultEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.logger; +package cn.iocoder.yudao.module.system.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysLoginResultEnum { +public enum LoginResultEnum { SUCCESS(0), // 成功 BAD_CREDENTIALS(10), // 账号或密码不正确 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSceneEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSceneEnum.java new file mode 100644 index 0000000000..2edcf0a2d1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSceneEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.system.enums.sms; + +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 用户短信验证码发送场景的枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum SmsSceneEnum implements IntArrayValuable { + + MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"), + MEMBER_UPDATE_MOBILE(2, "user-sms-reset-password", "会员用户 - 修改手机"), + MEMBER_FORGET_PASSWORD(3, "user-sms-update-mobile", "会员用户 - 忘记密码"); + + // 如果未来希望管理后台支持手机验证码登陆,可以通过添加 ADMIN_MEMBER_LOGIN 枚举 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray(); + + /** + * 验证场景的编号 + */ + private final Integer scene; + /** + * 模版编码 + */ + private final String templateCode; + /** + * 描述 + */ + private final String description; + + @Override + public int[] array() { + return ARRAYS; + } + + public static SmsSceneEnum getCodeByScene(Integer scene) { + return ArrayUtil.firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene)); + } + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java similarity index 89% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java index 3dba5bda03..8744c3509b 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.social; +package cn.iocoder.yudao.module.system.enums.social; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ArrayUtil; @@ -16,7 +16,7 @@ import java.util.List; */ @Getter @AllArgsConstructor -public enum SysSocialTypeEnum implements IntArrayValuable { +public enum SocialTypeEnum implements IntArrayValuable { /** * Gitee @@ -51,7 +51,7 @@ public enum SysSocialTypeEnum implements IntArrayValuable { WECHAT_MINI_PROGRAM(33, "WECHAT_MINI_PROGRAM"), ; - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray(); public static final List WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type, WECHAT_MINI_PROGRAM.type); @@ -70,7 +70,7 @@ public enum SysSocialTypeEnum implements IntArrayValuable { return ARRAYS; } - public static SysSocialTypeEnum valueOfType(Integer type) { + public static SocialTypeEnum valueOfType(Integer type) { return ArrayUtil.firstMatch(o -> o.getType().equals(type), values()); } diff --git a/yudao-core-service/pom.xml b/yudao-module-system/yudao-module-system-impl/pom.xml similarity index 69% rename from yudao-core-service/pom.xml rename to yudao-module-system/yudao-module-system-impl/pom.xml index e233046117..eb0e53e15b 100644 --- a/yudao-core-service/pom.xml +++ b/yudao-module-system/yudao-module-system-impl/pom.xml @@ -4,29 +4,40 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> cn.iocoder.boot - yudao + yudao-module-system ${revision} 4.0.0 - - yudao-core-service + yudao-module-system-impl jar - yudao-core-service + ${artifactId} - 公共服务,通过 jar 包的方式,被 yudao-admin-server、yudao-user-server 使用。例如说: - 1. 日志相关:访问日志、登录日志、异常日志等等 - 2. 认证相关:在线 Session - 3. 短信相关:短信模板、短信日志 - 等等 + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 - https://github.com/YunaiV/ruoyi-vue-pro + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-member-api + ${revision} + + + cn.iocoder.boot + yudao-module-infra-api + ${revision} + + cn.iocoder.boot - yudao-spring-boot-starter-biz-dict + yudao-spring-boot-starter-biz-operatelog cn.iocoder.boot @@ -34,7 +45,11 @@ cn.iocoder.boot - yudao-spring-boot-starter-biz-pay + yudao-spring-boot-starter-biz-dict + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-data-permission cn.iocoder.boot @@ -46,17 +61,6 @@ - - cn.iocoder.boot - yudao-spring-boot-starter-web - - - - org.springframework.boot - spring-boot-configuration-processor - true - - cn.iocoder.boot yudao-spring-boot-starter-security @@ -73,24 +77,12 @@ yudao-spring-boot-starter-redis - - - cn.iocoder.boot - yudao-spring-boot-starter-config - - cn.iocoder.boot yudao-spring-boot-starter-mq - - - cn.iocoder.boot - yudao-spring-boot-starter-protection - - cn.iocoder.boot @@ -99,10 +91,9 @@ - - com.google.guava - guava + cn.iocoder.boot + yudao-spring-boot-starter-excel diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApiImpl.java new file mode 100644 index 0000000000..f8ab2a1695 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/auth/UserSessionApiImpl.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.system.api.auth; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.service.auth.UserSessionService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 在线用户 Session API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class UserSessionApiImpl implements UserSessionApi { + + @Resource + private UserSessionService userSessionService; + + @Override + public String createUserSession(LoginUser loginUser, String userIp, String userAgent) { + return userSessionService.createUserSession(loginUser, userIp, userAgent); + } + + @Override + public void refreshUserSession(String sessionId, LoginUser loginUser) { + userSessionService.refreshUserSession(sessionId, loginUser); + } + + @Override + public void deleteUserSession(String sessionId) { + userSessionService.deleteUserSession(sessionId); + } + + @Override + public LoginUser getLoginUser(String sessionId) { + return userSessionService.getLoginUser(sessionId); + } + + @Override + public Long getSessionTimeoutMillis() { + return userSessionService.getSessionTimeoutMillis(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java new file mode 100644 index 0000000000..27fbc2f13c --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.system.api.dept; + +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 部门 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class DeptApiImpl implements DeptApi { + + @Resource + private DeptService deptService; + + @Override + public DeptRespDTO getDept(Long id) { + DeptDO dept = deptService.getDept(id); + return DeptConvert.INSTANCE.convert03(dept); + } + + @Override + public List getDepts(Collection ids) { + List depts = deptService.getDepts(ids); + return DeptConvert.INSTANCE.convertList03(depts); + } + + @Override + public void validDepts(Collection ids) { + deptService.validDepts(ids); + } + + @Override + public Map getDeptMap(Set ids) { + Map depts = deptService.getDeptMap(ids); + return DeptConvert.INSTANCE.convertMap(depts); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApiImpl.java new file mode 100644 index 0000000000..9454193e70 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dept/PostApiImpl.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.api.dept; + +import cn.iocoder.yudao.module.system.service.dept.PostService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; + +/** + * 岗位 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class PostApiImpl implements PostApi { + + @Resource + private PostService postService; + + @Override + public void validPosts(Collection ids) { + postService.validPosts(ids); + } +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java new file mode 100644 index 0000000000..6db4fb8e04 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.system.api.dict; + +import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; + +/** + * 字典数据 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class DictDataApiImpl implements DictDataApi { + + @Resource + private DictDataService dictDataService; + + @Override + public void validDictDatas(String dictType, Collection values) { + dictDataService.validDictDatas(dictType, values); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApiImpl.java new file mode 100644 index 0000000000..b5f40e01a9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/logger/LoginLogApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.api.logger; + +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 登录日志的 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class LoginLogApiImpl implements LoginLogApi { + + @Resource + private LoginLogService loginLogService; + + @Override + public void createLoginLog(LoginLogCreateReqDTO reqDTO) { + loginLogService.createLoginLog(reqDTO); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java new file mode 100644 index 0000000000..5d2b550781 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/PermissionApiImpl.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.api.permission; + +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Set; + +/** + * 权限 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class PermissionApiImpl implements PermissionApi { + + @Resource + private PermissionService permissionService; + + @Override + public Set getUserRoleIdListByRoleIds(Collection roleIds) { + return permissionService.getUserRoleIdListByRoleIds(roleIds); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApiImpl.java new file mode 100644 index 0000000000..2c4f94737d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/permission/RoleApiImpl.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.api.permission; + +import cn.iocoder.yudao.module.system.service.permission.RoleService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; + +/** + * 角色 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class RoleApiImpl implements RoleApi { + + @Resource + private RoleService roleService; + + @Override + public void validRoles(Collection ids) { + roleService.validRoles(ids); + } +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java new file mode 100644 index 0000000000..81957e0828 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.api.sms; + +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.service.sms.SmsCodeService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 短信验证码 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class SmsCodeApiImpl implements SmsCodeApi { + + @Resource + private SmsCodeService smsCodeService; + + @Override + public void sendSmsCode(SmsCodeSendReqDTO reqDTO) { + smsCodeService.sendSmsCode(reqDTO); + } + + @Override + public void useSmsCode(SmsCodeUseReqDTO reqDTO) { + smsCodeService.useSmsCode(reqDTO); + } + + @Override + public void checkSmsCode(SmsCodeCheckReqDTO reqDTO) { + smsCodeService.checkSmsCode(reqDTO); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApiImpl.java new file mode 100644 index 0000000000..ee5812d3c3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsSendApiImpl.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.api.sms; + +import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 短信发送 API 接口 + * + * @author 芋道源码 + */ +@Service +@Validated +public class SmsSendApiImpl implements SmsSendApi { + + @Resource + private SmsSendService smsSendService; + + @Override + public Long sendSingleSmsToAdmin(SmsSendSingleToUserReqDTO reqDTO) { + return smsSendService.sendSingleSmsToAdmin(reqDTO.getMobile(), reqDTO.getUserId(), + reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); + } + + @Override + public Long sendSingleSmsToMember(SmsSendSingleToUserReqDTO reqDTO) { + return smsSendService.sendSingleSmsToMember(reqDTO.getMobile(), reqDTO.getUserId(), + reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java new file mode 100644 index 0000000000..02a7942bbc --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.system.api.social; + +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 社交用户的 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class SocialUserApiImpl implements SocialUserApi { + + @Resource + private SocialUserService socialUserService; + + @Override + public String getAuthorizeUrl(Integer type, String redirectUri) { + return socialUserService.getAuthorizeUrl(type, redirectUri); + } + + @Override + public void bindSocialUser(SocialUserBindReqDTO reqDTO) { + socialUserService.bindSocialUser(reqDTO); + } + + @Override + public void unbindSocialUser(SocialUserUnbindReqDTO reqDTO) { + socialUserService.unbindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(), + reqDTO.getType(), reqDTO.getUnionId()); + } + + @Override + public void checkSocialUser(Integer type, String code, String state) { + socialUserService.checkSocialUser(type, code, state); + } + + @Override + public Long getBindUserId(Integer userType, Integer type, String code, String state) { + return socialUserService.getBindUserId(userType, type, code, state); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java new file mode 100644 index 0000000000..372e6f5e6e --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.system.api.user; + +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Admin 用户 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class AdminUserApiImpl implements AdminUserApi { + + @Resource + private AdminUserService userService; + + @Override + public AdminUserRespDTO getUser(Long id) { + AdminUserDO user = userService.getUser(id); + return UserConvert.INSTANCE.convert4(user); + } + + @Override + public List getUsersByDeptIds(Collection deptIds) { + List users = userService.getUsersByDeptIds(deptIds); + return UserConvert.INSTANCE.convertList4(users); + } + + @Override + public List getUsersByPostIds(Collection postIds) { + List users = userService.getUsersByPostIds(postIds); + return UserConvert.INSTANCE.convertList4(users); + } + + @Override + public Map getUserMap(Collection ids) { + Map userMap = userService.getUserMap(ids); + return UserConvert.INSTANCE.convertMap4(userMap); + } + + @Override + public void validUsers(Set ids) { + userService.validUsers(ids); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http index f8e32a5b8d..25124ca336 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.http @@ -1,7 +1,7 @@ ### 请求 /login 接口 => 成功 -POST {{baseUrl}}/login +POST {{baseUrl}}/system/login Content-Type: application/json -tenant-id: 1 +tenant-id: {{adminTenentId}} { "username": "admin", @@ -11,16 +11,12 @@ tenant-id: 1 } ### 请求 /get-permission-info 接口 => 成功 -GET {{baseUrl}}/get-permission-info +GET {{baseUrl}}/system/get-permission-info Authorization: Bearer {{token}} -tenant-id: 1 +tenant-id: {{adminTenentId}} ### 请求 /list-menus 接口 => 成功 -GET {{baseUrl}}/list-menus +GET {{baseUrl}}/system/list-menus Authorization: Bearer {{token}} #Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a -tenant-id: 1 - -### 请求 /druid/xxx 接口 => 失败 TODO 临时测试 -GET http://127.0.0.1:8080/druid/123 -Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index aef8cc40ac..8c45215a4e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -1,21 +1,21 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; +import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; +import cn.iocoder.yudao.module.system.service.auth.AdminAuthService; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.service.permission.RoleService; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -34,62 +34,62 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUse import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds; -@Api(tags = "认证") +@Api(tags = "管理后台 - 认证") @RestController -@RequestMapping("/") +@RequestMapping("/system") // 暂时不跟 /auth 结尾 @Validated @Slf4j -public class SysAuthController { +public class AuthController { @Resource - private SysAuthService authService; + private AdminAuthService authService; @Resource - private SysUserCoreService userCoreService; + private AdminUserService userService; @Resource - private SysRoleService roleService; + private RoleService roleService; @Resource - private SysPermissionService permissionService; + private PermissionService permissionService; @Resource - private SysSocialCoreService socialCoreService; + private SocialUserService socialUserService; @PostMapping("/login") @ApiOperation("使用账号密码登录") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 - public CommonResult login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { + public CommonResult login(@RequestBody @Valid AuthLoginReqVO reqVO) { String token = authService.login(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AuthLoginRespVO.builder().token(token).build()); } @GetMapping("/get-permission-info") @ApiOperation("获取登录用户的权限信息") - public CommonResult getPermissionInfo() { + public CommonResult getPermissionInfo() { // 获得用户信息 - SysUserDO user = userCoreService.getUser(getLoginUserId()); + AdminUserDO user = userService.getUser(getLoginUserId()); if (user == null) { return null; } // 获得角色列表 - List roleList = roleService.getRolesFromCache(getLoginUserRoleIds()); + List roleList = roleService.getRolesFromCache(getLoginUserRoleIds()); // 获得菜单列表 - List menuList = permissionService.getRoleMenusFromCache( + List menuList = permissionService.getRoleMenusFromCache( getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()), SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 拼接结果返回 - return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList)); + return success(AuthConvert.INSTANCE.convert(user, roleList, menuList)); } @GetMapping("list-menus") @ApiOperation("获得登录用户的菜单列表") - public CommonResult> getMenus() { + public CommonResult> getMenus() { // 获得用户拥有的菜单列表 - List menuList = permissionService.getRoleMenusFromCache( + List menuList = permissionService.getRoleMenusFromCache( getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型 SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的 // 转换成 Tree 结构返回 - return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList)); + return success(AuthConvert.INSTANCE.buildMenuTree(menuList)); } // ========== 社交登录相关 ========== @@ -102,38 +102,38 @@ public class SysAuthController { }) public CommonResult socialAuthRedirect(@RequestParam("type") Integer type, @RequestParam("redirectUri") String redirectUri) { - return CommonResult.success(socialCoreService.getAuthorizeUrl(type, redirectUri)); + return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri)); } @PostMapping("/social-login") @ApiOperation("社交登录,使用 code 授权码") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 - public CommonResult socialLogin(@RequestBody @Valid SysAuthSocialLoginReqVO reqVO) { + public CommonResult socialLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) { String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AuthLoginRespVO.builder().token(token).build()); } @PostMapping("/social-login2") @ApiOperation("社交登录,使用 code 授权码 + 账号密码") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 - public CommonResult socialLogin2(@RequestBody @Valid SysAuthSocialLogin2ReqVO reqVO) { + public CommonResult socialLogin2(@RequestBody @Valid AuthSocialLogin2ReqVO reqVO) { String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(SysAuthLoginRespVO.builder().token(token).build()); + return success(AuthLoginRespVO.builder().token(token).build()); } @PostMapping("/social-bind") @ApiOperation("社交绑定,使用 code 授权码") - public CommonResult socialBind(@RequestBody @Valid SysAuthSocialBindReqVO reqVO) { + public CommonResult socialBind(@RequestBody @Valid AuthSocialBindReqVO reqVO) { authService.socialBind(getLoginUserId(), reqVO); return CommonResult.success(true); } @DeleteMapping("/social-unbind") @ApiOperation("取消社交绑定") - public CommonResult socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) { - socialCoreService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN); + public CommonResult socialUnbind(@RequestBody AuthSocialUnbindReqVO reqVO) { + socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getUnionId()); return CommonResult.success(true); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysUserSessionController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysUserSessionController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java index 25279ef802..00150fd8b5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysUserSessionController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/UserSessionController.java @@ -1,18 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysUserSessionConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageItemRespVO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; +import cn.iocoder.yudao.module.system.convert.auth.UserSessionConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.service.auth.UserSessionService; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -28,36 +27,35 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -@Api(tags = "用户 Session") +@Api(tags = "管理后台 - 用户 Session") @RestController @RequestMapping("/system/user-session") -public class SysUserSessionController { +public class UserSessionController { @Resource - private SysUserSessionService userSessionService; + private UserSessionService userSessionService; @Resource - private SysUserSessionCoreService userSessionCoreService; + private AdminUserService userService; + @Resource - private SysUserService userService; - @Resource - private SysDeptService deptService; + private DeptService deptService; @GetMapping("/page") @ApiOperation("获得 Session 分页列表") @PreAuthorize("@ss.hasPermission('system:user-session:page')") - public CommonResult> getUserSessionPage(@Validated SysUserSessionPageReqVO reqVO) { + public CommonResult> getUserSessionPage(@Validated UserSessionPageReqVO reqVO) { // 获得 Session 分页 - PageResult pageResult = userSessionService.getUserSessionPage(reqVO); + PageResult pageResult = userSessionService.getUserSessionPage(reqVO); // 获得拼接需要的数据 - Map userMap = userService.getUserMap( - convertList(pageResult.getList(), SysUserSessionDO::getUserId)); - Map deptMap = deptService.getDeptMap( - convertList(userMap.values(), SysUserDO::getDeptId)); + Map userMap = userService.getUserMap( + convertList(pageResult.getList(), UserSessionDO::getUserId)); + Map deptMap = deptService.getDeptMap( + convertList(userMap.values(), AdminUserDO::getDeptId)); // 拼接结果返回 - List sessionList = new ArrayList<>(pageResult.getList().size()); + List sessionList = new ArrayList<>(pageResult.getList().size()); pageResult.getList().forEach(session -> { - SysUserSessionPageItemRespVO respVO = SysUserSessionConvert.INSTANCE.convert(session); + UserSessionPageItemRespVO respVO = UserSessionConvert.INSTANCE.convert(session); sessionList.add(respVO); // 设置用户账号 MapUtils.findAndThen(userMap, session.getUserId(), user -> { @@ -75,7 +73,7 @@ public class SysUserSessionController { example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7") @PreAuthorize("@ss.hasPermission('system:user-session:delete')") public CommonResult deleteUserSession(@RequestParam("id") String id) { - userSessionCoreService.deleteUserSession(id); + userSessionService.deleteUserSession(id); return success(true); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginReqVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginReqVO.java index 366144ea24..8e9eb4ed20 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -11,12 +11,12 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; -@ApiModel("账号密码登录 Request VO") +@ApiModel("管理后台 - 账号密码登录 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthLoginReqVO { +public class AuthLoginReqVO { @ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma") @NotEmpty(message = "登录账号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginRespVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginRespVO.java index 381c3223e3..bd13ba3770 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthLoginRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,12 +7,12 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("账号密码登录 Response VO") +@ApiModel("管理后台 - 账号密码登录 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthLoginRespVO { +public class AuthLoginRespVO { @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma") private String token; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthMenuRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthMenuRespVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthMenuRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthMenuRespVO.java index c39354b109..1c46ec291b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthMenuRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthMenuRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,12 @@ import lombok.NoArgsConstructor; import java.util.List; -@ApiModel("登录用户的菜单信息 Response VO") +@ApiModel("管理后台 - 登录用户的菜单信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthMenuRespVO { +public class AuthMenuRespVO { @ApiModelProperty(value = "菜单名称", required = true, example = "芋道") private Long id; @@ -37,6 +37,6 @@ public class SysAuthMenuRespVO { /** * 子路由 */ - private List children; + private List children; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthPermissionInfoRespVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthPermissionInfoRespVO.java index c3bd0923b4..bada252057 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthPermissionInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthPermissionInfoRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,12 @@ import lombok.NoArgsConstructor; import java.util.Set; -@ApiModel(value = "登录用户的权限信息 Response VO", description = "额外包括用户信息和角色列表") +@ApiModel(value = "管理后台 - 登录用户的权限信息 Response VO", description = "额外包括用户信息和角色列表") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthPermissionInfoRespVO { +public class AuthPermissionInfoRespVO { @ApiModelProperty(value = "用户信息", required = true) private UserVO user; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialBindReqVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialBindReqVO.java index e92d3fc504..2a83329d81 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialBindReqVO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("社交绑定 Request VO,使用 code 授权码") +@ApiModel("管理后台 - 社交绑定 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthSocialBindReqVO { +public class AuthSocialBindReqVO { - @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值") + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLogin2ReqVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLogin2ReqVO.java index 13aaa71cc7..725a52d8cb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLogin2ReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -14,15 +14,15 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; -@ApiModel("社交登录 Request VO,使用 code 授权码 + 账号密码") +@ApiModel("管理后台 - 社交登录 Request VO,使用 code 授权码 + 账号密码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthSocialLogin2ReqVO { +public class AuthSocialLogin2ReqVO { - @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值") + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLoginReqVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLoginReqVO.java index 71d19685d0..4f51bcb989 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLoginReqVO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("社交登录 Request VO,使用 code 授权码") +@ApiModel("管理后台 - 社交登录 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthSocialLoginReqVO { +public class AuthSocialLoginReqVO { - @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值") + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialUnbindReqVO.java similarity index 66% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialUnbindReqVO.java index 096164ed70..774602681b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialUnbindReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -12,15 +12,15 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("取消社交绑定 Request VO,使用 code 授权码") +@ApiModel("管理后台 - 取消社交绑定 Request VO,使用 code 授权码") @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class SysAuthSocialUnbindReqVO { +public class AuthSocialUnbindReqVO { - @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") - @InEnum(SysSocialTypeEnum.class) + @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值") + @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageItemRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageItemRespVO.java index c67fa99aeb..ad12877efc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageItemRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.session; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -10,12 +10,12 @@ import lombok.NoArgsConstructor; import java.util.Date; -@ApiModel(value = "用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息") +@ApiModel(value = "管理后台 - 用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysUserSessionPageItemRespVO extends PageParam { +public class UserSessionPageItemRespVO extends PageParam { @ApiModelProperty(value = "Session 编号", required = true, example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7") private String id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageReqVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageReqVO.java index fb8f4f2b6d..7e85c87baf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/session/SysUserSessionPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/session/UserSessionPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session; +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.session; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -6,10 +6,10 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; -@ApiModel("在线用户 Session 分页 Request VO") +@ApiModel("管理后台 - 在线用户 Session 分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysUserSessionPageReqVO extends PageParam { +public class UserSessionPageReqVO extends PageParam { @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配") private String userIp; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.http similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.http index 0b1cf854bf..2033fac315 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.http @@ -1,2 +1,3 @@ ### 请求 /captcha/get-image 接口 => 成功 GET {{baseUrl}}/system/captcha/get-image +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.java index 94e3c9d0da..5fc0b0a6bb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/SysCaptchaController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/CaptchaController.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.common; +package cn.iocoder.yudao.module.system.controller.admin.common; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.common.vo.SysCaptchaImageRespVO; -import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; +import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO; +import cn.iocoder.yudao.module.system.service.common.CaptchaService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; @@ -13,17 +13,17 @@ import javax.annotation.Resource; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "验证码") +@Api(tags = "管理后台 - 验证码") @RestController @RequestMapping("/system/captcha") -public class SysCaptchaController { +public class CaptchaController { @Resource - private SysCaptchaService captchaService; + private CaptchaService captchaService; @GetMapping("/get-image") @ApiOperation("生成图片验证码") - public CommonResult getCaptchaImage() { + public CommonResult getCaptchaImage() { return success(captchaService.getCaptchaImage()); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/vo/SysCaptchaImageRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/vo/CaptchaImageRespVO.java similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/vo/SysCaptchaImageRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/vo/CaptchaImageRespVO.java index b3e9f2c247..cef5d0845d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/common/vo/SysCaptchaImageRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/common/vo/CaptchaImageRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.common.vo; +package cn.iocoder.yudao.module.system.controller.admin.common.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,14 +7,15 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("验证码图片 Response VO") +@ApiModel("管理后台 - 验证码图片 Response VO") @Data @Builder @NoArgsConstructor @AllArgsConstructor -public class SysCaptchaImageRespVO { +public class CaptchaImageRespVO { - @ApiModelProperty(value = "uuid", required = true, example = "1b3b7d00-83a8-4638-9e37-d67011855968", notes = "通过该 uuid 作为该验证码的标识") + @ApiModelProperty(value = "uuid", required = true, example = "1b3b7d00-83a8-4638-9e37-d67011855968", + notes = "通过该 uuid 作为该验证码的标识") private String uuid; @ApiModelProperty(value = "图片", required = true, notes = "验证码的图片内容,使用 Base64 编码") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysDeptController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysDeptController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java index 1bae57f324..0a292e243c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysDeptController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.dept.SysDeptConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.*; +import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -20,19 +20,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "部门") +@Api(tags = "管理后台 - 部门") @RestController @RequestMapping("/system/dept") @Validated -public class SysDeptController { +public class DeptController { @Resource - private SysDeptService deptService; + private DeptService deptService; @PostMapping("create") @ApiOperation("创建部门") @PreAuthorize("@ss.hasPermission('system:dept:create')") - public CommonResult createDept(@Valid @RequestBody SysDeptCreateReqVO reqVO) { + public CommonResult createDept(@Valid @RequestBody DeptCreateReqVO reqVO) { Long deptId = deptService.createDept(reqVO); return success(deptId); } @@ -40,7 +40,7 @@ public class SysDeptController { @PutMapping("update") @ApiOperation("更新部门") @PreAuthorize("@ss.hasPermission('system:dept:update')") - public CommonResult updateDept(@Valid @RequestBody SysDeptUpdateReqVO reqVO) { + public CommonResult updateDept(@Valid @RequestBody DeptUpdateReqVO reqVO) { deptService.updateDept(reqVO); return success(true); } @@ -57,30 +57,30 @@ public class SysDeptController { @GetMapping("/list") @ApiOperation("获取部门列表") @PreAuthorize("@ss.hasPermission('system:dept:query')") - public CommonResult> listDepts(SysDeptListReqVO reqVO) { - List list = deptService.getSimpleDepts(reqVO); - list.sort(Comparator.comparing(SysDeptDO::getSort)); - return success(SysDeptConvert.INSTANCE.convertList(list)); + public CommonResult> listDepts(DeptListReqVO reqVO) { + List list = deptService.getSimpleDepts(reqVO); + list.sort(Comparator.comparing(DeptDO::getSort)); + return success(DeptConvert.INSTANCE.convertList(list)); } @GetMapping("/list-all-simple") @ApiOperation(value = "获取部门精简信息列表", notes = "只包含被开启的部门,主要用于前端的下拉选项") - public CommonResult> getSimpleDepts() { + public CommonResult> getSimpleDepts() { // 获得部门列表,只要开启状态的 - SysDeptListReqVO reqVO = new SysDeptListReqVO(); + DeptListReqVO reqVO = new DeptListReqVO(); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - List list = deptService.getSimpleDepts(reqVO); + List list = deptService.getSimpleDepts(reqVO); // 排序后,返回给前端 - list.sort(Comparator.comparing(SysDeptDO::getSort)); - return success(SysDeptConvert.INSTANCE.convertList02(list)); + list.sort(Comparator.comparing(DeptDO::getSort)); + return success(DeptConvert.INSTANCE.convertList02(list)); } @GetMapping("/get") @ApiOperation("获得部门信息") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:dept:query')") - public CommonResult getDept(@RequestParam("id") Long id) { - return success(SysDeptConvert.INSTANCE.convert(deptService.getDept(id))); + public CommonResult getDept(@RequestParam("id") Long id) { + return success(DeptConvert.INSTANCE.convert(deptService.getDept(id))); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysPostController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysPostController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java index c27dc1c95e..5275dc0c43 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/SysPostController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.dept.SysPostConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*; +import cn.iocoder.yudao.module.system.convert.dept.PostConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.service.dept.PostService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -27,19 +27,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "岗位") +@Api(tags = "管理后台 - 岗位") @RestController @RequestMapping("/system/post") -@Valid -public class SysPostController { +@Validated +public class PostController { @Resource - private SysPostService postService; + private PostService postService; @PostMapping("/create") @ApiOperation("创建岗位") @PreAuthorize("@ss.hasPermission('system:post:create')") - public CommonResult createPost(@Valid @RequestBody SysPostCreateReqVO reqVO) { + public CommonResult createPost(@Valid @RequestBody PostCreateReqVO reqVO) { Long postId = postService.createPost(reqVO); return success(postId); } @@ -47,7 +47,7 @@ public class SysPostController { @PutMapping("/update") @ApiOperation("修改岗位") @PreAuthorize("@ss.hasPermission('system:post:update')") - public CommonResult updatePost(@Valid @RequestBody SysPostUpdateReqVO reqVO) { + public CommonResult updatePost(@Valid @RequestBody PostUpdateReqVO reqVO) { postService.updatePost(reqVO); return success(true); } @@ -64,36 +64,36 @@ public class SysPostController { @ApiOperation("获得岗位信息") @ApiImplicitParam(name = "id", value = "岗位编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:post:query')") - public CommonResult getPost(@RequestParam("id") Long id) { - return success(SysPostConvert.INSTANCE.convert(postService.getPost(id))); + public CommonResult getPost(@RequestParam("id") Long id) { + return success(PostConvert.INSTANCE.convert(postService.getPost(id))); } @GetMapping("/list-all-simple") @ApiOperation(value = "获取岗位精简信息列表", notes = "只包含被开启的岗位,主要用于前端的下拉选项") - public CommonResult> getSimplePosts() { + public CommonResult> getSimplePosts() { // 获得岗位列表,只要开启状态的 - List list = postService.getPosts(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); + List list = postService.getPosts(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); // 排序后,返回给前端 - list.sort(Comparator.comparing(SysPostDO::getSort)); - return success(SysPostConvert.INSTANCE.convertList02(list)); + list.sort(Comparator.comparing(PostDO::getSort)); + return success(PostConvert.INSTANCE.convertList02(list)); } @GetMapping("/page") @ApiOperation("获得岗位分页列表") @PreAuthorize("@ss.hasPermission('system:post:query')") - public CommonResult> getPostPage(@Validated SysPostPageReqVO reqVO) { - return success(SysPostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO))); + public CommonResult> getPostPage(@Validated PostPageReqVO reqVO) { + return success(PostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO))); } @GetMapping("/export") @ApiOperation("岗位管理") @PreAuthorize("@ss.hasPermission('system:post:export')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Validated SysPostExportReqVO reqVO) throws IOException { - List posts = postService.getPosts(reqVO); - List data = SysPostConvert.INSTANCE.convertList03(posts); + public void export(HttpServletResponse response, @Validated PostExportReqVO reqVO) throws IOException { + List posts = postService.getPosts(reqVO); + List data = PostConvert.INSTANCE.convertList03(posts); // 输出 - ExcelUtils.write(response, "岗位数据.xls", "岗位列表", SysPostExcelVO.class, data); + ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostExcelVO.class, data); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java index 8296a89bed..2609f90678 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java @@ -1,7 +1,5 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -15,7 +13,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysDeptBaseVO { +public class DeptBaseVO { @ApiModelProperty(value = "菜单名称", required = true, example = "芋道") @NotBlank(message = "部门名称不能为空") @@ -42,7 +40,7 @@ public class SysDeptBaseVO { @Size(max = 50, message = "邮箱长度不能超过50个字符") private String email; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 CommonStatusEnum 枚举") @NotNull(message = "状态不能为空") // @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptCreateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java index c5c5aac56d..efd6c39a3e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptCreateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("部门创建 Request VO") +@ApiModel("管理后台 - 部门创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysDeptCreateReqVO extends SysDeptBaseVO { +public class DeptCreateReqVO extends DeptBaseVO { } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptListReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptListReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java index b47bc53be4..c4ff552438 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptListReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel("部门列表 Request VO") +@ApiModel("管理后台 - 部门列表 Request VO") @Data -public class SysDeptListReqVO { +public class DeptListReqVO { @ApiModelProperty(value = "部门名称", example = "芋道", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java index 325cce6b1e..072df230a7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,15 +7,15 @@ import lombok.EqualsAndHashCode; import java.util.Date; -@ApiModel("部门信息 Response VO") +@ApiModel("管理后台 - 部门信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDeptRespVO extends SysDeptBaseVO { +public class DeptRespVO extends DeptBaseVO { @ApiModelProperty(value = "部门编号", required = true, example = "1024") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java index bf9c8bdc5c..1a3d64f6e5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("部门精简信息 Response VO") +@ApiModel("管理后台 - 部门精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class SysDeptSimpleRespVO { +public class DeptSimpleRespVO { @ApiModelProperty(value = "部门编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java index 5838d1dd1a..3e2f13a849 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/dept/SysDeptUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("部门更新 Request VO") +@ApiModel("管理后台 - 部门更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDeptUpdateReqVO extends SysDeptBaseVO { +public class DeptUpdateReqVO extends DeptBaseVO { @ApiModelProperty(value = "部门编号", required = true, example = "1024") @NotNull(message = "部门编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java index c6ed5c82a1..98c1bf212e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysPostBaseVO { +public class PostBaseVO { @ApiModelProperty(value = "岗位名称", required = true, example = "小博主") @NotBlank(message = "岗位名称不能为空") @@ -28,7 +28,7 @@ public class SysPostBaseVO { @NotNull(message = "显示顺序不能为空") private Integer sort; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "备注", example = "快乐的备注") diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java new file mode 100644 index 0000000000..547739c0d0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@ApiModel("管理后台 - 岗位创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class PostCreateReqVO extends PostBaseVO { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java index acc23c3f8c..0053a78951 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import lombok.Data; * 岗位 Excel 导出响应 VO */ @Data -public class SysPostExcelVO { +public class PostExcelVO { @ExcelProperty("岗位序号") private Long id; @@ -25,7 +25,7 @@ public class SysPostExcelVO { private Integer sort; @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private String status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java index 465639236a..735bfcce19 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel(value = "岗位导出 Request VO", description = "参数和 SysPostExcelVO 是一致的") +@ApiModel(value = "管理后台 - 岗位导出 Request VO", description = "参数和 PostExcelVO 是一致的") @Data -public class SysPostExportReqVO { +public class PostExportReqVO { @ApiModelProperty(value = "岗位编码", example = "yudao", notes = "模糊匹配") private String code; @@ -14,7 +14,7 @@ public class SysPostExportReqVO { @ApiModelProperty(value = "岗位名称", example = "芋道", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostListReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostListReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java index 0e700a9c56..58ba469e12 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostListReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java @@ -1,19 +1,19 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; -@ApiModel("岗位列表 Request VO") +@ApiModel("管理后台 - 岗位列表 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysPostListReqVO extends SysPostBaseVO { +public class PostListReqVO extends PostBaseVO { @ApiModelProperty(value = "岗位名称", example = "芋道", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java index 432e16039b..be9ebeab49 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -6,10 +6,10 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; -@ApiModel("岗位分页 Request VO") +@ApiModel("管理后台 - 岗位分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysPostPageReqVO extends PageParam { +public class PostPageReqVO extends PageParam { @ApiModelProperty(value = "岗位编码", example = "yudao", notes = "模糊匹配") private String code; @@ -17,7 +17,7 @@ public class SysPostPageReqVO extends PageParam { @ApiModelProperty(value = "岗位名称", example = "芋道", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java index cfd42a204d..834e686179 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import java.util.Date; -@ApiModel("岗位信息 Response VO") +@ApiModel("管理后台 - 岗位信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysPostRespVO extends SysPostBaseVO { +public class PostRespVO extends PostBaseVO { @ApiModelProperty(value = "岗位序号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java index 244667f068..0334a7652a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("岗位精简信息 Response VO") +@ApiModel("管理后台 - 岗位精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class SysPostSimpleRespVO { +public class PostSimpleRespVO { @ApiModelProperty(value = "岗位编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java index cc95c9cd31..aeb91998b2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dept/vo/post/SysPostUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post; +package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("岗位更新 Request VO") +@ApiModel("管理后台 - 岗位更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysPostUpdateReqVO extends SysPostBaseVO { +public class PostUpdateReqVO extends PostBaseVO { @ApiModelProperty(value = "岗位编号", required = true, example = "1024") @NotNull(message = "岗位编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.http similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.http index f7890dc67c..f524315026 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.http @@ -1,3 +1,4 @@ ### 请求 /menu/list 接口 => 成功 GET {{baseUrl}}/system/dict-data/list-all-simple Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java index 5db6ccf6dc..124e5fd054 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictDataController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict; +package cn.iocoder.yudao.module.system.controller.admin.dict; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictDataConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.*; +import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -24,19 +24,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "字典数据") +@Api(tags = "管理后台 - 字典数据") @RestController @RequestMapping("/system/dict-data") @Validated -public class SysDictDataController { +public class DictDataController { @Resource - private SysDictDataService dictDataService; + private DictDataService dictDataService; @PostMapping("/create") @ApiOperation("新增字典数据") @PreAuthorize("@ss.hasPermission('system:dict:create')") - public CommonResult createDictData(@Valid @RequestBody SysDictDataCreateReqVO reqVO) { + public CommonResult createDictData(@Valid @RequestBody DictDataCreateReqVO reqVO) { Long dictDataId = dictDataService.createDictData(reqVO); return success(dictDataId); } @@ -44,7 +44,7 @@ public class SysDictDataController { @PutMapping("update") @ApiOperation("修改字典数据") @PreAuthorize("@ss.hasPermission('system:dict:update')") - public CommonResult updateDictData(@Valid @RequestBody SysDictDataUpdateReqVO reqVO) { + public CommonResult updateDictData(@Valid @RequestBody DictDataUpdateReqVO reqVO) { dictDataService.updateDictData(reqVO); return success(true); } @@ -61,35 +61,35 @@ public class SysDictDataController { @GetMapping("/list-all-simple") @ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地") // 无需添加权限认证,因为前端全局都需要 - public CommonResult> getSimpleDictDatas() { - List list = dictDataService.getDictDatas(); - return success(SysDictDataConvert.INSTANCE.convertList(list)); + public CommonResult> getSimpleDictDatas() { + List list = dictDataService.getDictDatas(); + return success(DictDataConvert.INSTANCE.convertList(list)); } @GetMapping("/page") @ApiOperation("/获得字典类型的分页列表") @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult> getDictTypePage(@Valid SysDictDataPageReqVO reqVO) { - return success(SysDictDataConvert.INSTANCE.convertPage(dictDataService.getDictDataPage(reqVO))); + public CommonResult> getDictTypePage(@Valid DictDataPageReqVO reqVO) { + return success(DictDataConvert.INSTANCE.convertPage(dictDataService.getDictDataPage(reqVO))); } @GetMapping(value = "/get") @ApiOperation("/查询字典数据详细") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult getDictData(@RequestParam("id") Long id) { - return success(SysDictDataConvert.INSTANCE.convert(dictDataService.getDictData(id))); + public CommonResult getDictData(@RequestParam("id") Long id) { + return success(DictDataConvert.INSTANCE.convert(dictDataService.getDictData(id))); } @GetMapping("/export") @ApiOperation("导出字典数据") @PreAuthorize("@ss.hasPermission('system:dict:export')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Valid SysDictDataExportReqVO reqVO) throws IOException { - List list = dictDataService.getDictDatas(reqVO); - List data = SysDictDataConvert.INSTANCE.convertList02(list); + public void export(HttpServletResponse response, @Valid DictDataExportReqVO reqVO) throws IOException { + List list = dictDataService.getDictDatas(reqVO); + List data = DictDataConvert.INSTANCE.convertList02(list); // 输出 - ExcelUtils.write(response, "字典数据.xls", "数据列表", SysDictDataExcelVO.class, data); + ExcelUtils.write(response, "字典数据.xls", "数据列表", DictDataExcelVO.class, data); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictTypeController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictTypeController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java index 4057f8a3f7..e7c9b88948 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictTypeController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict; +package cn.iocoder.yudao.module.system.controller.admin.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictTypeConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictTypeService; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.*; +import cn.iocoder.yudao.module.system.convert.dict.DictTypeConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import cn.iocoder.yudao.module.system.service.dict.DictTypeService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -24,19 +24,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "字典类型") +@Api(tags = "管理后台 - 字典类型") @RestController @RequestMapping("/system/dict-type") @Validated -public class SysDictTypeController { +public class DictTypeController { @Resource - private SysDictTypeService dictTypeService; + private DictTypeService dictTypeService; @PostMapping("/create") @ApiOperation("创建字典类型") @PreAuthorize("@ss.hasPermission('system:dict:create')") - public CommonResult createDictType(@Valid @RequestBody SysDictTypeCreateReqVO reqVO) { + public CommonResult createDictType(@Valid @RequestBody DictTypeCreateReqVO reqVO) { Long dictTypeId = dictTypeService.createDictType(reqVO); return success(dictTypeId); } @@ -44,7 +44,7 @@ public class SysDictTypeController { @PutMapping("/update") @ApiOperation("修改字典类型") @PreAuthorize("@ss.hasPermission('system:dict:update')") - public CommonResult updateDictType(@Valid @RequestBody SysDictTypeUpdateReqVO reqVO) { + public CommonResult updateDictType(@Valid @RequestBody DictTypeUpdateReqVO reqVO) { dictTypeService.updateDictType(reqVO); return success(true); } @@ -61,35 +61,35 @@ public class SysDictTypeController { @ApiOperation("/获得字典类型的分页列表") @GetMapping("/page") @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult> pageDictTypes(@Valid SysDictTypePageReqVO reqVO) { - return success(SysDictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO))); + public CommonResult> pageDictTypes(@Valid DictTypePageReqVO reqVO) { + return success(DictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO))); } @ApiOperation("/查询字典类型详细") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @GetMapping(value = "/get") @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult getDictType(@RequestParam("id") Long id) { - return success(SysDictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id))); + public CommonResult getDictType(@RequestParam("id") Long id) { + return success(DictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id))); } @GetMapping("/list-all-simple") @ApiOperation(value = "获得全部字典类型列表", notes = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项") // 无需添加权限认证,因为前端全局都需要 - public CommonResult> listSimpleDictTypes() { - List list = dictTypeService.getDictTypeList(); - return success(SysDictTypeConvert.INSTANCE.convertList(list)); + public CommonResult> listSimpleDictTypes() { + List list = dictTypeService.getDictTypeList(); + return success(DictTypeConvert.INSTANCE.convertList(list)); } @ApiOperation("导出数据类型") @GetMapping("/export") @PreAuthorize("@ss.hasPermission('system:dict:query')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Valid SysDictTypeExportReqVO reqVO) throws IOException { - List list = dictTypeService.getDictTypeList(reqVO); - List data = SysDictTypeConvert.INSTANCE.convertList02(list); + public void export(HttpServletResponse response, @Valid DictTypeExportReqVO reqVO) throws IOException { + List list = dictTypeService.getDictTypeList(reqVO); + List data = DictTypeConvert.INSTANCE.convertList02(list); // 输出 - ExcelUtils.write(response, "字典类型.xls", "类型列表", SysDictTypeExcelVO.class, data); + ExcelUtils.write(response, "字典类型.xls", "类型列表", DictTypeExcelVO.class, data); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java index adb4bb2f18..2cefd83cb8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysDictDataBaseVO { +public class DictDataBaseVO { @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") @NotNull(message = "显示顺序不能为空") @@ -33,9 +33,9 @@ public class SysDictDataBaseVO { @Size(max = 100, message = "字典类型长度不能超过100个字符") private String dictType; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 CommonStatusEnum 枚举") @NotNull(message = "状态不能为空") -// @InEnum(value = SysCommonStatusEnum.class, message = "修改状态必须是 {value}") +// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; @ApiModelProperty(value = "备注", example = "我是一个角色") diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java new file mode 100644 index 0000000000..57dc770d09 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@ApiModel("管理后台 - 字典数据创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class DictDataCreateReqVO extends DictDataBaseVO { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java index 23174a087f..6dcb9bb505 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import lombok.Data; * 字典数据 Excel 导出响应 VO */ @Data -public class SysDictDataExcelVO { +public class DictDataExcelVO { @ExcelProperty("字典编码") private Long id; @@ -28,7 +28,7 @@ public class SysDictDataExcelVO { private String dictType; @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java index 43e8884f26..90290cbdbc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,9 +6,9 @@ import lombok.Data; import javax.validation.constraints.Size; -@ApiModel("字典类型导出 Request VO") +@ApiModel("管理后台 - 字典类型导出 Request VO") @Data -public class SysDictDataExportReqVO { +public class DictDataExportReqVO { @ApiModelProperty(value = "字典标签", example = "芋道") @Size(max = 100, message = "字典标签长度不能超过100个字符") @@ -18,7 +18,7 @@ public class SysDictDataExportReqVO { @Size(max = 100, message = "字典类型类型长度不能超过100个字符") private String dictType; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java index 0cd2a488de..9df4605df6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -8,10 +8,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.Size; -@ApiModel("字典类型分页列表 Request VO") +@ApiModel("管理后台 - 字典类型分页列表 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictDataPageReqVO extends PageParam { +public class DictDataPageReqVO extends PageParam { @ApiModelProperty(value = "字典标签", example = "芋道") @Size(max = 100, message = "字典标签长度不能超过100个字符") @@ -21,7 +21,7 @@ public class SysDictDataPageReqVO extends PageParam { @Size(max = 100, message = "字典类型类型长度不能超过100个字符") private String dictType; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java index fa6f77fcad..697097008e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,12 @@ import lombok.NoArgsConstructor; import java.util.Date; -@ApiModel("字典数据信息 Response VO") +@ApiModel("管理后台 - 字典数据信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysDictDataRespVO extends SysDictDataBaseVO { +public class DictDataRespVO extends DictDataBaseVO { @ApiModelProperty(value = "字典数据编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java index e4a09e6954..c3dd560529 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSimpleRespVO.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel("数据字典精简 Response VO") +@ApiModel("管理后台 - 数据字典精简 Response VO") @Data -public class SysDictDataSimpleRespVO { +public class DictDataSimpleRespVO { @ApiModelProperty(value = "字典类型", required = true, example = "gender") private String dictType; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java index ccbd455840..f6f9b81a23 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/data/SysDictDataUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("字典数据更新 Request VO") +@ApiModel("管理后台 - 字典数据更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictDataUpdateReqVO extends SysDictDataBaseVO { +public class DictDataUpdateReqVO extends DictDataBaseVO { @ApiModelProperty(value = "字典数据编号", required = true, example = "1024") @NotNull(message = "字典数据编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java index c4458cd26b..4da6da0b31 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysDictTypeBaseVO { +public class DictTypeBaseVO { @ApiModelProperty(value = "字典名称", required = true, example = "性别") @NotBlank(message = "字典名称不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeCreateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java index 6f84ecfd70..ee2f45ae19 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeCreateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,10 +8,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -@ApiModel("字典类型创建 Request VO") +@ApiModel("管理后台 - 字典类型创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictTypeCreateReqVO extends SysDictTypeBaseVO { +public class DictTypeCreateReqVO extends DictTypeBaseVO { @ApiModelProperty(value = "字典类型", required = true, example = "sys_common_sex") @NotNull(message = "字典类型不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java index fbb4da3670..b7db46d0eb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import lombok.Data; * 字典类型 Excel 导出响应 VO */ @Data -public class SysDictTypeExcelVO { +public class DictTypeExcelVO { @ExcelProperty("字典主键") private Long id; @@ -22,7 +22,7 @@ public class SysDictTypeExcelVO { private String type; @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java index cfe54e563d..1043a1e72a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("字典类型分页列表 Request VO") +@ApiModel("管理后台 - 字典类型分页列表 Request VO") @Data -public class SysDictTypeExportReqVO { +public class DictTypeExportReqVO { @ApiModelProperty(value = "字典类型名称", example = "芋道", notes = "模糊匹配") private String name; @@ -19,7 +19,7 @@ public class SysDictTypeExportReqVO { @ApiModelProperty(value = "字典类型", example = "sys_common_sex", notes = "模糊匹配") private String type; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java index 434ca272d0..84635621c4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypePageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,10 +12,10 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("字典类型分页列表 Request VO") +@ApiModel("管理后台 - 字典类型分页列表 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictTypePageReqVO extends PageParam { +public class DictTypePageReqVO extends PageParam { @ApiModelProperty(value = "字典类型名称", example = "芋道", notes = "模糊匹配") private String name; @@ -24,7 +24,7 @@ public class SysDictTypePageReqVO extends PageParam { @Size(max = 100, message = "字典类型类型长度不能超过100个字符") private String type; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java index fd216bc8fe..9cfafdfa40 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,12 +9,12 @@ import lombok.NoArgsConstructor; import java.util.Date; -@ApiModel("字典类型信息 Response VO") +@ApiModel("管理后台 - 字典类型信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysDictTypeRespVO extends SysDictTypeBaseVO { +public class DictTypeRespVO extends DictTypeBaseVO { @ApiModelProperty(value = "字典类型编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java index 7d0ef04dce..8cca026a9f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("字典类型精简信息 Response VO") +@ApiModel("管理后台 - 字典类型精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class SysDictTypeSimpleRespVO { +public class DictTypeSimpleRespVO { @ApiModelProperty(value = "字典类型编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java index 9b887bd5d7..00955f4fe3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/vo/type/SysDictTypeUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type; +package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("字典类型更新 Request VO") +@ApiModel("管理后台 - 字典类型更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictTypeUpdateReqVO extends SysDictTypeBaseVO { +public class DictTypeUpdateReqVO extends DictTypeBaseVO { @ApiModelProperty(value = "字典类型编号", required = true, example = "1024") @NotNull(message = "字典类型编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.http similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.http index 76226d18e3..06b8723185 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.http @@ -1,7 +1,8 @@ -### +### 创建错误码 POST {{baseUrl}}/inra/error-code/create Authorization: Bearer {{token}} -Content-Type:application/json +Content-Type: application/json +tenant-id: {{adminTenentId}} { "code": 200, diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java index f7dd4a4111..e3161b8aa1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/SysErrorCodeController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode; +package cn.iocoder.yudao.module.system.controller.admin.errorcode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.convert.errorcode.SysErrorCodeConvert; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; -import cn.iocoder.yudao.adminserver.modules.system.service.errorcode.SysErrorCodeService; +import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.*; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; +import cn.iocoder.yudao.module.system.service.errorcode.ErrorCodeService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -24,26 +24,26 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "错误码") +@Api(tags = "管理后台 - 错误码") @RestController @RequestMapping("/system/error-code") @Validated -public class SysErrorCodeController { +public class ErrorCodeController { @Resource - private SysErrorCodeService errorCodeService; + private ErrorCodeService errorCodeService; @PostMapping("/create") @ApiOperation("创建错误码") @PreAuthorize("@ss.hasPermission('system:error-code:create')") - public CommonResult createErrorCode(@Valid @RequestBody SysErrorCodeCreateReqVO createReqVO) { + public CommonResult createErrorCode(@Valid @RequestBody ErrorCodeCreateReqVO createReqVO) { return success(errorCodeService.createErrorCode(createReqVO)); } @PutMapping("/update") @ApiOperation("更新错误码") @PreAuthorize("@ss.hasPermission('system:error-code:update')") - public CommonResult updateErrorCode(@Valid @RequestBody SysErrorCodeUpdateReqVO updateReqVO) { + public CommonResult updateErrorCode(@Valid @RequestBody ErrorCodeUpdateReqVO updateReqVO) { errorCodeService.updateErrorCode(updateReqVO); return success(true); } @@ -61,29 +61,29 @@ public class SysErrorCodeController { @ApiOperation("获得错误码") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:error-code:query')") - public CommonResult getErrorCode(@RequestParam("id") Long id) { - SysErrorCodeDO errorCode = errorCodeService.getErrorCode(id); - return success(SysErrorCodeConvert.INSTANCE.convert(errorCode)); + public CommonResult getErrorCode(@RequestParam("id") Long id) { + ErrorCodeDO errorCode = errorCodeService.getErrorCode(id); + return success(ErrorCodeConvert.INSTANCE.convert(errorCode)); } @GetMapping("/page") @ApiOperation("获得错误码分页") @PreAuthorize("@ss.hasPermission('system:error-code:query')") - public CommonResult> getErrorCodePage(@Valid SysErrorCodePageReqVO pageVO) { - PageResult pageResult = errorCodeService.getErrorCodePage(pageVO); - return success(SysErrorCodeConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getErrorCodePage(@Valid ErrorCodePageReqVO pageVO) { + PageResult pageResult = errorCodeService.getErrorCodePage(pageVO); + return success(ErrorCodeConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出错误码 Excel") @PreAuthorize("@ss.hasPermission('system:error-code:export')") @OperateLog(type = EXPORT) - public void exportErrorCodeExcel(@Valid SysErrorCodeExportReqVO exportReqVO, + public void exportErrorCodeExcel(@Valid ErrorCodeExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = errorCodeService.getErrorCodeList(exportReqVO); + List list = errorCodeService.getErrorCodeList(exportReqVO); // 导出 Excel - List datas = SysErrorCodeConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "错误码.xls", "数据", SysErrorCodeExcelVO.class, datas); + List datas = ErrorCodeConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "错误码.xls", "数据", ErrorCodeExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java index 118c38b251..150401aa32 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysErrorCodeBaseVO { +public class ErrorCodeBaseVO { @ApiModelProperty(value = "应用名", required = true, example = "dashboard") @NotNull(message = "应用名不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoCreateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java index b1866f780e..a0f36af1a9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoCreateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("字典类型创建 Request VO") +@ApiModel("管理后台 - 错误码创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ToolTestDemoCreateReqVO extends ToolTestDemoBaseVO { +public class ErrorCodeCreateReqVO extends ErrorCodeBaseVO { } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java index 8e20b6e4aa..a9c317bfba 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; +//import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -14,13 +14,13 @@ import java.util.Date; * @author 芋道源码 */ @Data -public class SysErrorCodeExcelVO { +public class ErrorCodeExcelVO { @ExcelProperty("错误码编号") private Long id; @ExcelProperty(value = "错误码类型", converter = DictConvert.class) - @DictFormat(InfDictTypeConstants.ERROR_CODE_TYPE) + @DictFormat("inf_error_code_type") // TODO 芋艿:得思考下杂解决枚举值 private Integer type; @ExcelProperty("应用名") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java index 6047679942..9f716152c8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "错误码 Excel 导出 Request VO", description = "参数和 InfErrorCodePageReqVO 是一致的") +@ApiModel(value = "管理后台 - 错误码 Excel 导出 Request VO", description = "参数和 InfErrorCodePageReqVO 是一致的") @Data -public class SysErrorCodeExportReqVO { +public class ErrorCodeExportReqVO { @ApiModelProperty(value = "错误码类型", example = "1") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java index baf781a595..ff3d09833c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodePageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,13 +12,13 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("错误码分页 Request VO") +@ApiModel("管理后台 - 错误码分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysErrorCodePageReqVO extends PageParam { +public class ErrorCodePageReqVO extends PageParam { - @ApiModelProperty(value = "错误码类型", example = "1", notes = "参见 SysErrorCodeTypeEnum 枚举类") + @ApiModelProperty(value = "错误码类型", example = "1", notes = "参见 ErrorCodeTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "应用名", example = "dashboard") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java index 69798f3f4b..8b5cd3e725 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,16 +8,16 @@ import lombok.ToString; import java.util.Date; -@ApiModel("错误码 Response VO") +@ApiModel("管理后台 - 错误码 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysErrorCodeRespVO extends SysErrorCodeBaseVO { +public class ErrorCodeRespVO extends ErrorCodeBaseVO { @ApiModelProperty(value = "错误码编号", required = true, example = "1024") private Long id; - @ApiModelProperty(value = "错误码类型", required = true, example = "1", notes = "参见 SysErrorCodeTypeEnum 枚举类") + @ApiModelProperty(value = "错误码类型", required = true, example = "1", notes = "参见 ErrorCodeTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "创建时间", required = true) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java index 11f124a9b1..ff16c02834 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/errorcode/vo/SysErrorCodeUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo; +package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("错误码更新 Request VO") +@ApiModel("管理后台 - 错误码更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysErrorCodeUpdateReqVO extends SysErrorCodeBaseVO { +public class ErrorCodeUpdateReqVO extends ErrorCodeBaseVO { @ApiModelProperty(value = "错误码编号", required = true, example = "1024") @NotNull(message = "错误码编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysLoginLogController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysLoginLogController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java index 24260c4a2f..7cb3ac4b7a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysLoginLogController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger; +package cn.iocoder.yudao.module.system.controller.admin.logger; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysLoginLogConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogRespVO; +import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; @@ -27,33 +27,33 @@ import java.util.List; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "登录日志") +@Api(tags = "管理后台 - 登录日志") @RestController @RequestMapping("/system/login-log") @Validated -public class SysLoginLogController { +public class LoginLogController { @Resource - private SysLoginLogService loginLogService; + private LoginLogService loginLogService; @GetMapping("/page") @ApiOperation("获得登录日志分页列表") @PreAuthorize("@ss.hasPermission('system:login-log:query')") - public CommonResult> getLoginLogPage(@Valid SysLoginLogPageReqVO reqVO) { - PageResult page = loginLogService.getLoginLogPage(reqVO); - return CommonResult.success(SysLoginLogConvert.INSTANCE.convertPage(page)); + public CommonResult> getLoginLogPage(@Valid LoginLogPageReqVO reqVO) { + PageResult page = loginLogService.getLoginLogPage(reqVO); + return CommonResult.success(LoginLogConvert.INSTANCE.convertPage(page)); } @GetMapping("/export") @ApiOperation("导出登录日志 Excel") @PreAuthorize("@ss.hasPermission('system:login-log:export')") @OperateLog(type = EXPORT) - public void exportLoginLog(HttpServletResponse response, @Valid SysLoginLogExportReqVO reqVO) throws IOException { - List list = loginLogService.getLoginLogList(reqVO); + public void exportLoginLog(HttpServletResponse response, @Valid LoginLogExportReqVO reqVO) throws IOException { + List list = loginLogService.getLoginLogList(reqVO); // 拼接数据 - List data = SysLoginLogConvert.INSTANCE.convertList(list); + List data = LoginLogConvert.INSTANCE.convertList(list); // 输出 - ExcelUtils.write(response, "登录日志.xls", "数据列表", SysLoginLogExcelVO.class, data); + ExcelUtils.write(response, "登录日志.xls", "数据列表", LoginLogExcelVO.class, data); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http index 3b88719963..f667482da4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http @@ -1,3 +1,4 @@ ### 请求 /system/operate-log/demo 接口 => 成功 GET {{baseUrl}}/system/operate-log/demo Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java index e44a4dd4d7..d23477eb82 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/SysOperateLogController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java @@ -1,20 +1,20 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger; +package cn.iocoder.yudao.module.system.controller.admin.logger; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogRespVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysOperateLogConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysOperateLogService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; +import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.logger.OperateLogService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.security.access.prepost.PreAuthorize; @@ -35,30 +35,30 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "操作日志") +@Api(tags = "管理后台 - 操作日志") @RestController @RequestMapping("/system/operate-log") @Validated -public class SysOperateLogController { +public class OperateLogController { @Resource - private SysOperateLogService operateLogService; + private OperateLogService operateLogService; @Resource - private SysUserService userService; + private AdminUserService userService; @GetMapping("/page") @ApiOperation("查看操作日志分页列表") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") - public CommonResult> pageOperateLog(@Valid SysOperateLogPageReqVO reqVO) { - PageResult pageResult = operateLogService.getOperateLogPage(reqVO); + public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO reqVO) { + PageResult pageResult = operateLogService.getOperateLogPage(reqVO); // 获得拼接需要的数据 - Collection userIds = CollectionUtils.convertList(pageResult.getList(), SysOperateLogDO::getUserId); - Map userMap = userService.getUserMap(userIds); + Collection userIds = CollectionUtils.convertList(pageResult.getList(), OperateLogDO::getUserId); + Map userMap = userService.getUserMap(userIds); // 拼接数据 - List list = new ArrayList<>(pageResult.getList().size()); + List list = new ArrayList<>(pageResult.getList().size()); pageResult.getList().forEach(operateLog -> { - SysOperateLogRespVO respVO = SysOperateLogConvert.INSTANCE.convert(operateLog); + OperateLogRespVO respVO = OperateLogConvert.INSTANCE.convert(operateLog); list.add(respVO); // 拼接用户信息 MapUtils.findAndThen(userMap, operateLog.getUserId(), user -> respVO.setUserNickname(user.getNickname())); @@ -70,16 +70,16 @@ public class SysOperateLogController { @GetMapping("/export") @PreAuthorize("@ss.hasPermission('system:operate-log:export')") @OperateLog(type = EXPORT) - public void exportOperateLog(HttpServletResponse response, @Valid SysOperateLogExportReqVO reqVO) throws IOException { - List list = operateLogService.getOperateLogs(reqVO); + public void exportOperateLog(HttpServletResponse response, @Valid OperateLogExportReqVO reqVO) throws IOException { + List list = operateLogService.getOperateLogs(reqVO); // 获得拼接需要的数据 - Collection userIds = CollectionUtils.convertList(list, SysOperateLogDO::getUserId); - Map userMap = userService.getUserMap(userIds); + Collection userIds = CollectionUtils.convertList(list, OperateLogDO::getUserId); + Map userMap = userService.getUserMap(userIds); // 拼接数据 - List excelDataList = SysOperateLogConvert.INSTANCE.convertList(list, userMap); + List excelDataList = OperateLogConvert.INSTANCE.convertList(list, userMap); // 输出 - ExcelUtils.write(response, "操作日志.xls", "数据列表", SysOperateLogExcelVO.class, excelDataList); + ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogExcelVO.class, excelDataList); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java index a346d946f9..e8101f6e97 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -13,9 +13,9 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysLoginLogBaseVO { +public class LoginLogBaseVO { - @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 SysLoginLogTypeEnum 枚举类") + @ApiModelProperty(value = "日志类型", required = true, example = "1", notes = "参见 LoginLogTypeEnum 枚举类") @NotNull(message = "日志类型不能为空") private Integer logType; @@ -28,7 +28,7 @@ public class SysLoginLogBaseVO { @Size(max = 30, message = "用户账号长度不能超过30个字符") private String username; - @ApiModelProperty(value = "登录结果", required = true, example = "1", notes = "参见 SysLoginResultEnum 枚举类") + @ApiModelProperty(value = "登录结果", required = true, example = "1", notes = "参见 LoginResultEnum 枚举类") @NotNull(message = "登录结果不能为空") private Integer result; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java index 852e9146a7..300cd088d8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import java.util.Date; * 登录日志 Excel 导出响应 VO */ @Data -public class SysLoginLogExcelVO { +public class LoginLogExcelVO { @ExcelProperty("日志主键") private Long id; @@ -21,11 +21,11 @@ public class SysLoginLogExcelVO { private String username; @ExcelProperty(value = "日志类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.LOGIN_TYPE) + @DictFormat(DictTypeConstants.LOGIN_TYPE) private Integer logType; @ExcelProperty(value = "登录结果", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.LOGIN_RESULT) + @DictFormat(DictTypeConstants.LOGIN_RESULT) private Integer result; @ExcelProperty("登录 IP") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java index a85f926857..df1a57ea52 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("登录日志分页列表 Request VO") +@ApiModel("管理后台 - 登录日志分页列表 Request VO") @Data -public class SysLoginLogExportReqVO { +public class LoginLogExportReqVO { @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模拟匹配") private String userIp; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java index 52079094c2..ebefb728e2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -11,10 +11,10 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("登录日志分页列表 Request VO") +@ApiModel("管理后台 - 登录日志分页列表 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysLoginLogPageReqVO extends PageParam { +public class LoginLogPageReqVO extends PageParam { @ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模拟匹配") private String userIp; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java index 65aa6494d8..17177dadf2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/loginlog/SysLoginLogRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,11 +9,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; import java.util.Date; -@ApiModel("登录日志 Response VO") +@ApiModel("管理后台 - 登录日志 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysLoginLogRespVO extends SysLoginLogBaseVO { +public class LoginLogRespVO extends LoginLogBaseVO { @ApiModelProperty(value = "日志编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java index d29a96ce39..33b3670392 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -13,7 +13,7 @@ import java.util.Map; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysOperateLogBaseVO { +public class OperateLogBaseVO { @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") @NotEmpty(message = "链路追踪编号不能为空") @@ -31,7 +31,7 @@ public class SysOperateLogBaseVO { @NotEmpty(message = "操作名") private String name; - @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") + @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 OperateLogTypeEnum 枚举类") @NotNull(message = "操作分类不能为空") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java index 71959d8838..7f38cfc797 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import java.util.Date; * 操作日志 Excel 导出响应 VO */ @Data -public class SysOperateLogExcelVO { +public class OperateLogExcelVO { @ExcelProperty("日志编号") private Long id; @@ -24,7 +24,7 @@ public class SysOperateLogExcelVO { private String name; @ExcelProperty(value = "操作类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.OPERATE_TYPE) + @DictFormat(DictTypeConstants.OPERATE_TYPE) private String type; @ExcelProperty("操作人") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java index 2c500e12b1..90adb822e5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("操作日志分页列表 Request VO") +@ApiModel("管理后台 - 操作日志分页列表 Request VO") @Data -public class SysOperateLogExportReqVO { +public class OperateLogExportReqVO { @ApiModelProperty(value = "操作模块", example = "订单", notes = "模拟匹配") private String module; @@ -19,7 +19,7 @@ public class SysOperateLogExportReqVO { @ApiModelProperty(value = "用户昵称", example = "芋道", notes = "模拟匹配") private String userNickname; - @ApiModelProperty(value = "操作分类", example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") + @ApiModelProperty(value = "操作分类", example = "1", notes = "参见 OperateLogTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "操作状态", example = "true") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java index 2a0378a59e..0741abd881 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -10,9 +10,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("操作日志分页列表 Request VO") +@ApiModel("管理后台 - 操作日志分页列表 Request VO") @Data -public class SysOperateLogPageReqVO extends PageParam { +public class OperateLogPageReqVO extends PageParam { @ApiModelProperty(value = "操作模块", example = "订单", notes = "模拟匹配") private String module; @@ -20,7 +20,7 @@ public class SysOperateLogPageReqVO extends PageParam { @ApiModelProperty(value = "用户昵称", example = "芋道", notes = "模拟匹配") private String userNickname; - @ApiModelProperty(value = "操作分类", example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") + @ApiModelProperty(value = "操作分类", example = "1", notes = "参见 OperateLogTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "操作状态", example = "true") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java index 1ac82a91ef..445b400603 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/logger/vo/operatelog/SysOperateLogRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog; +package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("操作日志 Response VO") +@ApiModel("管理后台 - 操作日志 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysOperateLogRespVO extends SysOperateLogBaseVO { +public class OperateLogRespVO extends OperateLogBaseVO { @ApiModelProperty(value = "日志编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/SysNoticeController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/SysNoticeController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java index 5ab1944ab5..d14cfb7333 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/SysNoticeController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice; +package cn.iocoder.yudao.module.system.controller.admin.notice; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.notice.SysNoticeConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.notice.SysNoticeService; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; +import cn.iocoder.yudao.module.system.service.notice.NoticeService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -20,19 +20,19 @@ import javax.validation.Valid; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "通知公告") +@Api(tags = "管理后台 - 通知公告") @RestController @RequestMapping("/system/notice") @Validated -public class SysNoticeController { +public class NoticeController { @Resource - private SysNoticeService noticeService; + private NoticeService noticeService; @PostMapping("/create") @ApiOperation("创建通知公告") @PreAuthorize("@ss.hasPermission('system:notice:create')") - public CommonResult createNotice(@Valid @RequestBody SysNoticeCreateReqVO reqVO) { + public CommonResult createNotice(@Valid @RequestBody NoticeCreateReqVO reqVO) { Long noticeId = noticeService.createNotice(reqVO); return success(noticeId); } @@ -40,7 +40,7 @@ public class SysNoticeController { @PutMapping("/update") @ApiOperation("修改通知公告") @PreAuthorize("@ss.hasPermission('system:notice:update')") - public CommonResult updateNotice(@Valid @RequestBody SysNoticeUpdateReqVO reqVO) { + public CommonResult updateNotice(@Valid @RequestBody NoticeUpdateReqVO reqVO) { noticeService.updateNotice(reqVO); return success(true); } @@ -57,16 +57,16 @@ public class SysNoticeController { @GetMapping("/page") @ApiOperation("获取通知公告列表") @PreAuthorize("@ss.hasPermission('system:notice:query')") - public CommonResult> pageNotices(@Validated SysNoticePageReqVO reqVO) { - return success(SysNoticeConvert.INSTANCE.convertPage(noticeService.pageNotices(reqVO))); + public CommonResult> pageNotices(@Validated NoticePageReqVO reqVO) { + return success(NoticeConvert.INSTANCE.convertPage(noticeService.pageNotices(reqVO))); } @GetMapping("/get") @ApiOperation("获得通知公告") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:notice:query')") - public CommonResult getNotice(@RequestParam("id") Long id) { - return success(SysNoticeConvert.INSTANCE.convert(noticeService.getNotice(id))); + public CommonResult getNotice(@RequestParam("id") Long id) { + return success(NoticeConvert.INSTANCE.convert(noticeService.getNotice(id))); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java index 9bd228ed58..a8ecb7758b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo; +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysNoticeBaseVO { +public class NoticeBaseVO { @ApiModelProperty(value = "公告标题", required = true, example = "小博主") @NotBlank(message = "公告标题不能为空") @@ -26,7 +26,7 @@ public class SysNoticeBaseVO { @ApiModelProperty(value = "公告内容", required = true, example = "半生编码") private String content; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java new file mode 100644 index 0000000000..49e671ce14 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@ApiModel("管理后台 - 通知公告创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class NoticeCreateReqVO extends NoticeBaseVO { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticePageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticePageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java index b347ab9362..ba1287c47d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticePageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo; +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -6,15 +6,15 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; -@ApiModel("通知公告分页 Request VO") +@ApiModel("管理后台 - 通知公告分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysNoticePageReqVO extends PageParam { +public class NoticePageReqVO extends PageParam { @ApiModelProperty(value = "通知公告名称", example = "芋道", notes = "模糊匹配") private String title; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java index 8145e85b26..1f18df030e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo; +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import java.util.Date; -@ApiModel("通知公告信息 Response VO") +@ApiModel("管理后台 - 通知公告信息 Response VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysNoticeRespVO extends SysNoticeBaseVO { +public class NoticeRespVO extends NoticeBaseVO { @ApiModelProperty(value = "通知公告序号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java index 2c02d5aaef..30f4a3720b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/vo/SysNoticeUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo; +package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("岗位公告更新 Request VO") +@ApiModel("管理后台 - 岗位公告更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysNoticeUpdateReqVO extends SysNoticeBaseVO { +public class NoticeUpdateReqVO extends NoticeBaseVO { @ApiModelProperty(value = "岗位公告编号", required = true, example = "1024") @NotNull(message = "岗位公告编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.http similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.http index c073f7bdc6..a90d8b8ab3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.http @@ -1,3 +1,4 @@ ### 请求 /menu/list 接口 => 成功 GET {{baseUrl}}/system/menu/list Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java index ddf388dd4b..8678da529c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysMenuController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.permission.SysMenuConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*; +import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.service.permission.MenuService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -20,19 +20,19 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "菜单") +@Api(tags = "管理后台 - 菜单") @RestController @RequestMapping("/system/menu") @Validated -public class SysMenuController { +public class MenuController { @Resource - private SysMenuService menuService; + private MenuService menuService; @PostMapping("/create") @ApiOperation("创建菜单") @PreAuthorize("@ss.hasPermission('system:menu:create')") - public CommonResult createMenu(@Valid @RequestBody SysMenuCreateReqVO reqVO) { + public CommonResult createMenu(@Valid @RequestBody MenuCreateReqVO reqVO) { Long menuId = menuService.createMenu(reqVO); return success(menuId); } @@ -40,7 +40,7 @@ public class SysMenuController { @PutMapping("/update") @ApiOperation("修改菜单") @PreAuthorize("@ss.hasPermission('system:menu:update')") - public CommonResult updateMenu(@Valid @RequestBody SysMenuUpdateReqVO reqVO) { + public CommonResult updateMenu(@Valid @RequestBody MenuUpdateReqVO reqVO) { menuService.updateMenu(reqVO); return success(true); } @@ -57,30 +57,30 @@ public class SysMenuController { @GetMapping("/list") @ApiOperation("获取菜单列表") @PreAuthorize("@ss.hasPermission('system:menu:query')") - public CommonResult> getMenus(SysMenuListReqVO reqVO) { - List list = menuService.getMenus(reqVO); - list.sort(Comparator.comparing(SysMenuDO::getSort)); - return success(SysMenuConvert.INSTANCE.convertList(list)); + public CommonResult> getMenus(MenuListReqVO reqVO) { + List list = menuService.getMenus(reqVO); + list.sort(Comparator.comparing(MenuDO::getSort)); + return success(MenuConvert.INSTANCE.convertList(list)); } @GetMapping("/list-all-simple") @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,主要用于前端的下拉选项") - public CommonResult> getSimpleMenus() { + public CommonResult> getSimpleMenus() { // 获得菜单列表,只要开启状态的 - SysMenuListReqVO reqVO = new SysMenuListReqVO(); + MenuListReqVO reqVO = new MenuListReqVO(); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - List list = menuService.getMenus(reqVO); + List list = menuService.getMenus(reqVO); // 排序后,返回个诶前端 - list.sort(Comparator.comparing(SysMenuDO::getSort)); - return success(SysMenuConvert.INSTANCE.convertList02(list)); + list.sort(Comparator.comparing(MenuDO::getSort)); + return success(MenuConvert.INSTANCE.convertList02(list)); } @GetMapping("/get") @ApiOperation("获取菜单信息") @PreAuthorize("@ss.hasPermission('system:menu:query')") - public CommonResult getMenu(Long id) { - SysMenuDO menu = menuService.getMenu(id); - return success(SysMenuConvert.INSTANCE.convert(menu)); + public CommonResult getMenu(Long id) { + MenuDO menu = menuService.getMenu(id); + return success(MenuConvert.INSTANCE.convert(menu)); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysPermissionController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysPermissionController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java index cbd1197aeb..de26fbf086 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysPermissionController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission.SysPermissionAssignRoleDataScopeReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission.SysPermissionAssignRoleMenuReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission.SysPermissionAssignUserRoleReqVO; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -12,6 +12,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.validation.Valid; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -21,13 +22,15 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; * * @author 芋道源码 */ -@Api(tags = "权限") +@Api(tags = "管理后台 - 权限") @RestController @RequestMapping("/system/permission") -public class SysPermissionController { +public class PermissionController { @Resource - private SysPermissionService permissionService; + private PermissionService permissionService; + + // TODO @芋艿:处理下全新啊标识 @ApiOperation("获得角色拥有的菜单编号") @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class) @@ -40,7 +43,7 @@ public class SysPermissionController { @PostMapping("/assign-role-menu") @ApiOperation("赋予角色菜单") // @RequiresPermissions("system:permission:assign-role-resource") - public CommonResult assignRoleMenu(@Validated @RequestBody SysPermissionAssignRoleMenuReqVO reqVO) { + public CommonResult assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) { permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds()); return success(true); } @@ -48,8 +51,7 @@ public class SysPermissionController { @PostMapping("/assign-role-data-scope") @ApiOperation("赋予角色数据权限") // @RequiresPermissions("system:permission:assign-role-data-scope") - public CommonResult assignRoleDataScope( - @Validated @RequestBody SysPermissionAssignRoleDataScopeReqVO reqVO) { + public CommonResult assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) { permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds()); return success(true); } @@ -65,7 +67,7 @@ public class SysPermissionController { @ApiOperation("赋予用户角色") @PostMapping("/assign-user-role") // @RequiresPermissions("system:permission:assign-user-role") - public CommonResult assignUserRole(@Validated @RequestBody SysPermissionAssignUserRoleReqVO reqVO) { + public CommonResult assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) { permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds()); return success(true); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http index 4e150ac303..c28725d860 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.http @@ -2,6 +2,7 @@ POST {{baseUrl}}/system/role/create Authorization: Bearer {{token}} Content-Type: application/json +tenant-id: {{adminTenentId}} { "name": "测试角色", @@ -13,7 +14,7 @@ Content-Type: application/json POST {{baseUrl}}/system/role/update Authorization: Bearer {{token}} Content-Type: application/json - +tenant-id: {{adminTenentId}} { "id": 100, @@ -25,6 +26,7 @@ Content-Type: application/json POST {{baseUrl}}/system/role/delete Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} roleId=14 @@ -32,10 +34,12 @@ roleId=14 GET {{baseUrl}}/system/role/get?id=100 Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} ### /role/page 成功 GET {{baseUrl}}/system/role/page?pageNo=1&pageSize=10 Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} ### diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java similarity index 67% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java index 15d7fa3f83..b200aba866 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/SysRoleController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.permission.SysRoleConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; +import cn.iocoder.yudao.module.system.convert.permission.RoleConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.service.permission.RoleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -27,26 +27,26 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "角色") +@Api(tags = "管理后台 - 角色") @RestController @RequestMapping("/system/role") @Validated -public class SysRoleController { +public class RoleController { @Resource - private SysRoleService roleService; + private RoleService roleService; @PostMapping("/create") @ApiOperation("创建角色") @PreAuthorize("@ss.hasPermission('system:role:create')") - public CommonResult createRole(@Valid @RequestBody SysRoleCreateReqVO reqVO) { + public CommonResult createRole(@Valid @RequestBody RoleCreateReqVO reqVO) { return success(roleService.createRole(reqVO)); } @PutMapping("/update") @ApiOperation("修改角色") @PreAuthorize("@ss.hasPermission('system:role:update')") - public CommonResult updateRole(@Valid @RequestBody SysRoleUpdateReqVO reqVO) { + public CommonResult updateRole(@Valid @RequestBody RoleUpdateReqVO reqVO) { roleService.updateRole(reqVO); return success(true); } @@ -54,7 +54,7 @@ public class SysRoleController { @PutMapping("/update-status") @ApiOperation("修改角色状态") @PreAuthorize("@ss.hasPermission('system:role:update')") - public CommonResult updateRoleStatus(@Valid @RequestBody SysRoleUpdateStatusReqVO reqVO) { + public CommonResult updateRoleStatus(@Valid @RequestBody RoleUpdateStatusReqVO reqVO) { roleService.updateRoleStatus(reqVO.getId(), reqVO.getStatus()); return success(true); } @@ -71,36 +71,36 @@ public class SysRoleController { @GetMapping("/get") @ApiOperation("获得角色信息") @PreAuthorize("@ss.hasPermission('system:role:query')") - public CommonResult getRole(@RequestParam("id") Long id) { - SysRoleDO role = roleService.getRole(id); - return success(SysRoleConvert.INSTANCE.convert(role)); + public CommonResult getRole(@RequestParam("id") Long id) { + RoleDO role = roleService.getRole(id); + return success(RoleConvert.INSTANCE.convert(role)); } @GetMapping("/page") @ApiOperation("获得角色分页") @PreAuthorize("@ss.hasPermission('system:role:query')") - public CommonResult> getRolePage(SysRolePageReqVO reqVO) { + public CommonResult> getRolePage(RolePageReqVO reqVO) { return success(roleService.getRolePage(reqVO)); } @GetMapping("/list-all-simple") @ApiOperation(value = "获取角色精简信息列表", notes = "只包含被开启的角色,主要用于前端的下拉选项") - public CommonResult> getSimpleRoles() { + public CommonResult> getSimpleRoles() { // 获得角色列表,只要开启状态的 - List list = roleService.getRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); + List list = roleService.getRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); // 排序后,返回个诶前端 - list.sort(Comparator.comparing(SysRoleDO::getSort)); - return success(SysRoleConvert.INSTANCE.convertList02(list)); + list.sort(Comparator.comparing(RoleDO::getSort)); + return success(RoleConvert.INSTANCE.convertList02(list)); } @GetMapping("/export") @OperateLog(type = EXPORT) @PreAuthorize("@ss.hasPermission('system:role:export')") - public void export(HttpServletResponse response, @Validated SysRoleExportReqVO reqVO) throws IOException { - List list = roleService.getRoleList(reqVO); - List data = SysRoleConvert.INSTANCE.convertList03(list); + public void export(HttpServletResponse response, @Validated RoleExportReqVO reqVO) throws IOException { + List list = roleService.getRoleList(reqVO); + List data = RoleConvert.INSTANCE.convertList03(list); // 输出 - ExcelUtils.write(response, "角色数据.xls", "角色列表", SysRoleExcelVO.class, data); + ExcelUtils.write(response, "角色数据.xls", "角色列表", RoleExcelVO.class, data); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java index 66b62d03b9..bbed03caa6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysMenuBaseVO { +public class MenuBaseVO { @ApiModelProperty(value = "菜单名称", required = true, example = "芋道") @NotBlank(message = "菜单名称不能为空") @@ -23,7 +23,7 @@ public class SysMenuBaseVO { @Size(max = 100) private String permission; - @ApiModelProperty(value = "类型", required = true, example = "1", notes = "参见 SysMenuTypeEnum 枚举类") + @ApiModelProperty(value = "类型", required = true, example = "1", notes = "参见 MenuTypeEnum 枚举类") @NotNull(message = "菜单类型不能为空") private Integer type; @@ -46,7 +46,7 @@ public class SysMenuBaseVO { @Size(max = 200, message = "组件路径不能超过255个字符") private String component; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 CommonStatusEnum 枚举") @NotNull(message = "状态不能为空") private Integer status; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java new file mode 100644 index 0000000000..a793997ff0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; + +import io.swagger.annotations.ApiModel; +import lombok.*; + +@ApiModel("管理后台 - 菜单创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MenuCreateReqVO extends MenuBaseVO { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuListReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuListReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java index 5600a132c8..2600fb92b9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuListReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel("菜单列表 Request VO") +@ApiModel("管理后台 - 菜单列表 Request VO") @Data -public class SysMenuListReqVO { +public class MenuListReqVO { @ApiModelProperty(value = "菜单名称", example = "芋道", notes = "模糊匹配") private String name; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java index 6175a8ca3a..34d70f4f53 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,17 +9,17 @@ import lombok.NoArgsConstructor; import java.util.Date; -@ApiModel("菜单信息 Response VO") +@ApiModel("管理后台 - 菜单信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysMenuRespVO extends SysMenuBaseVO { +public class MenuRespVO extends MenuBaseVO { @ApiModelProperty(value = "菜单编号", required = true, example = "1024") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java index 689d705d49..9274185186 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("菜单精简信息 Response VO") +@ApiModel("管理后台 - 菜单精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class SysMenuSimpleRespVO { +public class MenuSimpleRespVO { @ApiModelProperty(value = "菜单编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java similarity index 66% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java index 736d580733..7a17843631 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/menu/SysMenuUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,10 +6,10 @@ import lombok.*; import javax.validation.constraints.NotNull; -@ApiModel("菜单更新 Request VO") +@ApiModel("管理后台 - 菜单更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysMenuUpdateReqVO extends SysMenuBaseVO { +public class MenuUpdateReqVO extends MenuBaseVO { @ApiModelProperty(value = "菜单编号", required = true, example = "1024") @NotNull(message = "菜单编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleDataScopeReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleDataScopeReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java index 8050e81436..6adb8c8548 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleDataScopeReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,15 +8,15 @@ import javax.validation.constraints.NotNull; import java.util.Collections; import java.util.Set; -@ApiModel("赋予角色数据权限 Request VO") +@ApiModel("管理后台 - 赋予角色数据权限 Request VO") @Data -public class SysPermissionAssignRoleDataScopeReqVO { +public class PermissionAssignRoleDataScopeReqVO { @ApiModelProperty(value = "角色编号", required = true, example = "1") @NotNull(message = "角色编号不能为空") private Long roleId; - @ApiModelProperty(value = "数据范围", required = true, example = "1", notes = "参见 SysDataScopeEnum 枚举类") + @ApiModelProperty(value = "数据范围", required = true, example = "1", notes = "参见 DataScopeEnum 枚举类") @NotNull(message = "数据范围不能为空") // TODO 这里要多一个枚举校验 private Integer dataScope; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleMenuReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleMenuReqVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleMenuReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleMenuReqVO.java index 47ffae9288..3fc4dcb2c0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleMenuReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleMenuReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,9 +8,9 @@ import javax.validation.constraints.NotNull; import java.util.Collections; import java.util.Set; -@ApiModel("赋予角色菜单 Request VO") +@ApiModel("管理后台 - 赋予角色菜单 Request VO") @Data -public class SysPermissionAssignRoleMenuReqVO { +public class PermissionAssignRoleMenuReqVO { @ApiModelProperty(value = "角色编号", required = true, example = "1") @NotNull(message = "角色编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignUserRoleReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignUserRoleReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java index 1a3e034154..75671bcd2c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/permission/SysPermissionAssignUserRoleReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignUserRoleReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.permission; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,9 +8,9 @@ import javax.validation.constraints.NotNull; import java.util.Collections; import java.util.Set; -@ApiModel("赋予用户角色 Request VO") +@ApiModel("管理后台 - 赋予用户角色 Request VO") @Data -public class SysPermissionAssignUserRoleReqVO { +public class PermissionAssignUserRoleReqVO { @ApiModelProperty(value = "角色编号", required = true, example = "1") @NotNull(message = "角色编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java index a07e20c4a6..66b4d2053f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysRoleBaseVO { +public class RoleBaseVO { @ApiModelProperty(value = "角色名称", required = true, example = "管理员") @NotBlank(message = "角色名称不能为空") @@ -28,7 +28,7 @@ public class SysRoleBaseVO { @NotNull(message = "显示顺序不能为空") private Integer sort; - @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "见 SysRoleTypeEnum 枚举") + @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "见 RoleTypeEnum 枚举") private Integer type; @ApiModelProperty(value = "备注", example = "我是一个角色") diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java new file mode 100644 index 0000000000..785f658158 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@ApiModel("管理后台 - 角色创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class RoleCreateReqVO extends RoleBaseVO { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java index c8c130537e..d22cf9bf24 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import lombok.Data; * 角色 Excel 导出响应 VO */ @Data -public class SysRoleExcelVO { +public class RoleExcelVO { @ExcelProperty("角色序号") private Long id; @@ -28,7 +28,7 @@ public class SysRoleExcelVO { private Integer dataScope; @ExcelProperty(value = "角色状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private String status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java index 656f136d04..02e47ac6f5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("角色分页 Request VO") +@ApiModel("管理后台 - 角色分页 Request VO") @Data -public class SysRoleExportReqVO { +public class RoleExportReqVO { @ApiModelProperty(value = "角色名称", example = "芋道", notes = "模糊匹配") private String name; @@ -19,7 +19,7 @@ public class SysRoleExportReqVO { @ApiModelProperty(value = "角色标识", example = "yudao", notes = "模糊匹配") private String code; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "开始时间", example = "2020-10-24") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRolePageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRolePageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java index 6983176fad..2f4cc18586 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRolePageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RolePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -11,10 +11,10 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("角色分页 Request VO") +@ApiModel("管理后台 - 角色分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysRolePageReqVO extends PageParam { +public class RolePageReqVO extends PageParam { @ApiModelProperty(value = "角色名称", example = "芋道", notes = "模糊匹配") private String name; @@ -22,7 +22,7 @@ public class SysRolePageReqVO extends PageParam { @ApiModelProperty(value = "角色标识", example = "yudao", notes = "模糊匹配") private String code; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "开始时间", example = "2020-10-24") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java index f3a565d716..31acbedcdc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,12 +10,12 @@ import lombok.NoArgsConstructor; import java.util.Date; import java.util.Set; -@ApiModel("角色信息 Response VO") +@ApiModel("管理后台 - 角色信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysRoleRespVO extends SysRoleBaseVO { +public class RoleRespVO extends RoleBaseVO { @ApiModelProperty(value = "角色编号", required = true, example = "1") private Long id; @@ -26,10 +26,10 @@ public class SysRoleRespVO extends SysRoleBaseVO { @ApiModelProperty(value = "数据范围(指定部门数组)", example = "1") private Set dataScopeDeptIds; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; - @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "参见 SysRoleTypeEnum 枚举类") + @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "参见 RoleTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java index c1b973ff79..c0a4c30838 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel("角色精简信息 Response VO") +@ApiModel("管理后台 - 角色精简信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor -public class SysRoleSimpleRespVO { +public class RoleSimpleRespVO { @ApiModelProperty(value = "角色编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java index dcf994f8d2..362cbb2904 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("角色更新 Request VO") +@ApiModel("管理后台 - 角色更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysRoleUpdateReqVO extends SysRoleBaseVO { +public class RoleUpdateReqVO extends RoleBaseVO { @ApiModelProperty(value = "角色编号", required = true, example = "1024") @NotNull(message = "角色编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateStatusReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java similarity index 59% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateStatusReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java index 1741881dd1..708586b823 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/permission/vo/role/SysRoleUpdateStatusReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role; +package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,17 +6,17 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("角色更新状态 Request VO") +@ApiModel("管理后台 - 角色更新状态 Request VO") @Data -public class SysRoleUpdateStatusReqVO { +public class RoleUpdateStatusReqVO { @ApiModelProperty(value = "角色编号", required = true, example = "1024") @NotNull(message = "角色编号不能为空") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 CommonStatusEnum 枚举") @NotNull(message = "状态不能为空") -// @InEnum(value = SysCommonStatusEnum.class, message = "修改状态必须是 {value}") +// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SmsCallbackController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SmsCallbackController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java index 322b99d00f..00f17d9dd1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SmsCallbackController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms; +package cn.iocoder.yudao.module.system.controller.admin.sms; import cn.hutool.core.util.URLUtil; import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; @@ -19,21 +19,21 @@ import javax.servlet.http.HttpServletRequest; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "短信回调") +@Api(tags = "管理后台 - 短信回调") @RestController @RequestMapping("/system/sms/callback") public class SmsCallbackController { @Resource - private SysSmsCoreService smsCoreService; + private SmsSendService smsSendService; @PostMapping("/sms/yunpian") @ApiOperation(value = "云片短信的回调", notes = "参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档") - @ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = Long.class) + @ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = String.class) @OperateLog(enable = false) public String receiveYunpianSmsStatus(@RequestParam("sms_status") String smsStatus) throws Throwable { String text = URLUtil.decode(smsStatus); // decode 解码参数,因为它被 encode - smsCoreService.receiveSmsStatus(SmsChannelEnum.YUN_PIAN.getCode(), text); + smsSendService.receiveSmsStatus(SmsChannelEnum.YUN_PIAN.getCode(), text); return "SUCCESS"; // 约定返回 SUCCESS 为成功 } @@ -42,7 +42,7 @@ public class SmsCallbackController { @OperateLog(enable = false) public CommonResult receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable { String text = ServletUtil.getBody(request); - smsCoreService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text); + smsSendService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text); return success(true); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsChannelController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsChannelController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java index 3fbb47e6ec..638140d210 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsChannelController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms; +package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.sms.SysSmsChannelConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsChannelService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.*; +import cn.iocoder.yudao.module.system.convert.sms.SmsChannelConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.module.system.service.sms.SmsChannelService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import io.swagger.annotations.Api; @@ -19,25 +19,25 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "短信渠道") +@Api(tags = "管理后台 - 短信渠道") @RestController @RequestMapping("system/sms-channel") -public class SysSmsChannelController { +public class SmsChannelController { @Resource - private SysSmsChannelService smsChannelService; + private SmsChannelService smsChannelService; @PostMapping("/create") @ApiOperation("创建短信渠道") @PreAuthorize("@ss.hasPermission('system:sms-channel:create')") - public CommonResult createSmsChannel(@Valid @RequestBody SysSmsChannelCreateReqVO createReqVO) { + public CommonResult createSmsChannel(@Valid @RequestBody SmsChannelCreateReqVO createReqVO) { return success(smsChannelService.createSmsChannel(createReqVO)); } @PutMapping("/update") @ApiOperation("更新短信渠道") @PreAuthorize("@ss.hasPermission('system:sms-channel:update')") - public CommonResult updateSmsChannel(@Valid @RequestBody SysSmsChannelUpdateReqVO updateReqVO) { + public CommonResult updateSmsChannel(@Valid @RequestBody SmsChannelUpdateReqVO updateReqVO) { smsChannelService.updateSmsChannel(updateReqVO); return success(true); } @@ -55,26 +55,26 @@ public class SysSmsChannelController { @ApiOperation("获得短信渠道") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:sms-channel:query')") - public CommonResult getSmsChannel(@RequestParam("id") Long id) { - SysSmsChannelDO smsChannel = smsChannelService.getSmsChannel(id); - return success(SysSmsChannelConvert.INSTANCE.convert(smsChannel)); + public CommonResult getSmsChannel(@RequestParam("id") Long id) { + SmsChannelDO smsChannel = smsChannelService.getSmsChannel(id); + return success(SmsChannelConvert.INSTANCE.convert(smsChannel)); } @GetMapping("/page") @ApiOperation("获得短信渠道分页") @PreAuthorize("@ss.hasPermission('system:sms-channel:query')") - public CommonResult> getSmsChannelPage(@Valid SysSmsChannelPageReqVO pageVO) { - PageResult pageResult = smsChannelService.getSmsChannelPage(pageVO); - return success(SysSmsChannelConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getSmsChannelPage(@Valid SmsChannelPageReqVO pageVO) { + PageResult pageResult = smsChannelService.getSmsChannelPage(pageVO); + return success(SmsChannelConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/list-all-simple") @ApiOperation(value = "获得短信渠道精简列表", notes = "包含被禁用的短信渠道") - public CommonResult> getSimpleSmsChannels() { - List list = smsChannelService.getSmsChannelList(); + public CommonResult> getSimpleSmsChannels() { + List list = smsChannelService.getSmsChannelList(); // 排序后,返回给前端 - list.sort(Comparator.comparing(SysSmsChannelDO::getId)); - return success(SysSmsChannelConvert.INSTANCE.convertList03(list)); + list.sort(Comparator.comparing(SmsChannelDO::getId)); + return success(SmsChannelConvert.INSTANCE.convertList03(list)); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsLogController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsLogController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java index aa1eec9b2a..5fbf10e741 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsLogController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms; +package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogRespVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.sms.SysSmsLogConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsLogService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO; +import cn.iocoder.yudao.module.system.convert.sms.SmsLogConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.module.system.service.sms.SmsLogService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -28,33 +28,33 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "短信日志") +@Api(tags = "管理后台 - 短信日志") @RestController @RequestMapping("/system/sms-log") @Validated -public class SysSmsLogController { +public class SmsLogController { @Resource - private SysSmsLogService smsLogService; + private SmsLogService smsLogService; @GetMapping("/page") @ApiOperation("获得短信日志分页") @PreAuthorize("@ss.hasPermission('system:sms-log:query')") - public CommonResult> getSmsLogPage(@Valid SysSmsLogPageReqVO pageVO) { - PageResult pageResult = smsLogService.getSmsLogPage(pageVO); - return success(SysSmsLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getSmsLogPage(@Valid SmsLogPageReqVO pageVO) { + PageResult pageResult = smsLogService.getSmsLogPage(pageVO); + return success(SmsLogConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出短信日志 Excel") @PreAuthorize("@ss.hasPermission('system:sms-log:export')") @OperateLog(type = EXPORT) - public void exportSmsLogExcel(@Valid SysSmsLogExportReqVO exportReqVO, + public void exportSmsLogExcel(@Valid SmsLogExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = smsLogService.getSmsLogList(exportReqVO); + List list = smsLogService.getSmsLogList(exportReqVO); // 导出 Excel - List datas = SysSmsLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "短信日志.xls", "数据", SysSmsLogExcelVO.class, datas); + List datas = SmsLogConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "短信日志.xls", "数据", SmsLogExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http index d5441d057c..3bf59d965f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.http @@ -1,7 +1,8 @@ -### 请求 /menu/list 接口 => 成功 +### 请求 /system/sms-template/send-sms 接口 => 成功 POST {{baseUrl}}/system/sms-template/send-sms Authorization: Bearer {{token}} Content-Type: application/json +tenant-id: {{adminTenentId}} { "code": "test_01", diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java index 5b9d8bc6e1..3eef58652f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/SysSmsTemplateController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms; +package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.sms.SysSmsTemplateConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsTemplateService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.*; +import cn.iocoder.yudao.module.system.convert.sms.SmsTemplateConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -24,27 +24,27 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "短信模板") +@Api(tags = "管理后台 - 短信模板") @RestController @RequestMapping("/system/sms-template") -public class SysSmsTemplateController { +public class SmsTemplateController { @Resource - private SysSmsTemplateService smsTemplateService; + private SmsTemplateService smsTemplateService; @Resource - private SysSmsCoreService smsCoreService; + private SmsSendService smsSendService; @PostMapping("/create") @ApiOperation("创建短信模板") @PreAuthorize("@ss.hasPermission('system:sms-template:create')") - public CommonResult createSmsTemplate(@Valid @RequestBody SysSmsTemplateCreateReqVO createReqVO) { + public CommonResult createSmsTemplate(@Valid @RequestBody SmsTemplateCreateReqVO createReqVO) { return success(smsTemplateService.createSmsTemplate(createReqVO)); } @PutMapping("/update") @ApiOperation("更新短信模板") @PreAuthorize("@ss.hasPermission('system:sms-template:update')") - public CommonResult updateSmsTemplate(@Valid @RequestBody SysSmsTemplateUpdateReqVO updateReqVO) { + public CommonResult updateSmsTemplate(@Valid @RequestBody SmsTemplateUpdateReqVO updateReqVO) { smsTemplateService.updateSmsTemplate(updateReqVO); return success(true); } @@ -62,36 +62,36 @@ public class SysSmsTemplateController { @ApiOperation("获得短信模板") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:sms-template:query')") - public CommonResult getSmsTemplate(@RequestParam("id") Long id) { - SysSmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id); - return success(SysSmsTemplateConvert.INSTANCE.convert(smsTemplate)); + public CommonResult getSmsTemplate(@RequestParam("id") Long id) { + SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id); + return success(SmsTemplateConvert.INSTANCE.convert(smsTemplate)); } @GetMapping("/page") @ApiOperation("获得短信模板分页") @PreAuthorize("@ss.hasPermission('system:sms-template:query')") - public CommonResult> getSmsTemplatePage(@Valid SysSmsTemplatePageReqVO pageVO) { - PageResult pageResult = smsTemplateService.getSmsTemplatePage(pageVO); - return success(SysSmsTemplateConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getSmsTemplatePage(@Valid SmsTemplatePageReqVO pageVO) { + PageResult pageResult = smsTemplateService.getSmsTemplatePage(pageVO); + return success(SmsTemplateConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出短信模板 Excel") @PreAuthorize("@ss.hasPermission('system:sms-template:export')") @OperateLog(type = EXPORT) - public void exportSmsTemplateExcel(@Valid SysSmsTemplateExportReqVO exportReqVO, + public void exportSmsTemplateExcel(@Valid SmsTemplateExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = smsTemplateService.getSmsTemplateList(exportReqVO); + List list = smsTemplateService.getSmsTemplateList(exportReqVO); // 导出 Excel - List datas = SysSmsTemplateConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "短信模板.xls", "数据", SysSmsTemplateExcelVO.class, datas); + List datas = SmsTemplateConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "短信模板.xls", "数据", SmsTemplateExcelVO.class, datas); } @PostMapping("/send-sms") @ApiOperation("发送短信") @PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')") - public CommonResult sendSms(@Valid @RequestBody SysSmsTemplateSendReqVO sendReqVO) { - return success(smsCoreService.sendSingleSms(sendReqVO.getMobile(), null, null, + public CommonResult sendSms(@Valid @RequestBody SmsTemplateSendReqVO sendReqVO) { + return success(smsSendService.sendSingleSmsToAdmin(sendReqVO.getMobile(), null, sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java index fd475bdcf9..ab5595fc0a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysSmsChannelBaseVO { +public class SmsChannelBaseVO { @ApiModelProperty(value = "短信签名", required = true, example = "芋道源码") @NotNull(message = "短信签名不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelCreateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java index e9466a7b6b..edc162f474 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelCreateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("短信渠道创建 Request VO") +@ApiModel("管理后台 - 短信渠道创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsChannelCreateReqVO extends SysSmsChannelBaseVO { +public class SmsChannelCreateReqVO extends SmsChannelBaseVO { @ApiModelProperty(value = "渠道编码", required = true, example = "YUN_PIAN", notes = "参见 SmsChannelEnum 枚举类") @NotNull(message = "渠道编码不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java index e30bc3d48a..306c7d06f4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("短信渠道分页 Request VO") +@ApiModel("管理后台 - 短信渠道分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsChannelPageReqVO extends PageParam { +public class SmsChannelPageReqVO extends PageParam { @ApiModelProperty(value = "任务状态", example = "1") private Integer status; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java index 8e7d111a3d..b39e35edfd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("短信渠道 Response VO") +@ApiModel("管理后台 - 短信渠道 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsChannelRespVO extends SysSmsChannelBaseVO { +public class SmsChannelRespVO extends SmsChannelBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java index 451a943eba..22b5bc1d48 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,9 +6,9 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("短信渠道精简 Response VO") +@ApiModel("管理后台 - 短信渠道精简 Response VO") @Data -public class SysSmsChannelSimpleRespVO { +public class SmsChannelSimpleRespVO { @ApiModelProperty(value = "编号", required = true, example = "1024") @NotNull(message = "编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java index 816e5c2197..6833287459 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/channel/SysSmsChannelUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("短信渠道更新 Request VO") +@ApiModel("管理后台 - 短信渠道更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsChannelUpdateReqVO extends SysSmsChannelBaseVO { +public class SmsChannelUpdateReqVO extends SmsChannelBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1024") @NotNull(message = "编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java index 8376939805..f638f58fc2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -16,7 +16,7 @@ import java.util.Map; * @author 芋道源码 */ @Data -public class SysSmsLogExcelVO { +public class SmsLogExcelVO { @ExcelProperty("编号") private Long id; @@ -34,7 +34,7 @@ public class SysSmsLogExcelVO { private String templateCode; @ExcelProperty(value = "短信类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.SMS_TEMPLATE_TYPE) + @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) private Integer templateType; @ExcelProperty("短信内容") @@ -53,11 +53,11 @@ public class SysSmsLogExcelVO { private Long userId; @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.USER_TYPE) + @DictFormat(DictTypeConstants.USER_TYPE) private Integer userType; @ExcelProperty(value = "发送状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.SMS_SEND_STATUS) + @DictFormat(DictTypeConstants.SMS_SEND_STATUS) private Integer sendStatus; @ExcelProperty("发送时间") @@ -82,7 +82,7 @@ public class SysSmsLogExcelVO { private String apiSerialNo; @ExcelProperty(value = "接收状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.SMS_RECEIVE_STATUS) + @DictFormat(DictTypeConstants.SMS_RECEIVE_STATUS) private Integer receiveStatus; @ExcelProperty("接收时间") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java index 94be2d84e9..6754b43b2a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "短信日志 Excel 导出 Request VO", description = "参数和 SysSmsLogPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 短信日志 Excel 导出 Request VO", description = "参数和 SmsLogPageReqVO 是一致的") @Data -public class SysSmsLogExportReqVO { +public class SmsLogExportReqVO { @ApiModelProperty(value = "短信渠道编号", example = "10") private Long channelId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java index 1ea8a1fa75..767201f81c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("短信日志分页 Request VO") +@ApiModel("管理后台 - 短信日志分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsLogPageReqVO extends PageParam { +public class SmsLogPageReqVO extends PageParam { @ApiModelProperty(value = "短信渠道编号", example = "10") private Long channelId; @@ -27,7 +27,7 @@ public class SysSmsLogPageReqVO extends PageParam { @ApiModelProperty(value = "手机号", example = "15601691300") private String mobile; - @ApiModelProperty(value = "发送状态", example = "1", notes = "参见 SysSmsSendStatusEnum 枚举类") + @ApiModelProperty(value = "发送状态", example = "1", notes = "参见 SmsSendStatusEnum 枚举类") private Integer sendStatus; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @@ -38,7 +38,7 @@ public class SysSmsLogPageReqVO extends PageParam { @ApiModelProperty(value = "结束发送时间") private Date endSendTime; - @ApiModelProperty(value = "接收状态", example = "0", notes = "参见 SysSmsReceiveStatusEnum 枚举类") + @ApiModelProperty(value = "接收状态", example = "0", notes = "参见 SmsReceiveStatusEnum 枚举类") private Integer receiveStatus; @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java similarity index 95% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java index 10ff01a3d5..e179f4a5e6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/log/SysSmsLogRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,9 +7,9 @@ import lombok.Data; import java.util.Date; import java.util.Map; -@ApiModel("短信日志 Response VO") +@ApiModel("管理后台 - 短信日志 Response VO") @Data -public class SysSmsLogRespVO { +public class SmsLogRespVO { @ApiModelProperty(value = "编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java index cc587872e4..ca9220f8a0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,9 +10,9 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysSmsTemplateBaseVO { +public class SmsTemplateBaseVO { - @ApiModelProperty(value = "短信类型", required = true, example = "1", notes = "参见 SysSmsTemplateTypeEnum 枚举类") + @ApiModelProperty(value = "短信类型", required = true, example = "1", notes = "参见 SmsTemplateTypeEnum 枚举类") @NotNull(message = "短信类型不能为空") private Integer type; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java new file mode 100644 index 0000000000..ab8b89ebd9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@ApiModel("管理后台 - 短信模板创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SmsTemplateCreateReqVO extends SmsTemplateBaseVO { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java index a3215414c9..a640a93c1b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -14,17 +14,17 @@ import java.util.Date; * @author 芋道源码 */ @Data -public class SysSmsTemplateExcelVO { +public class SmsTemplateExcelVO { @ExcelProperty("编号") private Long id; @ExcelProperty(value = "短信签名", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.SMS_TEMPLATE_TYPE) + @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) private Integer type; @ExcelProperty(value = "开启状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; @ExcelProperty("模板编码") @@ -46,7 +46,7 @@ public class SysSmsTemplateExcelVO { private Long channelId; @ExcelProperty(value = "短信渠道编码", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.SMS_CHANNEL_CODE) + @DictFormat(DictTypeConstants.SMS_CHANNEL_CODE) private String channelCode; @ExcelProperty("创建时间") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java index 66efb4df65..e775e4c70a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "短信模板 Excel 导出 Request VO", description = "参数和 SysSmsTemplatePageReqVO 是一致的") +@ApiModel(value = "管理后台 - 短信模板 Excel 导出 Request VO", description = "参数和 SmsTemplatePageReqVO 是一致的") @Data -public class SysSmsTemplateExportReqVO { +public class SmsTemplateExportReqVO { @ApiModelProperty(value = "短信签名", example = "1") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java index fc8bd80b13..6932d2946b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplatePageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("短信模板分页 Request VO") +@ApiModel("管理后台 - 短信模板分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsTemplatePageReqVO extends PageParam { +public class SmsTemplatePageReqVO extends PageParam { @ApiModelProperty(value = "短信签名", example = "1") private Integer type; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java similarity index 79% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java index c26d3804d8..6633c383b3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,11 +9,11 @@ import lombok.ToString; import java.util.Date; import java.util.List; -@ApiModel("短信模板 Response VO") +@ApiModel("管理后台 - 短信模板 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsTemplateRespVO extends SysSmsTemplateBaseVO { +public class SmsTemplateRespVO extends SmsTemplateBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateSendReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateSendReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java index 34a773e036..956b4839eb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateSendReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,9 +7,9 @@ import lombok.Data; import javax.validation.constraints.NotNull; import java.util.Map; -@ApiModel("短信模板的发送 Request VO") +@ApiModel("管理后台 - 短信模板的发送 Request VO") @Data -public class SysSmsTemplateSendReqVO { +public class SmsTemplateSendReqVO { @ApiModelProperty(value = "手机号", required = true, example = "15601691300") @NotNull(message = "手机号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java index 223aa0caed..86bdbba9a3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/sms/vo/template/SysSmsTemplateUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template; +package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import javax.validation.constraints.NotNull; -@ApiModel("短信模板更新 Request VO") +@ApiModel("管理后台 - 短信模板更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsTemplateUpdateReqVO extends SysSmsTemplateBaseVO { +public class SmsTemplateUpdateReqVO extends SmsTemplateBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1024") @NotNull(message = "编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java index 54db21e9b3..1b7cee1d80 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant; +package cn.iocoder.yudao.module.system.controller.admin.tenant; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert; -import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.*; +import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.module.system.service.tenant.TenantService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -24,40 +24,40 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "租户") +@Api(tags = "管理后台 - 租户") @RestController @RequestMapping("/system/tenant") -public class SysTenantController { +public class TenantController { @Resource - private SysTenantService tenantService; + private TenantService tenantService; @GetMapping("/get-id-by-name") @ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号") - @ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class) + @ApiImplicitParam(name = "name", value = "租户名", required = true, example = "1024", dataTypeClass = Long.class) public CommonResult getTenantIdByName(@RequestParam("name") String name) { - SysTenantDO tenantDO = tenantService.getTenantByName(name); + TenantDO tenantDO = tenantService.getTenantByName(name); return success(tenantDO != null ? tenantDO.getId() : null); } @PostMapping("/create") @ApiOperation("创建租户") @PreAuthorize("@ss.hasPermission('system:tenant:create')") - public CommonResult createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) { + public CommonResult createTenant(@Valid @RequestBody TenantCreateReqVO createReqVO) { return success(tenantService.createTenant(createReqVO)); } @PutMapping("/update") @ApiOperation("更新租户") @PreAuthorize("@ss.hasPermission('system:tenant:update')") - public CommonResult updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) { + public CommonResult updateTenant(@Valid @RequestBody TenantUpdateReqVO updateReqVO) { tenantService.updateTenant(updateReqVO); return success(true); } @DeleteMapping("/delete") @ApiOperation("删除租户") - @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:tenant:delete')") public CommonResult deleteTenant(@RequestParam("id") Long id) { tenantService.deleteTenant(id); @@ -68,38 +68,38 @@ public class SysTenantController { @ApiOperation("获得租户") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:tenant:query')") - public CommonResult getTenant(@RequestParam("id") Long id) { - SysTenantDO tenant = tenantService.getTenant(id); - return success(SysTenantConvert.INSTANCE.convert(tenant)); + public CommonResult getTenant(@RequestParam("id") Long id) { + TenantDO tenant = tenantService.getTenant(id); + return success(TenantConvert.INSTANCE.convert(tenant)); } @GetMapping("/list") @ApiOperation("获得租户列表") @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) @PreAuthorize("@ss.hasPermission('system:tenant:query')") - public CommonResult> getTenantList(@RequestParam("ids") Collection ids) { - List list = tenantService.getTenantList(ids); - return success(SysTenantConvert.INSTANCE.convertList(list)); + public CommonResult> getTenantList(@RequestParam("ids") Collection ids) { + List list = tenantService.getTenantList(ids); + return success(TenantConvert.INSTANCE.convertList(list)); } @GetMapping("/page") @ApiOperation("获得租户分页") @PreAuthorize("@ss.hasPermission('system:tenant:query')") - public CommonResult> getTenantPage(@Valid SysTenantPageReqVO pageVO) { - PageResult pageResult = tenantService.getTenantPage(pageVO); - return success(SysTenantConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getTenantPage(@Valid TenantPageReqVO pageVO) { + PageResult pageResult = tenantService.getTenantPage(pageVO); + return success(TenantConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出租户 Excel") @PreAuthorize("@ss.hasPermission('system:tenant:export')") @OperateLog(type = EXPORT) - public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO, + public void exportTenantExcel(@Valid TenantExportReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = tenantService.getTenantList(exportReqVO); + List list = tenantService.getTenantList(exportReqVO); // 导出 Excel - List datas = SysTenantConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas); + List datas = TenantConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "租户.xls", "数据", TenantExcelVO.class, datas); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantBaseVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantBaseVO.java index 12511123fd..72ee63b9e2 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantBaseVO.java @@ -1,7 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; @@ -10,7 +9,7 @@ import javax.validation.constraints.*; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysTenantBaseVO { +public class TenantBaseVO { @ApiModelProperty(value = "租户名", required = true, example = "芋道") @NotNull(message = "租户名不能为空") diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantCreateReqVO.java new file mode 100755 index 0000000000..a7e75cb77f --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; + +import lombok.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 租户创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TenantCreateReqVO extends TenantBaseVO { + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExcelVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExcelVO.java index e98c8e66e2..9b317cb159 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExcelVO.java @@ -1,8 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import lombok.*; import java.util.*; -import io.swagger.annotations.*; import com.alibaba.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; @@ -15,7 +14,7 @@ import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; * @author 芋道源码 */ @Data -public class SysTenantExcelVO { +public class TenantExcelVO { @ExcelProperty("租户编号") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExportReqVO.java index e71e21db41..839239406b 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -9,9 +9,9 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 租户 Excel 导出 Request VO", description = "参数和 TenantPageReqVO 是一致的") @Data -public class SysTenantExportReqVO { +public class TenantExportReqVO { @ApiModelProperty(value = "租户名", example = "芋道") private String name; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantPageReqVO.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantPageReqVO.java index b2f5227a61..4a11a9cd62 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("租户分页 Request VO") +@ApiModel("管理后台 - 租户分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysTenantPageReqVO extends PageParam { +public class TenantPageReqVO extends PageParam { @ApiModelProperty(value = "租户名", example = "芋道") private String name; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantRespVO.java similarity index 67% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantRespVO.java index ab12ae53ce..5b6940a55b 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantRespVO.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import lombok.*; import java.util.*; import io.swagger.annotations.*; -@ApiModel("租户 Response VO") +@ApiModel("管理后台 - 租户 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysTenantRespVO extends SysTenantBaseVO { +public class TenantRespVO extends TenantBaseVO { @ApiModelProperty(value = "租户编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantUpdateReqVO.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantUpdateReqVO.java index 0ae05af383..0e10dabedc 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/TenantUpdateReqVO.java @@ -1,15 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo; +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo; import lombok.*; -import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("租户更新 Request VO") +@ApiModel("管理后台 - 租户更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysTenantUpdateReqVO extends SysTenantBaseVO { +public class TenantUpdateReqVO extends TenantBaseVO { @ApiModelProperty(value = "租户编号", required = true, example = "1024") @NotNull(message = "租户编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.http similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.http index ce138afcdb..6d9cea8010 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.http @@ -1,4 +1,4 @@ ### 请求 /system/user/page 接口 => 没有权限 GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10 -Authorization: Bearer test1 # 使用测试账号 -tenant-id: 1 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java index ae7628e49e..fbba577306 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java @@ -1,21 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user; +package cn.iocoder.yudao.module.system.controller.admin.user; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptSimpleRespVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.dept.SysDeptConvert; -import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; @@ -39,23 +34,21 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Api(tags = "用户") +@Api(tags = "管理后台 - 用户") @RestController @RequestMapping("/system/user") @Validated -public class SysUserController { +public class UserController { @Resource - private SysUserService userService; + private AdminUserService userService; @Resource - private SysUserCoreService userCoreService; - @Resource - private SysDeptService deptService; + private DeptService deptService; @PostMapping("/create") @ApiOperation("新增用户") @PreAuthorize("@ss.hasPermission('system:user:create')") - public CommonResult createUser(@Valid @RequestBody SysUserCreateReqVO reqVO) { + public CommonResult createUser(@Valid @RequestBody UserCreateReqVO reqVO) { Long id = userService.createUser(reqVO); return success(id); } @@ -63,7 +56,7 @@ public class SysUserController { @PutMapping("update") @ApiOperation("修改用户") @PreAuthorize("@ss.hasPermission('system:user:update')") - public CommonResult updateUser(@Valid @RequestBody SysUserUpdateReqVO reqVO) { + public CommonResult updateUser(@Valid @RequestBody UserUpdateReqVO reqVO) { userService.updateUser(reqVO); return success(true); } @@ -80,7 +73,7 @@ public class SysUserController { @PutMapping("/update-password") @ApiOperation("重置用户密码") @PreAuthorize("@ss.hasPermission('system:user:update-password')") - public CommonResult updateUserPassword(@Valid @RequestBody SysUserUpdatePasswordReqVO reqVO) { + public CommonResult updateUserPassword(@Valid @RequestBody UserUpdatePasswordReqVO reqVO) { userService.updateUserPassword(reqVO.getId(), reqVO.getPassword()); return success(true); } @@ -88,7 +81,7 @@ public class SysUserController { @PutMapping("/update-status") @ApiOperation("修改用户状态") @PreAuthorize("@ss.hasPermission('system:user:update')") - public CommonResult updateUserStatus(@Valid @RequestBody SysUserUpdateStatusReqVO reqVO) { + public CommonResult updateUserStatus(@Valid @RequestBody UserUpdateStatusReqVO reqVO) { userService.updateUserStatus(reqVO.getId(), reqVO.getStatus()); return success(true); } @@ -96,21 +89,21 @@ public class SysUserController { @GetMapping("/page") @ApiOperation("获得用户分页列表") @PreAuthorize("@ss.hasPermission('system:user:list')") - public CommonResult> getUserPage(@Valid SysUserPageReqVO reqVO) { + public CommonResult> getUserPage(@Valid UserPageReqVO reqVO) { // 获得用户分页列表 - PageResult pageResult = userService.getUserPage(reqVO); + PageResult pageResult = userService.getUserPage(reqVO); if (CollUtil.isEmpty(pageResult.getList())) { return success(new PageResult<>(pageResult.getTotal())); // 返回空 } // 获得拼接需要的数据 - Collection deptIds = convertList(pageResult.getList(), SysUserDO::getDeptId); - Map deptMap = deptService.getDeptMap(deptIds); + Collection deptIds = convertList(pageResult.getList(), AdminUserDO::getDeptId); + Map deptMap = deptService.getDeptMap(deptIds); // 拼接结果返回 - List userList = new ArrayList<>(pageResult.getList().size()); + List userList = new ArrayList<>(pageResult.getList().size()); pageResult.getList().forEach(user -> { - SysUserPageItemRespVO respVO = SysUserConvert.INSTANCE.convert(user); - respVO.setDept(SysUserConvert.INSTANCE.convert(deptMap.get(user.getDeptId()))); + UserPageItemRespVO respVO = UserConvert.INSTANCE.convert(user); + respVO.setDept(UserConvert.INSTANCE.convert(deptMap.get(user.getDeptId()))); userList.add(respVO); }); return success(new PageResult<>(userList, pageResult.getTotal())); @@ -118,38 +111,39 @@ public class SysUserController { @GetMapping("/list-all-simple") @ApiOperation(value = "获取用户精简信息列表", notes = "只包含被开启的用户,主要用于前端的下拉选项") - public CommonResult> getSimpleUsers() { + public CommonResult> getSimpleUsers() { // 获用户门列表,只要开启状态的 - List list = userService.getUsersByStatus(CommonStatusEnum.ENABLE.getStatus()); + List list = userService.getUsersByStatus(CommonStatusEnum.ENABLE.getStatus()); // 排序后,返回给前端 - return success(SysUserConvert.INSTANCE.convertList04(list)); + return success(UserConvert.INSTANCE.convertList04(list)); } @GetMapping("/get") @ApiOperation("获得用户详情") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('system:user:query')") - public CommonResult getInfo(@RequestParam("id") Long id) { - return success(SysUserConvert.INSTANCE.convert(userCoreService.getUser(id))); + public CommonResult getInfo(@RequestParam("id") Long id) { + return success(UserConvert.INSTANCE.convert(userService.getUser(id))); } @GetMapping("/export") @ApiOperation("导出用户") @PreAuthorize("@ss.hasPermission('system:user:export')") @OperateLog(type = EXPORT) - public void exportUsers(@Validated SysUserExportReqVO reqVO, + public void exportUsers(@Validated UserExportReqVO reqVO, HttpServletResponse response) throws IOException { // 获得用户列表 - List users = userService.getUsers(reqVO); + List users = userService.getUsers(reqVO); // 获得拼接需要的数据 - Collection deptIds = convertList(users, SysUserDO::getDeptId); - Map deptMap = deptService.getDeptMap(deptIds); - Map deptLeaderUserMap = userService.getUserMap(convertSet(deptMap.values(), SysDeptDO::getLeaderUserId)); + Collection deptIds = convertList(users, AdminUserDO::getDeptId); + Map deptMap = deptService.getDeptMap(deptIds); + Map deptLeaderUserMap = userService.getUserMap( + convertSet(deptMap.values(), DeptDO::getLeaderUserId)); // 拼接数据 - List excelUsers = new ArrayList<>(users.size()); + List excelUsers = new ArrayList<>(users.size()); users.forEach(user -> { - SysUserExcelVO excelVO = SysUserConvert.INSTANCE.convert02(user); + UserExcelVO excelVO = UserConvert.INSTANCE.convert02(user); // 设置部门 MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> { excelVO.setDeptName(dept.getName()); @@ -161,22 +155,22 @@ public class SysUserController { }); // 输出 - ExcelUtils.write(response, "用户数据.xls", "用户列表", SysUserExcelVO.class, excelUsers); + ExcelUtils.write(response, "用户数据.xls", "用户列表", UserExcelVO.class, excelUsers); } @GetMapping("/get-import-template") @ApiOperation("获得导入用户模板") public void importTemplate(HttpServletResponse response) throws IOException { // 手动创建导出 demo - List list = Arrays.asList( - SysUserImportExcelVO.builder().username("yudao").deptId(1L).email("yudao@iocoder.cn").mobile("15601691300") - .nickname("芋道").status(CommonStatusEnum.ENABLE.getStatus()).sex(SysSexEnum.MALE.getSex()).build(), - SysUserImportExcelVO.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300") - .nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SysSexEnum.FEMALE.getSex()).build() + List list = Arrays.asList( + UserImportExcelVO.builder().username("yudao").deptId(1L).email("yudao@iocoder.cn").mobile("15601691300") + .nickname("芋道").status(CommonStatusEnum.ENABLE.getStatus()).sex(SexEnum.MALE.getSex()).build(), + UserImportExcelVO.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300") + .nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build() ); // 输出 - ExcelUtils.write(response, "用户导入模板.xls", "用户列表", SysUserImportExcelVO.class, list); + ExcelUtils.write(response, "用户导入模板.xls", "用户列表", UserImportExcelVO.class, list); } @PostMapping("/import") @@ -186,9 +180,9 @@ public class SysUserController { @ApiImplicitParam(name = "updateSupport", value = "是否支持更新,默认为 false", example = "true", dataTypeClass = Boolean.class) }) @PreAuthorize("@ss.hasPermission('system:user:import')") - public CommonResult importExcel(@RequestParam("file") MultipartFile file, - @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { - List list = ExcelUtils.read(file, SysUserImportExcelVO.class); + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, UserImportExcelVO.class); return success(userService.importUsers(list, updateSupport)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.http b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.http similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.http rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.http index c0a817727c..f06037b37b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.http +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.http @@ -1,3 +1,4 @@ ### 请求 /system/user/profile/get 接口 => 没有权限 GET {{baseUrl}}/system/user/profile/get -Authorization: Bearer test1 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java new file mode 100644 index 0000000000..b46254713c --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.system.controller.admin.user; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.dept.PostService; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.service.permission.RoleService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.FILE_IS_EMPTY; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Api(tags = "管理后台 - 用户个人中心") +@RestController +@RequestMapping("/system/user/profile") +@Validated +@Slf4j +public class UserProfileController { + + @Resource + private AdminUserService userService; + @Resource + private DeptService deptService; + + @Resource + private PostService postService; + @Resource + private PermissionService permissionService; + @Resource + private RoleService roleService; + @Resource + private SocialUserService socialService; + + @GetMapping("/get") + @ApiOperation("获得登录用户信息") + public CommonResult profile() { + // 获得用户基本信息 + AdminUserDO user = userService.getUser(getLoginUserId()); + UserProfileRespVO resp = UserConvert.INSTANCE.convert03(user); + // 获得用户角色 + List userRoles = roleService.getRolesFromCache(permissionService.getUserRoleIdListByUserId(user.getId())); + resp.setRoles(UserConvert.INSTANCE.convertList(userRoles)); + // 获得部门信息 + if (user.getDeptId() != null) { + DeptDO dept = deptService.getDept(user.getDeptId()); + resp.setDept(UserConvert.INSTANCE.convert02(dept)); + } + // 获得岗位信息 + if (CollUtil.isNotEmpty(user.getPostIds())) { + List posts = postService.getPosts(user.getPostIds()); + resp.setPosts(UserConvert.INSTANCE.convertList02(posts)); + } + // 获得社交用户信息 + List socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue()); + resp.setSocialUsers(UserConvert.INSTANCE.convertList03(socialUsers)); + return success(resp); + } + + @PutMapping("/update") + @ApiOperation("修改用户个人信息") + public CommonResult updateUserProfile(@Valid @RequestBody UserProfileUpdateReqVO reqVO) { + userService.updateUserProfile(getLoginUserId(), reqVO); + return success(true); + } + + @PutMapping("/update-password") + @ApiOperation("修改用户个人密码") + public CommonResult updateUserProfilePassword(@Valid @RequestBody UserProfileUpdatePasswordReqVO reqVO) { + userService.updateUserPassword(getLoginUserId(), reqVO); + return success(true); + } + + @PutMapping("/update-avatar") + @ApiOperation("上传用户个人头像") + public CommonResult updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException { + if (file.isEmpty()) { + throw ServiceExceptionUtil.exception(FILE_IS_EMPTY); + } + String avatar = userService.updateUserAvatar(getLoginUserId(), file.getInputStream()); + return success(avatar); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java index 4269aaec08..c0b77f0f2d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserBaseVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserBaseVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -16,13 +16,13 @@ import java.util.List; @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor -@ApiModel("用户个人中心信息 Response VO") -public class SysUserProfileRespVO extends SysUserBaseVO { +@ApiModel("管理后台 - 用户个人中心信息 Response VO") +public class UserProfileRespVO extends UserBaseVO { @ApiModelProperty(value = "用户编号", required = true, example = "1") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "最后登录 IP", required = true, example = "192.168.1.1") @@ -93,7 +93,7 @@ public class SysUserProfileRespVO extends SysUserBaseVO { @Data public static class SocialUser { - @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysSocialTypeEnum 枚举类") + @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SocialTypeEnum 枚举类") private Integer type; @ApiModelProperty(value = "社交的全局编号", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java index 340d2e4078..2269b37df5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdatePasswordReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,9 +7,9 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; -@ApiModel("用户个人中心更新密码 Request VO") +@ApiModel("管理后台 - 用户个人中心更新密码 Request VO") @Data -public class SysUserProfileUpdatePasswordReqVO { +public class UserProfileUpdatePasswordReqVO { @ApiModelProperty(value = "旧密码", required = true, example = "123456") @NotEmpty(message = "旧密码不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java index e77bcd7f64..3716f4727a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/profile/SysUserProfileUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,9 +8,9 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Email; import javax.validation.constraints.Size; -@ApiModel("用户个人信息更新 Request VO") +@ApiModel("管理后台 - 用户个人信息更新 Request VO") @Data -public class SysUserProfileUpdateReqVO { +public class UserProfileUpdateReqVO { @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") @Size(max = 30, message = "用户昵称长度不能超过30个字符") @@ -25,7 +25,7 @@ public class SysUserProfileUpdateReqVO { @Length(min = 11, max = 11, message = "手机号长度必须 11 位") private String mobile; - @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类") + @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类") private Integer sex; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserBaseVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserBaseVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java index 1f41be3dba..985783f0b9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserBaseVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Set; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class SysUserBaseVO { +public class UserBaseVO { @ApiModelProperty(value = "用户账号", required = true, example = "yudao") @NotBlank(message = "用户账号不能为空") @@ -43,10 +43,10 @@ public class SysUserBaseVO { @Length(min = 11, max = 11, message = "手机号长度必须 11 位") private String mobile; - @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类") + @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类") private Integer sex; - @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png") + @ApiModelProperty(value = "用户头像", example = "https://www.iocoder.cn/xxx.png") private String avatar; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserCreateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserCreateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java index 89f2e17987..9d0ff1988d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserCreateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; @@ -9,10 +9,10 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; -@ApiModel("用户创建 Request VO") +@ApiModel("管理后台 - 用户创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysUserCreateReqVO extends SysUserBaseVO { +public class UserCreateReqVO extends UserBaseVO { @ApiModelProperty(value = "密码", required = true, example = "123456") @NotEmpty(message = "密码不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java index 02712ba868..a9163cb6cf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -12,7 +12,7 @@ import java.util.Date; * 用户 Excel 导出 VO */ @Data -public class SysUserExcelVO { +public class UserExcelVO { @ExcelProperty("用户编号") private Long id; @@ -30,11 +30,11 @@ public class SysUserExcelVO { private String mobile; @ExcelProperty(value = "用户性别", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.USER_SEX) + @DictFormat(DictTypeConstants.USER_SEX) private Integer sex; @ExcelProperty(value = "帐号状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; @ExcelProperty("最后登录IP") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExportReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java similarity index 82% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExportReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java index 24d8d00c34..a25ba0b0f4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserExportReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -11,11 +11,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel(value = "用户导出 Request VO", description = "参数和 SysUserPageReqVO 是一致的") +@ApiModel(value = "管理后台 - 用户导出 Request VO", description = "参数和 UserPageReqVO 是一致的") @Data @NoArgsConstructor @AllArgsConstructor -public class SysUserExportReqVO { +public class UserExportReqVO { @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") private String username; @@ -23,7 +23,7 @@ public class SysUserExportReqVO { @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配") private String mobile; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "开始时间", example = "2020-10-24") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportExcelVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportExcelVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java index b641f6412e..a360f1af2c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportExcelVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; @@ -18,7 +18,7 @@ import lombok.experimental.Accessors; @AllArgsConstructor @NoArgsConstructor @Accessors(chain = false) // 设置 chain = false,避免用户导入有问题 -public class SysUserImportExcelVO { +public class UserImportExcelVO { @ExcelProperty("登录名称") private String username; @@ -36,11 +36,11 @@ public class SysUserImportExcelVO { private String mobile; @ExcelProperty(value = "用户性别", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.USER_SEX) + @DictFormat(DictTypeConstants.USER_SEX) private Integer sex; @ExcelProperty(value = "账号状态", converter = DictConvert.class) - @DictFormat(SysDictTypeConstants.COMMON_STATUS) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java index bb4359eed6..49f9b98d1e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserImportRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,10 +8,10 @@ import lombok.Data; import java.util.List; import java.util.Map; -@ApiModel("用户导入 Response VO") +@ApiModel("管理后台 - 用户导入 Response VO") @Data @Builder -public class SysUserImportRespVO { +public class UserImportRespVO { @ApiModelProperty(value = "创建成功的用户名数组", required = true) private List createUsernames; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java index 58959a5331..bcfe9ea23b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,12 +7,12 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -@ApiModel(value = "用户分页时的信息 Response VO", description = "相比用户基本信息来说,会多部门信息") +@ApiModel(value = "管理后台 - 用户分页时的信息 Response VO", description = "相比用户基本信息来说,会多部门信息") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysUserPageItemRespVO extends SysUserRespVO { +public class UserPageItemRespVO extends UserRespVO { /** * 所在部门 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java index ca1e597f95..00f20eb4d8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserPageReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -13,12 +13,12 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("用户分页 Request VO") +@ApiModel("管理后台 - 用户分页 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysUserPageReqVO extends PageParam { +public class UserPageReqVO extends PageParam { @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") private String username; @@ -26,7 +26,7 @@ public class SysUserPageReqVO extends PageParam { @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配") private String mobile; - @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "开始时间", example = "2020-10-24") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java index 79abf64e59..b4525a5553 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,17 +6,17 @@ import lombok.*; import java.util.Date; -@ApiModel("用户信息 Response VO") +@ApiModel("管理后台 - 用户信息 Response VO") @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SysUserRespVO extends SysUserBaseVO { +public class UserRespVO extends UserBaseVO { @ApiModelProperty(value = "用户编号", required = true, example = "1") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类") private Integer status; @ApiModelProperty(value = "最后登录 IP", required = true, example = "192.168.1.1") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserSimpleRespVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserSimpleRespVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java index cd2b65c88d..a815253e94 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -10,7 +10,7 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -public class SysUserSimpleRespVO { +public class UserSimpleRespVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdatePasswordReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdatePasswordReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java index 9364c57aa7..542fc2b0f2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdatePasswordReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java @@ -1,17 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import lombok.EqualsAndHashCode; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -@ApiModel("用户更新密码 Request VO") +@ApiModel("管理后台 - 用户更新密码 Request VO") @Data -public class SysUserUpdatePasswordReqVO { +public class UserUpdatePasswordReqVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "用户编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java index 7fc8ffbb92..84a3de60fe 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -7,10 +7,10 @@ import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; -@ApiModel("用户更新 Request VO") +@ApiModel("管理后台 - 用户更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) -public class SysUserUpdateReqVO extends SysUserBaseVO { +public class UserUpdateReqVO extends UserBaseVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "用户编号不能为空") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateStatusReqVO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateStatusReqVO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java index dd1baa4fa7..2c7a83f22d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/SysUserUpdateStatusReqVO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; +package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,17 +6,17 @@ import lombok.Data; import javax.validation.constraints.NotNull; -@ApiModel("用户更新状态 Request VO") +@ApiModel("管理后台 - 用户更新状态 Request VO") @Data -public class SysUserUpdateStatusReqVO { +public class UserUpdateStatusReqVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "角色编号不能为空") private Long id; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 SysCommonStatusEnum 枚举") + @ApiModelProperty(value = "状态", required = true, example = "1", notes = "见 CommonStatusEnum 枚举") @NotNull(message = "状态不能为空") -// @InEnum(value = SysCommonStatusEnum.class, message = "修改状态必须是 {value}") +// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/package-info.java new file mode 100644 index 0000000000..9e4739f4c4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位,避免 package 无法提交到 Git 仓库 + */ +package cn.iocoder.yudao.module.system.controller.app; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/package-info.java new file mode 100644 index 0000000000..659a909478 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.system.controller; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java new file mode 100644 index 0000000000..c52328cc0d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.system.convert.auth; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.permission.MenuIdEnum; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import org.slf4j.LoggerFactory; + +import java.util.*; + +@Mapper +public interface AuthConvert { + + AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class); + + @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略 + LoginUser convert0(AdminUserDO bean); + + default LoginUser convert(AdminUserDO bean) { + // 目的,为了设置 UserTypeEnum.ADMIN.getValue() + return convert0(bean).setUserType(UserTypeEnum.ADMIN.getValue()); + } + + default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { + return AuthPermissionInfoRespVO.builder() + .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .roles(CollectionUtils.convertSet(roleList, RoleDO::getCode)) + .permissions(CollectionUtils.convertSet(menuList, MenuDO::getPermission)) + .build(); + } + + AuthMenuRespVO convertTreeNode(MenuDO menu); + + /** + * 将菜单列表,构建成菜单树 + * + * @param menuList 菜单列表 + * @return 菜单树 + */ + default List buildMenuTree(List menuList) { + // 排序,保证菜单的有序性 + menuList.sort(Comparator.comparing(MenuDO::getSort)); + // 构建菜单树 + // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 + Map treeNodeMap = new LinkedHashMap<>(); + menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AuthConvert.INSTANCE.convertTreeNode(menu))); + // 处理父子关系 + treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach(childNode -> { + // 获得父节点 + AuthMenuRespVO parentNode = treeNodeMap.get(childNode.getParentId()); + if (parentNode == null) { + LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", + childNode.getId(), childNode.getParentId()); + return; + } + // 将自己添加到父节点中 + if (parentNode.getChildren() == null) { + parentNode.setChildren(new ArrayList<>()); + } + parentNode.getChildren().add(childNode); + }); + // 获得到所有的根节点 + return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); + } + + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialBindReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLogin2ReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO); + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AuthSocialUnbindReqVO reqVO); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/UserSessionConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/UserSessionConvert.java new file mode 100644 index 0000000000..d30dfdcbb4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/UserSessionConvert.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.system.convert.auth; + +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageItemRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface UserSessionConvert { + + UserSessionConvert INSTANCE = Mappers.getMapper(UserSessionConvert.class); + + UserSessionPageItemRespVO convert(UserSessionDO session); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/common/CaptchaConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/common/CaptchaConvert.java new file mode 100644 index 0000000000..54d36bee9a --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/common/CaptchaConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.system.convert.common; + +import cn.hutool.captcha.AbstractCaptcha; +import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface CaptchaConvert { + + CaptchaConvert INSTANCE = Mappers.getMapper(CaptchaConvert.class); + + default CaptchaImageRespVO convert(String uuid, AbstractCaptcha captcha) { + return CaptchaImageRespVO.builder().uuid(uuid).img(captcha.getImageBase64()).build(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java new file mode 100644 index 0000000000..2a514743b8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.convert.dept; + +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface DeptConvert { + + DeptConvert INSTANCE = Mappers.getMapper(DeptConvert.class); + + List convertList(List list); + + List convertList02(List list); + + DeptRespVO convert(DeptDO bean); + + DeptDO convert(DeptCreateReqVO bean); + + DeptDO convert(DeptUpdateReqVO bean); + + List convertList03(List list); + + DeptRespDTO convert03(DeptDO bean); + + Map convertMap(Map map); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java new file mode 100644 index 0000000000..86a548edbe --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.convert.dept; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface PostConvert { + + PostConvert INSTANCE = Mappers.getMapper(PostConvert.class); + + List convertList02(List list); + + PageResult convertPage(PageResult page); + + PostRespVO convert(PostDO id); + + PostDO convert(PostCreateReqVO bean); + + PostDO convert(PostUpdateReqVO reqVO); + + List convertList03(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java new file mode 100644 index 0000000000..215f252e79 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.convert.dict; + +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.*; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface DictDataConvert { + + DictDataConvert INSTANCE = Mappers.getMapper(DictDataConvert.class); + + List convertList(List list); + + DictDataRespVO convert(DictDataDO bean); + + PageResult convertPage(PageResult page); + + DictDataDO convert(DictDataUpdateReqVO bean); + + DictDataDO convert(DictDataCreateReqVO bean); + + List convertList02(List bean); + + DictDataRespDTO convert02(DictDataDO bean); + + List convertList03(Collection list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java new file mode 100644 index 0000000000..392e3082e7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.convert.dict; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.*; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface DictTypeConvert { + + DictTypeConvert INSTANCE = Mappers.getMapper(DictTypeConvert.class); + + PageResult convertPage(PageResult bean); + + DictTypeRespVO convert(DictTypeDO bean); + + DictTypeDO convert(DictTypeCreateReqVO bean); + + DictTypeDO convert(DictTypeUpdateReqVO bean); + + List convertList(List list); + + List convertList02(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java new file mode 100644 index 0000000000..0402aca8b4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.system.convert.errorcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 错误码 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ErrorCodeConvert { + + ErrorCodeConvert INSTANCE = Mappers.getMapper(ErrorCodeConvert.class); + + ErrorCodeDO convert(ErrorCodeCreateReqVO bean); + + ErrorCodeDO convert(ErrorCodeUpdateReqVO bean); + + ErrorCodeRespVO convert(ErrorCodeDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + ErrorCodeDO convert(ErrorCodeAutoGenerateReqDTO bean); + + List convertList03(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java new file mode 100644 index 0000000000..ea50d4b095 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.convert.logger; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface LoginLogConvert { + + LoginLogConvert INSTANCE = Mappers.getMapper(LoginLogConvert.class); + + PageResult convertPage(PageResult page); + + List convertList(List list); + + LoginLogDO convert(LoginLogCreateReqDTO bean); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java new file mode 100644 index 0000000000..21584c9fcf --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.system.convert.logger; + +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; + +@Mapper +public interface OperateLogConvert { + + OperateLogConvert INSTANCE = Mappers.getMapper(OperateLogConvert.class); + + OperateLogDO convert(OperateLogCreateReqDTO bean); + + PageResult convertPage(PageResult page); + + OperateLogRespVO convert(OperateLogDO bean); + + default List convertList(List list, Map userMap) { + return list.stream().map(operateLog -> { + OperateLogExcelVO excelVO = convert02(operateLog); + MapUtils.findAndThen(userMap, operateLog.getId(), user -> excelVO.setUserNickname(user.getNickname())); + excelVO.setSuccessStr(SUCCESS.getCode().equals(operateLog.getResultCode()) ? "成功" : "失败"); + return excelVO; + }).collect(Collectors.toList()); + } + + OperateLogExcelVO convert02(OperateLogDO bean); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java new file mode 100644 index 0000000000..ad2bedec76 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.convert.notice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface NoticeConvert { + + NoticeConvert INSTANCE = Mappers.getMapper(NoticeConvert.class); + + PageResult convertPage(PageResult page); + + NoticeRespVO convert(NoticeDO bean); + + NoticeDO convert(NoticeUpdateReqVO bean); + + NoticeDO convert(NoticeCreateReqVO bean); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/package-info.java new file mode 100644 index 0000000000..b1ce8e379d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 POJO 类的实体转换 + * + * 目前使用 MapStruct 框架 + */ +package cn.iocoder.yudao.module.system.convert; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java new file mode 100644 index 0000000000..0fb3505cce --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.convert.permission; + +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface MenuConvert { + + MenuConvert INSTANCE = Mappers.getMapper(MenuConvert.class); + + List convertList(List list); + + MenuDO convert(MenuCreateReqVO bean); + + MenuDO convert(MenuUpdateReqVO bean); + + MenuRespVO convert(MenuDO bean); + + List convertList02(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java new file mode 100644 index 0000000000..646d7061de --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.system.convert.permission; + +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface RoleConvert { + + RoleConvert INSTANCE = Mappers.getMapper(RoleConvert.class); + + RoleDO convert(RoleUpdateReqVO bean); + + RoleRespVO convert(RoleDO bean); + + RoleDO convert(RoleCreateReqVO bean); + + List convertList02(List list); + + List convertList03(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java new file mode 100644 index 0000000000..0776c58f60 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.convert.sms; + +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 短信渠道 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SmsChannelConvert { + + SmsChannelConvert INSTANCE = Mappers.getMapper(SmsChannelConvert.class); + + SmsChannelDO convert(SmsChannelCreateReqVO bean); + + SmsChannelDO convert(SmsChannelUpdateReqVO bean); + + SmsChannelRespVO convert(SmsChannelDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + List convertList03(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java new file mode 100644 index 0000000000..40efe60a1e --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.system.convert.sms; + +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 短信日志 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SmsLogConvert { + + SmsLogConvert INSTANCE = Mappers.getMapper(SmsLogConvert.class); + + SmsLogRespVO convert(SmsLogDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java new file mode 100644 index 0000000000..b0fb02b8f9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.convert.sms; + +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface SmsTemplateConvert { + + SmsTemplateConvert INSTANCE = Mappers.getMapper(SmsTemplateConvert.class); + + SmsTemplateDO convert(SmsTemplateCreateReqVO bean); + + SmsTemplateDO convert(SmsTemplateUpdateReqVO bean); + + SmsTemplateRespVO convert(SmsTemplateDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java new file mode 100755 index 0000000000..afc05a92f8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.convert.tenant; + +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantRespVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 租户 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface TenantConvert { + + TenantConvert INSTANCE = Mappers.getMapper(TenantConvert.class); + + TenantDO convert(TenantCreateReqVO bean); + + TenantDO convert(TenantUpdateReqVO bean); + + TenantRespVO convert(TenantDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java new file mode 100644 index 0000000000..2e8a473366 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.system.convert.user; + +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface UserConvert { + + UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); + + UserPageItemRespVO convert(AdminUserDO bean); + + UserPageItemRespVO.Dept convert(DeptDO bean); + + AdminUserDO convert(UserCreateReqVO bean); + + AdminUserDO convert(UserUpdateReqVO bean); + + UserExcelVO convert02(AdminUserDO bean); + + AdminUserDO convert(UserImportExcelVO bean); + + UserProfileRespVO convert03(AdminUserDO bean); + + List convertList(List list); + + UserProfileRespVO.Dept convert02(DeptDO bean); + + AdminUserDO convert(UserProfileUpdateReqVO bean); + + AdminUserDO convert(UserProfileUpdatePasswordReqVO bean); + + List convertList02(List list); + + List convertList03(List list); + + List convertList04(List list); + + AdminUserRespDTO convert4(AdminUserDO bean); + + List convertList4(List users); + + Map convertMap4(Map map); + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md similarity index 100% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/UserSessionDO.java similarity index 78% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/UserSessionDO.java index d30d38491d..01885004ee 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/UserSessionDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth; +package cn.iocoder.yudao.module.system.dal.dataobject.auth; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.security.core.LoginUser; @@ -17,15 +17,15 @@ import java.util.Date; * * 我们已经将 {@link LoginUser} 缓存在 Redis 当中。 * 这里额外存储在线用户到 MySQL 中,目的是为了方便管理界面可以灵活查询。 - * 同时,通过定时轮询 SysUserSessionDO 表,可以主动删除 Redis 的缓存,因为 Redis 的过期删除是延迟的。 + * 同时,通过定时轮询 UserSessionDO 表,可以主动删除 Redis 的缓存,因为 Redis 的过期删除是延迟的。 * * @author 芋道源码 */ -@TableName(value = "sys_user_session", autoResultMap = true) +@TableName(value = "system_user_session", autoResultMap = true) @Data @Builder @EqualsAndHashCode(callSuper = true) -public class SysUserSessionDO extends TenantBaseDO { +public class UserSessionDO extends TenantBaseDO { /** * 会话编号, 即 sessionId @@ -35,7 +35,7 @@ public class SysUserSessionDO extends TenantBaseDO { /** * 用户编号 * - * 关联 SysUserDO.id 或者 MbrUserDO.id + * 关联 AdminUserDO.id 或者 MemberUserDO.id */ private Long userId; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java index ad0be694ab..557a1f36f8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept; +package cn.iocoder.yudao.module.system.dal.dataobject.dept; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import com.baomidou.mybatisplus.annotation.TableId; @@ -14,10 +14,10 @@ import lombok.EqualsAndHashCode; * @author ruoyi * @author 芋道源码 */ -@TableName("sys_dept") +@TableName("system_dept") @Data @EqualsAndHashCode(callSuper = true) -public class SysDeptDO extends TenantBaseDO { +public class DeptDO extends TenantBaseDO { /** * 部门ID @@ -41,7 +41,7 @@ public class SysDeptDO extends TenantBaseDO { /** * 负责人 * - * 关联 {@link SysUserDO#getId()} + * 关联 {@link AdminUserDO#getId()} */ private Long leaderUserId; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/PostDO.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/PostDO.java index 29652a0d81..ba9074d034 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/PostDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept; +package cn.iocoder.yudao.module.system.dal.dataobject.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; @@ -12,10 +12,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_post") +@TableName("system_post") @Data @EqualsAndHashCode(callSuper = true) -public class SysPostDO extends TenantBaseDO { +public class PostDO extends TenantBaseDO { /** * 岗位序号 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/dict/SysDictDataDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictDataDO.java similarity index 81% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/dict/SysDictDataDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictDataDO.java index d398d5ef34..1b5cee4e4e 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/dict/SysDictDataDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictDataDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict; +package cn.iocoder.yudao.module.system.dal.dataobject.dict; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -12,10 +12,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_dict_data") +@TableName("system_dict_data") @Data @EqualsAndHashCode(callSuper = true) -public class SysDictDataDO extends BaseDO { +public class DictDataDO extends BaseDO { /** * 字典数据编号 @@ -37,7 +37,7 @@ public class SysDictDataDO extends BaseDO { /** * 字典类型 * - * 冗余 {@link SysDictDataDO#getDictType()} + * 冗余 {@link DictDataDO#getDictType()} */ private String dictType; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dict/SysDictTypeDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dict/SysDictTypeDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java index 548ee6fe9a..01455f4383 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dict/SysDictTypeDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict; +package cn.iocoder.yudao.module.system.dal.dataobject.dict; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -12,14 +12,14 @@ import lombok.*; * * @author ruoyi */ -@TableName("sys_dict_type") +@TableName("system_dict_type") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class SysDictTypeDO extends BaseDO { +public class DictTypeDO extends BaseDO { /** * 字典主键 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/errorcode/SysErrorCodeDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/errorcode/ErrorCodeDO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/errorcode/SysErrorCodeDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/errorcode/ErrorCodeDO.java index d2fdb182e7..b279492873 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/errorcode/SysErrorCodeDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/errorcode/ErrorCodeDO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode; +package cn.iocoder.yudao.module.system.dal.dataobject.errorcode; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; +import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -13,11 +13,11 @@ import lombok.ToString; * * @author 芋道源码 */ -@TableName(value = "sys_error_code") +@TableName(value = "system_error_code") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysErrorCodeDO extends BaseDO { +public class ErrorCodeDO extends BaseDO { /** * 错误码编号,自增 @@ -27,7 +27,7 @@ public class SysErrorCodeDO extends BaseDO { /** * 错误码类型 * - * 枚举 {@link SysErrorCodeTypeEnum} + * 枚举 {@link ErrorCodeTypeEnum} */ private Integer type; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/logger/SysLoginLogDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/LoginLogDO.java similarity index 73% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/logger/SysLoginLogDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/LoginLogDO.java index e7e7a4144b..66a81443bf 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/logger/SysLoginLogDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/LoginLogDO.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger; +package cn.iocoder.yudao.module.system.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,11 +16,11 @@ import lombok.ToString; * * @author 芋道源码 */ -@TableName("sys_login_log") +@TableName("system_login_log") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysLoginLogDO extends BaseDO { +public class LoginLogDO extends BaseDO { /** * 日志主键 @@ -29,7 +29,7 @@ public class SysLoginLogDO extends BaseDO { /** * 日志类型 * - * 枚举 {@link SysLoginLogTypeEnum} + * 枚举 {@link LoginLogTypeEnum} */ private Integer logType; /** @@ -55,7 +55,7 @@ public class SysLoginLogDO extends BaseDO { /** * 登录结果 * - * 枚举 {@link SysLoginResultEnum} + * 枚举 {@link LoginResultEnum} */ private Integer result; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogDO.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogDO.java index 417c6f45fa..c76ec5f7b1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger; +package cn.iocoder.yudao.module.system.dal.dataobject.logger; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; @@ -19,10 +19,10 @@ import java.util.Map; * * @author 芋道源码 */ -@TableName(value = "sys_operate_log", autoResultMap = true) +@TableName(value = "system_operate_log", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) -public class SysOperateLogDO extends TenantBaseDO { +public class OperateLogDO extends TenantBaseDO { /** * {@link #javaMethodArgs} 的最大长度 @@ -48,9 +48,15 @@ public class SysOperateLogDO extends TenantBaseDO { /** * 用户编号 * - * {@link SysUserDO#getId()} + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 */ private Long userId; + /** + * 用户类型 + * + * 关联 {@link UserTypeEnum} + */ + private Integer userType; /** * 操作模块 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeDO.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeDO.java index c61398fe63..20860b835a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notice/NoticeDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice; +package cn.iocoder.yudao.module.system.dal.dataobject.notice; -import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum; +import cn.iocoder.yudao.module.system.enums.notice.NoticeTypeEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import com.baomidou.mybatisplus.annotation.TableField; @@ -13,10 +13,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_notice") +@TableName("system_notice") @Data @EqualsAndHashCode(callSuper = true) -public class SysNoticeDO extends TenantBaseDO { +public class NoticeDO extends TenantBaseDO { /** * 公告ID @@ -29,7 +29,7 @@ public class SysNoticeDO extends TenantBaseDO { /** * 公告类型 * - * 枚举 {@link SysNoticeTypeEnum} + * 枚举 {@link NoticeTypeEnum} */ @TableField("notice_type") private Integer type; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/package-info.java new file mode 100644 index 0000000000..000c252fcb --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.system.dal.dataobject; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysMenuDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysMenuDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java index 043f2e93db..2915efa4cb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysMenuDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission; +package cn.iocoder.yudao.module.system.dal.dataobject.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum; +import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -14,10 +14,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_menu") +@TableName("system_menu") @Data @EqualsAndHashCode(callSuper = true) -public class SysMenuDO extends BaseDO { +public class MenuDO extends BaseDO { /** * 菜单ID @@ -34,7 +34,7 @@ public class SysMenuDO extends BaseDO { * 一般格式为:${系统}:${模块}:${操作} * 例如说:system:admin:add,即 system 服务的添加管理员。 * - * 当我们把该 SysMenuDO 赋予给角色后,意味着该角色有该资源: + * 当我们把该 MenuDO 赋予给角色后,意味着该角色有该资源: * - 对于后端,配合 @PreAuthorize 注解,配置 API 接口需要该权限,从而对 API 接口进行权限控制。 * - 对于前端,配合前端标签,配置按钮是否展示,避免用户没有该权限时,结果可以看到该操作。 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java index 72ebedbfd1..cd3151f457 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java @@ -1,11 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission; +package cn.iocoder.yudao.module.system.dal.dataobject.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.RoleCodeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.SysRoleTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -19,10 +17,10 @@ import java.util.Set; * * @author ruoyi */ -@TableName(value = "sys_role", autoResultMap = true) +@TableName(value = "system_role", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) -public class SysRoleDO extends BaseDO { +public class RoleDO extends BaseDO { /** * 角色ID @@ -36,7 +34,7 @@ public class SysRoleDO extends BaseDO { /** * 角色标识 * - * 枚举 {@link RoleCodeEnum} + * 枚举 */ private String code; /** @@ -52,7 +50,7 @@ public class SysRoleDO extends BaseDO { /** * 角色类型 * - * 枚举 {@link SysRoleTypeEnum} + * 枚举 */ private Integer type; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleMenuDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleMenuDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleMenuDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleMenuDO.java index 5cb6c1a170..6b7778bf07 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysRoleMenuDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleMenuDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission; +package cn.iocoder.yudao.module.system.dal.dataobject.permission; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableId; @@ -11,10 +11,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_role_menu") +@TableName("system_role_menu") @Data @EqualsAndHashCode(callSuper = true) -public class SysRoleMenuDO extends BaseDO { +public class RoleMenuDO extends BaseDO { /** * 自增主键 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysUserRoleDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysUserRoleDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java index 6792f56087..d54b0f8250 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/permission/SysUserRoleDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission; +package cn.iocoder.yudao.module.system.dal.dataobject.permission; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableId; @@ -11,10 +11,10 @@ import lombok.EqualsAndHashCode; * * @author ruoyi */ -@TableName("sys_user_role") +@TableName("system_user_role") @Data @EqualsAndHashCode(callSuper = true) -public class SysUserRoleDO extends BaseDO { +public class UserRoleDO extends BaseDO { /** * 自增主键 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsChannelDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java similarity index 85% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsChannelDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java index 87b67cd7fe..5e6b8c4191 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsChannelDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms; +package cn.iocoder.yudao.module.system.dal.dataobject.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -14,11 +14,11 @@ import lombok.ToString; * @author zzf * @since 2021-01-25 */ -@TableName(value = "sys_sms_channel", autoResultMap = true) +@TableName(value = "system_sms_channel", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsChannelDO extends BaseDO { +public class SmsChannelDO extends BaseDO { /** * 渠道编号 diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/sms/SysSmsCodeDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java similarity index 81% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/sms/SysSmsCodeDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java index 8cce25f42a..b67a7326f4 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/sms/SysSmsCodeDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsCodeDO.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms; +package cn.iocoder.yudao.module.system.dal.dataobject.sms; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import lombok.experimental.Accessors; import java.util.Date; @@ -14,13 +13,13 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName("sys_sms_code") +@TableName("system_sms_code") @Data @EqualsAndHashCode(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class SysSmsCodeDO extends BaseDO { +public class SmsCodeDO extends BaseDO { /** * 编号 @@ -37,7 +36,7 @@ public class SysSmsCodeDO extends BaseDO { /** * 发送场景 * - * 枚举 {@link SysSmsCodeDO} + * 枚举 {@link SmsCodeDO} */ private Integer scene; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsLogDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java similarity index 78% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsLogDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java index 6567ee215f..441f6ad178 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsLogDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms; +package cn.iocoder.yudao.module.system.dal.dataobject.sms; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsReceiveStatusEnum; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsSendStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; @@ -19,14 +19,14 @@ import java.util.Map; * @author zzf * @since 2021-01-25 */ -@TableName(value = "sys_sms_log", autoResultMap = true) +@TableName(value = "system_sms_log", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @AllArgsConstructor @NoArgsConstructor -public class SysSmsLogDO extends BaseDO { +public class SmsLogDO extends BaseDO { /** * 自增编号 @@ -38,13 +38,13 @@ public class SysSmsLogDO extends BaseDO { /** * 短信渠道编号 * - * 关联 {@link SysSmsChannelDO#getId()} + * 关联 {@link SmsChannelDO#getId()} */ private Long channelId; /** * 短信渠道编码 * - * 冗余 {@link SysSmsChannelDO#getCode()} + * 冗余 {@link SmsChannelDO#getCode()} */ private String channelCode; @@ -53,34 +53,34 @@ public class SysSmsLogDO extends BaseDO { /** * 模板编号 * - * 关联 {@link SysSmsTemplateDO#getId()} + * 关联 {@link SmsTemplateDO#getId()} */ private Long templateId; /** * 模板编码 * - * 冗余 {@link SysSmsTemplateDO#getCode()} + * 冗余 {@link SmsTemplateDO#getCode()} */ private String templateCode; /** * 短信类型 * - * 冗余 {@link SysSmsTemplateDO#getType()} + * 冗余 {@link SmsTemplateDO#getType()} */ private Integer templateType; /** - * 基于 {@link SysSmsTemplateDO#getContent()} 格式化后的内容 + * 基于 {@link SmsTemplateDO#getContent()} 格式化后的内容 */ private String templateContent; /** - * 基于 {@link SysSmsTemplateDO#getParams()} 输入后的参数 + * 基于 {@link SmsTemplateDO#getParams()} 输入后的参数 */ @TableField(typeHandler = JacksonTypeHandler.class) private Map templateParams; /** * 短信 API 的模板编号 * - * 冗余 {@link SysSmsTemplateDO#getApiTemplateId()} + * 冗余 {@link SmsTemplateDO#getApiTemplateId()} */ private String apiTemplateId; @@ -106,7 +106,7 @@ public class SysSmsLogDO extends BaseDO { /** * 发送状态 * - * 枚举 {@link SysSmsSendStatusEnum} + * 枚举 {@link SmsSendStatusEnum} */ private Integer sendStatus; /** @@ -154,7 +154,7 @@ public class SysSmsLogDO extends BaseDO { /** * 接收状态 * - * 枚举 {@link SysSmsReceiveStatusEnum} + * 枚举 {@link SmsReceiveStatusEnum} */ private Integer receiveStatus; /** diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsTemplateDO.java similarity index 79% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsTemplateDO.java index 9e1dd35c71..54c2098681 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/sms/SysSmsTemplateDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsTemplateDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms; +package cn.iocoder.yudao.module.system.dal.dataobject.sms; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsTemplateTypeEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableField; @@ -18,11 +18,11 @@ import java.util.List; * @author zzf * @since 2021-01-25 */ -@TableName(value = "sys_sms_template", autoResultMap = true) +@TableName(value = "system_sms_template", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class SysSmsTemplateDO extends BaseDO { +public class SmsTemplateDO extends BaseDO { /** * 自增编号 @@ -34,7 +34,7 @@ public class SysSmsTemplateDO extends BaseDO { /** * 短信类型 * - * 枚举 {@link SysSmsTemplateTypeEnum} + * 枚举 {@link SmsTemplateTypeEnum} */ private Integer type; /** @@ -76,13 +76,13 @@ public class SysSmsTemplateDO extends BaseDO { /** * 短信渠道编号 * - * 关联 {@link SysSmsChannelDO#getId()} + * 关联 {@link SmsChannelDO#getId()} */ private Long channelId; /** * 短信渠道编码 * - * 冗余 {@link SysSmsChannelDO#getCode()} + * 冗余 {@link SmsChannelDO#getCode()} */ private String channelCode; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/social/SysSocialUserDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserDO.java similarity index 81% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/social/SysSocialUserDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserDO.java index d1772a1324..9572f1e939 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/social/SysSocialUserDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social; +package cn.iocoder.yudao.module.system.dal.dataobject.social; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableId; @@ -9,17 +9,17 @@ import lombok.*; /** * 社交用户 - * 通过 {@link SysSocialUserDO#getUserId()} 关联到对应的 {@link SysUserDO} + * 通过 {@link SocialUserDO#getUserId()} 关联到对应的 {@link AdminUserDO} * * @author weir */ -@TableName(value = "sys_social_user", autoResultMap = true) +@TableName(value = "system_social_user", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class SysSocialUserDO extends BaseDO { +public class SocialUserDO extends BaseDO { /** * 自增主键 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java similarity index 81% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index c0b5298c88..99a658e094 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant; +package cn.iocoder.yudao.module.system.dal.dataobject.tenant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -10,14 +10,14 @@ import lombok.*; * * @author 芋道源码 */ -@TableName(value = "sys_tenant", autoResultMap = true) +@TableName(value = "system_tenant", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @AllArgsConstructor @NoArgsConstructor -public class SysTenantDO extends BaseDO { +public class TenantDO extends BaseDO { /** * 租户编号,自增 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/user/SysUserDO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java similarity index 86% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/user/SysUserDO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java index bb5e6854ce..870ad30fce 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/user/SysUserDO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user; +package cn.iocoder.yudao.module.system.dal.dataobject.user; -import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; @@ -18,13 +18,13 @@ import java.util.Set; * * @author 芋道源码 */ -@TableName(value = "sys_user", autoResultMap = true) +@TableName(value = "system_user", autoResultMap = true) @Data @EqualsAndHashCode(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class SysUserDO extends TenantBaseDO { +public class AdminUserDO extends TenantBaseDO { /** * 用户ID @@ -69,7 +69,7 @@ public class SysUserDO extends TenantBaseDO { /** * 用户性别 * - * 枚举类 {@link SysSexEnum} + * 枚举类 {@link SexEnum} */ private Integer sex; /** diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/auth/UserSessionMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/auth/UserSessionMapper.java new file mode 100644 index 0000000000..1b7f31be33 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/auth/UserSessionMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.dal.mysql.auth; + +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +@Mapper +public interface UserSessionMapper extends BaseMapperX { + + default PageResult selectPage(UserSessionPageReqVO reqVO, Collection userIds) { + return selectPage(reqVO, new QueryWrapperX() + .inIfPresent("user_id", userIds) + .likeIfPresent("user_ip", reqVO.getUserIp())); + } + + default List selectListBySessionTimoutLt() { + return selectList(new QueryWrapperX().lt("session_timeout",new Date())); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/DeptMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/DeptMapper.java new file mode 100644 index 0000000000..3f76709c82 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/DeptMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.system.dal.mysql.dept; + +import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface DeptMapper extends BaseMapperX { + + default List selectList(DeptListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX().likeIfPresent(DeptDO::getName, reqVO.getName()) + .eqIfPresent(DeptDO::getStatus, reqVO.getStatus())); + } + + default DeptDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(new LambdaQueryWrapper().eq(DeptDO::getParentId, parentId) + .eq(DeptDO::getName, name)); + } + + default Integer selectCountByParentId(Long parentId) { + return selectCount(DeptDO::getParentId, parentId); + } + + @InterceptorIgnore(tenantLine = "on") // 该方法忽略多租户。原因:该方法被异步 task 调用,此时获取不到租户编号 + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { + return selectOne(new LambdaQueryWrapper().select(DeptDO::getId) + .gt(DeptDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java new file mode 100644 index 0000000000..ecbd75949b --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.system.dal.mysql.dept; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface PostMapper extends BaseMapperX { + + default List selectList(Collection ids, Collection statuses) { + return selectList(new QueryWrapperX().inIfPresent("id", ids) + .inIfPresent("status", statuses)); + } + + default PageResult selectPage(PostPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .likeIfPresent("code", reqVO.getCode()) + .likeIfPresent("name", reqVO.getName()) + .eqIfPresent("status", reqVO.getStatus())); + } + + default List selectList(PostExportReqVO reqVO) { + return selectList(new QueryWrapperX() + .likeIfPresent("code", reqVO.getCode()) + .likeIfPresent("name", reqVO.getName()) + .eqIfPresent("status", reqVO.getStatus())); + } + + default PostDO selectByName(String name) { + return selectOne(new QueryWrapper().eq("name", name)); + } + + default PostDO selectByCode(String code) { + return selectOne(new QueryWrapper().eq("code", code)); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java new file mode 100644 index 0000000000..07462fc44a --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.system.dal.mysql.dict; + +import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +@Mapper +public interface DictDataMapper extends BaseMapperX { + + default DictDataDO selectByDictTypeAndValue(String dictType, String value) { + return selectOne(new LambdaQueryWrapper().eq(DictDataDO::getDictType, dictType) + .eq(DictDataDO::getValue, value)); + } + + default List selectByDictTypeAndValues(String dictType, Collection values) { + return selectList(new LambdaQueryWrapper().eq(DictDataDO::getDictType, dictType) + .in(DictDataDO::getValue, values)); + } + + default int selectCountByDictType(String dictType) { + return selectCount(DictDataDO::getDictType, dictType); + } + + default PageResult selectPage(DictDataPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) + .likeIfPresent(DictDataDO::getDictType, reqVO.getDictType()) + .eqIfPresent(DictDataDO::getStatus, reqVO.getStatus()) + .orderByAsc(Arrays.asList(DictDataDO::getDictType, DictDataDO::getSort))); + } + + default List selectList(DictDataExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX().likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) + .likeIfPresent(DictDataDO::getDictType, reqVO.getDictType()) + .eqIfPresent(DictDataDO::getStatus, reqVO.getStatus())); + } + + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { + return selectOne(new LambdaQueryWrapper().select(DictDataDO::getId) + .gt(DictDataDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java new file mode 100644 index 0000000000..11b9d5f3e9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.system.dal.mysql.dict; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface DictTypeMapper extends BaseMapperX { + + default PageResult selectPage(DictTypePageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .likeIfPresent("name", reqVO.getName()) + .likeIfPresent("`type`", reqVO.getType()) + .eqIfPresent("status", reqVO.getStatus()) + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())); + } + + default List selectList(DictTypeExportReqVO reqVO) { + return selectList(new QueryWrapperX() + .likeIfPresent("name", reqVO.getName()) + .likeIfPresent("`type`", reqVO.getType()) + .eqIfPresent("status", reqVO.getStatus()) + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())); + } + + default DictTypeDO selectByType(String type) { + return selectOne(new QueryWrapperX().eq("`type`", type)); + } + + default DictTypeDO selectByName(String name) { + return selectOne(new QueryWrapperX().eq("name", name)); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/errorcode/SysErrorCodeMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/errorcode/SysErrorCodeMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java index 7760f80586..ab514bd225 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/errorcode/SysErrorCodeMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.errorcode; +package cn.iocoder.yudao.module.system.dal.mysql.errorcode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; @@ -14,10 +14,10 @@ import java.util.Date; import java.util.List; @Mapper -public interface SysErrorCodeMapper extends BaseMapperX { +public interface ErrorCodeMapper extends BaseMapperX { - default PageResult selectPage(SysErrorCodePageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(ErrorCodePageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("type", reqVO.getType()) .likeIfPresent("application_name", reqVO.getApplicationName()) .eqIfPresent("code", reqVO.getCode()) @@ -26,8 +26,8 @@ public interface SysErrorCodeMapper extends BaseMapperX { .orderByAsc("application_name", "code")); } - default List selectList(SysErrorCodeExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(ErrorCodeExportReqVO reqVO) { + return selectList(new QueryWrapperX() .eqIfPresent("type", reqVO.getType()) .likeIfPresent("application_name", reqVO.getApplicationName()) .eqIfPresent("code", reqVO.getCode()) @@ -36,16 +36,16 @@ public interface SysErrorCodeMapper extends BaseMapperX { .orderByAsc("application_name", "code")); } - default List selectListByCodes(Collection codes) { - return selectList(new QueryWrapper().in("code", codes)); + default List selectListByCodes(Collection codes) { + return selectList(new QueryWrapper().in("code", codes)); } - default SysErrorCodeDO selectByCode(Integer code) { - return selectOne(new QueryWrapper().eq("code", code)); + default ErrorCodeDO selectByCode(Integer code) { + return selectOne(new QueryWrapper().eq("code", code)); } - default List selectListByApplicationNameAndUpdateTimeGt(String applicationName, Date minUpdateTime) { - return selectList(new QueryWrapperX().eq("application_name", applicationName) + default List selectListByApplicationNameAndUpdateTimeGt(String applicationName, Date minUpdateTime) { + return selectList(new QueryWrapperX().eq("application_name", applicationName) .gtIfPresent("update_time", minUpdateTime)); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysLoginLogMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysLoginLogMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java index eea1812e83..a2731a5f6f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysLoginLogMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java @@ -1,42 +1,42 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger; +package cn.iocoder.yudao.module.system.dal.mysql.logger; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper -public interface SysLoginLogMapper extends BaseMapperX { +public interface LoginLogMapper extends BaseMapperX { - default PageResult selectPage(SysLoginLogPageReqVO reqVO) { - QueryWrapperX query = new QueryWrapperX() + default PageResult selectPage(LoginLogPageReqVO reqVO) { + QueryWrapperX query = new QueryWrapperX() .likeIfPresent("user_ip", reqVO.getUserIp()) .likeIfPresent("username", reqVO.getUsername()) .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()); if (Boolean.TRUE.equals(reqVO.getStatus())) { - query.eq("result", SysLoginResultEnum.SUCCESS.getResult()); + query.eq("result", LoginResultEnum.SUCCESS.getResult()); } else if (Boolean.FALSE.equals(reqVO.getStatus())) { - query.gt("result", SysLoginResultEnum.SUCCESS.getResult()); + query.gt("result", LoginResultEnum.SUCCESS.getResult()); } query.orderByDesc("id"); // 降序 return selectPage(reqVO, query); } - default List selectList(SysLoginLogExportReqVO reqVO) { - QueryWrapperX query = new QueryWrapperX() + default List selectList(LoginLogExportReqVO reqVO) { + QueryWrapperX query = new QueryWrapperX() .likeIfPresent("user_ip", reqVO.getUserIp()) .likeIfPresent("username", reqVO.getUsername()) .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()); if (Boolean.TRUE.equals(reqVO.getStatus())) { - query.eq("result", SysLoginResultEnum.SUCCESS.getResult()); + query.eq("result", LoginResultEnum.SUCCESS.getResult()); } else if (Boolean.FALSE.equals(reqVO.getStatus())) { - query.gt("result", SysLoginResultEnum.SUCCESS.getResult()); + query.gt("result", LoginResultEnum.SUCCESS.getResult()); } query.orderByDesc("id"); // 降序 return selectList(query); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysOperateLogMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java similarity index 66% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysOperateLogMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java index c588867cd0..94367c55ff 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/logger/SysOperateLogMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java @@ -1,22 +1,22 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger; +package cn.iocoder.yudao.module.system.dal.mysql.logger; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; import java.util.List; @Mapper -public interface SysOperateLogMapper extends BaseMapperX { +public interface OperateLogMapper extends BaseMapperX { - default PageResult selectPage(SysOperateLogPageReqVO reqVO, Collection userIds) { - QueryWrapperX query = new QueryWrapperX() + default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { + QueryWrapperX query = new QueryWrapperX() .likeIfPresent("module", reqVO.getModule()) .inIfPresent("user_id", userIds) .eqIfPresent("operate_type", reqVO.getType()) @@ -30,8 +30,8 @@ public interface SysOperateLogMapper extends BaseMapperX { return selectPage(reqVO, query); } - default List selectList(SysOperateLogExportReqVO reqVO, Collection userIds) { - QueryWrapperX query = new QueryWrapperX() + default List selectList(OperateLogExportReqVO reqVO, Collection userIds) { + QueryWrapperX query = new QueryWrapperX() .likeIfPresent("module", reqVO.getModule()) .inIfPresent("user_id", userIds) .eqIfPresent("operate_type", reqVO.getType()) diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeMapper.java new file mode 100644 index 0000000000..9f077918b2 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notice/NoticeMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.system.dal.mysql.notice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface NoticeMapper extends BaseMapperX { + + default PageResult selectPage(NoticePageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() + .likeIfPresent("title", reqVO.getTitle()) + .eqIfPresent("status", reqVO.getStatus())); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/package-info.java new file mode 100644 index 0000000000..b47bbaac1f --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.system.dal.mysql; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java new file mode 100644 index 0000000000..1eaa072993 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.system.dal.mysql.permission; + +import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface MenuMapper extends BaseMapperX { + + default MenuDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(new LambdaQueryWrapper().eq(MenuDO::getParentId, parentId) + .eq(MenuDO::getName, name)); + } + + default Integer selectCountByParentId(Long parentId) { + return selectCount(MenuDO::getParentId, parentId); + } + + default List selectList(MenuListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX().likeIfPresent(MenuDO::getName, reqVO.getName()) + .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())); + } + + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { + return selectOne(new LambdaQueryWrapper().select(MenuDO::getId) + .gt(MenuDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java new file mode 100644 index 0000000000..0bf94990a4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.system.dal.mysql.permission; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.lang.Nullable; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +@Mapper +public interface RoleMapper extends BaseMapperX { + + default PageResult selectPage(RolePageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX().likeIfPresent("name", reqVO.getName()) + .likeIfPresent("code", reqVO.getCode()) + .eqIfPresent("status", reqVO.getStatus()) + .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())); + } + + default List listRoles(RoleExportReqVO reqVO) { + return selectList(new QueryWrapperX().likeIfPresent("name", reqVO.getName()) + .likeIfPresent("code", reqVO.getCode()) + .eqIfPresent("status", reqVO.getStatus()) + .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime())); + } + + default RoleDO selectByName(String name) { + return selectOne(new QueryWrapperX().eq("name", name)); + } + + default RoleDO selectByCode(String code) { + return selectOne(new QueryWrapperX().eq("code", code)); + } + + default List selectListByStatus(@Nullable Collection statuses) { + return selectList(new QueryWrapperX().in("status", statuses)); + } + + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { + return selectOne(new QueryWrapper().select("id") + .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null; + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMenuMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java similarity index 54% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMenuMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java index 698ca73194..02008bce82 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysRoleMenuMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission; +package cn.iocoder.yudao.module.system.dal.mysql.permission; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @@ -12,15 +12,15 @@ import java.util.List; import java.util.stream.Collectors; @Mapper -public interface SysRoleMenuMapper extends BaseMapperX { +public interface RoleMenuMapper extends BaseMapperX { - default List selectListByRoleId(Long roleId) { - return selectList(new QueryWrapper().eq("role_id", roleId)); + default List selectListByRoleId(Long roleId) { + return selectList(new QueryWrapper().eq("role_id", roleId)); } default void insertList(Long roleId, Collection menuIds) { - List list = menuIds.stream().map(menuId -> { - SysRoleMenuDO entity = new SysRoleMenuDO(); + List list = menuIds.stream().map(menuId -> { + RoleMenuDO entity = new RoleMenuDO(); entity.setRoleId(roleId); entity.setMenuId(menuId); return entity; @@ -30,19 +30,19 @@ public interface SysRoleMenuMapper extends BaseMapperX { } default void deleteListByRoleIdAndMenuIds(Long roleId, Collection menuIds) { - delete(new QueryWrapper().eq("role_id", roleId) + delete(new QueryWrapper().eq("role_id", roleId) .in("menu_id", menuIds)); } default void deleteListByMenuId(Long menuId) { - delete(new QueryWrapper().eq("menu_id", menuId)); + delete(new QueryWrapper().eq("menu_id", menuId)); } default void deleteListByRoleId(Long roleId) { - delete(new QueryWrapper().eq("role_id", roleId)); + delete(new QueryWrapper().eq("role_id", roleId)); } - @Select("SELECT id FROM sys_role_menu WHERE update_time > #{maxUpdateTime} LIMIT 1") + @Select("SELECT id FROM system_role_menu WHERE update_time > #{maxUpdateTime} LIMIT 1") Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleMapper.java new file mode 100644 index 0000000000..bc1d36cf2c --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleMapper.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.system.dal.mysql.permission; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@Mapper +public interface UserRoleMapper extends BaseMapperX { + + default List selectListByUserId(Long userId) { + return selectList(new QueryWrapper().eq("user_id", userId)); + } + + default List selectListByRoleId(Long roleId) { + return selectList(new QueryWrapper().eq("role_id", roleId)); + } + + + default void insertList(Long userId, Collection roleIds) { + List list = roleIds.stream().map(roleId -> { + UserRoleDO entity = new UserRoleDO(); + entity.setUserId(userId); + entity.setRoleId(roleId); + return entity; + }).collect(Collectors.toList()); + insertBatch(list); + } + + default void deleteListByUserIdAndRoleIdIds(Long userId, Collection roleIds) { + delete(new QueryWrapper().eq("user_id", userId) + .in("role_id", roleIds)); + } + + default void deleteListByUserId(Long userId) { + delete(new QueryWrapper().eq("user_id", userId)); + } + + default void deleteListByRoleId(Long roleId) { + delete(new QueryWrapper().eq("role_id", roleId)); + } + + + default List selectListByRoleIds(Collection roleIds) { + return selectList(UserRoleDO::getRoleId, roleIds); + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsChannelMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsChannelMapper.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsChannelMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsChannelMapper.java index bd69d4f736..7b0c9f6f9b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsChannelMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsChannelMapper.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms; +package cn.iocoder.yudao.module.system.dal.mysql.sms; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; @@ -11,17 +11,17 @@ import org.apache.ibatis.annotations.Select; import java.util.Date; @Mapper -public interface SysSmsChannelMapper extends BaseMapperX { +public interface SmsChannelMapper extends BaseMapperX { - default PageResult selectPage(SysSmsChannelPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(SmsChannelPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .likeIfPresent("signature", reqVO.getSignature()) .eqIfPresent("status", reqVO.getStatus()) .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) .orderByDesc("id")); } - @Select("SELECT id FROM sys_sms_channel WHERE update_time > #{maxUpdateTime} LIMIT 1") + @Select("SELECT id FROM system_sms_channel WHERE update_time > #{maxUpdateTime} LIMIT 1") Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsCodeMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsCodeMapper.java new file mode 100644 index 0000000000..06d7431ce5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsCodeMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.dal.mysql.sms; + +import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SmsCodeMapper extends BaseMapperX { + + /** + * 获得手机号的最后一个手机验证码 + * + * @param mobile 手机号 + * @param scene 发送场景,选填 + * @param code 验证码 选填 + * @return 手机验证码 + */ + default SmsCodeDO selectLastByMobile(String mobile, String code, Integer scene) { + return selectOne(new QueryWrapperX() + .eq("mobile", mobile).eqIfPresent("scene", scene).eqIfPresent("code", code) + .orderByDesc("id").last(SqlConstants.LIMIT1)); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsLogMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java similarity index 67% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsLogMapper.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java index 0269e75e6f..01ea77a46b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/sms/SysSmsLogMapper.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms; +package cn.iocoder.yudao.module.system.dal.mysql.sms; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsLogDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; @@ -11,10 +11,10 @@ import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper -public interface SysSmsLogMapper extends BaseMapperX { +public interface SmsLogMapper extends BaseMapperX { - default PageResult selectPage(SysSmsLogPageReqVO reqVO) { - return selectPage(reqVO, new QueryWrapperX() + default PageResult selectPage(SmsLogPageReqVO reqVO) { + return selectPage(reqVO, new QueryWrapperX() .eqIfPresent("channel_id", reqVO.getChannelId()) .eqIfPresent("template_id", reqVO.getTemplateId()) .likeIfPresent("mobile", reqVO.getMobile()) @@ -25,8 +25,8 @@ public interface SysSmsLogMapper extends BaseMapperX { .orderByDesc("id")); } - default List selectList(SysSmsLogExportReqVO reqVO) { - return selectList(new QueryWrapperX() + default List selectList(SmsLogExportReqVO reqVO) { + return selectList(new QueryWrapperX() .eqIfPresent("channel_id", reqVO.getChannelId()) .eqIfPresent("template_id", reqVO.getTemplateId()) .likeIfPresent("mobile", reqVO.getMobile()) diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java new file mode 100644 index 0000000000..daf9882f0e --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.system.dal.mysql.sms; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface SmsTemplateMapper extends BaseMapperX { + + @Select("SELECT id FROM system_sms_template WHERE update_time > #{maxUpdateTime} LIMIT 1") + Long selectExistsByUpdateTimeAfter(Date maxUpdateTime); + + default SmsTemplateDO selectByCode(String code) { + return selectOne(SmsTemplateDO::getCode, code); + } + + default PageResult selectPage(SmsTemplatePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(SmsTemplateDO::getType, reqVO.getType()) + .eqIfPresent(SmsTemplateDO::getStatus, reqVO.getStatus()) + .likeIfPresent(SmsTemplateDO::getCode, reqVO.getCode()) + .likeIfPresent(SmsTemplateDO::getContent, reqVO.getContent()) + .likeIfPresent(SmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId()) + .eqIfPresent(SmsTemplateDO::getChannelId, reqVO.getChannelId()) + .betweenIfPresent(SmsTemplateDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(SmsTemplateDO::getId)); + } + + default List selectList(SmsTemplateExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(SmsTemplateDO::getType, reqVO.getType()) + .eqIfPresent(SmsTemplateDO::getStatus, reqVO.getStatus()) + .likeIfPresent(SmsTemplateDO::getCode, reqVO.getCode()) + .likeIfPresent(SmsTemplateDO::getContent, reqVO.getContent()) + .likeIfPresent(SmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId()) + .eqIfPresent(SmsTemplateDO::getChannelId, reqVO.getChannelId()) + .betweenIfPresent(SmsTemplateDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(SmsTemplateDO::getId)); + } + + default Integer selectCountByChannelId(Long channelId) { + return selectCount(SmsTemplateDO::getChannelId, channelId); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java new file mode 100644 index 0000000000..3322ab8403 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.dal.mysql.social; + +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface SocialUserMapper extends BaseMapperX { + + default List selectListByTypeAndUnionId(Integer userType, Collection types, String unionId) { + return selectList(new QueryWrapper().eq("user_type", userType) + .in("type", types).eq("union_id", unionId)); + } + + default List selectListByTypeAndUserId(Integer userType, Collection types, Long userId) { + return selectList(new QueryWrapper().eq("user_type", userType) + .in("type", types).eq("user_id", userId)); + } + + default List selectListByUserId(Integer userType, Long userId) { + return selectList(new QueryWrapper().eq("user_type", userType).eq("user_id", userId)); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java new file mode 100755 index 0000000000..9fe0dbec8b --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.system.dal.mysql.tenant; + +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 租户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface TenantMapper extends BaseMapperX { + + default PageResult selectPage(TenantPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TenantDO::getName, reqVO.getName()) + .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) + .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) + .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(TenantDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(TenantDO::getId)); + } + + default List selectList(TenantExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(TenantDO::getName, reqVO.getName()) + .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) + .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) + .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(TenantDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(TenantDO::getId)); + } + + default TenantDO selectByName(String name) { + return selectOne(TenantDO::getName, name); + } +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java new file mode 100644 index 0000000000..be4b5ea218 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.system.dal.mysql.user; + +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface AdminUserMapper extends BaseMapperX { + + default AdminUserDO selectByUsername(String username) { + return selectOne(new LambdaQueryWrapper().eq(AdminUserDO::getUsername, username)); + } + + default AdminUserDO selectByEmail(String email) { + return selectOne(new LambdaQueryWrapper().eq(AdminUserDO::getEmail, email)); + } + + default AdminUserDO selectByMobile(String mobile) { + return selectOne(new LambdaQueryWrapper().eq(AdminUserDO::getMobile, mobile)); + } + + default PageResult selectPage(UserPageReqVO reqVO, Collection deptIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername()) + .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile()) + .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()) + .inIfPresent(AdminUserDO::getDeptId, deptIds)); + } + + default List selectList(UserExportReqVO reqVO, Collection deptIds) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername()) + .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile()) + .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()) + .inIfPresent(AdminUserDO::getDeptId, deptIds)); + } + + default List selectListByNickname(String nickname) { + return selectList(new LambdaQueryWrapperX().like(AdminUserDO::getNickname, nickname)); + } + + default List selectListByUsername(String username) { + return selectList(new LambdaQueryWrapperX().like(AdminUserDO::getUsername, username)); + } + + default List selectListByStatus(Integer status) { + return selectList(AdminUserDO::getStatus, status); + } + + default List selectListByDeptIds(Collection deptIds) { + return selectList(AdminUserDO::getDeptId, deptIds); + } + +} + diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/SysRedisKeyCoreConstants.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java similarity index 71% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/SysRedisKeyCoreConstants.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java index 5db3e9fd48..a98edc17f9 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/SysRedisKeyCoreConstants.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.redis; +package cn.iocoder.yudao.module.system.dal.redis; import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; import cn.iocoder.yudao.framework.security.core.LoginUser; @@ -13,7 +13,11 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S * * @author 芋道源码 */ -public interface SysRedisKeyCoreConstants { +public interface RedisKeyConstants { + + RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("验证码的缓存", + "captcha_code:%s", // 参数为 uuid + STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登录用户的缓存", "login_user:%s", // 参数为 sessionId @@ -23,7 +27,8 @@ public interface SysRedisKeyCoreConstants { "social_auth_user:%d:%s", // 参数为 type,code STRING, AuthUser.class, Duration.ofDays(1)); - RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", + RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", // 注意,它是被 JustAuth 的 justauth.type.prefix 使用到 "social_auth_state:%s", // 参数为 state STRING, String.class, Duration.ofHours(24)); // 值为 state + } diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/auth/SysLoginUserCoreRedisDAO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/auth/LoginUserRedisDAO.java similarity index 85% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/auth/SysLoginUserCoreRedisDAO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/auth/LoginUserRedisDAO.java index 921492c9d6..8132a882ef 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/auth/SysLoginUserCoreRedisDAO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/auth/LoginUserRedisDAO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth; +package cn.iocoder.yudao.module.system.dal.redis.auth; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.security.config.SecurityProperties; @@ -8,7 +8,7 @@ import org.springframework.stereotype.Repository; import javax.annotation.Resource; -import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.LOGIN_USER; +import static cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants.LOGIN_USER; /** * {@link LoginUser} 的 RedisDAO @@ -16,7 +16,7 @@ import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyC * @author 芋道源码 */ @Repository -public class SysLoginUserCoreRedisDAO { +public class LoginUserRedisDAO { @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/common/SysCaptchaRedisDAO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/common/SysCaptchaRedisDAO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java index 701501c908..bfcb7878b1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/common/SysCaptchaRedisDAO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.dal.redis.common; +package cn.iocoder.yudao.module.system.dal.redis.common; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; @@ -6,7 +6,7 @@ import org.springframework.stereotype.Repository; import javax.annotation.Resource; import java.time.Duration; -import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyConstants.CAPTCHA_CODE; +import static cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants.CAPTCHA_CODE; /** * 验证码的 Redis DAO @@ -14,7 +14,7 @@ import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyC * @author 芋道源码 */ @Repository -public class SysCaptchaRedisDAO { +public class CaptchaRedisDAO { @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/social/SocialAuthUserRedisDAO.java similarity index 83% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/social/SocialAuthUserRedisDAO.java index 0c033f89e2..ac71f1b5d7 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/redis/social/SocialAuthUserRedisDAO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.dal.redis.social; +package cn.iocoder.yudao.module.system.dal.redis.social; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import me.zhyd.oauth.model.AuthCallback; @@ -8,7 +8,8 @@ import org.springframework.stereotype.Repository; import javax.annotation.Resource; -import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.SOCIAL_AUTH_USER; +import static cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants.SOCIAL_AUTH_USER; + /** * 社交 {@link me.zhyd.oauth.model.AuthUser} 的 RedisDAO @@ -16,7 +17,7 @@ import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyC * @author 芋道源码 */ @Repository -public class SysSocialAuthUserRedisDAO { +public class SocialAuthUserRedisDAO { @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/common/SysSexEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java similarity index 76% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/common/SysSexEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java index a7b0a9c29e..f6120c4187 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/common/SysSexEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/common/SexEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.common; +package cn.iocoder.yudao.module.system.enums.common; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysSexEnum { +public enum SexEnum { /** 男 */ MALE(1), diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/dept/DeptIdEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/dept/DeptIdEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java index d228a9bbd5..2a7effec27 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/dept/DeptIdEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/dept/DeptIdEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.dept; +package cn.iocoder.yudao.module.system.enums.dept; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/errorcode/SysErrorCodeTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/errorcode/SysErrorCodeTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java index 8c0b4c7e02..97349e763c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/errorcode/SysErrorCodeTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/errorcode/ErrorCodeTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.errorcode; +package cn.iocoder.yudao.module.system.enums.errorcode; import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; @@ -13,7 +13,7 @@ import java.util.Arrays; */ @AllArgsConstructor @Getter -public enum SysErrorCodeTypeEnum implements IntArrayValuable { +public enum ErrorCodeTypeEnum implements IntArrayValuable { /** * 自动生成 @@ -24,7 +24,7 @@ public enum SysErrorCodeTypeEnum implements IntArrayValuable { */ MANUAL_OPERATION(2); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysErrorCodeTypeEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErrorCodeTypeEnum::getType).toArray(); /** * 类型 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java similarity index 84% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java index 40f18e8674..2f845fd105 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/logger/SysLoginLogTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginLogTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.logger; +package cn.iocoder.yudao.module.system.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysLoginLogTypeEnum { +public enum LoginLogTypeEnum { LOGIN_USERNAME(100), // 使用账号登录 LOGIN_SOCIAL(101), // 使用社交登录 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginResultEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java similarity index 82% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginResultEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java index 290931038c..7084e13da1 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/logger/SysLoginResultEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/logger/LoginResultEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.logger; +package cn.iocoder.yudao.module.system.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysLoginResultEnum { +public enum LoginResultEnum { SUCCESS(0), // 成功 BAD_CREDENTIALS(10), // 账号或密码不正确 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/notice/SysNoticeTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/notice/SysNoticeTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java index 0c8bff35a9..9a2a3c4626 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/notice/SysNoticeTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/notice/NoticeTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.notice; +package cn.iocoder.yudao.module.system.enums.notice; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysNoticeTypeEnum { +public enum NoticeTypeEnum { NOTICE(1), ANNOUNCEMENT(2); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuIdEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuIdEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java index a82ab25139..fc2b72ac42 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuIdEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuIdEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.permission; +package cn.iocoder.yudao.module.system.enums.permission; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java index 213f7992fd..575a33c447 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/MenuTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/MenuTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.permission; +package cn.iocoder.yudao.module.system.enums.permission; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/RoleCodeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/RoleCodeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java index ddfdd05340..44487a4d63 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/RoleCodeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.permission; +package cn.iocoder.yudao.module.system.enums.permission; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/SysRoleTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/SysRoleTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java index 61b15b0be2..1607b20b34 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/permission/SysRoleTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleTypeEnum.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.enums.permission; +package cn.iocoder.yudao.module.system.enums.permission; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor -public enum SysRoleTypeEnum { +public enum RoleTypeEnum { /** * 内置角色 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsReceiveStatusEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java similarity index 75% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsReceiveStatusEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java index 48fd0c84c4..581ee6f9a4 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsReceiveStatusEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsReceiveStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.sms; +package cn.iocoder.yudao.module.system.enums.sms; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,7 +11,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysSmsReceiveStatusEnum { +public enum SmsReceiveStatusEnum { INIT(0), // 初始化 SUCCESS(10), // 接收成功 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsSendStatusEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java similarity index 77% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsSendStatusEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java index f30e613018..307c9f6b75 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsSendStatusEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSendStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.sms; +package cn.iocoder.yudao.module.system.enums.sms; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,7 +11,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysSmsSendStatusEnum { +public enum SmsSendStatusEnum { INIT(0), // 初始化 SUCCESS(10), // 发送成功 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsTemplateTypeEnum.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java similarity index 75% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsTemplateTypeEnum.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java index b3811e5ecd..d24b07a9ed 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/sms/SysSmsTemplateTypeEnum.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsTemplateTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.enums.sms; +package cn.iocoder.yudao.module.system.enums.sms; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum SysSmsTemplateTypeEnum { +public enum SmsTemplateTypeEnum { VERIFICATION_CODE(1), // 验证码 NOTICE(2), // 通知 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaConfig.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaConfig.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaConfig.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaConfig.java index 174efe4acb..4028f6cefb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaConfig.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaConfig.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.framework.captcha.config; +package cn.iocoder.yudao.module.system.framework.captcha.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaProperties.java similarity index 92% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaProperties.java index 73939df754..0d7cd0d208 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/config/CaptchaProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.framework.captcha.config; +package cn.iocoder.yudao.module.system.framework.captcha.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/package-info.java new file mode 100644 index 0000000000..ee406c0794 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/captcha/package-info.java @@ -0,0 +1,4 @@ +/** + * 基于 Hutool captcha 库,实现验证码功能 + */ +package cn.iocoder.yudao.module.system.framework.captcha; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java index 20f2e16028..0be6684c89 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/config/DataPermissionConfiguration.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission.config; +package cn.iocoder.yudao.module.system.framework.datapermission.config; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,14 +11,14 @@ import org.springframework.context.annotation.Configuration; * * @author 芋道源码 */ -@Configuration -public class SysDataPermissionConfiguration { +@Configuration(proxyBeanMethods = false) +public class DataPermissionConfiguration { @Bean public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() { return rule -> { - rule.addDeptColumn(SysUserDO.class); - rule.addDeptColumn(SysDeptDO.class, "id"); + rule.addDeptColumn(AdminUserDO.class); + rule.addDeptColumn(DeptDO.class, "id"); }; } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/package-info.java new file mode 100644 index 0000000000..a666845510 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/datapermission/package-info.java @@ -0,0 +1,4 @@ +/** + * system 模块的数据权限配置 + */ +package cn.iocoder.yudao.module.system.framework.datapermission; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeConfiguration.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeConfiguration.java index 9a2789ec3d..4c72ccec73 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeConfiguration.java @@ -1,16 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.config; +package cn.iocoder.yudao.module.system.framework.errorcode.config; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.generator.ErrorCodeAutoGenerator; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.loader.ErrorCodeLoader; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.loader.ErrorCodeLoaderImpl; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl; +import cn.iocoder.yudao.module.system.framework.errorcode.core.generator.ErrorCodeAutoGenerator; +import cn.iocoder.yudao.module.system.framework.errorcode.core.loader.ErrorCodeLoader; +import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.yudao.module.system.framework.errorcode.core.loader.ErrorCodeLoaderImpl; +import cn.iocoder.yudao.module.system.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; +// TODO 芋艿:貌似放的位置有问题 /** * 错误码配置类 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeProperties.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeProperties.java similarity index 87% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeProperties.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeProperties.java index f652a6a899..686f03e2c8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/config/ErrorCodeProperties.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/config/ErrorCodeProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.config; +package cn.iocoder.yudao.module.system.framework.errorcode.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java index 098f0438cf..6f54258697 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto; +package cn.iocoder.yudao.module.system.framework.errorcode.core.dto; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeRespDTO.java similarity index 81% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeRespDTO.java index 7e2bb2a397..c0b0cbaa3d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/dto/ErrorCodeRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto; +package cn.iocoder.yudao.module.system.framework.errorcode.core.dto; import lombok.Data; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java index 60689af962..6fb2abc020 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.generator; +package cn.iocoder.yudao.module.system.framework.errorcode.core.generator; /** * 错误码的自动生成器 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java index bedbcdc199..0551e4732b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.generator; +package cn.iocoder.yudao.module.system.framework.errorcode.core.generator; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationReadyEvent; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoader.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoader.java index d35767fd31..6712c33e9b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoader.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.loader; +package cn.iocoder.yudao.module.system.framework.errorcode.core.loader; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java similarity index 88% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java index 234d30dcc6..1641f520fa 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.loader; +package cn.iocoder.yudao.module.system.framework.errorcode.core.loader; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/service/ErrorCodeFrameworkService.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/service/ErrorCodeFrameworkService.java index e3f5e91cc3..2d93f75f1f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/core/service/ErrorCodeFrameworkService.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.service; +package cn.iocoder.yudao.module.system.framework.errorcode.core.service; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO; import javax.validation.Valid; import java.util.Date; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/package-info.java similarity index 59% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/package-info.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/package-info.java index 343ccaeb3e..012bcb33ce 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/errorcode/package-info.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/errorcode/package-info.java @@ -3,4 +3,4 @@ * * 将错误码缓存在内存中,同时通过定时器每 n 分钟更新 */ -package cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode; +package cn.iocoder.yudao.module.system.framework.errorcode; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/package-info.java similarity index 56% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/package-info.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/package-info.java index cb0def51fa..4b8440611a 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/package-info.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.userserver.modules.system.framework; +package cn.iocoder.yudao.module.system.framework; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java new file mode 100644 index 0000000000..53b99ce8cf --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.system.framework.security.config; + +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; + +/** + * System 模块的 Security 配置 + */ +@Configuration("systemSecurityConfiguration") +public class SecurityConfiguration { + + @Bean("systemAuthorizeRequestsCustomizer") + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { + return new AuthorizeRequestsCustomizer() { + + @Override + public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + // 登录的接口,可匿名访问 + registry.antMatchers(buildAdminApi("/system/login")).anonymous(); + // 验证码的接口 + registry.antMatchers(buildAdminApi("/system/captcha/**")).anonymous(); + // 获得租户编号的接口 + registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous(); + // 短信回调 API + registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous(); + } + + }; + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/core/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/core/package-info.java new file mode 100644 index 0000000000..04a8d8b378 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.system.framework.security.core; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeConfiguration.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java similarity index 79% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeConfiguration.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java index a4510ea476..eb8620c61f 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeConfiguration.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.system.framework.sms; +package cn.iocoder.yudao.module.system.framework.sms; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeProperties.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java similarity index 87% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeProperties.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java index b600c28dc9..5d246bad7f 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeProperties.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java @@ -1,13 +1,11 @@ -package cn.iocoder.yudao.userserver.modules.system.framework.sms; +package cn.iocoder.yudao.module.system.framework.sms; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.Duration; -import java.util.Collection; @ConfigurationProperties(prefix = "yudao.sms-code") @Validated diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/auth/UserSessionTimeoutJob.java similarity index 71% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/auth/UserSessionTimeoutJob.java index 57588fa801..d1a061d3e4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/auth/UserSessionTimeoutJob.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.system.job.auth; +package cn.iocoder.yudao.module.system.job.auth; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; +import cn.iocoder.yudao.module.system.service.auth.UserSessionService; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -16,10 +16,10 @@ import javax.annotation.Resource; @Component @TenantJob @Slf4j -public class SysUserSessionTimeoutJob implements JobHandler { +public class UserSessionTimeoutJob implements JobHandler { @Resource - private SysUserSessionService sysUserSessionService; + private UserSessionService sysUserSessionService; @Override public String execute(String param) throws Exception { diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/package-info.java new file mode 100644 index 0000000000..a7f5954178 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.system.job; diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dept/DeptRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dept/DeptRefreshConsumer.java new file mode 100644 index 0000000000..981244d909 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dept/DeptRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.dept; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.dept.DeptRefreshMessage; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link DeptRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class DeptRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private DeptService deptService; + + @Override + public void onMessage(DeptRefreshMessage message) { + log.info("[onMessage][收到 Dept 刷新消息]"); + deptService.initLocalCache(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dict/DictDataRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dict/DictDataRefreshConsumer.java new file mode 100644 index 0000000000..e466f96b22 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/dict/DictDataRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.dict; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.dict.DictDataRefreshMessage; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link DictDataRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class DictDataRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private DictDataService dictDataService; + + @Override + public void onMessage(DictDataRefreshMessage message) { + log.info("[onMessage][收到 DictData 刷新消息]"); + dictDataService.initLocalCache(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java new file mode 100644 index 0000000000..4b02f760ea --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.system.mq.consumer.mail; + +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +// TODO 芋艿:这个暂未实现 +@Component +@Slf4j +public class MailSendConsumer extends AbstractStreamMessageListener { + + @Override + public void onMessage(MailSendMessage message) { + log.info("[onMessage][消息内容({})]", message); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/MenuRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/MenuRefreshConsumer.java new file mode 100644 index 0000000000..a4b6335124 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/MenuRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.permission; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.permission.MenuRefreshMessage; +import cn.iocoder.yudao.module.system.service.permission.MenuService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link MenuRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class MenuRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private MenuService menuService; + + @Override + public void onMessage(MenuRefreshMessage message) { + log.info("[onMessage][收到 Menu 刷新消息]"); + menuService.initLocalCache(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java new file mode 100644 index 0000000000..d9f0e92208 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.permission; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link RoleMenuRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class RoleMenuRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private PermissionService permissionService; + + @Override + public void onMessage(RoleMenuRefreshMessage message) { + log.info("[onMessage][收到 Role 与 Menu 的关联刷新消息]"); + permissionService.initLocalCache(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleRefreshConsumer.java new file mode 100644 index 0000000000..bb53b7499a --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.permission; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.permission.RoleRefreshMessage; +import cn.iocoder.yudao.module.system.service.permission.RoleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link RoleRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class RoleRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private RoleService roleService; + + @Override + public void onMessage(RoleRefreshMessage message) { + log.info("[onMessage][收到 Role 刷新消息]"); + roleService.initLocalCache(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java new file mode 100644 index 0000000000..cc5d83d1eb --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.sms; + +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsChannelRefreshMessage; +import cn.iocoder.yudao.module.system.service.sms.SmsChannelService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link SmsChannelRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class SmsChannelRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private SmsChannelService smsChannelService; + + @Override + public void onMessage(SmsChannelRefreshMessage message) { + log.info("[onMessage][收到 SmsChannel 刷新消息]"); + smsChannelService.initSmsClients(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsSendConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsSendConsumer.java new file mode 100644 index 0000000000..495c06a9be --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsSendConsumer.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.system.mq.consumer.sms; + +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link SmsSendMessage} 的消费者 + * + * @author zzf + * @date 2021/3/9 16:35 + */ +@Component +@Slf4j +public class SmsSendConsumer extends AbstractStreamMessageListener { + + @Resource + private SmsSendService smsSendService; + + @Override + public void onMessage(SmsSendMessage message) { + log.info("[onMessage][消息内容({})]", message); + smsSendService.doSendSms(message); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsTemplateRefreshConsumer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsTemplateRefreshConsumer.java new file mode 100644 index 0000000000..02bc599842 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsTemplateRefreshConsumer.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.system.mq.consumer.sms; + +import cn.iocoder.yudao.module.system.mq.message.sms.SmsTemplateRefreshMessage; +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link SmsTemplateRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class SmsTemplateRefreshConsumer extends AbstractChannelMessageListener { + + @Resource + private SmsTemplateService smsTemplateService; + + @Override + public void onMessage(SmsTemplateRefreshMessage message) { + log.info("[onMessage][收到 SmsTemplate 刷新消息]"); + smsTemplateService.initLocalCache(); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dept/DeptRefreshMessage.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dept/DeptRefreshMessage.java index 96362a8fe3..80d3c8c39f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dept/DeptRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.dept; +package cn.iocoder.yudao.module.system.mq.message.dept; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysDeptRefreshMessage extends AbstractChannelMessage { +public class DeptRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dict/DictDataRefreshMessage.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dict/DictDataRefreshMessage.java index 4415d60bca..01e5b86056 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/dict/DictDataRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.dict; +package cn.iocoder.yudao.module.system.mq.message.dict; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -9,7 +9,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysDictDataRefreshMessage extends AbstractChannelMessage { +public class DictDataRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java index a0e258796f..aee02c76e9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.mail; +package cn.iocoder.yudao.module.system.mq.message.mail; import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysMailSendMessage extends AbstractStreamMessage { +public class MailSendMessage extends AbstractStreamMessage { /** * 邮箱地址 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/MenuRefreshMessage.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/MenuRefreshMessage.java index 3f0ef3da97..abd75dbaaf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/MenuRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission; +package cn.iocoder.yudao.module.system.mq.message.permission; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysMenuRefreshMessage extends AbstractChannelMessage { +public class MenuRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java index 8ddcb17d40..0982775bc6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission; +package cn.iocoder.yudao.module.system.mq.message.permission; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysRoleMenuRefreshMessage extends AbstractChannelMessage { +public class RoleMenuRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleRefreshMessage.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleRefreshMessage.java index 9e89fa1863..e80d8f30c3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission; +package cn.iocoder.yudao.module.system.mq.message.permission; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysRoleRefreshMessage extends AbstractChannelMessage { +public class RoleRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsChannelRefreshMessage.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsChannelRefreshMessage.java index 22c9341d52..0841cdee0d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsChannelRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms; +package cn.iocoder.yudao.module.system.mq.message.sms; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysSmsChannelRefreshMessage extends AbstractChannelMessage { +public class SmsChannelRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsSendMessage.java similarity index 88% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsSendMessage.java index 19c7d044cd..42a32623a9 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsSendMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice.modules.system.mq.message.sms; +package cn.iocoder.yudao.module.system.mq.message.sms; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; @@ -15,7 +15,7 @@ import java.util.List; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysSmsSendMessage extends AbstractStreamMessage { +public class SmsSendMessage extends AbstractStreamMessage { /** * 短信日志编号 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsTemplateRefreshMessage.java similarity index 70% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsTemplateRefreshMessage.java index 8401829cb8..4873c06c4a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/sms/SmsTemplateRefreshMessage.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms; +package cn.iocoder.yudao.module.system.mq.message.sms; import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class SysSmsTemplateRefreshMessage extends AbstractChannelMessage { +public class SmsTemplateRefreshMessage extends AbstractChannelMessage { @Override public String getChannel() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dept/DeptProducer.java similarity index 54% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dept/DeptProducer.java index c4bbb74192..9a2ca1b9c5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dept/DeptProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept; +package cn.iocoder.yudao.module.system.mq.producer.dept; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.dept.DeptRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * Dept 部门相关消息的 Producer */ @Component -public class SysDeptProducer { +public class DeptProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link SysDeptRefreshMessage} 消息 + * 发送 {@link DeptRefreshMessage} 消息 */ public void sendDeptRefreshMessage() { - SysDeptRefreshMessage message = new SysDeptRefreshMessage(); + DeptRefreshMessage message = new DeptRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dict/DictDataProducer.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dict/DictDataProducer.java index 4bce9db1c2..fa90c8c424 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/dict/DictDataProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict; +package cn.iocoder.yudao.module.system.mq.producer.dict; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.dict.DictDataRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * DictData 字典数据相关消息的 Producer */ @Component -public class SysDictDataProducer { +public class DictDataProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link SysDictDataRefreshMessage} 消息 + * 发送 {@link DictDataRefreshMessage} 消息 */ public void sendDictDataRefreshMessage() { - SysDictDataRefreshMessage message = new SysDictDataRefreshMessage(); + DictDataRefreshMessage message = new DictDataRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/package-info.java new file mode 100644 index 0000000000..255ab310c9 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.system.mq.producer; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/MenuProducer.java similarity index 53% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/MenuProducer.java index 1f42965300..5764c872af 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/MenuProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission; +package cn.iocoder.yudao.module.system.mq.producer.permission; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.permission.MenuRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * Menu 菜单相关消息的 Producer */ @Component -public class SysMenuProducer { +public class MenuProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link SysMenuRefreshMessage} 消息 + * 发送 {@link MenuRefreshMessage} 消息 */ public void sendMenuRefreshMessage() { - SysMenuRefreshMessage message = new SysMenuRefreshMessage(); + MenuRefreshMessage message = new MenuRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java index def201962c..56c8e31790 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission; +package cn.iocoder.yudao.module.system.mq.producer.permission; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -10,16 +10,16 @@ import javax.annotation.Resource; * Permission 权限相关消息的 Producer */ @Component -public class SysPermissionProducer { +public class PermissionProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link SysRoleMenuRefreshMessage} 消息 + * 发送 {@link RoleMenuRefreshMessage} 消息 */ public void sendRoleMenuRefreshMessage() { - SysRoleMenuRefreshMessage message = new SysRoleMenuRefreshMessage(); + RoleMenuRefreshMessage message = new RoleMenuRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/RoleProducer.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/RoleProducer.java index c3ab839a17..c249d964e8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/RoleProducer.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission; +package cn.iocoder.yudao.module.system.mq.producer.permission; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.permission.RoleRefreshMessage; import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; import org.springframework.stereotype.Component; @@ -12,16 +12,16 @@ import javax.annotation.Resource; * @author 芋道源码 */ @Component -public class SysRoleProducer { +public class RoleProducer { @Resource private RedisMQTemplate redisMQTemplate; /** - * 发送 {@link SysRoleRefreshMessage} 消息 + * 发送 {@link RoleRefreshMessage} 消息 */ public void sendRoleRefreshMessage() { - SysRoleRefreshMessage message = new SysRoleRefreshMessage(); + RoleRefreshMessage message = new RoleRefreshMessage(); redisMQTemplate.send(message); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/sms/SmsProducer.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/sms/SmsProducer.java new file mode 100644 index 0000000000..e14fb953bf --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/sms/SmsProducer.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.system.mq.producer.sms; + +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsChannelRefreshMessage; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsTemplateRefreshMessage; +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +/** + * Sms 短信相关消息的 Producer + * + * @author zzf + * @date 2021/3/9 16:35 + */ +@Slf4j +@Component +public class SmsProducer { + + @Resource + private RedisMQTemplate redisMQTemplate; + + /** + * 发送 {@link SmsChannelRefreshMessage} 消息 + */ + public void sendSmsChannelRefreshMessage() { + SmsChannelRefreshMessage message = new SmsChannelRefreshMessage(); + redisMQTemplate.send(message); + } + + /** + * 发送 {@link SmsTemplateRefreshMessage} 消息 + */ + public void sendSmsTemplateRefreshMessage() { + SmsTemplateRefreshMessage message = new SmsTemplateRefreshMessage(); + redisMQTemplate.send(message); + } + + /** + * 发送 {@link SmsSendMessage} 消息 + * + * @param logId 短信日志编号 + * @param mobile 手机号 + * @param channelId 渠道编号 + * @param apiTemplateId 短信模板编号 + * @param templateParams 短信模板参数 + */ + public void sendSmsSendMessage(Long logId, String mobile, + Long channelId, String apiTemplateId, List> templateParams) { + SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile); + message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams); + redisMQTemplate.send(message); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/package-info.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/package-info.java new file mode 100644 index 0000000000..df82ac7134 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/package-info.java @@ -0,0 +1,8 @@ +/** + * system 模块下,我们放通用业务,支撑上层的核心业务。 + * 例如说:用户、部门、权限、数据字典等等 + * + * 1. Controller URL:以 /system/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 system_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.system; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java index 2d5fe8c47c..36ef97972d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth; +package cn.iocoder.yudao.module.system.service.auth; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.*; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import javax.validation.Valid; @@ -12,7 +12,7 @@ import javax.validation.Valid; * * @author 芋道源码 */ -public interface SysAuthService extends SecurityAuthFrameworkService { +public interface AdminAuthService extends SecurityAuthFrameworkService { /** * 账号登录 @@ -22,7 +22,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent); + String login(@Valid AuthLoginReqVO reqVO, String userIp, String userAgent); /** * 社交登录,使用 code 授权码 @@ -32,7 +32,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String socialLogin(@Valid SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent); + String socialLogin(@Valid AuthSocialLoginReqVO reqVO, String userIp, String userAgent); /** * 社交登录,使用 code 授权码 + 账号密码 @@ -42,7 +42,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userAgent 用户 UA * @return 身份令牌,使用 JWT 方式 */ - String socialLogin2(@Valid SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); + String socialLogin2(@Valid AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); /** * 社交绑定,使用 code 授权码 @@ -50,6 +50,6 @@ public interface SysAuthService extends SecurityAuthFrameworkService { * @param userId 用户编号 * @param reqVO 绑定信息 */ - void socialBind(Long userId, @Valid SysAuthSocialBindReqVO reqVO); + void socialBind(Long userId, @Valid AuthSocialBindReqVO reqVO); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index 438bd1e75a..7bdb58f3a3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -1,38 +1,32 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; +package cn.iocoder.yudao.module.system.service.auth; -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; -import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthLoginReqVO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialBindReqVO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLogin2ReqVO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLoginReqVO; +import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.service.common.CaptchaService; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthUser; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; @@ -41,14 +35,11 @@ import org.springframework.stereotype.Service; import org.springframework.util.Assert; import javax.annotation.Resource; -import java.util.Collections; -import java.util.List; import java.util.Objects; import java.util.Set; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static java.util.Collections.singleton; /** @@ -58,36 +49,30 @@ import static java.util.Collections.singleton; */ @Service @Slf4j -public class SysAuthServiceImpl implements SysAuthService { - - private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN; +public class AdminAuthServiceImpl implements AdminAuthService { @Resource @Lazy // 延迟加载,因为存在相互依赖的问题 private AuthenticationManager authenticationManager; + @Autowired + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // UserService 存在重名 + private AdminUserService userService; @Resource - private SysUserService userService; + private PermissionService permissionService; @Resource - private SysUserCoreService userCoreService; + private CaptchaService captchaService; @Resource - private SysPermissionService permissionService; + private LoginLogService loginLogService; @Resource - private SysCaptchaService captchaService; + private UserSessionService userSessionService; @Resource - private SysLoginLogCoreService loginLogCoreService; - @Resource - private SysUserSessionCoreService userSessionCoreService; - @Resource - private SysPostService postService; - @Resource - private SysSocialCoreService socialService; - + private SocialUserService socialUserService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - // 获取 username 对应的 SysUserDO - SysUserDO user = userService.getUserByUsername(username); + // 获取 username 对应的 AdminUserDO + AdminUserDO user = userService.getUserByUsername(username); if (user == null) { throw new UsernameNotFoundException(username); } @@ -97,19 +82,19 @@ public class SysAuthServiceImpl implements SysAuthService { @Override public LoginUser mockLogin(Long userId) { - // 获取用户编号对应的 SysUserDO - SysUserDO user = userCoreService.getUser(userId); + // 获取用户编号对应的 AdminUserDO + AdminUserDO user = userService.getUser(userId); if (user == null) { throw new UsernameNotFoundException(String.valueOf(userId)); } - this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS); + this.createLoginLog(user.getUsername(), LoginLogTypeEnum.LOGIN_MOCK, LoginResultEnum.SUCCESS); // 创建 LoginUser 对象 return this.buildLoginUser(user); } @Override - public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) { + public String login(AuthLoginReqVO reqVO, String userIp, String userAgent) { // 判断验证码是否正确 this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode()); @@ -117,14 +102,7 @@ public class SysAuthServiceImpl implements SysAuthService { LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // 缓存登陆用户到 Redis 中,返回 sessionId 编号 - return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); - } - - private List getUserPosts(Set postIds) { - if (CollUtil.isEmpty(postIds)) { - return Collections.emptyList(); - } - return convertList(postService.getPosts(postIds), SysPostDO::getCode); + return userSessionService.createUserSession(loginUser, userIp, userAgent); } private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { @@ -133,17 +111,17 @@ public class SysAuthServiceImpl implements SysAuthService { return; } // 验证码不存在 - final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME; + final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; String code = captchaService.getCaptchaCode(captchaUUID); if (code == null) { // 创建登录失败日志(验证码不存在) - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.CAPTCHA_NOT_FOUND); throw exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND); } // 验证码不正确 if (!code.equals(captchaCode)) { // 创建登录失败日志(验证码不正确) - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_CODE_ERROR); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.CAPTCHA_CODE_ERROR); throw exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR); } // 正确,所以要删除下验证码 @@ -151,49 +129,49 @@ public class SysAuthServiceImpl implements SysAuthService { } private LoginUser login0(String username, String password) { - final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME; + final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; // 用户验证 Authentication authentication; try { // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 - authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); - // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username); + authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken( + username, password, getUserType())); } catch (BadCredentialsException badCredentialsException) { - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); throw exception(AUTH_LOGIN_BAD_CREDENTIALS); } catch (DisabledException disabledException) { - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.USER_DISABLED); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.USER_DISABLED); throw exception(AUTH_LOGIN_USER_DISABLED); } catch (AuthenticationException authenticationException) { log.error("[login0][username({}) 发生未知异常]", username, authenticationException); - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.UNKNOWN_ERROR); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.UNKNOWN_ERROR); throw exception(AUTH_LOGIN_FAIL_UNKNOWN); } // 登录成功的日志 Assert.notNull(authentication.getPrincipal(), "Principal 不会为空"); - this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.SUCCESS); + this.createLoginLog(username, logTypeEnum, LoginResultEnum.SUCCESS); return (LoginUser) authentication.getPrincipal(); } - private void createLoginLog(String username, SysLoginLogTypeEnum logTypeEnum, SysLoginResultEnum loginResult) { + private void createLoginLog(String username, LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) { // 获得用户 - SysUserDO user = userService.getUserByUsername(username); + AdminUserDO user = userService.getUserByUsername(username); // 插入登录日志 - SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); reqDTO.setLogType(logTypeEnum.getType()); reqDTO.setTraceId(TracerUtils.getTraceId()); if (user != null) { reqDTO.setUserId(user.getId()); } - reqDTO.setUserType(UserTypeEnum.ADMIN.getValue()); + reqDTO.setUserType(getUserType().getValue()); reqDTO.setUsername(username); reqDTO.setUserAgent(ServletUtils.getUserAgent()); reqDTO.setUserIp(ServletUtils.getClientIP()); reqDTO.setResult(loginResult.getResult()); - loginLogCoreService.createLoginLog(reqDTO); + loginLogService.createLoginLog(reqDTO); // 更新最后登录时间 - if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { + if (user != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { userService.updateUserLogin(user.getId(), ServletUtils.getClientIP()); } } @@ -209,91 +187,88 @@ public class SysAuthServiceImpl implements SysAuthService { } @Override - public String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent) { - // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); - Assert.notNull(authUser, "授权用户不为空"); - - // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错 - String unionId = socialService.getAuthUserUnionId(authUser); - List socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM); - if (CollUtil.isEmpty(socialUsers)) { + public String socialLogin(AuthSocialLoginReqVO reqVO, String userIp, String userAgent) { + // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 + Long userId = socialUserService.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + reqVO.getCode(), reqVO.getState()); + if (userId == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } // 自动登录 - SysUserDO user = userCoreService.getUser(socialUsers.get(0).getUserId()); + AdminUserDO user = userService.getUser(userId); if (user == null) { throw exception(USER_NOT_EXISTS); } - this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS); + this.createLoginLog(user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL, LoginResultEnum.SUCCESS); // 创建 LoginUser 对象 LoginUser loginUser = this.buildLoginUser(user); // 绑定社交用户(更新) - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); // 缓存登录用户到 Redis 中,返回 sessionId 编号 - return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); + return userSessionService.createUserSession(loginUser, userIp, userAgent); } @Override - public String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { + public String socialLogin2(AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); + AuthUser authUser = socialUserService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); Assert.notNull(authUser, "授权用户不为空"); // 使用账号密码,进行登录。 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // 绑定社交用户(新增) - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); // 缓存登录用户到 Redis 中,返回 sessionId 编号 - return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); + return userSessionService.createUserSession(loginUser, userIp, userAgent); } @Override - public void socialBind(Long userId, SysAuthSocialBindReqVO reqVO) { - // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); - Assert.notNull(authUser, "授权用户不为空"); - + public void socialBind(Long userId, AuthSocialBindReqVO reqVO) { // 绑定社交用户(新增) - socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO)); } @Override public void logout(String token) { // 查询用户信息 - LoginUser loginUser = userSessionCoreService.getLoginUser(token); + LoginUser loginUser = userSessionService.getLoginUser(token); if (loginUser == null) { return; } // 删除 session - userSessionCoreService.deleteUserSession(token); + userSessionService.deleteUserSession(token); // 记录登出日志 this.createLogoutLog(loginUser.getId(), loginUser.getUsername()); } + @Override + public UserTypeEnum getUserType() { + return UserTypeEnum.ADMIN; + } + private void createLogoutLog(Long userId, String username) { - SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); - reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType()); reqDTO.setTraceId(TracerUtils.getTraceId()); reqDTO.setUserId(userId); - reqDTO.setUserType(USER_TYPE_ENUM.getValue()); + reqDTO.setUserType(getUserType().getValue()); reqDTO.setUsername(username); reqDTO.setUserAgent(ServletUtils.getUserAgent()); reqDTO.setUserIp(ServletUtils.getClientIP()); - reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult()); - loginLogCoreService.createLoginLog(reqDTO); + reqDTO.setResult(LoginResultEnum.SUCCESS.getResult()); + loginLogService.createLoginLog(reqDTO); } @Override public LoginUser verifyTokenAndRefresh(String token) { // 获得 LoginUser - LoginUser loginUser = userSessionCoreService.getLoginUser(token); + LoginUser loginUser = userSessionService.getLoginUser(token); if (loginUser == null) { return null; } @@ -304,24 +279,24 @@ public class SysAuthServiceImpl implements SysAuthService { private LoginUser refreshLoginUserCache(String token, LoginUser loginUser) { // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存 if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() < - userSessionCoreService.getSessionTimeoutMillis() / 3) { + userSessionService.getSessionTimeoutMillis() / 3) { return loginUser; } - // 重新加载 SysUserDO 信息 - SysUserDO user = userCoreService.getUser(loginUser.getId()); + // 重新加载 AdminUserDO 信息 + AdminUserDO user = userService.getUser(loginUser.getId()); if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 } // 刷新 LoginUser 缓存 LoginUser newLoginUser= this.buildLoginUser(user); - userSessionCoreService.refreshUserSession(token, newLoginUser); + userSessionService.refreshUserSession(token, newLoginUser); return newLoginUser; } - private LoginUser buildLoginUser(SysUserDO user) { - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); + private LoginUser buildLoginUser(AdminUserDO user) { + LoginUser loginUser = AuthConvert.INSTANCE.convert(user); // 补全字段 loginUser.setDeptId(user.getDeptId()); loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionService.java new file mode 100644 index 0000000000..779f33a476 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.system.service.auth; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 在线用户 Session Service 接口 + * + * @author 芋道源码 + */ +public interface UserSessionService { + + /** + * 获得在线用户分页列表 + * + * @param reqVO 分页条件 + * @return 份额与列表 + */ + PageResult getUserSessionPage(UserSessionPageReqVO reqVO); + + /** + * 移除超时的在线用户 + * + * @return {@link Long } 移出的超时用户数量 + **/ + long clearSessionTimeout(); + + /** + * 创建在线用户 Session + * + * @param loginUser 登录用户 + * @param userIp 用户 IP + * @param userAgent 用户 UA + * @return Session 编号 + */ + String createUserSession(LoginUser loginUser, String userIp, String userAgent); + + /** + * 刷新在线用户 Session 的更新时间 + * + * @param sessionId Session 编号 + * @param loginUser 登录用户 + */ + void refreshUserSession(String sessionId, LoginUser loginUser); + + /** + * 删除在线用户 Session + * + * @param sessionId Session 编号 + */ + void deleteUserSession(String sessionId); + + /** + * 获得 Session 编号对应的在线用户 + * + * @param sessionId Session 编号 + * @return 在线用户 + */ + LoginUser getLoginUser(String sessionId); + + /** + * 获得 Session 超时时间,单位:毫秒 + * + * @return 超时时间 + */ + Long getSessionTimeoutMillis(); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImpl.java new file mode 100644 index 0000000000..a1118958ac --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImpl.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.system.service.auth; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; + +/** + * 在线用户 Session Service 实现类 + * + * @author 芋道源码 + */ +@Slf4j +@Service +public class UserSessionServiceImpl implements UserSessionService { + + @Resource + private UserSessionMapper userSessionMapper; + + @Resource + private AdminUserService userService; + @Resource + private LoginLogService loginLogService; + + @Resource + private LoginUserRedisDAO loginUserRedisDAO; + + @Resource + private SecurityProperties securityProperties; + + @Override + public PageResult getUserSessionPage(UserSessionPageReqVO reqVO) { + // 处理基于用户昵称的查询 + Collection userIds = null; + if (StrUtil.isNotEmpty(reqVO.getUsername())) { + userIds = convertSet(userService.getUsersByUsername(reqVO.getUsername()), AdminUserDO::getId); + if (CollUtil.isEmpty(userIds)) { + return PageResult.empty(); + } + } + return userSessionMapper.selectPage(reqVO, userIds); + } + + // TODO @芋艿:优化下该方法 + @Override + public long clearSessionTimeout() { + // 获取db里已经超时的用户列表 + List sessionTimeoutDOS = userSessionMapper.selectListBySessionTimoutLt(); + Map timeoutSessionDOMap = sessionTimeoutDOS + .stream() + .filter(sessionDO -> loginUserRedisDAO.get(sessionDO.getId()) == null) + .collect(Collectors.toMap(UserSessionDO::getId, o -> o)); + // 确认已经超时,按批次移出在线用户列表 + if (CollUtil.isNotEmpty(timeoutSessionDOMap)) { + Lists.partition(new ArrayList<>(timeoutSessionDOMap.keySet()), 100) + .forEach(userSessionMapper::deleteBatchIds); + // 记录用户超时退出日志 + createTimeoutLogoutLog(timeoutSessionDOMap.values()); + } + return timeoutSessionDOMap.size(); + } + + private void createTimeoutLogoutLog(Collection timeoutSessionDOS) { + for (UserSessionDO timeoutSessionDO : timeoutSessionDOS) { + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_TIMEOUT.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(timeoutSessionDO.getUserId()); + reqDTO.setUserType(timeoutSessionDO.getUserType()); + reqDTO.setUsername(timeoutSessionDO.getUsername()); + reqDTO.setUserAgent(timeoutSessionDO.getUserAgent()); + reqDTO.setUserIp(timeoutSessionDO.getUserIp()); + reqDTO.setResult(LoginResultEnum.SUCCESS.getResult()); + loginLogService.createLoginLog(reqDTO); + } + } + + @Override + public String createUserSession(LoginUser loginUser, String userIp, String userAgent) { + // 生成 Session 编号 + String sessionId = generateSessionId(); + // 写入 Redis 缓存 + loginUser.setUpdateTime(new Date()); + loginUserRedisDAO.set(sessionId, loginUser); + // 写入 DB 中 + UserSessionDO userSession = UserSessionDO.builder().id(sessionId) + .userId(loginUser.getId()).userType(loginUser.getUserType()) + .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername()) + .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis()))) + .build(); + userSessionMapper.insert(userSession); + // 返回 Session 编号 + return sessionId; + } + + @Override + public void refreshUserSession(String sessionId, LoginUser loginUser) { + // 写入 Redis 缓存 + loginUser.setUpdateTime(new Date()); + loginUserRedisDAO.set(sessionId, loginUser); + // 更新 DB 中 + UserSessionDO updateObj = UserSessionDO.builder().id(sessionId).build(); + updateObj.setUsername(loginUser.getUsername()); + updateObj.setUpdateTime(new Date()); + updateObj.setSessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis()))); + userSessionMapper.updateById(updateObj); + } + + @Override + public void deleteUserSession(String sessionId) { + // 删除 Redis 缓存 + loginUserRedisDAO.delete(sessionId); + // 删除 DB 记录 + userSessionMapper.deleteById(sessionId); + } + + @Override + public LoginUser getLoginUser(String sessionId) { + return loginUserRedisDAO.get(sessionId); + } + + @Override + public Long getSessionTimeoutMillis() { + return securityProperties.getSessionTimeout().toMillis(); + } + + /** + * 生成 Session 编号,目前采用 UUID 算法 + * + * @return Session 编号 + */ + private static String generateSessionId() { + return IdUtil.fastSimpleUUID(); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaService.java similarity index 68% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaService.java index 32aff5b06a..ecb05d88a2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaService.java @@ -1,18 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.common; +package cn.iocoder.yudao.module.system.service.common; -import cn.iocoder.yudao.adminserver.modules.system.controller.common.vo.SysCaptchaImageRespVO; +import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO; /** * 验证码 Service 接口 */ -public interface SysCaptchaService { +public interface CaptchaService { /** * 获得验证码图片 * * @return 验证码图片 */ - SysCaptchaImageRespVO getCaptchaImage(); + CaptchaImageRespVO getCaptchaImage(); /** * 是否开启图片验证码 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceImpl.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceImpl.java index daefc007f4..1c1a388757 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceImpl.java @@ -1,13 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.common.impl; +package cn.iocoder.yudao.module.system.service.common; import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.CircleCaptcha; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.adminserver.modules.system.framework.captcha.config.CaptchaProperties; -import cn.iocoder.yudao.adminserver.modules.system.controller.common.vo.SysCaptchaImageRespVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.common.SysCaptchaConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.common.SysCaptchaRedisDAO; -import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; +import cn.iocoder.yudao.module.system.convert.common.CaptchaConvert; +import cn.iocoder.yudao.module.system.framework.captcha.config.CaptchaProperties; +import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO; +import cn.iocoder.yudao.module.system.dal.redis.common.CaptchaRedisDAO; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -16,23 +15,23 @@ import javax.annotation.Resource; * 验证码 Service 实现类 */ @Service -public class SysCaptchaServiceImpl implements SysCaptchaService { +public class CaptchaServiceImpl implements CaptchaService { @Resource private CaptchaProperties captchaProperties; @Resource - private SysCaptchaRedisDAO captchaRedisDAO; + private CaptchaRedisDAO captchaRedisDAO; @Override - public SysCaptchaImageRespVO getCaptchaImage() { + public CaptchaImageRespVO getCaptchaImage() { // 生成验证码 CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight()); // 缓存到 Redis 中 String uuid = IdUtil.fastSimpleUUID(); captchaRedisDAO.set(uuid, captcha.getCode(), captchaProperties.getTimeout()); // 返回 - return SysCaptchaConvert.INSTANCE.convert(uuid, captcha); + return CaptchaConvert.INSTANCE.convert(uuid, captcha); } @Override diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java index bf3ce317f3..a6c30bc10d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept; +package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import java.util.Collection; import java.util.Collections; @@ -17,7 +17,7 @@ import java.util.Map; * * @author 芋道源码 */ -public interface SysDeptService { +public interface DeptService { /** * 初始化部门的本地缓存 @@ -30,14 +30,14 @@ public interface SysDeptService { * @param reqVO 部门信息 * @return 部门编号 */ - Long createDept(SysDeptCreateReqVO reqVO); + Long createDept(DeptCreateReqVO reqVO); /** * 更新部门 * * @param reqVO 部门信息 */ - void updateDept(SysDeptUpdateReqVO reqVO); + void updateDept(DeptUpdateReqVO reqVO); /** * 删除部门 @@ -46,51 +46,13 @@ public interface SysDeptService { */ void deleteDept(Long id); - /** - * 获得指定编号的部门列表 - * - * @param ids 部门编号数组 - * @return 部门列表 - */ - List getSimpleDepts(Collection ids); - - /** - * 获得指定编号的部门 Map - * - * @param ids 部门编号数组 - * @return 部门 Map - */ - default Map getDeptMap(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return Collections.emptyMap(); - } - List list = getSimpleDepts(ids); - return CollectionUtils.convertMap(list, SysDeptDO::getId); - } - /** * 筛选部门列表 * * @param reqVO 筛选条件请求 VO * @return 部门列表 */ - List getSimpleDepts(SysDeptListReqVO reqVO); - - /** - * 获得部门信息 - * - * @param id 部门编号 - * @return 部门信息 - */ - SysDeptDO getDept(Long id); - - /** - * 获得部门信息数组 - * - * @param ids 部门编号数组 - * @return 部门信息数组 - */ - List getDepts(Collection ids); + List getSimpleDepts(DeptListReqVO reqVO); /** * 获得所有子部门,从缓存中 @@ -99,7 +61,23 @@ public interface SysDeptService { * @param recursive 是否递归获取所有 * @return 子部门列表 */ - List getDeptsByParentIdFromCache(Long parentId, boolean recursive); + List getDeptsByParentIdFromCache(Long parentId, boolean recursive); + + /** + * 获得部门信息数组 + * + * @param ids 部门编号数组 + * @return 部门信息数组 + */ + List getDepts(Collection ids); + + /** + * 获得部门信息 + * + * @param id 部门编号 + * @return 部门信息 + */ + DeptDO getDept(Long id); /** * 校验部门们是否有效。如下情况,视为无效: @@ -110,4 +88,25 @@ public interface SysDeptService { */ void validDepts(Collection ids); + /** + * 获得指定编号的部门列表 + * + * @param ids 部门编号数组 + * @return 部门列表 + */ + List getSimpleDepts(Collection ids); + + /** + * 获得指定编号的部门 Map + * + * @param ids 部门编号数组 + * @return 部门 Map + */ + default Map getDeptMap(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyMap(); + } + List list = getSimpleDepts(ids); + return CollectionUtils.convertMap(list, DeptDO::getId); + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index 60b33431bd..955ce890ac 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -1,19 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept.impl; +package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.dept.SysDeptConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysDeptMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.dept.DeptIdEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept.SysDeptProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; +import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; +import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; @@ -26,8 +25,8 @@ import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 部门 Service 实现类 @@ -37,7 +36,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU @Service @Validated @Slf4j -public class SysDeptServiceImpl implements SysDeptService { +public class DeptServiceImpl implements DeptService { /** * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 @@ -47,43 +46,43 @@ public class SysDeptServiceImpl implements SysDeptService { /** * 部门缓存 - * key:部门编号 {@link SysDeptDO#getId()} + * key:部门编号 {@link DeptDO#getId()} * * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ @SuppressWarnings("FieldCanBeLocal") - private volatile Map deptCache; + private volatile Map deptCache; /** * 父部门缓存 - * key:部门编号 {@link SysDeptDO#getParentId()} + * key:部门编号 {@link DeptDO#getParentId()} * value: 直接子部门列表 * * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ - private volatile Multimap parentDeptCache; + private volatile Multimap parentDeptCache; /** * 缓存部门的最大更新时间,用于后续的增量轮询,判断是否有更新 */ private volatile Date maxUpdateTime; @Resource - private SysDeptMapper deptMapper; + private DeptMapper deptMapper; @Resource - private SysDeptProducer deptProducer; + private DeptProducer deptProducer; @Override @PostConstruct public synchronized void initLocalCache() { // 获取部门列表,如果有更新 - List deptList = this.loadDeptIfUpdate(maxUpdateTime); + List deptList = this.loadDeptIfUpdate(maxUpdateTime); if (CollUtil.isEmpty(deptList)) { return; } // 构建缓存 - ImmutableMap.Builder builder = ImmutableMap.builder(); - ImmutableMultimap.Builder parentBuilder = ImmutableMultimap.builder(); + ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMultimap.Builder parentBuilder = ImmutableMultimap.builder(); deptList.forEach(sysRoleDO -> { builder.put(sysRoleDO.getId(), sysRoleDO); parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); @@ -108,7 +107,7 @@ public class SysDeptServiceImpl implements SysDeptService { * @param maxUpdateTime 当前部门的最大更新时间 * @return 部门列表 */ - private List loadDeptIfUpdate(Date maxUpdateTime) { + private List loadDeptIfUpdate(Date maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadMenuIfUpdate][首次加载全量部门]"); @@ -123,11 +122,11 @@ public class SysDeptServiceImpl implements SysDeptService { } @Override - public Long createDept(SysDeptCreateReqVO reqVO) { + public Long createDept(DeptCreateReqVO reqVO) { // 校验正确性 checkCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName()); // 插入部门 - SysDeptDO dept = SysDeptConvert.INSTANCE.convert(reqVO); + DeptDO dept = DeptConvert.INSTANCE.convert(reqVO); deptMapper.insert(dept); // 发送刷新消息 deptProducer.sendDeptRefreshMessage(); @@ -135,11 +134,11 @@ public class SysDeptServiceImpl implements SysDeptService { } @Override - public void updateDept(SysDeptUpdateReqVO reqVO) { + public void updateDept(DeptUpdateReqVO reqVO) { // 校验正确性 checkCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName()); // 更新部门 - SysDeptDO updateObj = SysDeptConvert.INSTANCE.convert(reqVO); + DeptDO updateObj = DeptConvert.INSTANCE.convert(reqVO); deptMapper.updateById(updateObj); // 发送刷新消息 deptProducer.sendDeptRefreshMessage(); @@ -160,21 +159,16 @@ public class SysDeptServiceImpl implements SysDeptService { } @Override - public List getSimpleDepts(Collection ids) { - return deptMapper.selectBatchIds(ids); - } - - @Override - public List getSimpleDepts(SysDeptListReqVO reqVO) { + public List getSimpleDepts(DeptListReqVO reqVO) { return deptMapper.selectList(reqVO); } @Override - public List getDeptsByParentIdFromCache(Long parentId, boolean recursive) { + public List getDeptsByParentIdFromCache(Long parentId, boolean recursive) { if (parentId == null) { return Collections.emptyList(); } - List result = new ArrayList<>(); // TODO 芋艿:待优化,新增缓存,避免每次遍历的计算 + List result = new ArrayList<>(); // TODO 芋艿:待优化,新增缓存,避免每次遍历的计算 // 递归,简单粗暴 this.getDeptsByParentIdFromCache(result, parentId, recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次 @@ -182,26 +176,6 @@ public class SysDeptServiceImpl implements SysDeptService { return result; } - @Override - public void validDepts(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return; - } - // 获得科室信息 - List depts = deptMapper.selectBatchIds(ids); - Map deptMap = CollectionUtils.convertMap(depts, SysDeptDO::getId); - // 校验 - ids.forEach(id -> { - SysDeptDO dept = deptMap.get(id); - if (dept == null) { - throw exception(DEPT_NOT_FOUND); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getStatus())) { - throw exception(DEPT_NOT_ENABLE, dept.getName()); - } - }); - } - /** * 递归获取所有的子部门,添加到 result 结果 * @@ -210,14 +184,14 @@ public class SysDeptServiceImpl implements SysDeptService { * @param recursiveCount 递归次数 * @param parentDeptMap 父部门 Map,使用缓存,避免变化 */ - private void getDeptsByParentIdFromCache(List result, Long parentId, int recursiveCount, - Multimap parentDeptMap) { + private void getDeptsByParentIdFromCache(List result, Long parentId, int recursiveCount, + Multimap parentDeptMap) { // 递归次数为 0,结束! if (recursiveCount == 0) { return; } // 获得子部门 - Collection depts = parentDeptMap.get(parentId); + Collection depts = parentDeptMap.get(parentId); if (CollUtil.isEmpty(depts)) { return; } @@ -227,16 +201,6 @@ public class SysDeptServiceImpl implements SysDeptService { recursiveCount - 1, parentDeptMap)); } - @Override - public SysDeptDO getDept(Long id) { - return deptMapper.selectById(id); - } - - @Override - public List getDepts(Collection ids) { - return deptMapper.selectBatchIds(ids); - } - private void checkCreateOrUpdate(Long id, Long parentId, String name) { // 校验自己存在 checkDeptExists(id); @@ -255,7 +219,7 @@ public class SysDeptServiceImpl implements SysDeptService { throw ServiceExceptionUtil.exception(DEPT_PARENT_ERROR); } // 父岗位不存在 - SysDeptDO dept = deptMapper.selectById(parentId); + DeptDO dept = deptMapper.selectById(parentId); if (dept == null) { throw ServiceExceptionUtil.exception(DEPT_PARENT_NOT_EXITS); } @@ -264,7 +228,7 @@ public class SysDeptServiceImpl implements SysDeptService { throw ServiceExceptionUtil.exception(DEPT_NOT_ENABLE); } // 父部门不能是原来的子部门 - List children = this.getDeptsByParentIdFromCache(id, true); + List children = this.getDeptsByParentIdFromCache(id, true); if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) { throw ServiceExceptionUtil.exception(DEPT_PARENT_IS_CHILD); } @@ -274,14 +238,14 @@ public class SysDeptServiceImpl implements SysDeptService { if (id == null) { return; } - SysDeptDO dept = deptMapper.selectById(id); + DeptDO dept = deptMapper.selectById(id); if (dept == null) { throw ServiceExceptionUtil.exception(DEPT_NOT_FOUND); } } private void checkDeptNameUnique(Long id, Long parentId, String name) { - SysDeptDO menu = deptMapper.selectByParentIdAndName(parentId, name); + DeptDO menu = deptMapper.selectByParentIdAndName(parentId, name); if (menu == null) { return; } @@ -294,4 +258,39 @@ public class SysDeptServiceImpl implements SysDeptService { } } + @Override + public List getDepts(Collection ids) { + return deptMapper.selectBatchIds(ids); + } + + @Override + public DeptDO getDept(Long id) { + return deptMapper.selectById(id); + } + + @Override + public void validDepts(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得科室信息 + List depts = deptMapper.selectBatchIds(ids); + Map deptMap = CollectionUtils.convertMap(depts, DeptDO::getId); + // 校验 + ids.forEach(id -> { + DeptDO dept = deptMap.get(id); + if (dept == null) { + throw exception(DEPT_NOT_FOUND); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getStatus())) { + throw exception(DEPT_NOT_ENABLE, dept.getName()); + } + }); + } + + @Override + public List getSimpleDepts(Collection ids) { + return deptMapper.selectBatchIds(ids); + } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java similarity index 63% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java index 608e360b2f..fc74c944a7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept; +package cn.iocoder.yudao.module.system.service.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import org.springframework.lang.Nullable; import java.util.Collection; @@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; * * @author 芋道源码 */ -public interface SysPostService { +public interface PostService { /** * 创建岗位 @@ -27,14 +27,14 @@ public interface SysPostService { * @param reqVO 岗位信息 * @return 岗位编号 */ - Long createPost(SysPostCreateReqVO reqVO); + Long createPost(PostCreateReqVO reqVO); /** * 更新岗位 * * @param reqVO 岗位信息 */ - void updatePost(SysPostUpdateReqVO reqVO); + void updatePost(PostUpdateReqVO reqVO); /** * 删除岗位信息 @@ -49,7 +49,7 @@ public interface SysPostService { * @param ids 岗位编号数组。如果为空,不进行筛选 * @return 部门列表 */ - default List getPosts(@Nullable Collection ids) { + default List getPosts(@Nullable Collection ids) { return getPosts(ids, asSet(CommonStatusEnum.ENABLE.getStatus(), CommonStatusEnum.DISABLE.getStatus())); } @@ -60,7 +60,7 @@ public interface SysPostService { * @param statuses 状态数组。如果为空,不进行筛选 * @return 部门列表 */ - List getPosts(@Nullable Collection ids, @Nullable Collection statuses); + List getPosts(@Nullable Collection ids, @Nullable Collection statuses); /** * 获得岗位分页列表 @@ -68,7 +68,7 @@ public interface SysPostService { * @param reqVO 分页条件 * @return 部门分页列表 */ - PageResult getPostPage(SysPostPageReqVO reqVO); + PageResult getPostPage(PostPageReqVO reqVO); /** * 获得岗位列表 @@ -76,7 +76,7 @@ public interface SysPostService { * @param reqVO 查询条件 * @return 部门列表 */ - List getPosts(SysPostExportReqVO reqVO); + List getPosts(PostExportReqVO reqVO); /** * 获得岗位信息 @@ -84,7 +84,7 @@ public interface SysPostService { * @param id 岗位编号 * @return 岗位信息 */ - SysPostDO getPost(Long id); + PostDO getPost(Long id); /** * 校验岗位们是否有效。如下情况,视为无效: diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysPostServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysPostServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java index 220724e332..81e003152e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysPostServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java @@ -1,19 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept.impl; +package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.dept.SysPostConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysPostMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.dept.PostConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.dal.mysql.dept.PostMapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -22,8 +19,9 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 岗位 Service 实现类 @@ -32,27 +30,27 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU */ @Service @Validated -public class SysPostServiceImpl implements SysPostService { +public class PostServiceImpl implements PostService { @Resource - private SysPostMapper postMapper; + private PostMapper postMapper; @Override - public Long createPost(SysPostCreateReqVO reqVO) { + public Long createPost(PostCreateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(null, reqVO.getName(), reqVO.getCode()); // 插入岗位 - SysPostDO post = SysPostConvert.INSTANCE.convert(reqVO); + PostDO post = PostConvert.INSTANCE.convert(reqVO); postMapper.insert(post); return post.getId(); } @Override - public void updatePost(SysPostUpdateReqVO reqVO) { + public void updatePost(PostUpdateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(reqVO.getId(), reqVO.getName(), reqVO.getCode()); // 更新岗位 - SysPostDO updateObj = SysPostConvert.INSTANCE.convert(reqVO); + PostDO updateObj = PostConvert.INSTANCE.convert(reqVO); postMapper.updateById(updateObj); } @@ -65,45 +63,25 @@ public class SysPostServiceImpl implements SysPostService { } @Override - public List getPosts(Collection ids, Collection statuses) { + public List getPosts(Collection ids, Collection statuses) { return postMapper.selectList(ids, statuses); } @Override - public PageResult getPostPage(SysPostPageReqVO reqVO) { + public PageResult getPostPage(PostPageReqVO reqVO) { return postMapper.selectPage(reqVO); } @Override - public List getPosts(SysPostExportReqVO reqVO) { + public List getPosts(PostExportReqVO reqVO) { return postMapper.selectList(reqVO); } @Override - public SysPostDO getPost(Long id) { + public PostDO getPost(Long id) { return postMapper.selectById(id); } - @Override - public void validPosts(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return; - } - // 获得岗位信息 - List posts = postMapper.selectBatchIds(ids); - Map postMap = CollectionUtils.convertMap(posts, SysPostDO::getId); - // 校验 - ids.forEach(id -> { - SysPostDO post = postMap.get(id); - if (post == null) { - throw exception(POST_NOT_FOUND); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(post.getStatus())) { - throw exception(POST_NOT_ENABLE, post.getName()); - } - }); - } - private void checkCreateOrUpdate(Long id, String name, String code) { // 校验自己存在 checkPostExists(id); @@ -114,7 +92,7 @@ public class SysPostServiceImpl implements SysPostService { } private void checkPostNameUnique(Long id, String name) { - SysPostDO post = postMapper.selectByName(name); + PostDO post = postMapper.selectByName(name); if (post == null) { return; } @@ -128,7 +106,7 @@ public class SysPostServiceImpl implements SysPostService { } private void checkPostCodeUnique(Long id, String code) { - SysPostDO post = postMapper.selectByCode(code); + PostDO post = postMapper.selectByCode(code); if (post == null) { return; } @@ -145,10 +123,29 @@ public class SysPostServiceImpl implements SysPostService { if (id == null) { return; } - SysPostDO post = postMapper.selectById(id); + PostDO post = postMapper.selectById(id); if (post == null) { throw ServiceExceptionUtil.exception(POST_NOT_FOUND); } } + @Override + public void validPosts(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得岗位信息 + List posts = postMapper.selectBatchIds(ids); + Map postMap = convertMap(posts, PostDO::getId); + // 校验 + ids.forEach(id -> { + PostDO post = postMap.get(id); + if (post == null) { + throw exception(POST_NOT_FOUND); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(post.getStatus())) { + throw exception(POST_NOT_ENABLE, post.getName()); + } + }); + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java index 7fd19f4e93..0742f82931 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict; +package cn.iocoder.yudao.module.system.service.dict; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; import java.util.Collection; import java.util.List; @@ -16,7 +16,12 @@ import java.util.List; * * @author ruoyi */ -public interface SysDictDataService { +public interface DictDataService extends DictDataFrameworkService { + + /** + * 初始化字典数据的本地缓存 + */ + void initLocalCache(); /** * 创建字典数据 @@ -24,14 +29,14 @@ public interface SysDictDataService { * @param reqVO 字典数据信息 * @return 字典数据编号 */ - Long createDictData(SysDictDataCreateReqVO reqVO); + Long createDictData(DictDataCreateReqVO reqVO); /** * 更新字典数据 * * @param reqVO 字典数据信息 */ - void updateDictData(SysDictDataUpdateReqVO reqVO); + void updateDictData(DictDataUpdateReqVO reqVO); /** * 删除字典数据 @@ -45,7 +50,7 @@ public interface SysDictDataService { * * @return 字典数据全列表 */ - List getDictDatas(); + List getDictDatas(); /** * 获得字典数据分页列表 @@ -53,7 +58,7 @@ public interface SysDictDataService { * @param reqVO 分页请求 * @return 字典数据分页列表 */ - PageResult getDictDataPage(SysDictDataPageReqVO reqVO); + PageResult getDictDataPage(DictDataPageReqVO reqVO); /** * 获得字典数据列表 @@ -61,7 +66,7 @@ public interface SysDictDataService { * @param reqVO 列表请求 * @return 字典数据列表 */ - List getDictDatas(SysDictDataExportReqVO reqVO); + List getDictDatas(DictDataExportReqVO reqVO); /** * 获得字典数据详情 @@ -69,7 +74,7 @@ public interface SysDictDataService { * @param id 字典数据编号 * @return 字典数据 */ - SysDictDataDO getDictData(Long id); + DictDataDO getDictData(Long id); /** * 获得指定字典类型的数据数量 diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java new file mode 100644 index 0000000000..1ecbdd41cd --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java @@ -0,0 +1,281 @@ +package cn.iocoder.yudao.module.system.service.dict; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; +import cn.iocoder.yudao.module.system.mq.producer.dict.DictDataProducer; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableTable; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; + +/** + * 字典数据 Service 实现类 + * + * @author ruoyi + */ +@Service +@Slf4j +public class DictDataServiceImpl implements DictDataService { + + /** + * 排序 dictType > sort + */ + private static final Comparator COMPARATOR_TYPE_AND_SORT = Comparator + .comparing(DictDataDO::getDictType) + .thenComparingInt(DictDataDO::getSort); + + /** + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 + */ + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; + + @Resource + private DictTypeService dictTypeService; + + @Resource + private DictDataMapper dictDataMapper; + + @Resource + private DictDataProducer dictDataProducer; + + /** + * 字典数据缓存,第二个 key 使用 label + * + * key1:字典类型 dictType + * key2:字典标签 label + */ + private ImmutableTable labelDictDataCache; + /** + * 字典数据缓存,第二个 key 使用 value + * + * key1:字典类型 dictType + * key2:字典值 value + */ + private ImmutableTable valueDictDataCache; + /** + * 缓存字典数据的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private volatile Date maxUpdateTime; + + @Override + @PostConstruct + public synchronized void initLocalCache() { + // 获取字典数据列表,如果有更新 + List dataList = loadDictDataIfUpdate(maxUpdateTime); + if (CollUtil.isEmpty(dataList)) { + return; + } + + // 构建缓存 + ImmutableTable.Builder labelDictDataBuilder = ImmutableTable.builder(); + ImmutableTable.Builder valueDictDataBuilder = ImmutableTable.builder(); + dataList.forEach(dictData -> { + labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData); + valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData); + }); + labelDictDataCache = labelDictDataBuilder.build(); + valueDictDataCache = valueDictDataBuilder.build(); + assert dataList.size() > 0; // 断言,避免告警 + maxUpdateTime = dataList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); + log.info("[initLocalCache][缓存字典数据,数量为:{}]", dataList.size()); + } + + /** + * 如果字典数据发生变化,从数据库中获取最新的全量字典数据。 + * 如果未发生变化,则返回空 + * + * @param maxUpdateTime 当前字典数据的最大更新时间 + * @return 字典数据列表 + */ + private List loadDictDataIfUpdate(Date maxUpdateTime) { + // 第一步,判断是否要更新。 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 + log.info("[loadDictDataIfUpdate][首次加载全量字典数据]"); + } else { // 判断数据库中是否有更新的字典数据 + if (!dictDataMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) { + return null; + } + log.info("[loadDictDataIfUpdate][增量加载全量字典数据]"); + } + // 第二步,如果有更新,则从数据库加载所有字典数据 + return dictDataMapper.selectList(); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCache(); + } + + @Override + public List getDictDatas() { + List list = dictDataMapper.selectList(); + list.sort(COMPARATOR_TYPE_AND_SORT); + return list; + } + + @Override + public PageResult getDictDataPage(DictDataPageReqVO reqVO) { + return dictDataMapper.selectPage(reqVO); + } + + @Override + public List getDictDatas(DictDataExportReqVO reqVO) { + List list = dictDataMapper.selectList(reqVO); + list.sort(COMPARATOR_TYPE_AND_SORT); + return list; + } + + @Override + public DictDataDO getDictData(Long id) { + return dictDataMapper.selectById(id); + } + + @Override + public DictDataRespDTO getDictDataFromCache(String type, String value) { + return DictDataConvert.INSTANCE.convert02(valueDictDataCache.get(type, value)); + } + + @Override + public DictDataRespDTO parseDictDataFromCache(String type, String label) { + return DictDataConvert.INSTANCE.convert02(labelDictDataCache.get(type, label)); + } + + @Override + public List listDictDatasFromCache(String type) { + return DictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values()); + } + + @Override + public Long createDictData(DictDataCreateReqVO reqVO) { + // 校验正确性 + checkCreateOrUpdate(null, reqVO.getValue(), reqVO.getDictType()); + + // 插入字典类型 + DictDataDO dictData = DictDataConvert.INSTANCE.convert(reqVO); + dictDataMapper.insert(dictData); + + // 发送刷新消息 + dictDataProducer.sendDictDataRefreshMessage(); + return dictData.getId(); + } + + @Override + public void updateDictData(DictDataUpdateReqVO reqVO) { + // 校验正确性 + checkCreateOrUpdate(reqVO.getId(), reqVO.getValue(), reqVO.getDictType()); + + // 更新字典类型 + DictDataDO updateObj = DictDataConvert.INSTANCE.convert(reqVO); + dictDataMapper.updateById(updateObj); + + // 发送刷新消息 + dictDataProducer.sendDictDataRefreshMessage(); + } + + @Override + public void deleteDictData(Long id) { + // 校验是否存在 + checkDictDataExists(id); + + // 删除字典数据 + dictDataMapper.deleteById(id); + + // 发送刷新消息 + dictDataProducer.sendDictDataRefreshMessage(); + } + + @Override + public int countByDictType(String dictType) { + return dictDataMapper.selectCountByDictType(dictType); + } + + + private void checkCreateOrUpdate(Long id, String value, String dictType) { + // 校验自己存在 + checkDictDataExists(id); + // 校验字典类型有效 + checkDictTypeValid(dictType); + // 校验字典数据的值的唯一性 + checkDictDataValueUnique(id, dictType, value); + } + + @VisibleForTesting + public void checkDictDataValueUnique(Long id, String dictType, String value) { + DictDataDO dictData = dictDataMapper.selectByDictTypeAndValue(dictType, value); + if (dictData == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典数据 + if (id == null) { + throw exception(DICT_DATA_VALUE_DUPLICATE); + } + if (!dictData.getId().equals(id)) { + throw exception(DICT_DATA_VALUE_DUPLICATE); + } + } + + @VisibleForTesting + public void checkDictDataExists(Long id) { + if (id == null) { + return; + } + DictDataDO dictData = dictDataMapper.selectById(id); + if (dictData == null) { + throw exception(DICT_DATA_NOT_EXISTS); + } + } + + @VisibleForTesting + public void checkDictTypeValid(String type) { + DictTypeDO dictType = dictTypeService.getDictType(type); + if (dictType == null) { + throw exception(DICT_TYPE_NOT_EXISTS); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) { + throw exception(DICT_TYPE_NOT_ENABLE); + } + } + + @Override + public void validDictDatas(String dictType, Collection values) { + if (CollUtil.isEmpty(values)) { + return; + } + ImmutableMap dictDataMap = valueDictDataCache.row(dictType); + // 校验 + values.forEach(value -> { + DictDataDO dictData = dictDataMap.get(value); + if (dictData == null) { + throw exception(DICT_DATA_NOT_EXISTS); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(dictData.getStatus())) { + throw exception(DICT_DATA_NOT_ENABLE, dictData.getLabel()); + } + }); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java index 6c3324fb56..4b334b08be 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict; +package cn.iocoder.yudao.module.system.service.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import java.util.List; @@ -14,7 +14,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface SysDictTypeService { +public interface DictTypeService { /** * 创建字典类型 @@ -22,14 +22,14 @@ public interface SysDictTypeService { * @param reqVO 字典类型信息 * @return 字典类型编号 */ - Long createDictType(SysDictTypeCreateReqVO reqVO); + Long createDictType(DictTypeCreateReqVO reqVO); /** * 更新字典类型 * * @param reqVO 字典类型信息 */ - void updateDictType(SysDictTypeUpdateReqVO reqVO); + void updateDictType(DictTypeUpdateReqVO reqVO); /** * 删除字典类型 @@ -44,7 +44,7 @@ public interface SysDictTypeService { * @param reqVO 分页请求 * @return 字典类型分页列表 */ - PageResult getDictTypePage(SysDictTypePageReqVO reqVO); + PageResult getDictTypePage(DictTypePageReqVO reqVO); /** * 获得字典类型列表 @@ -52,7 +52,7 @@ public interface SysDictTypeService { * @param reqVO 列表请求 * @return 字典类型列表 */ - List getDictTypeList(SysDictTypeExportReqVO reqVO); + List getDictTypeList(DictTypeExportReqVO reqVO); /** * 获得字典类型详情 @@ -60,7 +60,7 @@ public interface SysDictTypeService { * @param id 字典类型编号 * @return 字典类型 */ - SysDictTypeDO getDictType(Long id); + DictTypeDO getDictType(Long id); /** * 获得字典类型详情 @@ -68,13 +68,13 @@ public interface SysDictTypeService { * @param type 字典类型 * @return 字典类型详情 */ - SysDictTypeDO getDictType(String type); + DictTypeDO getDictType(String type); /** * 获得全部字典类型列表 * * @return 字典类型列表 */ - List getDictTypeList(); + List getDictTypeList(); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictTypeServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictTypeServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java index b054764532..c0677aff16 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/impl/SysDictTypeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java @@ -1,15 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict.impl; +package cn.iocoder.yudao.module.system.service.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictTypeConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictTypeMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictTypeService; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.dict.DictTypeConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; import com.google.common.annotations.VisibleForTesting; import org.springframework.stereotype.Service; @@ -17,7 +15,7 @@ import javax.annotation.Resource; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 字典类型 Service 实现类 @@ -25,57 +23,57 @@ import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeCons * @author 芋道源码 */ @Service -public class SysDictTypeServiceImpl implements SysDictTypeService { +public class DictTypeServiceImpl implements DictTypeService { @Resource - private SysDictDataService dictDataService; + private DictDataService dictDataService; @Resource - private SysDictTypeMapper dictTypeMapper; + private DictTypeMapper dictTypeMapper; @Override - public PageResult getDictTypePage(SysDictTypePageReqVO reqVO) { + public PageResult getDictTypePage(DictTypePageReqVO reqVO) { return dictTypeMapper.selectPage(reqVO); } @Override - public List getDictTypeList(SysDictTypeExportReqVO reqVO) { + public List getDictTypeList(DictTypeExportReqVO reqVO) { return dictTypeMapper.selectList(reqVO); } @Override - public SysDictTypeDO getDictType(Long id) { + public DictTypeDO getDictType(Long id) { return dictTypeMapper.selectById(id); } @Override - public SysDictTypeDO getDictType(String type) { + public DictTypeDO getDictType(String type) { return dictTypeMapper.selectByType(type); } @Override - public Long createDictType(SysDictTypeCreateReqVO reqVO) { + public Long createDictType(DictTypeCreateReqVO reqVO) { // 校验正确性 - this.checkCreateOrUpdate(null, reqVO.getName(), reqVO.getType()); + checkCreateOrUpdate(null, reqVO.getName(), reqVO.getType()); // 插入字典类型 - SysDictTypeDO dictType = SysDictTypeConvert.INSTANCE.convert(reqVO); + DictTypeDO dictType = DictTypeConvert.INSTANCE.convert(reqVO); dictTypeMapper.insert(dictType); return dictType.getId(); } @Override - public void updateDictType(SysDictTypeUpdateReqVO reqVO) { + public void updateDictType(DictTypeUpdateReqVO reqVO) { // 校验正确性 - this.checkCreateOrUpdate(reqVO.getId(), reqVO.getName(), null); + checkCreateOrUpdate(reqVO.getId(), reqVO.getName(), null); // 更新字典类型 - SysDictTypeDO updateObj = SysDictTypeConvert.INSTANCE.convert(reqVO); + DictTypeDO updateObj = DictTypeConvert.INSTANCE.convert(reqVO); dictTypeMapper.updateById(updateObj); } @Override public void deleteDictType(Long id) { // 校验是否存在 - SysDictTypeDO dictType = this.checkDictTypeExists(id); + DictTypeDO dictType = checkDictTypeExists(id); // 校验是否有字典数据 if (dictDataService.countByDictType(dictType.getType()) > 0) { throw exception(DICT_TYPE_HAS_CHILDREN); @@ -85,7 +83,7 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { } @Override - public List getDictTypeList() { + public List getDictTypeList() { return dictTypeMapper.selectList(); } @@ -100,7 +98,7 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { @VisibleForTesting public void checkDictTypeNameUnique(Long id, String name) { - SysDictTypeDO dictType = dictTypeMapper.selectByName(name); + DictTypeDO dictType = dictTypeMapper.selectByName(name); if (dictType == null) { return; } @@ -115,7 +113,7 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { @VisibleForTesting public void checkDictTypeUnique(Long id, String type) { - SysDictTypeDO dictType = dictTypeMapper.selectByType(type); + DictTypeDO dictType = dictTypeMapper.selectByType(type); if (dictType == null) { return; } @@ -129,11 +127,11 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { } @VisibleForTesting - public SysDictTypeDO checkDictTypeExists(Long id) { + public DictTypeDO checkDictTypeExists(Long id) { if (id == null) { return null; } - SysDictTypeDO dictType = dictTypeMapper.selectById(id); + DictTypeDO dictType = dictTypeMapper.selectById(id); if (dictType == null) { throw exception(DICT_TYPE_NOT_EXISTS); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java new file mode 100644 index 0000000000..18875f628d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.system.service.errorcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 错误码 Service 接口 + * + * @author 芋道源码 + */ +public interface ErrorCodeService extends ErrorCodeFrameworkService { + + /** + * 创建错误码 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createErrorCode(@Valid ErrorCodeCreateReqVO createReqVO); + + /** + * 更新错误码 + * + * @param updateReqVO 更新信息 + */ + void updateErrorCode(@Valid ErrorCodeUpdateReqVO updateReqVO); + + /** + * 删除错误码 + * + * @param id 编号 + */ + void deleteErrorCode(Long id); + + /** + * 获得错误码 + * + * @param id 编号 + * @return 错误码 + */ + ErrorCodeDO getErrorCode(Long id); + + /** + * 获得错误码分页 + * + * @param pageReqVO 分页查询 + * @return 错误码分页 + */ + PageResult getErrorCodePage(ErrorCodePageReqVO pageReqVO); + + /** + * 获得错误码列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 错误码列表 + */ + List getErrorCodeList(ErrorCodeExportReqVO exportReqVO); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java similarity index 59% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java index 178e071dd0..a34f098cd5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java @@ -1,18 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.errorcode.impl; +package cn.iocoder.yudao.module.system.service.errorcode; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.adminserver.modules.system.convert.errorcode.SysErrorCodeConvert; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.errorcode.SysErrorCodeMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.errorcode.SysErrorCodeService; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; +import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper; +import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -25,7 +24,7 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -37,34 +36,34 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @Service @Validated @Slf4j -public class SysErrorCodeServiceImpl implements SysErrorCodeService { +public class ErrorCodeServiceImpl implements ErrorCodeService { @Resource - private SysErrorCodeMapper errorCodeMapper; + private ErrorCodeMapper errorCodeMapper; @Override - public Long createErrorCode(SysErrorCodeCreateReqVO createReqVO) { + public Long createErrorCode(ErrorCodeCreateReqVO createReqVO) { // 校验 code 重复 validateCodeDuplicate(createReqVO.getCode(), null); // 插入 - SysErrorCodeDO errorCode = SysErrorCodeConvert.INSTANCE.convert(createReqVO) - .setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType()); + ErrorCodeDO errorCode = ErrorCodeConvert.INSTANCE.convert(createReqVO) + .setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType()); errorCodeMapper.insert(errorCode); // 返回 return errorCode.getId(); } @Override - public void updateErrorCode(SysErrorCodeUpdateReqVO updateReqVO) { + public void updateErrorCode(ErrorCodeUpdateReqVO updateReqVO) { // 校验存在 this.validateErrorCodeExists(updateReqVO.getId()); // 校验 code 重复 validateCodeDuplicate(updateReqVO.getCode(), updateReqVO.getId()); // 更新 - SysErrorCodeDO updateObj = SysErrorCodeConvert.INSTANCE.convert(updateReqVO) - .setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType()); + ErrorCodeDO updateObj = ErrorCodeConvert.INSTANCE.convert(updateReqVO) + .setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType()); errorCodeMapper.updateById(updateObj); } @@ -86,7 +85,7 @@ public class SysErrorCodeServiceImpl implements SysErrorCodeService { */ @VisibleForTesting public void validateCodeDuplicate(Integer code, Long id) { - SysErrorCodeDO errorCodeDO = errorCodeMapper.selectByCode(code); + ErrorCodeDO errorCodeDO = errorCodeMapper.selectByCode(code); if (errorCodeDO == null) { return; } @@ -107,17 +106,17 @@ public class SysErrorCodeServiceImpl implements SysErrorCodeService { } @Override - public SysErrorCodeDO getErrorCode(Long id) { + public ErrorCodeDO getErrorCode(Long id) { return errorCodeMapper.selectById(id); } @Override - public PageResult getErrorCodePage(SysErrorCodePageReqVO pageReqVO) { + public PageResult getErrorCodePage(ErrorCodePageReqVO pageReqVO) { return errorCodeMapper.selectPage(pageReqVO); } @Override - public List getErrorCodeList(SysErrorCodeExportReqVO exportReqVO) { + public List getErrorCodeList(ErrorCodeExportReqVO exportReqVO) { return errorCodeMapper.selectList(exportReqVO); } @@ -128,23 +127,23 @@ public class SysErrorCodeServiceImpl implements SysErrorCodeService { return; } // 获得错误码 - List errorCodeDOs = errorCodeMapper.selectListByCodes( + List errorCodeDOs = errorCodeMapper.selectListByCodes( convertSet(autoGenerateDTOs, ErrorCodeAutoGenerateReqDTO::getCode)); - Map errorCodeDOMap = convertMap(errorCodeDOs, SysErrorCodeDO::getCode); + Map errorCodeDOMap = convertMap(errorCodeDOs, ErrorCodeDO::getCode); // 遍历 autoGenerateBOs 数组,逐个插入或更新。考虑到每次量级不大,就不走批量了 autoGenerateDTOs.forEach(autoGenerateDTO -> { - SysErrorCodeDO errorCodeDO = errorCodeDOMap.get(autoGenerateDTO.getCode()); + ErrorCodeDO errorCodeDO = errorCodeDOMap.get(autoGenerateDTO.getCode()); // 不存在,则进行新增 if (errorCodeDO == null) { - errorCodeDO = SysErrorCodeConvert.INSTANCE.convert(autoGenerateDTO) - .setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType()); + errorCodeDO = ErrorCodeConvert.INSTANCE.convert(autoGenerateDTO) + .setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); errorCodeMapper.insert(errorCodeDO); return; } // 存在,则进行更新。更新有三个前置条件: // 条件 1. 只更新自动生成的错误码,即 Type 为 ErrorCodeTypeEnum.AUTO_GENERATION - if (!SysErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCodeDO.getType())) { + if (!ErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCodeDO.getType())) { return; } // 条件 2. 分组 applicationName 必须匹配,避免存在错误码冲突的情况 @@ -159,15 +158,15 @@ public class SysErrorCodeServiceImpl implements SysErrorCodeService { return; } // 最终匹配,进行更新 - errorCodeMapper.updateById(new SysErrorCodeDO().setId(errorCodeDO.getId()).setMessage(autoGenerateDTO.getMessage())); + errorCodeMapper.updateById(new ErrorCodeDO().setId(errorCodeDO.getId()).setMessage(autoGenerateDTO.getMessage())); }); } @Override public List getErrorCodeList(String applicationName, Date minUpdateTime) { - List errorCodeDOs = errorCodeMapper.selectListByApplicationNameAndUpdateTimeGt( + List errorCodeDOs = errorCodeMapper.selectListByApplicationNameAndUpdateTimeGt( applicationName, minUpdateTime); - return SysErrorCodeConvert.INSTANCE.convertList03(errorCodeDOs); + return ErrorCodeConvert.INSTANCE.convertList03(errorCodeDOs); } } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java new file mode 100644 index 0000000000..38b4fe78ef --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.system.service.logger; + +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 登录日志 Service 接口 + */ +public interface LoginLogService { + + /** + * 获得登录日志分页 + * + * @param reqVO 分页条件 + * @return 登录日志分页 + */ + PageResult getLoginLogPage(LoginLogPageReqVO reqVO); + + /** + * 获得登录日志列表 + * + * @param reqVO 列表条件 + * @return 登录日志列表 + */ + List getLoginLogList(LoginLogExportReqVO reqVO); + + /** + * 创建登录日志 + * + * @param reqDTO 日志信息 + */ + void createLoginLog(@Valid LoginLogCreateReqDTO reqDTO); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java new file mode 100644 index 0000000000..0b806f6da4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.system.service.logger; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; +import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 登录日志 Service 实现 + */ +@Service +@Validated +public class LoginLogServiceImpl implements LoginLogService { + + @Resource + private LoginLogMapper loginLogMapper; + + @Override + public PageResult getLoginLogPage(LoginLogPageReqVO reqVO) { + return loginLogMapper.selectPage(reqVO); + } + + @Override + public List getLoginLogList(LoginLogExportReqVO reqVO) { + return loginLogMapper.selectList(reqVO); + } + + @Override + public void createLoginLog(LoginLogCreateReqDTO reqDTO) { + LoginLogDO loginLog = LoginLogConvert.INSTANCE.convert(reqDTO); + loginLogMapper.insert(loginLog); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java new file mode 100644 index 0000000000..4ec2d8f011 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.system.service.logger; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; + +import java.util.List; + +/** + * 操作日志 Service 接口 + */ +public interface OperateLogService extends OperateLogFrameworkService { + + /** + * 获得操作日志分页列表 + * + * @param reqVO 分页条件 + * @return 操作日志分页列表 + */ + PageResult getOperateLogPage(OperateLogPageReqVO reqVO); + + /** + * 获得操作日志列表 + * + * @param reqVO 列表条件 + * @return 日志列表 + */ + List getOperateLogs(OperateLogExportReqVO reqVO); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java similarity index 60% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysOperateLogServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index 811710e24c..b1e0383feb 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -1,15 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl; +package cn.iocoder.yudao.module.system.service.logger; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysOperateLogConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysOperateLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysOperateLogService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; +import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; @@ -17,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; @@ -24,26 +24,27 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.Future; -import static cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; -import static cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO.RESULT_MAX_LENGTH; +import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; +import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.RESULT_MAX_LENGTH; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Service +@Validated @Slf4j -public class SysOperateLogServiceImpl implements SysOperateLogService { +public class OperateLogServiceImpl implements OperateLogService { @Resource - private SysOperateLogMapper operateLogMapper; + private OperateLogMapper operateLogMapper; @Resource - private SysUserService userService; + private AdminUserService userService; @Override @Async public Future createOperateLogAsync(OperateLogCreateReqDTO reqVO) { boolean success = false; try { - SysOperateLogDO logDO = SysOperateLogConvert.INSTANCE.convert(reqVO); + OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(reqVO); logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH)); success = operateLogMapper.insert(logDO) == 1; @@ -55,11 +56,11 @@ public class SysOperateLogServiceImpl implements SysOperateLogService { } @Override - public PageResult getOperateLogPage(SysOperateLogPageReqVO reqVO) { + public PageResult getOperateLogPage(OperateLogPageReqVO reqVO) { // 处理基于用户昵称的查询 Collection userIds = null; if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { - userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId); + userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), AdminUserDO::getId); if (CollUtil.isEmpty(userIds)) { return PageResult.empty(); } @@ -69,11 +70,11 @@ public class SysOperateLogServiceImpl implements SysOperateLogService { } @Override - public List getOperateLogs(SysOperateLogExportReqVO reqVO) { + public List getOperateLogs(OperateLogExportReqVO reqVO) { // 处理基于用户昵称的查询 Collection userIds = null; if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { - userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId); + userIds = convertSet(userService.getUsersByNickname(reqVO.getUserNickname()), AdminUserDO::getId); if (CollUtil.isEmpty(userIds)) { return Collections.emptyList(); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java similarity index 52% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java index ee4ecddb7b..264fc3048f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java @@ -1,15 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.notice; +package cn.iocoder.yudao.module.system.service.notice; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice.SysNoticeDO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; /** * 通知公告 Service 接口 */ -public interface SysNoticeService { +public interface NoticeService { /** * 创建岗位公告公告 @@ -17,14 +17,14 @@ public interface SysNoticeService { * @param reqVO 岗位公告公告信息 * @return 岗位公告公告编号 */ - Long createNotice(SysNoticeCreateReqVO reqVO); + Long createNotice(NoticeCreateReqVO reqVO); /** * 更新岗位公告公告 * * @param reqVO 岗位公告公告信息 */ - void updateNotice(SysNoticeUpdateReqVO reqVO); + void updateNotice(NoticeUpdateReqVO reqVO); /** * 删除岗位公告公告信息 @@ -39,7 +39,7 @@ public interface SysNoticeService { * @param reqVO 分页条件 * @return 部门分页列表 */ - PageResult pageNotices(SysNoticePageReqVO reqVO); + PageResult pageNotices(NoticePageReqVO reqVO); /** * 获得岗位公告公告信息 @@ -47,6 +47,6 @@ public interface SysNoticeService { * @param id 岗位公告公告编号 * @return 岗位公告公告信息 */ - SysNoticeDO getNotice(Long id); + NoticeDO getNotice(Long id); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java new file mode 100644 index 0000000000..2b796e28c8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.system.service.notice; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; +import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import com.google.common.annotations.VisibleForTesting; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND; + +/** + * 通知公告 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class NoticeServiceImpl implements NoticeService { + + @Resource + private NoticeMapper noticeMapper; + + @Override + public Long createNotice(NoticeCreateReqVO reqVO) { + NoticeDO notice = NoticeConvert.INSTANCE.convert(reqVO); + noticeMapper.insert(notice); + return notice.getId(); + } + + @Override + public void updateNotice(NoticeUpdateReqVO reqVO) { + // 校验是否存在 + this.checkNoticeExists(reqVO.getId()); + // 更新通知公告 + NoticeDO updateObj = NoticeConvert.INSTANCE.convert(reqVO); + noticeMapper.updateById(updateObj); + } + + @Override + public void deleteNotice(Long id) { + // 校验是否存在 + this.checkNoticeExists(id); + // 删除通知公告 + noticeMapper.deleteById(id); + } + + @Override + public PageResult pageNotices(NoticePageReqVO reqVO) { + return noticeMapper.selectPage(reqVO); + } + + @Override + public NoticeDO getNotice(Long id) { + return noticeMapper.selectById(id); + } + + @VisibleForTesting + public void checkNoticeExists(Long id) { + if (id == null) { + return; + } + NoticeDO notice = noticeMapper.selectById(id); + if (notice == null) { + throw ServiceExceptionUtil.exception(NOTICE_NOT_FOUND); + } + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java index 5979f16d14..405f390e4b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import java.util.Collection; import java.util.List; @@ -13,7 +13,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface SysMenuService { +public interface MenuService { /** * 初始化菜单的本地缓存 @@ -26,14 +26,14 @@ public interface SysMenuService { * @param reqVO 菜单信息 * @return 创建出来的菜单编号 */ - Long createMenu(SysMenuCreateReqVO reqVO); + Long createMenu(MenuCreateReqVO reqVO); /** * 更新菜单 * * @param reqVO 菜单信息 */ - void updateMenu(SysMenuUpdateReqVO reqVO); + void updateMenu(MenuUpdateReqVO reqVO); /** * 删除菜单 @@ -47,7 +47,7 @@ public interface SysMenuService { * * @return 菜单列表 */ - List getMenus(); + List getMenus(); /** * 筛选菜单列表 @@ -55,7 +55,7 @@ public interface SysMenuService { * @param reqVO 筛选条件请求 VO * @return 菜单列表 */ - List getMenus(SysMenuListReqVO reqVO); + List getMenus(MenuListReqVO reqVO); /** * 获得所有菜单,从缓存中 @@ -66,7 +66,7 @@ public interface SysMenuService { * @param menusStatuses 菜单状态数组 * @return 菜单列表 */ - List listMenusFromCache(Collection menuTypes, Collection menusStatuses); + List listMenusFromCache(Collection menuTypes, Collection menusStatuses); /** * 获得指定编号的菜单数组,从缓存中 @@ -78,8 +78,8 @@ public interface SysMenuService { * @param menusStatuses 菜单状态数组 * @return 菜单数组 */ - List listMenusFromCache(Collection menuIds, Collection menuTypes, - Collection menusStatuses); + List listMenusFromCache(Collection menuIds, Collection menuTypes, + Collection menusStatuses); /** * 获得权限对应的菜单数组 @@ -87,7 +87,7 @@ public interface SysMenuService { * @param permission 权限标识 * @return 数组 */ - List getMenuListByPermissionFromCache(String permission); + List getMenuListByPermissionFromCache(String permission); /** * 获得菜单 @@ -95,6 +95,6 @@ public interface SysMenuService { * @param id 菜单编号 * @return 菜单 */ - SysMenuDO getMenu(Long id); + MenuDO getMenu(Long id); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysMenuServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java similarity index 75% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysMenuServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java index 39200225ef..40d8c13c58 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysMenuServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java @@ -1,19 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission.impl; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.permission.SysMenuConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysMenuMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysMenuProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; +import cn.iocoder.yudao.module.system.enums.permission.MenuIdEnum; +import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; +import cn.iocoder.yudao.module.system.mq.producer.permission.MenuProducer; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; @@ -31,7 +29,7 @@ import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 菜单 Service 实现 @@ -40,7 +38,7 @@ import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeCons */ @Service @Slf4j -public class SysMenuServiceImpl implements SysMenuService { +public class MenuServiceImpl implements MenuService { /** * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 @@ -54,27 +52,27 @@ public class SysMenuServiceImpl implements SysMenuService { * * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ - private volatile Map menuCache; + private volatile Map menuCache; /** * 权限与菜单缓存 - * key:权限 {@link SysMenuDO#getPermission()} - * value:SysMenuDO 数组,因为一个权限可能对应多个 SysMenuDO 对象 + * key:权限 {@link MenuDO#getPermission()} + * value:MenuDO 数组,因为一个权限可能对应多个 MenuDO 对象 * * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ - private volatile Multimap permissionMenuCache; + private volatile Multimap permissionMenuCache; /** * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 */ private volatile Date maxUpdateTime; @Resource - private SysMenuMapper menuMapper; + private MenuMapper menuMapper; @Resource - private SysPermissionService permissionService; + private PermissionService permissionService; @Resource - private SysMenuProducer menuProducer; + private MenuProducer menuProducer; /** * 初始化 {@link #menuCache} 和 {@link #permissionMenuCache} 缓存 @@ -83,14 +81,14 @@ public class SysMenuServiceImpl implements SysMenuService { @PostConstruct public synchronized void initLocalCache() { // 获取菜单列表,如果有更新 - List menuList = this.loadMenuIfUpdate(maxUpdateTime); + List menuList = this.loadMenuIfUpdate(maxUpdateTime); if (CollUtil.isEmpty(menuList)) { return; } // 构建缓存 - ImmutableMap.Builder menuCacheBuilder = ImmutableMap.builder(); - ImmutableMultimap.Builder permMenuCacheBuilder = ImmutableMultimap.builder(); + ImmutableMap.Builder menuCacheBuilder = ImmutableMap.builder(); + ImmutableMultimap.Builder permMenuCacheBuilder = ImmutableMultimap.builder(); menuList.forEach(menuDO -> { menuCacheBuilder.put(menuDO.getId(), menuDO); permMenuCacheBuilder.put(menuDO.getPermission(), menuDO); @@ -114,7 +112,7 @@ public class SysMenuServiceImpl implements SysMenuService { * @param maxUpdateTime 当前菜单的最大更新时间 * @return 菜单列表 */ - private List loadMenuIfUpdate(Date maxUpdateTime) { + private List loadMenuIfUpdate(Date maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadMenuIfUpdate][首次加载全量菜单]"); @@ -129,13 +127,13 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public Long createMenu(SysMenuCreateReqVO reqVO) { + public Long createMenu(MenuCreateReqVO reqVO) { // 校验父菜单存在 checkParentResource(reqVO.getParentId(), null); // 校验菜单(自己) checkResource(reqVO.getParentId(), reqVO.getName(), null); // 插入数据库 - SysMenuDO menu = SysMenuConvert.INSTANCE.convert(reqVO); + MenuDO menu = MenuConvert.INSTANCE.convert(reqVO); initMenuProperty(menu); menuMapper.insert(menu); // 发送刷新消息 @@ -145,7 +143,7 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public void updateMenu(SysMenuUpdateReqVO reqVO) { + public void updateMenu(MenuUpdateReqVO reqVO) { // 校验更新的菜单是否存在 if (menuMapper.selectById(reqVO.getId()) == null) { throw ServiceExceptionUtil.exception(MENU_NOT_EXISTS); @@ -155,7 +153,7 @@ public class SysMenuServiceImpl implements SysMenuService { // 校验菜单(自己) checkResource(reqVO.getParentId(), reqVO.getName(), reqVO.getId()); // 更新到数据库 - SysMenuDO updateObject = SysMenuConvert.INSTANCE.convert(reqVO); + MenuDO updateObject = MenuConvert.INSTANCE.convert(reqVO); initMenuProperty(updateObject); menuMapper.updateById(updateObject); // 发送刷新消息 @@ -193,17 +191,17 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public List getMenus() { + public List getMenus() { return menuMapper.selectList(); } @Override - public List getMenus(SysMenuListReqVO reqVO) { + public List getMenus(MenuListReqVO reqVO) { return menuMapper.selectList(reqVO); } @Override - public List listMenusFromCache(Collection menuTypes, Collection menusStatuses) { + public List listMenusFromCache(Collection menuTypes, Collection menusStatuses) { // 任一一个参数为空,则返回空 if (CollectionUtils.isAnyEmpty(menuTypes, menusStatuses)) { return Collections.emptyList(); @@ -215,8 +213,8 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public List listMenusFromCache(Collection menuIds, Collection menuTypes, - Collection menusStatuses) { + public List listMenusFromCache(Collection menuIds, Collection menuTypes, + Collection menusStatuses) { // 任一一个参数为空,则返回空 if (CollectionUtils.isAnyEmpty(menuIds, menuTypes, menusStatuses)) { return Collections.emptyList(); @@ -228,12 +226,12 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public List getMenuListByPermissionFromCache(String permission) { + public List getMenuListByPermissionFromCache(String permission) { return new ArrayList<>(permissionMenuCache.get(permission)); } @Override - public SysMenuDO getMenu(Long id) { + public MenuDO getMenu(Long id) { return menuMapper.selectById(id); } @@ -256,7 +254,7 @@ public class SysMenuServiceImpl implements SysMenuService { if (parentId.equals(childId)) { throw ServiceExceptionUtil.exception(MENU_PARENT_ERROR); } - SysMenuDO menu = menuMapper.selectById(parentId); + MenuDO menu = menuMapper.selectById(parentId); // 父菜单不存在 if (menu == null) { throw ServiceExceptionUtil.exception(MENU_PARENT_NOT_EXISTS); @@ -279,7 +277,7 @@ public class SysMenuServiceImpl implements SysMenuService { */ @VisibleForTesting public void checkResource(Long parentId, String name, Long id) { - SysMenuDO menu = menuMapper.selectByParentIdAndName(parentId, name); + MenuDO menu = menuMapper.selectByParentIdAndName(parentId, name); if (menu == null) { return; } @@ -299,7 +297,7 @@ public class SysMenuServiceImpl implements SysMenuService { * * @param menu 菜单 */ - private void initMenuProperty(SysMenuDO menu) { + private void initMenuProperty(MenuDO menu) { // 菜单为按钮类型时,无需 component、icon、path 属性,进行置空 if (MenuTypeEnum.BUTTON.getType().equals(menu.getType())) { menu.setComponent(""); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java similarity index 86% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java index 78eeb9ad05..153eb71ac7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService; import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import org.springframework.lang.Nullable; import java.util.Collection; @@ -16,7 +16,7 @@ import java.util.Set; * * @author 芋道源码 */ -public interface SysPermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService { +public interface PermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService { /** * 初始化权限的本地缓存 @@ -33,8 +33,8 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService * @param menusStatuses 菜单状态数组 * @return 菜单列表 */ - List getRoleMenusFromCache(Collection roleIds, Collection menuTypes, - Collection menusStatuses); + List getRoleMenusFromCache(Collection roleIds, Collection menuTypes, + Collection menusStatuses); /** * 获得用户拥有的角色编号集合 @@ -77,14 +77,6 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService */ Set getUserRoleIdListByRoleId(Long roleId); - /** - * 获得拥有多个角色的用户编号集合 - * - * @param roleIds 角色编号集合 - * @return 用户编号集合 - */ - Set getUserRoleIdListByRoleIds(Collection roleIds); - /** * 设置用户角色 * @@ -123,4 +115,12 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService */ void processUserDeleted(Long userId); + /** + * 获得拥有多个角色的用户编号集合 + * + * @param roleIds 角色编号集合 + * @return 用户编号集合 + */ + Set getUserRoleIdListByRoleIds(Collection roleIds); + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java index 32f61c1d88..cb86bc7ada 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java @@ -1,20 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission.impl; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; +import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; +import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; +import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -43,12 +40,12 @@ import java.util.*; */ @Service("ss") // 使用 Spring Security 的缩写,方便食用 @Slf4j -public class SysPermissionServiceImpl implements SysPermissionService { +public class PermissionServiceImpl implements PermissionService { /** * LoginUser 的 Context 缓存 Key */ - public static final String CONTEXT_KEY = SysPermissionServiceImpl.class.getSimpleName(); + public static final String CONTEXT_KEY = PermissionServiceImpl.class.getSimpleName(); /** * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 @@ -78,19 +75,19 @@ public class SysPermissionServiceImpl implements SysPermissionService { private volatile Date maxUpdateTime; @Resource - private SysRoleMenuMapper roleMenuMapper; + private RoleMenuMapper roleMenuMapper; @Resource - private SysUserRoleMapper userRoleMapper; + private UserRoleMapper userRoleMapper; @Resource - private SysRoleService roleService; + private RoleService roleService; @Resource - private SysMenuService menuService; + private MenuService menuService; @Resource - private SysDeptService deptService; + private DeptService deptService; @Resource - private SysPermissionProducer permissionProducer; + private PermissionProducer permissionProducer; /** * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存 @@ -100,7 +97,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { public void initLocalCache() { Date now = new Date(); // 获取角色与菜单的关联列表,如果有更新 - List roleMenuList = this.loadRoleMenuIfUpdate(maxUpdateTime); + List roleMenuList = this.loadRoleMenuIfUpdate(maxUpdateTime); if (CollUtil.isEmpty(roleMenuList)) { return; } @@ -131,7 +128,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { * @param maxUpdateTime 当前角色与菜单的关联的最大更新时间 * @return 角色与菜单的关联列表 */ - private List loadRoleMenuIfUpdate(Date maxUpdateTime) { + private List loadRoleMenuIfUpdate(Date maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadRoleMenuIfUpdate][首次加载全量角色与菜单的关联]"); @@ -146,14 +143,14 @@ public class SysPermissionServiceImpl implements SysPermissionService { } @Override - public List getRoleMenusFromCache(Collection roleIds, Collection menuTypes, - Collection menusStatuses) { + public List getRoleMenusFromCache(Collection roleIds, Collection menuTypes, + Collection menusStatuses) { // 任一一个参数为空时,不返回任何菜单 if (CollectionUtils.isAnyEmpty(roleIds, menusStatuses, menusStatuses)) { return Collections.emptyList(); } // 判断角色是否包含管理员 - List roleList = roleService.getRolesFromCache(roleIds); + List roleList = roleService.getRolesFromCache(roleIds); boolean hasAdmin = roleService.hasAnyAdmin(roleList); // 获得角色拥有的菜单关联 if (hasAdmin) { // 管理员,获取到全部 @@ -165,27 +162,27 @@ public class SysPermissionServiceImpl implements SysPermissionService { @Override public Set getUserRoleIds(Long userId, Collection roleStatuses) { - List userRoleList = userRoleMapper.selectListByUserId(userId); + List userRoleList = userRoleMapper.selectListByUserId(userId); // 过滤角色状态 if (CollectionUtil.isNotEmpty(roleStatuses)) { userRoleList.removeIf(userRoleDO -> { - SysRoleDO role = roleService.getRoleFromCache(userRoleDO.getRoleId()); + RoleDO role = roleService.getRoleFromCache(userRoleDO.getRoleId()); return role == null || !roleStatuses.contains(role.getStatus()); }); } - return CollectionUtils.convertSet(userRoleList, SysUserRoleDO::getRoleId); + return CollectionUtils.convertSet(userRoleList, UserRoleDO::getRoleId); } @Override public Set listRoleMenuIds(Long roleId) { // 如果是管理员的情况下,获取全部菜单编号 - SysRoleDO role = roleService.getRole(roleId); + RoleDO role = roleService.getRole(roleId); if (roleService.hasAnyAdmin(Collections.singletonList(role))) { - return CollectionUtils.convertSet(menuService.getMenus(), SysMenuDO::getId); + return CollectionUtils.convertSet(menuService.getMenus(), MenuDO::getId); } // 如果是非管理员的情况下,获得拥有的菜单编号 return CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId), - SysRoleMenuDO::getMenuId); + RoleMenuDO::getMenuId); } @Override @@ -193,7 +190,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { public void assignRoleMenu(Long roleId, Set menuIds) { // 获得角色拥有菜单编号 Set dbMenuIds = CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId), - SysRoleMenuDO::getMenuId); + RoleMenuDO::getMenuId); // 计算新增和删除的菜单编号 Collection createMenuIds = CollUtil.subtract(menuIds, dbMenuIds); Collection deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds); @@ -218,26 +215,22 @@ public class SysPermissionServiceImpl implements SysPermissionService { @Override public Set getUserRoleIdListByUserId(Long userId) { return CollectionUtils.convertSet(userRoleMapper.selectListByUserId(userId), - SysUserRoleDO::getRoleId); + UserRoleDO::getRoleId); } @Override public Set getUserRoleIdListByRoleId(Long roleId) { return CollectionUtils.convertSet(userRoleMapper.selectListByRoleId(roleId), - SysUserRoleDO::getRoleId); + UserRoleDO::getRoleId); } - @Override - public Set getUserRoleIdListByRoleIds(Collection roleIds) { - return CollectionUtils.convertSet(userRoleMapper.selectListByRoleIds(roleIds), - SysUserRoleDO::getRoleId); - } + @Override public void assignUserRole(Long userId, Set roleIds) { // 获得角色拥有角色编号 Set dbRoleIds = CollectionUtils.convertSet(userRoleMapper.selectListByUserId(userId), - SysUserRoleDO::getRoleId); + UserRoleDO::getRoleId); // 计算新增和删除的角色编号 Collection createRoleIds = CollUtil.subtract(roleIds, dbRoleIds); Collection deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds); @@ -317,7 +310,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { // 遍历权限,判断是否有一个满足 return Arrays.stream(permissions).anyMatch(permission -> { - List menuList = menuService.getMenuListByPermissionFromCache(permission); + List menuList = menuService.getMenuListByPermissionFromCache(permission); // 采用严格模式,如果权限找不到对应的 Menu 的话,认为 if (CollUtil.isEmpty(menuList)) { return false; @@ -350,7 +343,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { return true; } Set userRoles = CollectionUtils.convertSet(roleService.getRolesFromCache(roleIds), - SysRoleDO::getCode); + RoleDO::getCode); return CollUtil.containsAny(userRoles, Sets.newHashSet(roles)); } @@ -364,8 +357,8 @@ public class SysPermissionServiceImpl implements SysPermissionService { // 创建 DeptDataPermissionRespDTO 对象 result = new DeptDataPermissionRespDTO(); - List roles = roleService.getRolesFromCache(loginUser.getRoleIds()); - for (SysRoleDO role : roles) { + List roles = roleService.getRolesFromCache(loginUser.getRoleIds()); + for (RoleDO role : roles) { // 为空时,跳过 if (role.getDataScope() == null) { continue; @@ -390,8 +383,8 @@ public class SysPermissionServiceImpl implements SysPermissionService { } // 情况四,DEPT_DEPT_AND_CHILD if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) { - List depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true); - CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, SysDeptDO::getId)); + List depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true); + CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, DeptDO::getId)); continue; } // 情况五,SELF @@ -408,4 +401,10 @@ public class SysPermissionServiceImpl implements SysPermissionService { return result; } + @Override + public Set getUserRoleIdListByRoleIds(Collection roleIds) { + return CollectionUtils.convertSet(userRoleMapper.selectListByRoleIds(roleIds), + UserRoleDO::getRoleId); + } + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java index 4272bab787..003ea62cc9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRolePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import org.springframework.lang.Nullable; import java.util.Collection; @@ -17,7 +17,7 @@ import java.util.Set; * * @author 芋道源码 */ -public interface SysRoleService { +public interface RoleService { /** * 初始化角色的本地缓存 @@ -30,14 +30,14 @@ public interface SysRoleService { * @param reqVO 创建角色信息 * @return 角色编号 */ - Long createRole(SysRoleCreateReqVO reqVO); + Long createRole(RoleCreateReqVO reqVO); /** * 更新角色 * * @param reqVO 更新角色信息 */ - void updateRole(SysRoleUpdateReqVO reqVO); + void updateRole(RoleUpdateReqVO reqVO); /** * 删除角色 @@ -69,7 +69,7 @@ public interface SysRoleService { * @param id 角色编号 * @return 角色 */ - SysRoleDO getRoleFromCache(Long id); + RoleDO getRoleFromCache(Long id); /** * 获得角色列表 @@ -77,7 +77,7 @@ public interface SysRoleService { * @param statuses 筛选的状态。允许空,空时不筛选 * @return 角色列表 */ - List getRoles(@Nullable Collection statuses); + List getRoles(@Nullable Collection statuses); /** * 获得角色数组,从缓存中 @@ -85,7 +85,7 @@ public interface SysRoleService { * @param ids 角色编号数组 * @return 角色数组 */ - List getRolesFromCache(Collection ids); + List getRolesFromCache(Collection ids); /** * 判断角色数组中,是否有管理员 @@ -93,7 +93,7 @@ public interface SysRoleService { * @param roleList 角色数组 * @return 是否有管理员 */ - boolean hasAnyAdmin(Collection roleList); + boolean hasAnyAdmin(Collection roleList); /** * 判断角色编号数组中,是否有管理员 @@ -111,7 +111,7 @@ public interface SysRoleService { * @param id 角色编号 * @return 角色 */ - SysRoleDO getRole(Long id); + RoleDO getRole(Long id); /** * 获得角色分页 @@ -119,7 +119,7 @@ public interface SysRoleService { * @param reqVO 角色分页查询 * @return 角色分页结果 */ - PageResult getRolePage(SysRolePageReqVO reqVO); + PageResult getRolePage(RolePageReqVO reqVO); /** * 获得角色列表 @@ -127,7 +127,7 @@ public interface SysRoleService { * @param reqVO 列表查询 * @return 角色列表 */ - List getRoleList(SysRoleExportReqVO reqVO); + List getRoleList(RoleExportReqVO reqVO); /** * 校验角色们是否有效。如下情况,视为无效: diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index 0c271c3a2d..48182a3f68 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -1,25 +1,22 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission.impl; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRolePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.permission.SysRoleConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.RoleCodeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.SysRoleTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.permission.RoleConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; +import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; +import cn.iocoder.yudao.module.system.mq.producer.permission.RoleProducer; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import lombok.extern.slf4j.Slf4j; @@ -34,11 +31,10 @@ import org.springframework.util.StringUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.*; -import java.util.function.Consumer; import java.util.stream.Collectors; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 角色 Service 实现类 @@ -47,7 +43,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU */ @Service @Slf4j -public class SysRoleServiceImpl implements SysRoleService { +public class RoleServiceImpl implements RoleService { /** * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 @@ -57,24 +53,24 @@ public class SysRoleServiceImpl implements SysRoleService { /** * 角色缓存 - * key:角色编号 {@link SysRoleDO#getId()} + * key:角色编号 {@link RoleDO#getId()} * * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 */ - private volatile Map roleCache; + private volatile Map roleCache; /** * 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新 */ private volatile Date maxUpdateTime; @Resource - private SysPermissionService permissionService; + private PermissionService permissionService; @Resource - private SysRoleMapper roleMapper; + private RoleMapper roleMapper; @Resource - private SysRoleProducer roleProducer; + private RoleProducer roleProducer; /** * 初始化 {@link #roleCache} 缓存 @@ -83,13 +79,13 @@ public class SysRoleServiceImpl implements SysRoleService { @PostConstruct public void initLocalCache() { // 获取角色列表,如果有更新 - List roleList = this.loadRoleIfUpdate(maxUpdateTime); + List roleList = this.loadRoleIfUpdate(maxUpdateTime); if (CollUtil.isEmpty(roleList)) { return; } // 写入缓存 - ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMap.Builder builder = ImmutableMap.builder(); roleList.forEach(sysRoleDO -> builder.put(sysRoleDO.getId(), sysRoleDO)); roleCache = builder.build(); assert roleList.size() > 0; // 断言,避免告警 @@ -109,7 +105,7 @@ public class SysRoleServiceImpl implements SysRoleService { * @param maxUpdateTime 当前角色的最大更新时间 * @return 角色列表 */ - private List loadRoleIfUpdate(Date maxUpdateTime) { + private List loadRoleIfUpdate(Date maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadRoleIfUpdate][首次加载全量角色]"); @@ -124,12 +120,12 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - public Long createRole(SysRoleCreateReqVO reqVO) { + public Long createRole(RoleCreateReqVO reqVO) { // 校验角色 checkDuplicateRole(reqVO.getName(), reqVO.getCode(), null); // 插入到数据库 - SysRoleDO role = SysRoleConvert.INSTANCE.convert(reqVO); - role.setType(SysRoleTypeEnum.CUSTOM.getType()); + RoleDO role = RoleConvert.INSTANCE.convert(reqVO); + role.setType(RoleTypeEnum.CUSTOM.getType()); role.setStatus(CommonStatusEnum.ENABLE.getStatus()); role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 roleMapper.insert(role); @@ -140,13 +136,13 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - public void updateRole(SysRoleUpdateReqVO reqVO) { + public void updateRole(RoleUpdateReqVO reqVO) { // 校验是否可以更新 this.checkUpdateRole(reqVO.getId()); // 校验角色的唯一字段是否重复 checkDuplicateRole(reqVO.getName(), reqVO.getCode(), reqVO.getId()); // 更新到数据库 - SysRoleDO updateObject = SysRoleConvert.INSTANCE.convert(reqVO); + RoleDO updateObject = RoleConvert.INSTANCE.convert(reqVO); roleMapper.updateById(updateObject); // 发送刷新消息 roleProducer.sendRoleRefreshMessage(); @@ -157,7 +153,7 @@ public class SysRoleServiceImpl implements SysRoleService { // 校验是否可以更新 this.checkUpdateRole(id); // 更新状态 - SysRoleDO updateObject = new SysRoleDO(); + RoleDO updateObject = new RoleDO(); updateObject.setId(id); updateObject.setStatus(status); roleMapper.updateById(updateObject); @@ -170,7 +166,7 @@ public class SysRoleServiceImpl implements SysRoleService { // 校验是否可以更新 checkUpdateRole(id); // 更新数据范围 - SysRoleDO updateObject = new SysRoleDO(); + RoleDO updateObject = new RoleDO(); updateObject.setId(id); updateObject.setDataScope(dataScope); updateObject.setDataScopeDeptIds(dataScopeDeptIds); @@ -200,17 +196,17 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - public SysRoleDO getRoleFromCache(Long id) { + public RoleDO getRoleFromCache(Long id) { return roleCache.get(id); } @Override - public List getRoles(@Nullable Collection statuses) { + public List getRoles(@Nullable Collection statuses) { return roleMapper.selectListByStatus(statuses); } @Override - public List getRolesFromCache(Collection ids) { + public List getRolesFromCache(Collection ids) { if (CollectionUtil.isEmpty(ids)) { return Collections.emptyList(); } @@ -219,7 +215,7 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - public boolean hasAnyAdmin(Collection roleList) { + public boolean hasAnyAdmin(Collection roleList) { if (CollectionUtil.isEmpty(roleList)) { return false; } @@ -227,40 +223,20 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - public SysRoleDO getRole(Long id) { + public RoleDO getRole(Long id) { return roleMapper.selectById(id); } @Override - public PageResult getRolePage(SysRolePageReqVO reqVO) { + public PageResult getRolePage(RolePageReqVO reqVO) { return roleMapper.selectPage(reqVO); } @Override - public List getRoleList(SysRoleExportReqVO reqVO) { + public List getRoleList(RoleExportReqVO reqVO) { return roleMapper.listRoles(reqVO); } - @Override - public void validRoles(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return; - } - // 获得角色信息 - List roles = roleMapper.selectBatchIds(ids); - Map roleMap = CollectionUtils.convertMap(roles, SysRoleDO::getId); - // 校验 - ids.forEach(id -> { - SysRoleDO role = roleMap.get(id); - if (role == null) { - throw exception(ROLE_NOT_EXISTS); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) { - throw exception(ROLE_IS_DISABLE, role.getName()); - } - }); - } - /** * 校验角色的唯一字段是否重复 * @@ -274,7 +250,7 @@ public class SysRoleServiceImpl implements SysRoleService { @VisibleForTesting public void checkDuplicateRole(String name, String code, Long id) { // 1. 该 name 名字被其它角色所使用 - SysRoleDO role = roleMapper.selectByName(name); + RoleDO role = roleMapper.selectByName(name); if (role != null && !role.getId().equals(id)) { throw exception(ROLE_NAME_DUPLICATE, name); } @@ -296,14 +272,33 @@ public class SysRoleServiceImpl implements SysRoleService { */ @VisibleForTesting public void checkUpdateRole(Long id) { - SysRoleDO roleDO = roleMapper.selectById(id); + RoleDO roleDO = roleMapper.selectById(id); if (roleDO == null) { throw exception(ROLE_NOT_EXISTS); } // 内置角色,不允许删除 - if (SysRoleTypeEnum.SYSTEM.getType().equals(roleDO.getType())) { + if (RoleTypeEnum.SYSTEM.getType().equals(roleDO.getType())) { throw exception(ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); } } + @Override + public void validRoles(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得角色信息 + List roles = roleMapper.selectBatchIds(ids); + Map roleMap = CollectionUtils.convertMap(roles, RoleDO::getId); + // 校验 + ids.forEach(id -> { + RoleDO role = roleMap.get(id); + if (role == null) { + throw exception(ROLE_NOT_EXISTS); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) { + throw exception(ROLE_IS_DISABLE, role.getName()); + } + }); + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java similarity index 54% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java index 0a7220a791..50e13a6025 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; import javax.validation.Valid; import java.util.Collection; @@ -16,7 +16,7 @@ import java.util.List; * @author zzf * @date 2021/1/25 9:24 */ -public interface SysSmsChannelService { +public interface SmsChannelService { /** * 初始化短信客户端 @@ -29,14 +29,14 @@ public interface SysSmsChannelService { * @param createReqVO 创建信息 * @return 编号 */ - Long createSmsChannel(@Valid SysSmsChannelCreateReqVO createReqVO); + Long createSmsChannel(@Valid SmsChannelCreateReqVO createReqVO); /** * 更新短信渠道 * * @param updateReqVO 更新信息 */ - void updateSmsChannel(@Valid SysSmsChannelUpdateReqVO updateReqVO); + void updateSmsChannel(@Valid SmsChannelUpdateReqVO updateReqVO); /** * 删除短信渠道 @@ -51,7 +51,7 @@ public interface SysSmsChannelService { * @param id 编号 * @return 短信渠道 */ - SysSmsChannelDO getSmsChannel(Long id); + SmsChannelDO getSmsChannel(Long id); /** * 获得短信渠道列表 @@ -59,14 +59,14 @@ public interface SysSmsChannelService { * @param ids 编号 * @return 短信渠道列表 */ - List getSmsChannelList(Collection ids); + List getSmsChannelList(Collection ids); /** * 获得所有短信渠道列表 * * @return 短信渠道列表 */ - List getSmsChannelList(); + List getSmsChannelList(); /** * 获得短信渠道分页 @@ -74,6 +74,6 @@ public interface SysSmsChannelService { * @param pageReqVO 分页查询 * @return 短信渠道分页 */ - PageResult getSmsChannelPage(SysSmsChannelPageReqVO pageReqVO); + PageResult getSmsChannelPage(SmsChannelPageReqVO pageReqVO); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java similarity index 66% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java index 59f2a9a307..f1fd44a901 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/impl/SysSmsChannelServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java @@ -1,15 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms.impl; +package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.convert.sms.SysSmsChannelConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsChannelMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsChannelService; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.SysSmsTemplateService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.sms.SmsChannelConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; @@ -25,8 +23,8 @@ import java.util.Comparator; import java.util.Date; import java.util.List; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; /** @@ -37,7 +35,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU */ @Service @Slf4j -public class SysSmsChannelServiceImpl implements SysSmsChannelService { +public class SmsChannelServiceImpl implements SmsChannelService { /** * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 @@ -54,25 +52,25 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { private SmsClientFactory smsClientFactory; @Resource - private SysSmsChannelMapper smsChannelMapper; + private SmsChannelMapper smsChannelMapper; @Resource - private SysSmsTemplateService smsTemplateService; + private SmsTemplateService smsTemplateService; @Resource - private SysSmsProducer smsProducer; + private SmsProducer smsProducer; @Override @PostConstruct public void initSmsClients() { // 获取短信渠道,如果有更新 - List smsChannels = this.loadSmsChannelIfUpdate(maxUpdateTime); + List smsChannels = this.loadSmsChannelIfUpdate(maxUpdateTime); if (CollUtil.isEmpty(smsChannels)) { return; } // 创建或更新短信 Client - List propertiesList = SysSmsChannelConvert.INSTANCE.convertList02(smsChannels); + List propertiesList = SmsChannelConvert.INSTANCE.convertList02(smsChannels); propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); // 写入缓存 @@ -93,7 +91,7 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { * @param maxUpdateTime 当前短信渠道的最大更新时间 * @return 短信渠道列表 */ - private List loadSmsChannelIfUpdate(Date maxUpdateTime) { + private List loadSmsChannelIfUpdate(Date maxUpdateTime) { // 第一步,判断是否要更新。 if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 log.info("[loadSmsChannelIfUpdate][首次加载全量短信渠道]"); @@ -108,9 +106,9 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { } @Override - public Long createSmsChannel(SysSmsChannelCreateReqVO createReqVO) { + public Long createSmsChannel(SmsChannelCreateReqVO createReqVO) { // 插入 - SysSmsChannelDO smsChannel = SysSmsChannelConvert.INSTANCE.convert(createReqVO); + SmsChannelDO smsChannel = SmsChannelConvert.INSTANCE.convert(createReqVO); smsChannelMapper.insert(smsChannel); // 发送刷新消息 smsProducer.sendSmsChannelRefreshMessage(); @@ -119,11 +117,11 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { } @Override - public void updateSmsChannel(SysSmsChannelUpdateReqVO updateReqVO) { + public void updateSmsChannel(SmsChannelUpdateReqVO updateReqVO) { // 校验存在 this.validateSmsChannelExists(updateReqVO.getId()); // 更新 - SysSmsChannelDO updateObj = SysSmsChannelConvert.INSTANCE.convert(updateReqVO); + SmsChannelDO updateObj = SmsChannelConvert.INSTANCE.convert(updateReqVO); smsChannelMapper.updateById(updateObj); // 发送刷新消息 smsProducer.sendSmsChannelRefreshMessage(); @@ -150,22 +148,22 @@ public class SysSmsChannelServiceImpl implements SysSmsChannelService { } @Override - public SysSmsChannelDO getSmsChannel(Long id) { + public SmsChannelDO getSmsChannel(Long id) { return smsChannelMapper.selectById(id); } @Override - public List getSmsChannelList(Collection ids) { + public List getSmsChannelList(Collection ids) { return smsChannelMapper.selectBatchIds(ids); } @Override - public List getSmsChannelList() { + public List getSmsChannelList() { return smsChannelMapper.selectList(); } @Override - public PageResult getSmsChannelPage(SysSmsChannelPageReqVO pageReqVO) { + public PageResult getSmsChannelPage(SmsChannelPageReqVO pageReqVO) { return smsChannelMapper.selectPage(pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java new file mode 100644 index 0000000000..f71b8a6bdf --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; + +import javax.validation.Valid; + +/** + * 短信验证码 Service 接口 + * + * @author 芋道源码 + */ +public interface SmsCodeService { + + /** + * 创建短信验证码,并进行发送 + * + * @param reqDTO 发送请求 + */ + void sendSmsCode(@Valid SmsCodeSendReqDTO reqDTO); + + /** + * 验证短信验证码,并进行使用 + * 如果正确,则将验证码标记成已使用 + * 如果错误,则抛出 {@link ServiceException} 异常 + * + * @param reqDTO 使用请求 + */ + void useSmsCode(@Valid SmsCodeUseReqDTO reqDTO); + + /** + * 检查验证码是否有效 + * + * @param reqDTO 校验请求 + */ + void checkSmsCode(@Valid SmsCodeCheckReqDTO reqDTO); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java new file mode 100644 index 0000000000..c1d366584d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import cn.iocoder.yudao.module.system.framework.sms.SmsCodeProperties; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Date; + +import static cn.hutool.core.util.RandomUtil.randomInt; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; + +/** + * 短信验证码 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class SmsCodeServiceImpl implements SmsCodeService { + + @Resource + private SmsCodeProperties smsCodeProperties; + + @Resource + private SmsCodeMapper smsCodeMapper; + + @Resource + private SmsSendService smsSendService; + + @Override + public void sendSmsCode(SmsCodeSendReqDTO reqDTO) { + SmsSceneEnum sceneEnum = SmsSceneEnum.getCodeByScene(reqDTO.getScene()); + Assert.notNull(sceneEnum, "验证码场景({}) 查找不到配置", reqDTO.getScene()); + // 创建验证码 + String code = createSmsCode(reqDTO.getMobile(), reqDTO.getScene(), reqDTO.getCreateIp()); + // 发送验证码 + smsSendService.sendSingleSms(reqDTO.getMobile(), null, null, + sceneEnum.getTemplateCode(), MapUtil.of("code", code)); + } + + private String createSmsCode(String mobile, Integer scene, String ip) { + // 校验是否可以发送验证码,不用筛选场景 + SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null,null); + if (lastSmsCode != null) { + if (lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。 + throw ServiceExceptionUtil.exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); + } + if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime() + < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁 + throw ServiceExceptionUtil.exception(SMS_CODE_SEND_TOO_FAST); + } + // TODO 芋艿:提升,每个 IP 每天可发送数量 + // TODO 芋艿:提升,每个 IP 每小时可发送数量 + } + + // 创建验证码记录 + String code = String.valueOf(randomInt(smsCodeProperties.getBeginCode(), smsCodeProperties.getEndCode() + 1)); + SmsCodeDO newSmsCode = SmsCodeDO.builder().mobile(mobile).code(code) + .scene(scene).todayIndex(lastSmsCode != null ? lastSmsCode.getTodayIndex() + 1 : 1) + .createIp(ip).used(false).build(); + smsCodeMapper.insert(newSmsCode); + return code; + } + + @Override + public void useSmsCode(SmsCodeUseReqDTO reqDTO) { + // 检测验证码是否有效 + SmsCodeDO lastSmsCode = this.checkSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); + // 使用验证码 + smsCodeMapper.updateById(SmsCodeDO.builder().id(lastSmsCode.getId()) + .used(true).usedTime(new Date()).usedIp(reqDTO.getUsedIp()).build()); + } + + @Override + public void checkSmsCode(SmsCodeCheckReqDTO reqDTO) { + checkSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); + } + + public SmsCodeDO checkSmsCode0(String mobile, String code, Integer scene) { + // 校验验证码 + SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile,code,scene); + // 若验证码不存在,抛出异常 + if (lastSmsCode == null) { + throw ServiceExceptionUtil.exception(SMS_CODE_NOT_FOUND); + } + // 超过时间 + if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime() + >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期 + throw ServiceExceptionUtil.exception(SMS_CODE_EXPIRED); + } + // 判断验证码是否已被使用 + if (Boolean.TRUE.equals(lastSmsCode.getUsed())) { + throw ServiceExceptionUtil.exception(SMS_CODE_USED); + } + return lastSmsCode; + } + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java similarity index 60% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java index 02a8c26960..2932949ee8 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsLogCoreService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java @@ -1,17 +1,22 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import java.util.Date; +import java.util.List; import java.util.Map; /** - * 短信日志 Core Service 接口 + * 短信日志 Service 接口 * * @author zzf * @date 13:48 2021/3/2 */ -public interface SysSmsLogCoreService { +public interface SmsLogService { /** * 创建短信日志 @@ -26,7 +31,7 @@ public interface SysSmsLogCoreService { * @return 发送日志编号 */ Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend, - SysSmsTemplateDO template, String templateContent, Map templateParams); + SmsTemplateDO template, String templateContent, Map templateParams); /** * 更新日志的发送结果 @@ -53,4 +58,20 @@ public interface SysSmsLogCoreService { */ void updateSmsReceiveResult(Long id, Boolean success, Date receiveTime, String apiReceiveCode, String apiReceiveMsg); + /** + * 获得短信日志分页 + * + * @param pageReqVO 分页查询 + * @return 短信日志分页 + */ + PageResult getSmsLogPage(SmsLogPageReqVO pageReqVO); + + /** + * 获得短信日志列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 短信日志列表 + */ + List getSmsLogList(SmsLogExportReqVO exportReqVO); + } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java new file mode 100644 index 0000000000..a5abf4003a --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 短信日志 Service 实现类 + * + * @author zzf + */ +@Slf4j +@Service +public class SmsLogServiceImpl implements SmsLogService { + + @Resource + private SmsLogMapper smsLogMapper; + + @Override + public Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend, + SmsTemplateDO template, String templateContent, Map templateParams) { + SmsLogDO.SmsLogDOBuilder logBuilder = SmsLogDO.builder(); + // 根据是否要发送,设置状态 + logBuilder.sendStatus(Objects.equals(isSend, true) ? SmsSendStatusEnum.INIT.getStatus() + : SmsSendStatusEnum.IGNORE.getStatus()); + // 设置手机相关字段 + logBuilder.mobile(mobile).userId(userId).userType(userType); + // 设置模板相关字段 + logBuilder.templateId(template.getId()).templateCode(template.getCode()).templateType(template.getType()); + logBuilder.templateContent(templateContent).templateParams(templateParams) + .apiTemplateId(template.getApiTemplateId()); + // 设置渠道相关字段 + logBuilder.channelId(template.getChannelId()).channelCode(template.getChannelCode()); + // 设置接收相关字段 + logBuilder.receiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + + // 插入数据库 + SmsLogDO logDO = logBuilder.build(); + smsLogMapper.insert(logDO); + return logDO.getId(); + } + + @Override + public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, + String apiSendCode, String apiSendMsg, + String apiRequestId, String apiSerialNo) { + SmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? + SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; + smsLogMapper.updateById(SmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()) + .sendTime(new Date()).sendCode(sendCode).sendMsg(sendMsg) + .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) + .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); + } + + @Override + public void updateSmsReceiveResult(Long id, Boolean success, Date receiveTime, + String apiReceiveCode, String apiReceiveMsg) { + SmsReceiveStatusEnum receiveStatus = Objects.equals(success, true) ? + SmsReceiveStatusEnum.SUCCESS : SmsReceiveStatusEnum.FAILURE; + smsLogMapper.updateById(SmsLogDO.builder().id(id).receiveStatus(receiveStatus.getStatus()) + .receiveTime(receiveTime).apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build()); + } + + @Override + public PageResult getSmsLogPage(SmsLogPageReqVO pageReqVO) { + return smsLogMapper.selectPage(pageReqVO); + } + + @Override + public List getSmsLogList(SmsLogExportReqVO exportReqVO) { + return smsLogMapper.selectList(exportReqVO); + } + +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendService.java similarity index 56% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendService.java index 55f4d41e00..3c42cf58ea 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendService.java @@ -1,22 +1,19 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; import java.util.List; import java.util.Map; /** - * 短信 Service Core 接口 - * - * 接入方,通过调用 send 开头的方法,创建发送短信的任务到 MQ 中 - * 后续,yudao-admin-server 监听 MQ,执行真正的短信发送逻辑 + * 短信发送 Service 接口 * * @author 芋道源码 */ -public interface SysSmsCoreService { +public interface SmsSendService { /** - * 发送单条短信给后台用户 + * 发送单条短信给管理后台的用户 * * 在 mobile 为空时,使用 userId 加载对应管理员的手机号 * @@ -30,7 +27,7 @@ public interface SysSmsCoreService { String templateCode, Map templateParams); /** - * 发送单条短信给前台用户 + * 发送单条短信给用户 APP 的用户 * * 在 mobile 为空时,使用 userId 加载对应会员的手机号 * @@ -43,13 +40,31 @@ public interface SysSmsCoreService { Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map templateParams); + /** + * 发送单条短信给用户 + * + * @param mobile 手机号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param templateCode 短信模板编号 + * @param templateParams 短信模板参数 + * @return 发送日志编号 + */ Long sendSingleSms(String mobile, Long userId, Integer userType, String templateCode, Map templateParams); - void sendBatchSms(List mobiles, List userIds, Integer userType, - String templateCode, Map templateParams); + default void sendBatchSms(List mobiles, List userIds, Integer userType, + String templateCode, Map templateParams) { + throw new UnsupportedOperationException("暂时不支持该操作,感兴趣可以实现该功能哟!"); + } - void doSendSms(SysSmsSendMessage message); + /** + * 执行真正的短信发送 + * 注意,该方法仅仅提供给 MQ Consumer 使用 + * + * @param message 短信 + */ + void doSendSms(SmsSendMessage message); /** * 接收短信的接收结果 diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsCoreServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java similarity index 65% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsCoreServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java index 3893ba3403..538e0f925f 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsCoreServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java @@ -1,17 +1,7 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms.impl; +package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; -import cn.iocoder.yudao.coreservice.modules.member.service.user.MbrUserCoreService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; -import cn.iocoder.yudao.coreservice.modules.system.mq.producer.sms.SysSmsCoreProducer; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsTemplateCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -20,6 +10,13 @@ import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.google.common.annotations.VisibleForTesting; import org.springframework.stereotype.Service; import org.springframework.util.Assert; @@ -29,37 +26,38 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** - * 短信 Service Core 实现 + * 短信发送 Service 发送的实现 * * @author 芋道源码 */ @Service -public class SysSmsCoreServiceImpl implements SysSmsCoreService { +public class SmsSendServiceImpl implements SmsSendService { @Resource - private SysUserCoreService sysUserCoreService; + private AdminUserService adminUserService; @Resource - private MbrUserCoreService mbrUserCoreService; + private MemberUserApi memberUserApi; + @Resource - private SysSmsTemplateCoreService smsTemplateCoreService; + private SmsTemplateService smsTemplateService; @Resource - private SysSmsLogCoreService smsLogCoreService; + private SmsLogService smsLogService; @Resource private SmsClientFactory smsClientFactory; @Resource - private SysSmsCoreProducer smsCoreProducer; + private SmsProducer smsProducer; @Override public Long sendSingleSmsToAdmin(String mobile, Long userId, String templateCode, Map templateParams) { // 如果 mobile 为空,则加载用户编号对应的手机号 if (StrUtil.isEmpty(mobile)) { - SysUserDO user = sysUserCoreService.getUser(userId); + AdminUserDO user = adminUserService.getUser(userId); if (user != null) { mobile = user.getMobile(); } @@ -72,7 +70,7 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map templateParams) { // 如果 mobile 为空,则加载用户编号对应的手机号 if (StrUtil.isEmpty(mobile)) { - MbrUserDO user = mbrUserCoreService.getUser(userId); + UserRespDTO user = memberUserApi.getUser(userId); if (user != null) { mobile = user.getMobile(); } @@ -85,35 +83,30 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { public Long sendSingleSms(String mobile, Long userId, Integer userType, String templateCode, Map templateParams) { // 校验短信模板是否合法 - SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode); + SmsTemplateDO template = this.checkSmsTemplateValid(templateCode); // 校验手机号码是否存在 mobile = this.checkMobile(mobile); // 构建有序的模板参数。为什么放在这个位置,是提前保证模板参数的正确性,而不是到了插入发送日志 List> newTemplateParams = this.buildTemplateParams(template, templateParams); - // 创建发送日志 - Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); // 如果模板被禁用,则不发送短信,只记录日志 - String content = smsTemplateCoreService.formatSmsTemplateContent(template.getContent(), templateParams); - Long sendLogId = smsLogCoreService.createSmsLog(mobile, userId, userType, isSend, template, content, templateParams); + // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 + Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); + String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams); + Long sendLogId = smsLogService.createSmsLog(mobile, userId, userType, isSend, template, content, templateParams); // 发送 MQ 消息,异步执行发送短信 if (isSend) { - smsCoreProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), + smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), template.getApiTemplateId(), newTemplateParams); } return sendLogId; } - @Override - public void sendBatchSms(List mobiles, List userIds, Integer userType, - String templateCode, Map templateParams) { - throw new UnsupportedOperationException("暂时不支持该操作,感兴趣可以实现该功能哟!"); - } @VisibleForTesting - public SysSmsTemplateDO checkSmsTemplateValid(String templateCode) { + public SmsTemplateDO checkSmsTemplateValid(String templateCode) { // 获得短信模板。考虑到效率,从缓存中获取 - SysSmsTemplateDO template = smsTemplateCoreService.getSmsTemplateByCodeFromCache(templateCode); + SmsTemplateDO template = smsTemplateService.getSmsTemplateByCodeFromCache(templateCode); // 短信模板不存在 if (template == null) { throw exception(SMS_SEND_TEMPLATE_NOT_EXISTS); @@ -131,7 +124,7 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { * @return 处理后的参数 */ @VisibleForTesting - public List> buildTemplateParams(SysSmsTemplateDO template, Map templateParams) { + public List> buildTemplateParams(SmsTemplateDO template, Map templateParams) { return template.getParams().stream().map(key -> { Object value = templateParams.get(key); if (value == null) { @@ -149,16 +142,15 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { return mobile; } - @Override - public void doSendSms(SysSmsSendMessage message) { + public void doSendSms(SmsSendMessage message) { // 获得渠道对应的 SmsClient 客户端 SmsClient smsClient = smsClientFactory.getSmsClient(message.getChannelId()); Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", message.getChannelId())); // 发送短信 SmsCommonResult sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(), message.getApiTemplateId(), message.getTemplateParams()); - smsLogCoreService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), + smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), sendResult.getData() != null ? sendResult.getData().getSerialNo() : null); } @@ -174,7 +166,7 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { return; } // 更新短信日志的接收结果. 因为量一般不大,所以先使用 for 循环更新 - receiveResults.forEach(result -> smsLogCoreService.updateSmsReceiveResult(result.getLogId(), + receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(result.getLogId(), result.getSuccess(), result.getReceiveTime(), result.getErrorCode(), result.getErrorCode())); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java new file mode 100644 index 0000000000..eaa6550665 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java @@ -0,0 +1,115 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 短信模板 Service 接口 + * + * @author zzf + * @date 2021/1/25 9:24 + */ +public interface SmsTemplateService { + + /** + * 初始化短信模板的本地缓存 + */ + void initLocalCache(); + + /** + * 获得短信模板,从缓存中 + * + * @param code 模板编码 + * @return 短信模板 + */ + SmsTemplateDO getSmsTemplateByCodeFromCache(String code); + + /** + * 格式化短信内容 + * + * @param content 短信模板的内容 + * @param params 内容的参数 + * @return 格式化后的内容 + */ + String formatSmsTemplateContent(String content, Map params); + + /** + * 获得短信模板 + * + * @param code 模板编码 + * @return 短信模板 + */ + SmsTemplateDO getSmsTemplateByCode(String code); + + /** + * 创建短信模板 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSmsTemplate(@Valid SmsTemplateCreateReqVO createReqVO); + + /** + * 更新短信模板 + * + * @param updateReqVO 更新信息 + */ + void updateSmsTemplate(@Valid SmsTemplateUpdateReqVO updateReqVO); + + /** + * 删除短信模板 + * + * @param id 编号 + */ + void deleteSmsTemplate(Long id); + + /** + * 获得短信模板 + * + * @param id 编号 + * @return 短信模板 + */ + SmsTemplateDO getSmsTemplate(Long id); + + /** + * 获得短信模板列表 + * + * @param ids 编号 + * @return 短信模板列表 + */ + List getSmsTemplateList(Collection ids); + + /** + * 获得短信模板分页 + * + * @param pageReqVO 分页查询 + * @return 短信模板分页 + */ + PageResult getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO); + + /** + * 获得短信模板列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 短信模板分页 + */ + List getSmsTemplateList(SmsTemplateExportReqVO exportReqVO); + + /** + * 获得指定短信渠道下的短信模板数量 + * + * @param channelId 短信渠道编号 + * @return 数量 + */ + Integer countByChannelId(Long channelId); + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java new file mode 100644 index 0000000000..ce8e71435d --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java @@ -0,0 +1,270 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.sms.SmsTemplateConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.*; +import java.util.regex.Pattern; + +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + +/** + * 短信模板 Service 实现类 + * + * @author zzf + * @date 2021/1/25 9:25 + */ +@Service +@Slf4j +public class SmsTemplateServiceImpl implements SmsTemplateService { + + /** + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 + */ + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; + + /** + * 正则表达式,匹配 {} 中的变量 + */ + private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); + + @Resource + private SmsTemplateMapper smsTemplateMapper; + + @Resource + private SmsChannelService smsChannelService; + + @Resource + private SmsClientFactory smsClientFactory; + + @Resource + private SmsProducer smsProducer; + + /** + * 短信模板缓存 + * key:短信模板编码 {@link SmsTemplateDO#getCode()} + * + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 + */ + private volatile Map smsTemplateCache; + /** + * 缓存短信模板的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private volatile Date maxUpdateTime; + + @Override + @PostConstruct + public void initLocalCache() { + // 获取短信模板列表,如果有更新 + List smsTemplateList = this.loadSmsTemplateIfUpdate(maxUpdateTime); + if (CollUtil.isEmpty(smsTemplateList)) { + return; + } + + // 写入缓存 + ImmutableMap.Builder builder = ImmutableMap.builder(); + smsTemplateList.forEach(sysSmsTemplateDO -> builder.put(sysSmsTemplateDO.getCode(), sysSmsTemplateDO)); + smsTemplateCache = builder.build(); + assert smsTemplateList.size() > 0; // 断言,避免告警 + maxUpdateTime = smsTemplateList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime(); + log.info("[initLocalCache][初始化 SmsTemplate 数量为 {}]", smsTemplateList.size()); + } + + /** + * 如果短信模板发生变化,从数据库中获取最新的全量短信模板。 + * 如果未发生变化,则返回空 + * + * @param maxUpdateTime 当前短信模板的最大更新时间 + * @return 短信模板列表 + */ + private List loadSmsTemplateIfUpdate(Date maxUpdateTime) { + // 第一步,判断是否要更新。 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 + log.info("[loadSmsTemplateIfUpdate][首次加载全量短信模板]"); + } else { // 判断数据库中是否有更新的短信模板 + if (smsTemplateMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) { + return null; + } + log.info("[loadSmsTemplateIfUpdate][增量加载全量短信模板]"); + } + // 第二步,如果有更新,则从数据库加载所有短信模板 + return smsTemplateMapper.selectList(); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCache(); + } + + @Override + public SmsTemplateDO getSmsTemplateByCodeFromCache(String code) { + return smsTemplateCache.get(code); + } + + @Override + public String formatSmsTemplateContent(String content, Map params) { + return StrUtil.format(content, params); + } + + @Override + public SmsTemplateDO getSmsTemplateByCode(String code) { + return smsTemplateMapper.selectByCode(code); + } + + @VisibleForTesting + public List parseTemplateContentParams(String content) { + return ReUtil.findAllGroup1(PATTERN_PARAMS, content); + } + + @Override + public Long createSmsTemplate(SmsTemplateCreateReqVO createReqVO) { + // 校验短信渠道 + SmsChannelDO channelDO = checkSmsChannel(createReqVO.getChannelId()); + // 校验短信编码是否重复 + checkSmsTemplateCodeDuplicate(null, createReqVO.getCode()); + // 校验短信模板 + checkApiTemplate(createReqVO.getChannelId(), createReqVO.getApiTemplateId()); + + // 插入 + SmsTemplateDO template = SmsTemplateConvert.INSTANCE.convert(createReqVO); + template.setParams(parseTemplateContentParams(template.getContent())); + template.setChannelCode(channelDO.getCode()); + smsTemplateMapper.insert(template); + // 发送刷新消息 + smsProducer.sendSmsTemplateRefreshMessage(); + // 返回 + return template.getId(); + } + + @Override + public void updateSmsTemplate(SmsTemplateUpdateReqVO updateReqVO) { + // 校验存在 + this.validateSmsTemplateExists(updateReqVO.getId()); + // 校验短信渠道 + SmsChannelDO channelDO = checkSmsChannel(updateReqVO.getChannelId()); + // 校验短信编码是否重复 + checkSmsTemplateCodeDuplicate(updateReqVO.getId(), updateReqVO.getCode()); + // 校验短信模板 + checkApiTemplate(updateReqVO.getChannelId(), updateReqVO.getApiTemplateId()); + + // 更新 + SmsTemplateDO updateObj = SmsTemplateConvert.INSTANCE.convert(updateReqVO); + updateObj.setParams(parseTemplateContentParams(updateObj.getContent())); + updateObj.setChannelCode(channelDO.getCode()); + smsTemplateMapper.updateById(updateObj); + // 发送刷新消息 + smsProducer.sendSmsTemplateRefreshMessage(); + } + + @Override + public void deleteSmsTemplate(Long id) { + // 校验存在 + this.validateSmsTemplateExists(id); + // 更新 + smsTemplateMapper.deleteById(id); + // 发送刷新消息 + smsProducer.sendSmsTemplateRefreshMessage(); + } + + private void validateSmsTemplateExists(Long id) { + if (smsTemplateMapper.selectById(id) == null) { + throw exception(SMS_TEMPLATE_NOT_EXISTS); + } + } + + @Override + public SmsTemplateDO getSmsTemplate(Long id) { + return smsTemplateMapper.selectById(id); + } + + @Override + public List getSmsTemplateList(Collection ids) { + return smsTemplateMapper.selectBatchIds(ids); + } + + @Override + public PageResult getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO) { + return smsTemplateMapper.selectPage(pageReqVO); + } + + @Override + public List getSmsTemplateList(SmsTemplateExportReqVO exportReqVO) { + return smsTemplateMapper.selectList(exportReqVO); + } + + @Override + public Integer countByChannelId(Long channelId) { + return smsTemplateMapper.selectCountByChannelId(channelId); + } + + @VisibleForTesting + public SmsChannelDO checkSmsChannel(Long channelId) { + SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId); + if (channelDO == null) { + throw exception(SMS_CHANNEL_NOT_EXISTS); + } + if (!Objects.equals(channelDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + throw exception(SMS_CHANNEL_DISABLE); + } + return channelDO; + } + + @VisibleForTesting + public void checkSmsTemplateCodeDuplicate(Long id, String code) { + SmsTemplateDO template = smsTemplateMapper.selectByCode(code); + if (template == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 + if (id == null) { + throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code); + } + if (!template.getId().equals(id)) { + throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code); + } + } + + /** + * 校验 API 短信平台的模板是否有效 + * + * @param channelId 渠道编号 + * @param apiTemplateId API 模板编号 + */ + @VisibleForTesting + public void checkApiTemplate(Long channelId, String apiTemplateId) { + // 获得短信模板 + SmsClient smsClient = smsClientFactory.getSmsClient(channelId); + Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); + SmsCommonResult templateResult = smsClient.getSmsTemplate(apiTemplateId); + // 校验短信模板是否正确 + templateResult.checkError(); + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java new file mode 100644 index 0000000000..f57baff0d3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.system.service.social; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import me.zhyd.oauth.model.AuthUser; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 社交用户 Service 接口,例如说社交平台的授权登录 + * + * @author 芋道源码 + */ +public interface SocialUserService { + + /** + * 获得社交平台的授权 URL + * + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param redirectUri 重定向 URL + * @return 社交平台的授权 URL + */ + String getAuthorizeUrl(Integer type, String redirectUri); + + /** + * 获得授权的用户 + * 如果授权失败,则会抛出 {@link ServiceException} 异常 + * + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param code 授权码 + * @param state state + * @return 授权用户 + */ + @NotNull + AuthUser getAuthUser(Integer type, String code, String state); + + /** + * 获得社交用户的 unionId 编号 + * + * @param authUser 社交用户 + * @return unionId 编号 + */ + default String getAuthUserUnionId(AuthUser authUser) { + return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid()); + } + + /** + * 获得指定用户的社交用户列表 + * + * @param userId 用户编号 + * @param userType 用户类型 + * @return 社交用户列表 + */ + List getSocialUserList(Long userId, Integer userType); + + /** + * 绑定社交用户 + * + * @param reqDTO 绑定信息 + */ + void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); + + /** + * 取消绑定社交用户 + * + * @param userId 用户编号 + * @param userType 全局用户类型 + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param unionId 社交平台的 unionId + */ + void unbindSocialUser(Long userId, Integer userType, Integer type, String unionId); + + /** + * 校验社交用户的认证信息是否正确 + * 如果校验不通过,则抛出 {@link ServiceException} 业务异常 + * + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + */ + void checkSocialUser(Integer type, String code, String state); + + /** + * 获得社交用户的绑定用户编号 + * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 该方法会执行和 {@link #checkSocialUser(Integer, String, String)} 一样的逻辑。 + * 所以在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 + * + * @param userType 用户类型 + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + * @return 绑定用户编号 + */ + Long getBindUserId(Integer userType, Integer type, String code, String state); +} diff --git a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialCoreServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java similarity index 52% rename from yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialCoreServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 2d0979912c..b408a1fd49 100644 --- a/yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialCoreServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -1,14 +1,13 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.social.impl; +package cn.iocoder.yudao.module.system.service.social; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; +import cn.iocoder.yudao.module.system.dal.redis.social.SocialAuthUserRedisDAO; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import com.google.common.annotations.VisibleForTesting; import com.xkcoding.justauth.AuthRequestFactory; import lombok.extern.slf4j.Slf4j; @@ -25,34 +24,33 @@ import javax.annotation.Resource; import java.util.List; import java.util.Objects; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.SOCIAL_AUTH_FAILURE; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.SOCIAL_UNBIND_NOT_SELF; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** - * 社交 Service 实现类 + * 社交用户 Service 实现类 * * @author 芋道源码 */ @Service @Validated @Slf4j -public class SysSocialCoreServiceImpl implements SysSocialCoreService { +public class SocialUserServiceImpl implements SocialUserService { @Resource private AuthRequestFactory authRequestFactory; @Resource - private SysSocialAuthUserRedisDAO authSocialUserRedisDAO; + private SocialAuthUserRedisDAO authSocialUserRedisDAO; @Resource - private SysSocialUserCoreMapper socialUserMapper; + private SocialUserMapper socialUserMapper; @Override public String getAuthorizeUrl(Integer type, String redirectUri) { // 获得对应的 AuthRequest 实现 - AuthRequest authRequest = authRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource()); + AuthRequest authRequest = authRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); // 生成跳转地址 String authorizeUri = authRequest.authorize(AuthStateUtils.createState()); return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri); @@ -74,26 +72,54 @@ public class SysSocialCoreServiceImpl implements SysSocialCoreService { return authUser; } - @Override - public List getAllSocialUserList(Integer type, String unionId,UserTypeEnum userTypeEnum) { - List types = SysSocialTypeEnum.getRelationTypes(type); - return socialUserMapper.selectListByTypeAndUnionId(userTypeEnum.getValue(), types, unionId); + /** + * 获得 unionId 对应的某个社交平台的“所有”社交用户 + * 注意,这里的“所有”,指的是类似【微信】平台,包括了小程序、公众号、PC 网站,他们的 unionId 是一致的 + * + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param unionId 社交平台的 unionId + * @param userType 全局用户类型 + * @return 社交用户列表 + */ + private List getAllSocialUserList(Integer type, String unionId, Integer userType) { + List types = SocialTypeEnum.getRelationTypes(type); + return socialUserMapper.selectListByTypeAndUnionId(userType, types, unionId); } @Override - public List getSocialUserList(Long userId,UserTypeEnum userTypeEnum) { - return socialUserMapper.selectListByUserId(userTypeEnum.getValue(), userId); + public List getSocialUserList(Long userId, Integer userType) { + return socialUserMapper.selectListByUserId(userType, userId); } @Override - @Transactional - public void bindSocialUser(Long userId, Integer type, AuthUser authUser, UserTypeEnum userTypeEnum) { - // 获得 unionId 对应的 SysSocialUserDO 列表 + public void bindSocialUser(SocialUserBindReqDTO reqDTO) { + // 使用 code 授权 + AuthUser authUser = getAuthUser(reqDTO.getType(), reqDTO.getCode(), + reqDTO.getState()); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + + // 绑定社交用户(新增) + bindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(), + reqDTO.getType(), authUser); + } + + /** + * 绑定社交用户 + * @param userId 用户编号 + * @param userType 用户类型 + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param authUser 授权用户 + */ + @Transactional(rollbackFor = Exception.class) + protected void bindSocialUser(Long userId, Integer userType, Integer type, AuthUser authUser) { + // 获得 unionId 对应的 SocialUserDO 列表 String unionId = getAuthUserUnionId(authUser); - List socialUsers = this.getAllSocialUserList(type, unionId, userTypeEnum); + List socialUsers = this.getAllSocialUserList(type, unionId, userType); // 逻辑一:如果 userId 之前绑定过该 type 的其它账号,需要进行解绑 - this.unbindOldSocialUser(userId, type, unionId, userTypeEnum); + this.unbindOldSocialUser(userId, userType, type, unionId); // 逻辑二:如果 socialUsers 指定的 userId 改变,需要进行更新 // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改 @@ -102,17 +128,17 @@ public class SysSocialCoreServiceImpl implements SysSocialCoreService { if (Objects.equals(socialUser.getUserId(), userId)) { return; } - socialUserMapper.updateById(new SysSocialUserDO().setId(socialUser.getId()).setUserId(userId)); + socialUserMapper.updateById(new SocialUserDO().setId(socialUser.getId()).setUserId(userId)); }); // 逻辑三:如果 authUser 不存在于 socialUsers 中,则进行新增;否则,进行更新 - SysSocialUserDO socialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid()); - SysSocialUserDO saveSocialUser = SysSocialUserDO.builder() // 新增和更新的通用属性 + SocialUserDO socialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid()); + SocialUserDO saveSocialUser = SocialUserDO.builder() // 新增和更新的通用属性 .token(authUser.getToken().getAccessToken()).rawTokenInfo(toJsonString(authUser.getToken())) .nickname(authUser.getNickname()).avatar(authUser.getAvatar()).rawUserInfo(toJsonString(authUser.getRawUserInfo())) .build(); if (socialUser == null) { - saveSocialUser.setUserId(userId).setUserType(userTypeEnum.getValue()) + saveSocialUser.setUserId(userId).setUserType(userType) .setType(type).setOpenid(authUser.getUuid()).setUnionId(unionId); socialUserMapper.insert(saveSocialUser); } else { @@ -122,35 +148,58 @@ public class SysSocialCoreServiceImpl implements SysSocialCoreService { } @Override - public void unbindSocialUser(Long userId, Integer type, String unionId, UserTypeEnum userTypeEnum) { - // 获得 unionId 对应的所有 SysSocialUserDO 社交用户 - List socialUsers = this.getAllSocialUserList(type, unionId, userTypeEnum); + public void unbindSocialUser(Long userId, Integer userType, Integer type, String unionId) { + // 获得 unionId 对应的所有 SocialUserDO 社交用户 + List socialUsers = this.getAllSocialUserList(type, unionId, userType); if (CollUtil.isEmpty(socialUsers)) { return; } // 校验,是否解绑的是非自己的 socialUsers.forEach(socialUser -> { if (!Objects.equals(socialUser.getUserId(), userId)) { - throw exception(SOCIAL_UNBIND_NOT_SELF); + throw exception(SOCIAL_USER_UNBIND_NOT_SELF); } }); // 解绑 - socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(socialUsers, SysSocialUserDO::getId)); + socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(socialUsers, SocialUserDO::getId)); + } + + @Override + public void checkSocialUser(Integer type, String code, String state) { + AuthUser authUser = getAuthUser(type, code, state); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + } + + @Override + public Long getBindUserId(Integer userType, Integer type, String code, String state) { + AuthUser authUser = getAuthUser(type, code, state); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + + // 如果未绑定 SocialUserDO 用户,则无法自动登录,进行报错 + String unionId = getAuthUserUnionId(authUser); + List socialUsers = getAllSocialUserList(type, unionId, userType); + if (CollUtil.isEmpty(socialUsers)) { + throw exception(AUTH_THIRD_LOGIN_NOT_BIND); + } + return socialUsers.get(0).getUserId(); } @VisibleForTesting - public void unbindOldSocialUser(Long userId, Integer type, String newUnionId, UserTypeEnum userTypeEnum) { - List types = SysSocialTypeEnum.getRelationTypes(type); - List oldSocialUsers = socialUserMapper.selectListByTypeAndUserId( - userTypeEnum.getValue(), types, userId); + public void unbindOldSocialUser(Long userId, Integer userType, Integer type, String newUnionId) { + List types = SocialTypeEnum.getRelationTypes(type); + List oldSocialUsers = socialUserMapper.selectListByTypeAndUserId(userType, types, userId); // 如果新老的 unionId 是一致的,说明无需解绑 if (CollUtil.isEmpty(oldSocialUsers) || Objects.equals(newUnionId, oldSocialUsers.get(0).getUnionId())) { return; } // 解绑 - socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(oldSocialUsers, SysSocialUserDO::getId)); + socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(oldSocialUsers, SocialUserDO::getId)); } /** @@ -161,12 +210,12 @@ public class SysSocialCoreServiceImpl implements SysSocialCoreService { * @return 授权的用户 */ private AuthUser getAuthUser0(Integer type, AuthCallback authCallback) { - AuthRequest authRequest = authRequestFactory.get(SysSocialTypeEnum.valueOfType(type).getSource()); + AuthRequest authRequest = authRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); AuthResponse authResponse = authRequest.login(authCallback); log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, toJsonString(authCallback), toJsonString(authResponse)); if (!authResponse.ok()) { - throw exception(SOCIAL_AUTH_FAILURE, authResponse.getMsg()); + throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg()); } return (AuthUser) authResponse.getData(); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java similarity index 51% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java index b32e81f122..5742a7a102 100755 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java @@ -1,11 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.tenant; +package cn.iocoder.yudao.module.system.service.tenant; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import javax.validation.Valid; import java.util.Collection; @@ -16,7 +17,7 @@ import java.util.List; * * @author 芋道源码 */ -public interface SysTenantService { +public interface TenantService extends TenantFrameworkService { /** * 创建租户 @@ -24,14 +25,14 @@ public interface SysTenantService { * @param createReqVO 创建信息 * @return 编号 */ - Long createTenant(@Valid SysTenantCreateReqVO createReqVO); + Long createTenant(@Valid TenantCreateReqVO createReqVO); /** * 更新租户 * * @param updateReqVO 更新信息 */ - void updateTenant(@Valid SysTenantUpdateReqVO updateReqVO); + void updateTenant(@Valid TenantUpdateReqVO updateReqVO); /** * 删除租户 @@ -46,7 +47,7 @@ public interface SysTenantService { * @param id 编号 * @return 租户 */ - SysTenantDO getTenant(Long id); + TenantDO getTenant(Long id); /** * 获得租户列表 @@ -54,7 +55,7 @@ public interface SysTenantService { * @param ids 编号 * @return 租户列表 */ - List getTenantList(Collection ids); + List getTenantList(Collection ids); /** * 获得租户分页 @@ -62,7 +63,7 @@ public interface SysTenantService { * @param pageReqVO 分页查询 * @return 租户分页 */ - PageResult getTenantPage(SysTenantPageReqVO pageReqVO); + PageResult getTenantPage(TenantPageReqVO pageReqVO); /** * 获得租户列表, 用于 Excel 导出 @@ -70,7 +71,7 @@ public interface SysTenantService { * @param exportReqVO 查询条件 * @return 租户列表 */ - List getTenantList(SysTenantExportReqVO exportReqVO); + List getTenantList(TenantExportReqVO exportReqVO); /** * 获得名字对应的租户 @@ -78,6 +79,6 @@ public interface SysTenantService { * @param name 组户名 * @return 租户 */ - SysTenantDO getTenantByName(String name); + TenantDO getTenantByName(String name); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java new file mode 100755 index 0000000000..6a584d29dc --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.system.service.tenant; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS; + +/** + * 租户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class TenantServiceImpl implements TenantService { + + @Resource + private TenantMapper tenantMapper; + + @Override + public List getTenantIds() { + List tenants = tenantMapper.selectList(); + return CollectionUtils.convertList(tenants, TenantDO::getId); + } + + @Override + public Long createTenant(TenantCreateReqVO createReqVO) { + // 插入 + TenantDO tenant = TenantConvert.INSTANCE.convert(createReqVO); + tenantMapper.insert(tenant); + // 返回 + return tenant.getId(); + } + + @Override + public void updateTenant(TenantUpdateReqVO updateReqVO) { + // 校验存在 + this.validateTenantExists(updateReqVO.getId()); + // 更新 + TenantDO updateObj = TenantConvert.INSTANCE.convert(updateReqVO); + tenantMapper.updateById(updateObj); + } + + @Override + public void deleteTenant(Long id) { + // 校验存在 + this.validateTenantExists(id); + // 删除 + tenantMapper.deleteById(id); + } + + private void validateTenantExists(Long id) { + if (tenantMapper.selectById(id) == null) { + throw exception(TENANT_NOT_EXISTS); + } + } + + @Override + public TenantDO getTenant(Long id) { + return tenantMapper.selectById(id); + } + + @Override + public List getTenantList(Collection ids) { + return tenantMapper.selectBatchIds(ids); + } + + @Override + public PageResult getTenantPage(TenantPageReqVO pageReqVO) { + return tenantMapper.selectPage(pageReqVO); + } + + @Override + public List getTenantList(TenantExportReqVO exportReqVO) { + return tenantMapper.selectList(exportReqVO); + } + + @Override + public TenantDO getTenantByName(String name) { + return tenantMapper.selectByName(name); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java similarity index 67% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index fe35cfe6ba..68dd3bb572 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.user; +package cn.iocoder.yudao.module.system.service.user; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import java.io.InputStream; import java.util.*; @@ -16,7 +16,7 @@ import java.util.*; * * @author 芋道源码 */ -public interface SysUserService { +public interface AdminUserService { /** * 创建用户 @@ -24,14 +24,14 @@ public interface SysUserService { * @param reqVO 用户信息 * @return 用户编号 */ - Long createUser(SysUserCreateReqVO reqVO); + Long createUser(UserCreateReqVO reqVO); /** * 修改用户 * * @param reqVO 用户信息 */ - void updateUser(SysUserUpdateReqVO reqVO); + void updateUser(UserUpdateReqVO reqVO); /** * 更新用户的最后登陆信息 @@ -47,7 +47,7 @@ public interface SysUserService { * @param id 用户编号 * @param reqVO 用户个人信息 */ - void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO); + void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO); /** * 修改用户个人密码 @@ -55,7 +55,7 @@ public interface SysUserService { * @param id 用户编号 * @param reqVO 更新用户个人密码 */ - void updateUserPassword(Long id, SysUserProfileUpdatePasswordReqVO reqVO); + void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO); /** * 更新用户头像 @@ -94,7 +94,7 @@ public interface SysUserService { * @param username 用户名 * @return 用户对象信息 */ - SysUserDO getUserByUsername(String username); + AdminUserDO getUserByUsername(String username); /** * 获得用户分页列表 @@ -102,85 +102,15 @@ public interface SysUserService { * @param reqVO 分页条件 * @return 分页列表 */ - PageResult getUserPage(SysUserPageReqVO reqVO); + PageResult getUserPage(UserPageReqVO reqVO); /** - * 获得用户 + * 通过用户 ID 查询用户 * - * @param id 用户编号 - * @return 用户 + * @param id 用户ID + * @return 用户对象信息 */ - SysUserDO getUser(Long id); - - /** - * 获得用户列表 - * - * @param reqVO 列表请求 - * @return 用户列表 - */ - List getUsers(SysUserExportReqVO reqVO); - - /** - * 获得用户列表 - * - * @param ids 用户编号数组 - * @return 用户列表 - */ - List getUsers(Collection ids); - - /** - * 获得用户 Map - * - * @param ids 用户编号数组 - * @return 用户 Map - */ - default Map getUserMap(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return new HashMap<>(); - } - return CollectionUtils.convertMap(getUsers(ids), SysUserDO::getId); - } - - /** - * 获得用户列表,基于昵称模糊匹配 - * - * @param nickname 昵称 - * @return 用户列表 - */ - List getUsersByNickname(String nickname); - - /** - * 获得用户列表,基于用户账号模糊匹配 - * - * @param username 用户账号 - * @return 用户列表 - */ - List getUsersByUsername(String username); - - /** - * 批量导入用户 - * - * @param importUsers 导入用户列表 - * @param isUpdateSupport 是否支持更新 - * @return 导入结果 - */ - SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport); - - /** - * 获得指定状态的用户们 - * - * @param status 状态 - * @return 用户们 - */ - List getUsersByStatus(Integer status); - - /** - * 获得指定岗位的用户数组 - * - * @param postIds 岗位数组 - * @return 用户数组 - */ - List getUsersByPostIds(Collection postIds); + AdminUserDO getUser(Long id); /** * 获得指定部门的用户数组 @@ -188,7 +118,23 @@ public interface SysUserService { * @param deptIds 部门数组 * @return 用户数组 */ - List getUsersByDeptIds(Collection deptIds); + List getUsersByDeptIds(Collection deptIds); + + /** + * 获得指定岗位的用户数组 + * + * @param postIds 岗位数组 + * @return 用户数组 + */ + List getUsersByPostIds(Collection postIds); + + /** + * 获得用户列表 + * + * @param ids 用户编号数组 + * @return 用户列表 + */ + List getUsers(Collection ids); /** * 校验用户们是否有效。如下情况,视为无效: @@ -199,4 +145,58 @@ public interface SysUserService { */ void validUsers(Set ids); + /** + * 获得用户 Map + * + * @param ids 用户编号数组 + * @return 用户 Map + */ + default Map getUserMap(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return new HashMap<>(); + } + return CollectionUtils.convertMap(getUsers(ids), AdminUserDO::getId); + } + + /** + * 获得用户列表 + * + * @param reqVO 列表请求 + * @return 用户列表 + */ + List getUsers(UserExportReqVO reqVO); + + /** + * 获得用户列表,基于昵称模糊匹配 + * + * @param nickname 昵称 + * @return 用户列表 + */ + List getUsersByNickname(String nickname); + + /** + * 获得用户列表,基于用户账号模糊匹配 + * + * @param username 用户账号 + * @return 用户列表 + */ + List getUsersByUsername(String username); + + /** + * 批量导入用户 + * + * @param importUsers 导入用户列表 + * @param isUpdateSupport 是否支持更新 + * @return 导入结果 + */ + UserImportRespVO importUsers(List importUsers, boolean isUpdateSupport); + + /** + * 获得指定状态的用户们 + * + * @param status 状态 + * @return 用户们 + */ + List getUsersByStatus(Integer status); + } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java similarity index 64% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java rename to yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index d5b2ad18ba..8f308a0c76 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -1,26 +1,24 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.user.impl; +package cn.iocoder.yudao.module.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; -import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysUserMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.dept.PostService; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -32,42 +30,43 @@ import javax.annotation.Resource; import java.io.InputStream; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** - * 用户 Service 实现类 + * 后台用户 Service 实现类 * * @author 芋道源码 */ -@Service +@Service("adminUserService") @Slf4j -public class SysUserServiceImpl implements SysUserService { +public class AdminUserServiceImpl implements AdminUserService { @Value("${sys.user.init-password:yudaoyuanma}") private String userInitPassword; @Resource - private SysUserMapper userMapper; + private AdminUserMapper userMapper; @Resource - private SysDeptService deptService; + private DeptService deptService; @Resource - private SysPostService postService; + private PostService postService; @Resource - private SysPermissionService permissionService; + private PermissionService permissionService; @Resource private PasswordEncoder passwordEncoder; + @Resource - private InfFileCoreService fileService; + private FileApi fileApi; @Override - public Long createUser(SysUserCreateReqVO reqVO) { + public Long createUser(UserCreateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), reqVO.getDeptId(), reqVO.getPostIds()); // 插入用户 - SysUserDO user = SysUserConvert.INSTANCE.convert(reqVO); + AdminUserDO user = UserConvert.INSTANCE.convert(reqVO); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 user.setPassword(passwordEncoder.encode(reqVO.getPassword())); // 加密密码 userMapper.insert(user); @@ -75,36 +74,36 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public void updateUser(SysUserUpdateReqVO reqVO) { + public void updateUser(UserUpdateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), reqVO.getDeptId(), reqVO.getPostIds()); // 更新用户 - SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); + AdminUserDO updateObj = UserConvert.INSTANCE.convert(reqVO); userMapper.updateById(updateObj); } @Override public void updateUserLogin(Long id, String loginIp) { - userMapper.updateById(new SysUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date())); + userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date())); } @Override - public void updateUserProfile(Long id, SysUserProfileUpdateReqVO reqVO) { + public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) { // 校验正确性 this.checkUserExists(id); this.checkEmailUnique(id, reqVO.getEmail()); this.checkMobileUnique(id, reqVO.getMobile()); // 执行更新 - userMapper.updateById(SysUserConvert.INSTANCE.convert(reqVO).setId(id)); + userMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id)); } @Override - public void updateUserPassword(Long id, SysUserProfileUpdatePasswordReqVO reqVO) { + public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) { // 校验旧密码密码 this.checkOldPassword(id, reqVO.getOldPassword()); // 执行更新 - SysUserDO updateObj = new SysUserDO().setId(id); + AdminUserDO updateObj = new AdminUserDO().setId(id); updateObj.setPassword(passwordEncoder.encode(reqVO.getNewPassword())); // 加密密码 userMapper.updateById(updateObj); } @@ -113,9 +112,9 @@ public class SysUserServiceImpl implements SysUserService { public String updateUserAvatar(Long id, InputStream avatarFile) { this.checkUserExists(id); // 存储文件 - String avatar = fileService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile)); + String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile)); // 更新路径 - SysUserDO sysUserDO = new SysUserDO(); + AdminUserDO sysUserDO = new AdminUserDO(); sysUserDO.setId(id); sysUserDO.setAvatar(avatar); userMapper.updateById(sysUserDO); @@ -127,7 +126,7 @@ public class SysUserServiceImpl implements SysUserService { // 校验用户存在 this.checkUserExists(id); // 更新密码 - SysUserDO updateObj = new SysUserDO(); + AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); updateObj.setPassword(passwordEncoder.encode(password)); // 加密密码 userMapper.updateById(updateObj); @@ -138,7 +137,7 @@ public class SysUserServiceImpl implements SysUserService { // 校验用户存在 this.checkUserExists(id); // 更新状态 - SysUserDO updateObj = new SysUserDO(); + AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); updateObj.setStatus(status); userMapper.updateById(updateObj); @@ -155,27 +154,42 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public SysUserDO getUserByUsername(String username) { + public AdminUserDO getUserByUsername(String username) { return userMapper.selectByUsername(username); } @Override - public PageResult getUserPage(SysUserPageReqVO reqVO) { + public PageResult getUserPage(UserPageReqVO reqVO) { return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId())); } @Override - public SysUserDO getUser(Long id) { + public AdminUserDO getUser(Long id) { return userMapper.selectById(id); } @Override - public List getUsers(SysUserExportReqVO reqVO) { - return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); + public List getUsersByDeptIds(Collection deptIds) { + if (CollUtil.isEmpty(deptIds)) { + return Collections.emptyList(); + } + return userMapper.selectListByDeptIds(deptIds); } @Override - public List getUsers(Collection ids) { + public List getUsersByPostIds(Collection postIds) { + if (CollUtil.isEmpty(postIds)) { + return Collections.emptyList(); + } + // 过滤不符合条件的 + // TODO 芋艿:暂时只能内存过滤。解决方案:1、新建一个关联表;2、基于 where + 函数;3、json 字段,适合 mysql 8+ 版本 + List users = userMapper.selectList(); + users.removeIf(user -> !CollUtil.containsAny(user.getPostIds(), postIds)); + return users; + } + + @Override + public List getUsers(Collection ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } @@ -183,17 +197,37 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public Map getUserMap(Collection ids) { - return SysUserService.super.getUserMap(ids); + public void validUsers(Set ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + // 获得岗位信息 + List users = userMapper.selectBatchIds(ids); + Map userMap = CollectionUtils.convertMap(users, AdminUserDO::getId); + // 校验 + ids.forEach(id -> { + AdminUserDO user = userMap.get(id); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) { + throw exception(USER_IS_DISABLE, user.getNickname()); + } + }); } @Override - public List getUsersByNickname(String nickname) { + public List getUsers(UserExportReqVO reqVO) { + return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); + } + + @Override + public List getUsersByNickname(String nickname) { return userMapper.selectListByNickname(nickname); } @Override - public List getUsersByUsername(String username) { + public List getUsersByUsername(String username) { return userMapper.selectListByUsername(username); } @@ -208,7 +242,7 @@ public class SysUserServiceImpl implements SysUserService { return Collections.emptySet(); } Set deptIds = CollectionUtils.convertSet(deptService.getDeptsByParentIdFromCache( - deptId, true), SysDeptDO::getId); + deptId, true), DeptDO::getId); deptIds.add(deptId); // 包括自身 return deptIds; } @@ -224,9 +258,9 @@ public class SysUserServiceImpl implements SysUserService { // 校验邮箱唯一 this.checkEmailUnique(id, email); // 校验部门处于开启状态 - this.checkDeptEnable(deptId); + deptService.validDepts(Collections.singleton(deptId)); // 校验岗位处于开启状态 - this.checkPostEnable(postIds); + postService.validPosts(postIds); } @VisibleForTesting @@ -234,7 +268,7 @@ public class SysUserServiceImpl implements SysUserService { if (id == null) { return; } - SysUserDO user = userMapper.selectById(id); + AdminUserDO user = userMapper.selectById(id); if (user == null) { throw exception(USER_NOT_EXISTS); } @@ -245,7 +279,7 @@ public class SysUserServiceImpl implements SysUserService { if (StrUtil.isBlank(username)) { return; } - SysUserDO user = userMapper.selectByUsername(username); + AdminUserDO user = userMapper.selectByUsername(username); if (user == null) { return; } @@ -263,7 +297,7 @@ public class SysUserServiceImpl implements SysUserService { if (StrUtil.isBlank(email)) { return; } - SysUserDO user = userMapper.selectByEmail(email); + AdminUserDO user = userMapper.selectByEmail(email); if (user == null) { return; } @@ -281,7 +315,7 @@ public class SysUserServiceImpl implements SysUserService { if (StrUtil.isBlank(mobile)) { return; } - SysUserDO user = userMapper.selectByMobile(mobile); + AdminUserDO user = userMapper.selectByMobile(mobile); if (user == null) { return; } @@ -294,41 +328,6 @@ public class SysUserServiceImpl implements SysUserService { } } - @VisibleForTesting - public void checkDeptEnable(Long deptId) { - if (deptId == null) { // 允许不选择 - return; - } - SysDeptDO dept = deptService.getDept(deptId); - if (dept == null) { - throw exception(DEPT_NOT_FOUND); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getStatus())) { - throw exception(DEPT_NOT_ENABLE); - } - } - - @VisibleForTesting - public void checkPostEnable(Set postIds) { - if (CollUtil.isEmpty(postIds)) { // 允许不选择 - return; - } - List posts = postService.getPosts(postIds, null); - if (CollUtil.isEmpty(posts)) { - throw exception(POST_NOT_FOUND); - } - Map postMap = CollectionUtils.convertMap(posts, SysPostDO::getId); - postIds.forEach(postId -> { - SysPostDO post = postMap.get(postId); - if (post == null) { - throw exception(POST_NOT_FOUND); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(post.getStatus())) { - throw exception(POST_NOT_ENABLE, post.getName()); - } - }); - } - /** * 校验旧密码 * @@ -337,7 +336,7 @@ public class SysUserServiceImpl implements SysUserService { */ @VisibleForTesting public void checkOldPassword(Long id, String oldPassword) { - SysUserDO user = userMapper.selectById(id); + AdminUserDO user = userMapper.selectById(id); if (user == null) { throw exception(USER_NOT_EXISTS); } @@ -348,11 +347,11 @@ public class SysUserServiceImpl implements SysUserService { @Override @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 - public SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport) { + public UserImportRespVO importUsers(List importUsers, boolean isUpdateSupport) { if (CollUtil.isEmpty(importUsers)) { throw exception(USER_IMPORT_LIST_IS_EMPTY); } - SysUserImportRespVO respVO = SysUserImportRespVO.builder().createUsernames(new ArrayList<>()) + UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>()) .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build(); importUsers.forEach(importUser -> { // 校验,判断是否有不符合的原因 @@ -364,9 +363,9 @@ public class SysUserServiceImpl implements SysUserService { return; } // 判断如果不存在,在进行插入 - SysUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); + AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); if (existUser == null) { - userMapper.insert(SysUserConvert.INSTANCE.convert(importUser) + userMapper.insert(UserConvert.INSTANCE.convert(importUser) .setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码 respVO.getCreateUsernames().add(importUser.getUsername()); return; @@ -376,7 +375,7 @@ public class SysUserServiceImpl implements SysUserService { respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg()); return; } - SysUserDO updateUser = SysUserConvert.INSTANCE.convert(importUser); + AdminUserDO updateUser = UserConvert.INSTANCE.convert(importUser); updateUser.setId(existUser.getId()); userMapper.updateById(updateUser); respVO.getUpdateUsernames().add(importUser.getUsername()); @@ -385,48 +384,8 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public List getUsersByStatus(Integer status) { + public List getUsersByStatus(Integer status) { return userMapper.selectListByStatus(status); } - @Override - public List getUsersByPostIds(Collection postIds) { - if (CollUtil.isEmpty(postIds)) { - return Collections.emptyList(); - } - // 过滤不符合条件的 - // TODO 芋艿:暂时只能内存过滤。解决方案:1、新建一个关联表;2、基于 where + 函数;3、json 字段,适合 mysql 8+ 版本 - List users = userMapper.selectList(); - users.removeIf(user -> !CollUtil.containsAny(user.getPostIds(), postIds)); - return users; - } - - @Override - public List getUsersByDeptIds(Collection deptIds) { - if (CollUtil.isEmpty(deptIds)) { - return Collections.emptyList(); - } - return userMapper.selectListByDeptIds(deptIds); - } - - @Override - public void validUsers(Set ids) { - if (CollUtil.isEmpty(ids)) { - return; - } - // 获得岗位信息 - List users = userMapper.selectBatchIds(ids); - Map userMap = CollectionUtils.convertMap(users, SysUserDO::getId); - // 校验 - ids.forEach(id -> { - SysUserDO user = userMap.get(id); - if (user == null) { - throw exception(USER_NOT_EXISTS); - } - if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) { - throw exception(USER_IS_DISABLE, user.getNickname()); - } - }); - } - } diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/quartz/core/SchedulerManagerTest.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/job/SchedulerManagerTest.java similarity index 57% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/quartz/core/SchedulerManagerTest.java rename to yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/job/SchedulerManagerTest.java index efa95928b4..2d1d6f4c8a 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/quartz/core/SchedulerManagerTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/job/SchedulerManagerTest.java @@ -1,52 +1,52 @@ -package cn.iocoder.yudao.adminserver.framework.quartz.core; +package cn.iocoder.yudao.module.system.job; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.job.auth.SysUserSessionTimeoutJob; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; +import cn.iocoder.yudao.module.system.job.auth.UserSessionTimeoutJob; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.quartz.SchedulerException; import javax.annotation.Resource; -class SchedulerManagerTest extends BaseDbUnitTest { +public class SchedulerManagerTest extends BaseDbUnitTest { @Resource private SchedulerManager schedulerManager; @Test public void testAddJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.addJob(1L, jobHandlerName, "test", "0/10 * * * * ? *", 0, 0); } @Test public void testUpdateJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.updateJob(jobHandlerName, "hahaha", "0/20 * * * * ? *", 0, 0); } @Test public void testDeleteJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.deleteJob(jobHandlerName); } @Test public void testPauseJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.pauseJob(jobHandlerName); } @Test public void testResumeJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.resumeJob(jobHandlerName); } @Test public void testTriggerJob() throws SchedulerException { - String jobHandlerName = StrUtil.lowerFirst(SysUserSessionTimeoutJob.class.getSimpleName()); + String jobHandlerName = StrUtil.lowerFirst(UserSessionTimeoutJob.class.getSimpleName()); schedulerManager.triggerJob(1L, jobHandlerName, "niubi!!!"); } diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/redis/core/stream/RedisStreamTest.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/mq/RedisStreamTest.java similarity index 53% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/redis/core/stream/RedisStreamTest.java rename to yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/mq/RedisStreamTest.java index 90e25aeebf..c94316a817 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/framework/redis/core/stream/RedisStreamTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/mq/RedisStreamTest.java @@ -1,24 +1,23 @@ -package cn.iocoder.yudao.adminserver.framework.redis.core.stream; +package cn.iocoder.yudao.module.system.mq; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.adminserver.BaseRedisIntegrationTest; -import cn.iocoder.yudao.adminserver.modules.system.mq.consumer.mail.SysMailSendConsumer; -import cn.iocoder.yudao.adminserver.modules.system.mq.consumer.sms.SysSmsSendConsumer; -import cn.iocoder.yudao.adminserver.modules.system.mq.message.mail.SysMailSendMessage; -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils; +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; +import cn.iocoder.yudao.module.system.mq.consumer.mail.MailSendConsumer; +import cn.iocoder.yudao.module.system.mq.consumer.sms.SmsSendConsumer; +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.yudao.module.system.test.BaseRedisIntegrationTest; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; public class RedisStreamTest { - @Import({SysSmsSendConsumer.class, SysMailSendConsumer.class}) + @Import({SmsSendConsumer.class, MailSendConsumer.class}) @Disabled public static class ConsumerTest extends BaseRedisIntegrationTest { @@ -33,7 +32,7 @@ public class RedisStreamTest { public static class ProducerTest extends BaseRedisIntegrationTest { @Resource - private StringRedisTemplate stringRedisTemplate; + private RedisMQTemplate redisMQTemplate; @Resource private RedisTemplate redisTemplate; @@ -42,20 +41,20 @@ public class RedisStreamTest { public void testProducer01() { for (int i = 0; i < 100; i++) { // 创建消息 - SysSmsSendMessage message = new SysSmsSendMessage(); + SmsSendMessage message = new SmsSendMessage(); message.setMobile("15601691300").setApiTemplateId("test:" + i); // 发送消息 - RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message); + redisMQTemplate.send(message); } } @Test public void testProducer02() { // 创建消息 - SysMailSendMessage message = new SysMailSendMessage(); + MailSendMessage message = new MailSendMessage(); message.setAddress("fangfang@mihayou.com").setTemplateCode("test"); // 发送消息 - RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message); + redisMQTemplate.send(message); } } diff --git a/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/package-info.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/package-info.java new file mode 100644 index 0000000000..7b475e53e4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.system.service; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsServiceIntegrationTest.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java similarity index 61% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsServiceIntegrationTest.java rename to yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java index dc4301952e..b3ae5cde46 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsServiceIntegrationTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java @@ -1,17 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.map.MapUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.iocoder.yudao.adminserver.BaseDbAndRedisIntegrationTest; -import cn.iocoder.yudao.adminserver.modules.system.mq.consumer.sms.SysSmsSendConsumer; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsChannelServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsLogServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsTemplateServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.impl.SysSmsCoreServiceImpl; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration; +import cn.iocoder.yudao.module.system.test.BaseDbAndRedisIntegrationTest; +import cn.iocoder.yudao.module.system.mq.consumer.sms.SmsSendConsumer; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -22,17 +18,17 @@ import java.util.concurrent.TimeUnit; // TODO @芋艿:需要迁移 @Import({YudaoSmsAutoConfiguration.class, - SysSmsChannelServiceImpl.class, SysSmsCoreServiceImpl.class, SysSmsTemplateServiceImpl.class, SysSmsLogServiceImpl.class, - SysSmsProducer.class, SysSmsSendConsumer.class}) -public class SysSmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest { + SmsChannelServiceImpl.class, SmsSendServiceImpl.class, SmsTemplateServiceImpl.class, SmsLogServiceImpl.class, + SmsProducer.class, SmsSendConsumer.class}) +public class SmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest { @Resource - private SysSmsCoreServiceImpl smsService; + private SmsSendServiceImpl smsService; @Resource - private SysSmsChannelServiceImpl smsChannelService; + private SmsChannelServiceImpl smsChannelService; @MockBean - private SysUserService userService; + private AdminUserService userService; @Test public void testSendSingleSms_yunpianSuccess() { diff --git a/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisIntegrationTest.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisIntegrationTest.java new file mode 100644 index 0000000000..5b9b21ffd5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisIntegrationTest.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.system.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.redisson.spring.starter.RedissonAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisIntegrationTest.Application.class) +@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件 +public class BaseDbAndRedisIntegrationTest { + + @Import({ + // DB 配置类 + DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + + // Redis 配置类 + RedisAutoConfiguration.class, // Spring Redis 自动配置类 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 + RedissonAutoConfiguration.class, // Redisson 自动高配置类 + }) + public static class Application { + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseRedisIntegrationTest.java b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseRedisIntegrationTest.java new file mode 100644 index 0000000000..f48b2891df --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test-integration/java/cn/iocoder/yudao/module/system/test/BaseRedisIntegrationTest.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.test; + +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import org.redisson.spring.starter.RedissonAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisIntegrationTest.Application.class) +@ActiveProfiles("integration-test") // 设置使用 application-integration-test 配置文件 +public class BaseRedisIntegrationTest { + + @Import({ + // Redis 配置类 + RedisAutoConfiguration.class, // Spring Redis 自动配置类 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 + RedissonAutoConfiguration.class, // Redisson 自动高配置类 + }) + public static class Application { + } + +} diff --git a/yudao-admin-server/src/test-integration/resources/application-integration-test.yaml b/yudao-module-system/yudao-module-system-impl/src/test-integration/resources/application-integration-test.yaml similarity index 100% rename from yudao-admin-server/src/test-integration/resources/application-integration-test.yaml rename to yudao-module-system/yudao-module-system-impl/src/test-integration/resources/application-integration-test.yaml diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java similarity index 64% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java index 6e213a57d2..9869cee2c6 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/AuthServiceImplTest.java @@ -1,22 +1,19 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.auth; +package cn.iocoder.yudao.module.system.service.auth; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; -import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthLoginReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.service.common.CaptchaService; +import cn.iocoder.yudao.module.system.service.dept.PostService; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.test.core.util.AssertUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -32,7 +29,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import javax.annotation.Resource; import java.util.Set; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static java.util.Collections.singleton; @@ -40,37 +37,30 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -/** - * {@link SysAuthServiceImpl} 的单元测试 - * - * @author 芋道源码 - */ -@Import(SysAuthServiceImpl.class) -public class SysAuthServiceImplTest extends BaseDbUnitTest { +@Import(AdminAuthServiceImpl.class) +public class AuthServiceImplTest extends BaseDbUnitTest { @Resource - private SysAuthServiceImpl authService; + private AdminAuthServiceImpl authService; @MockBean - private SysUserService userService; + private AdminUserService userService; @MockBean - private SysUserCoreService userCoreService; - @MockBean - private SysPermissionService permissionService; + private PermissionService permissionService; @MockBean private AuthenticationManager authenticationManager; @MockBean private Authentication authentication; @MockBean - private SysCaptchaService captchaService; + private CaptchaService captchaService; @MockBean - private SysLoginLogCoreService loginLogCoreService; + private LoginLogService loginLogService; @MockBean - private SysUserSessionCoreService userSessionCoreService; + private UserSessionService userSessionService; @MockBean - private SysSocialCoreService socialService; + private SocialUserService socialService; @MockBean - private SysPostService postService; + private PostService postService; @BeforeEach public void setUp() { @@ -82,7 +72,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // 准备参数 String username = randomString(); // mock 方法 - SysUserDO user = randomPojo(SysUserDO.class, o -> o.setUsername(username)); + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername(username)); when(userService.getUserByUsername(eq(username))).thenReturn(user); // 调用 @@ -108,8 +98,8 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // 准备参数 Long userId = randomLongId(); // mock 方法 01 - SysUserDO user = randomPojo(SysUserDO.class, o -> o.setId(userId)); - when(userCoreService.getUser(eq(userId))).thenReturn(user); + AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); + when(userService.getUser(eq(userId))).thenReturn(user); // mock 方法 02 Set roleIds = randomSet(Long.class); when(permissionService.getUserRoleIds(eq(userId), eq(singleton(CommonStatusEnum.ENABLE.getStatus())))) @@ -137,15 +127,15 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { @Test public void testLogin_captchaNotFound() { // 准备参数 - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); String userIp = randomString(); String userAgent = randomString(); // 调用, 并断言异常 assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_NOT_FOUND); // 校验调用参数 - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.CAPTCHA_NOT_FOUND.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.CAPTCHA_NOT_FOUND.getResult())) ); } @@ -155,15 +145,15 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { String userIp = randomString(); String userAgent = randomString(); String code = randomString(); - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); // mock 验证码不正确 when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(code); // 调用, 并断言异常 assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_CODE_ERROR); // 校验调用参数 - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.CAPTCHA_CODE_ERROR.getResult())) ); } @@ -172,7 +162,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // 准备参数 String userIp = randomString(); String userAgent = randomString(); - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); // mock 验证码正确 when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); // mock 抛出异常 @@ -182,9 +172,9 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_BAD_CREDENTIALS); // 校验调用参数 verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.BAD_CREDENTIALS.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.BAD_CREDENTIALS.getResult())) ); } @@ -193,7 +183,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // 准备参数 String userIp = randomString(); String userAgent = randomString(); - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); // mock 验证码正确 when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); // mock 抛出异常 @@ -203,9 +193,9 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_USER_DISABLED); // 校验调用参数 verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.USER_DISABLED.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult())) ); } @@ -214,7 +204,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // 准备参数 String userIp = randomString(); String userAgent = randomString(); - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); // mock 验证码正确 when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode()); // mock 抛出异常 @@ -224,9 +214,9 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_FAIL_UNKNOWN); // 校验调用参数 verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.UNKNOWN_ERROR.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.UNKNOWN_ERROR.getResult())) ); } @@ -238,7 +228,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { Long userId = randomLongId(); Set userRoleIds = randomSet(Long.class); String sessionId = randomString(); - SysAuthLoginReqVO reqVO = randomPojo(SysAuthLoginReqVO.class); + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class); LoginUser loginUser = randomPojo(LoginUser.class, o -> { o.setId(userId); o.setRoleIds(userRoleIds); @@ -252,15 +242,15 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { // mock 获得 User 拥有的角色编号数组 when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds); // mock 缓存登录用户到 Redis - when(userSessionCoreService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId); + when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId); // 调用, 并断言异常 String login = authService.login(reqVO, userIp, userAgent); assertEquals(sessionId, login); // 校验调用参数 verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid()); - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult())) + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())) ); } @@ -270,14 +260,14 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { String token = randomString(); LoginUser loginUser = randomPojo(LoginUser.class); // mock - when(userSessionCoreService.getLoginUser(token)).thenReturn(loginUser); + when(userSessionService.getLoginUser(token)).thenReturn(loginUser); // 调用 authService.logout(token); // 校验调用参数 - verify(userSessionCoreService, times(1)).deleteUserSession(token); - verify(loginLogCoreService, times(1)).createLoginLog( - argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGOUT_SELF.getType()) - && o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult())) + verify(userSessionService, times(1)).deleteUserSession(token); + verify(loginLogService, times(1)).createLoginLog( + argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType()) + && o.getResult().equals(LoginResultEnum.SUCCESS.getResult())) ); } diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImplTest.java new file mode 100644 index 0000000000..1862c68c88 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/auth/UserSessionServiceImplTest.java @@ -0,0 +1,219 @@ +package cn.iocoder.yudao.module.system.service.auth; + +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO; +import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbAndRedisUnitTest; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +/** + * {@link UserSessionServiceImpl} 的单元测试 + * + * @author Lyon + */ +@Import({UserSessionServiceImpl.class, LoginUserRedisDAO.class}) +public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest { + + @Resource + private UserSessionServiceImpl userSessionService; + + @Resource + private UserSessionMapper userSessionMapper; + + @MockBean + private AdminUserService userService; + @MockBean + private LoginLogService loginLogService; + @Resource + private LoginUserRedisDAO loginUserRedisDAO; + + @MockBean + private SecurityProperties securityProperties; + + @Test + public void testGetUserSessionPage_success() { + // mock 数据 + AdminUserDO dbUser = randomPojo(AdminUserDO.class, o -> { + o.setSex(randomEle(SexEnum.values()).getSex()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + when(userService.getUsersByUsername(eq(dbUser.getUsername()))).thenReturn(singletonList(dbUser)); + // 插入可被查询到的数据 + String userIp = randomString(); + UserSessionDO dbSession = randomPojo(UserSessionDO.class, o -> { + o.setUserId(dbUser.getId()); + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); + o.setUserIp(userIp); + }); + userSessionMapper.insert(dbSession); + // 测试 username 不匹配 + userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> { + o.setId(randomString()); + o.setUserId(123456L); + })); + // 测试 userIp 不匹配 + userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> { + o.setId(randomString()); + o.setUserIp("testUserIp"); + })); + // 准备参数 + UserSessionPageReqVO reqVO = new UserSessionPageReqVO(); + reqVO.setUsername(dbUser.getUsername()); + reqVO.setUserIp(userIp); + + // 调用 + PageResult pageResult = userSessionService.getUserSessionPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSession, pageResult.getList().get(0)); + } + + // TODO 芋艿:单测写的有问题 + @Test + public void testClearSessionTimeout_success() { + // 准备超时数据 120 条, 在线用户 1 条 + int expectedTimeoutCount = 120, expectedTotal = 1; + + // 准备数据 + List prepareData = Stream + .iterate(0, i -> i) + .limit(expectedTimeoutCount) + .map(i -> randomPojo(UserSessionDO.class, o -> { + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); + o.setSessionTimeout(DateUtil.offsetSecond(new Date(), -1)); + })) + .collect(Collectors.toList()); + UserSessionDO sessionDO = randomPojo(UserSessionDO.class, o -> { + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); + o.setSessionTimeout(DateUtil.offsetMinute(new Date(), 30)); + }); + prepareData.add(sessionDO); + prepareData.forEach(userSessionMapper::insert); + + // 清空超时数据 + long actualTimeoutCount = userSessionService.clearSessionTimeout(); + // 校验 + assertEquals(expectedTimeoutCount, actualTimeoutCount); + List userSessionDOS = userSessionMapper.selectList(); + assertEquals(expectedTotal, userSessionDOS.size()); + assertPojoEquals(sessionDO, userSessionDOS.get(0), "updateTime"); + } + + @Test + public void testCreateUserSession_success() { + // 准备参数 + String userIp = randomString(); + String userAgent = randomString(); + LoginUser loginUser = randomPojo(LoginUser.class, o -> { + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); + o.setTenantId(0L); // 租户设置为 0,因为暂未启用多租户组件 + }); + // mock 方法 + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); + + // 调用 + String sessionId = userSessionService.createUserSession(loginUser, userIp, userAgent); + // 校验 UserSessionDO 记录 + UserSessionDO userSessionDO = userSessionMapper.selectById(sessionId); + assertPojoEquals(loginUser, userSessionDO, "id", "updateTime"); + assertEquals(sessionId, userSessionDO.getId()); + assertEquals(userIp, userSessionDO.getUserIp()); + assertEquals(userAgent, userSessionDO.getUserAgent()); + // 校验 LoginUser 缓存 + LoginUser redisLoginUser = loginUserRedisDAO.get(sessionId); + assertPojoEquals(loginUser, redisLoginUser, "username", "password"); + } + + @Test + public void testCreateRefreshUserSession_success() { + // 准备参数 + String sessionId = randomString(); + String userIp = randomString(); + String userAgent = randomString(); + long timeLong = randomLongId(); + String userName = randomString(); + Date date = randomDate(); + LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue())); + // mock 方法 + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); + // mock 数据 + loginUser.setUpdateTime(date); + loginUserRedisDAO.set(sessionId, loginUser); + UserSessionDO userSession = UserSessionDO.builder().id(sessionId) + .userId(loginUser.getId()).userType(loginUser.getUserType()) + .userIp(userIp).userAgent(userAgent).username(userName) + .sessionTimeout(addTime(Duration.ofMillis(timeLong))) + .build(); + userSessionMapper.insert(userSession); + + // 调用 + userSessionService.refreshUserSession(sessionId, loginUser); + // 校验 LoginUser 缓存 + LoginUser redisLoginUser = loginUserRedisDAO.get(sessionId); + assertNotEquals(redisLoginUser.getUpdateTime(), date); + // 校验 UserSessionDO 记录 + UserSessionDO updateDO = userSessionMapper.selectById(sessionId); + assertEquals(updateDO.getUsername(), loginUser.getUsername()); + assertNotEquals(updateDO.getUpdateTime(), userSession.getUpdateTime()); + assertNotEquals(updateDO.getSessionTimeout(), addTime(Duration.ofMillis(timeLong))); + } + + @Test + public void testDeleteUserSession_success() { + // 准备参数 + String sessionId = randomString(); + String userIp = randomString(); + String userAgent = randomString(); + Long timeLong = randomLongId(); + LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue())); + // mock 存入 Redis + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1)); + // mock 数据 + loginUserRedisDAO.set(sessionId, loginUser); + UserSessionDO userSession = UserSessionDO.builder().id(sessionId) + .userId(loginUser.getId()).userType(loginUser.getUserType()) + .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername()) + .sessionTimeout(addTime(Duration.ofMillis(timeLong))) + .build(); + userSessionMapper.insert(userSession); + + // 调用 + userSessionService.deleteUserSession(sessionId); + // 校验数据不存在了 + assertNull(loginUserRedisDAO.get(sessionId)); + assertNull(userSessionMapper.selectById(sessionId)); + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceTest.java similarity index 63% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceTest.java index c45ed4cbf6..79fb65f43d 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/common/CaptchaServiceTest.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.common; +package cn.iocoder.yudao.module.system.service.common; -import cn.iocoder.yudao.adminserver.BaseRedisUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.framework.captcha.config.CaptchaProperties; -import cn.iocoder.yudao.adminserver.modules.system.controller.common.vo.SysCaptchaImageRespVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.common.SysCaptchaRedisDAO; -import cn.iocoder.yudao.adminserver.modules.system.service.common.impl.SysCaptchaServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO; +import cn.iocoder.yudao.module.system.dal.redis.common.CaptchaRedisDAO; +import cn.iocoder.yudao.module.system.framework.captcha.config.CaptchaProperties; +import cn.iocoder.yudao.module.system.test.BaseRedisUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -13,21 +12,21 @@ import javax.annotation.Resource; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; import static org.junit.jupiter.api.Assertions.*; -@Import({SysCaptchaServiceImpl.class, CaptchaProperties.class, SysCaptchaRedisDAO.class}) -public class SysCaptchaServiceTest extends BaseRedisUnitTest { +@Import({CaptchaServiceImpl.class, CaptchaProperties.class, CaptchaRedisDAO.class}) +public class CaptchaServiceTest extends BaseRedisUnitTest { @Resource - private SysCaptchaServiceImpl captchaService; + private CaptchaServiceImpl captchaService; @Resource - private SysCaptchaRedisDAO captchaRedisDAO; + private CaptchaRedisDAO captchaRedisDAO; @Resource private CaptchaProperties captchaProperties; @Test public void testGetCaptchaImage() { // 调用 - SysCaptchaImageRespVO respVO = captchaService.getCaptchaImage(); + CaptchaImageRespVO respVO = captchaService.getCaptchaImage(); // 断言 assertNotNull(respVO.getUuid()); assertNotNull(respVO.getImg()); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceTest.java similarity index 69% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceTest.java index 1e276e3eac..3f78cec2f3 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceTest.java @@ -1,17 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept; +package cn.iocoder.yudao.module.system.service.dept; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysDeptMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.dept.DeptIdEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept.SysDeptProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.impl.SysDeptServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; +import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; +import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import com.google.common.collect.Multimap; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -25,7 +24,7 @@ import java.util.function.Consumer; import static cn.hutool.core.bean.BeanUtil.getFieldValue; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -34,38 +33,38 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** - * {@link SysDeptServiceImpl} 的单元测试类 + * {@link DeptServiceImpl} 的单元测试类 * * @author niudehua */ -@Import(SysDeptServiceImpl.class) -class SysDeptServiceTest extends BaseDbUnitTest { +@Import(DeptServiceImpl.class) +public class DeptServiceTest extends BaseDbUnitTest { @Resource - private SysDeptServiceImpl deptService; + private DeptServiceImpl deptService; @Resource - private SysDeptMapper deptMapper; + private DeptMapper deptMapper; @MockBean - private SysDeptProducer deptProducer; + private DeptProducer deptProducer; @Test @SuppressWarnings("unchecked") void testInitLocalCache() { // mock 数据 - SysDeptDO deptDO1 = randomDeptDO(); + DeptDO deptDO1 = randomDeptDO(); deptMapper.insert(deptDO1); - SysDeptDO deptDO2 = randomDeptDO(); + DeptDO deptDO2 = randomDeptDO(); deptMapper.insert(deptDO2); // 调用 deptService.initLocalCache(); // 断言 deptCache 缓存 - Map deptCache = (Map) getFieldValue(deptService, "deptCache"); + Map deptCache = (Map) getFieldValue(deptService, "deptCache"); assertEquals(2, deptCache.size()); assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId())); assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId())); // 断言 parentDeptCache 缓存 - Multimap parentDeptCache = (Multimap) getFieldValue(deptService, "parentDeptCache"); + Multimap parentDeptCache = (Multimap) getFieldValue(deptService, "parentDeptCache"); assertEquals(2, parentDeptCache.size()); assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId())); assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId())); @@ -77,7 +76,7 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testListDepts() { // mock 数据 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { // 等会查询到 + DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到 o.setName("开发部"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); @@ -87,11 +86,11 @@ class SysDeptServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 准备参数 - SysDeptListReqVO reqVO = new SysDeptListReqVO(); + DeptListReqVO reqVO = new DeptListReqVO(); reqVO.setName("开"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 调用 - List sysDeptDOS = deptService.getSimpleDepts(reqVO); + List sysDeptDOS = deptService.getSimpleDepts(reqVO); // 断言 assertEquals(1, sysDeptDOS.size()); assertPojoEquals(dept, sysDeptDOS.get(0)); @@ -100,7 +99,7 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCreateDept_success() { // 准备参数 - SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class, + DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { o.setParentId(DeptIdEnum.ROOT.getId()); o.setStatus(randomCommonStatus()); @@ -110,7 +109,7 @@ class SysDeptServiceTest extends BaseDbUnitTest { // 断言 assertNotNull(deptId); // 校验记录的属性是否正确 - SysDeptDO deptDO = deptMapper.selectById(deptId); + DeptDO deptDO = deptMapper.selectById(deptId); assertPojoEquals(reqVO, deptDO); // 校验调用 verify(deptProducer, times(1)).sendDeptRefreshMessage(); @@ -119,10 +118,10 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testUpdateDept_success() { // mock 数据 - SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus())); + DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class, o -> { + DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { // 设置更新的 ID o.setParentId(DeptIdEnum.ROOT.getId()); o.setId(dbDeptDO.getId()); @@ -131,14 +130,14 @@ class SysDeptServiceTest extends BaseDbUnitTest { // 调用 deptService.updateDept(reqVO); // 校验是否更新正确 - SysDeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的 + DeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, deptDO); } @Test void testDeleteDept_success() { // mock 数据 - SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus())); + DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbDeptDO.getId(); @@ -151,17 +150,17 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_nameDuplicateForUpdate() { // mock 数据 - SysDeptDO deptDO = randomDeptDO(); + DeptDO deptDO = randomDeptDO(); // 设置根节点部门 deptDO.setParentId(DeptIdEnum.ROOT.getId()); deptMapper.insert(deptDO); // mock 数据 稍后模拟重复它的 name - SysDeptDO nameDeptDO = randomDeptDO(); + DeptDO nameDeptDO = randomDeptDO(); // 设置根节点部门 nameDeptDO.setParentId(DeptIdEnum.ROOT.getId()); deptMapper.insert(nameDeptDO); // 准备参数 - SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class, + DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { // 设置根节点部门 o.setParentId(DeptIdEnum.ROOT.getId()); @@ -176,7 +175,7 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_parentNotExitsForCreate() { - SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class, + DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); // 调用,并断言异常 assertServiceException(() -> deptService.createDept(reqVO), DEPT_PARENT_NOT_EXITS); @@ -193,10 +192,10 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_exitsChildrenForDelete() { // mock 数据 - SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus())); + DeptDO parentDept = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); deptMapper.insert(parentDept);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysDeptDO childrenDeptDO = randomPojo(SysDeptDO.class, o -> { + DeptDO childrenDeptDO = randomPojo(DeptDO.class, o -> { o.setParentId(parentDept.getId()); o.setStatus(randomCommonStatus()); }); @@ -209,10 +208,10 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_parentErrorForUpdate() { // mock 数据 - SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus())); + DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); deptMapper.insert(dbDeptDO); // 准备参数 - SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class, + DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { // 设置自己为父部门 o.setParentId(dbDeptDO.getId()); @@ -226,10 +225,10 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_notEnableForCreate() { // mock 数据 - SysDeptDO deptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())); + DeptDO deptDO = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())); deptMapper.insert(deptDO); // 准备参数 - SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class, + DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { // 设置未启用的部门为副部门 o.setParentId(deptDO.getId()); @@ -241,9 +240,9 @@ class SysDeptServiceTest extends BaseDbUnitTest { @Test void testCheckDept_parentIsChildForUpdate() { // mock 数据 - SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); + DeptDO parentDept = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); deptMapper.insert(parentDept); - SysDeptDO childDept = randomPojo(SysDeptDO.class, o -> { + DeptDO childDept = randomPojo(DeptDO.class, o -> { o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setParentId(parentDept.getId()); }); @@ -251,7 +250,7 @@ class SysDeptServiceTest extends BaseDbUnitTest { // 初始化本地缓存 deptService.initLocalCache(); // 准备参数 - SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class, + DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { // 设置自己的子部门为父部门 o.setParentId(childDept.getId()); @@ -263,11 +262,11 @@ class SysDeptServiceTest extends BaseDbUnitTest { } @SafeVarargs - private static SysDeptDO randomDeptDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static DeptDO randomDeptDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 }; - return randomPojo(SysDeptDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(DeptDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceTest.java similarity index 68% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceTest.java index c2a811f0b3..19850d0c79 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceTest.java @@ -1,17 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dept; +package cn.iocoder.yudao.module.system.service.dept; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.post.SysPostUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysPostMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.impl.SysPostServiceImpl; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.mysql.dept.PostMapper; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -20,30 +19,25 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; -/** - * {@link SysPostServiceImpl} 的单元测试类 - * - * @author niudehua - */ -@Import(SysPostServiceImpl.class) -class SysPostServiceTest extends BaseDbUnitTest { +@Import(PostServiceImpl.class) +public class PostServiceTest extends BaseDbUnitTest { @Resource - private SysPostServiceImpl postService; + private PostServiceImpl postService; @Resource - private SysPostMapper postMapper; + private PostMapper postMapper; @Test void testPagePosts() { // mock 数据 - SysPostDO postDO = randomPojo(SysPostDO.class, o -> { + PostDO postDO = randomPojo(PostDO.class, o -> { o.setName("码仔"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); @@ -54,12 +48,12 @@ class SysPostServiceTest extends BaseDbUnitTest { postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 准备参数 - SysPostPageReqVO reqVO = new SysPostPageReqVO(); + PostPageReqVO reqVO = new PostPageReqVO(); reqVO.setName("码"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 调用 - PageResult pageResult = postService.getPostPage(reqVO); + PageResult pageResult = postService.getPostPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); @@ -70,7 +64,7 @@ class SysPostServiceTest extends BaseDbUnitTest { @Test void testListPosts() { // mock 数据 - SysPostDO postDO = randomPojo(SysPostDO.class, o -> { + PostDO postDO = randomPojo(PostDO.class, o -> { o.setName("码仔"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); @@ -80,12 +74,12 @@ class SysPostServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 准备参数 - SysPostExportReqVO reqVO = new SysPostExportReqVO(); + PostExportReqVO reqVO = new PostExportReqVO(); reqVO.setName("码"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 调用 - List list = postService.getPosts(reqVO); + List list = postService.getPosts(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(postDO, list.get(0)); @@ -94,12 +88,12 @@ class SysPostServiceTest extends BaseDbUnitTest { @Test void testGetPost() { // mock 数据 - SysPostDO dbPostDO = randomPostDO(); + PostDO dbPostDO = randomPostDO(); postMapper.insert(dbPostDO); // 准备参数 Long id = dbPostDO.getId(); // 调用 - SysPostDO post = postService.getPost(id); + PostDO post = postService.getPost(id); // 断言 assertNotNull(post); assertPojoEquals(dbPostDO, post); @@ -108,24 +102,24 @@ class SysPostServiceTest extends BaseDbUnitTest { @Test void testCreatePost_success() { // 准备参数 - SysPostCreateReqVO reqVO = randomPojo(SysPostCreateReqVO.class, + PostCreateReqVO reqVO = randomPojo(PostCreateReqVO.class, o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())); // 调用 Long postId = postService.createPost(reqVO); // 断言 assertNotNull(postId); // 校验记录的属性是否正确 - SysPostDO post = postMapper.selectById(postId); + PostDO post = postMapper.selectById(postId); assertPojoEquals(reqVO, post); } @Test void testUpdatePost_success() { // mock 数据 - SysPostDO postDO = randomPostDO(); + PostDO postDO = randomPostDO(); postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysPostUpdateReqVO reqVO = randomPojo(SysPostUpdateReqVO.class, + PostUpdateReqVO reqVO = randomPojo(PostUpdateReqVO.class, o -> { // 设置更新的 ID o.setId(postDO.getId()); @@ -134,14 +128,14 @@ class SysPostServiceTest extends BaseDbUnitTest { // 调用 postService.updatePost(reqVO); // 校验是否更新正确 - SysPostDO post = postMapper.selectById(reqVO.getId());// 获取最新的 + PostDO post = postMapper.selectById(reqVO.getId());// 获取最新的 assertPojoEquals(reqVO, post); } @Test void testDeletePost_success() { // mock 数据 - SysPostDO postDO = randomPostDO(); + PostDO postDO = randomPostDO(); postMapper.insert(postDO); // 准备参数 Long id = postDO.getId(); @@ -161,10 +155,10 @@ class SysPostServiceTest extends BaseDbUnitTest { @Test void testCheckPost_nameDuplicateForCreate() { // mock 数据 - SysPostDO postDO = randomPostDO(); + PostDO postDO = randomPostDO(); postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysPostCreateReqVO reqVO = randomPojo(SysPostCreateReqVO.class, + PostCreateReqVO reqVO = randomPojo(PostCreateReqVO.class, // 模拟 name 重复 o -> o.setName(postDO.getName())); assertServiceException(() -> postService.createPost(reqVO), POST_NAME_DUPLICATE); @@ -173,13 +167,13 @@ class SysPostServiceTest extends BaseDbUnitTest { @Test void testCheckPost_codeDuplicateForUpdate() { // mock 数据 - SysPostDO postDO = randomPostDO(); + PostDO postDO = randomPostDO(); postMapper.insert(postDO); // mock 数据 稍后模拟重复它的 code - SysPostDO codePostDO = randomPostDO(); + PostDO codePostDO = randomPostDO(); postMapper.insert(codePostDO); // 准备参数 - SysPostUpdateReqVO reqVO = randomPojo(SysPostUpdateReqVO.class, + PostUpdateReqVO reqVO = randomPojo(PostUpdateReqVO.class, o -> { // 设置更新的 ID o.setId(postDO.getId()); @@ -191,10 +185,10 @@ class SysPostServiceTest extends BaseDbUnitTest { } @SafeVarargs - private static SysPostDO randomPostDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static PostDO randomPostDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 }; - return randomPojo(SysPostDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(PostDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceTest.java similarity index 64% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceTest.java index e69b6297e0..94691d4840 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceTest.java @@ -1,28 +1,30 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict; +package cn.iocoder.yudao.module.system.service.dict; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictDataMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict.SysDictDataProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.impl.SysDictDataServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; +import cn.iocoder.yudao.module.system.mq.producer.dict.DictDataProducer; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; +import com.google.common.collect.ImmutableTable; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; +import java.util.Date; import java.util.List; import java.util.function.Consumer; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.hutool.core.bean.BeanUtil.getFieldValue; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -30,28 +32,54 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -/** -* {@link SysDictDataServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysDictDataServiceImpl.class) -public class SysDictDataServiceTest extends BaseDbUnitTest { +@Import(DictDataServiceImpl.class) +public class DictDataServiceTest extends BaseDbUnitTest { @Resource - private SysDictDataServiceImpl dictDataService; + private DictDataServiceImpl dictDataService; @Resource - private SysDictDataMapper dictDataMapper; + private DictDataMapper dictDataMapper; @MockBean - private SysDictTypeService dictTypeService; + private DictTypeService dictTypeService; @MockBean - private SysDictDataProducer dictDataProducer; + private DictDataProducer dictDataProducer; + + /** + * 测试加载到新的字典数据的情况 + */ + @Test + @SuppressWarnings("unchecked") + public void testInitLocalCache() { + // mock 数据 + DictDataDO dictData01 = randomDictDataDO(); + dictDataMapper.insert(dictData01); + DictDataDO dictData02 = randomDictDataDO(); + dictDataMapper.insert(dictData02); + + // 调用 + dictDataService.initLocalCache(); + // 断言 labelDictDataCache 缓存 + ImmutableTable labelDictDataCache = + (ImmutableTable) getFieldValue(dictDataService, "labelDictDataCache"); + assertEquals(2, labelDictDataCache.size()); + assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel())); + assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel())); + // 断言 valueDictDataCache 缓存 + ImmutableTable valueDictDataCache = + (ImmutableTable) getFieldValue(dictDataService, "valueDictDataCache"); + assertEquals(2, valueDictDataCache.size()); + assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue())); + assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue())); + // 断言 maxUpdateTime 缓存 + Date maxUpdateTime = (Date) getFieldValue(dictDataService, "maxUpdateTime"); + assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime); + } @Test public void testGetDictDataPage() { // mock 数据 - SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class, o -> { // 等会查询到 + DictDataDO dbDictData = randomPojo(DictDataDO.class, o -> { // 等会查询到 o.setLabel("芋艿"); o.setDictType("yunai"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -64,13 +92,13 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 准备参数 - SysDictDataPageReqVO reqVO = new SysDictDataPageReqVO(); + DictDataPageReqVO reqVO = new DictDataPageReqVO(); reqVO.setLabel("芋"); reqVO.setDictType("yu"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 调用 - PageResult pageResult = dictDataService.getDictDataPage(reqVO); + PageResult pageResult = dictDataService.getDictDataPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -80,7 +108,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { @Test public void testGetDictDataList() { // mock 数据 - SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class, o -> { // 等会查询到 + DictDataDO dbDictData = randomPojo(DictDataDO.class, o -> { // 等会查询到 o.setLabel("芋艿"); o.setDictType("yunai"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -93,13 +121,13 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 准备参数 - SysDictDataExportReqVO reqVO = new SysDictDataExportReqVO(); + DictDataExportReqVO reqVO = new DictDataExportReqVO(); reqVO.setLabel("芋"); reqVO.setDictType("yu"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 调用 - List list = dictDataService.getDictDatas(reqVO); + List list = dictDataService.getDictDatas(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbDictData, list.get(0)); @@ -108,7 +136,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { @Test public void testCreateDictData_success() { // 准备参数 - SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class, + DictDataCreateReqVO reqVO = randomPojo(DictDataCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); // mock 方法 when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType())); @@ -118,7 +146,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // 断言 assertNotNull(dictDataId); // 校验记录的属性是否正确 - SysDictDataDO dictData = dictDataMapper.selectById(dictDataId); + DictDataDO dictData = dictDataMapper.selectById(dictDataId); assertPojoEquals(reqVO, dictData); // 校验调用 verify(dictDataProducer, times(1)).sendDictDataRefreshMessage(); @@ -127,10 +155,10 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { @Test public void testUpdateDictData_success() { // mock 数据 - SysDictDataDO dbDictData = randomDictDataDO(); + DictDataDO dbDictData = randomDictDataDO(); dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> { + DictDataUpdateReqVO reqVO = randomPojo(DictDataUpdateReqVO.class, o -> { o.setId(dbDictData.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); }); @@ -140,7 +168,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // 调用 dictDataService.updateDictData(reqVO); // 校验是否更新正确 - SysDictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的 + DictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, dictData); // 校验调用 verify(dictDataProducer, times(1)).sendDictDataRefreshMessage(); @@ -149,7 +177,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { @Test public void testDeleteDictData_success() { // mock 数据 - SysDictDataDO dbDictData = randomDictDataDO(); + DictDataDO dbDictData = randomDictDataDO(); dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbDictData.getId(); @@ -165,7 +193,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { @Test public void testCheckDictDataExists_success() { // mock 数据 - SysDictDataDO dbDictData = randomDictDataDO(); + DictDataDO dbDictData = randomDictDataDO(); dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据 // 调用成功 @@ -197,7 +225,7 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // mock 方法,数据类型被禁用 String dictType = randomString(); when(dictTypeService.getDictType(eq(dictType))).thenReturn( - randomPojo(SysDictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + randomPojo(DictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 调用, 并断言异常 assertServiceException(() -> dictDataService.checkDictTypeValid(dictType), DICT_TYPE_NOT_ENABLE); @@ -245,21 +273,21 @@ public class SysDictDataServiceTest extends BaseDbUnitTest { // ========== 随机对象 ========== @SafeVarargs - private static SysDictDataDO randomDictDataDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static DictDataDO randomDictDataDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomCommonStatus()); // 保证 status 的范围 }; - return randomPojo(SysDictDataDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(DictDataDO.class, ArrayUtils.append(consumer, consumers)); } /** * 生成一个有效的字典类型 * * @param type 字典类型 - * @return SysDictTypeDO 对象 + * @return DictTypeDO 对象 */ - private static SysDictTypeDO randomDictTypeDO(String type) { - return randomPojo(SysDictTypeDO.class, o -> { + private static DictTypeDO randomDictTypeDO(String type) { + return randomPojo(DictTypeDO.class, o -> { o.setType(type); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 是开启 }); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java similarity index 76% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java index 8ca3638d21..406f1e8a44 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java @@ -1,17 +1,16 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.dict; +package cn.iocoder.yudao.module.system.service.dict; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.type.SysDictTypeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictTypeMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.dict.impl.SysDictTypeServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; +import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -21,7 +20,7 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; @@ -30,26 +29,21 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -/** -* {@link SysDictTypeServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysDictTypeServiceImpl.class) -public class SysDictTypeServiceTest extends BaseDbUnitTest { +@Import(DictTypeServiceImpl.class) +public class DictTypeServiceTest extends BaseDbUnitTest { @Resource - private SysDictTypeServiceImpl dictTypeService; + private DictTypeServiceImpl dictTypeService; @Resource - private SysDictTypeMapper dictTypeMapper; + private DictTypeMapper dictTypeMapper; @MockBean - private SysDictDataService dictDataService; + private DictDataService dictDataService; @Test public void testGetDictTypePage() { // mock 数据 - SysDictTypeDO dbDictType = randomPojo(SysDictTypeDO.class, o -> { // 等会查询到 + DictTypeDO dbDictType = randomPojo(DictTypeDO.class, o -> { // 等会查询到 o.setName("yunai"); o.setType("芋艿"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -65,7 +59,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 - SysDictTypePageReqVO reqVO = new SysDictTypePageReqVO(); + DictTypePageReqVO reqVO = new DictTypePageReqVO(); reqVO.setName("nai"); reqVO.setType("艿"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -73,7 +67,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2021, 1, 20)); // 调用 - PageResult pageResult = dictTypeService.getDictTypePage(reqVO); + PageResult pageResult = dictTypeService.getDictTypePage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -83,7 +77,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { @Test public void testGetDictTypeList() { // mock 数据 - SysDictTypeDO dbDictType = randomPojo(SysDictTypeDO.class, o -> { // 等会查询到 + DictTypeDO dbDictType = randomPojo(DictTypeDO.class, o -> { // 等会查询到 o.setName("yunai"); o.setType("芋艿"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -99,7 +93,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 - SysDictTypeExportReqVO reqVO = new SysDictTypeExportReqVO(); + DictTypeExportReqVO reqVO = new DictTypeExportReqVO(); reqVO.setName("nai"); reqVO.setType("艿"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -107,7 +101,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2021, 1, 20)); // 调用 - List list = dictTypeService.getDictTypeList(reqVO); + List list = dictTypeService.getDictTypeList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbDictType, list.get(0)); @@ -116,13 +110,13 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { @Test public void testGetDictType() { // mock 数据 - SysDictTypeDO dbDictType = randomDictTypeDO(); + DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType); // 准备参数 String type = dbDictType.getType(); // 调用 - SysDictTypeDO dictType = dictTypeService.getDictType(type); + DictTypeDO dictType = dictTypeService.getDictType(type); // 断言 assertNotNull(dictType); assertPojoEquals(dbDictType, dictType); @@ -131,7 +125,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { @Test public void testCreateDictType_success() { // 准备参数 - SysDictTypeCreateReqVO reqVO = randomPojo(SysDictTypeCreateReqVO.class, + DictTypeCreateReqVO reqVO = randomPojo(DictTypeCreateReqVO.class, o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())); // 调用 @@ -139,17 +133,17 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { // 断言 assertNotNull(dictTypeId); // 校验记录的属性是否正确 - SysDictTypeDO dictType = dictTypeMapper.selectById(dictTypeId); + DictTypeDO dictType = dictTypeMapper.selectById(dictTypeId); assertPojoEquals(reqVO, dictType); } @Test public void testUpdateDictType_success() { // mock 数据 - SysDictTypeDO dbDictType = randomDictTypeDO(); + DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysDictTypeUpdateReqVO reqVO = randomPojo(SysDictTypeUpdateReqVO.class, o -> { + DictTypeUpdateReqVO reqVO = randomPojo(DictTypeUpdateReqVO.class, o -> { o.setId(dbDictType.getId()); // 设置更新的 ID o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); }); @@ -157,14 +151,14 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { // 调用 dictTypeService.updateDictType(reqVO); // 校验是否更新正确 - SysDictTypeDO dictType = dictTypeMapper.selectById(reqVO.getId()); // 获取最新的 + DictTypeDO dictType = dictTypeMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, dictType); } @Test public void testDeleteDictType_success() { // mock 数据 - SysDictTypeDO dbDictType = randomDictTypeDO(); + DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbDictType.getId(); @@ -178,7 +172,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { @Test public void testDeleteDictType_hasChildren() { // mock 数据 - SysDictTypeDO dbDictType = randomDictTypeDO(); + DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbDictType.getId(); @@ -192,7 +186,7 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { @Test public void testCheckDictDataExists_success() { // mock 数据 - SysDictTypeDO dbDictType = randomDictTypeDO(); + DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据 // 调用成功 @@ -269,11 +263,11 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest { // ========== 随机对象 ========== @SafeVarargs - private static SysDictTypeDO randomDictTypeDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static DictTypeDO randomDictTypeDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 }; - return randomPojo(SysDictTypeDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(DictTypeDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java similarity index 64% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java index 56c0b34949..e16cbf1f29 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java @@ -1,23 +1,19 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.errorcode; +package cn.iocoder.yudao.module.system.service.errorcode; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.adminserver.modules.infra.enums.config.InfConfigTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.errorcode.vo.SysErrorCodeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.errorcode.SysErrorCodeMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.errorcode.impl.SysErrorCodeServiceImpl; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; +import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper; +import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.slf4j.Logger; import org.springframework.context.annotation.Import; import javax.annotation.Resource; @@ -25,68 +21,60 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_DUPLICATE; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_NOT_EXISTS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_NOT_EXISTS; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; -/** -* {@link SysErrorCodeServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysErrorCodeServiceImpl.class) -public class SysErrorCodeServiceTest extends BaseDbUnitTest { +@Import(ErrorCodeServiceImpl.class) +public class ErrorCodeServiceTest extends BaseDbUnitTest { @Resource - private SysErrorCodeServiceImpl errorCodeService; + private ErrorCodeServiceImpl errorCodeService; @Resource - private SysErrorCodeMapper errorCodeMapper; - - @Mock - private Logger log; + private ErrorCodeMapper errorCodeMapper; @Test public void testCreateErrorCode_success() { // 准备参数 - SysErrorCodeCreateReqVO reqVO = randomPojo(SysErrorCodeCreateReqVO.class); + ErrorCodeCreateReqVO reqVO = randomPojo(ErrorCodeCreateReqVO.class); // 调用 Long errorCodeId = errorCodeService.createErrorCode(reqVO); // 断言 assertNotNull(errorCodeId); // 校验记录的属性是否正确 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(errorCodeId); + ErrorCodeDO errorCode = errorCodeMapper.selectById(errorCodeId); assertPojoEquals(reqVO, errorCode); - assertEquals(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType(), errorCode.getType()); + assertEquals(ErrorCodeTypeEnum.MANUAL_OPERATION.getType(), errorCode.getType()); } @Test public void testUpdateErrorCode_success() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(); errorCodeMapper.insert(dbErrorCode);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysErrorCodeUpdateReqVO reqVO = randomPojo(SysErrorCodeUpdateReqVO.class, o -> { + ErrorCodeUpdateReqVO reqVO = randomPojo(ErrorCodeUpdateReqVO.class, o -> { o.setId(dbErrorCode.getId()); // 设置更新的 ID }); // 调用 errorCodeService.updateErrorCode(reqVO); // 校验是否更新正确 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(reqVO.getId()); // 获取最新的 + ErrorCodeDO errorCode = errorCodeMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, errorCode); - assertEquals(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType(), errorCode.getType()); + assertEquals(ErrorCodeTypeEnum.MANUAL_OPERATION.getType(), errorCode.getType()); } @Test public void testDeleteErrorCode_success() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(); errorCodeMapper.insert(dbErrorCode);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbErrorCode.getId(); @@ -100,10 +88,10 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testGetErrorCodePage() { // mock 数据 - SysErrorCodeDO dbErrorCode = initGetErrorCodePage(); + ErrorCodeDO dbErrorCode = initGetErrorCodePage(); // 准备参数 - SysErrorCodePageReqVO reqVO = new SysErrorCodePageReqVO(); - reqVO.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType()); + ErrorCodePageReqVO reqVO = new ErrorCodePageReqVO(); + reqVO.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); reqVO.setApplicationName("yudao"); reqVO.setCode(1); reqVO.setMessage("yu"); @@ -111,7 +99,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2020, 11, 30)); // 调用 - PageResult pageResult = errorCodeService.getErrorCodePage(reqVO); + PageResult pageResult = errorCodeService.getErrorCodePage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -121,9 +109,9 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { /** * 初始化 getErrorCodePage 方法的测试数据 */ - private SysErrorCodeDO initGetErrorCodePage() { - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> { // 等会查询到 - o.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType()); + private ErrorCodeDO initGetErrorCodePage() { + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> { // 等会查询到 + o.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); o.setApplicationName("yudaoyuanma"); o.setCode(1); o.setMessage("yudao"); @@ -131,7 +119,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { }); errorCodeMapper.insert(dbErrorCode); // 测试 type 不匹配 - errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType()))); + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType()))); // 测试 applicationName 不匹配 errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setApplicationName("yunai"))); // 测试 code 不匹配 @@ -146,10 +134,10 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testGetErrorCodeList() { // mock 数据 - SysErrorCodeDO dbErrorCode = initGetErrorCodePage(); + ErrorCodeDO dbErrorCode = initGetErrorCodePage(); // 准备参数 - SysErrorCodeExportReqVO reqVO = new SysErrorCodeExportReqVO(); - reqVO.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType()); + ErrorCodeExportReqVO reqVO = new ErrorCodeExportReqVO(); + reqVO.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); reqVO.setApplicationName("yudao"); reqVO.setCode(1); reqVO.setMessage("yu"); @@ -157,7 +145,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2020, 11, 30)); // 调用 - List list = errorCodeService.getErrorCodeList(reqVO); + List list = errorCodeService.getErrorCodeList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbErrorCode, list.get(0)); @@ -206,18 +194,18 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { // 调用 errorCodeService.autoGenerateErrorCodes(Lists.newArrayList(generateReqDTO)); // 断言 - SysErrorCodeDO errorCode = errorCodeMapper.selectOne(null); + ErrorCodeDO errorCode = errorCodeMapper.selectOne(null); assertPojoEquals(generateReqDTO, errorCode); - assertEquals(SysErrorCodeTypeEnum.AUTO_GENERATION.getType(), errorCode.getType()); + assertEquals(ErrorCodeTypeEnum.AUTO_GENERATION.getType(), errorCode.getType()); } /** - * 情况 2.1,错误码存在,但是是 SysErrorCodeTypeEnum.MANUAL_OPERATION 类型 + * 情况 2.1,错误码存在,但是是 ErrorCodeTypeEnum.MANUAL_OPERATION 类型 */ @Test public void testAutoGenerateErrorCodes_021() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType())); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType())); errorCodeMapper.insert(dbErrorCode); // 准备参数 ErrorCodeAutoGenerateReqDTO generateReqDTO = randomPojo(ErrorCodeAutoGenerateReqDTO.class, @@ -227,7 +215,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { // 调用 errorCodeService.autoGenerateErrorCodes(Lists.newArrayList(generateReqDTO)); // 断言,相等,说明不会更新 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); + ErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); assertPojoEquals(dbErrorCode, errorCode); } @@ -237,7 +225,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testAutoGenerateErrorCodes_022() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType())); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType())); errorCodeMapper.insert(dbErrorCode); // 准备参数 ErrorCodeAutoGenerateReqDTO generateReqDTO = randomPojo(ErrorCodeAutoGenerateReqDTO.class, @@ -247,7 +235,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { // 调用 errorCodeService.autoGenerateErrorCodes(Lists.newArrayList(generateReqDTO)); // 断言,相等,说明不会更新 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); + ErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); assertPojoEquals(dbErrorCode, errorCode); } @@ -257,7 +245,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testAutoGenerateErrorCodes_023() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType())); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType())); errorCodeMapper.insert(dbErrorCode); // 准备参数 ErrorCodeAutoGenerateReqDTO generateReqDTO = randomPojo(ErrorCodeAutoGenerateReqDTO.class, @@ -268,7 +256,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { // 调用 errorCodeService.autoGenerateErrorCodes(Lists.newArrayList(generateReqDTO)); // 断言,相等,说明不会更新 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); + ErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); assertPojoEquals(dbErrorCode, errorCode); } @@ -278,7 +266,7 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testAutoGenerateErrorCodes_024() { // mock 数据 - SysErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType())); + ErrorCodeDO dbErrorCode = randomInfErrorCodeDO(o -> o.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType())); errorCodeMapper.insert(dbErrorCode); // 准备参数 ErrorCodeAutoGenerateReqDTO generateReqDTO = randomPojo(ErrorCodeAutoGenerateReqDTO.class, @@ -288,18 +276,18 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest { // 调用 errorCodeService.autoGenerateErrorCodes(Lists.newArrayList(generateReqDTO)); // 断言,匹配 - SysErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); + ErrorCodeDO errorCode = errorCodeMapper.selectById(dbErrorCode.getId()); assertPojoEquals(generateReqDTO, errorCode); } // ========== 随机对象 ========== @SafeVarargs - private static SysErrorCodeDO randomInfErrorCodeDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setType(randomEle(InfConfigTypeEnum.values()).getType()); // 保证 key 的范围 + private static ErrorCodeDO randomInfErrorCodeDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setType(randomEle(ErrorCodeTypeEnum.values()).getType()); // 保证 key 的范围 }; - return randomPojo(SysErrorCodeDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(ErrorCodeDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java similarity index 57% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java index 820ee51677..1d59a64d07 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java @@ -1,57 +1,58 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger; +package cn.iocoder.yudao.module.system.service.logger; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.impl.SysLoginLogServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.List; +import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static org.junit.jupiter.api.Assertions.assertEquals; -@Import(SysLoginLogServiceImpl.class) -public class SysLoginLogServiceImplTest extends BaseDbUnitTest { +@Import(LoginLogServiceImpl.class) +public class LoginLogServiceImplTest extends BaseDbUnitTest { @Resource - private SysLoginLogServiceImpl sysLoginLogService; + private LoginLogServiceImpl loginLogService; @Resource - private SysLoginLogMapper loginLogMapper; + private LoginLogMapper loginLogMapper; @Test public void testGetLoginLogPage() { // 构造测试数据 // 登录成功的 - SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { - logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); + LoginLogDO loginLogDO = RandomUtils.randomPojo(LoginLogDO.class, logDO -> { + logDO.setLogType(RandomUtil.randomEle(cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum.values()).getType()); logDO.setTraceId(TracerUtils.getTraceId()); logDO.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()); logDO.setUserIp("192.168.199.16"); logDO.setUsername("wangkai"); logDO.setCreateTime(buildTime(2021, 3, 6)); - logDO.setResult(SysLoginResultEnum.SUCCESS.getResult()); + logDO.setResult(cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.SUCCESS.getResult()); }); loginLogMapper.insert(loginLogDO); // 下面几个都是不匹配的数据 // 登录失败的 - loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); // 不同ip段的 loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18"))); // 不同username @@ -61,7 +62,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { // 构造调用参数 - SysLoginLogPageReqVO reqVO = new SysLoginLogPageReqVO(); + LoginLogPageReqVO reqVO = new LoginLogPageReqVO(); reqVO.setUsername("wangkai"); reqVO.setUserIp("192.168.199"); reqVO.setStatus(true); @@ -69,7 +70,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { reqVO.setEndTime(buildTime(2021, 3, 7)); // 调用service方法 - PageResult pageResult = sysLoginLogService.getLoginLogPage(reqVO); + PageResult pageResult = loginLogService.getLoginLogPage(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, pageResult.getTotal()); @@ -82,21 +83,21 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { // 构造测试数据 // 登录成功的 - SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { - logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); + LoginLogDO loginLogDO = RandomUtils.randomPojo(LoginLogDO.class, logDO -> { + logDO.setLogType(RandomUtil.randomEle(cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum.values()).getType()); logDO.setTraceId(TracerUtils.getTraceId()); logDO.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()); logDO.setUserIp("192.168.111.16"); logDO.setUsername("wangxiaokai"); logDO.setCreateTime(buildTime(2021, 3, 6)); - logDO.setResult(SysLoginResultEnum.SUCCESS.getResult()); + logDO.setResult(cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.SUCCESS.getResult()); }); loginLogMapper.insert(loginLogDO); // 下面几个都是不匹配的数据 // 登录失败的 - loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); // 不同ip段的 loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18"))); // 不同username @@ -106,7 +107,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { // 构造调用参数 - SysLoginLogExportReqVO reqVO = new SysLoginLogExportReqVO(); + LoginLogExportReqVO reqVO = new LoginLogExportReqVO(); reqVO.setUsername("wangxiaokai"); reqVO.setUserIp("192.168.111"); reqVO.setStatus(true); @@ -115,10 +116,28 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { // 调用service方法 - List loginLogList = sysLoginLogService.getLoginLogList(reqVO); + List loginLogList = loginLogService.getLoginLogList(reqVO); // 断言 assertEquals(1, loginLogList.size()); assertPojoEquals(loginLogDO, loginLogList.get(0)); } + + @Test + public void testCreateLoginLog() { + LoginLogCreateReqDTO reqDTO = RandomUtils.randomPojo(LoginLogCreateReqDTO.class, vo -> { + // 指定随机的范围,避免超出范围入库失败 + vo.setUserType(randomEle(UserTypeEnum.values()).getValue()); + vo.setLogType(randomEle(LoginLogTypeEnum.values()).getType()); + vo.setResult(randomEle(LoginResultEnum.values()).getResult()); + vo.setTraceId(TracerUtils.getTraceId()); + }); + + // 调用 + loginLogService.createLoginLog(reqDTO); + // 断言,忽略基本字段 + LoginLogDO sysLoginLogDO = loginLogMapper.selectOne(null); + assertPojoEquals(reqDTO, sysLoginLogDO); + } + } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java similarity index 76% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java index f375be35b1..b7bbcbed10 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java @@ -1,15 +1,13 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.logger; +package cn.iocoder.yudao.module.system.service.logger; import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysOperateLogDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysOperateLogMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.logger.impl.SysOperateLogServiceImpl; -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -18,6 +16,7 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -34,17 +33,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; -@Import({SysOperateLogServiceImpl.class}) -public class SysOperateLogServiceImplTest extends BaseDbUnitTest { +@Import({OperateLogServiceImpl.class}) +public class OperateLogServiceImplTest extends BaseDbUnitTest { @Resource - private SysOperateLogService operateLogServiceImpl; + private OperateLogService operateLogServiceImpl; @Resource - private SysOperateLogMapper operateLogMapper; + private OperateLogMapper operateLogMapper; @MockBean - private SysUserService userService; + private AdminUserService userService; @Test public void testCreateOperateLogAsync() throws InterruptedException, ExecutionException { @@ -59,7 +58,7 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { Future future = operateLogServiceImpl.createOperateLogAsync(reqVO); future.get(); // 断言插入是否正确 - SysOperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId); + OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId); assertPojoEquals(reqVO, sysOperateLogDO); } @@ -67,15 +66,15 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { public void testGetOperateLogPage() { // 构造测试数据 // 先构造用户 - SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, o -> { + AdminUserDO user = RandomUtils.randomPojo(AdminUserDO.class, o -> { o.setNickname("wangkai"); - o.setSex(SysSexEnum.MALE.getSex()); + o.setSex(SexEnum.MALE.getSex()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(userService.getUsersByNickname("wangkai")).thenReturn(Collections.singletonList(user)); Long userId = user.getId(); // 构造操作日志 - SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, o -> { + OperateLogDO sysOperateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> { o.setUserId(userId); o.setModule("order"); o.setType(OperateTypeEnum.CREATE.getType()); @@ -98,7 +97,7 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode()))); // 构造调用参数 - SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO(); + OperateLogPageReqVO reqVO = new OperateLogPageReqVO(); reqVO.setUserNickname("wangkai"); reqVO.setModule("order"); reqVO.setType(OperateTypeEnum.CREATE.getType()); @@ -107,7 +106,7 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { reqVO.setSuccess(true); // 调用service方法 - PageResult pageResult = operateLogServiceImpl.getOperateLogPage(reqVO); + PageResult pageResult = operateLogServiceImpl.getOperateLogPage(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -118,15 +117,15 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { public void testGetOperateLogs() { // 构造测试数据 // 先构造用户 - SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, o -> { + AdminUserDO user = RandomUtils.randomPojo(AdminUserDO.class, o -> { o.setNickname("wangkai"); - o.setSex(SysSexEnum.MALE.getSex()); + o.setSex(SexEnum.MALE.getSex()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(userService.getUsersByNickname("wangkai")).thenReturn(Collections.singletonList(user)); Long userId = user.getId(); // 构造操作日志 - SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, o -> { + OperateLogDO sysOperateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> { o.setUserId(userId); o.setModule("order"); o.setType(OperateTypeEnum.CREATE.getType()); @@ -149,7 +148,7 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode()))); // 构造调用参数 - SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO(); + OperateLogExportReqVO reqVO = new OperateLogExportReqVO(); reqVO.setUserNickname("wangkai"); reqVO.setModule("order"); reqVO.setType(OperateTypeEnum.CREATE.getType()); @@ -158,7 +157,7 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest { reqVO.setSuccess(true); // 调用 service 方法 - List list = operateLogServiceImpl.getOperateLogs(reqVO); + List list = operateLogServiceImpl.getOperateLogs(reqVO); // 断言,只查到了一条符合条件的 assertEquals(1, list.size()); assertPojoEquals(sysOperateLogDO, list.get(0)); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java similarity index 58% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java index 8d1325544b..ed0a707b5a 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.notice; +package cn.iocoder.yudao.module.system.service.notice; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.notice.vo.SysNoticeUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice.SysNoticeDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.notice.SysNoticeMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.service.notice.impl.SysNoticeServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; +import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper; +import cn.iocoder.yudao.module.system.enums.notice.NoticeTypeEnum; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -19,29 +18,29 @@ import javax.annotation.Resource; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.NOTICE_NOT_FOUND; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.*; -@Import(SysNoticeServiceImpl.class) -class SysNoticeServiceImplTest extends BaseDbUnitTest { +@Import(NoticeServiceImpl.class) +class NoticeServiceImplTest extends BaseDbUnitTest { @Resource - private SysNoticeServiceImpl sysNoticeService; + private NoticeServiceImpl sysNoticeService; @Resource - private SysNoticeMapper sysNoticeMapper; + private NoticeMapper sysNoticeMapper; @Test public void testPageNotices_success() { // 插入前置数据 - SysNoticeDO dbNotice = randomPojo(SysNoticeDO.class, o -> { + NoticeDO dbNotice = randomPojo(NoticeDO.class, o -> { o.setTitle("尼古拉斯赵四来啦!"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setType(randomEle(SysNoticeTypeEnum.values()).getType()); + o.setType(randomEle(NoticeTypeEnum.values()).getType()); }); sysNoticeMapper.insert(dbNotice); @@ -52,10 +51,10 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest { // 查询 - SysNoticePageReqVO reqVO = new SysNoticePageReqVO(); + NoticePageReqVO reqVO = new NoticePageReqVO(); reqVO.setTitle("尼古拉斯赵四来啦!"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - PageResult pageResult = sysNoticeService.pageNotices(reqVO); + PageResult pageResult = sysNoticeService.pageNotices(reqVO); // 验证查询结果经过筛选 assertEquals(1, pageResult.getTotal()); @@ -67,11 +66,11 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest { @Test public void testGetNotice_success() { // 插入前置数据 - SysNoticeDO dbNotice = randomSysNoticeDO(); + NoticeDO dbNotice = randomNoticeDO(); sysNoticeMapper.insert(dbNotice); // 查询 - SysNoticeDO notice = sysNoticeService.getNotice(dbNotice.getId()); + NoticeDO notice = sysNoticeService.getNotice(dbNotice.getId()); // 验证插入与读取对象是否一致 assertNotNull(notice); @@ -81,38 +80,38 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest { @Test public void testCreateNotice_success() { // 准备参数 - SysNoticeCreateReqVO reqVO = randomSysNoticeCreateReqVO(); + NoticeCreateReqVO reqVO = randomNoticeCreateReqVO(); // 校验插入是否成功 Long noticeId = sysNoticeService.createNotice(reqVO); assertNotNull(noticeId); // 校验插入属性是否正确 - SysNoticeDO notice = sysNoticeMapper.selectById(noticeId); + NoticeDO notice = sysNoticeMapper.selectById(noticeId); assertPojoEquals(reqVO, notice); } @Test public void testUpdateNotice_success() { // 插入前置数据 - SysNoticeDO dbNoticeDO = randomSysNoticeDO(); + NoticeDO dbNoticeDO = randomNoticeDO(); sysNoticeMapper.insert(dbNoticeDO); // 准备更新参数 - SysNoticeUpdateReqVO reqVO = randomSysNoticeUpdateReqVO(o -> o.setId(dbNoticeDO.getId())); + NoticeUpdateReqVO reqVO = randomNoticeUpdateReqVO(o -> o.setId(dbNoticeDO.getId())); // 更新 sysNoticeService.updateNotice(reqVO); // 检验是否更新成功 - SysNoticeDO notice = sysNoticeMapper.selectById(reqVO.getId()); + NoticeDO notice = sysNoticeMapper.selectById(reqVO.getId()); assertPojoEquals(reqVO, notice); } @Test public void testDeleteNotice_success() { // 插入前置数据 - SysNoticeDO dbNotice = randomSysNoticeDO(); + NoticeDO dbNotice = randomNoticeDO(); sysNoticeMapper.insert(dbNotice); // 删除 @@ -125,7 +124,7 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest { @Test public void checkNoticeExists_success() { // 插入前置数据 - SysNoticeDO dbNotice = randomSysNoticeDO(); + NoticeDO dbNotice = randomNoticeDO(); sysNoticeMapper.insert(dbNotice); // 成功调用 @@ -138,24 +137,24 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest { } @SafeVarargs - private static SysNoticeDO randomSysNoticeDO(Consumer... consumers) { - SysNoticeDO notice = randomPojo(SysNoticeDO.class, consumers); - notice.setType(randomEle(SysNoticeTypeEnum.values()).getType()); + private static NoticeDO randomNoticeDO(Consumer... consumers) { + NoticeDO notice = randomPojo(NoticeDO.class, consumers); + notice.setType(randomEle(NoticeTypeEnum.values()).getType()); notice.setStatus(CommonStatusEnum.ENABLE.getStatus()); return notice; } @SafeVarargs - private static SysNoticeUpdateReqVO randomSysNoticeUpdateReqVO(Consumer... consumers) { - SysNoticeUpdateReqVO reqVO = randomPojo(SysNoticeUpdateReqVO.class, consumers); - reqVO.setType(randomEle(SysNoticeTypeEnum.values()).getType()); + private static NoticeUpdateReqVO randomNoticeUpdateReqVO(Consumer... consumers) { + NoticeUpdateReqVO reqVO = randomPojo(NoticeUpdateReqVO.class, consumers); + reqVO.setType(randomEle(NoticeTypeEnum.values()).getType()); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); return reqVO; } - private static SysNoticeCreateReqVO randomSysNoticeCreateReqVO() { - SysNoticeCreateReqVO reqVO = randomPojo(SysNoticeCreateReqVO.class); - reqVO.setType(randomEle(SysNoticeTypeEnum.values()).getType()); + private static NoticeCreateReqVO randomNoticeCreateReqVO() { + NoticeCreateReqVO reqVO = randomPojo(NoticeCreateReqVO.class); + reqVO.setType(randomEle(NoticeTypeEnum.values()).getType()); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); return reqVO; } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceTest.java similarity index 65% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceTest.java index e9dab50a42..5c777eda7d 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysMenuServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceTest.java @@ -1,22 +1,19 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuListReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysMenuMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysMenuProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysMenuServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; +import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; +import cn.iocoder.yudao.module.system.mq.producer.permission.MenuProducer; import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils; -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import com.google.common.collect.Multimap; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -24,49 +21,49 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.*; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.verify; -@Import(SysMenuServiceImpl.class) -public class SysMenuServiceTest extends BaseDbUnitTest { +@Import(MenuServiceImpl.class) +public class MenuServiceTest extends BaseDbUnitTest { @Resource - private SysMenuServiceImpl sysMenuService; + private MenuServiceImpl sysMenuService; @MockBean - private SysPermissionService sysPermissionService; + private PermissionService sysPermissionService; @MockBean - private SysMenuProducer sysMenuProducer; + private MenuProducer sysMenuProducer; @Resource - private SysMenuMapper menuMapper; + private MenuMapper menuMapper; @Test public void testInitLocalCache_success() throws Exception { - SysMenuDO menuDO1 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); + MenuDO menuDO1 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); menuMapper.insert(menuDO1); - SysMenuDO menuDO2 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); + MenuDO menuDO2 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L); menuMapper.insert(menuDO2); // 调用 sysMenuService.initLocalCache(); // 获取代理对象 - SysMenuServiceImpl target = (SysMenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); + MenuServiceImpl target = (MenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); - Map menuCache = - (Map) BeanUtil.getFieldValue(target, "menuCache"); + Map menuCache = + (Map) BeanUtil.getFieldValue(target, "menuCache"); Assert.isTrue(menuCache.size() == 2); assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId())); assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId())); - Multimap permissionMenuCache = - (Multimap) BeanUtil.getFieldValue(target, "permissionMenuCache"); + Multimap permissionMenuCache = + (Multimap) BeanUtil.getFieldValue(target, "permissionMenuCache"); Assert.isTrue(permissionMenuCache.size() == 2); assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission())); assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission())); @@ -78,23 +75,23 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testCreateMenu_success() { //构造父目录 - SysMenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); + MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); menuMapper.insert(menuDO); Long parentId = menuDO.getId(); //调用 - SysMenuCreateReqVO vo = randomPojo(SysMenuCreateReqVO.class, o -> { + MenuCreateReqVO vo = randomPojo(MenuCreateReqVO.class, o -> { o.setParentId(parentId); o.setName("testSonName"); o.setType(MenuTypeEnum.MENU.getType()); - o.setStatus(RandomUtils.randomCommonStatus()); + o.setStatus(randomCommonStatus()); }); Long menuId = sysMenuService.createMenu(vo); //断言 - Assertions.assertNotNull(menuId); + assertNotNull(menuId); // 校验记录的属性是否正确 - SysMenuDO ret = menuMapper.selectById(menuId); + MenuDO ret = menuMapper.selectById(menuId); assertPojoEquals(vo, ret); // 校验调用 verify(sysMenuProducer).sendMenuRefreshMessage(); @@ -103,23 +100,23 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testUpdateMenu_success() { //构造父子目录 - SysMenuDO sonMenuDO = initParentAndSonMenuDO(); + MenuDO sonMenuDO = initParentAndSonMenuDO(); Long sonId = sonMenuDO.getId(); Long parentId = sonMenuDO.getParentId(); //调用 - SysMenuUpdateReqVO vo = randomPojo(SysMenuUpdateReqVO.class, o -> { + MenuUpdateReqVO vo = randomPojo(MenuUpdateReqVO.class, o -> { o.setId(sonId); o.setParentId(parentId); o.setType(MenuTypeEnum.MENU.getType()); - o.setStatus(RandomUtils.randomCommonStatus()); + o.setStatus(randomCommonStatus()); o.setName("pppppp"); //修改名字 }); sysMenuService.updateMenu(vo); //断言 // 校验记录的属性是否正确 - SysMenuDO ret = menuMapper.selectById(sonId); + MenuDO ret = menuMapper.selectById(sonId); assertPojoEquals(vo, ret); // 校验调用 verify(sysMenuProducer).sendMenuRefreshMessage(); @@ -131,11 +128,11 @@ public class SysMenuServiceTest extends BaseDbUnitTest { Long parentId = 10000L; //调用 - SysMenuUpdateReqVO vo = randomPojo(SysMenuUpdateReqVO.class, o -> { + MenuUpdateReqVO vo = randomPojo(MenuUpdateReqVO.class, o -> { o.setId(sonId); o.setParentId(parentId); o.setType(MenuTypeEnum.MENU.getType()); - o.setStatus(RandomUtils.randomCommonStatus()); + o.setStatus(randomCommonStatus()); }); //断言 assertServiceException(() -> sysMenuService.updateMenu(vo), MENU_NOT_EXISTS); @@ -143,14 +140,14 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testDeleteMenu_success() { - SysMenuDO sonMenuDO = initParentAndSonMenuDO(); + MenuDO sonMenuDO = initParentAndSonMenuDO(); Long sonId = sonMenuDO.getId(); // 调用 sysMenuService.deleteMenu(sonId); // 断言 - SysMenuDO menuDO = menuMapper.selectById(sonId); + MenuDO menuDO = menuMapper.selectById(sonId); assertNull(menuDO); verify(sysPermissionService).processMenuDeleted(sonId); verify(sysMenuProducer).sendMenuRefreshMessage(); @@ -165,7 +162,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testDeleteMenu_existChildren() { - SysMenuDO sonMenu = initParentAndSonMenuDO(); + MenuDO sonMenu = initParentAndSonMenuDO(); Long parentId = sonMenu.getParentId(); assertServiceException(() -> sysMenuService.deleteMenu(parentId), MENU_EXISTS_CHILDREN); @@ -173,17 +170,17 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testGetMenus_success() { - Map idMenuMap = new HashMap<>(); - SysMenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); + Map idMenuMap = new HashMap<>(); + MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); menuMapper.insert(menuDO); idMenuMap.put(menuDO.getId(), menuDO); - SysMenuDO sonMenu = createMenuDO(MenuTypeEnum.MENU, "son", menuDO.getId()); + MenuDO sonMenu = createMenuDO(MenuTypeEnum.MENU, "son", menuDO.getId()); menuMapper.insert(sonMenu); idMenuMap.put(sonMenu.getId(), sonMenu); // 调用 - List menuDOS = sysMenuService.getMenus(); + List menuDOS = sysMenuService.getMenus(); // 断言 assertEquals(menuDOS.size(), idMenuMap.size()); @@ -192,9 +189,9 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testGetMenusReqVo_success() { - Map idMenuMap = new HashMap<>(); + Map idMenuMap = new HashMap<>(); // 用于验证可以模糊搜索名称包含"name",状态为1的menu - SysMenuDO menu = createMenuDO(MenuTypeEnum.MENU, "name2", 0L, 1); + MenuDO menu = createMenuDO(MenuTypeEnum.MENU, "name2", 0L, 1); menuMapper.insert(menu); idMenuMap.put(menu.getId(), menu); @@ -213,10 +210,10 @@ public class SysMenuServiceTest extends BaseDbUnitTest { menuMapper.insert(menu); // 调用 - SysMenuListReqVO reqVO = new SysMenuListReqVO(); + MenuListReqVO reqVO = new MenuListReqVO(); reqVO.setStatus(1); reqVO.setName("name"); - List menuDOS = sysMenuService.getMenus(reqVO); + List menuDOS = sysMenuService.getMenus(reqVO); // 断言 assertEquals(menuDOS.size(), idMenuMap.size()); @@ -225,14 +222,14 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testListMenusFromCache_success() throws Exception { - Map mockCacheMap = new HashMap<>(); + Map mockCacheMap = new HashMap<>(); // 获取代理对象 - SysMenuServiceImpl target = (SysMenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); + MenuServiceImpl target = (MenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); BeanUtil.setFieldValue(target, "menuCache", mockCacheMap); - Map idMenuMap = new HashMap<>(); + Map idMenuMap = new HashMap<>(); // 用于验证搜索类型为MENU,状态为1的menu - SysMenuDO menuDO = createMenuDO(1L, MenuTypeEnum.MENU, "name", 0L, 1); + MenuDO menuDO = createMenuDO(1L, MenuTypeEnum.MENU, "name", 0L, 1); mockCacheMap.put(menuDO.getId(), menuDO); idMenuMap.put(menuDO.getId(), menuDO); @@ -246,7 +243,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { menuDO = createMenuDO(4L, MenuTypeEnum.MENU, "name", 0L, 2); mockCacheMap.put(menuDO.getId(), menuDO); - List menuDOS = sysMenuService.listMenusFromCache(Collections.singletonList(MenuTypeEnum.MENU.getType()), + List menuDOS = sysMenuService.listMenusFromCache(Collections.singletonList(MenuTypeEnum.MENU.getType()), Collections.singletonList(CommonStatusEnum.DISABLE.getStatus())); assertEquals(menuDOS.size(), idMenuMap.size()); menuDOS.forEach(m -> assertPojoEquals(idMenuMap.get(m.getId()), m)); @@ -254,14 +251,14 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testListMenusFromCache2_success() throws Exception { - Map mockCacheMap = new HashMap<>(); + Map mockCacheMap = new HashMap<>(); // 获取代理对象 - SysMenuServiceImpl target = (SysMenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); + MenuServiceImpl target = (MenuServiceImpl) SpringAopUtils.getTarget(sysMenuService); BeanUtil.setFieldValue(target, "menuCache", mockCacheMap); - Map idMenuMap = new HashMap<>(); + Map idMenuMap = new HashMap<>(); // 验证搜索id为1, 类型为MENU, 状态为1 的menu - SysMenuDO menuDO = createMenuDO(1L, MenuTypeEnum.MENU, "name", 0L, 1); + MenuDO menuDO = createMenuDO(1L, MenuTypeEnum.MENU, "name", 0L, 1); mockCacheMap.put(menuDO.getId(), menuDO); idMenuMap.put(menuDO.getId(), menuDO); @@ -273,7 +270,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { menuDO = createMenuDO(4L, MenuTypeEnum.MENU, "name", 0L, 2); mockCacheMap.put(menuDO.getId(), menuDO); - List menuDOS = sysMenuService.listMenusFromCache(Collections.singletonList(1L), + List menuDOS = sysMenuService.listMenusFromCache(Collections.singletonList(1L), Collections.singletonList(MenuTypeEnum.MENU.getType()), Collections.singletonList(1)); assertEquals(menuDOS.size(), idMenuMap.size()); menuDOS.forEach(menu -> assertPojoEquals(idMenuMap.get(menu.getId()), menu)); @@ -281,7 +278,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testCheckParentResource_success() { - SysMenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); + MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); menuMapper.insert(menuDO); Long parentId = menuDO.getId(); @@ -300,7 +297,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testCheckParentResource_parentTypeError() { - SysMenuDO menuDO = createMenuDO(MenuTypeEnum.BUTTON, "parent", 0L); + MenuDO menuDO = createMenuDO(MenuTypeEnum.BUTTON, "parent", 0L); menuMapper.insert(menuDO); Long parentId = menuDO.getId(); @@ -309,7 +306,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testCheckResource_success() { - SysMenuDO sonMenu = initParentAndSonMenuDO(); + MenuDO sonMenu = initParentAndSonMenuDO(); Long parentId = sonMenu.getParentId(); Long otherSonMenuId = randomLongId(); @@ -320,7 +317,7 @@ public class SysMenuServiceTest extends BaseDbUnitTest { @Test public void testCheckResource_sonMenuNameDuplicate(){ - SysMenuDO sonMenu=initParentAndSonMenuDO(); + MenuDO sonMenu=initParentAndSonMenuDO(); Long parentId=sonMenu.getParentId(); Long otherSonMenuId=randomLongId(); @@ -334,27 +331,27 @@ public class SysMenuServiceTest extends BaseDbUnitTest { * * @return */ - private SysMenuDO initParentAndSonMenuDO() { + private MenuDO initParentAndSonMenuDO() { //构造父子目录 - SysMenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); + MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L); menuMapper.insert(menuDO); Long parentId = menuDO.getId(); - SysMenuDO sonMenuDO = createMenuDO(MenuTypeEnum.MENU, "testSonName", parentId); + MenuDO sonMenuDO = createMenuDO(MenuTypeEnum.MENU, "testSonName", parentId); menuMapper.insert(sonMenuDO); return sonMenuDO; } - private SysMenuDO createMenuDO(MenuTypeEnum typeEnum, String menuName, Long parentId) { - return createMenuDO(typeEnum, menuName, parentId, RandomUtils.randomCommonStatus()); + private MenuDO createMenuDO(MenuTypeEnum typeEnum, String menuName, Long parentId) { + return createMenuDO(typeEnum, menuName, parentId, randomCommonStatus()); } - private SysMenuDO createMenuDO(MenuTypeEnum typeEnum, String menuName, Long parentId, Integer status) { + private MenuDO createMenuDO(MenuTypeEnum typeEnum, String menuName, Long parentId, Integer status) { return createMenuDO(null, typeEnum, menuName, parentId, status); } - private SysMenuDO createMenuDO(Long id, MenuTypeEnum typeEnum, String menuName, Long parentId, Integer status) { - return randomPojo(SysMenuDO.class, o -> { + private MenuDO createMenuDO(Long id, MenuTypeEnum typeEnum, String menuName, Long parentId, Integer status) { + return randomPojo(MenuDO.class, o -> { o.setId(id); o.setParentId(parentId); o.setType(typeEnum.getType()); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java similarity index 64% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java index 3dd74408d5..dc6a99ed97 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java @@ -1,19 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysPermissionServiceImpl; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; +import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; +import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; +import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -31,50 +30,50 @@ import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@Import(SysPermissionServiceImpl.class) -public class SysPermissionServiceTest extends BaseDbUnitTest { +@Import(PermissionServiceImpl.class) +public class PermissionServiceTest extends BaseDbUnitTest { @Resource - private SysPermissionServiceImpl permissionService; + private PermissionServiceImpl permissionService; @Resource - private SysRoleMenuMapper roleMenuMapper; + private RoleMenuMapper roleMenuMapper; @Resource - private SysUserRoleMapper userRoleMapper; + private UserRoleMapper userRoleMapper; @MockBean - private SysRoleService roleService; + private RoleService roleService; @MockBean - private SysMenuService menuService; + private MenuService menuService; @MockBean - private SysDeptService deptService; + private DeptService deptService; @MockBean - private SysPermissionProducer permissionProducer; + private PermissionProducer permissionProducer; @Test public void testProcessRoleDeleted() { // 准备参数 Long roleId = randomLongId(); // mock 数据 UserRole - SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除 + UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除 userRoleMapper.insert(userRoleDO01); - SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除 + UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除 userRoleMapper.insert(userRoleDO02); // mock 数据 RoleMenu - SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除 + RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除 roleMenuMapper.insert(roleMenuDO01); - SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除 + RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除 roleMenuMapper.insert(roleMenuDO02); // 调用 permissionService.processRoleDeleted(roleId); // 断言数据 RoleMenuDO - List dbRoleMenus = roleMenuMapper.selectList(); + List dbRoleMenus = roleMenuMapper.selectList(); assertEquals(1, dbRoleMenus.size()); assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02); // 断言数据 UserRoleDO - List dbUserRoles = userRoleMapper.selectList(); + List dbUserRoles = userRoleMapper.selectList(); assertEquals(1, dbUserRoles.size()); assertPojoEquals(dbUserRoles.get(0), userRoleDO02); // 断言调用 @@ -86,15 +85,15 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 Long menuId = randomLongId(); // mock 数据 - SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除 + RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除 roleMenuMapper.insert(roleMenuDO01); - SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除 + RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除 roleMenuMapper.insert(roleMenuDO02); // 调用 permissionService.processMenuDeleted(menuId); // 断言数据 - List dbRoleMenus = roleMenuMapper.selectList(); + List dbRoleMenus = roleMenuMapper.selectList(); assertEquals(1, dbRoleMenus.size()); assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02); // 断言调用 @@ -106,15 +105,15 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 Long userId = randomLongId(); // mock 数据 - SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setUserId(userId)); // 被删除 + UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(userId)); // 被删除 userRoleMapper.insert(userRoleDO01); - SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除 + UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除 userRoleMapper.insert(userRoleDO02); // 调用 permissionService.processUserDeleted(userId); // 断言数据 - List dbUserRoles = userRoleMapper.selectList(); + List dbUserRoles = userRoleMapper.selectList(); assertEquals(1, dbUserRoles.size()); assertPojoEquals(dbUserRoles.get(0), userRoleDO02); } @@ -125,7 +124,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法 DeptDataPermissionRespDTO respDTO = new DeptDataPermissionRespDTO(); - loginUser.setContext(SysPermissionServiceImpl.CONTEXT_KEY, respDTO); + loginUser.setContext(PermissionServiceImpl.CONTEXT_KEY, respDTO); // 调用 DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser); @@ -138,7 +137,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法 - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())); + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())); when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO)); // 调用 @@ -147,7 +146,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { assertTrue(result.getAll()); assertFalse(result.getSelf()); assertTrue(CollUtil.isEmpty(result.getDeptIds())); - assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); + assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); } @Test @@ -155,7 +154,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法 - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())); + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())); when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO)); // 调用 @@ -166,7 +165,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size()); assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds())); assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId())); - assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); + assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); } @Test @@ -174,7 +173,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法 - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())); + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())); when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO)); // 调用 @@ -184,7 +183,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { assertFalse(result.getSelf()); assertEquals(1, result.getDeptIds().size()); assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId())); - assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); + assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); } @Test @@ -192,10 +191,10 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法(角色) - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())); + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())); when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO)); // mock 方法(部门) - SysDeptDO deptDO = randomPojo(SysDeptDO.class); + DeptDO deptDO = randomPojo(DeptDO.class); when(deptService.getDeptsByParentIdFromCache(eq(loginUser.getDeptId()), eq(true))) .thenReturn(singletonList(deptDO)); @@ -206,7 +205,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { assertFalse(result.getSelf()); assertEquals(1, result.getDeptIds().size()); assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId())); - assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); + assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); } @Test @@ -214,7 +213,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { // 准备参数 LoginUser loginUser = randomPojo(LoginUser.class); // mock 方法 - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())); + RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())); when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO)); // 调用 @@ -223,7 +222,7 @@ public class SysPermissionServiceTest extends BaseDbUnitTest { assertFalse(result.getAll()); assertTrue(result.getSelf()); assertTrue(CollUtil.isEmpty(result.getDeptIds())); - assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); + assertSame(result, loginUser.getContext(PermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); } } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java similarity index 61% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java index 08bd6521b1..e607cd7251 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java @@ -1,19 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.permission; +package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRolePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.permission.vo.role.SysRoleUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMapper; -import cn.iocoder.yudao.adminserver.modules.system.enums.permission.SysRoleTypeEnum; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysRoleServiceImpl; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; +import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; +import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; +import cn.iocoder.yudao.module.system.mq.producer.permission.RoleProducer; import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -22,7 +21,7 @@ import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; @@ -30,26 +29,26 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.verify; -@Import(SysRoleServiceImpl.class) -public class SysRoleServiceTest extends BaseDbUnitTest { +@Import(RoleServiceImpl.class) +public class RoleServiceTest extends BaseDbUnitTest { @Resource - private SysRoleServiceImpl sysRoleService; + private RoleServiceImpl sysRoleService; @Resource - private SysRoleMapper roleMapper; + private RoleMapper roleMapper; @MockBean - private SysPermissionService sysPermissionService; + private PermissionService sysPermissionService; @MockBean - private SysRoleProducer sysRoleProducer; + private RoleProducer sysRoleProducer; @Test public void testInitLocalCache_success() throws Exception { - SysRoleDO roleDO1 = createRoleDO("role1", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO1 = createRoleDO("role1", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO1); - SysRoleDO roleDO2 = createRoleDO("role2", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO2 = createRoleDO("role2", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO2); //调用 @@ -57,9 +56,9 @@ public class SysRoleServiceTest extends BaseDbUnitTest { //断言 //获取代理对象 - SysRoleServiceImpl target = (SysRoleServiceImpl) SpringAopUtils.getTarget(sysRoleService); + RoleServiceImpl target = (RoleServiceImpl) SpringAopUtils.getTarget(sysRoleService); - Map roleCache = (Map) BeanUtil.getFieldValue(target, "roleCache"); + Map roleCache = (Map) BeanUtil.getFieldValue(target, "roleCache"); assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId())); assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId())); @@ -69,18 +68,18 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testCreateRole_success() { - SysRoleCreateReqVO reqVO = randomPojo(SysRoleCreateReqVO.class, o -> { + RoleCreateReqVO reqVO = randomPojo(RoleCreateReqVO.class, o -> { o.setCode("role_code"); o.setName("role_name"); o.setRemark("remark"); - o.setType(SysRoleTypeEnum.CUSTOM.getType()); + o.setType(RoleTypeEnum.CUSTOM.getType()); o.setSort(1); }); Long roleId = sysRoleService.createRole(reqVO); //断言 assertNotNull(roleId); - SysRoleDO roleDO = roleMapper.selectById(roleId); + RoleDO roleDO = roleMapper.selectById(roleId); assertPojoEquals(reqVO, roleDO); verify(sysRoleProducer).sendRoleRefreshMessage(); @@ -88,22 +87,22 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testUpdateRole_success() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); //调用 - SysRoleUpdateReqVO reqVO = randomPojo(SysRoleUpdateReqVO.class, o -> { + RoleUpdateReqVO reqVO = randomPojo(RoleUpdateReqVO.class, o -> { o.setId(roleId); o.setCode("role_code"); o.setName("update_name"); - o.setType(SysRoleTypeEnum.SYSTEM.getType()); + o.setType(RoleTypeEnum.SYSTEM.getType()); o.setSort(999); }); sysRoleService.updateRole(reqVO); //断言 - SysRoleDO newRoleDO = roleMapper.selectById(roleId); + RoleDO newRoleDO = roleMapper.selectById(roleId); assertPojoEquals(reqVO, newRoleDO); verify(sysRoleProducer).sendRoleRefreshMessage(); @@ -111,7 +110,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testUpdateRoleStatus_success() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, CommonStatusEnum.ENABLE.getStatus()); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, CommonStatusEnum.ENABLE.getStatus()); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); @@ -119,7 +118,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { sysRoleService.updateRoleStatus(roleId, CommonStatusEnum.DISABLE.getStatus()); //断言 - SysRoleDO newRoleDO = roleMapper.selectById(roleId); + RoleDO newRoleDO = roleMapper.selectById(roleId); assertEquals(CommonStatusEnum.DISABLE.getStatus(), newRoleDO.getStatus()); verify(sysRoleProducer).sendRoleRefreshMessage(); @@ -127,7 +126,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testUpdateRoleDataScope_success() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); @@ -136,7 +135,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { sysRoleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScope(), deptIdSet); //断言 - SysRoleDO newRoleDO = roleMapper.selectById(roleId); + RoleDO newRoleDO = roleMapper.selectById(roleId); assertEquals(DataScopeEnum.DEPT_CUSTOM.getScope(), newRoleDO.getDataScope()); Set newDeptIdSet = newRoleDO.getDataScopeDeptIds(); @@ -148,7 +147,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testDeleteRole_success() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); @@ -156,7 +155,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { sysRoleService.deleteRole(roleId); //断言 - SysRoleDO newRoleDO = roleMapper.selectById(roleId); + RoleDO newRoleDO = roleMapper.selectById(roleId); assertNull(newRoleDO); verify(sysRoleProducer).sendRoleRefreshMessage(); @@ -164,22 +163,22 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testGetRoles_success() { - Map idRoleMap = new HashMap<>(); + Map idRoleMap = new HashMap<>(); // 验证查询状态为1的角色 - SysRoleDO roleDO1 = createRoleDO("role1", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1); + RoleDO roleDO1 = createRoleDO("role1", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1); roleMapper.insert(roleDO1); idRoleMap.put(roleDO1.getId(), roleDO1); - SysRoleDO roleDO2 = createRoleDO("role2", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1); + RoleDO roleDO2 = createRoleDO("role2", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1); roleMapper.insert(roleDO2); idRoleMap.put(roleDO2.getId(), roleDO2); // 以下是排除的角色 - SysRoleDO roleDO3 = createRoleDO("role3", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 2); + RoleDO roleDO3 = createRoleDO("role3", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 2); roleMapper.insert(roleDO3); //调用 - List roles = sysRoleService.getRoles(Arrays.asList(1)); + List roles = sysRoleService.getRoles(Arrays.asList(1)); //断言 assertEquals(2, roles.size()); @@ -189,24 +188,24 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testGetRolePage_success() { - Map idRoleMap = new HashMap<>(); + Map idRoleMap = new HashMap<>(); // 验证名称包含"role", 状态为1,code为"code"的角色 // 第一页 - SysRoleDO roleDO = createRoleDO("role1", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "code"); + RoleDO roleDO = createRoleDO("role1", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "code"); roleMapper.insert(roleDO); idRoleMap.put(roleDO.getId(), roleDO); // 第二页 - roleDO = createRoleDO("role2", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "code"); + roleDO = createRoleDO("role2", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "code"); roleMapper.insert(roleDO); // 以下是排除的角色 - roleDO = createRoleDO("role3", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 2, "code"); + roleDO = createRoleDO("role3", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 2, "code"); roleMapper.insert(roleDO); - roleDO = createRoleDO("role4", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "xxxxx"); + roleDO = createRoleDO("role4", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL, 1, "xxxxx"); roleMapper.insert(roleDO); //调用 - SysRolePageReqVO reqVO = randomPojo(SysRolePageReqVO.class, o -> { + RolePageReqVO reqVO = randomPojo(RolePageReqVO.class, o -> { o.setName("role"); o.setCode("code"); o.setStatus(1); @@ -215,7 +214,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { o.setBeginTime(null); o.setEndTime(null); }); - PageResult result = sysRoleService.getRolePage(reqVO); + PageResult result = sysRoleService.getRolePage(reqVO); assertEquals(2, result.getTotal()); result.getList().stream().forEach(r -> assertPojoEquals(idRoleMap.get(r.getId()), r)); } @@ -227,7 +226,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testCheckDuplicateRole_nameDuplicate() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO); String duplicateName = "role_name"; @@ -237,10 +236,10 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testCheckDuplicateRole_codeDuplicate() { - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> { + RoleDO roleDO = randomPojo(RoleDO.class, o -> { o.setName("role_999"); o.setCode("code"); - o.setType(SysRoleTypeEnum.CUSTOM.getType()); + o.setType(RoleTypeEnum.CUSTOM.getType()); o.setStatus(1); o.setDataScope(DataScopeEnum.ALL.getScope()); }); @@ -254,7 +253,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testCheckUpdateRole_success() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.CUSTOM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.CUSTOM, DataScopeEnum.ALL); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); @@ -268,27 +267,27 @@ public class SysRoleServiceTest extends BaseDbUnitTest { @Test public void testCheckUpdateRole_systemRoleCanNotBeUpdate() { - SysRoleDO roleDO = createRoleDO("role_name", SysRoleTypeEnum.SYSTEM, DataScopeEnum.ALL); + RoleDO roleDO = createRoleDO("role_name", RoleTypeEnum.SYSTEM, DataScopeEnum.ALL); roleMapper.insert(roleDO); Long roleId = roleDO.getId(); assertServiceException(() -> sysRoleService.checkUpdateRole(roleId), ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); } - private SysRoleDO createRoleDO(String name, SysRoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status) { + private RoleDO createRoleDO(String name, RoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status) { return createRoleDO( name, typeEnum, scopeEnum, status, randomString()); } - private SysRoleDO createRoleDO(String name, SysRoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status, String code) { + private RoleDO createRoleDO(String name, RoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status, String code) { return createRoleDO(null, name, typeEnum, scopeEnum, status, code); } - private SysRoleDO createRoleDO(String name, SysRoleTypeEnum typeEnum, DataScopeEnum scopeEnum) { + private RoleDO createRoleDO(String name, RoleTypeEnum typeEnum, DataScopeEnum scopeEnum) { return createRoleDO(null, name, typeEnum, scopeEnum, randomCommonStatus(), randomString()); } - private SysRoleDO createRoleDO(Long id, String name, SysRoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status, String code) { - SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> { + private RoleDO createRoleDO(Long id, String name, RoleTypeEnum typeEnum, DataScopeEnum scopeEnum, Integer status, String code) { + RoleDO roleDO = randomPojo(RoleDO.class, o -> { o.setId(id); o.setName(name); o.setType(typeEnum.getType()); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java similarity index 68% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java index 4442751206..7e8b8445ed 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java @@ -1,19 +1,18 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.bean.BeanUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsChannelMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsChannelServiceImpl; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -23,8 +22,8 @@ import java.util.Date; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; @@ -33,33 +32,28 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -/** -* {@link SysSmsChannelServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysSmsChannelServiceImpl.class) -public class SysSmsChannelServiceTest extends BaseDbUnitTest { +@Import(SmsChannelServiceImpl.class) +public class SmsChannelServiceTest extends BaseDbUnitTest { @Resource - private SysSmsChannelServiceImpl smsChannelService; + private SmsChannelServiceImpl smsChannelService; @Resource - private SysSmsChannelMapper smsChannelMapper; + private SmsChannelMapper smsChannelMapper; @MockBean private SmsClientFactory smsClientFactory; @MockBean - private SysSmsTemplateService smsTemplateService; + private SmsTemplateService smsTemplateService; @MockBean - private SysSmsProducer smsProducer; + private SmsProducer smsProducer; @Test public void testInitLocalCache_success() { // mock 数据 - SysSmsChannelDO smsChannelDO01 = randomSmsChannelDO(); + SmsChannelDO smsChannelDO01 = randomSmsChannelDO(); smsChannelMapper.insert(smsChannelDO01); - SysSmsChannelDO smsChannelDO02 = randomSmsChannelDO(); + SmsChannelDO smsChannelDO02 = randomSmsChannelDO(); smsChannelMapper.insert(smsChannelDO02); // 调用 @@ -77,14 +71,14 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testCreateSmsChannel_success() { // 准备参数 - SysSmsChannelCreateReqVO reqVO = randomPojo(SysSmsChannelCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); + SmsChannelCreateReqVO reqVO = randomPojo(SmsChannelCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); // 调用 Long smsChannelId = smsChannelService.createSmsChannel(reqVO); // 断言 assertNotNull(smsChannelId); // 校验记录的属性是否正确 - SysSmsChannelDO smsChannel = smsChannelMapper.selectById(smsChannelId); + SmsChannelDO smsChannel = smsChannelMapper.selectById(smsChannelId); assertPojoEquals(reqVO, smsChannel); // 校验调用 verify(smsProducer, times(1)).sendSmsChannelRefreshMessage(); @@ -93,10 +87,10 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testUpdateSmsChannel_success() { // mock 数据 - SysSmsChannelDO dbSmsChannel = randomSmsChannelDO(); + SmsChannelDO dbSmsChannel = randomSmsChannelDO(); smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysSmsChannelUpdateReqVO reqVO = randomPojo(SysSmsChannelUpdateReqVO.class, o -> { + SmsChannelUpdateReqVO reqVO = randomPojo(SmsChannelUpdateReqVO.class, o -> { o.setId(dbSmsChannel.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); o.setCallbackUrl(randomString()); @@ -105,7 +99,7 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { // 调用 smsChannelService.updateSmsChannel(reqVO); // 校验是否更新正确 - SysSmsChannelDO smsChannel = smsChannelMapper.selectById(reqVO.getId()); // 获取最新的 + SmsChannelDO smsChannel = smsChannelMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, smsChannel); // 校验调用 verify(smsProducer, times(1)).sendSmsChannelRefreshMessage(); @@ -114,7 +108,7 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testUpdateSmsChannel_notExists() { // 准备参数 - SysSmsChannelUpdateReqVO reqVO = randomPojo(SysSmsChannelUpdateReqVO.class); + SmsChannelUpdateReqVO reqVO = randomPojo(SmsChannelUpdateReqVO.class); // 调用, 并断言异常 assertServiceException(() -> smsChannelService.updateSmsChannel(reqVO), SMS_CHANNEL_NOT_EXISTS); @@ -123,7 +117,7 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testDeleteSmsChannel_success() { // mock 数据 - SysSmsChannelDO dbSmsChannel = randomSmsChannelDO(); + SmsChannelDO dbSmsChannel = randomSmsChannelDO(); smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbSmsChannel.getId(); @@ -148,7 +142,7 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testDeleteSmsChannel_hasChildren() { // mock 数据 - SysSmsChannelDO dbSmsChannel = randomSmsChannelDO(); + SmsChannelDO dbSmsChannel = randomSmsChannelDO(); smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbSmsChannel.getId(); @@ -162,7 +156,7 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { @Test public void testGetSmsChannelPage() { // mock 数据 - SysSmsChannelDO dbSmsChannel = randomPojo(SysSmsChannelDO.class, o -> { // 等会查询到 + SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 o.setSignature("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setCreateTime(buildTime(2020, 12, 12)); @@ -175,14 +169,14 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); // 准备参数 - SysSmsChannelPageReqVO reqVO = new SysSmsChannelPageReqVO(); + SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); reqVO.setSignature("芋道"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setBeginCreateTime(buildTime(2020, 12, 1)); reqVO.setEndCreateTime(buildTime(2020, 12, 24)); // 调用 - PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); + PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -192,11 +186,11 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest { // ========== 随机对象 ========== @SafeVarargs - private static SysSmsChannelDO randomSmsChannelDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static SmsChannelDO randomSmsChannelDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 }; - return randomPojo(SysSmsChannelDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(SmsChannelDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java new file mode 100644 index 0000000000..de6a6bd0ca --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java @@ -0,0 +1,243 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper; +import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static cn.hutool.core.util.RandomUtil.randomBoolean; +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@Import(SmsLogServiceImpl.class) +public class SmsLogServiceTest extends BaseDbUnitTest { + + @Resource + private SmsLogServiceImpl smsLogService; + + @Resource + private SmsLogMapper smsLogMapper; + + @Test + public void testGetSmsLogPage() { + // mock 数据 + SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 + o.setChannelId(1L); + o.setTemplateId(10L); + o.setMobile("15601691300"); + o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + o.setSendTime(buildTime(2020, 11, 11)); + o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + o.setReceiveTime(buildTime(2021, 11, 11)); + }); + smsLogMapper.insert(dbSmsLog); + // 测试 channelId 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); + // 测试 templateId 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); + // 测试 mobile 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); + // 测试 sendStatus 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); + // 测试 sendTime 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); + // 测试 receiveStatus 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); + // 测试 receiveTime 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); + // 准备参数 + SmsLogPageReqVO reqVO = new SmsLogPageReqVO(); + reqVO.setChannelId(1L); + reqVO.setTemplateId(10L); + reqVO.setMobile("156"); + reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + reqVO.setBeginSendTime(buildTime(2020, 11, 1)); + reqVO.setEndSendTime(buildTime(2020, 11, 30)); + reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); + reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); + + // 调用 + PageResult pageResult = smsLogService.getSmsLogPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); + } + + @Test + public void testGetSmsLogList() { + // mock 数据 + SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 + o.setChannelId(1L); + o.setTemplateId(10L); + o.setMobile("15601691300"); + o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + o.setSendTime(buildTime(2020, 11, 11)); + o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + o.setReceiveTime(buildTime(2021, 11, 11)); + }); + smsLogMapper.insert(dbSmsLog); + // 测试 channelId 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); + // 测试 templateId 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); + // 测试 mobile 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); + // 测试 sendStatus 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); + // 测试 sendTime 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); + // 测试 receiveStatus 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); + // 测试 receiveTime 不匹配 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); + // 准备参数 + SmsLogExportReqVO reqVO = new SmsLogExportReqVO(); + reqVO.setChannelId(1L); + reqVO.setTemplateId(10L); + reqVO.setMobile("156"); + reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + reqVO.setBeginSendTime(buildTime(2020, 11, 1)); + reqVO.setEndSendTime(buildTime(2020, 11, 30)); + reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + reqVO.setBeginReceiveTime(buildTime(2021, 11, 1)); + reqVO.setEndReceiveTime(buildTime(2021, 11, 30)); + + // 调用 + List list = smsLogService.getSmsLogList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbSmsLog, list.get(0)); + } + + @Test + public void testCreateSmsLog() { + // 准备参数 + String mobile = randomString(); + Long userId = randomLongId(); + Integer userType = randomEle(UserTypeEnum.values()).getValue(); + Boolean isSend = randomBoolean(); + SmsTemplateDO templateDO = randomPojo(SmsTemplateDO.class, + o -> o.setType(randomEle(SmsTemplateTypeEnum.values()).getType())); + String templateContent = randomString(); + Map templateParams = randomTemplateParams(); + // mock 方法 + + // 调用 + Long logId = smsLogService.createSmsLog(mobile, userId, userType, isSend, + templateDO, templateContent, templateParams); + // 断言 + SmsLogDO logDO = smsLogMapper.selectById(logId); + assertEquals(isSend ? SmsSendStatusEnum.INIT.getStatus() : SmsSendStatusEnum.IGNORE.getStatus(), + logDO.getSendStatus()); + assertEquals(mobile, logDO.getMobile()); + assertEquals(userType, logDO.getUserType()); + assertEquals(userId, logDO.getUserId()); + assertEquals(templateDO.getId(), logDO.getTemplateId()); + assertEquals(templateDO.getCode(), logDO.getTemplateCode()); + assertEquals(templateDO.getType(), logDO.getTemplateType()); + assertEquals(templateDO.getChannelId(), logDO.getChannelId()); + assertEquals(templateDO.getChannelCode(), logDO.getChannelCode()); + assertEquals(templateContent, logDO.getTemplateContent()); + assertEquals(templateParams, logDO.getTemplateParams()); + assertEquals(SmsReceiveStatusEnum.INIT.getStatus(), logDO.getReceiveStatus()); + } + + @Test + public void testUpdateSmsSendResult() { + // mock 数据 + SmsLogDO dbSmsLog = randomSmsLogDO( + o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus())); + smsLogMapper.insert(dbSmsLog); + // 准备参数 + Long id = dbSmsLog.getId(); + Integer sendCode = randomInteger(); + String sendMsg = randomString(); + String apiSendCode = randomString(); + String apiSendMsg = randomString(); + String apiRequestId = randomString(); + String apiSerialNo = randomString(); + + // 调用 + smsLogService.updateSmsSendResult(id, sendCode, sendMsg, + apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); + // 断言 + dbSmsLog = smsLogMapper.selectById(id); + assertEquals(CommonResult.isSuccess(sendCode) ? SmsSendStatusEnum.SUCCESS.getStatus() + : SmsSendStatusEnum.FAILURE.getStatus(), dbSmsLog.getSendStatus()); + assertNotNull(dbSmsLog.getSendTime()); + assertEquals(sendMsg, dbSmsLog.getSendMsg()); + assertEquals(apiSendCode, dbSmsLog.getApiSendCode()); + assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg()); + assertEquals(apiRequestId, dbSmsLog.getApiRequestId()); + assertEquals(apiSerialNo, dbSmsLog.getApiSerialNo()); + } + + @Test + public void testUpdateSmsReceiveResult() { + // mock 数据 + SmsLogDO dbSmsLog = randomSmsLogDO( + o -> o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus())); + smsLogMapper.insert(dbSmsLog); + // 准备参数 + Long id = dbSmsLog.getId(); + Boolean success = randomBoolean(); + Date receiveTime = randomDate(); + String apiReceiveCode = randomString(); + String apiReceiveMsg = randomString(); + + // 调用 + smsLogService.updateSmsReceiveResult(id, success, receiveTime, apiReceiveCode, apiReceiveMsg); + // 断言 + dbSmsLog = smsLogMapper.selectById(id); + assertEquals(success ? SmsReceiveStatusEnum.SUCCESS.getStatus() + : SmsReceiveStatusEnum.FAILURE.getStatus(), dbSmsLog.getReceiveStatus()); + assertEquals(receiveTime, dbSmsLog.getReceiveTime()); + assertEquals(apiReceiveCode, dbSmsLog.getApiReceiveCode()); + assertEquals(apiReceiveMsg, dbSmsLog.getApiReceiveMsg()); + } + + // ========== 随机对象 ========== + + @SafeVarargs + private static SmsLogDO randomSmsLogDO(Consumer... consumers) { + Consumer consumer = (o) -> { + o.setTemplateParams(randomTemplateParams()); + o.setTemplateType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 templateType 的范围 + o.setUserType(randomEle(UserTypeEnum.values()).getValue()); // 保证 userType 的范围 + o.setSendStatus(randomEle(SmsSendStatusEnum.values()).getStatus()); // 保证 sendStatus 的范围 + o.setReceiveStatus(randomEle(SmsReceiveStatusEnum.values()).getStatus()); // 保证 receiveStatus 的范围 + }; + return randomPojo(SmsLogDO.class, ArrayUtils.append(consumer, consumers)); + } + + + private static Map randomTemplateParams() { + return MapUtil.builder().put(randomString(), randomString()) + .put(randomString(), randomString()).build(); + } +} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java similarity index 68% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java index 97e1e37031..7f9309499c 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/SysSmsCoreServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java @@ -1,10 +1,9 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; -import cn.iocoder.yudao.coreservice.modules.system.mq.producer.sms.SysSmsCoreProducer; -import cn.iocoder.yudao.coreservice.modules.system.service.sms.impl.SysSmsCoreServiceImpl; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -24,29 +23,24 @@ import java.util.List; import java.util.Map; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -/** - * {@link SysSmsCoreService} 的单元测试类 - * - * @author 芋道源码 - */ -public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { +public class SmsSendServiceTest extends BaseMockitoUnitTest { @InjectMocks - private SysSmsCoreServiceImpl smsCoreService; + private SmsSendServiceImpl smsService; @Mock - private SysSmsTemplateCoreService smsTemplateCoreService; + private SmsTemplateService smsTemplateService; @Mock - private SysSmsLogCoreService smsLogCoreService; + private SmsLogService smsLogService; @Mock - private SysSmsCoreProducer smsCoreProducer; + private SmsProducer smsProducer; @Mock private SmsClientFactory smsClientFactory; @@ -63,26 +57,26 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { Map templateParams = MapUtil.builder().put("code", "1234") .put("op", "login").build(); // mock SmsTemplateService 的方法 - SysSmsTemplateDO template = randomPojo(SysSmsTemplateDO.class, o -> { + SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setContent("验证码为{code}, 操作为{op}"); o.setParams(Lists.newArrayList("code", "op")); }); - when(smsTemplateCoreService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); + when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); String content = randomString(); - when(smsTemplateCoreService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) + when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) .thenReturn(content); // mock SmsLogService 的方法 Long smsLogId = randomLongId(); - when(smsLogCoreService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template), + when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template), eq(content), eq(templateParams))).thenReturn(smsLogId); // 调用 - Long resultSmsLogId = smsCoreService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); + Long resultSmsLogId = smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsCoreProducer, times(1)).sendSmsSendMessage(eq(smsLogId), eq(mobile), + verify(smsProducer, times(1)).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template.getChannelId()), eq(template.getApiTemplateId()), eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); } @@ -100,26 +94,26 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { Map templateParams = MapUtil.builder().put("code", "1234") .put("op", "login").build(); // mock SmsTemplateService 的方法 - SysSmsTemplateDO template = randomPojo(SysSmsTemplateDO.class, o -> { + SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { o.setStatus(CommonStatusEnum.DISABLE.getStatus()); o.setContent("验证码为{code}, 操作为{op}"); o.setParams(Lists.newArrayList("code", "op")); }); - when(smsTemplateCoreService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); + when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); String content = randomString(); - when(smsTemplateCoreService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) + when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) .thenReturn(content); // mock SmsLogService 的方法 Long smsLogId = randomLongId(); - when(smsLogCoreService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template), + when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template), eq(content), eq(templateParams))).thenReturn(smsLogId); // 调用 - Long resultSmsLogId = smsCoreService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); + Long resultSmsLogId = smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); // 断言 assertEquals(smsLogId, resultSmsLogId); // 断言调用 - verify(smsCoreProducer, times(0)).sendSmsSendMessage(anyLong(), anyString(), + verify(smsProducer, times(0)).sendSmsSendMessage(anyLong(), anyString(), anyLong(), any(), anyList()); } @@ -130,20 +124,20 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { // mock 方法 // 调用,并断言异常 - assertServiceException(() -> smsCoreService.checkSmsTemplateValid(templateCode), + assertServiceException(() -> smsService.checkSmsTemplateValid(templateCode), SMS_SEND_TEMPLATE_NOT_EXISTS); } @Test public void testBuildTemplateParams_paramMiss() { // 准备参数 - SysSmsTemplateDO template = randomPojo(SysSmsTemplateDO.class, + SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> o.setParams(Lists.newArrayList("code"))); Map templateParams = new HashMap<>(); // mock 方法 // 调用,并断言异常 - assertServiceException(() -> smsCoreService.buildTemplateParams(template, templateParams), + assertServiceException(() -> smsService.buildTemplateParams(template, templateParams), SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, "code"); } @@ -153,7 +147,7 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { // mock 方法 // 调用,并断言异常 - assertServiceException(() -> smsCoreService.checkMobile(null), + assertServiceException(() -> smsService.checkMobile(null), SMS_SEND_MOBILE_NOT_EXISTS); } @@ -161,7 +155,7 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { @SuppressWarnings("unchecked") public void testDoSendSms() { // 准备参数 - SysSmsSendMessage message = randomPojo(SysSmsSendMessage.class); + SmsSendMessage message = randomPojo(SmsSendMessage.class); // mock SmsClientFactory 的方法 SmsClient smsClient = spy(SmsClient.class); when(smsClientFactory.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient); @@ -171,9 +165,9 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { eq(message.getTemplateParams()))).thenReturn(sendResult); // 调用 - smsCoreService.doSendSms(message); + smsService.doSendSms(message); // 断言 - verify(smsLogCoreService, times(1)).updateSmsSendResult(eq(message.getLogId()), + verify(smsLogService, times(1)).updateSmsSendResult(eq(message.getLogId()), eq(sendResult.getCode()), eq(sendResult.getMsg()), eq(sendResult.getApiCode()), eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getData().getSerialNo())); } @@ -190,9 +184,9 @@ public class SysSmsCoreServiceTest extends BaseMockitoUnitTest { List receiveResults = randomPojoList(SmsReceiveRespDTO.class); // 调用 - smsCoreService.receiveSmsStatus(channelCode, text); + smsService.receiveSmsStatus(channelCode, text); // 断言 - receiveResults.forEach(result -> smsLogCoreService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()), + receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()), eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode()))); } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java similarity index 72% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java index a893ee2966..034310fa26 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java @@ -1,16 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.sms; +package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.sms.SysSmsTemplateMapper; -import cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms.SysSmsProducer; -import cn.iocoder.yudao.adminserver.modules.system.service.sms.impl.SysSmsTemplateServiceImpl; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsChannelDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.sms.SysSmsTemplateTypeEnum; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; +import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -20,17 +18,22 @@ import cn.iocoder.yudao.framework.sms.core.client.SmsClient; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; +import java.util.Date; import java.util.List; +import java.util.Map; import java.util.function.Consumer; +import static cn.hutool.core.bean.BeanUtil.getFieldValue; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -39,28 +42,44 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -/** -* {@link SysSmsTemplateServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(SysSmsTemplateServiceImpl.class) -public class SysSmsTemplateServiceTest extends BaseDbUnitTest { +@Import(SmsTemplateServiceImpl.class) +public class SmsTemplateServiceTest extends BaseDbUnitTest { @Resource - private SysSmsTemplateServiceImpl smsTemplateService; + private SmsTemplateServiceImpl smsTemplateService; @Resource - private SysSmsTemplateMapper smsTemplateMapper; + private SmsTemplateMapper smsTemplateMapper; @MockBean - private SysSmsChannelService smsChannelService; + private SmsChannelService smsChannelService; @MockBean private SmsClientFactory smsClientFactory; @MockBean private SmsClient smsClient; @MockBean - private SysSmsProducer smsProducer; + private SmsProducer smsProducer; + + @Test + @SuppressWarnings("unchecked") + void testInitLocalCache() { + // mock 数据 + SmsTemplateDO smsTemplate01 = randomSmsTemplateDO(); + smsTemplateMapper.insert(smsTemplate01); + SmsTemplateDO smsTemplate02 = randomSmsTemplateDO(); + smsTemplateMapper.insert(smsTemplate02); + + // 调用 + smsTemplateService.initLocalCache(); + // 断言 deptCache 缓存 + Map smsTemplateCache = (Map) getFieldValue(smsTemplateService, "smsTemplateCache"); + assertEquals(2, smsTemplateCache.size()); + assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode())); + assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode())); + // 断言 maxUpdateTime 缓存 + Date maxUpdateTime = (Date) getFieldValue(smsTemplateService, "maxUpdateTime"); + assertEquals(max(smsTemplate01.getUpdateTime(), smsTemplate02.getUpdateTime()), maxUpdateTime); + } @Test public void testParseTemplateContentParams() { @@ -78,13 +97,13 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @SuppressWarnings("unchecked") public void testCreateSmsTemplate_success() { // 准备参数 - SysSmsTemplateCreateReqVO reqVO = randomPojo(SysSmsTemplateCreateReqVO.class, o -> { + SmsTemplateCreateReqVO reqVO = randomPojo(SmsTemplateCreateReqVO.class, o -> { o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 + o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }); // mock Channel 的方法 - SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { + SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> { o.setId(reqVO.getChannelId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态 }); @@ -99,7 +118,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 断言 assertNotNull(smsTemplateId); // 校验记录的属性是否正确 - SysSmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId); + SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId); assertPojoEquals(reqVO, smsTemplate); assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams()); assertEquals(channelDO.getCode(), smsTemplate.getChannelCode()); @@ -111,17 +130,17 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @SuppressWarnings("unchecked") public void testUpdateSmsTemplate_success() { // mock 数据 - SysSmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); + SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysSmsTemplateUpdateReqVO reqVO = randomPojo(SysSmsTemplateUpdateReqVO.class, o -> { + SmsTemplateUpdateReqVO reqVO = randomPojo(SmsTemplateUpdateReqVO.class, o -> { o.setId(dbSmsTemplate.getId()); // 设置更新的 ID o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 + o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }); // mock 方法 - SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { + SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> { o.setId(reqVO.getChannelId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态 }); @@ -134,7 +153,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 调用 smsTemplateService.updateSmsTemplate(reqVO); // 校验是否更新正确 - SysSmsTemplateDO smsTemplate = smsTemplateMapper.selectById(reqVO.getId()); // 获取最新的 + SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, smsTemplate); assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams()); assertEquals(channelDO.getCode(), smsTemplate.getChannelCode()); @@ -145,7 +164,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @Test public void testUpdateSmsTemplate_notExists() { // 准备参数 - SysSmsTemplateUpdateReqVO reqVO = randomPojo(SysSmsTemplateUpdateReqVO.class); + SmsTemplateUpdateReqVO reqVO = randomPojo(SmsTemplateUpdateReqVO.class); // 调用, 并断言异常 assertServiceException(() -> smsTemplateService.updateSmsTemplate(reqVO), SMS_TEMPLATE_NOT_EXISTS); @@ -154,7 +173,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @Test public void testDeleteSmsTemplate_success() { // mock 数据 - SysSmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); + SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbSmsTemplate.getId(); @@ -179,8 +198,8 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @Test public void testGetSmsTemplatePage() { // mock 数据 - SysSmsTemplateDO dbSmsTemplate = randomPojo(SysSmsTemplateDO.class, o -> { // 等会查询到 - o.setType(SysSmsTemplateTypeEnum.PROMOTION.getType()); + SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到 + o.setType(SmsTemplateTypeEnum.PROMOTION.getType()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setCode("yudaoyuanma"); o.setContent("芋道源码"); @@ -190,7 +209,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { }); smsTemplateMapper.insert(dbSmsTemplate); // 测试 type 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); // 测试 status 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 code 不匹配 @@ -204,8 +223,8 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 - SysSmsTemplatePageReqVO reqVO = new SysSmsTemplatePageReqVO(); - reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType()); + SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO(); + reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setCode("yudao"); reqVO.setContent("芋道"); @@ -215,7 +234,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2021, 12, 1)); // 调用 - PageResult pageResult = smsTemplateService.getSmsTemplatePage(reqVO); + PageResult pageResult = smsTemplateService.getSmsTemplatePage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -225,8 +244,8 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { @Test public void testGetSmsTemplateList() { // mock 数据 - SysSmsTemplateDO dbSmsTemplate = randomPojo(SysSmsTemplateDO.class, o -> { // 等会查询到 - o.setType(SysSmsTemplateTypeEnum.PROMOTION.getType()); + SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到 + o.setType(SmsTemplateTypeEnum.PROMOTION.getType()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setCode("yudaoyuanma"); o.setContent("芋道源码"); @@ -236,7 +255,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { }); smsTemplateMapper.insert(dbSmsTemplate); // 测试 type 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); // 测试 status 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 code 不匹配 @@ -250,8 +269,8 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 - SysSmsTemplateExportReqVO reqVO = new SysSmsTemplateExportReqVO(); - reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType()); + SmsTemplateExportReqVO reqVO = new SmsTemplateExportReqVO(); + reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setCode("yudao"); reqVO.setContent("芋道"); @@ -261,7 +280,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2021, 12, 1)); // 调用 - List list = smsTemplateService.getSmsTemplateList(reqVO); + List list = smsTemplateService.getSmsTemplateList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbSmsTemplate, list.get(0)); @@ -272,14 +291,14 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 准备参数 Long channelId = randomLongId(); // mock 方法 - SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { + SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> { o.setId(channelId); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态 }); when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO); // 调用 - SysSmsChannelDO returnChannelDO = smsTemplateService.checkSmsChannel(channelId); + SmsChannelDO returnChannelDO = smsTemplateService.checkSmsChannel(channelId); // 断言 assertPojoEquals(returnChannelDO, channelDO); } @@ -299,7 +318,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // 准备参数 Long channelId = randomLongId(); // mock 方法 - SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> { + SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> { o.setId(channelId); o.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 保证 status 禁用,触发失败 }); @@ -344,12 +363,12 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest { // ========== 随机对象 ========== @SafeVarargs - private static SysSmsTemplateDO randomSmsTemplateDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static SmsTemplateDO randomSmsTemplateDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 + o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 }; - return randomPojo(SysSmsTemplateDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(SmsTemplateDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceTest.java similarity index 61% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceTest.java index 2a33dd869e..8fb527baa8 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialCoreServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceTest.java @@ -1,12 +1,11 @@ -package cn.iocoder.yudao.coreservice.modules.system.service.social; +package cn.iocoder.yudao.module.system.service.social; -import cn.iocoder.yudao.coreservice.BaseDbAndRedisUnitTest; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; -import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserCoreMapper; -import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO; -import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; -import cn.iocoder.yudao.coreservice.modules.system.service.social.impl.SysSocialCoreServiceImpl; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; +import cn.iocoder.yudao.module.system.dal.redis.social.SocialAuthUserRedisDAO; +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.module.system.test.BaseDbAndRedisUnitTest; import com.xkcoding.justauth.AuthRequestFactory; import me.zhyd.oauth.model.AuthUser; import org.junit.jupiter.api.Test; @@ -23,52 +22,47 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; -/** - * {@link SysSocialCoreServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import({SysSocialCoreServiceImpl.class, SysSocialAuthUserRedisDAO.class}) -public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { +@Import({SocialUserServiceImpl.class, SocialAuthUserRedisDAO.class}) +public class SocialUserServiceTest extends BaseDbAndRedisUnitTest { @Resource - private SysSocialCoreServiceImpl socialService; + private SocialUserServiceImpl socialService; @Resource - private SysSocialUserCoreMapper socialUserMapper; + private SocialUserMapper socialUserMapper; @MockBean private AuthRequestFactory authRequestFactory; /** - * 情况一,创建 SysSocialUserDO 的情况 + * 情况一,创建 SocialUserDO 的情况 */ @Test public void testBindSocialUser_create() { // mock 数据 // 准备参数 Long userId = randomLongId(); - Integer type = randomEle(SysSocialTypeEnum.values()).getType(); + Integer type = randomEle(SocialTypeEnum.values()).getType(); AuthUser authUser = randomPojo(AuthUser.class); // mock 方法 // 调用 - socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN); + socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser); // 断言 - List socialUsers = socialUserMapper.selectList("user_id", userId); + List socialUsers = socialUserMapper.selectList("user_id", userId); assertEquals(1, socialUsers.size()); assertBindSocialUser(socialUsers.get(0), authUser, userId, type); } /** - * 情况二,更新 SysSocialUserDO 的情况 + * 情况二,更新 SocialUserDO 的情况 */ @Test public void testBindSocialUser_update() { // mock 数据 - SysSocialUserDO dbSocialUser = randomPojo(SysSocialUserDO.class, socialUserDO -> { + SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> { socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue()); - socialUserDO.setType(randomEle(SysSocialTypeEnum.values()).getType()); + socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType()); }); socialUserMapper.insert(dbSocialUser); // 准备参数 @@ -78,9 +72,9 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { // mock 方法 // 调用 - socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN); + socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser); // 断言 - List socialUsers = socialUserMapper.selectList("user_id", userId); + List socialUsers = socialUserMapper.selectList("user_id", userId); assertEquals(1, socialUsers.size()); assertBindSocialUser(socialUsers.get(0), authUser, userId, type); } @@ -91,9 +85,9 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { @Test public void testBindSocialUser_userId() { // mock 数据 - SysSocialUserDO dbSocialUser = randomPojo(SysSocialUserDO.class, socialUserDO -> { + SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> { socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue()); - socialUserDO.setType(randomEle(SysSocialTypeEnum.values()).getType()); + socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType()); }); socialUserMapper.insert(dbSocialUser); // 准备参数 @@ -103,14 +97,14 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { // mock 方法 // 调用 - socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN); + socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser); // 断言 - List socialUsers = socialUserMapper.selectList("user_id", userId); + List socialUsers = socialUserMapper.selectList("user_id", userId); assertEquals(1, socialUsers.size()); } - private void assertBindSocialUser(SysSocialUserDO socialUser, AuthUser authUser, Long userId, - Integer type) { + private void assertBindSocialUser(SocialUserDO socialUser, AuthUser authUser, Long userId, + Integer type) { assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken()); assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo()); assertEquals(authUser.getNickname(), socialUser.getNickname()); @@ -129,9 +123,9 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { @Test public void testUnbindOldSocialUser_no() { // mock 数据 - SysSocialUserDO oldSocialUser = randomPojo(SysSocialUserDO.class, socialUserDO -> { + SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> { socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue()); - socialUserDO.setType(randomEle(SysSocialTypeEnum.values()).getType()); + socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType()); }); socialUserMapper.insert(oldSocialUser); // 准备参数 @@ -140,7 +134,7 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { String newUnionId = oldSocialUser.getUnionId(); // 调用 - socialService.unbindOldSocialUser(userId, type, newUnionId, UserTypeEnum.ADMIN); + socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId); // 断言 assertEquals(1L, socialUserMapper.selectCount(null).longValue()); } @@ -152,9 +146,9 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { @Test public void testUnbindOldSocialUser_yes() { // mock 数据 - SysSocialUserDO oldSocialUser = randomPojo(SysSocialUserDO.class, socialUserDO -> { + SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> { socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue()); - socialUserDO.setType(randomEle(SysSocialTypeEnum.values()).getType()); + socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType()); }); socialUserMapper.insert(oldSocialUser); // 准备参数 @@ -163,7 +157,7 @@ public class SysSocialCoreServiceTest extends BaseDbAndRedisUnitTest { String newUnionId = randomString(10); // 调用 - socialService.unbindOldSocialUser(userId, type, newUnionId, UserTypeEnum.ADMIN); + socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId); // 断言 assertEquals(0L, socialUserMapper.selectCount(null).longValue()); } diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceTest.java similarity index 71% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceTest.java index abb16e80e1..ade6613a0d 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceTest.java @@ -1,22 +1,21 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.tenant; +package cn.iocoder.yudao.module.system.service.tenant; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl.SysTenantServiceImpl; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.List; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -24,41 +23,36 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; -/** - * {@link SysTenantServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(SysTenantServiceImpl.class) -public class SysTenantServiceTest extends BaseDbUnitTest { +@Import(TenantServiceImpl.class) +public class TenantServiceTest extends BaseDbUnitTest { @Resource - private SysTenantServiceImpl tenantService; + private TenantServiceImpl tenantService; @Resource - private SysTenantMapper tenantMapper; + private TenantMapper tenantMapper; @Test public void testCreateTenant_success() { // 准备参数 - SysTenantCreateReqVO reqVO = randomPojo(SysTenantCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); + TenantCreateReqVO reqVO = randomPojo(TenantCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); // 调用 Long tenantId = tenantService.createTenant(reqVO); // 断言 assertNotNull(tenantId); // 校验记录的属性是否正确 - SysTenantDO tenant = tenantMapper.selectById(tenantId); + TenantDO tenant = tenantMapper.selectById(tenantId); assertPojoEquals(reqVO, tenant); } @Test public void testUpdateTenant_success() { // mock 数据 - SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> o.setStatus(randomCommonStatus())); + TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setStatus(randomCommonStatus())); tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据 // 准备参数 - SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class, o -> { + TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class, o -> { o.setId(dbTenant.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); }); @@ -66,14 +60,14 @@ public class SysTenantServiceTest extends BaseDbUnitTest { // 调用 tenantService.updateTenant(reqVO); // 校验是否更新正确 - SysTenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的 + TenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, tenant); } @Test public void testUpdateTenant_notExists() { // 准备参数 - SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class); + TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class); // 调用, 并断言异常 assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS); @@ -82,7 +76,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { @Test public void testDeleteTenant_success() { // mock 数据 - SysTenantDO dbTenant = randomPojo(SysTenantDO.class, + TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setStatus(randomCommonStatus())); tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据 // 准备参数 @@ -106,7 +100,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { @Test public void testGetTenantPage() { // mock 数据 - SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到 + TenantDO dbTenant = randomPojo(TenantDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setContactName("芋艿"); o.setContactMobile("15601691300"); @@ -125,7 +119,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 - SysTenantPageReqVO reqVO = new SysTenantPageReqVO(); + TenantPageReqVO reqVO = new TenantPageReqVO(); reqVO.setName("芋道"); reqVO.setContactName("艿"); reqVO.setContactMobile("1560"); @@ -134,7 +128,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2020, 12, 24)); // 调用 - PageResult pageResult = tenantService.getTenantPage(reqVO); + PageResult pageResult = tenantService.getTenantPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -144,7 +138,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { @Test public void testGetTenantList() { // mock 数据 - SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到 + TenantDO dbTenant = randomPojo(TenantDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setContactName("芋艿"); o.setContactMobile("15601691300"); @@ -163,7 +157,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 - SysTenantExportReqVO reqVO = new SysTenantExportReqVO(); + TenantExportReqVO reqVO = new TenantExportReqVO(); reqVO.setName("芋道"); reqVO.setContactName("艿"); reqVO.setContactMobile("1560"); @@ -172,7 +166,7 @@ public class SysTenantServiceTest extends BaseDbUnitTest { reqVO.setEndCreateTime(buildTime(2020, 12, 24)); // 调用 - List list = tenantService.getTenantList(reqVO); + List list = tenantService.getTenantList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbTenant, list.get(0)); diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/user/UserServiceImplTest.java similarity index 62% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/user/UserServiceImplTest.java index d1d01c9542..0beb281c52 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/user/UserServiceImplTest.java @@ -1,27 +1,25 @@ -package cn.iocoder.yudao.adminserver.modules.system.service.user; +package cn.iocoder.yudao.module.system.service.user; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysUserMapper; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; -import cn.iocoder.yudao.adminserver.modules.system.service.user.impl.SysUserServiceImpl; -import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; -import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; -import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; +import cn.iocoder.yudao.module.system.service.dept.DeptService; +import cn.iocoder.yudao.module.system.service.dept.PostService; +import cn.iocoder.yudao.module.system.service.permission.PermissionService; +import cn.iocoder.yudao.module.system.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.springframework.boot.test.mock.mockito.MockBean; @@ -30,66 +28,59 @@ import org.springframework.security.crypto.password.PasswordEncoder; import javax.annotation.Resource; import java.io.ByteArrayInputStream; -import java.util.*; +import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomBytes; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static org.assertj.core.util.Lists.newArrayList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -/** - * {@link SysUserService} 的单元测试类 - * - * @author zxl - */ -@Import(SysUserServiceImpl.class) -public class SysUserServiceImplTest extends BaseDbUnitTest { +@Import(AdminUserServiceImpl.class) +public class UserServiceImplTest extends BaseDbUnitTest { @Resource - private SysUserServiceImpl userService; + private AdminUserServiceImpl userService; @Resource - private SysUserMapper userMapper; + private AdminUserMapper userMapper; @MockBean - private SysDeptService deptService; + private DeptService deptService; + @MockBean - private SysPostService postService; + private PostService postService; @MockBean - private SysPermissionService permissionService; + private PermissionService permissionService; @MockBean private PasswordEncoder passwordEncoder; @MockBean - private InfFileCoreService fileService; + private FileApi fileApi; @Test public void testCreatUser_success() { // 准备参数 - SysUserCreateReqVO reqVO = randomPojo(SysUserCreateReqVO.class, o -> { - o.setSex(RandomUtil.randomEle(SysSexEnum.values()).getSex()); + UserCreateReqVO reqVO = randomPojo(UserCreateReqVO.class, o -> { + o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); o.setMobile(randomString()); }); // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + DeptDO dept = randomPojo(DeptDO.class, o -> { o.setId(reqVO.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); // mock postService 的方法 - List posts = CollectionUtils.convertList(reqVO.getPostIds(), postId -> - randomPojo(SysPostDO.class, o -> { + List posts = CollectionUtils.convertList(reqVO.getPostIds(), postId -> + randomPojo(PostDO.class, o -> { o.setId(postId); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); })); @@ -100,7 +91,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 调用 Long userId = userService.createUser(reqVO); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertPojoEquals(reqVO, user, "password"); assertEquals("yudaoyuanma", user.getPassword()); assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus()); @@ -109,23 +100,23 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateUser_success() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 - SysUserUpdateReqVO reqVO = randomPojo(SysUserUpdateReqVO.class, o -> { + UserUpdateReqVO reqVO = randomPojo(UserUpdateReqVO.class, o -> { o.setId(dbUser.getId()); - o.setSex(RandomUtil.randomEle(SysSexEnum.values()).getSex()); + o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); o.setMobile(randomString()); }); // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + DeptDO dept = randomPojo(DeptDO.class, o -> { o.setId(reqVO.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); // mock postService 的方法 - List posts = CollectionUtils.convertList(reqVO.getPostIds(), postId -> - randomPojo(SysPostDO.class, o -> { + List posts = CollectionUtils.convertList(reqVO.getPostIds(), postId -> + randomPojo(PostDO.class, o -> { o.setId(postId); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); })); @@ -134,37 +125,37 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 调用 userService.updateUser(reqVO); // 断言 - SysUserDO user = userMapper.selectById(reqVO.getId()); + AdminUserDO user = userMapper.selectById(reqVO.getId()); assertPojoEquals(reqVO, user); } @Test public void testUpdateUserProfile_success() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); - SysUserProfileUpdateReqVO reqVO = randomPojo(SysUserProfileUpdateReqVO.class, o -> { + UserProfileUpdateReqVO reqVO = randomPojo(UserProfileUpdateReqVO.class, o -> { o.setMobile(randomString()); - o.setSex(RandomUtil.randomEle(SysSexEnum.values()).getSex()); + o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); }); // 调用 userService.updateUserProfile(userId, reqVO); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertPojoEquals(reqVO, user); } @Test public void testUpdateUserPassword_success() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(o -> o.setPassword("encode:yudao")); + AdminUserDO dbUser = randomAdminUserDO(o -> o.setPassword("encode:yudao")); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); - SysUserProfileUpdatePasswordReqVO reqVO = randomPojo(SysUserProfileUpdatePasswordReqVO.class, o -> { + UserProfileUpdatePasswordReqVO reqVO = randomPojo(UserProfileUpdatePasswordReqVO.class, o -> { o.setOldPassword("yudao"); o.setNewPassword("yuanma"); }); @@ -176,14 +167,14 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 调用 userService.updateUserPassword(userId, reqVO); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertEquals("encode:yuanma", user.getPassword()); } @Test public void testUpdateUserAvatar_success() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); @@ -191,19 +182,19 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes); // mock 方法 String avatar = randomString(); - when(fileService.createFile(anyString(), eq(avatarFileBytes))).thenReturn(avatar); + when(fileApi.createFile(eq(avatarFileBytes))).thenReturn(avatar); // 调用 userService.updateUserAvatar(userId, avatarFile); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertEquals(avatar, user.getAvatar()); } @Test public void testUpdateUserPassword02_success() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); @@ -215,14 +206,14 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 调用 userService.updateUserPassword(userId, password); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertEquals("encode:" + password, user.getPassword()); } @Test public void testUpdateUserStatus() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); @@ -231,14 +222,14 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 调用 userService.updateUserStatus(userId, status); // 断言 - SysUserDO user = userMapper.selectById(userId); + AdminUserDO user = userMapper.selectById(userId); assertEquals(status, user.getStatus()); } @Test public void testDeleteUser_success(){ // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 Long userId = dbUser.getId(); @@ -254,9 +245,9 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testGetUserPage() { // mock 数据 - SysUserDO dbUser = initGetUserPageData(); + AdminUserDO dbUser = initGetUserPageData(); // 准备参数 - SysUserPageReqVO reqVO = new SysUserPageReqVO(); + UserPageReqVO reqVO = new UserPageReqVO(); reqVO.setUsername("yudao"); reqVO.setMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -264,11 +255,11 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { reqVO.setEndTime(buildTime(2020, 12, 24)); reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 // mock 方法 - List deptList = newArrayList(randomPojo(SysDeptDO.class, o -> o.setId(2L))); + List deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L))); when(deptService.getDeptsByParentIdFromCache(eq(reqVO.getDeptId()), eq(true))).thenReturn(deptList); // 调用 - PageResult pageResult = userService.getUserPage(reqVO); + PageResult pageResult = userService.getUserPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -278,9 +269,9 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testGetUsers() { // mock 数据 - SysUserDO dbUser = initGetUserPageData(); + AdminUserDO dbUser = initGetUserPageData(); // 准备参数 - SysUserExportReqVO reqVO = new SysUserExportReqVO(); + UserExportReqVO reqVO = new UserExportReqVO(); reqVO.setUsername("yudao"); reqVO.setMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -288,11 +279,11 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { reqVO.setEndTime(buildTime(2020, 12, 24)); reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 // mock 方法 - List deptList = newArrayList(randomPojo(SysDeptDO.class, o -> o.setId(2L))); + List deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L))); when(deptService.getDeptsByParentIdFromCache(eq(reqVO.getDeptId()), eq(true))).thenReturn(deptList); // 调用 - List list = userService.getUsers(reqVO); + List list = userService.getUsers(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbUser, list.get(0)); @@ -301,9 +292,9 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { /** * 初始化 getUserPage 方法的测试数据 */ - private SysUserDO initGetUserPageData() { + private AdminUserDO initGetUserPageData() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(o -> { // 等会查询到 + AdminUserDO dbUser = randomAdminUserDO(o -> { // 等会查询到 o.setUsername("yudaoyuanma"); o.setMobile("15601691300"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -330,11 +321,13 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testImportUsers_01() { // 准备参数 - SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class); - // mock 方法 + UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> { + }); + // mock 方法,模拟失败 + doThrow(new ServiceException(DEPT_NOT_FOUND)).when(deptService).validDepts(any()); // 调用 - SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + UserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); // 断言 assertEquals(0, respVO.getCreateUsernames().size()); assertEquals(0, respVO.getUpdateUsernames().size()); @@ -348,12 +341,12 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testImportUsers_02() { // 准备参数 - SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围 }); // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + DeptDO dept = randomPojo(DeptDO.class, o -> { o.setId(importUser.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); @@ -362,10 +355,10 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { when(passwordEncoder.encode(eq("yudaoyuanma"))).thenReturn("java"); // 调用 - SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + UserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); // 断言 assertEquals(1, respVO.getCreateUsernames().size()); - SysUserDO user = userMapper.selectByUsername(respVO.getCreateUsernames().get(0)); + AdminUserDO user = userMapper.selectByUsername(respVO.getCreateUsernames().get(0)); assertPojoEquals(importUser, user); assertEquals("java", user.getPassword()); assertEquals(0, respVO.getUpdateUsernames().size()); @@ -378,23 +371,23 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testImportUsers_03() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 - SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围 o.setUsername(dbUser.getUsername()); }); // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + DeptDO dept = randomPojo(DeptDO.class, o -> { o.setId(importUser.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); // 调用 - SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), false); + UserImportRespVO respVO = userService.importUsers(newArrayList(importUser), false); // 断言 assertEquals(0, respVO.getCreateUsernames().size()); assertEquals(0, respVO.getUpdateUsernames().size()); @@ -408,27 +401,27 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testImportUsers_04() { // mock 数据 - SysUserDO dbUser = randomSysUserDO(); + AdminUserDO dbUser = randomAdminUserDO(); userMapper.insert(dbUser); // 准备参数 - SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围 o.setUsername(dbUser.getUsername()); }); // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + DeptDO dept = randomPojo(DeptDO.class, o -> { o.setId(importUser.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); // 调用 - SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + UserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); // 断言 assertEquals(0, respVO.getCreateUsernames().size()); assertEquals(1, respVO.getUpdateUsernames().size()); - SysUserDO user = userMapper.selectByUsername(respVO.getUpdateUsernames().get(0)); + AdminUserDO user = userMapper.selectByUsername(respVO.getUpdateUsernames().get(0)); assertPojoEquals(importUser, user); assertEquals(0, respVO.getFailureUsernames().size()); } @@ -443,7 +436,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 准备参数 String username = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setUsername(username))); + userMapper.insert(randomAdminUserDO(o -> o.setUsername(username))); // 调用,校验异常 assertServiceException(() -> userService.checkUsernameUnique(null, username), @@ -456,7 +449,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); String username = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setUsername(username))); + userMapper.insert(randomAdminUserDO(o -> o.setUsername(username))); // 调用,校验异常 assertServiceException(() -> userService.checkUsernameUnique(id, username), @@ -468,7 +461,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 准备参数 String email = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setEmail(email))); + userMapper.insert(randomAdminUserDO(o -> o.setEmail(email))); // 调用,校验异常 assertServiceException(() -> userService.checkEmailUnique(null, email), @@ -481,7 +474,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); String email = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setEmail(email))); + userMapper.insert(randomAdminUserDO(o -> o.setEmail(email))); // 调用,校验异常 assertServiceException(() -> userService.checkEmailUnique(id, email), @@ -493,7 +486,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { // 准备参数 String mobile = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setMobile(mobile))); + userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile))); // 调用,校验异常 assertServiceException(() -> userService.checkMobileUnique(null, mobile), @@ -506,58 +499,13 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); String mobile = randomString(); // mock 数据 - userMapper.insert(randomSysUserDO(o -> o.setMobile(mobile))); + userMapper.insert(randomAdminUserDO(o -> o.setMobile(mobile))); // 调用,校验异常 assertServiceException(() -> userService.checkMobileUnique(id, mobile), USER_MOBILE_EXISTS); } - @Test - public void testCheckDeptEnable_notFound() { - assertServiceException(() -> userService.checkDeptEnable(randomLongId()), - DEPT_NOT_FOUND); - } - - @Test - public void testCheckDeptEnable_notEnable() { - // 准备参数 - Long deptId = randomLongId(); - // mock deptService 的方法 - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { - o.setId(deptId); - o.setStatus(CommonStatusEnum.DISABLE.getStatus()); - }); - when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); - - // 调用,校验异常 - assertServiceException(() -> userService.checkDeptEnable(deptId), - DEPT_NOT_ENABLE); - } - - @Test - public void testCheckPostEnable_notFound() { - assertServiceException(() -> userService.checkPostEnable(randomSet(Long.class)), - POST_NOT_FOUND); - } - - @Test - public void testCheckPostEnable_notEnable() { - // 准备参数 - Set postIds = randomSet(Long.class); - // mock postService 的方法 - List posts = CollectionUtils.convertList(postIds, postId -> - randomPojo(SysPostDO.class, o -> { - o.setId(postId); - o.setStatus(CommonStatusEnum.DISABLE.getStatus()); - })); - when(postService.getPosts(eq(postIds), isNull())).thenReturn(posts); - - // 调用,校验异常 - assertServiceException(() -> userService.checkPostEnable(postIds), - POST_NOT_ENABLE, CollUtil.getFirst(posts).getName()); - } - @Test public void testCheckOldPassword_notExists() { assertServiceException(() -> userService.checkOldPassword(randomLongId(), randomString()), @@ -567,7 +515,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @Test public void testCheckOldPassword_passwordFailed() { // mock 数据 - SysUserDO user = randomSysUserDO(); + AdminUserDO user = randomAdminUserDO(); userMapper.insert(user); // 准备参数 Long id = user.getId(); @@ -580,32 +528,32 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { verify(passwordEncoder, times(1)).matches(eq(oldPassword), eq(user.getPassword())); } - @Test - public void testUsersByPostIds() { - // 准备参数 - Collection postIds = asSet(10L, 20L); - // mock 方法 - SysUserDO user1 = randomSysUserDO(o -> o.setPostIds(asSet(10L, 30L))); - userMapper.insert(user1); - SysUserDO user2 = randomSysUserDO(o -> o.setPostIds(singleton(100L))); - userMapper.insert(user2); - - // 调用 - List result = userService.getUsersByPostIds(postIds); - // 断言 - assertEquals(1, result.size()); - assertEquals(user1, result.get(0)); - } +// @Test //TODO jason 已经移到userCoreService.getUsersByPostIds +// public void testUsersByPostIds() { +// // 准备参数 +// Collection postIds = asSet(10L, 20L); +// // mock 方法 +// AdminUserDO user1 = randomAdminUserDO(o -> o.setPostIds(asSet(10L, 30L))); +// userMapper.insert(user1); +// AdminUserDO user2 = randomAdminUserDO(o -> o.setPostIds(singleton(100L))); +// userMapper.insert(user2); +// +// // 调用 +// List result = userService.getUsersByPostIds(postIds); +// // 断言 +// assertEquals(1, result.size()); +// assertEquals(user1, result.get(0)); +// } // ========== 随机对象 ========== @SafeVarargs - private static SysUserDO randomSysUserDO(Consumer... consumers) { - Consumer consumer = (o) -> { + private static AdminUserDO randomAdminUserDO(Consumer... consumers) { + Consumer consumer = (o) -> { o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setSex(randomEle(SexEnum.values()).getSex()); // 保证 sex 的范围 }; - return randomPojo(SysUserDO.class, ArrayUtils.append(consumer, consumers)); + return randomPojo(AdminUserDO.class, ArrayUtils.append(consumer, consumers)); } } diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisUnitTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisUnitTest.java new file mode 100644 index 0000000000..a526d934a6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbAndRedisUnitTest.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.system.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.redisson.spring.starter.RedissonAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +/** + * 依赖内存 DB + Redis 的单元测试 + * + * 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB +public class BaseDbAndRedisUnitTest { + + @Import({ + // DB 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类 + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + // Redis 配置类 + RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer + RedisAutoConfiguration.class, // Spring Redis 自动配置类 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 + RedissonAutoConfiguration.class, // Redisson 自动高配置类 + }) + public static class Application { + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbUnitTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbUnitTest.java new file mode 100644 index 0000000000..b897afc9f3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseDbUnitTest.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.system.test; + +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; + +/** + * 依赖内存 DB 的单元测试 + * + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB +public class BaseDbUnitTest { + + @Import({ + // DB 配置类 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类 + // MyBatis 配置类 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 + }) + public static class Application { + } + +} diff --git a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseRedisUnitTest.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseRedisUnitTest.java similarity index 86% rename from yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseRedisUnitTest.java rename to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseRedisUnitTest.java index 7e650bc3e2..0e3472f4fc 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseRedisUnitTest.java +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/BaseRedisUnitTest.java @@ -1,8 +1,6 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.module.system.test; -import cn.iocoder.yudao.adminserver.config.RedisTestConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; -import cn.iocoder.yudao.framework.tracer.config.YudaoTracerAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; diff --git a/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/RedisTestConfiguration.java b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/RedisTestConfiguration.java new file mode 100644 index 0000000000..71c912d45e --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/test/RedisTestConfiguration.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.system.test; + +import com.github.fppt.jedismock.RedisServer; +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +import java.io.IOException; + +@Configuration(proxyBeanMethods = false) +@Lazy(false) // 禁止延迟加载 +@EnableConfigurationProperties(RedisProperties.class) +public class RedisTestConfiguration { + + /** + * 创建模拟的 Redis Server 服务器 + */ + @Bean + public RedisServer redisServer(RedisProperties properties) throws IOException { + RedisServer redisServer = new RedisServer(properties.getPort()); + // TODO 芋艿:一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样,就导致端口被占用,无法启动。。。 + try { + redisServer.start(); + } catch (Exception ignore) {} + return redisServer; + } + +} diff --git a/yudao-module-system/yudao-module-system-impl/src/test/resources/application-unit-test.yaml b/yudao-module-system/yudao-module-system-impl/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000000..c7785de7f7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/resources/application-unit-test.yaml @@ -0,0 +1,50 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module + captcha: + timeout: 5m + width: 160 + height: 60 diff --git a/yudao-module-system/yudao-module-system-impl/src/test/resources/logback.xml b/yudao-module-system/yudao-module-system-impl/src/test/resources/logback.xml new file mode 100644 index 0000000000..daf756bff0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-system/yudao-module-system-impl/src/test/resources/sql/clean.sql b/yudao-module-system/yudao-module-system-impl/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..88c7c845bd --- /dev/null +++ b/yudao-module-system/yudao-module-system-impl/src/test/resources/sql/clean.sql @@ -0,0 +1,18 @@ +DELETE FROM "system_dept"; +DELETE FROM "system_dict_data"; +DELETE FROM "system_role"; +DELETE FROM "system_role_menu"; +DELETE FROM "system_menu"; +DELETE FROM "system_user_role"; +DELETE FROM "system_dict_type"; +DELETE FROM "system_user_session"; +DELETE FROM "system_post"; +DELETE FROM "system_login_log"; +DELETE FROM "system_operate_log"; +DELETE FROM "system_user"; +DELETE FROM "system_sms_channel"; +DELETE FROM "system_sms_template"; +DELETE FROM "system_sms_log"; +DELETE FROM "system_error_code"; +DELETE FROM "system_social_user"; +DELETE FROM "system_tenant"; diff --git a/yudao-admin-server/src/test/resources/sql/create_tables.sql b/yudao-module-system/yudao-module-system-impl/src/test/resources/sql/create_tables.sql similarity index 58% rename from yudao-admin-server/src/test/resources/sql/create_tables.sql rename to yudao-module-system/yudao-module-system-impl/src/test/resources/sql/create_tables.sql index 9b2f0d69f1..914352e8f1 100644 --- a/yudao-admin-server/src/test/resources/sql/create_tables.sql +++ b/yudao-module-system/yudao-module-system-impl/src/test/resources/sql/create_tables.sql @@ -1,75 +1,6 @@ --- inf 开头的 DB - -CREATE TABLE IF NOT EXISTS "inf_config" ( - "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "group" varchar(50) NOT NULL, - "type" tinyint NOT NULL, - "name" varchar(100) NOT NULL DEFAULT '', - "key" varchar(100) NOT NULL DEFAULT '', - "value" varchar(500) NOT NULL DEFAULT '', - "sensitive" bit NOT NULL, - "remark" varchar(500) DEFAULT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '参数配置表'; - -CREATE TABLE IF NOT EXISTS "inf_file" ( - "id" varchar(188) NOT NULL, - "type" varchar(63) DEFAULT NULL, - "content" blob NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint not null default '0', - PRIMARY KEY ("id") -) COMMENT '文件表'; - -CREATE TABLE IF NOT EXISTS "inf_job" ( - "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '任务编号', - "name" varchar(32) NOT NULL COMMENT '任务名称', - "status" tinyint(4) NOT NULL COMMENT '任务状态', - "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', - "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', - "cron_expression" varchar(32) NOT NULL COMMENT 'CRON 表达式', - "retry_count" int(11) NOT NULL DEFAULT '0' COMMENT '重试次数', - "retry_interval" int(11) NOT NULL DEFAULT '0' COMMENT '重试间隔', - "monitor_timeout" int(11) NOT NULL DEFAULT '0' COMMENT '监控超时时间', - "creator" varchar(64) DEFAULT '' COMMENT '创建者', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - "updater" varchar(64) DEFAULT '' COMMENT '更新者', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - "deleted" bit NOT NULL DEFAULT FALSE COMMENT '是否删除', - PRIMARY KEY ("id") -) COMMENT='定时任务表'; - -CREATE TABLE IF NOT EXISTS "inf_job_log" ( - "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '日志编号', - "job_id" bigint(20) NOT NULL COMMENT '任务编号', - "handler_name" varchar(64) NOT NULL COMMENT '处理器的名字', - "handler_param" varchar(255) DEFAULT NULL COMMENT '处理器的参数', - "execute_index" tinyint(4) NOT NULL DEFAULT '1' COMMENT '第几次执行', - "begin_time" datetime NOT NULL COMMENT '开始执行时间', - "end_time" datetime DEFAULT NULL COMMENT '结束执行时间', - "duration" int(11) DEFAULT NULL COMMENT '执行时长', - "status" tinyint(4) NOT NULL COMMENT '任务状态', - "result" varchar(4000) DEFAULT '' COMMENT '结果数据', - "creator" varchar(64) DEFAULT '' COMMENT '创建者', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - "updater" varchar(64) DEFAULT '' COMMENT '更新者', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - "deleted" bit(1) NOT NULL DEFAULT FALSE COMMENT '是否删除', - PRIMARY KEY ("id") -)COMMENT='定时任务日志表'; - -- sys 开头的 DB -CREATE TABLE IF NOT EXISTS "sys_dept" ( +CREATE TABLE IF NOT EXISTS "system_dept" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(30) NOT NULL DEFAULT '', "parent_id" bigint NOT NULL DEFAULT '0', @@ -87,7 +18,7 @@ CREATE TABLE IF NOT EXISTS "sys_dept" ( PRIMARY KEY ("id") ) COMMENT '部门表'; -CREATE TABLE IF NOT EXISTS "sys_dict_data" ( +CREATE TABLE IF NOT EXISTS "system_dict_data" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "sort" int NOT NULL DEFAULT '0', "label" varchar(100) NOT NULL DEFAULT '', @@ -103,7 +34,7 @@ CREATE TABLE IF NOT EXISTS "sys_dict_data" ( PRIMARY KEY ("id") ) COMMENT '字典数据表'; -CREATE TABLE IF NOT EXISTS "sys_role" ( +CREATE TABLE IF NOT EXISTS "system_role" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(30) NOT NULL, "code" varchar(100) NOT NULL, @@ -121,7 +52,7 @@ CREATE TABLE IF NOT EXISTS "sys_role" ( PRIMARY KEY ("id") ) COMMENT '角色信息表'; -CREATE TABLE IF NOT EXISTS "sys_role_menu" ( +CREATE TABLE IF NOT EXISTS "system_role_menu" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "role_id" bigint NOT NULL, "menu_id" bigint NOT NULL, @@ -133,7 +64,7 @@ CREATE TABLE IF NOT EXISTS "sys_role_menu" ( PRIMARY KEY ("id") ) COMMENT '角色和菜单关联表'; -CREATE TABLE IF NOT EXISTS "sys_menu" ( +CREATE TABLE IF NOT EXISTS "system_menu" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(50) NOT NULL, "permission" varchar(100) NOT NULL DEFAULT '', @@ -152,7 +83,7 @@ CREATE TABLE IF NOT EXISTS "sys_menu" ( PRIMARY KEY ("id") ) COMMENT '菜单权限表'; -CREATE TABLE IF NOT EXISTS "sys_user_role" ( +CREATE TABLE IF NOT EXISTS "system_user_role" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "user_id" bigint NOT NULL, "role_id" bigint NOT NULL, @@ -164,7 +95,7 @@ CREATE TABLE IF NOT EXISTS "sys_user_role" ( PRIMARY KEY ("id") ) COMMENT '用户和角色关联表'; -CREATE TABLE IF NOT EXISTS "sys_dict_type" ( +CREATE TABLE IF NOT EXISTS "system_dict_type" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(100) NOT NULL DEFAULT '', "type" varchar(100) NOT NULL DEFAULT '', @@ -178,7 +109,7 @@ CREATE TABLE IF NOT EXISTS "sys_dict_type" ( PRIMARY KEY ("id") ) COMMENT '字典类型表'; -CREATE TABLE IF NOT EXISTS `sys_user_session` ( +CREATE TABLE IF NOT EXISTS `system_user_session` ( `id` varchar(32) NOT NULL, `user_id` bigint DEFAULT NULL, "user_type" tinyint NOT NULL, @@ -195,7 +126,7 @@ CREATE TABLE IF NOT EXISTS `sys_user_session` ( PRIMARY KEY (`id`) ) COMMENT '用户在线 Session'; -CREATE TABLE IF NOT EXISTS "sys_post" ( +CREATE TABLE IF NOT EXISTS "system_post" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "code" varchar(64) NOT NULL, "name" varchar(50) NOT NULL, @@ -211,7 +142,7 @@ CREATE TABLE IF NOT EXISTS "sys_post" ( PRIMARY KEY ("id") ) COMMENT '岗位信息表'; -CREATE TABLE IF NOT EXISTS "sys_notice" ( +CREATE TABLE IF NOT EXISTS "system_notice" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "title" varchar(50) NOT NULL COMMENT '公告标题', "content" text NOT NULL COMMENT '公告内容', @@ -226,7 +157,7 @@ CREATE TABLE IF NOT EXISTS "sys_notice" ( PRIMARY KEY("id") ) COMMENT '通知公告表'; -CREATE TABLE IF NOT EXISTS `sys_login_log` ( +CREATE TABLE IF NOT EXISTS `system_login_log` ( `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, `log_type` bigint(4) NOT NULL, "user_id" bigint not null default '0', @@ -244,7 +175,7 @@ CREATE TABLE IF NOT EXISTS `sys_login_log` ( PRIMARY KEY (`id`) ) COMMENT ='系统访问记录'; -CREATE TABLE IF NOT EXISTS `sys_operate_log` ( +CREATE TABLE IF NOT EXISTS `system_operate_log` ( `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, `trace_id` varchar(64) NOT NULL DEFAULT '', `user_id` bigint(20) NOT NULL, @@ -273,7 +204,7 @@ CREATE TABLE IF NOT EXISTS `sys_operate_log` ( PRIMARY KEY (`id`) ) COMMENT ='操作日志记录'; -CREATE TABLE IF NOT EXISTS "sys_user" ( +CREATE TABLE IF NOT EXISTS "system_user" ( "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, "username" varchar(30) not null, "password" varchar(100) not null default '', @@ -354,7 +285,7 @@ CREATE TABLE IF NOT EXISTS "inf_api_error_log" ( primary key ("id") ) COMMENT '系统异常日志'; -CREATE TABLE IF NOT EXISTS "sys_sms_channel" ( +CREATE TABLE IF NOT EXISTS "system_sms_channel" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "signature" varchar(10) NOT NULL, "code" varchar(63) NOT NULL, @@ -371,7 +302,7 @@ CREATE TABLE IF NOT EXISTS "sys_sms_channel" ( PRIMARY KEY ("id") ) COMMENT '短信渠道'; -CREATE TABLE IF NOT EXISTS "sys_sms_template" ( +CREATE TABLE IF NOT EXISTS "system_sms_template" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "type" tinyint NOT NULL, "status" tinyint NOT NULL, @@ -391,7 +322,7 @@ CREATE TABLE IF NOT EXISTS "sys_sms_template" ( PRIMARY KEY ("id") ) COMMENT '短信模板'; -CREATE TABLE IF NOT EXISTS "sys_sms_log" ( +CREATE TABLE IF NOT EXISTS "system_sms_log" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "channel_id" bigint NOT NULL, "channel_code" varchar(63) NOT NULL, @@ -424,7 +355,7 @@ CREATE TABLE IF NOT EXISTS "sys_sms_log" ( PRIMARY KEY ("id") ) COMMENT '短信日志'; -CREATE TABLE IF NOT EXISTS "sys_error_code" ( +CREATE TABLE IF NOT EXISTS "system_error_code" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "type" tinyint NOT NULL DEFAULT '0', "application_name" varchar(50) NOT NULL, @@ -439,7 +370,7 @@ CREATE TABLE IF NOT EXISTS "sys_error_code" ( PRIMARY KEY ("id") ) COMMENT '错误码表'; -CREATE TABLE IF NOT EXISTS "sys_social_user" ( +CREATE TABLE IF NOT EXISTS "system_social_user" ( "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, "user_id" bigint NOT NULL, "user_type" tinyint NOT NULL DEFAULT '0', @@ -459,7 +390,7 @@ CREATE TABLE IF NOT EXISTS "sys_social_user" ( PRIMARY KEY ("id") ) COMMENT '社交用户'; -CREATE TABLE IF NOT EXISTS "sys_tenant" ( +CREATE TABLE IF NOT EXISTS "system_tenant" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(63) NOT NULL, "contact_name" varchar(255) NOT NULL, @@ -472,153 +403,3 @@ CREATE TABLE IF NOT EXISTS "sys_tenant" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '租户'; - - -CREATE TABLE IF NOT EXISTS "pay_merchant" -( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "no" varchar(32) NOT NULL, - "name" varchar(64) NOT NULL, - "short_name" varchar(64) NOT NULL, - "status" tinyint NOT NULL, - "remark" varchar(255) DEFAULT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit(1) NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '支付商户信息'; - --- bpm 开头的 DB - -CREATE TABLE IF NOT EXISTS "pay_app" ( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar(64) NOT NULL, - "status" tinyint NOT NULL, - "remark" varchar(255) DEFAULT NULL, - `pay_notify_url` varchar(1024) NOT NULL, - `refund_notify_url` varchar(1024) NOT NULL, - `merchant_id` bigint(20) NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit(1) NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT = '支付应用信息'; - -CREATE TABLE IF NOT EXISTS "pay_channel" ( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "code" varchar(32) NOT NULL, - "status" tinyint(4) NOT NULL, - "remark" varchar(255) DEFAULT NULL, - "fee_rate" double NOT NULL DEFAULT 0, - "merchant_id" bigint(20) NOT NULL, - "app_id" bigint(20) NOT NULL, - "config" varchar(10240) NOT NULL, - "creator" varchar(64) NULL DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) NULL DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit(1) NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT = '支付渠道'; - -CREATE TABLE IF NOT EXISTS `pay_order` ( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `merchant_id` bigint(20) NOT NULL, - `app_id` bigint(20) NOT NULL, - `channel_id` bigint(20) DEFAULT NULL, - `channel_code` varchar(32) DEFAULT NULL, - `merchant_order_id` varchar(64) NOT NULL, - `subject` varchar(32) NOT NULL, - `body` varchar(128) NOT NULL, - `notify_url` varchar(1024) NOT NULL, - `notify_status` tinyint(4) NOT NULL, - `amount` bigint(20) NOT NULL, - `channel_fee_rate` double DEFAULT 0, - `channel_fee_amount` bigint(20) DEFAULT 0, - `status` tinyint(4) NOT NULL, - `user_ip` varchar(50) NOT NULL, - `expire_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, - `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, - `success_extension_id` bigint(20) DEFAULT NULL COMMENT '支付成功的订单拓展单编号', - `refund_status` tinyint(4) NOT NULL, - `refund_times` tinyint(4) NOT NULL, - `refund_amount` bigint(20) NOT NULL, - `channel_user_id` varchar(255) DEFAULT NULL, - `channel_order_no` varchar(64) DEFAULT NULL, - `creator` varchar(64) DEFAULT '', - `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updater` varchar(64) DEFAULT '', - `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `deleted` bit(1) NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT = '支付订单'; - -CREATE TABLE IF NOT EXISTS `pay_refund` ( - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `merchant_id` bigint(20) NOT NULL, - `app_id` bigint(20) NOT NULL, - `channel_id` bigint(20) NOT NULL, - `channel_code` varchar(32) NOT NULL, - `order_id` bigint(20) NOT NULL, - `trade_no` varchar(64) NOT NULL, - `merchant_order_id` varchar(64) NOT NULL, - `merchant_refund_no` varchar(64) NOT NULL, - `notify_url` varchar(1024) NOT NULL, - `notify_status` tinyint(4) NOT NULL, - `status` tinyint(4) NOT NULL, - `type` tinyint(4) NOT NULL, - `pay_amount` bigint(20) NOT NULL, - `refund_amount` bigint(20) NOT NULL, - `reason` varchar(256) NOT NULL, - `user_ip` varchar(50) NULL DEFAULT NULL, - `channel_order_no` varchar(64) NOT NULL, - `channel_refund_no` varchar(64) NULL DEFAULT NULL, - `channel_error_code` varchar(128) NULL DEFAULT NULL, - `channel_error_msg` varchar(256) NULL DEFAULT NULL, - `channel_extras` varchar(1024) NULL DEFAULT NULL, - `expire_time` datetime(0) NULL DEFAULT NULL, - `success_time` datetime(0) NULL DEFAULT NULL, - `notify_time` datetime(0) NULL DEFAULT NULL, - `creator` varchar(64) NULL DEFAULT '', - `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updater` varchar(64) NULL DEFAULT '', - `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `deleted` bit(1) NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT = '退款订单'; - --- bpm 开头的 DB - -CREATE TABLE IF NOT EXISTS "bpm_form" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar(63) NOT NULL, - "status" tinyint NOT NULL, - "fields" varchar(255) NOT NULL, - "conf" varchar(255) NOT NULL, - "remark" varchar(255), - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") -) COMMENT '动态表单'; - -CREATE TABLE IF NOT EXISTS "bpm_user_group" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "name" varchar(63) NOT NULL, - "description" varchar(255) NOT NULL, - "status" tinyint NOT NULL, - "member_user_ids" varchar(255) NOT NULL, - "creator" varchar(64) DEFAULT '', - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar(64) DEFAULT '', - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") - ) COMMENT '用户组'; diff --git a/yudao-module-tool/pom.xml b/yudao-module-tool/pom.xml new file mode 100644 index 0000000000..094286fa6e --- /dev/null +++ b/yudao-module-tool/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-module-tool-api + yudao-module-tool-impl + + yudao-module-tool + pom + + ${artifactId} + + tool 模块,我们放研发工具,提升研发效率与质量。 + 例如说:代码生成器、接口文档等等 + + + diff --git a/yudao-module-tool/yudao-module-tool-api/pom.xml b/yudao-module-tool/yudao-module-tool-api/pom.xml new file mode 100644 index 0000000000..ea237be1fc --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-api/pom.xml @@ -0,0 +1,26 @@ + + + + cn.iocoder.boot + yudao-module-tool + ${revision} + + 4.0.0 + yudao-module-tool-api + jar + + ${artifactId} + + tool 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + diff --git a/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/api/package-info.java b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/api/package-info.java new file mode 100644 index 0000000000..77a92cf560 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/api/package-info.java @@ -0,0 +1,4 @@ +/** + * Tool API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.tool.api; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolDictTypeConstants.java b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/DictTypeConstants.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolDictTypeConstants.java rename to yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/DictTypeConstants.java index 1bf2b7a1d0..f22e39f1ed 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolDictTypeConstants.java +++ b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/DictTypeConstants.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums; +package cn.iocoder.yudao.module.tool.enums; /** * Tool 字典类型的枚举类 * * @author 芋道源码 */ -public interface ToolDictTypeConstants { +public interface DictTypeConstants { String TEST_DEMO_TYPE = "tool_test_demo_type"; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolErrorCodeConstants.java b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/ErrorCodeConstants.java similarity index 91% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolErrorCodeConstants.java rename to yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/ErrorCodeConstants.java index cdf341d749..2d62edc1be 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/ToolErrorCodeConstants.java +++ b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/enums/ErrorCodeConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums; +package cn.iocoder.yudao.module.tool.enums; import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; * * tool 系统,使用 1-003-000-000 段 */ -public interface ToolErrorCodeConstants { +public interface ErrorCodeConstants { // ========== 字典类型(测试) 1003000000 ========== ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1003000000, "测试示例不存在"); diff --git a/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/package-info.java b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/package-info.java new file mode 100644 index 0000000000..1b5a668009 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-api/src/main/java/cn/iocoder/yudao/module/tool/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.tool; diff --git a/yudao-module-tool/yudao-module-tool-impl/pom.xml b/yudao-module-tool/yudao-module-tool-impl/pom.xml new file mode 100644 index 0000000000..4d8cb4876d --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/pom.xml @@ -0,0 +1,82 @@ + + + + yudao-module-tool + cn.iocoder.boot + ${revision} + + 4.0.0 + yudao-module-tool-impl + jar + + ${artifactId} + + tool 模块,我们放研发工具,提升研发效率与质量。 + 例如说:代码生成器、接口文档等等 + + + + + cn.iocoder.boot + yudao-module-tool-api + ${revision} + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + org.apache.velocity + velocity-engine-core + + + + cn.smallbun.screw + screw-core + + + + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/ToolCodegenController.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/CodegenController.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/ToolCodegenController.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/CodegenController.java index a6bd6a64b9..c7d6e9324e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/ToolCodegenController.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/CodegenController.java @@ -1,20 +1,21 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen; +package cn.iocoder.yudao.module.tool.controller.admin.codegen; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ZipUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenDetailRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenPreviewRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTablePageReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTableRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolSchemaTableRespVO; -import cn.iocoder.yudao.adminserver.modules.tool.convert.codegen.ToolCodegenConvert; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.service.codegen.ToolCodegenService; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenDetailRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenPreviewRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenUpdateReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTablePageReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTableRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.SchemaTableRespVO; +import cn.iocoder.yudao.module.tool.convert.codegen.CodegenConvert; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.tool.service.codegen.CodegenService; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import io.swagger.annotations.Api; @@ -36,15 +37,16 @@ import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Api(tags = "代码生成器") +@Api(tags = "管理后台 - 代码生成器") @RestController @RequestMapping("/tool/codegen") @Validated -public class ToolCodegenController { +public class CodegenController { @Resource - private ToolCodegenService codegenService; + private CodegenService codegenService; @GetMapping("/db/table/list") @ApiOperation(value = "获得数据库自带的表定义列表", notes = "会过滤掉已经导入 Codegen 的表") @@ -53,34 +55,34 @@ public class ToolCodegenController { @ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", required = true, example = "芋道", dataTypeClass = String.class) }) @PreAuthorize("@ss.hasPermission('tool:codegen:query')") - public CommonResult> getSchemaTableList( + public CommonResult> getSchemaTableList( @RequestParam(value = "tableName", required = false) String tableName, @RequestParam(value = "tableComment", required = false) String tableComment) { // 获得数据库自带的表定义列表 - List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); + List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); // 移除在 Codegen 中,已经存在的 - Set existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), ToolCodegenTableDO::getTableName); + Set existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); schemaTables.removeIf(table -> existsTables.contains(table.getTableName())); - return success(ToolCodegenConvert.INSTANCE.convertList04(schemaTables)); + return success(CodegenConvert.INSTANCE.convertList04(schemaTables)); } @GetMapping("/table/page") @ApiOperation("获得表定义分页") @PreAuthorize("@ss.hasPermission('tool:codegen:query')") - public CommonResult> getCodeGenTablePage(@Valid ToolCodegenTablePageReqVO pageReqVO) { - PageResult pageResult = codegenService.getCodegenTablePage(pageReqVO); - return success(ToolCodegenConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getCodeGenTablePage(@Valid CodegenTablePageReqVO pageReqVO) { + PageResult pageResult = codegenService.getCodegenTablePage(pageReqVO); + return success(CodegenConvert.INSTANCE.convertPage(pageResult)); } @GetMapping("/detail") @ApiOperation("获得表和字段的明细") @ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('tool:codegen:query')") - public CommonResult getCodegenDetail(@RequestParam("tableId") Long tableId) { - ToolCodegenTableDO table = codegenService.getCodegenTablePage(tableId); - List columns = codegenService.getCodegenColumnListByTableId(tableId); + public CommonResult getCodegenDetail(@RequestParam("tableId") Long tableId) { + CodegenTableDO table = codegenService.getCodegenTablePage(tableId); + List columns = codegenService.getCodegenColumnListByTableId(tableId); // 拼装返回 - return success(ToolCodegenConvert.INSTANCE.convert(table, columns)); + return success(CodegenConvert.INSTANCE.convert(table, columns)); } @ApiOperation("基于数据库的表结构,创建代码生成器的表和字段定义") @@ -88,7 +90,7 @@ public class ToolCodegenController { @PostMapping("/create-list-from-db") @PreAuthorize("@ss.hasPermission('tool:codegen:create')") public CommonResult> createCodegenListFromDB(@RequestParam("tableNames") List tableNames) { - return success(codegenService.createCodegenListFromDB(tableNames)); + return success(codegenService.createCodegenListFromDB(getLoginUserId(), tableNames)); } @ApiOperation("基于 SQL 建表语句,创建代码生成器的表和字段定义") @@ -96,13 +98,13 @@ public class ToolCodegenController { @PostMapping("/create-list-from-sql") @PreAuthorize("@ss.hasPermission('tool:codegen:create')") public CommonResult createCodegenListFromSQL(@RequestParam("sql") String sql) { - return success(codegenService.createCodegenListFromSQL(sql)); + return success(codegenService.createCodegenListFromSQL(getLoginUserId(), sql)); } @ApiOperation("更新数据库的表和字段定义") @PutMapping("/update") @PreAuthorize("@ss.hasPermission('tool:codegen:update')") - public CommonResult updateCodegen(@Valid @RequestBody ToolCodegenUpdateReqVO updateReqVO) { + public CommonResult updateCodegen(@Valid @RequestBody CodegenUpdateReqVO updateReqVO) { codegenService.updateCodegen(updateReqVO); return success(true); } @@ -142,9 +144,9 @@ public class ToolCodegenController { @GetMapping("/preview") @ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('tool:codegen:preview')") - public CommonResult> previewCodegen(@RequestParam("tableId") Long tableId) { + public CommonResult> previewCodegen(@RequestParam("tableId") Long tableId) { Map codes = codegenService.generationCodes(tableId); - return success(ToolCodegenConvert.INSTANCE.convert(codes)); + return success(CodegenConvert.INSTANCE.convert(codes)); } @ApiOperation("下载生成代码") diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenDetailRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenDetailRespVO.java new file mode 100644 index 0000000000..c4e6ce068d --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenDetailRespVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo; + +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.column.CodegenColumnRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTableRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("管理后台 - 代码生成表和字段的明细 Response VO") +@Data +public class CodegenDetailRespVO { + + @ApiModelProperty("表定义") + private CodegenTableRespVO table; + + @ApiModelProperty("字段定义") + private List columns; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenPreviewRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenPreviewRespVO.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenPreviewRespVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenPreviewRespVO.java index 3a532708ad..5c2ec6858f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenPreviewRespVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenPreviewRespVO.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel(value = "代码生成预览 Response VO", description ="注意,每个文件都是一个该对象") +@ApiModel(value = "管理后台 - 代码生成预览 Response VO", description ="注意,每个文件都是一个该对象") @Data -public class ToolCodegenPreviewRespVO { +public class CodegenPreviewRespVO { @ApiModelProperty(value = "文件路径", required = true, example = "java/cn/iocoder/yudao/adminserver/modules/system/controller/test/SysTestDemoController.java") private String filePath; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenUpdateReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenUpdateReqVO.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenUpdateReqVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenUpdateReqVO.java index b82064ecc9..eb20c60218 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/ToolCodegenUpdateReqVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/CodegenUpdateReqVO.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.column.ToolCodegenColumnBaseVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTableBaseVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTableBaseVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.column.CodegenColumnBaseVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -12,9 +12,9 @@ import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.List; -@ApiModel("代码生成表和字段的修改 Request VO") +@ApiModel("管理后台 - 代码生成表和字段的修改 Request VO") @Data -public class ToolCodegenUpdateReqVO { +public class CodegenUpdateReqVO { @Valid // 校验内嵌的字段 @NotNull(message = "表定义不能为空") @@ -28,7 +28,7 @@ public class ToolCodegenUpdateReqVO { @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) - public static class Table extends ToolCodegenTableBaseVO { + public static class Table extends CodegenTableBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1") private Long id; @@ -39,7 +39,7 @@ public class ToolCodegenUpdateReqVO { @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) - public static class Column extends ToolCodegenColumnBaseVO { + public static class Column extends CodegenColumnBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnBaseVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java similarity index 94% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnBaseVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java index bd899712f0..5a9b693370 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/column/ToolCodegenColumnBaseVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.column; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.column; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class ToolCodegenColumnBaseVO { +public class CodegenColumnBaseVO { @ApiModelProperty(value = "表编号", required = true, example = "1") @NotNull(message = "表编号不能为空") @@ -70,7 +70,7 @@ public class ToolCodegenColumnBaseVO { @NotNull(message = "是否为 List 查询操作的字段不能为空") private Boolean listOperation; - @ApiModelProperty(value = "List 查询操作的条件类型", required = true, example = "LIKE", notes = "参见 ToolCodegenColumnListConditionEnum 枚举") + @ApiModelProperty(value = "List 查询操作的条件类型", required = true, example = "LIKE", notes = "参见 CodegenColumnListConditionEnum 枚举") @NotNull(message = "List 查询操作的条件类型不能为空") private String listOperationCondition; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnRespVO.java similarity index 69% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoRespVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnRespVO.java index e679fd4b0f..358f1f506f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/test/vo/ToolTestDemoRespVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/column/CodegenColumnRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.column; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("字典类型 Response VO") +@ApiModel("管理后台 - 代码生成字段定义 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ToolTestDemoRespVO extends ToolTestDemoBaseVO { +public class CodegenColumnRespVO extends CodegenColumnBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableBaseVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableBaseVO.java similarity index 80% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableBaseVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableBaseVO.java index e4fa2ab749..dbe155c8a3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableBaseVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,12 +10,16 @@ import javax.validation.constraints.NotNull; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class ToolCodegenTableBaseVO { +public class CodegenTableBaseVO { - @ApiModelProperty(value = "导入类型", required = true, example = "1", notes = "参见 ToolCodegenImportTypeEnum 枚举") + @ApiModelProperty(value = "导入类型", required = true, example = "1", notes = "参见 CodegenImportTypeEnum 枚举") @NotNull(message = "导入类型不能为空") private Integer importType; + @ApiModelProperty(value = "生成场景", required = true, example = "1", notes = "参见 CodegenSceneEnum 枚举") + @NotNull(message = "导入类型不能为空") + private Integer scene; + @ApiModelProperty(value = "表名称", required = true, example = "yudao") @NotNull(message = "表名称不能为空") private String tableName; @@ -35,7 +39,7 @@ public class ToolCodegenTableBaseVO { @NotNull(message = "业务名不能为空") private String businessName; - @ApiModelProperty(value = "类名称", required = true, example = "ToolCodegenTable") + @ApiModelProperty(value = "类名称", required = true, example = "CodegenTable") @NotNull(message = "类名称不能为空") private String className; @@ -47,7 +51,7 @@ public class ToolCodegenTableBaseVO { @NotNull(message = "作者不能为空") private String author; - @ApiModelProperty(value = "模板类型", required = true, example = "1", notes = "参见 ToolCodegenTemplateTypeEnum 枚举") + @ApiModelProperty(value = "模板类型", required = true, example = "1", notes = "参见 CodegenTemplateTypeEnum 枚举") @NotNull(message = "模板类型不能为空") private Integer templateType; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java similarity index 85% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java index b09238b062..69095e277b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTablePageReqVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTablePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.annotations.ApiModel; @@ -12,11 +12,11 @@ import java.util.Date; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("表定义分页 Request VO") +@ApiModel("管理后台 - 表定义分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ToolCodegenTablePageReqVO extends PageParam { +public class CodegenTablePageReqVO extends PageParam { @ApiModelProperty(value = "表名称", example = "yudao", notes = "模糊匹配") private String tableName; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableRespVO.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableRespVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableRespVO.java index 73ec3f880b..06d7c0d459 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolCodegenTableRespVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/CodegenTableRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -8,11 +8,11 @@ import lombok.ToString; import java.util.Date; -@ApiModel("代码生成表定义 Response VO") +@ApiModel("管理后台 - 代码生成表定义 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ToolCodegenTableRespVO extends ToolCodegenTableBaseVO { +public class CodegenTableRespVO extends CodegenTableBaseVO { @ApiModelProperty(value = "编号", required = true, example = "1") private Long id; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolSchemaTableRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/SchemaTableRespVO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolSchemaTableRespVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/SchemaTableRespVO.java index 284856f291..8b54b64f27 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/controller/codegen/vo/table/ToolSchemaTableRespVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/codegen/vo/table/SchemaTableRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table; +package cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,9 +6,9 @@ import lombok.Data; import java.util.Date; -@ApiModel("数据字典的表定义 Response VO") +@ApiModel("管理后台 - 数据字典的表定义 Response VO") @Data -public class ToolSchemaTableRespVO { +public class SchemaTableRespVO { @ApiModelProperty(value = "数据库", required = true, example = "yudao") private String tableSchema; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/doc/InfDbDocController.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/doc/DbDocController.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/doc/InfDbDocController.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/doc/DbDocController.java index 48b52f88ab..cda1a67631 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/doc/InfDbDocController.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/doc/DbDocController.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.infra.controller.doc; +package cn.iocoder.yudao.module.tool.controller.admin.doc; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; @@ -16,7 +16,6 @@ import com.zaxxer.hikari.HikariDataSource; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -26,12 +25,13 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; -@Api(tags = "数据库文档") +@Api(tags = "管理后台 - 数据库文档") @RestController -@RequestMapping("/infra/db-doc") -public class InfDbDocController { +@RequestMapping("/tool/db-doc") +public class DbDocController { @Resource private DynamicDataSourceProperties dynamicDataSourceProperties; @@ -44,7 +44,8 @@ public class InfDbDocController { @GetMapping("/export-html") @ApiOperation("导出 html 格式的数据文档") - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", + dataTypeClass = Boolean.class) public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.HTML, deleteFile, response); @@ -52,7 +53,8 @@ public class InfDbDocController { @GetMapping("/export-word") @ApiOperation("导出 word 格式的数据文档") - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", + dataTypeClass = Boolean.class) public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.WORD, deleteFile, response); @@ -60,7 +62,8 @@ public class InfDbDocController { @GetMapping("/export-markdown") @ApiOperation("导出 markdown 格式的数据文档") - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", + dataTypeClass = Boolean.class) public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.MD, deleteFile, response); @@ -137,7 +140,7 @@ public class InfDbDocController { .fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径 .openOutputDir(false) // 打开目录 .fileType(fileOutputType) // 文件类型 - .produceType(EngineTemplateType.freemarker) // 文件类型 + .produceType(EngineTemplateType.velocity) // 文件类型 .fileName(docFileName) // 自定义文件名称 .build(); } @@ -148,7 +151,7 @@ public class InfDbDocController { */ private static ProcessConfig buildProcessConfig() { return ProcessConfig.builder() - .ignoreTablePrefix(Collections.singletonList("QRTZ_")) // 忽略表前缀 + .ignoreTablePrefix(Arrays.asList("QRTZ_", "ACT_")) // 忽略表前缀 .build(); } diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/TestDemoController.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/TestDemoController.java new file mode 100755 index 0000000000..bc0de312ff --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/TestDemoController.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.annotations.*; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; +import cn.iocoder.yudao.module.tool.convert.test.TestDemoConvert; +import cn.iocoder.yudao.module.tool.service.test.TestDemoService; + +@Api(tags = "管理后台 - 字典类型") +@RestController +@RequestMapping("/tool/test-demo") +@Validated +public class TestDemoController { + + @Resource + private TestDemoService testDemoService; + + @PostMapping("/create") + @ApiOperation("创建字典类型") + @PreAuthorize("@ss.hasPermission('tool:test-demo:create')") public CommonResult createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) { + return success(testDemoService.createTestDemo(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新字典类型") + @PreAuthorize("@ss.hasPermission('tool:test-demo:update')") public CommonResult updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) { + testDemoService.updateTestDemo(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除字典类型") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')") + public CommonResult deleteTestDemo(@RequestParam("id") Long id) { + testDemoService.deleteTestDemo(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得字典类型") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") + public CommonResult getTestDemo(@RequestParam("id") Long id) { + TestDemoDO testDemo = testDemoService.getTestDemo(id); + return success(TestDemoConvert.INSTANCE.convert(testDemo)); + } + + @GetMapping("/list") + @ApiOperation("获得字典类型列表") + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") + public CommonResult> getTestDemoList(@RequestParam("ids") Collection ids) { + List list = testDemoService.getTestDemoList(ids); + return success(TestDemoConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @ApiOperation("获得字典类型分页") + @PreAuthorize("@ss.hasPermission('tool:test-demo:query')") public CommonResult> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) { + PageResult pageResult = testDemoService.getTestDemoPage(pageVO); + return success(TestDemoConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @ApiOperation("导出字典类型 Excel") + @PreAuthorize("@ss.hasPermission('tool:test-demo:export')") @OperateLog(type = EXPORT) + public void exportTestDemoExcel(@Valid TestDemoExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = testDemoService.getTestDemoList(exportReqVO); + // 导出 Excel + List datas = TestDemoConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoBaseVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoBaseVO.java new file mode 100755 index 0000000000..28eb831a73 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoBaseVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +/** +* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class TestDemoBaseVO { + + @ApiModelProperty(value = "名字", required = true) + @NotNull(message = "名字不能为空") + private String name; + + @ApiModelProperty(value = "状态", required = true) + @NotNull(message = "状态不能为空") + private Integer status; + + @ApiModelProperty(value = "类型", required = true) + @NotNull(message = "类型不能为空") + private Integer type; + + @ApiModelProperty(value = "分类", required = true) + @NotNull(message = "分类不能为空") + private Integer category; + + @ApiModelProperty(value = "备注") + private String remark; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoCreateReqVO.java old mode 100644 new mode 100755 similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoCreateReqVO.java index 3b0e69b99c..8fcecd9f1c --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppCreateReqVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoCreateReqVO.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; import lombok.*; import java.util.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("支付应用信息创建 Request VO") +@ApiModel("管理后台 - 字典类型创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class PayAppCreateReqVO extends PayAppBaseVO { +public class TestDemoCreateReqVO extends TestDemoBaseVO { } diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExcelVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExcelVO.java new file mode 100755 index 0000000000..496fa135d9 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExcelVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +import com.alibaba.excel.annotation.ExcelProperty; + +/** + * 字典类型 Excel VO + * + * @author 芋道源码 + */ +@Data +public class TestDemoExcelVO { + + @ExcelProperty("编号") + private Long id; + + @ExcelProperty("名字") + private String name; + + @ExcelProperty("状态") + private Integer status; + + @ExcelProperty("类型") + private Integer type; + + @ExcelProperty("分类") + private Integer category; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("创建时间") + private Date createTime; + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExportReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExportReqVO.java new file mode 100755 index 0000000000..ae47495f3e --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExportReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel(value = "管理后台 - 字典类型 Excel 导出 Request VO", description = "参数和 TestDemoPageReqVO 是一致的") +@Data +public class TestDemoExportReqVO { + + @ApiModelProperty(value = "名字") + private String name; + + @ApiModelProperty(value = "状态") + private Integer status; + + @ApiModelProperty(value = "类型") + private Integer type; + + @ApiModelProperty(value = "分类") + private Integer category; + + @ApiModelProperty(value = "备注") + private String remark; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "开始创建时间") + private Date beginCreateTime; + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ApiModelProperty(value = "结束创建时间") + private Date endCreateTime; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupPageReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoPageReqVO.java old mode 100644 new mode 100755 similarity index 61% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupPageReqVO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoPageReqVO.java index 6a4497afc5..1c9f8a9841 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/definition/vo/group/BpmUserGroupPageReqVO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.group; +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; import lombok.*; import java.util.*; @@ -8,18 +8,27 @@ import org.springframework.format.annotation.DateTimeFormat; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("用户组分页 Request VO") +@ApiModel("管理后台 - 字典类型分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class BpmUserGroupPageReqVO extends PageParam { +public class TestDemoPageReqVO extends PageParam { - @ApiModelProperty(value = "组名", example = "芋道") + @ApiModelProperty(value = "名字") private String name; - @ApiModelProperty(value = "状态", example = "1") + @ApiModelProperty(value = "状态") private Integer status; + @ApiModelProperty(value = "类型") + private Integer type; + + @ApiModelProperty(value = "分类") + private Integer category; + + @ApiModelProperty(value = "备注") + private String remark; + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ApiModelProperty(value = "开始创建时间") private Date beginCreateTime; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoRespVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoRespVO.java new file mode 100755 index 0000000000..cdc0e000de --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 字典类型 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TestDemoRespVO extends TestDemoBaseVO { + + @ApiModelProperty(value = "编号", required = true) + private Long id; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoUpdateReqVO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoUpdateReqVO.java new file mode 100755 index 0000000000..47953b14f2 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.tool.controller.admin.test.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 字典类型更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TestDemoUpdateReqVO extends TestDemoBaseVO { + + @ApiModelProperty(value = "编号", required = true) + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/app/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/app/package-info.java new file mode 100644 index 0000000000..3489a716e7 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位,避免 package 无法提交到 Git 仓库 + */ +package cn.iocoder.yudao.module.tool.controller.app; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/package-info.java new file mode 100644 index 0000000000..f06bab1671 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.tool.controller; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/codegen/CodegenConvert.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/codegen/CodegenConvert.java new file mode 100644 index 0000000000..08ab991bfb --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/codegen/CodegenConvert.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.tool.convert.codegen; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenDetailRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenPreviewRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenUpdateReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.column.CodegenColumnRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTableRespVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.SchemaTableRespVO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Mapper +public interface CodegenConvert { + + CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class); + + // ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ========== + + CodegenTableDO convert(SchemaTableDO bean); + + List convertList(List list); + + CodegenTableRespVO convert(SchemaColumnDO bean); + + // ========== CodegenTableDO 相关 ========== + +// List convertList02(List list); + + CodegenTableRespVO convert(CodegenTableDO bean); + + PageResult convertPage(PageResult page); + + // ========== CodegenTableDO 相关 ========== + + List convertList02(List list); + + CodegenTableDO convert(CodegenUpdateReqVO.Table bean); + + List convertList03(List columns); + + List convertList04(List list); + + // ========== 其它 ========== + + default CodegenDetailRespVO convert(CodegenTableDO table, List columns) { + CodegenDetailRespVO respVO = new CodegenDetailRespVO(); + respVO.setTable(convert(table)); + respVO.setColumns(convertList02(columns)); + return respVO; + } + + default List convert(Map codes) { + return codes.entrySet().stream().map(entry -> { + CodegenPreviewRespVO respVO = new CodegenPreviewRespVO(); + respVO.setFilePath(entry.getKey()); + respVO.setCode(entry.getValue()); + return respVO; + }).collect(Collectors.toList()); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/test/TestDemoConvert.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/test/TestDemoConvert.java new file mode 100755 index 0000000000..c959a66dfa --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/test/TestDemoConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.tool.convert.test; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; + +/** + * 字典类型 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface TestDemoConvert { + + TestDemoConvert INSTANCE = Mappers.getMapper(TestDemoConvert.class); + + TestDemoDO convert(TestDemoCreateReqVO bean); + + TestDemoDO convert(TestDemoUpdateReqVO bean); + + TestDemoRespVO convert(TestDemoDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenColumnDO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenColumnDO.java similarity index 78% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenColumnDO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenColumnDO.java index 7d0d950c03..65f1206400 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenColumnDO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenColumnDO.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen; +package cn.iocoder.yudao.module.tool.dal.dataobject.codegen; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenColumnHtmlTypeEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenColumnListConditionEnum; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -19,7 +18,7 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) @EqualsAndHashCode(callSuper = true) -public class ToolCodegenColumnDO extends BaseDO { +public class CodegenColumnDO extends BaseDO { /** * ID 编号 @@ -29,7 +28,7 @@ public class ToolCodegenColumnDO extends BaseDO { /** * 表编号 * - * 关联 {@link ToolCodegenTableDO#getId()} + * 关联 {@link CodegenTableDO#getId()} */ private Long tableId; @@ -80,7 +79,7 @@ public class ToolCodegenColumnDO extends BaseDO { /** * 字典类型 * - * 关联 {@link SysDictTypeDO#getType()} + * 关联 DictTypeDO 的 type 属性 */ private String dictType; /** @@ -105,7 +104,7 @@ public class ToolCodegenColumnDO extends BaseDO { /** * List 查询操作的条件类型 * - * 枚举 {@link ToolCodegenColumnListConditionEnum} + * 枚举 {@link CodegenColumnListConditionEnum} */ private String listOperationCondition; /** @@ -118,7 +117,7 @@ public class ToolCodegenColumnDO extends BaseDO { /** * 显示类型 * - * 枚举 {@link ToolCodegenColumnHtmlTypeEnum} + * 枚举 {@link CodegenColumnHtmlTypeEnum} */ private String htmlType; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenTableDO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenTableDO.java similarity index 77% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenTableDO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenTableDO.java index 4ed11b2be7..9585cb3882 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolCodegenTableDO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/CodegenTableDO.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen; +package cn.iocoder.yudao.module.tool.dal.dataobject.codegen; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenTemplateTypeEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenTemplateTypeEnum; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,7 +17,7 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) @EqualsAndHashCode(callSuper = true) -public class ToolCodegenTableDO extends BaseDO { +public class CodegenTableDO extends BaseDO { /** * ID 编号 @@ -27,9 +27,15 @@ public class ToolCodegenTableDO extends BaseDO { /** * 导入类型 * - * 枚举 {@link ToolCodegenTemplateTypeEnum} + * 枚举 {@link CodegenTemplateTypeEnum} */ private Integer importType; + /** + * 生成场景 + * + * 枚举 {@link CodegenSceneEnum} + */ + private Integer scene; // ========== 表相关字段 ========== @@ -80,7 +86,7 @@ public class ToolCodegenTableDO extends BaseDO { /** * 模板类型 * - * 枚举 {@link ToolCodegenTemplateTypeEnum} + * 枚举 {@link CodegenTemplateTypeEnum} */ private Integer templateType; @@ -89,7 +95,7 @@ public class ToolCodegenTableDO extends BaseDO { /** * 父菜单编号 * - * 关联 {@link SysMenuDO#getId()} + * 关联 MenuDO 的 id 属性 */ private Long parentMenuId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaColumnDO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaColumnDO.java similarity index 90% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaColumnDO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaColumnDO.java index e78e16f533..d7c2b0d22d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaColumnDO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaColumnDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen; +package cn.iocoder.yudao.module.tool.dal.dataobject.codegen; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -13,7 +13,7 @@ import lombok.Data; @TableName(value = "information_schema.columns", autoResultMap = true) @Data @Builder -public class ToolSchemaColumnDO { +public class SchemaColumnDO { /** * 表名称 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaTableDO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaTableDO.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaTableDO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaTableDO.java index e3e70352d8..eaec25fae7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/codegen/ToolSchemaTableDO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/codegen/SchemaTableDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen; +package cn.iocoder.yudao.module.tool.dal.dataobject.codegen; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Builder; @@ -14,7 +14,7 @@ import java.util.Date; @TableName(value = "information_schema.tables", autoResultMap = true) @Data @Builder -public class ToolSchemaTableDO { +public class SchemaTableDO { /** * 数据库 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/test/ToolTestDemoDO.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/test/TestDemoDO.java old mode 100644 new mode 100755 similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/test/ToolTestDemoDO.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/test/TestDemoDO.java index 0af46d798d..a82f7528fa --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/dal/dataobject/test/ToolTestDemoDO.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/test/TestDemoDO.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test; +package cn.iocoder.yudao.module.tool.dal.dataobject.test; -import lombok.*; -import java.util.*; -import com.baomidou.mybatisplus.annotation.*; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; /** * 字典类型 DO * - * @author 芋艿 + * @author 芋道源码 */ @TableName("tool_test_demo") @Data @@ -17,7 +17,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @Builder @NoArgsConstructor @AllArgsConstructor -public class ToolTestDemoDO extends BaseDO { +public class TestDemoDO extends BaseDO { /** * 编号 diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenColumnMapper.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenColumnMapper.java new file mode 100644 index 0000000000..8c1e47ea9a --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenColumnMapper.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.codegen; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface CodegenColumnMapper extends BaseMapperX { + + default List selectListByTableId(Long tableId) { + return selectList(new QueryWrapper().eq("table_id", tableId) + .orderByAsc("ordinal_position")); + } + + default void deleteListByTableId(Long tableId) { + delete(new QueryWrapper().eq("table_id", tableId)); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenTableMapper.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenTableMapper.java new file mode 100644 index 0000000000..292941b1d8 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/CodegenTableMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.codegen; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTablePageReqVO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CodegenTableMapper extends BaseMapperX { + + default CodegenTableDO selectByTableName(String tableName) { + return selectOne(new QueryWrapper().eq("table_name", tableName)); + } + + default PageResult selectPage(CodegenTablePageReqVO pageReqVO) { + return selectPage(pageReqVO, new QueryWrapperX() + .likeIfPresent("table_name", pageReqVO.getTableName()) + .likeIfPresent("table_comment", pageReqVO.getTableComment()) + .betweenIfPresent("create_time", pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime())); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapper.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapper.java new file mode 100644 index 0000000000..52bb6ba2c7 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.codegen; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface SchemaColumnMapper extends BaseMapperX { + + default List selectListByTableName(String tableSchema, String tableName) { + return selectList(new QueryWrapper().eq("table_name", tableName) + .eq("table_schema", tableSchema) + .orderByAsc("ordinal_position")); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaTableMapper.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaTableMapper.java new file mode 100644 index 0000000000..51d00c2240 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaTableMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.codegen; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface SchemaTableMapper extends BaseMapperX { + + default List selectList(Collection tableSchemas, String tableName, String tableComment) { + return selectList(new QueryWrapperX().in("table_schema", tableSchemas) + .likeIfPresent("table_name", tableName) + .likeIfPresent("table_comment", tableComment)); + } + + default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) { + return selectOne(new QueryWrapper().eq("table_schema",tableSchema) + .eq("table_name", tableName)); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/test/TestDemoMapper.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/test/TestDemoMapper.java new file mode 100755 index 0000000000..0848057b8b --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/test/TestDemoMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.test; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*; + +/** + * 字典类型 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface TestDemoMapper extends BaseMapperX { + + default PageResult selectPage(TestDemoPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TestDemoDO::getName, reqVO.getName()) + .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TestDemoDO::getType, reqVO.getType()) + .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory()) + .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(TestDemoDO::getId)); + } + + default List selectList(TestDemoExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(TestDemoDO::getName, reqVO.getName()) + .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TestDemoDO::getType, reqVO.getType()) + .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory()) + .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) + .orderByDesc(TestDemoDO::getId)); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnHtmlTypeEnum.java similarity index 83% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnHtmlTypeEnum.java index 22dbdd2b76..c7d968410e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnHtmlTypeEnum.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnHtmlTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums.codegen; +package cn.iocoder.yudao.module.tool.enums.codegen; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ToolCodegenColumnHtmlTypeEnum { +public enum CodegenColumnHtmlTypeEnum { INPUT("input"), // 文本框 TEXTAREA("textarea"), // 文本域 diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnListConditionEnum.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnListConditionEnum.java similarity index 74% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnListConditionEnum.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnListConditionEnum.java index 0783c9869f..4264b9aa59 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenColumnListConditionEnum.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenColumnListConditionEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums.codegen; +package cn.iocoder.yudao.module.tool.enums.codegen; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,7 +8,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ToolCodegenColumnListConditionEnum { +public enum CodegenColumnListConditionEnum { EQ("="), NE("!="), diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenImportTypeEnum.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenImportTypeEnum.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenImportTypeEnum.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenImportTypeEnum.java index 746cb7181d..62c7e99526 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenImportTypeEnum.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenImportTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums.codegen; +package cn.iocoder.yudao.module.tool.enums.codegen; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ToolCodegenImportTypeEnum { +public enum CodegenImportTypeEnum { DB(1), // 从 information_schema 的 table 和 columns 表导入 SQL(2); // 基于建表 SQL 语句导入 diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenSceneEnum.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenSceneEnum.java new file mode 100644 index 0000000000..5b0f59b3b3 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenSceneEnum.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.tool.enums.codegen; + +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static cn.hutool.core.util.ArrayUtil.*; + +/** + * 代码生成的场景枚举 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum CodegenSceneEnum { + + ADMIN(1, "管理后台", "admin", ""), + APP(2, "用户 APP", "app", "App"); + + /** + * 场景 + */ + private final Integer scene; + /** + * 场景名 + */ + private final String name; + /** + * 基础包名 + */ + private final String basePackage; + /** + * Controller 和 VO 类的前缀 + */ + private final String prefixClass; + + public static CodegenSceneEnum valueOf(Integer scene) { + return firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene), values()); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenTemplateTypeEnum.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenTemplateTypeEnum.java similarity index 73% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenTemplateTypeEnum.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenTemplateTypeEnum.java index b192c31734..9f96aaf971 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/enums/codegen/ToolCodegenTemplateTypeEnum.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/codegen/CodegenTemplateTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.tool.enums.codegen; +package cn.iocoder.yudao.module.tool.enums.codegen; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +10,7 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum ToolCodegenTemplateTypeEnum { +public enum CodegenTemplateTypeEnum { CRUD(1), // 单表(增删改查) TREE(2), // 树表(增删改查) diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/package-info.java new file mode 100644 index 0000000000..c2b493d907 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/enums/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.tool.enums; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenConfiguration.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenConfiguration.java similarity index 76% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenConfiguration.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenConfiguration.java index 9f514eed5a..b19add66cd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenConfiguration.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenConfiguration.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config; +package cn.iocoder.yudao.module.tool.framework.codegen.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenProperties.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenProperties.java similarity index 89% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenProperties.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenProperties.java index b0f08460e9..ba113cf5b6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/codegen/config/CodegenProperties.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/config/CodegenProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config; +package cn.iocoder.yudao.module.tool.framework.codegen.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/package-info.java new file mode 100644 index 0000000000..3348d54d51 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/codegen/package-info.java @@ -0,0 +1,4 @@ +/** + * 代码生成器 + */ +package cn.iocoder.yudao.module.tool.framework.codegen; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/package-info.java similarity index 55% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/package-info.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/package-info.java index f9a66d3640..76dbd50012 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/framework/package-info.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.modules.tool.framework; +package cn.iocoder.yudao.module.tool.framework; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/package-info.java new file mode 100644 index 0000000000..4568d4c3d6 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/package-info.java @@ -0,0 +1,8 @@ +/** + * tool 模块下,我们放研发工具,提升研发效率与质量。 + * 例如说:代码生成器、接口文档等等 + * + * 1. Controller URL:以 /tool/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 tool_ 开头,方便在数据库中区分 + */ +package cn.iocoder.yudao.module.tool; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenService.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenService.java similarity index 62% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenService.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenService.java index fbe61c4b16..75327b3315 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenService.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenService.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen; +package cn.iocoder.yudao.module.tool.service.codegen; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTablePageReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenUpdateReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTablePageReqVO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; import java.util.List; import java.util.Map; @@ -15,38 +15,41 @@ import java.util.Map; * * @author 芋道源码 */ -public interface ToolCodegenService { +public interface CodegenService { /** * 基于 SQL 建表语句,创建代码生成器的表定义 * + * @param userId 用户编号 * @param sql SQL 建表语句 * @return 创建的表定义的编号 */ - Long createCodegenListFromSQL(String sql); + Long createCodegenListFromSQL(Long userId, String sql); /** * 基于数据库的表结构,创建代码生成器的表定义 * + * @param userId 用户编号 * @param tableName 表名称 * @return 创建的表定义的编号 */ - Long createCodegen(String tableName); + Long createCodegen(Long userId, String tableName); /** - * 基于 {@link #createCodegen(String)} 的批量创建 + * 基于 {@link #createCodegen(Long, String)} 的批量创建 * + * @param userId 用户编号 * @param tableNames 表名称数组 * @return 创建的表定义的编号数组 */ - List createCodegenListFromDB(List tableNames); + List createCodegenListFromDB(Long userId, List tableNames); /** * 更新数据库的表和字段定义 * * @param updateReqVO 更新信息 */ - void updateCodegen(ToolCodegenUpdateReqVO updateReqVO); + void updateCodegen(CodegenUpdateReqVO updateReqVO); /** * 基于数据库的表结构,同步数据库的表和字段定义 @@ -76,7 +79,7 @@ public interface ToolCodegenService { * @param pageReqVO 分页条件 * @return 表定义分页 */ - PageResult getCodegenTablePage(ToolCodegenTablePageReqVO pageReqVO); + PageResult getCodegenTablePage(CodegenTablePageReqVO pageReqVO); /** * 获得表定义 @@ -84,14 +87,14 @@ public interface ToolCodegenService { * @param id 表编号 * @return 表定义 */ - ToolCodegenTableDO getCodegenTablePage(Long id); + CodegenTableDO getCodegenTablePage(Long id); /** * 获得全部表定义 * * @return 表定义数组 */ - List getCodeGenTableList(); + List getCodeGenTableList(); /** * 获得指定表的字段定义数组 @@ -99,7 +102,7 @@ public interface ToolCodegenService { * @param tableId 表编号 * @return 字段定义数组 */ - List getCodegenColumnListByTableId(Long tableId); + List getCodegenColumnListByTableId(Long tableId); /** * 执行指定表的代码生成 @@ -116,6 +119,6 @@ public interface ToolCodegenService { * @param tableComment 表描述 * @return 表定义列表 */ - List getSchemaTableList(String tableName, String tableComment); + List getSchemaTableList(String tableName, String tableComment); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImpl.java similarity index 58% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImpl.java index ff9cdeafaf..93210f26d2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImpl.java @@ -1,22 +1,25 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl; +package cn.iocoder.yudao.module.tool.service.codegen; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.ToolCodegenUpdateReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.controller.codegen.vo.table.ToolCodegenTablePageReqVO; -import cn.iocoder.yudao.adminserver.modules.tool.convert.codegen.ToolCodegenConvert; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolCodegenColumnMapper; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolCodegenTableMapper; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolSchemaColumnMapper; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.codegen.ToolSchemaTableMapper; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenImportTypeEnum; -import cn.iocoder.yudao.adminserver.modules.tool.service.codegen.ToolCodegenService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.tool.framework.codegen.config.CodegenProperties; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.CodegenUpdateReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.codegen.vo.table.CodegenTablePageReqVO; +import cn.iocoder.yudao.module.tool.convert.codegen.CodegenConvert; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.CodegenColumnMapper; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.CodegenTableMapper; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.SchemaColumnMapper; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.SchemaTableMapper; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenImportTypeEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.tool.service.codegen.inner.CodegenBuilder; +import cn.iocoder.yudao.module.tool.service.codegen.inner.CodegenEngine; +import cn.iocoder.yudao.module.tool.service.codegen.inner.CodegenSQLParser; import org.apache.commons.collections4.KeyValue; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,7 +32,7 @@ import java.util.Set; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.adminserver.modules.tool.enums.ToolErrorCodeConstants.*; +import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.*; /** * 代码生成 Service 实现类 @@ -37,27 +40,30 @@ import static cn.iocoder.yudao.adminserver.modules.tool.enums.ToolErrorCodeConst * @author 芋道源码 */ @Service -public class ToolCodegenServiceImpl implements ToolCodegenService { +public class CodegenServiceImpl implements CodegenService { @Resource - private ToolSchemaTableMapper schemaTableMapper; + private SchemaTableMapper schemaTableMapper; @Resource - private ToolSchemaColumnMapper schemaColumnMapper; + private SchemaColumnMapper schemaColumnMapper; @Resource - private ToolCodegenTableMapper codegenTableMapper; + private CodegenTableMapper codegenTableMapper; @Resource - private ToolCodegenColumnMapper codegenColumnMapper; + private CodegenColumnMapper codegenColumnMapper; @Resource - private ToolCodegenBuilder codegenBuilder; + private AdminUserApi userApi; + @Resource - private ToolCodegenEngine codegenEngine; + private CodegenBuilder codegenBuilder; + @Resource + private CodegenEngine codegenEngine; @Resource private CodegenProperties codegenProperties; - private Long createCodegen0(ToolCodegenImportTypeEnum importType, - ToolSchemaTableDO schemaTable, List schemaColumns) { + private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, + SchemaTableDO schemaTable, List schemaColumns) { // 校验导入的表和字段非空 if (schemaTable == null) { throw exception(CODEGEN_IMPORT_TABLE_NULL); @@ -70,12 +76,13 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { throw exception(CODEGEN_TABLE_EXISTS); } - // 构建 ToolCodegenTableDO 对象,插入到 DB 中 - ToolCodegenTableDO table = codegenBuilder.buildTable(schemaTable); + // 构建 CodegenTableDO 对象,插入到 DB 中 + CodegenTableDO table = codegenBuilder.buildTable(schemaTable); table.setImportType(importType.getType()); + table.setAuthor(userApi.getUser(userId).getNickname()); codegenTableMapper.insert(table); - // 构建 ToolCodegenColumnDO 数组,插入到 DB 中 - List columns = codegenBuilder.buildColumns(schemaColumns); + // 构建 CodegenColumnDO 数组,插入到 DB 中 + List columns = codegenBuilder.buildColumns(schemaColumns); columns.forEach(column -> { column.setTableId(table.getId()); codegenColumnMapper.insert(column); // TODO 批量插入 @@ -84,54 +91,54 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - public Long createCodegenListFromSQL(String sql) { + public Long createCodegenListFromSQL(Long userId, String sql) { // 从 SQL 中,获得数据库表结构 - ToolSchemaTableDO schemaTable; - List schemaColumns; + SchemaTableDO schemaTable; + List schemaColumns; try { - KeyValue> result = ToolCodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaTable = result.getKey(); schemaColumns = result.getValue(); } catch (Exception ex) { throw exception(CODEGEN_PARSE_SQL_ERROR); } // 导入 - return this.createCodegen0(ToolCodegenImportTypeEnum.SQL, schemaTable, schemaColumns); + return this.createCodegen0(userId, CodegenImportTypeEnum.SQL, schemaTable, schemaColumns); } @Override - public Long createCodegen(String tableName) { + public Long createCodegen(Long userId, String tableName) { // 获取当前schema String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - ToolSchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName); - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); + SchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName); + List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); // 导入 - return this.createCodegen0(ToolCodegenImportTypeEnum.DB, schemaTable, schemaColumns); + return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns); } @Override @Transactional(rollbackFor = Exception.class) - public List createCodegenListFromDB(List tableNames) { + public List createCodegenListFromDB(Long userId, List tableNames) { List ids = new ArrayList<>(tableNames.size()); // 遍历添加。虽然效率会低一点,但是没必要做成完全批量,因为不会这么大量 - tableNames.forEach(tableName -> ids.add(createCodegen(tableName))); + tableNames.forEach(tableName -> ids.add(createCodegen(userId, tableName))); return ids; } @Override @Transactional(rollbackFor = Exception.class) - public void updateCodegen(ToolCodegenUpdateReqVO updateReqVO) { + public void updateCodegen(CodegenUpdateReqVO updateReqVO) { // 校验是否已经存在 if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } // 更新 table 表定义 - ToolCodegenTableDO updateTableObj = ToolCodegenConvert.INSTANCE.convert(updateReqVO.getTable()); + CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable()); codegenTableMapper.updateById(updateTableObj); // 更新 column 字段定义 - List updateColumnObjs = ToolCodegenConvert.INSTANCE.convertList03(updateReqVO.getColumns()); + List updateColumnObjs = CodegenConvert.INSTANCE.convertList03(updateReqVO.getColumns()); updateColumnObjs.forEach(updateColumnObj -> codegenColumnMapper.updateById(updateColumnObj)); } @@ -139,13 +146,13 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { @Transactional(rollbackFor = Exception.class) public void syncCodegenFromDB(Long tableId) { // 校验是否已经存在 - ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); + CodegenTableDO table = codegenTableMapper.selectById(tableId); if (table == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName()); + List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName()); // 执行同步 this.syncCodegen0(tableId, schemaColumns); @@ -155,14 +162,14 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { @Transactional(rollbackFor = Exception.class) public void syncCodegenFromSQL(Long tableId, String sql) { // 校验是否已经存在 - ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); + CodegenTableDO table = codegenTableMapper.selectById(tableId); if (table == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } // 从 SQL 中,获得数据库表结构 - List schemaColumns; + List schemaColumns; try { - KeyValue> result = ToolCodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaColumns = result.getValue(); } catch (Exception ex) { throw exception(CODEGEN_PARSE_SQL_ERROR); @@ -172,27 +179,27 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { this.syncCodegen0(tableId, schemaColumns); } - private void syncCodegen0(Long tableId, List schemaColumns) { + private void syncCodegen0(Long tableId, List schemaColumns) { // 校验导入的字段不为空 if (CollUtil.isEmpty(schemaColumns)) { throw exception(CODEGEN_SYNC_COLUMNS_NULL); } - Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, ToolSchemaColumnDO::getColumnName); + Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName); - // 构建 ToolCodegenColumnDO 数组,只同步新增的字段 - List codegenColumns = codegenColumnMapper.selectListByTableId(tableId); - Set codegenColumnNames = CollectionUtils.convertSet(codegenColumns, ToolCodegenColumnDO::getColumnName); + // 构建 CodegenColumnDO 数组,只同步新增的字段 + List codegenColumns = codegenColumnMapper.selectListByTableId(tableId); + Set codegenColumnNames = CollectionUtils.convertSet(codegenColumns, CodegenColumnDO::getColumnName); // 移除已经存在的字段 schemaColumns.removeIf(column -> codegenColumnNames.contains(column.getColumnName())); // 计算需要删除的字段 Set deleteColumnIds = codegenColumns.stream().filter(column -> !schemaColumnNames.contains(column.getColumnName())) - .map(ToolCodegenColumnDO::getId).collect(Collectors.toSet()); + .map(CodegenColumnDO::getId).collect(Collectors.toSet()); if (CollUtil.isEmpty(schemaColumns) && CollUtil.isEmpty(deleteColumnIds)) { throw exception(CODEGEN_SYNC_NONE_CHANGE); } // 插入新增的字段 - List columns = codegenBuilder.buildColumns(schemaColumns); + List columns = codegenBuilder.buildColumns(schemaColumns); columns.forEach(column -> { column.setTableId(tableId); codegenColumnMapper.insert(column); // TODO 批量插入 @@ -218,33 +225,33 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - public PageResult getCodegenTablePage(ToolCodegenTablePageReqVO pageReqVO) { + public PageResult getCodegenTablePage(CodegenTablePageReqVO pageReqVO) { return codegenTableMapper.selectPage(pageReqVO); } @Override - public ToolCodegenTableDO getCodegenTablePage(Long id) { + public CodegenTableDO getCodegenTablePage(Long id) { return codegenTableMapper.selectById(id); } @Override - public List getCodeGenTableList() { + public List getCodeGenTableList() { return codegenTableMapper.selectList(); } @Override - public List getCodegenColumnListByTableId(Long tableId) { + public List getCodegenColumnListByTableId(Long tableId) { return codegenColumnMapper.selectListByTableId(tableId); } @Override public Map generationCodes(Long tableId) { // 校验是否已经存在 - ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); + CodegenTableDO table = codegenTableMapper.selectById(tableId); if (codegenTableMapper.selectById(tableId) == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } - List columns = codegenColumnMapper.selectListByTableId(tableId); + List columns = codegenColumnMapper.selectListByTableId(tableId); if (CollUtil.isEmpty(columns)) { throw exception(CODEGEN_COLUMN_NOT_EXISTS); } @@ -254,8 +261,8 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - public List getSchemaTableList(String tableName, String tableComment) { - List tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment); + public List getSchemaTableList(String tableName, String tableComment) { + List tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment); // TODO 强制移除 Quartz 的表,未来做成可配置 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); tables.removeIf(table -> table.getTableName().startsWith("ACT_")); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenBuilder.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenBuilder.java similarity index 57% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenBuilder.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenBuilder.java index 87e6ab6bd0..4914b3d229 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenBuilder.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenBuilder.java @@ -1,16 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl; +package cn.iocoder.yudao.module.tool.service.codegen.inner; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.adminserver.modules.tool.convert.codegen.ToolCodegenConvert; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum; -import cn.iocoder.yudao.adminserver.modules.tool.enums.codegen.ToolCodegenTemplateTypeEnum; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.tool.convert.codegen.CodegenConvert; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenColumnHtmlTypeEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenColumnListConditionEnum; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenTemplateTypeEnum; import com.google.common.collect.Sets; import org.springframework.stereotype.Component; @@ -21,53 +22,45 @@ import static cn.hutool.core.text.CharSequenceUtil.*; /** * 代码生成器的 Builder,负责: - * 1. 将数据库的表 {@link ToolSchemaTableDO} 定义,构建成 {@link ToolCodegenTableDO} - * 2. 将数据库的列 {@link ToolSchemaColumnDO} 构定义,建成 {@link ToolCodegenColumnDO} + * 1. 将数据库的表 {@link SchemaTableDO} 定义,构建成 {@link CodegenTableDO} + * 2. 将数据库的列 {@link SchemaColumnDO} 构定义,建成 {@link CodegenColumnDO} */ @Component -public class ToolCodegenBuilder { +public class CodegenBuilder { /** - * Module 名字的映射 TODO 后续梳理到配置类 - * - * key:模块的完整名 - * value:模块的缩写名 - */ - private static final Map moduleNames = MapUtil.builder() - .put("system", "sys") - .put("infra", "inf") - .put("tool", "tool") - .build(); - - /** - * 字段名与 {@link ToolCodegenColumnListConditionEnum} 的默认映射 + * 字段名与 {@link CodegenColumnListConditionEnum} 的默认映射 * 注意,字段的匹配以后缀的方式 */ - private static final Map columnListOperationConditionMappings = - MapUtil.builder() - .put("name", ToolCodegenColumnListConditionEnum.LIKE) - .put("time", ToolCodegenColumnListConditionEnum.BETWEEN) - .put("date", ToolCodegenColumnListConditionEnum.BETWEEN) + private static final Map columnListOperationConditionMappings = + MapUtil.builder() + .put("name", CodegenColumnListConditionEnum.LIKE) + .put("time", CodegenColumnListConditionEnum.BETWEEN) + .put("date", CodegenColumnListConditionEnum.BETWEEN) .build(); /** - * 字段名与 {@link ToolCodegenColumnHtmlTypeEnum} 的默认映射 + * 字段名与 {@link CodegenColumnHtmlTypeEnum} 的默认映射 * 注意,字段的匹配以后缀的方式 */ - private static final Map columnHtmlTypeMappings = - MapUtil.builder() - .put("status", ToolCodegenColumnHtmlTypeEnum.RADIO) - .put("sex", ToolCodegenColumnHtmlTypeEnum.RADIO) - .put("type", ToolCodegenColumnHtmlTypeEnum.SELECT) - .put("image", ToolCodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) - .put("file", ToolCodegenColumnHtmlTypeEnum.UPLOAD_FILE) - .put("content", ToolCodegenColumnHtmlTypeEnum.EDITOR) - .put("time", ToolCodegenColumnHtmlTypeEnum.DATETIME) - .put("date", ToolCodegenColumnHtmlTypeEnum.DATETIME) + private static final Map columnHtmlTypeMappings = + MapUtil.builder() + .put("status", CodegenColumnHtmlTypeEnum.RADIO) + .put("sex", CodegenColumnHtmlTypeEnum.RADIO) + .put("type", CodegenColumnHtmlTypeEnum.SELECT) + .put("image", CodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) + .put("file", CodegenColumnHtmlTypeEnum.UPLOAD_FILE) + .put("content", CodegenColumnHtmlTypeEnum.EDITOR) + .put("time", CodegenColumnHtmlTypeEnum.DATETIME) + .put("date", CodegenColumnHtmlTypeEnum.DATETIME) .build(); /** - * {@link BaseDO} 的字段 + * 多租户编号的字段名 + */ + public static final String TENANT_ID_FIELD = "tenant_id"; + /** + * {@link TenantBaseDO} 的字段 */ public static final Set BASE_DO_FIELDS = new HashSet<>(); /** @@ -103,7 +96,7 @@ public class ToolCodegenBuilder { .build(); static { - Arrays.stream(BaseDO.class.getDeclaredFields()).forEach(field -> BASE_DO_FIELDS.add(field.getName())); + Arrays.stream(ReflectUtil.getFields(TenantBaseDO.class)).forEach(field -> BASE_DO_FIELDS.add(field.getName())); // 处理 OPERATION 相关的字段 CREATE_OPERATION_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS); UPDATE_OPERATION_EXCLUDE_COLUMN.addAll(BASE_DO_FIELDS); @@ -113,8 +106,8 @@ public class ToolCodegenBuilder { LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的 } - public ToolCodegenTableDO buildTable(ToolSchemaTableDO schemaTable) { - ToolCodegenTableDO table = ToolCodegenConvert.INSTANCE.convert(schemaTable); + public CodegenTableDO buildTable(SchemaTableDO schemaTable) { + CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); initTableDefault(table); return table; } @@ -124,20 +117,22 @@ public class ToolCodegenBuilder { * * @param table 表定义 */ - private void initTableDefault(ToolCodegenTableDO table) { - table.setModuleName(getFullModuleName(StrUtil.subBefore(table.getTableName(), - '_', false))); // 第一个 _ 前缀的前面,作为 module 名字 + private void initTableDefault(CodegenTableDO table) { + // 以 system_dept 举例子。moduleName 为 system、businessName 为 dept、className 为 SystemDept + // 如果不希望 System 前缀,则可以手动在【代码生成 - 修改生成配置 - 基本信息】,将实体类名称改为 Dept 即可 + table.setModuleName(StrUtil.subBefore(table.getTableName(), + '_', false)); // 第一个 _ 前缀的前面,作为 module 名字 table.setBusinessName(toCamelCase(subAfter(table.getTableName(), '_', false))); // 第一步,第一个 _ 前缀的后面,作为 module 名字; 第二步,可能存在多个 _ 的情况,转换成驼峰 table.setClassName(upperFirst(toCamelCase(table.getTableName()))); // 驼峰 + 首字母大写 table.setClassComment(subBefore(table.getTableComment(), // 去除结尾的表,作为类描述 '表', true)); table.setAuthor("芋艿"); // TODO 稍后改成创建人 - table.setTemplateType(ToolCodegenTemplateTypeEnum.CRUD.getType()); + table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); } - public List buildColumns(List schemaColumns) { - List columns = ToolCodegenConvert.INSTANCE.convertList(schemaColumns); + public List buildColumns(List schemaColumns) { + List columns = CodegenConvert.INSTANCE.convertList(schemaColumns); columns.forEach(this::initColumnDefault); return columns; } @@ -147,7 +142,7 @@ public class ToolCodegenBuilder { * * @param column 列定义 */ - private void initColumnDefault(ToolCodegenColumnDO column) { + private void initColumnDefault(CodegenColumnDO column) { // 处理 Java 相关的字段的默认值 processColumnJava(column); // 处理 CRUD 相关的字段的默认值 @@ -156,7 +151,7 @@ public class ToolCodegenBuilder { processColumnUI(column); } - private void processColumnJava(ToolCodegenColumnDO column) { + private void processColumnJava(CodegenColumnDO column) { // 处理 javaField 字段 column.setJavaField(toCamelCase(column.getColumnName())); // 处理 dictType 字段,暂无 @@ -171,7 +166,7 @@ public class ToolCodegenBuilder { } } - private void processColumnOperation(ToolCodegenColumnDO column) { + private void processColumnOperation(CodegenColumnDO column) { // 处理 createOperation 字段 column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField()) && !column.getPrimaryKey()); // 对于主键,创建时无需传递 @@ -186,13 +181,13 @@ public class ToolCodegenBuilder { .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); if (column.getListOperationCondition() == null) { - column.setListOperationCondition(ToolCodegenColumnListConditionEnum.EQ.getCondition()); + column.setListOperationCondition(CodegenColumnListConditionEnum.EQ.getCondition()); } // 处理 listOperationResult 字段 column.setListOperationResult(!LIST_OPERATION_RESULT_EXCLUDE_COLUMN.contains(column.getJavaField())); } - private void processColumnUI(ToolCodegenColumnDO column) { + private void processColumnUI(CodegenColumnDO column) { // 基于后缀进行匹配 columnHtmlTypeMappings.entrySet().stream() .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) @@ -200,35 +195,12 @@ public class ToolCodegenBuilder { // 如果是 Boolean 类型时,设置为 radio 类型. // 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型. if (Boolean.class.getSimpleName().equals(column.getJavaType())) { - column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.RADIO.getType()); + column.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType()); } // 兜底,设置默认为 input 类型 if (column.getHtmlType() == null) { - column.setHtmlType(ToolCodegenColumnHtmlTypeEnum.INPUT.getType()); + column.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType()); } } - /** - * 获得模块的缩略名 - * - * @param fullModuleName 模块的完整名 - * @return 缩略名 - */ - public String getSimpleModuleName(String fullModuleName) { - return moduleNames.getOrDefault(fullModuleName, fullModuleName); - } - - /** - * 获得模块的完整名 - * - * @param shortModuleName 模块的缩略名 - * @return 完整名 - */ - public String getFullModuleName(String shortModuleName) { - return moduleNames.entrySet().stream() - .filter(entry -> entry.getValue().equals(shortModuleName)) // 匹配 - .findFirst().map(Map.Entry::getKey) // 返回 key - .orElse(shortModuleName); // 兜底返回 shortModuleName - } - } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java similarity index 56% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java index f7a1e4c9be..d1c3304752 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java @@ -1,6 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl; +package cn.iocoder.yudao.module.tool.service.codegen.inner; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateEngine; @@ -9,7 +11,10 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; +import cn.iocoder.yudao.module.tool.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.tool.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -19,8 +24,8 @@ import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import com.google.common.collect.Maps; @@ -45,7 +50,7 @@ import static cn.hutool.core.text.CharSequenceUtil.*; * @author 芋道源码 */ @Component -public class ToolCodegenEngine { +public class CodegenEngine { /** * 模板配置 @@ -53,38 +58,30 @@ public class ToolCodegenEngine { * value:生成的路径 */ private static final Map TEMPLATES = MapUtil.builder(new LinkedHashMap<>()) // 有序 - // Java Main - .put(javaTemplatePath("controller/vo/baseVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}BaseVO")) - .put(javaTemplatePath("controller/vo/createReqVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}CreateReqVO")) - .put(javaTemplatePath("controller/vo/pageReqVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}PageReqVO")) - .put(javaTemplatePath("controller/vo/respVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}RespVO")) - .put(javaTemplatePath("controller/vo/updateReqVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}UpdateReqVO")) - .put(javaTemplatePath("controller/vo/exportReqVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}ExportReqVO")) - .put(javaTemplatePath("controller/vo/excelVO"), - javaFilePath("controller/${table.businessName}/vo/${table.className}ExcelVO")) - .put(javaTemplatePath("controller/controller"), - javaFilePath("controller/${table.businessName}/${table.className}Controller")) + // Java module-impl Main + .put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO")) + .put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO")) + .put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO")) + .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO")) + .put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO")) + .put(javaTemplatePath("controller/vo/exportReqVO"), javaModuleImplVOFilePath("ExportReqVO")) + .put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO")) + .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) .put(javaTemplatePath("convert/convert"), - javaFilePath("convert/${table.businessName}/${table.className}Convert")) + javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert")) .put(javaTemplatePath("dal/do"), - javaFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) + javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) .put(javaTemplatePath("dal/mapper"), - javaFilePath("dal/mysql/${table.businessName}/${table.className}Mapper")) - .put(javaTemplatePath("enums/errorcode"), - javaFilePath("enums/${simpleModuleName_upperFirst}ErrorCodeConstants")) + javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}Mapper")) .put(javaTemplatePath("service/serviceImpl"), - javaFilePath("service/${table.businessName}/impl/${table.className}ServiceImpl")) + javaModuleImplMainFilePath("service/${table.businessName}/${table.className}ServiceImpl")) .put(javaTemplatePath("service/service"), - javaFilePath("service/${table.businessName}/${table.className}Service")) - // Java Test + javaModuleImplMainFilePath("service/${table.businessName}/${table.className}Service")) + // Java module-impl Test .put(javaTemplatePath("test/serviceTest"), - javaFilePath("service/${table.businessName}/${table.className}ServiceTest")) + javaModuleImplTestFilePath("service/${table.businessName}/${table.className}ServiceImplTest")) + // Java module-api Main + .put(javaTemplatePath("enums/errorcode"), javaModuleApiMainFilePath("enums/ErrorCodeConstants_手动操作")) // Vue .put(vueTemplatePath("views/index.vue"), vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue")) @@ -92,11 +89,9 @@ public class ToolCodegenEngine { vueFilePath("api/${table.moduleName}/${classNameVar}.js")) // SQL .put("codegen/sql/sql.vm", "sql/sql.sql") + .put("codegen/sql/h2.vm", "sql/h2.sql") .build(); - @Resource - private ToolCodegenBuilder codegenBuilder; - @Resource private CodegenProperties codegenProperties; @@ -109,7 +104,7 @@ public class ToolCodegenEngine { */ private final Map globalBindingMap = new HashMap<>(); - public ToolCodegenEngine() { + public CodegenEngine() { // 初始化 TemplateEngine 属性 TemplateConfig config = new TemplateConfig(); config.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH); @@ -120,8 +115,7 @@ public class ToolCodegenEngine { private void initGlobalBindingMap() { // 全局配置 globalBindingMap.put("basePackage", codegenProperties.getBasePackage()); - globalBindingMap.put("baseFrameworkPackage", StrUtil.subBefore(codegenProperties.getBasePackage(), - '.', true) + '.' + "framework"); + globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage() + '.' + "framework"); // 用于后续获取测试类的 package 地址 // 全局 Java Bean globalBindingMap.put("CommonResultClassName", CommonResult.class.getName()); globalBindingMap.put("PageResultClassName", PageResult.class.getName()); @@ -129,9 +123,8 @@ public class ToolCodegenEngine { globalBindingMap.put("PageParamClassName", PageParam.class.getName()); globalBindingMap.put("DictFormatClassName", DictFormat.class.getName()); // DO 类,独有字段 - globalBindingMap.put("baseDOFields", ToolCodegenBuilder.BASE_DO_FIELDS); - globalBindingMap.put("BaseDOClassName", BaseDO.class.getName()); - globalBindingMap.put("QueryWrapperClassName", QueryWrapperX.class.getName()); + globalBindingMap.put("baseDOFields", CodegenBuilder.BASE_DO_FIELDS); + globalBindingMap.put("QueryWrapperClassName", LambdaQueryWrapperX.class.getName()); globalBindingMap.put("BaseMapperClassName", BaseMapperX.class.getName()); // Util 工具类 globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName()); @@ -143,27 +136,35 @@ public class ToolCodegenEngine { globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName()); } - public Map execute(ToolCodegenTableDO table, List columns) { + public Map execute(CodegenTableDO table, List columns) { // 创建 bindingMap Map bindingMap = new HashMap<>(globalBindingMap); bindingMap.put("table", table); bindingMap.put("columns", columns); - bindingMap.put("primaryColumn", CollectionUtils.findFirst(columns, ToolCodegenColumnDO::getPrimaryKey)); // 主键字段 - // moduleName 相关 - String simpleModuleName = codegenBuilder.getSimpleModuleName(table.getModuleName()); - bindingMap.put("simpleModuleName", simpleModuleName); // 将 system 转成 sys - bindingMap.put("simpleModuleName_upperFirst", upperFirst(simpleModuleName)); // 将 sys 转成 Sys + bindingMap.put("primaryColumn", CollectionUtils.findFirst(columns, CodegenColumnDO::getPrimaryKey)); // 主键字段 + bindingMap.put("sceneEnum", CodegenSceneEnum.valueOf(table.getScene())); + // className 相关 - // 去掉指定前缀 将 TestDictType 转换成 DictType. 因为在 create 等方法后,不需要带上 Test 前缀 - String simpleClassName = removePrefix(table.getClassName(), upperFirst(simpleModuleName)); + // 去掉指定前缀,将 TestDictType 转换成 DictType. 因为在 create 等方法后,不需要带上 Test 前缀 + String simpleClassName = removePrefix(table.getClassName(), upperFirst(table.getModuleName())); bindingMap.put("simpleClassName", simpleClassName); bindingMap.put("simpleClassName_underlineCase", toUnderlineCase(simpleClassName)); // 将 DictType 转换成 dict_type bindingMap.put("classNameVar", lowerFirst(simpleClassName)); // 将 DictType 转换成 dictType,用于变量 - String simpleClassNameStrikeCase = toSymbolCase(simpleClassName, '-'); // 将 DictType 转换成 dict-type + // 将 DictType 转换成 dict-type + String simpleClassNameStrikeCase = toSymbolCase(simpleClassName, '-'); bindingMap.put("simpleClassName_strikeCase", simpleClassNameStrikeCase); // permission 前缀 bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase); + // 如果多租户,则进行覆盖 DB 独有字段 + if (CollectionUtils.findFirst(columns, column -> column.getColumnName().equals(CodegenBuilder.TENANT_ID_FIELD)) != null) { + bindingMap.put("BaseDOClassName", TenantBaseDO.class.getName()); + bindingMap.put("BaseDOClassName_simple", TenantBaseDO.class.getSimpleName()); + } else { + bindingMap.put("BaseDOClassName", BaseDO.class.getName()); + bindingMap.put("BaseDOClassName_simple", BaseDO.class.getSimpleName()); + } + // 执行生成 final Map result = Maps.newLinkedHashMapWithExpectedSize(TEMPLATES.size()); // 有序 TEMPLATES.forEach((vmPath, filePath) -> { @@ -177,13 +178,14 @@ public class ToolCodegenEngine { private String formatFilePath(String filePath, Map bindingMap) { filePath = StrUtil.replace(filePath, "${basePackage}", getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); - filePath = StrUtil.replace(filePath, "${simpleModuleName_upperFirst}", - getStr(bindingMap, "simpleModuleName_upperFirst")); filePath = StrUtil.replace(filePath, "${classNameVar}", getStr(bindingMap, "classNameVar")); - + // sceneEnum 包含的字段 + CodegenSceneEnum sceneEnum = (CodegenSceneEnum) bindingMap.get("sceneEnum"); + filePath = StrUtil.replace(filePath, "${sceneEnum.prefixClass}", sceneEnum.getPrefixClass()); + filePath = StrUtil.replace(filePath, "${sceneEnum.basePackage}", sceneEnum.getBasePackage()); // table 包含的字段 - ToolCodegenTableDO table = (ToolCodegenTableDO) bindingMap.get("table"); + CodegenTableDO table = (CodegenTableDO) bindingMap.get("table"); filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName()); filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName()); filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName()); @@ -194,8 +196,32 @@ public class ToolCodegenEngine { return "codegen/java/" + path + ".vm"; } - private static String javaFilePath(String path) { - return "java/${basePackage}/modules/${table.moduleName}/" + path + ".java"; + private static String javaModuleImplVOFilePath(String path) { + return javaModuleFilePath("controller/${sceneEnum.basePackage}/${table.businessName}/" + + "vo/${sceneEnum.prefixClass}${table.className}" + path, "impl", "main"); + } + + private static String javaModuleImplControllerFilePath() { + return javaModuleFilePath("controller/${sceneEnum.basePackage}/${table.businessName}/" + + "${sceneEnum.prefixClass}${table.className}Controller", "impl", "main"); + } + + private static String javaModuleImplMainFilePath(String path) { + return javaModuleFilePath(path, "impl", "main"); + } + + private static String javaModuleApiMainFilePath(String path) { + return javaModuleFilePath(path, "api", "main"); + } + + private static String javaModuleImplTestFilePath(String path) { + return javaModuleFilePath(path, "impl", "test"); + } + + private static String javaModuleFilePath(String path, String module, String src) { + return "yudao-module-${table.moduleName}/" + // 顶级模块 + "yudao-module-${table.moduleName}-" + module + "/" + // 子模块 + "src/" + src + "/java/${basePackage}/module/${table.moduleName}/" + path + ".java"; } private static String vueTemplatePath(String path) { @@ -203,7 +229,8 @@ public class ToolCodegenEngine { } private static String vueFilePath(String path) { - return "vue/" + path; + return "yudao-ui-${sceneEnum.basePackage}/" + // 顶级目录 + "src/" + path; } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenSQLParser.java similarity index 72% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenSQLParser.java index d9f2538812..d58ac04c47 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenSQLParser.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl; +package cn.iocoder.yudao.module.tool.service.codegen.inner; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaTableDO; import com.alibaba.druid.DbType; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -21,26 +21,26 @@ import java.util.Objects; import static com.alibaba.druid.sql.SQLUtils.normalize; /** - * SQL 解析器,将创建表的 SQL,解析成 {@link ToolSchemaTableDO} 和 {@link ToolSchemaColumnDO} 对象, + * SQL 解析器,将创建表的 SQL,解析成 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象, * 后续可以基于它们,生成代码~ * * @author 芋道源码 */ -public class ToolCodegenSQLParser { +public class CodegenSQLParser { /** - * 解析建表 SQL 语句,返回 {@link ToolSchemaTableDO} 和 {@link ToolSchemaColumnDO} 对象 + * 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象 * * @param sql 建表 SQL 语句 * @return 解析结果 */ - public static KeyValue> parse(String sql) { + public static KeyValue> parse(String sql) { // 解析 SQL 成 Statement SQLCreateTableStatement statement = parseCreateSQL(sql); // 解析 Table 表 - ToolSchemaTableDO table = parseTable(statement); + SchemaTableDO table = parseTable(statement); // 解析 Column 字段 - List columns = parseColumns(statement); + List columns = parseColumns(statement); columns.forEach(column -> column.setTableName(table.getTableName())); // 返回 return new DefaultKeyValue<>(table, columns); @@ -61,8 +61,8 @@ public class ToolCodegenSQLParser { return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement(); } - private static ToolSchemaTableDO parseTable(SQLCreateTableStatement statement) { - return ToolSchemaTableDO.builder() + private static SchemaTableDO parseTable(SQLCreateTableStatement statement) { + return SchemaTableDO.builder() .tableName(statement.getTableSource().getTableName(true)) .tableComment(getCommentText(statement)) .build(); @@ -75,13 +75,13 @@ public class ToolCodegenSQLParser { return ((SQLCharExpr) statement.getComment()).getText(); } - private static List parseColumns(SQLCreateTableStatement statement) { - List columns = new ArrayList<>(); + private static List parseColumns(SQLCreateTableStatement statement) { + List columns = new ArrayList<>(); statement.getTableElementList().forEach(element -> parseColumn(columns, element)); return columns; } - private static void parseColumn(List columns, SQLTableElement element) { + private static void parseColumn(List columns, SQLTableElement element) { // 处理主键 if (element instanceof SQLPrimaryKey) { parsePrimaryKey(columns, (SQLPrimaryKey) element); @@ -93,16 +93,16 @@ public class ToolCodegenSQLParser { } } - private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { + private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键 // 匹配 columns 主键字段,设置为 primary columns.stream().filter(column -> column.getColumnName().equals(columnName)) .forEach(column -> column.setPrimaryKey(true)); } - private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { + private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { String text = definition.toString().toUpperCase(); - columns.add(ToolSchemaColumnDO.builder() + columns.add(SchemaColumnDO.builder() .columnName(normalize(definition.getColumnName())) .columnType(definition.getDataType().toString()) .columnComment(Objects.isNull(definition.getComment()) ? "" diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/ToolTestDemoService.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoService.java old mode 100644 new mode 100755 similarity index 58% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/ToolTestDemoService.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoService.java index 7fff9185d4..017aaa9240 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/ToolTestDemoService.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoService.java @@ -1,17 +1,17 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.test; +package cn.iocoder.yudao.module.tool.service.test; import java.util.*; import javax.validation.*; -import cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo.*; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test.ToolTestDemoDO; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; /** * 字典类型 Service 接口 * - * @author 芋艿 + * @author 芋道源码 */ -public interface ToolTestDemoService { +public interface TestDemoService { /** * 创建字典类型 @@ -19,14 +19,14 @@ public interface ToolTestDemoService { * @param createReqVO 创建信息 * @return 编号 */ - Long createTestDemo(@Valid ToolTestDemoCreateReqVO createReqVO); + Long createTestDemo(@Valid TestDemoCreateReqVO createReqVO); /** * 更新字典类型 * * @param updateReqVO 更新信息 */ - void updateTestDemo(@Valid ToolTestDemoUpdateReqVO updateReqVO); + void updateTestDemo(@Valid TestDemoUpdateReqVO updateReqVO); /** * 删除字典类型 @@ -41,7 +41,7 @@ public interface ToolTestDemoService { * @param id 编号 * @return 字典类型 */ - ToolTestDemoDO getTestDemo(Long id); + TestDemoDO getTestDemo(Long id); /** * 获得字典类型列表 @@ -49,7 +49,7 @@ public interface ToolTestDemoService { * @param ids 编号 * @return 字典类型列表 */ - List getTestDemoList(Collection ids); + List getTestDemoList(Collection ids); /** * 获得字典类型分页 @@ -57,7 +57,7 @@ public interface ToolTestDemoService { * @param pageReqVO 分页查询 * @return 字典类型分页 */ - PageResult getTestDemoPage(ToolTestDemoPageReqVO pageReqVO); + PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO); /** * 获得字典类型列表, 用于 Excel 导出 @@ -65,6 +65,6 @@ public interface ToolTestDemoService { * @param exportReqVO 查询条件 * @return 字典类型列表 */ - List getTestDemoList(ToolTestDemoExportReqVO exportReqVO); + List getTestDemoList(TestDemoExportReqVO exportReqVO); } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/impl/ToolTestDemoServiceImpl.java b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImpl.java old mode 100644 new mode 100755 similarity index 50% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/impl/ToolTestDemoServiceImpl.java rename to yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImpl.java index ad8fd1e81e..dcd8e97dbd --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/test/impl/ToolTestDemoServiceImpl.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImpl.java @@ -1,48 +1,47 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.test.impl; +package cn.iocoder.yudao.module.tool.service.test; import org.springframework.stereotype.Service; import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; import java.util.*; -import cn.iocoder.yudao.adminserver.modules.tool.controller.test.vo.*; -import cn.iocoder.yudao.adminserver.modules.tool.dal.dataobject.test.ToolTestDemoDO; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.adminserver.modules.tool.convert.test.ToolTestDemoConvert; -import cn.iocoder.yudao.adminserver.modules.tool.dal.mysql.test.ToolTestDemoMapper; -import cn.iocoder.yudao.adminserver.modules.tool.service.test.ToolTestDemoService; +import cn.iocoder.yudao.module.tool.convert.test.TestDemoConvert; +import cn.iocoder.yudao.module.tool.dal.mysql.test.TestDemoMapper; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.adminserver.modules.tool.enums.ToolErrorCodeConstants.*; +import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.*; /** * 字典类型 Service 实现类 * - * @author 芋艿 + * @author 芋道源码 */ @Service @Validated -public class ToolTestDemoServiceImpl implements ToolTestDemoService { +public class TestDemoServiceImpl implements TestDemoService { @Resource - private ToolTestDemoMapper testDemoMapper; + private TestDemoMapper testDemoMapper; @Override - public Long createTestDemo(ToolTestDemoCreateReqVO createReqVO) { + public Long createTestDemo(TestDemoCreateReqVO createReqVO) { // 插入 - ToolTestDemoDO testDemo = ToolTestDemoConvert.INSTANCE.convert(createReqVO); + TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO); testDemoMapper.insert(testDemo); // 返回 return testDemo.getId(); } @Override - public void updateTestDemo(ToolTestDemoUpdateReqVO updateReqVO) { + public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) { // 校验存在 this.validateTestDemoExists(updateReqVO.getId()); // 更新 - ToolTestDemoDO updateObj = ToolTestDemoConvert.INSTANCE.convert(updateReqVO); + TestDemoDO updateObj = TestDemoConvert.INSTANCE.convert(updateReqVO); testDemoMapper.updateById(updateObj); } @@ -61,22 +60,22 @@ public class ToolTestDemoServiceImpl implements ToolTestDemoService { } @Override - public ToolTestDemoDO getTestDemo(Long id) { + public TestDemoDO getTestDemo(Long id) { return testDemoMapper.selectById(id); } @Override - public List getTestDemoList(Collection ids) { + public List getTestDemoList(Collection ids) { return testDemoMapper.selectBatchIds(ids); } @Override - public PageResult getTestDemoPage(ToolTestDemoPageReqVO pageReqVO) { + public PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO) { return testDemoMapper.selectPage(pageReqVO); } @Override - public List getTestDemoList(ToolTestDemoExportReqVO exportReqVO) { + public List getTestDemoList(TestDemoExportReqVO exportReqVO) { return testDemoMapper.selectList(exportReqVO); } diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/controller.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/controller.vm similarity index 57% rename from yudao-admin-server/src/main/resources/codegen/java/controller/controller.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/controller.vm index 6038d39373..ba0780421c 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/controller.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/controller.vm @@ -1,9 +1,9 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; -import org.springframework.security.access.prepost.PreAuthorize; +#if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end import io.swagger.annotations.*; @@ -22,32 +22,32 @@ import ${ExcelUtilsClassName}; import ${OperateLogClassName}; import static ${OperateTypeEnumClassName}.*; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; -import ${basePackage}.modules.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; -import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.${table.className}Service; +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; +import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service; -@Api(tags = "${table.classComment}") +@Api(tags = "${sceneEnum.name} - ${table.classComment}") @RestController ##二级的 businessName 暂时不算在 HTTP 路径上,可以根据需要写 @RequestMapping("/${table.moduleName}/${simpleClassName_strikeCase}") @Validated -public class ${table.className}Controller { +public class ${sceneEnum.prefixClass}${table.className}Controller { @Resource private ${table.className}Service ${classNameVar}Service; @PostMapping("/create") @ApiOperation("创建${table.classComment}") - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") - public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${table.className}CreateReqVO createReqVO) { +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")#end + public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { return success(${classNameVar}Service.create${simpleClassName}(createReqVO)); } @PutMapping("/update") @ApiOperation("更新${table.classComment}") - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") - public CommonResult update${simpleClassName}(@Valid @RequestBody ${table.className}UpdateReqVO updateReqVO) { +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")#end + public CommonResult update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { ${classNameVar}Service.update${simpleClassName}(updateReqVO); return success(true); } @@ -55,7 +55,7 @@ public class ${table.className}Controller { @DeleteMapping("/delete") @ApiOperation("删除${table.classComment}") @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = ${primaryColumn.javaType}.class) - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')") +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")#end public CommonResult delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { ${classNameVar}Service.delete${simpleClassName}(id); return success(true); @@ -65,7 +65,7 @@ public class ${table.className}Controller { @ApiOperation("获得${table.classComment}") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = ${primaryColumn.javaType}.class) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") - public CommonResult<${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { + public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { ${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id); return success(${table.className}Convert.INSTANCE.convert(${classNameVar})); } @@ -73,30 +73,30 @@ public class ${table.className}Controller { @GetMapping("/list") @ApiOperation("获得${table.classComment}列表") @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") - public CommonResult> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) { +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end + public CommonResult> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) { List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids); return success(${table.className}Convert.INSTANCE.convertList(list)); } @GetMapping("/page") @ApiOperation("获得${table.classComment}分页") - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") - public CommonResult> get${simpleClassName}Page(@Valid ${table.className}PageReqVO pageVO) { +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end + public CommonResult> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageVO) { PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageVO); return success(${table.className}Convert.INSTANCE.convertPage(pageResult)); } @GetMapping("/export-excel") @ApiOperation("导出${table.classComment} Excel") - @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')") +#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")#end @OperateLog(type = EXPORT) - public void export${simpleClassName}Excel(@Valid ${table.className}ExportReqVO exportReqVO, + public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO, HttpServletResponse response) throws IOException { List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(exportReqVO); // 导出 Excel - List<${table.className}ExcelVO> datas = ${table.className}Convert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}ExcelVO.class, datas); + List<${sceneEnum.prefixClass}${table.className}ExcelVO> datas = ${table.className}Convert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, datas); } } diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/_column.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/_column.vm similarity index 100% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/_column.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/_column.vm diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/baseVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/baseVO.vm similarity index 83% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/baseVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/baseVO.vm index 705869a8da..3036c16edb 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/baseVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/baseVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -20,7 +20,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class ${table.className}BaseVO { +public class ${sceneEnum.prefixClass}${table.className}BaseVO { #foreach ($column in $columns) #if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult})##通用操作 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/createReqVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/createReqVO.vm similarity index 71% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/createReqVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/createReqVO.vm index cfb288241e..ca13efac5f 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/createReqVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/createReqVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -15,11 +15,11 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; #end #end -@ApiModel("${table.classComment}创建 Request VO") +@ApiModel("${sceneEnum.name} - ${table.classComment}创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ${table.className}CreateReqVO extends ${table.className}BaseVO { +public class ${sceneEnum.prefixClass}${table.className}CreateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { #foreach ($column in $columns) #if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}))##不是通用字段 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/excelVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/excelVO.vm similarity index 82% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/excelVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/excelVO.vm index b91e4e1784..2ce6f28a88 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/excelVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/excelVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -20,7 +20,7 @@ import ${DictConvertClassName}; * @author ${table.author} */ @Data -public class ${table.className}ExcelVO { +public class ${sceneEnum.prefixClass}${table.className}ExcelVO { #foreach ($column in $columns) #if (${column.listOperationResult})##返回字段 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/exportReqVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/exportReqVO.vm similarity index 78% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/exportReqVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/exportReqVO.vm index cd0e340e88..10ab97afc6 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/exportReqVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/exportReqVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -22,9 +22,9 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; #end -@ApiModel(value = "${table.classComment} Excel 导出 Request VO", description = "参数和 ${table.className}PageReqVO 是一致的") +@ApiModel(value = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO", description = "参数和 ${table.className}PageReqVO 是一致的") @Data -public class ${table.className}ExportReqVO { +public class ${sceneEnum.prefixClass}${table.className}ExportReqVO { #foreach ($column in $columns) #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/pageReqVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/pageReqVO.vm similarity index 83% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/pageReqVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/pageReqVO.vm index 0ac69e94df..5f5952c59e 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/pageReqVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/pageReqVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -22,11 +22,11 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; #end -@ApiModel("${table.classComment}分页 Request VO") +@ApiModel("${sceneEnum.name} - ${table.classComment}分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ${table.className}PageReqVO extends PageParam { +public class ${sceneEnum.prefixClass}${table.className}PageReqVO extends PageParam { #foreach ($column in $columns) #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/respVO.vm similarity index 63% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/respVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/respVO.vm index a100dd16c5..4034b6f63c 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -1,14 +1,14 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; import io.swagger.annotations.*; -@ApiModel("${table.classComment} Response VO") +@ApiModel("${sceneEnum.name} - ${table.classComment} Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ${table.className}RespVO extends ${table.className}BaseVO { +public class ${sceneEnum.prefixClass}${table.className}RespVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { #foreach ($column in $columns) #if (${column.listOperationResult} && (!${column.createOperation} || !${column.updateOperation}))##不是通用字段 diff --git a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/updateReqVO.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/updateReqVO.vm similarity index 71% rename from yudao-admin-server/src/main/resources/codegen/java/controller/vo/updateReqVO.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/updateReqVO.vm index a05ae8d66c..58ce1f73d3 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/controller/vo/updateReqVO.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/controller/vo/updateReqVO.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo; +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; import java.util.*; @@ -15,11 +15,11 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; #end #end -@ApiModel("${table.classComment}更新 Request VO") +@ApiModel("${sceneEnum.name} - ${table.classComment}更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ${table.className}UpdateReqVO extends ${table.className}BaseVO { +public class ${sceneEnum.prefixClass}${table.className}UpdateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { #foreach ($column in $columns) #if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}))##不是通用字段 diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/convert/convert.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/convert/convert.vm new file mode 100644 index 0000000000..6176e0f548 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/convert/convert.vm @@ -0,0 +1,34 @@ +package ${basePackage}.module.${table.moduleName}.convert.${table.businessName}; + +import java.util.*; + +import ${PageResultClassName}; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; + +/** + * ${table.classComment} Convert + * + * @author ${table.author} + */ +@Mapper +public interface ${table.className}Convert { + + ${table.className}Convert INSTANCE = Mappers.getMapper(${table.className}Convert.class); + + ${table.className}DO convert(${sceneEnum.prefixClass}${table.className}CreateReqVO bean); + + ${table.className}DO convert(${sceneEnum.prefixClass}${table.className}UpdateReqVO bean); + + ${sceneEnum.prefixClass}${table.className}RespVO convert(${table.className}DO bean); + + List<${sceneEnum.prefixClass}${table.className}RespVO> convertList(List<${table.className}DO> list); + + PageResult<${sceneEnum.prefixClass}${table.className}RespVO> convertPage(PageResult<${table.className}DO> page); + + List<${sceneEnum.prefixClass}${table.className}ExcelVO> convertList02(List<${table.className}DO> list); + +} diff --git a/yudao-admin-server/src/main/resources/codegen/java/dal/do.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/do.vm similarity index 83% rename from yudao-admin-server/src/main/resources/codegen/java/dal/do.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/do.vm index 8f10fd5e46..ffad97a28a 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/do.vm @@ -1,4 +1,4 @@ -package ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}; +package ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}; import lombok.*; import java.util.*; @@ -17,7 +17,7 @@ import ${BaseDOClassName}; @Builder @NoArgsConstructor @AllArgsConstructor -public class ${table.className}DO extends BaseDO { +public class ${table.className}DO extends ${BaseDOClassName_simple} { #foreach ($column in $columns) #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/mapper.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/mapper.vm new file mode 100644 index 0000000000..cab43effba --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/dal/mapper.vm @@ -0,0 +1,66 @@ +package ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}; + +import java.util.*; + +import ${PageResultClassName}; +import ${QueryWrapperClassName}; +import ${BaseMapperClassName}; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +import org.apache.ibatis.annotations.Mapper; +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; + +## 字段模板 +#macro(listCondition) +#foreach ($column in $columns) +#if (${column.listOperation}) +#set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 +#if (${column.listOperationCondition} == "=")##情况一,= 的时候 + .eqIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == "!=")##情况二,!= 的时候 + .neIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == ">")##情况三,> 的时候 + .gtIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == ">=")##情况四,>= 的时候 + .geIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == "<")##情况五,< 的时候 + .ltIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == "<=")##情况五,<= 的时候 + .leIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == "LIKE")##情况七,Like 的时候 + .likeIfPresent(${table.className}DO::get${JavaField}, reqVO.get${JavaField}()) +#end +#if (${column.listOperationCondition} == "BETWEEN")##情况八,Between 的时候 + .betweenIfPresent(${table.className}DO::get${JavaField}, reqVO.getBegin${JavaField}(), reqVO.getEnd${JavaField}()) +#end +#end +#end +#end +/** + * ${table.classComment} Mapper + * + * @author ${table.author} + */ +@Mapper +public interface ${table.className}Mapper extends BaseMapperX<${table.className}DO> { + + default PageResult<${table.className}DO> selectPage(${sceneEnum.prefixClass}${table.className}PageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX<${table.className}DO>() + #listCondition() + .orderByDesc(${table.className}DO::getId));## 大多数情况下,id 倒序 + + } + + default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX<${table.className}DO>() + #listCondition() + .orderByDesc(${table.className}DO::getId));## 大多数情况下,id 倒序 + + } + +} diff --git a/yudao-admin-server/src/main/resources/codegen/java/enums/errorcode.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/enums/errorcode.vm similarity index 50% rename from yudao-admin-server/src/main/resources/codegen/java/enums/errorcode.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/enums/errorcode.vm index 94f12df038..a9a6daf25b 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/enums/errorcode.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/enums/errorcode.vm @@ -1,2 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-${table.moduleName}-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! // ========== ${table.classComment} TODO 补充编号 ========== ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${table.classComment}不存在"); diff --git a/yudao-admin-server/src/main/resources/codegen/java/service/service.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/service.vm similarity index 68% rename from yudao-admin-server/src/main/resources/codegen/java/service/service.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/service.vm index 17a9b39532..b8c6376988 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/service/service.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/service.vm @@ -1,9 +1,9 @@ -package ${basePackage}.modules.${table.moduleName}.service.${table.businessName}; +package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import java.util.*; import javax.validation.*; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; import ${PageResultClassName}; /** @@ -19,14 +19,14 @@ public interface ${table.className}Service { * @param createReqVO 创建信息 * @return 编号 */ - ${primaryColumn.javaType} create${simpleClassName}(@Valid ${table.className}CreateReqVO createReqVO); + ${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO); /** * 更新${table.classComment} * * @param updateReqVO 更新信息 */ - void update${simpleClassName}(@Valid ${table.className}UpdateReqVO updateReqVO); + void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO); /** * 删除${table.classComment} @@ -57,7 +57,7 @@ public interface ${table.className}Service { * @param pageReqVO 分页查询 * @return ${table.classComment}分页 */ - PageResult<${table.className}DO> get${simpleClassName}Page(${table.className}PageReqVO pageReqVO); + PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO); /** * 获得${table.classComment}列表, 用于 Excel 导出 @@ -65,6 +65,6 @@ public interface ${table.className}Service { * @param exportReqVO 查询条件 * @return ${table.classComment}列表 */ - List<${table.className}DO> get${simpleClassName}List(${table.className}ExportReqVO exportReqVO); + List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO); } diff --git a/yudao-admin-server/src/main/resources/codegen/java/service/serviceImpl.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/serviceImpl.vm similarity index 70% rename from yudao-admin-server/src/main/resources/codegen/java/service/serviceImpl.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/serviceImpl.vm index 33201a6d82..85dfa0aab0 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/service/serviceImpl.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/service/serviceImpl.vm @@ -1,20 +1,19 @@ -package ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.impl; +package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import org.springframework.stereotype.Service; import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; import java.util.*; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; import ${PageResultClassName}; -import ${basePackage}.modules.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; -import ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; -import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.${table.className}Service; +import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; +import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; import static ${ServiceExceptionUtilClassName}.exception; -import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*; +import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; /** * ${table.classComment} Service 实现类 @@ -29,7 +28,7 @@ public class ${table.className}ServiceImpl implements ${table.className}Service private ${table.className}Mapper ${classNameVar}Mapper; @Override - public ${primaryColumn.javaType} create${simpleClassName}(${table.className}CreateReqVO createReqVO) { + public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { // 插入 ${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO); ${classNameVar}Mapper.insert(${classNameVar}); @@ -38,7 +37,7 @@ public class ${table.className}ServiceImpl implements ${table.className}Service } @Override - public void update${simpleClassName}(${table.className}UpdateReqVO updateReqVO) { + public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { // 校验存在 this.validate${simpleClassName}Exists(updateReqVO.getId()); // 更新 @@ -71,12 +70,12 @@ public class ${table.className}ServiceImpl implements ${table.className}Service } @Override - public PageResult<${table.className}DO> get${simpleClassName}Page(${table.className}PageReqVO pageReqVO) { + public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { return ${classNameVar}Mapper.selectPage(pageReqVO); } @Override - public List<${table.className}DO> get${simpleClassName}List(${table.className}ExportReqVO exportReqVO) { + public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO) { return ${classNameVar}Mapper.selectList(exportReqVO); } diff --git a/yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/test/serviceTest.vm similarity index 81% rename from yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/test/serviceTest.vm index 511d65148d..53b7429ec1 100644 --- a/yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/java/test/serviceTest.vm @@ -1,15 +1,15 @@ -package ${basePackage}.modules.${table.moduleName}.service.${table.businessName}; +package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import javax.annotation.Resource; -import ${basePackage}.BaseDbUnitTest; -import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.impl.${table.className}ServiceImpl; -import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*; -import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; -import ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; +import ${basePackage}.module.${table.moduleName}.test.BaseDbUnitTest;## 每个项目,默认有一个基础 DB Test 基类 + +import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; +import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; import ${PageResultClassName}; import javax.annotation.Resource; @@ -17,7 +17,7 @@ import org.springframework.context.annotation.Import; import java.util.*; import static cn.hutool.core.util.RandomUtil.*; -import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*; +import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; import static ${baseFrameworkPackage}.test.core.util.AssertUtils.*; import static ${baseFrameworkPackage}.test.core.util.RandomUtils.*; import static ${ObjectUtilsClassName}.*; @@ -45,7 +45,7 @@ import static org.mockito.Mockito.*; #end #end // 准备参数 - ${table.className}${VO} reqVO = new ${table.className}${VO}(); + ${sceneEnum.prefixClass}${table.className}${VO} reqVO = new ${sceneEnum.prefixClass}${table.className}${VO}(); #foreach ($column in $columns) #if (${column.listOperation}) #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写 @@ -64,7 +64,7 @@ import static org.mockito.Mockito.*; * @author ${table.author} */ @Import(${table.className}ServiceImpl.class) -public class ${table.className}ServiceTest extends BaseDbUnitTest { +public class ${table.className}ServiceImplTest extends BaseDbUnitTest { @Resource private ${table.className}ServiceImpl ${classNameVar}Service; @@ -75,7 +75,7 @@ public class ${table.className}ServiceTest extends BaseDbUnitTest { @Test public void testCreate${simpleClassName}_success() { // 准备参数 - ${table.className}CreateReqVO reqVO = randomPojo(${table.className}CreateReqVO.class); + ${sceneEnum.prefixClass}${table.className}CreateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}CreateReqVO.class); // 调用 ${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO); @@ -92,7 +92,7 @@ public class ${table.className}ServiceTest extends BaseDbUnitTest { ${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class); ${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据 // 准备参数 - ${table.className}UpdateReqVO reqVO = randomPojo(${table.className}UpdateReqVO.class, o -> { + ${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class, o -> { o.setId(db${simpleClassName}.getId()); // 设置更新的 ID }); @@ -106,7 +106,7 @@ public class ${table.className}ServiceTest extends BaseDbUnitTest { @Test public void testUpdate${simpleClassName}_notExists() { // 准备参数 - ${table.className}UpdateReqVO reqVO = randomPojo(${table.className}UpdateReqVO.class); + ${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class); // 调用, 并断言异常 assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(reqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); diff --git a/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/h2.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/h2.vm new file mode 100644 index 0000000000..842605a0fd --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/h2.vm @@ -0,0 +1,24 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-impl 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "${table.tableName}" ( +#foreach ($column in $columns) + #if (${column.primaryKey})##处理主键 + "${column.javaField}"#if (${column.javaType} == 'String') ${column.columnType} NOT NULL#else ${column.columnType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end, + #else + #if (${column.columnName} == 'create_time') + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + #elseif (${column.columnName} == 'update_time') + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + #elseif (${column.columnName} == 'creator' || ${column.columnName} == 'updater') + "${column.columnName}" ${column.columnType} DEFAULT '', + #elseif (${column.columnName} == 'deleted') + "deleted" bit NOT NULL DEFAULT FALSE, + #else + "${column.columnName}" ${column.columnType}#if (${column.nullable} == false) NOT NULL#end, + #end + #end +#end + PRIMARY KEY ("${primaryColumn.columnName}") +) COMMENT '${table.tableComment}'; + +-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-impl 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "${table.tableName}"; diff --git a/yudao-admin-server/src/main/resources/codegen/sql/sql.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/sql.vm similarity index 94% rename from yudao-admin-server/src/main/resources/codegen/sql/sql.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/sql.vm index 741016c231..25d76ae1de 100644 --- a/yudao-admin-server/src/main/resources/codegen/sql/sql.vm +++ b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/sql/sql.vm @@ -1,5 +1,5 @@ -- 菜单 SQL -INSERT INTO `sys_menu`( +INSERT INTO `system_menu`( `name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status` ) @@ -16,7 +16,7 @@ SELECT @parentId := LAST_INSERT_ID(); #set ($functionOps = ['query', 'create', 'update', 'delete', 'export']) #foreach ($functionName in $functionNames) #set ($index = $foreach.count - 1) -INSERT INTO `sys_menu`( +INSERT INTO `system_menu`( `name`, `permission`, `menu_type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status` ) diff --git a/yudao-admin-server/src/main/resources/codegen/vue/api/api.js.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/vue/api/api.js.vm similarity index 100% rename from yudao-admin-server/src/main/resources/codegen/vue/api/api.js.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/vue/api/api.js.vm diff --git a/yudao-admin-server/src/main/resources/codegen/vue/views/index.vue.vm b/yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/vue/views/index.vue.vm similarity index 100% rename from yudao-admin-server/src/main/resources/codegen/vue/views/index.vue.vm rename to yudao-module-tool/yudao-module-tool-impl/src/main/resources/codegen/vue/views/index.vue.vm diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapperTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapperTest.java new file mode 100644 index 0000000000..1adf32fddf --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/codegen/SchemaColumnMapperTest.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.tool.dal.mysql.codegen; + +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.SchemaColumnDO; +import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SchemaColumnMapperTest extends BaseDbUnitTest { + + @Resource + private SchemaColumnMapper schemaColumnMapper; + + @Test + public void testSelectListByTableName() { + List columns = schemaColumnMapper.selectListByTableName("", "inf_config"); + assertTrue(columns.size() > 0); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/package-info.java new file mode 100644 index 0000000000..858488d9f4 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/mysql/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.tool.dal.mysql; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/package-info.java new file mode 100644 index 0000000000..589846c6d4 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/dal/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.tool.dal; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenEngineTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenEngineTest.java new file mode 100644 index 0000000000..eabc880311 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenEngineTest.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.tool.service.codegen; + +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenColumnDO; +import cn.iocoder.yudao.module.tool.dal.dataobject.codegen.CodegenTableDO; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.CodegenColumnMapper; +import cn.iocoder.yudao.module.tool.dal.mysql.codegen.CodegenTableMapper; +import cn.iocoder.yudao.module.tool.service.codegen.inner.CodegenEngine; +import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +public class CodegenEngineTest extends BaseDbUnitTest { + + @Resource + private CodegenTableMapper codegenTableMapper; + @Resource + private CodegenColumnMapper codegenColumnMapper; + + @Resource + private CodegenEngine codegenEngine; + + @Test + public void testExecute() { + CodegenTableDO table = codegenTableMapper.selectById(20); + List columns = codegenColumnMapper.selectListByTableId(table.getId()); + Map result = codegenEngine.execute(table, columns); + result.forEach((s, s2) -> System.out.println(s2)); +// System.out.println(result.get("vue/views/system/test/index.vue")); + } + +} diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenSQLParserTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenSQLParserTest.java similarity index 80% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenSQLParserTest.java rename to yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenSQLParserTest.java index 44c909118a..e9a2603e96 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/ToolCodegenSQLParserTest.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenSQLParserTest.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.adminserver.modules.tool.service.codegen; +package cn.iocoder.yudao.module.tool.service.codegen; -import cn.iocoder.yudao.adminserver.BaseDbUnitTest; -import cn.iocoder.yudao.adminserver.modules.tool.service.codegen.impl.ToolCodegenSQLParser; +import cn.iocoder.yudao.module.tool.service.codegen.inner.CodegenSQLParser; +import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest; import org.junit.jupiter.api.Test; -public class ToolCodegenSQLParserTest extends BaseDbUnitTest { +public class CodegenSQLParserTest extends BaseDbUnitTest { @Test public void testParse() { @@ -22,7 +22,7 @@ public class ToolCodegenSQLParserTest extends BaseDbUnitTest { " `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" + " PRIMARY KEY (`id`) USING BTREE\n" + ") ENGINE=InnoDB AUTO_INCREMENT=108 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';"; - ToolCodegenSQLParser.parse(sql); + CodegenSQLParser.parse(sql); // TODO 芋艿:后续完善断言 } diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImplTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImplTest.java new file mode 100644 index 0000000000..461f45b855 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/codegen/CodegenServiceImplTest.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.tool.service.codegen; + +import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; + +class CodegenServiceImplTest extends BaseDbUnitTest { + + @Resource + private CodegenServiceImpl codegenService; + + @Test + public void tetCreateCodegenTable() { + codegenService.createCodegen(0L, "tool_test_demo"); +// toolCodegenService.createCodegenTable("tool_codegen_table"); +// toolCodegenService.createCodegen("tool_codegen_column"); + } + +} diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/package-info.java new file mode 100644 index 0000000000..5dd2f92481 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/service/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.tool.service; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisIntegrationTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseDbAndRedisIntegrationTest.java similarity index 97% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisIntegrationTest.java rename to yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseDbAndRedisIntegrationTest.java index 915715c33f..7ce9039cdf 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseDbAndRedisIntegrationTest.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseDbAndRedisIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.module.tool.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; diff --git a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseRedisIntegrationTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseRedisIntegrationTest.java similarity index 95% rename from yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseRedisIntegrationTest.java rename to yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseRedisIntegrationTest.java index 78857e01f6..06bae00a83 100644 --- a/yudao-admin-server/src/test-integration/java/cn/iocoder/yudao/adminserver/BaseRedisIntegrationTest.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/java/cn/iocoder/yudao/module/tool/test/BaseRedisIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.module.tool.test; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import org.redisson.spring.starter.RedissonAutoConfiguration; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test-integration/resources/application-integration-test.yaml b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/resources/application-integration-test.yaml new file mode 100644 index 0000000000..d9612eee75 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test-integration/resources/application-integration-test.yaml @@ -0,0 +1,108 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 123456 + slave: # 模拟从库,可根据自己需要修改 + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 123456 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 +resilience4j: + ratelimiter: + instances: + backendA: + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s + register-health-indicator: true # 是否注册到健康监测 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + security: + token-header: Authorization + token-secret: abcdefghijklmnopqrstuvwxyz + token-timeout: 1d + session-timeout: 30m + mock-enable: true + mock-secret: test + swagger: + enable: false # 单元测试,禁用 Swagger + file: + base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/ + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/package-info.java b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/package-info.java new file mode 100644 index 0000000000..be7a3de4bf --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.tool.service; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java new file mode 100755 index 0000000000..b8a2c86c88 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java @@ -0,0 +1,187 @@ +package cn.iocoder.yudao.module.tool.service.test; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.TestDemoCreateReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.TestDemoExportReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.TestDemoPageReqVO; +import cn.iocoder.yudao.module.tool.controller.admin.test.vo.TestDemoUpdateReqVO; +import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO; +import cn.iocoder.yudao.module.tool.dal.mysql.test.TestDemoMapper; +import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.TEST_DEMO_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link TestDemoServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(TestDemoServiceImpl.class) +public class TestDemoServiceImplTest extends BaseDbUnitTest { + + @Resource + private TestDemoServiceImpl testDemoService; + + @Resource + private TestDemoMapper testDemoMapper; + + @Test + public void testCreateTestDemo_success() { + // 准备参数 + TestDemoCreateReqVO reqVO = randomPojo(TestDemoCreateReqVO.class); + + // 调用 + Long testDemoId = testDemoService.createTestDemo(reqVO); + // 断言 + assertNotNull(testDemoId); + // 校验记录的属性是否正确 + TestDemoDO testDemo = testDemoMapper.selectById(testDemoId); + assertPojoEquals(reqVO, testDemo); + } + + @Test + public void testUpdateTestDemo_success() { + // mock 数据 + TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class); + testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据 + // 准备参数 + TestDemoUpdateReqVO reqVO = randomPojo(TestDemoUpdateReqVO.class, o -> { + o.setId(dbTestDemo.getId()); // 设置更新的 ID + }); + + // 调用 + testDemoService.updateTestDemo(reqVO); + // 校验是否更新正确 + TestDemoDO testDemo = testDemoMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, testDemo); + } + + @Test + public void testUpdateTestDemo_notExists() { + // 准备参数 + TestDemoUpdateReqVO reqVO = randomPojo(TestDemoUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> testDemoService.updateTestDemo(reqVO), TEST_DEMO_NOT_EXISTS); + } + + @Test + public void testDeleteTestDemo_success() { + // mock 数据 + TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class); + testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbTestDemo.getId(); + + // 调用 + testDemoService.deleteTestDemo(id); + // 校验数据不存在了 + assertNull(testDemoMapper.selectById(id)); + } + + @Test + public void testDeleteTestDemo_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> testDemoService.deleteTestDemo(id), TEST_DEMO_NOT_EXISTS); + } + + @Test + public void testGetTestDemoPage() { + // mock 数据 + TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到 + o.setName("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setType(1); + o.setCategory(2); + o.setRemark("哈哈哈"); + o.setCreateTime(DateUtils.buildTime(2021, 11, 11)); + }); + testDemoMapper.insert(dbTestDemo); + // 测试 name 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName("不匹配"))); + // 测试 status 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 type 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(2))); + // 测试 category 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(1))); + // 测试 remark 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵"))); + // 测试 createTime 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildTime(2021, 12, 12)))); + // 准备参数 + TestDemoPageReqVO reqVO = new TestDemoPageReqVO(); + reqVO.setName("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setType(1); + reqVO.setCategory(2); + reqVO.setRemark("哈哈哈"); + reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 11, 10)); + reqVO.setEndCreateTime(DateUtils.buildTime(2021, 11, 12)); + + // 调用 + PageResult pageResult = testDemoService.getTestDemoPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbTestDemo, pageResult.getList().get(0)); + } + + @Test + public void testGetTestDemoList() { + // mock 数据 + TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到 + o.setName("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setType(1); + o.setCategory(2); + o.setRemark("哈哈哈"); + o.setCreateTime(DateUtils.buildTime(2021, 11, 11)); + }); + testDemoMapper.insert(dbTestDemo); + // 测试 name 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName("不匹配"))); + // 测试 status 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 type 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(2))); + // 测试 category 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(1))); + // 测试 remark 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵"))); + // 测试 createTime 不匹配 + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildTime(2021, 12, 12)))); + // 准备参数 + TestDemoExportReqVO reqVO = new TestDemoExportReqVO(); + reqVO.setName("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setType(1); + reqVO.setCategory(2); + reqVO.setRemark("哈哈哈"); + reqVO.setBeginCreateTime(DateUtils.buildTime(2021, 11, 10)); + reqVO.setEndCreateTime(DateUtils.buildTime(2021, 11, 12)); + + // 调用 + List list = testDemoService.getTestDemoList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbTestDemo, list.get(0)); + } + +} diff --git a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbUnitTest.java b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/test/BaseDbUnitTest.java similarity index 91% rename from yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbUnitTest.java rename to yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/test/BaseDbUnitTest.java index 94d6d3107c..3cfbf88e3a 100644 --- a/yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbUnitTest.java +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/test/BaseDbUnitTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.coreservice; +package cn.iocoder.yudao.module.tool.test; import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; @@ -20,6 +20,7 @@ import org.springframework.test.context.jdbc.Sql; */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) @ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +@Sql(scripts = "/sql/create_tables.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) // 每个单元测试结束前,创建表 @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB public class BaseDbUnitTest { diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/resources/application-unit-test.yaml b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/application-unit-test.yaml new file mode 100644 index 0000000000..9f36ec4ac9 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/application-unit-test.yaml @@ -0,0 +1,46 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/resources/logback.xml b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/logback.xml new file mode 100644 index 0000000000..daf756bff0 --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/clean.sql b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/clean.sql new file mode 100644 index 0000000000..4afb9e7fce --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/clean.sql @@ -0,0 +1 @@ +DELETE FROM "tool_test_demo"; diff --git a/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/create_tables.sql b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/create_tables.sql new file mode 100644 index 0000000000..298430883b --- /dev/null +++ b/yudao-module-tool/yudao-module-tool-impl/src/test/resources/sql/create_tables.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS "tool_test_demo" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(100) NOT NULL, + "status" tinyint NOT NULL, + "type" tinyint NOT NULL, + "category" tinyint NOT NULL, + "remark" varchar(500), + "creator" varchar(64) DEFAULT '''', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '''', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '字典类型表'; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml new file mode 100644 index 0000000000..0e933ce054 --- /dev/null +++ b/yudao-server/pom.xml @@ -0,0 +1,94 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-server + jar + + ${artifactId} + + 后端 Server 的主项目,通过引入需要 yudao-module-xxx 的依赖, + 从而实现提供 RESTful API 给 yudao-ui-admin、yudao-ui-user 等前端项目。 + 本质上来说,它就是个空壳(容器)! + + https://github.com/YunaiV/ruoyi-vue-pro + + + + + cn.iocoder.boot + yudao-module-member-impl + ${revision} + + + cn.iocoder.boot + yudao-module-system-impl + ${revision} + + + cn.iocoder.boot + yudao-module-tool-impl + ${revision} + + + cn.iocoder.boot + yudao-module-infra-impl + ${revision} + + + cn.iocoder.boot + yudao-module-pay-impl + ${revision} + + + + cn.iocoder.boot + yudao-module-bpm-impl-activiti + ${revision} + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + cn.iocoder.boot + yudao-spring-boot-starter-protection + + + + + + + ${artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + repackage + + + + + + + + diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/admin/package-info.java b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/admin/package-info.java new file mode 100644 index 0000000000..624b6c6145 --- /dev/null +++ b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/admin/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.shop.controller.admin; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/ShopOrderController.java b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java similarity index 71% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/ShopOrderController.java rename to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java index 25ebd6d282..54ff4daf97 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/ShopOrderController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java @@ -1,13 +1,13 @@ -package cn.iocoder.yudao.userserver.modules.shop.controller; +package cn.iocoder.yudao.module.shop.controller.app; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayNotifyOrderReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayRefundOrderReqVO; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; -import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; -import cn.iocoder.yudao.userserver.modules.shop.controller.vo.ShopOrderCreateRespVO; +import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO; +import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.util.PaySeqUtils; +import cn.iocoder.yudao.module.shop.controller.app.vo.AppShopOrderCreateRespVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -24,20 +24,20 @@ import java.time.Duration; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; -@Api(tags = "商城订单") +@Api(tags = "用户 APP - 商城订单") @RestController @RequestMapping("/shop/order") @Validated @Slf4j -public class ShopOrderController { +public class AppShopOrderController { @Resource - private PayOrderCoreService payOrderCoreService; + private PayOrderService payOrderService; @PostMapping("/create") @ApiOperation("创建商城订单") // @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好 - public CommonResult create() { + public CommonResult create() { // 假装创建商城订单 Long shopOrderId = System.currentTimeMillis(); @@ -50,10 +50,10 @@ public class ShopOrderController { reqDTO.setBody("内容:" + shopOrderId); reqDTO.setAmount(200); // 单位:分 reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); - Long payOrderId = payOrderCoreService.createPayOrder(reqDTO); + Long payOrderId = payOrderService.createPayOrder(reqDTO); // 拼接返回 - return success(ShopOrderCreateRespVO.builder().id(shopOrderId) + return success(AppShopOrderCreateRespVO.builder().id(shopOrderId) .payOrderId(payOrderId).build()); } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/vo/ShopOrderCreateRespVO.java b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/vo/AppShopOrderCreateRespVO.java similarity index 73% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/vo/ShopOrderCreateRespVO.java rename to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/vo/AppShopOrderCreateRespVO.java index 682afc4e9d..06a677dbb5 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/vo/ShopOrderCreateRespVO.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/vo/AppShopOrderCreateRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.userserver.modules.shop.controller.vo; +package cn.iocoder.yudao.module.shop.controller.app.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -@ApiModel("商城订单创建 Response VO") +@ApiModel("用户 APP - 商城订单创建 Response VO") @Data @Builder @AllArgsConstructor -public class ShopOrderCreateRespVO { +public class AppShopOrderCreateRespVO { @ApiModelProperty(value = "商城订单编号", required = true, example = "1024") private Long id; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/package-info.java b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/package-info.java similarity index 62% rename from yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/package-info.java rename to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/package-info.java index c592130af3..f088370dd1 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/package-info.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/package-info.java @@ -5,4 +5,5 @@ * * 缩写:shop */ -package cn.iocoder.yudao.userserver.modules.shop; +// TODO 芋艿:后续会迁移到 yudao-module-mall-trade 下 +package cn.iocoder.yudao.module.shop; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/AdminServerApplication.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/YudaoServerApplication.java similarity index 54% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/AdminServerApplication.java rename to yudao-server/src/main/java/cn/iocoder/yudao/server/YudaoServerApplication.java index 810869768e..4a963dedd4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/AdminServerApplication.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/YudaoServerApplication.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.adminserver; +package cn.iocoder.yudao.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} 和 ${yudao.core-service.base-package} -@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"}) -public class AdminServerApplication { +@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} +@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}.server", "${yudao.info.base-package}.module"}) +public class YudaoServerApplication { public static void main(String[] args) { - SpringApplication.run(AdminServerApplication.class, args); + SpringApplication.run(YudaoServerApplication.class, args); } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/package-info.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/package-info.java similarity index 65% rename from yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/package-info.java rename to yudao-server/src/main/java/cn/iocoder/yudao/server/framework/package-info.java index fcb2a09363..bca006708d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/package-info.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.adminserver.framework; +package cn.iocoder.yudao.server.framework; diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/config/AdminUiConfiguration.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/config/AdminUiConfiguration.java new file mode 100644 index 0000000000..c24ae0d3ed --- /dev/null +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/config/AdminUiConfiguration.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.server.framework.ui.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * yudao-admin-ui 的配置类 + * + * @author 芋道源码 + */ +@Configuration +public class AdminUiConfiguration implements WebMvcConfigurer { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/admin-ui/**", "/admin-ui/", "/admin-ui") + .addResourceLocations("classpath:/admin-ui/") + // 自定义 ClassPathResource 实现类,在前端请求的地址匹配不到对应的路径时,强制使用 /admin-ui/index.html 资源 + // 本质上,等价于 nginx 在处理不到 Vue 的请求地址时,try_files 到 index.html 地址 + // 想要彻底理解,可以调试 ResourceHttpRequestHandler 的 resolveResourceLocations 方法,前端请求 /admin-ui/system/tenant 地址 + .addResourceLocations(new ClassPathResource("/admin-ui/index.html") { + + @Override + public Resource createRelative(String relativePath) { + return this; + } + + }) + ; + } + +} diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/AdminUiController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/AdminUiController.java new file mode 100644 index 0000000000..00cacc1752 --- /dev/null +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/AdminUiController.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.server.framework.ui.core; + +import org.springframework.boot.web.servlet.error.ErrorController; + +//@Controller +//@RequestMapping("/admin-ui/") +public class AdminUiController implements ErrorController { + +// public String + +} diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/package-info.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/package-info.java new file mode 100644 index 0000000000..a1b463fae6 --- /dev/null +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.server.framework.ui.core; diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/package-info.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/package-info.java new file mode 100644 index 0000000000..87aec7a71e --- /dev/null +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/framework/ui/package-info.java @@ -0,0 +1,7 @@ +/** + * 目的:解决后端开发,不太擅长 node 环境的配置,导致启动 yudao-admin-ui 项目一直失败 + * 所以,本项目将 yudao-admin-ui 项目通过 npm run build:demo1024 的方式,将它构建成静态资源, + * 然后,使用 Spring Boot 作为静态资源服务器,进行启动访问。 + * 注意,这个项目仅仅作为后端开发的快速体验,并不要部署到生产环境!!! + */ +package cn.iocoder.yudao.server.framework.ui; diff --git a/yudao-admin-ui/public/favicon.ico b/yudao-server/src/main/resources/admin-ui/favicon.ico similarity index 100% rename from yudao-admin-ui/public/favicon.ico rename to yudao-server/src/main/resources/admin-ui/favicon.ico diff --git a/yudao-server/src/main/resources/admin-ui/index.html b/yudao-server/src/main/resources/admin-ui/index.html new file mode 100644 index 0000000000..1c9d686774 --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/index.html @@ -0,0 +1,207 @@ + + + + + + + + + 芋道管理系统 + + + +

+
+
+
+
+
正在加载系统资源,请耐心等待
+
+
+ + diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/base/worker/workerMain.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/base/worker/workerMain.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/base/worker/workerMain.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/base/worker/workerMain.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/abap/abap.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/abap/abap.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/abap/abap.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/abap/abap.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/apex/apex.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/apex/apex.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/apex/apex.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/apex/apex.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/azcli/azcli.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/azcli/azcli.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/azcli/azcli.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/azcli/azcli.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/bat/bat.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/bat/bat.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/bat/bat.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/bat/bat.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/cameligo/cameligo.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/cameligo/cameligo.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/cameligo/cameligo.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/cameligo/cameligo.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/clojure/clojure.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/clojure/clojure.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/clojure/clojure.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/clojure/clojure.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/coffee/coffee.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/coffee/coffee.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/coffee/coffee.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/coffee/coffee.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/cpp/cpp.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/cpp/cpp.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/cpp/cpp.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/cpp/cpp.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/csharp/csharp.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/csharp/csharp.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/csharp/csharp.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/csharp/csharp.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/csp/csp.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/csp/csp.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/csp/csp.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/csp/csp.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/css/css.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/css/css.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/css/css.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/css/css.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/dart/dart.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/dart/dart.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/dart/dart.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/dart/dart.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/dockerfile/dockerfile.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/dockerfile/dockerfile.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/dockerfile/dockerfile.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/dockerfile/dockerfile.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ecl/ecl.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ecl/ecl.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ecl/ecl.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ecl/ecl.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/fsharp/fsharp.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/fsharp/fsharp.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/fsharp/fsharp.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/fsharp/fsharp.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/go/go.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/go/go.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/go/go.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/go/go.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/graphql/graphql.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/graphql/graphql.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/graphql/graphql.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/graphql/graphql.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/handlebars/handlebars.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/handlebars/handlebars.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/handlebars/handlebars.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/handlebars/handlebars.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/hcl/hcl.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/hcl/hcl.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/hcl/hcl.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/hcl/hcl.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/html/html.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/html/html.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/html/html.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/html/html.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ini/ini.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ini/ini.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ini/ini.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ini/ini.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/java/java.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/java/java.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/java/java.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/java/java.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/javascript/javascript.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/javascript/javascript.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/javascript/javascript.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/javascript/javascript.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/julia/julia.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/julia/julia.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/julia/julia.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/julia/julia.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/kotlin/kotlin.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/kotlin/kotlin.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/kotlin/kotlin.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/kotlin/kotlin.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/less/less.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/less/less.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/less/less.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/less/less.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/lexon/lexon.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/lexon/lexon.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/lexon/lexon.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/lexon/lexon.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/lua/lua.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/lua/lua.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/lua/lua.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/lua/lua.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/m3/m3.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/m3/m3.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/m3/m3.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/m3/m3.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/markdown/markdown.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/markdown/markdown.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/markdown/markdown.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/markdown/markdown.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/mips/mips.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/mips/mips.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/mips/mips.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/mips/mips.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/msdax/msdax.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/msdax/msdax.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/msdax/msdax.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/msdax/msdax.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/mysql/mysql.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/mysql/mysql.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/mysql/mysql.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/mysql/mysql.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/objective-c/objective-c.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/objective-c/objective-c.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/objective-c/objective-c.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/objective-c/objective-c.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pascal/pascal.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pascal/pascal.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pascal/pascal.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pascal/pascal.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pascaligo/pascaligo.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pascaligo/pascaligo.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pascaligo/pascaligo.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pascaligo/pascaligo.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/perl/perl.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/perl/perl.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/perl/perl.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/perl/perl.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pgsql/pgsql.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pgsql/pgsql.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pgsql/pgsql.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pgsql/pgsql.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/php/php.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/php/php.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/php/php.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/php/php.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/postiats/postiats.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/postiats/postiats.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/postiats/postiats.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/postiats/postiats.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/powerquery/powerquery.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/powerquery/powerquery.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/powerquery/powerquery.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/powerquery/powerquery.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/powershell/powershell.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/powershell/powershell.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/powershell/powershell.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/powershell/powershell.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pug/pug.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pug/pug.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/pug/pug.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/pug/pug.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/python/python.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/python/python.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/python/python.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/python/python.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/r/r.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/r/r.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/r/r.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/r/r.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/razor/razor.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/razor/razor.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/razor/razor.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/razor/razor.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/redis/redis.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/redis/redis.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/redis/redis.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/redis/redis.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/redshift/redshift.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/redshift/redshift.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/redshift/redshift.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/redshift/redshift.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ruby/ruby.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ruby/ruby.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/ruby/ruby.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/ruby/ruby.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/rust/rust.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/rust/rust.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/rust/rust.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/rust/rust.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sb/sb.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sb/sb.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sb/sb.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sb/sb.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scala/scala.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scala/scala.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scala/scala.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scala/scala.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scheme/scheme.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scheme/scheme.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scheme/scheme.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scheme/scheme.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scss/scss.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scss/scss.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/scss/scss.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/scss/scss.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/shell/shell.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/shell/shell.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/shell/shell.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/shell/shell.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/solidity/solidity.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/solidity/solidity.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/solidity/solidity.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/solidity/solidity.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sophia/sophia.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sophia/sophia.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sophia/sophia.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sophia/sophia.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sql/sql.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sql/sql.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/sql/sql.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/sql/sql.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/st/st.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/st/st.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/st/st.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/st/st.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/swift/swift.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/swift/swift.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/swift/swift.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/swift/swift.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/systemverilog/systemverilog.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/systemverilog/systemverilog.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/systemverilog/systemverilog.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/systemverilog/systemverilog.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/tcl/tcl.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/tcl/tcl.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/tcl/tcl.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/tcl/tcl.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/twig/twig.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/twig/twig.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/twig/twig.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/twig/twig.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/typescript/typescript.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/typescript/typescript.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/typescript/typescript.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/typescript/typescript.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/vb/vb.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/vb/vb.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/vb/vb.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/vb/vb.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/xml/xml.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/xml/xml.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/xml/xml.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/xml/xml.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/yaml/yaml.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/yaml/yaml.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/basic-languages/yaml/yaml.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/basic-languages/yaml/yaml.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.css b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.css similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.css rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.css diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.de.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.de.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.de.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.de.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.es.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.es.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.es.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.es.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.fr.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.fr.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.fr.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.fr.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.it.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.it.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.it.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.it.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ja.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ja.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ja.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ja.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ko.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ko.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ko.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ko.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ru.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ru.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.ru.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.ru.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.zh-cn.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.zh-cn.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.zh-cn.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.zh-cn.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.zh-tw.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.zh-tw.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/editor/editor.main.nls.zh-tw.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/editor/editor.main.nls.zh-tw.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/css/cssMode.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/css/cssMode.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/css/cssMode.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/css/cssMode.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/css/cssWorker.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/css/cssWorker.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/css/cssWorker.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/css/cssWorker.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/html/htmlMode.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/html/htmlMode.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/html/htmlMode.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/html/htmlMode.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/html/htmlWorker.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/html/htmlWorker.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/html/htmlWorker.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/html/htmlWorker.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/json/jsonMode.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/json/jsonMode.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/json/jsonMode.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/json/jsonMode.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/json/jsonWorker.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/json/jsonWorker.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/json/jsonWorker.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/json/jsonWorker.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/typescript/tsMode.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/typescript/tsMode.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/typescript/tsMode.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/typescript/tsMode.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/language/typescript/tsWorker.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/typescript/tsWorker.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/language/typescript/tsWorker.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/language/typescript/tsWorker.js diff --git a/yudao-admin-ui/public/libs/monaco-editor/vs/loader.js b/yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/loader.js similarity index 100% rename from yudao-admin-ui/public/libs/monaco-editor/vs/loader.js rename to yudao-server/src/main/resources/admin-ui/libs/monaco-editor/vs/loader.js diff --git a/yudao-admin-ui/public/robots.txt b/yudao-server/src/main/resources/admin-ui/robots.txt similarity index 100% rename from yudao-admin-ui/public/robots.txt rename to yudao-server/src/main/resources/admin-ui/robots.txt diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.08b5f281.eot b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.08b5f281.eot new file mode 100644 index 0000000000..8f3a3ddc4f Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.08b5f281.eot differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.3c4c9f45.woff2 b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.3c4c9f45.woff2 new file mode 100644 index 0000000000..79929b236a Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.3c4c9f45.woff2 differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.acbc6cbd.woff b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.acbc6cbd.woff new file mode 100644 index 0000000000..c4132a61af Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.acbc6cbd.woff differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.f922519e.ttf b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.f922519e.ttf new file mode 100644 index 0000000000..f5f0b9992f Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/bpmn.f922519e.ttf differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.535877f5.woff b/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.535877f5.woff new file mode 100644 index 0000000000..02b9a2539e Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.535877f5.woff differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.732389de.ttf b/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.732389de.ttf new file mode 100644 index 0000000000..91b74de367 Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/element-icons.732389de.ttf differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.674f50d2.eot b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.674f50d2.eot new file mode 100644 index 0000000000..e9f60ca953 Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.674f50d2.eot differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.af7ae505.woff2 b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.af7ae505.woff2 new file mode 100644 index 0000000000..4d13fc6040 Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.af7ae505.woff2 differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.b06871f2.ttf b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.b06871f2.ttf new file mode 100644 index 0000000000..35acda2fa1 Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.b06871f2.ttf differ diff --git a/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.fee66e71.woff b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.fee66e71.woff new file mode 100644 index 0000000000..400014a4b0 Binary files /dev/null and b/yudao-server/src/main/resources/admin-ui/static/fonts/fontawesome-webfont.fee66e71.woff differ diff --git a/yudao-admin-ui/src/assets/401_images/401.gif b/yudao-server/src/main/resources/admin-ui/static/img/401.089007e7.gif similarity index 100% rename from yudao-admin-ui/src/assets/401_images/401.gif rename to yudao-server/src/main/resources/admin-ui/static/img/401.089007e7.gif diff --git a/yudao-admin-ui/src/assets/404_images/404.png b/yudao-server/src/main/resources/admin-ui/static/img/404.a57b6f31.png similarity index 100% rename from yudao-admin-ui/src/assets/404_images/404.png rename to yudao-server/src/main/resources/admin-ui/static/img/404.a57b6f31.png diff --git a/yudao-admin-ui/src/assets/404_images/404_cloud.png b/yudao-server/src/main/resources/admin-ui/static/img/404_cloud.0f4bc32b.png similarity index 100% rename from yudao-admin-ui/src/assets/404_images/404_cloud.png rename to yudao-server/src/main/resources/admin-ui/static/img/404_cloud.0f4bc32b.png diff --git a/yudao-server/src/main/resources/admin-ui/static/img/bpmn.1381b44e.svg b/yudao-server/src/main/resources/admin-ui/static/img/bpmn.1381b44e.svg new file mode 100644 index 0000000000..00a316260c --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/img/bpmn.1381b44e.svg @@ -0,0 +1,224 @@ + + + +camunda Services GmbH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yudao-admin-ui/src/assets/icons/svg/button.svg b/yudao-server/src/main/resources/admin-ui/static/img/button.43a072f1.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/button.svg rename to yudao-server/src/main/resources/admin-ui/static/img/button.43a072f1.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/cascader.svg b/yudao-server/src/main/resources/admin-ui/static/img/cascader.af4b06f5.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/cascader.svg rename to yudao-server/src/main/resources/admin-ui/static/img/cascader.af4b06f5.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/checkbox.svg b/yudao-server/src/main/resources/admin-ui/static/img/checkbox.33950d05.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/checkbox.svg rename to yudao-server/src/main/resources/admin-ui/static/img/checkbox.33950d05.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/color.svg b/yudao-server/src/main/resources/admin-ui/static/img/color.d6e1d0d9.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/color.svg rename to yudao-server/src/main/resources/admin-ui/static/img/color.d6e1d0d9.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/component.svg b/yudao-server/src/main/resources/admin-ui/static/img/component.a69885f8.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/component.svg rename to yudao-server/src/main/resources/admin-ui/static/img/component.a69885f8.svg diff --git a/yudao-admin-ui/src/assets/images/dark.svg b/yudao-server/src/main/resources/admin-ui/static/img/dark.d0efa020.svg similarity index 100% rename from yudao-admin-ui/src/assets/images/dark.svg rename to yudao-server/src/main/resources/admin-ui/static/img/dark.d0efa020.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/date-range.svg b/yudao-server/src/main/resources/admin-ui/static/img/date-range.21c0ab78.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/date-range.svg rename to yudao-server/src/main/resources/admin-ui/static/img/date-range.21c0ab78.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/date.svg b/yudao-server/src/main/resources/admin-ui/static/img/date.43878da9.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/date.svg rename to yudao-server/src/main/resources/admin-ui/static/img/date.43878da9.svg diff --git a/yudao-server/src/main/resources/admin-ui/static/img/fontawesome-webfont.acf3dcb7.svg b/yudao-server/src/main/resources/admin-ui/static/img/fontawesome-webfont.acf3dcb7.svg new file mode 100644 index 0000000000..855c845e53 --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/img/fontawesome-webfont.acf3dcb7.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/yudao-admin-ui/src/assets/icons/svg/input.svg b/yudao-server/src/main/resources/admin-ui/static/img/input.fd627960.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/input.svg rename to yudao-server/src/main/resources/admin-ui/static/img/input.fd627960.svg diff --git a/yudao-admin-ui/src/assets/images/light.svg b/yudao-server/src/main/resources/admin-ui/static/img/light.ccbb6cbd.svg similarity index 100% rename from yudao-admin-ui/src/assets/images/light.svg rename to yudao-server/src/main/resources/admin-ui/static/img/light.ccbb6cbd.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/number.svg b/yudao-server/src/main/resources/admin-ui/static/img/number.7e0faaa5.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/number.svg rename to yudao-server/src/main/resources/admin-ui/static/img/number.7e0faaa5.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/password.svg b/yudao-server/src/main/resources/admin-ui/static/img/password.9173da92.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/password.svg rename to yudao-server/src/main/resources/admin-ui/static/img/password.9173da92.svg diff --git a/yudao-admin-ui/src/assets/images/profile.jpg b/yudao-server/src/main/resources/admin-ui/static/img/profile.473f5971.jpg similarity index 100% rename from yudao-admin-ui/src/assets/images/profile.jpg rename to yudao-server/src/main/resources/admin-ui/static/img/profile.473f5971.jpg diff --git a/yudao-admin-ui/src/assets/icons/svg/radio.svg b/yudao-server/src/main/resources/admin-ui/static/img/radio.1db061a7.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/radio.svg rename to yudao-server/src/main/resources/admin-ui/static/img/radio.1db061a7.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/rate.svg b/yudao-server/src/main/resources/admin-ui/static/img/rate.d8284c44.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/rate.svg rename to yudao-server/src/main/resources/admin-ui/static/img/rate.d8284c44.svg diff --git a/yudao-admin-ui/src/icons/svg/rich-text.svg b/yudao-server/src/main/resources/admin-ui/static/img/rich-text.e05415fa.svg similarity index 100% rename from yudao-admin-ui/src/icons/svg/rich-text.svg rename to yudao-server/src/main/resources/admin-ui/static/img/rich-text.e05415fa.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/row.svg b/yudao-server/src/main/resources/admin-ui/static/img/row.88cc2b15.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/row.svg rename to yudao-server/src/main/resources/admin-ui/static/img/row.88cc2b15.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/select.svg b/yudao-server/src/main/resources/admin-ui/static/img/select.be2885c0.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/select.svg rename to yudao-server/src/main/resources/admin-ui/static/img/select.be2885c0.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/slider.svg b/yudao-server/src/main/resources/admin-ui/static/img/slider.dca17dd6.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/slider.svg rename to yudao-server/src/main/resources/admin-ui/static/img/slider.dca17dd6.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/switch.svg b/yudao-server/src/main/resources/admin-ui/static/img/switch.67ff45e5.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/switch.svg rename to yudao-server/src/main/resources/admin-ui/static/img/switch.67ff45e5.svg diff --git a/yudao-admin-ui/src/icons/svg/table.svg b/yudao-server/src/main/resources/admin-ui/static/img/table.b3930c2c.svg similarity index 100% rename from yudao-admin-ui/src/icons/svg/table.svg rename to yudao-server/src/main/resources/admin-ui/static/img/table.b3930c2c.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/textarea.svg b/yudao-server/src/main/resources/admin-ui/static/img/textarea.6a19873e.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/textarea.svg rename to yudao-server/src/main/resources/admin-ui/static/img/textarea.6a19873e.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/time-range.svg b/yudao-server/src/main/resources/admin-ui/static/img/time-range.4a869bcb.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/time-range.svg rename to yudao-server/src/main/resources/admin-ui/static/img/time-range.4a869bcb.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/time.svg b/yudao-server/src/main/resources/admin-ui/static/img/time.809df2f6.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/time.svg rename to yudao-server/src/main/resources/admin-ui/static/img/time.809df2f6.svg diff --git a/yudao-admin-ui/src/assets/icons/svg/upload.svg b/yudao-server/src/main/resources/admin-ui/static/img/upload.84d5b598.svg similarity index 100% rename from yudao-admin-ui/src/assets/icons/svg/upload.svg rename to yudao-server/src/main/resources/admin-ui/static/img/upload.84d5b598.svg diff --git a/yudao-server/src/main/resources/admin-ui/static/js/0.js b/yudao-server/src/main/resources/admin-ui/static/js/0.js new file mode 100644 index 0000000000..7aa2c3b870 --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/js/0.js @@ -0,0 +1,170 @@ +(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{ + +/***/ "./node_modules/@vue/babel-helper-vue-jsx-merge-props/dist/helper.js": +/*!***************************************************************************!*\ + !*** ./node_modules/@vue/babel-helper-vue-jsx-merge-props/dist/helper.js ***! + \***************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("function _extends(){return _extends=Object.assign||function(a){for(var b,c=1;c 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n mouseDownHandler.call.apply(mouseDownHandler, [this, evt].concat(args));\n }\n };\n}\n// CONCATENATED MODULE: ./src/utils/scrollIntoView.js\nfunction scrollIntoView($scrollingEl, $focusedEl) {\n var scrollingReact = $scrollingEl.getBoundingClientRect();\n var focusedRect = $focusedEl.getBoundingClientRect();\n var overScroll = $focusedEl.offsetHeight / 3;\n\n if (focusedRect.bottom + overScroll > scrollingReact.bottom) {\n $scrollingEl.scrollTop = Math.min($focusedEl.offsetTop + $focusedEl.clientHeight - $scrollingEl.offsetHeight + overScroll, $scrollingEl.scrollHeight);\n } else if (focusedRect.top - overScroll < scrollingReact.top) {\n $scrollingEl.scrollTop = Math.max($focusedEl.offsetTop - overScroll, 0);\n }\n}\n// EXTERNAL MODULE: external \"lodash/debounce\"\nvar debounce_ = __webpack_require__(5);\nvar debounce_default = /*#__PURE__*/__webpack_require__.n(debounce_);\n\n// CONCATENATED MODULE: ./src/utils/debounce.js\n\n// EXTERNAL MODULE: external \"watch-size\"\nvar external_watch_size_ = __webpack_require__(6);\nvar external_watch_size_default = /*#__PURE__*/__webpack_require__.n(external_watch_size_);\n\n// CONCATENATED MODULE: ./src/utils/removeFromArray.js\nfunction removeFromArray(arr, elem) {\n var idx = arr.indexOf(elem);\n if (idx !== -1) arr.splice(idx, 1);\n}\n// CONCATENATED MODULE: ./src/utils/watchSize.js\n\n\nvar intervalId;\nvar registered = [];\nvar INTERVAL_DURATION = 100;\n\nfunction run() {\n intervalId = setInterval(function () {\n registered.forEach(test);\n }, INTERVAL_DURATION);\n}\n\nfunction stop() {\n clearInterval(intervalId);\n intervalId = null;\n}\n\nfunction test(item) {\n var $el = item.$el,\n listener = item.listener,\n lastWidth = item.lastWidth,\n lastHeight = item.lastHeight;\n var width = $el.offsetWidth;\n var height = $el.offsetHeight;\n\n if (lastWidth !== width || lastHeight !== height) {\n item.lastWidth = width;\n item.lastHeight = height;\n listener({\n width: width,\n height: height\n });\n }\n}\n\nfunction watchSizeForIE9($el, listener) {\n var item = {\n $el: $el,\n listener: listener,\n lastWidth: null,\n lastHeight: null\n };\n\n var unwatch = function unwatch() {\n removeFromArray(registered, item);\n if (!registered.length) stop();\n };\n\n registered.push(item);\n test(item);\n run();\n return unwatch;\n}\n\nfunction watchSize($el, listener) {\n var isIE9 = document.documentMode === 9;\n var locked = true;\n\n var wrappedListener = function wrappedListener() {\n return locked || listener.apply(void 0, arguments);\n };\n\n var implementation = isIE9 ? watchSizeForIE9 : external_watch_size_default.a;\n var removeSizeWatcher = implementation($el, wrappedListener);\n locked = false;\n return removeSizeWatcher;\n}\n// CONCATENATED MODULE: ./src/utils/setupResizeAndScrollEventListeners.js\nfunction findScrollParents($el) {\n var $scrollParents = [];\n var $parent = $el.parentNode;\n\n while ($parent && $parent.nodeName !== 'BODY' && $parent.nodeType === document.ELEMENT_NODE) {\n if (isScrollElment($parent)) $scrollParents.push($parent);\n $parent = $parent.parentNode;\n }\n\n $scrollParents.push(window);\n return $scrollParents;\n}\n\nfunction isScrollElment($el) {\n var _getComputedStyle = getComputedStyle($el),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /(auto|scroll|overlay)/.test(overflow + overflowY + overflowX);\n}\n\nfunction setupResizeAndScrollEventListeners($el, listener) {\n var $scrollParents = findScrollParents($el);\n window.addEventListener('resize', listener, {\n passive: true\n });\n $scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', listener, {\n passive: true\n });\n });\n return function removeEventListeners() {\n window.removeEventListener('resize', listener, {\n passive: true\n });\n $scrollParents.forEach(function ($scrollParent) {\n $scrollParent.removeEventListener('scroll', listener, {\n passive: true\n });\n });\n };\n}\n// CONCATENATED MODULE: ./src/utils/isNaN.js\nfunction isNaN_isNaN(x) {\n return x !== x;\n}\n// EXTERNAL MODULE: external \"is-promise\"\nvar external_is_promise_ = __webpack_require__(7);\nvar external_is_promise_default = /*#__PURE__*/__webpack_require__.n(external_is_promise_);\n\n// CONCATENATED MODULE: ./src/utils/isPromise.js\n\n// EXTERNAL MODULE: external \"lodash/once\"\nvar once_ = __webpack_require__(8);\nvar once_default = /*#__PURE__*/__webpack_require__.n(once_);\n\n// CONCATENATED MODULE: ./src/utils/once.js\n\n// EXTERNAL MODULE: external \"lodash/identity\"\nvar identity_ = __webpack_require__(9);\nvar identity_default = /*#__PURE__*/__webpack_require__.n(identity_);\n\n// CONCATENATED MODULE: ./src/utils/identity.js\n\n// EXTERNAL MODULE: external \"lodash/constant\"\nvar constant_ = __webpack_require__(10);\nvar constant_default = /*#__PURE__*/__webpack_require__.n(constant_);\n\n// CONCATENATED MODULE: ./src/utils/constant.js\n\n// CONCATENATED MODULE: ./src/utils/createMap.js\nvar createMap = function createMap() {\n return Object.create(null);\n};\n// EXTERNAL MODULE: external \"@babel/runtime/helpers/typeof\"\nvar typeof_ = __webpack_require__(11);\nvar typeof_default = /*#__PURE__*/__webpack_require__.n(typeof_);\n\n// CONCATENATED MODULE: ./src/utils/deepExtend.js\n\n\nfunction isPlainObject(value) {\n if (value == null || typeof_default()(value) !== 'object') return false;\n return Object.getPrototypeOf(value) === Object.prototype;\n}\n\nfunction copy(obj, key, value) {\n if (isPlainObject(value)) {\n obj[key] || (obj[key] = {});\n deepExtend(obj[key], value);\n } else {\n obj[key] = value;\n }\n}\n\nfunction deepExtend(target, source) {\n if (isPlainObject(source)) {\n var keys = Object.keys(source);\n\n for (var i = 0, len = keys.length; i < len; i++) {\n copy(target, keys[i], source[keys[i]]);\n }\n }\n\n return target;\n}\n// EXTERNAL MODULE: external \"lodash/last\"\nvar last_ = __webpack_require__(12);\nvar last_default = /*#__PURE__*/__webpack_require__.n(last_);\n\n// CONCATENATED MODULE: ./src/utils/last.js\n\n// CONCATENATED MODULE: ./src/utils/includes.js\nfunction includes(arrOrStr, elem) {\n return arrOrStr.indexOf(elem) !== -1;\n}\n// CONCATENATED MODULE: ./src/utils/find.js\nfunction find(arr, predicate, ctx) {\n for (var i = 0, len = arr.length; i < len; i++) {\n if (predicate.call(ctx, arr[i], i, arr)) return arr[i];\n }\n\n return undefined;\n}\n// CONCATENATED MODULE: ./src/utils/quickDiff.js\nfunction quickDiff(arrA, arrB) {\n if (arrA.length !== arrB.length) return true;\n\n for (var i = 0; i < arrA.length; i++) {\n if (arrA[i] !== arrB[i]) return true;\n }\n\n return false;\n}\n// CONCATENATED MODULE: ./src/utils/index.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// CONCATENATED MODULE: ./src/constants.js\nvar NO_PARENT_NODE = null;\nvar UNCHECKED = 0;\nvar INDETERMINATE = 1;\nvar CHECKED = 2;\nvar ALL_CHILDREN = 'ALL_CHILDREN';\nvar ALL_DESCENDANTS = 'ALL_DESCENDANTS';\nvar LEAF_CHILDREN = 'LEAF_CHILDREN';\nvar LEAF_DESCENDANTS = 'LEAF_DESCENDANTS';\nvar LOAD_ROOT_OPTIONS = 'LOAD_ROOT_OPTIONS';\nvar LOAD_CHILDREN_OPTIONS = 'LOAD_CHILDREN_OPTIONS';\nvar ASYNC_SEARCH = 'ASYNC_SEARCH';\nvar ALL = 'ALL';\nvar BRANCH_PRIORITY = 'BRANCH_PRIORITY';\nvar LEAF_PRIORITY = 'LEAF_PRIORITY';\nvar ALL_WITH_INDETERMINATE = 'ALL_WITH_INDETERMINATE';\nvar ORDER_SELECTED = 'ORDER_SELECTED';\nvar LEVEL = 'LEVEL';\nvar INDEX = 'INDEX';\nvar KEY_CODES = {\n BACKSPACE: 8,\n ENTER: 13,\n ESCAPE: 27,\n END: 35,\n HOME: 36,\n ARROW_LEFT: 37,\n ARROW_UP: 38,\n ARROW_RIGHT: 39,\n ARROW_DOWN: 40,\n DELETE: 46\n};\nvar INPUT_DEBOUNCE_DELAY = false ? undefined : 200;\nvar MIN_INPUT_WIDTH = 5;\nvar MENU_BUFFER = 40;\n// CONCATENATED MODULE: ./src/mixins/treeselectMixin.js\n\n\n\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { defineProperty_default()(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\n\n\n\n\nfunction sortValueByIndex(a, b) {\n var i = 0;\n\n do {\n if (a.level < i) return -1;\n if (b.level < i) return 1;\n if (a.index[i] !== b.index[i]) return a.index[i] - b.index[i];\n i++;\n } while (true);\n}\n\nfunction sortValueByLevel(a, b) {\n return a.level === b.level ? sortValueByIndex(a, b) : a.level - b.level;\n}\n\nfunction createAsyncOptionsStates() {\n return {\n isLoaded: false,\n isLoading: false,\n loadingError: ''\n };\n}\n\nfunction stringifyOptionPropValue(value) {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' && !isNaN_isNaN(value)) return value + '';\n return '';\n}\n\nfunction match(enableFuzzyMatch, needle, haystack) {\n return enableFuzzyMatch ? external_fuzzysearch_default()(needle, haystack) : includes(haystack, needle);\n}\n\nfunction getErrorMessage(err) {\n return err.message || String(err);\n}\n\nvar instanceId = 0;\n/* harmony default export */ var treeselectMixin = ({\n provide: function provide() {\n return {\n instance: this\n };\n },\n props: {\n allowClearingDisabled: {\n type: Boolean,\n default: false\n },\n allowSelectingDisabledDescendants: {\n type: Boolean,\n default: false\n },\n alwaysOpen: {\n type: Boolean,\n default: false\n },\n appendToBody: {\n type: Boolean,\n default: false\n },\n async: {\n type: Boolean,\n default: false\n },\n autoFocus: {\n type: Boolean,\n default: false\n },\n autoLoadRootOptions: {\n type: Boolean,\n default: true\n },\n autoDeselectAncestors: {\n type: Boolean,\n default: false\n },\n autoDeselectDescendants: {\n type: Boolean,\n default: false\n },\n autoSelectAncestors: {\n type: Boolean,\n default: false\n },\n autoSelectDescendants: {\n type: Boolean,\n default: false\n },\n backspaceRemoves: {\n type: Boolean,\n default: true\n },\n beforeClearAll: {\n type: Function,\n default: constant_default()(true)\n },\n branchNodesFirst: {\n type: Boolean,\n default: false\n },\n cacheOptions: {\n type: Boolean,\n default: true\n },\n clearable: {\n type: Boolean,\n default: true\n },\n clearAllText: {\n type: String,\n default: 'Clear all'\n },\n clearOnSelect: {\n type: Boolean,\n default: false\n },\n clearValueText: {\n type: String,\n default: 'Clear value'\n },\n closeOnSelect: {\n type: Boolean,\n default: true\n },\n defaultExpandLevel: {\n type: Number,\n default: 0\n },\n defaultOptions: {\n default: false\n },\n deleteRemoves: {\n type: Boolean,\n default: true\n },\n delimiter: {\n type: String,\n default: ','\n },\n flattenSearchResults: {\n type: Boolean,\n default: false\n },\n disableBranchNodes: {\n type: Boolean,\n default: false\n },\n disabled: {\n type: Boolean,\n default: false\n },\n disableFuzzyMatching: {\n type: Boolean,\n default: false\n },\n flat: {\n type: Boolean,\n default: false\n },\n instanceId: {\n default: function _default() {\n return \"\".concat(instanceId++, \"$$\");\n },\n type: [String, Number]\n },\n joinValues: {\n type: Boolean,\n default: false\n },\n limit: {\n type: Number,\n default: Infinity\n },\n limitText: {\n type: Function,\n default: function limitTextDefault(count) {\n return \"and \".concat(count, \" more\");\n }\n },\n loadingText: {\n type: String,\n default: 'Loading...'\n },\n loadOptions: {\n type: Function\n },\n matchKeys: {\n type: Array,\n default: constant_default()(['label'])\n },\n maxHeight: {\n type: Number,\n default: 300\n },\n multiple: {\n type: Boolean,\n default: false\n },\n name: {\n type: String\n },\n noChildrenText: {\n type: String,\n default: 'No sub-options.'\n },\n noOptionsText: {\n type: String,\n default: 'No options available.'\n },\n noResultsText: {\n type: String,\n default: 'No results found...'\n },\n normalizer: {\n type: Function,\n default: identity_default.a\n },\n openDirection: {\n type: String,\n default: 'auto',\n validator: function validator(value) {\n var acceptableValues = ['auto', 'top', 'bottom', 'above', 'below'];\n return includes(acceptableValues, value);\n }\n },\n openOnClick: {\n type: Boolean,\n default: true\n },\n openOnFocus: {\n type: Boolean,\n default: false\n },\n options: {\n type: Array\n },\n placeholder: {\n type: String,\n default: 'Select...'\n },\n required: {\n type: Boolean,\n default: false\n },\n retryText: {\n type: String,\n default: 'Retry?'\n },\n retryTitle: {\n type: String,\n default: 'Click to retry'\n },\n searchable: {\n type: Boolean,\n default: true\n },\n searchNested: {\n type: Boolean,\n default: false\n },\n searchPromptText: {\n type: String,\n default: 'Type to search...'\n },\n showCount: {\n type: Boolean,\n default: false\n },\n showCountOf: {\n type: String,\n default: ALL_CHILDREN,\n validator: function validator(value) {\n var acceptableValues = [ALL_CHILDREN, ALL_DESCENDANTS, LEAF_CHILDREN, LEAF_DESCENDANTS];\n return includes(acceptableValues, value);\n }\n },\n showCountOnSearch: null,\n sortValueBy: {\n type: String,\n default: ORDER_SELECTED,\n validator: function validator(value) {\n var acceptableValues = [ORDER_SELECTED, LEVEL, INDEX];\n return includes(acceptableValues, value);\n }\n },\n tabIndex: {\n type: Number,\n default: 0\n },\n value: null,\n valueConsistsOf: {\n type: String,\n default: BRANCH_PRIORITY,\n validator: function validator(value) {\n var acceptableValues = [ALL, BRANCH_PRIORITY, LEAF_PRIORITY, ALL_WITH_INDETERMINATE];\n return includes(acceptableValues, value);\n }\n },\n valueFormat: {\n type: String,\n default: 'id'\n },\n zIndex: {\n type: [Number, String],\n default: 999\n }\n },\n data: function data() {\n return {\n trigger: {\n isFocused: false,\n searchQuery: ''\n },\n menu: {\n isOpen: false,\n current: null,\n lastScrollPosition: 0,\n placement: 'bottom'\n },\n forest: {\n normalizedOptions: [],\n nodeMap: createMap(),\n checkedStateMap: createMap(),\n selectedNodeIds: this.extractCheckedNodeIdsFromValue(),\n selectedNodeMap: createMap()\n },\n rootOptionsStates: createAsyncOptionsStates(),\n localSearch: {\n active: false,\n noResults: true,\n countMap: createMap()\n },\n remoteSearch: createMap()\n };\n },\n computed: {\n selectedNodes: function selectedNodes() {\n return this.forest.selectedNodeIds.map(this.getNode);\n },\n internalValue: function internalValue() {\n var _this = this;\n\n var internalValue;\n\n if (this.single || this.flat || this.disableBranchNodes || this.valueConsistsOf === ALL) {\n internalValue = this.forest.selectedNodeIds.slice();\n } else if (this.valueConsistsOf === BRANCH_PRIORITY) {\n internalValue = this.forest.selectedNodeIds.filter(function (id) {\n var node = _this.getNode(id);\n\n if (node.isRootNode) return true;\n return !_this.isSelected(node.parentNode);\n });\n } else if (this.valueConsistsOf === LEAF_PRIORITY) {\n internalValue = this.forest.selectedNodeIds.filter(function (id) {\n var node = _this.getNode(id);\n\n if (node.isLeaf) return true;\n return node.children.length === 0;\n });\n } else if (this.valueConsistsOf === ALL_WITH_INDETERMINATE) {\n var _internalValue;\n\n var indeterminateNodeIds = [];\n internalValue = this.forest.selectedNodeIds.slice();\n this.selectedNodes.forEach(function (selectedNode) {\n selectedNode.ancestors.forEach(function (ancestor) {\n if (includes(indeterminateNodeIds, ancestor.id)) return;\n if (includes(internalValue, ancestor.id)) return;\n indeterminateNodeIds.push(ancestor.id);\n });\n });\n\n (_internalValue = internalValue).push.apply(_internalValue, indeterminateNodeIds);\n }\n\n if (this.sortValueBy === LEVEL) {\n internalValue.sort(function (a, b) {\n return sortValueByLevel(_this.getNode(a), _this.getNode(b));\n });\n } else if (this.sortValueBy === INDEX) {\n internalValue.sort(function (a, b) {\n return sortValueByIndex(_this.getNode(a), _this.getNode(b));\n });\n }\n\n return internalValue;\n },\n hasValue: function hasValue() {\n return this.internalValue.length > 0;\n },\n single: function single() {\n return !this.multiple;\n },\n visibleOptionIds: function visibleOptionIds() {\n var _this2 = this;\n\n var visibleOptionIds = [];\n this.traverseAllNodesByIndex(function (node) {\n if (!_this2.localSearch.active || _this2.shouldOptionBeIncludedInSearchResult(node)) {\n visibleOptionIds.push(node.id);\n }\n\n if (node.isBranch && !_this2.shouldExpand(node)) {\n return false;\n }\n });\n return visibleOptionIds;\n },\n hasVisibleOptions: function hasVisibleOptions() {\n return this.visibleOptionIds.length !== 0;\n },\n showCountOnSearchComputed: function showCountOnSearchComputed() {\n return typeof this.showCountOnSearch === 'boolean' ? this.showCountOnSearch : this.showCount;\n },\n hasBranchNodes: function hasBranchNodes() {\n return this.forest.normalizedOptions.some(function (rootNode) {\n return rootNode.isBranch;\n });\n },\n shouldFlattenOptions: function shouldFlattenOptions() {\n return this.localSearch.active && this.flattenSearchResults;\n }\n },\n watch: {\n alwaysOpen: function alwaysOpen(newValue) {\n if (newValue) this.openMenu();else this.closeMenu();\n },\n branchNodesFirst: function branchNodesFirst() {\n this.initialize();\n },\n disabled: function disabled(newValue) {\n if (newValue && this.menu.isOpen) this.closeMenu();else if (!newValue && !this.menu.isOpen && this.alwaysOpen) this.openMenu();\n },\n flat: function flat() {\n this.initialize();\n },\n internalValue: function internalValue(newValue, oldValue) {\n var hasChanged = quickDiff(newValue, oldValue);\n if (hasChanged) this.$emit('input', this.getValue(), this.getInstanceId());\n },\n matchKeys: function matchKeys() {\n this.initialize();\n },\n multiple: function multiple(newValue) {\n if (newValue) this.buildForestState();\n },\n options: {\n handler: function handler() {\n if (this.async) return;\n this.initialize();\n this.rootOptionsStates.isLoaded = Array.isArray(this.options);\n },\n deep: true,\n immediate: true\n },\n 'trigger.searchQuery': function triggerSearchQuery() {\n if (this.async) {\n this.handleRemoteSearch();\n } else {\n this.handleLocalSearch();\n }\n\n this.$emit('search-change', this.trigger.searchQuery, this.getInstanceId());\n },\n value: function value() {\n var nodeIdsFromValue = this.extractCheckedNodeIdsFromValue();\n var hasChanged = quickDiff(nodeIdsFromValue, this.internalValue);\n if (hasChanged) this.fixSelectedNodeIds(nodeIdsFromValue);\n }\n },\n methods: {\n verifyProps: function verifyProps() {\n var _this3 = this;\n\n warning_warning(function () {\n return _this3.async ? _this3.searchable : true;\n }, function () {\n return 'For async search mode, the value of \"searchable\" prop must be true.';\n });\n\n if (this.options == null && !this.loadOptions) {\n warning_warning(function () {\n return false;\n }, function () {\n return 'Are you meant to dynamically load options? You need to use \"loadOptions\" prop.';\n });\n }\n\n if (this.flat) {\n warning_warning(function () {\n return _this3.multiple;\n }, function () {\n return 'You are using flat mode. But you forgot to add \"multiple=true\"?';\n });\n }\n\n if (!this.flat) {\n var propNames = ['autoSelectAncestors', 'autoSelectDescendants', 'autoDeselectAncestors', 'autoDeselectDescendants'];\n propNames.forEach(function (propName) {\n warning_warning(function () {\n return !_this3[propName];\n }, function () {\n return \"\\\"\".concat(propName, \"\\\" only applies to flat mode.\");\n });\n });\n }\n },\n resetFlags: function resetFlags() {\n this._blurOnSelect = false;\n },\n initialize: function initialize() {\n var options = this.async ? this.getRemoteSearchEntry().options : this.options;\n\n if (Array.isArray(options)) {\n var prevNodeMap = this.forest.nodeMap;\n this.forest.nodeMap = createMap();\n this.keepDataOfSelectedNodes(prevNodeMap);\n this.forest.normalizedOptions = this.normalize(NO_PARENT_NODE, options, prevNodeMap);\n this.fixSelectedNodeIds(this.internalValue);\n } else {\n this.forest.normalizedOptions = [];\n }\n },\n getInstanceId: function getInstanceId() {\n return this.instanceId == null ? this.id : this.instanceId;\n },\n getValue: function getValue() {\n var _this4 = this;\n\n if (this.valueFormat === 'id') {\n return this.multiple ? this.internalValue.slice() : this.internalValue[0];\n }\n\n var rawNodes = this.internalValue.map(function (id) {\n return _this4.getNode(id).raw;\n });\n return this.multiple ? rawNodes : rawNodes[0];\n },\n getNode: function getNode(nodeId) {\n warning_warning(function () {\n return nodeId != null;\n }, function () {\n return \"Invalid node id: \".concat(nodeId);\n });\n if (nodeId == null) return null;\n return nodeId in this.forest.nodeMap ? this.forest.nodeMap[nodeId] : this.createFallbackNode(nodeId);\n },\n createFallbackNode: function createFallbackNode(id) {\n var raw = this.extractNodeFromValue(id);\n var label = this.enhancedNormalizer(raw).label || \"\".concat(id, \" (unknown)\");\n var fallbackNode = {\n id: id,\n label: label,\n ancestors: [],\n parentNode: NO_PARENT_NODE,\n isFallbackNode: true,\n isRootNode: true,\n isLeaf: true,\n isBranch: false,\n isDisabled: false,\n isNew: false,\n index: [-1],\n level: 0,\n raw: raw\n };\n return this.$set(this.forest.nodeMap, id, fallbackNode);\n },\n extractCheckedNodeIdsFromValue: function extractCheckedNodeIdsFromValue() {\n var _this5 = this;\n\n if (this.value == null) return [];\n\n if (this.valueFormat === 'id') {\n return this.multiple ? this.value.slice() : [this.value];\n }\n\n return (this.multiple ? this.value : [this.value]).map(function (node) {\n return _this5.enhancedNormalizer(node);\n }).map(function (node) {\n return node.id;\n });\n },\n extractNodeFromValue: function extractNodeFromValue(id) {\n var _this6 = this;\n\n var defaultNode = {\n id: id\n };\n\n if (this.valueFormat === 'id') {\n return defaultNode;\n }\n\n var valueArray = this.multiple ? Array.isArray(this.value) ? this.value : [] : this.value ? [this.value] : [];\n var matched = find(valueArray, function (node) {\n return node && _this6.enhancedNormalizer(node).id === id;\n });\n return matched || defaultNode;\n },\n fixSelectedNodeIds: function fixSelectedNodeIds(nodeIdListOfPrevValue) {\n var _this7 = this;\n\n var nextSelectedNodeIds = [];\n\n if (this.single || this.flat || this.disableBranchNodes || this.valueConsistsOf === ALL) {\n nextSelectedNodeIds = nodeIdListOfPrevValue;\n } else if (this.valueConsistsOf === BRANCH_PRIORITY) {\n nodeIdListOfPrevValue.forEach(function (nodeId) {\n nextSelectedNodeIds.push(nodeId);\n\n var node = _this7.getNode(nodeId);\n\n if (node.isBranch) _this7.traverseDescendantsBFS(node, function (descendant) {\n nextSelectedNodeIds.push(descendant.id);\n });\n });\n } else if (this.valueConsistsOf === LEAF_PRIORITY) {\n var map = createMap();\n var queue = nodeIdListOfPrevValue.slice();\n\n while (queue.length) {\n var nodeId = queue.shift();\n var node = this.getNode(nodeId);\n nextSelectedNodeIds.push(nodeId);\n if (node.isRootNode) continue;\n if (!(node.parentNode.id in map)) map[node.parentNode.id] = node.parentNode.children.length;\n if (--map[node.parentNode.id] === 0) queue.push(node.parentNode.id);\n }\n } else if (this.valueConsistsOf === ALL_WITH_INDETERMINATE) {\n var _map = createMap();\n\n var _queue = nodeIdListOfPrevValue.filter(function (nodeId) {\n var node = _this7.getNode(nodeId);\n\n return node.isLeaf || node.children.length === 0;\n });\n\n while (_queue.length) {\n var _nodeId = _queue.shift();\n\n var _node = this.getNode(_nodeId);\n\n nextSelectedNodeIds.push(_nodeId);\n if (_node.isRootNode) continue;\n if (!(_node.parentNode.id in _map)) _map[_node.parentNode.id] = _node.parentNode.children.length;\n if (--_map[_node.parentNode.id] === 0) _queue.push(_node.parentNode.id);\n }\n }\n\n var hasChanged = quickDiff(this.forest.selectedNodeIds, nextSelectedNodeIds);\n if (hasChanged) this.forest.selectedNodeIds = nextSelectedNodeIds;\n this.buildForestState();\n },\n keepDataOfSelectedNodes: function keepDataOfSelectedNodes(prevNodeMap) {\n var _this8 = this;\n\n this.forest.selectedNodeIds.forEach(function (id) {\n if (!prevNodeMap[id]) return;\n\n var node = _objectSpread({}, prevNodeMap[id], {\n isFallbackNode: true\n });\n\n _this8.$set(_this8.forest.nodeMap, id, node);\n });\n },\n isSelected: function isSelected(node) {\n return this.forest.selectedNodeMap[node.id] === true;\n },\n traverseDescendantsBFS: function traverseDescendantsBFS(parentNode, callback) {\n if (!parentNode.isBranch) return;\n var queue = parentNode.children.slice();\n\n while (queue.length) {\n var currNode = queue[0];\n if (currNode.isBranch) queue.push.apply(queue, toConsumableArray_default()(currNode.children));\n callback(currNode);\n queue.shift();\n }\n },\n traverseDescendantsDFS: function traverseDescendantsDFS(parentNode, callback) {\n var _this9 = this;\n\n if (!parentNode.isBranch) return;\n parentNode.children.forEach(function (child) {\n _this9.traverseDescendantsDFS(child, callback);\n\n callback(child);\n });\n },\n traverseAllNodesDFS: function traverseAllNodesDFS(callback) {\n var _this10 = this;\n\n this.forest.normalizedOptions.forEach(function (rootNode) {\n _this10.traverseDescendantsDFS(rootNode, callback);\n\n callback(rootNode);\n });\n },\n traverseAllNodesByIndex: function traverseAllNodesByIndex(callback) {\n var walk = function walk(parentNode) {\n parentNode.children.forEach(function (child) {\n if (callback(child) !== false && child.isBranch) {\n walk(child);\n }\n });\n };\n\n walk({\n children: this.forest.normalizedOptions\n });\n },\n toggleClickOutsideEvent: function toggleClickOutsideEvent(enabled) {\n if (enabled) {\n document.addEventListener('mousedown', this.handleClickOutside, false);\n } else {\n document.removeEventListener('mousedown', this.handleClickOutside, false);\n }\n },\n getValueContainer: function getValueContainer() {\n return this.$refs.control.$refs['value-container'];\n },\n getInput: function getInput() {\n return this.getValueContainer().$refs.input;\n },\n focusInput: function focusInput() {\n this.getInput().focus();\n },\n blurInput: function blurInput() {\n this.getInput().blur();\n },\n handleMouseDown: onLeftClick(function handleMouseDown(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n if (this.disabled) return;\n var isClickedOnValueContainer = this.getValueContainer().$el.contains(evt.target);\n\n if (isClickedOnValueContainer && !this.menu.isOpen && (this.openOnClick || this.trigger.isFocused)) {\n this.openMenu();\n }\n\n if (this._blurOnSelect) {\n this.blurInput();\n } else {\n this.focusInput();\n }\n\n this.resetFlags();\n }),\n handleClickOutside: function handleClickOutside(evt) {\n if (this.$refs.wrapper && !this.$refs.wrapper.contains(evt.target)) {\n this.blurInput();\n this.closeMenu();\n }\n },\n handleLocalSearch: function handleLocalSearch() {\n var _this11 = this;\n\n var searchQuery = this.trigger.searchQuery;\n\n var done = function done() {\n return _this11.resetHighlightedOptionWhenNecessary(true);\n };\n\n if (!searchQuery) {\n this.localSearch.active = false;\n return done();\n }\n\n this.localSearch.active = true;\n this.localSearch.noResults = true;\n this.traverseAllNodesDFS(function (node) {\n if (node.isBranch) {\n var _this11$$set;\n\n node.isExpandedOnSearch = false;\n node.showAllChildrenOnSearch = false;\n node.isMatched = false;\n node.hasMatchedDescendants = false;\n\n _this11.$set(_this11.localSearch.countMap, node.id, (_this11$$set = {}, defineProperty_default()(_this11$$set, ALL_CHILDREN, 0), defineProperty_default()(_this11$$set, ALL_DESCENDANTS, 0), defineProperty_default()(_this11$$set, LEAF_CHILDREN, 0), defineProperty_default()(_this11$$set, LEAF_DESCENDANTS, 0), _this11$$set));\n }\n });\n var lowerCasedSearchQuery = searchQuery.trim().toLocaleLowerCase();\n var splitSearchQuery = lowerCasedSearchQuery.replace(/\\s+/g, ' ').split(' ');\n this.traverseAllNodesDFS(function (node) {\n if (_this11.searchNested && splitSearchQuery.length > 1) {\n node.isMatched = splitSearchQuery.every(function (filterValue) {\n return match(false, filterValue, node.nestedSearchLabel);\n });\n } else {\n node.isMatched = _this11.matchKeys.some(function (matchKey) {\n return match(!_this11.disableFuzzyMatching, lowerCasedSearchQuery, node.lowerCased[matchKey]);\n });\n }\n\n if (node.isMatched) {\n _this11.localSearch.noResults = false;\n node.ancestors.forEach(function (ancestor) {\n return _this11.localSearch.countMap[ancestor.id][ALL_DESCENDANTS]++;\n });\n if (node.isLeaf) node.ancestors.forEach(function (ancestor) {\n return _this11.localSearch.countMap[ancestor.id][LEAF_DESCENDANTS]++;\n });\n\n if (node.parentNode !== NO_PARENT_NODE) {\n _this11.localSearch.countMap[node.parentNode.id][ALL_CHILDREN] += 1;\n if (node.isLeaf) _this11.localSearch.countMap[node.parentNode.id][LEAF_CHILDREN] += 1;\n }\n }\n\n if ((node.isMatched || node.isBranch && node.isExpandedOnSearch) && node.parentNode !== NO_PARENT_NODE) {\n node.parentNode.isExpandedOnSearch = true;\n node.parentNode.hasMatchedDescendants = true;\n }\n });\n done();\n },\n handleRemoteSearch: function handleRemoteSearch() {\n var _this12 = this;\n\n var searchQuery = this.trigger.searchQuery;\n var entry = this.getRemoteSearchEntry();\n\n var done = function done() {\n _this12.initialize();\n\n _this12.resetHighlightedOptionWhenNecessary(true);\n };\n\n if ((searchQuery === '' || this.cacheOptions) && entry.isLoaded) {\n return done();\n }\n\n this.callLoadOptionsProp({\n action: ASYNC_SEARCH,\n args: {\n searchQuery: searchQuery\n },\n isPending: function isPending() {\n return entry.isLoading;\n },\n start: function start() {\n entry.isLoading = true;\n entry.isLoaded = false;\n entry.loadingError = '';\n },\n succeed: function succeed(options) {\n entry.isLoaded = true;\n entry.options = options;\n if (_this12.trigger.searchQuery === searchQuery) done();\n },\n fail: function fail(err) {\n entry.loadingError = getErrorMessage(err);\n },\n end: function end() {\n entry.isLoading = false;\n }\n });\n },\n getRemoteSearchEntry: function getRemoteSearchEntry() {\n var _this13 = this;\n\n var searchQuery = this.trigger.searchQuery;\n\n var entry = this.remoteSearch[searchQuery] || _objectSpread({}, createAsyncOptionsStates(), {\n options: []\n });\n\n this.$watch(function () {\n return entry.options;\n }, function () {\n if (_this13.trigger.searchQuery === searchQuery) _this13.initialize();\n }, {\n deep: true\n });\n\n if (searchQuery === '') {\n if (Array.isArray(this.defaultOptions)) {\n entry.options = this.defaultOptions;\n entry.isLoaded = true;\n return entry;\n } else if (this.defaultOptions !== true) {\n entry.isLoaded = true;\n return entry;\n }\n }\n\n if (!this.remoteSearch[searchQuery]) {\n this.$set(this.remoteSearch, searchQuery, entry);\n }\n\n return entry;\n },\n shouldExpand: function shouldExpand(node) {\n return this.localSearch.active ? node.isExpandedOnSearch : node.isExpanded;\n },\n shouldOptionBeIncludedInSearchResult: function shouldOptionBeIncludedInSearchResult(node) {\n if (node.isMatched) return true;\n if (node.isBranch && node.hasMatchedDescendants && !this.flattenSearchResults) return true;\n if (!node.isRootNode && node.parentNode.showAllChildrenOnSearch) return true;\n return false;\n },\n shouldShowOptionInMenu: function shouldShowOptionInMenu(node) {\n if (this.localSearch.active && !this.shouldOptionBeIncludedInSearchResult(node)) {\n return false;\n }\n\n return true;\n },\n getControl: function getControl() {\n return this.$refs.control.$el;\n },\n getMenu: function getMenu() {\n var ref = this.appendToBody ? this.$refs.portal.portalTarget : this;\n var $menu = ref.$refs.menu.$refs.menu;\n return $menu && $menu.nodeName !== '#comment' ? $menu : null;\n },\n setCurrentHighlightedOption: function setCurrentHighlightedOption(node) {\n var _this14 = this;\n\n var scroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var prev = this.menu.current;\n\n if (prev != null && prev in this.forest.nodeMap) {\n this.forest.nodeMap[prev].isHighlighted = false;\n }\n\n this.menu.current = node.id;\n node.isHighlighted = true;\n\n if (this.menu.isOpen && scroll) {\n var scrollToOption = function scrollToOption() {\n var $menu = _this14.getMenu();\n\n var $option = $menu.querySelector(\".vue-treeselect__option[data-id=\\\"\".concat(node.id, \"\\\"]\"));\n if ($option) scrollIntoView($menu, $option);\n };\n\n if (this.getMenu()) {\n scrollToOption();\n } else {\n this.$nextTick(scrollToOption);\n }\n }\n },\n resetHighlightedOptionWhenNecessary: function resetHighlightedOptionWhenNecessary() {\n var forceReset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n var current = this.menu.current;\n\n if (forceReset || current == null || !(current in this.forest.nodeMap) || !this.shouldShowOptionInMenu(this.getNode(current))) {\n this.highlightFirstOption();\n }\n },\n highlightFirstOption: function highlightFirstOption() {\n if (!this.hasVisibleOptions) return;\n var first = this.visibleOptionIds[0];\n this.setCurrentHighlightedOption(this.getNode(first));\n },\n highlightPrevOption: function highlightPrevOption() {\n if (!this.hasVisibleOptions) return;\n var prev = this.visibleOptionIds.indexOf(this.menu.current) - 1;\n if (prev === -1) return this.highlightLastOption();\n this.setCurrentHighlightedOption(this.getNode(this.visibleOptionIds[prev]));\n },\n highlightNextOption: function highlightNextOption() {\n if (!this.hasVisibleOptions) return;\n var next = this.visibleOptionIds.indexOf(this.menu.current) + 1;\n if (next === this.visibleOptionIds.length) return this.highlightFirstOption();\n this.setCurrentHighlightedOption(this.getNode(this.visibleOptionIds[next]));\n },\n highlightLastOption: function highlightLastOption() {\n if (!this.hasVisibleOptions) return;\n var last = last_default()(this.visibleOptionIds);\n this.setCurrentHighlightedOption(this.getNode(last));\n },\n resetSearchQuery: function resetSearchQuery() {\n this.trigger.searchQuery = '';\n },\n closeMenu: function closeMenu() {\n if (!this.menu.isOpen || !this.disabled && this.alwaysOpen) return;\n this.saveMenuScrollPosition();\n this.menu.isOpen = false;\n this.toggleClickOutsideEvent(false);\n this.resetSearchQuery();\n this.$emit('close', this.getValue(), this.getInstanceId());\n },\n openMenu: function openMenu() {\n if (this.disabled || this.menu.isOpen) return;\n this.menu.isOpen = true;\n this.$nextTick(this.resetHighlightedOptionWhenNecessary);\n this.$nextTick(this.restoreMenuScrollPosition);\n if (!this.options && !this.async) this.loadRootOptions();\n this.toggleClickOutsideEvent(true);\n this.$emit('open', this.getInstanceId());\n },\n toggleMenu: function toggleMenu() {\n if (this.menu.isOpen) {\n this.closeMenu();\n } else {\n this.openMenu();\n }\n },\n toggleExpanded: function toggleExpanded(node) {\n var nextState;\n\n if (this.localSearch.active) {\n nextState = node.isExpandedOnSearch = !node.isExpandedOnSearch;\n if (nextState) node.showAllChildrenOnSearch = true;\n } else {\n nextState = node.isExpanded = !node.isExpanded;\n }\n\n if (nextState && !node.childrenStates.isLoaded) {\n this.loadChildrenOptions(node);\n }\n },\n buildForestState: function buildForestState() {\n var _this15 = this;\n\n var selectedNodeMap = createMap();\n this.forest.selectedNodeIds.forEach(function (selectedNodeId) {\n selectedNodeMap[selectedNodeId] = true;\n });\n this.forest.selectedNodeMap = selectedNodeMap;\n var checkedStateMap = createMap();\n\n if (this.multiple) {\n this.traverseAllNodesByIndex(function (node) {\n checkedStateMap[node.id] = UNCHECKED;\n });\n this.selectedNodes.forEach(function (selectedNode) {\n checkedStateMap[selectedNode.id] = CHECKED;\n\n if (!_this15.flat && !_this15.disableBranchNodes) {\n selectedNode.ancestors.forEach(function (ancestorNode) {\n if (!_this15.isSelected(ancestorNode)) {\n checkedStateMap[ancestorNode.id] = INDETERMINATE;\n }\n });\n }\n });\n }\n\n this.forest.checkedStateMap = checkedStateMap;\n },\n enhancedNormalizer: function enhancedNormalizer(raw) {\n return _objectSpread({}, raw, {}, this.normalizer(raw, this.getInstanceId()));\n },\n normalize: function normalize(parentNode, nodes, prevNodeMap) {\n var _this16 = this;\n\n var normalizedOptions = nodes.map(function (node) {\n return [_this16.enhancedNormalizer(node), node];\n }).map(function (_ref, index) {\n var _ref2 = slicedToArray_default()(_ref, 2),\n node = _ref2[0],\n raw = _ref2[1];\n\n _this16.checkDuplication(node);\n\n _this16.verifyNodeShape(node);\n\n var id = node.id,\n label = node.label,\n children = node.children,\n isDefaultExpanded = node.isDefaultExpanded;\n var isRootNode = parentNode === NO_PARENT_NODE;\n var level = isRootNode ? 0 : parentNode.level + 1;\n var isBranch = Array.isArray(children) || children === null;\n var isLeaf = !isBranch;\n var isDisabled = !!node.isDisabled || !_this16.flat && !isRootNode && parentNode.isDisabled;\n var isNew = !!node.isNew;\n\n var lowerCased = _this16.matchKeys.reduce(function (prev, key) {\n return _objectSpread({}, prev, defineProperty_default()({}, key, stringifyOptionPropValue(node[key]).toLocaleLowerCase()));\n }, {});\n\n var nestedSearchLabel = isRootNode ? lowerCased.label : parentNode.nestedSearchLabel + ' ' + lowerCased.label;\n\n var normalized = _this16.$set(_this16.forest.nodeMap, id, createMap());\n\n _this16.$set(normalized, 'id', id);\n\n _this16.$set(normalized, 'label', label);\n\n _this16.$set(normalized, 'level', level);\n\n _this16.$set(normalized, 'ancestors', isRootNode ? [] : [parentNode].concat(parentNode.ancestors));\n\n _this16.$set(normalized, 'index', (isRootNode ? [] : parentNode.index).concat(index));\n\n _this16.$set(normalized, 'parentNode', parentNode);\n\n _this16.$set(normalized, 'lowerCased', lowerCased);\n\n _this16.$set(normalized, 'nestedSearchLabel', nestedSearchLabel);\n\n _this16.$set(normalized, 'isDisabled', isDisabled);\n\n _this16.$set(normalized, 'isNew', isNew);\n\n _this16.$set(normalized, 'isMatched', false);\n\n _this16.$set(normalized, 'isHighlighted', false);\n\n _this16.$set(normalized, 'isBranch', isBranch);\n\n _this16.$set(normalized, 'isLeaf', isLeaf);\n\n _this16.$set(normalized, 'isRootNode', isRootNode);\n\n _this16.$set(normalized, 'raw', raw);\n\n if (isBranch) {\n var _this16$$set;\n\n var isLoaded = Array.isArray(children);\n\n _this16.$set(normalized, 'childrenStates', _objectSpread({}, createAsyncOptionsStates(), {\n isLoaded: isLoaded\n }));\n\n _this16.$set(normalized, 'isExpanded', typeof isDefaultExpanded === 'boolean' ? isDefaultExpanded : level < _this16.defaultExpandLevel);\n\n _this16.$set(normalized, 'hasMatchedDescendants', false);\n\n _this16.$set(normalized, 'hasDisabledDescendants', false);\n\n _this16.$set(normalized, 'isExpandedOnSearch', false);\n\n _this16.$set(normalized, 'showAllChildrenOnSearch', false);\n\n _this16.$set(normalized, 'count', (_this16$$set = {}, defineProperty_default()(_this16$$set, ALL_CHILDREN, 0), defineProperty_default()(_this16$$set, ALL_DESCENDANTS, 0), defineProperty_default()(_this16$$set, LEAF_CHILDREN, 0), defineProperty_default()(_this16$$set, LEAF_DESCENDANTS, 0), _this16$$set));\n\n _this16.$set(normalized, 'children', isLoaded ? _this16.normalize(normalized, children, prevNodeMap) : []);\n\n if (isDefaultExpanded === true) normalized.ancestors.forEach(function (ancestor) {\n ancestor.isExpanded = true;\n });\n\n if (!isLoaded && typeof _this16.loadOptions !== 'function') {\n warning_warning(function () {\n return false;\n }, function () {\n return 'Unloaded branch node detected. \"loadOptions\" prop is required to load its children.';\n });\n } else if (!isLoaded && normalized.isExpanded) {\n _this16.loadChildrenOptions(normalized);\n }\n }\n\n normalized.ancestors.forEach(function (ancestor) {\n return ancestor.count[ALL_DESCENDANTS]++;\n });\n if (isLeaf) normalized.ancestors.forEach(function (ancestor) {\n return ancestor.count[LEAF_DESCENDANTS]++;\n });\n\n if (!isRootNode) {\n parentNode.count[ALL_CHILDREN] += 1;\n if (isLeaf) parentNode.count[LEAF_CHILDREN] += 1;\n if (isDisabled) parentNode.hasDisabledDescendants = true;\n }\n\n if (prevNodeMap && prevNodeMap[id]) {\n var prev = prevNodeMap[id];\n normalized.isMatched = prev.isMatched;\n normalized.showAllChildrenOnSearch = prev.showAllChildrenOnSearch;\n normalized.isHighlighted = prev.isHighlighted;\n\n if (prev.isBranch && normalized.isBranch) {\n normalized.isExpanded = prev.isExpanded;\n normalized.isExpandedOnSearch = prev.isExpandedOnSearch;\n\n if (prev.childrenStates.isLoaded && !normalized.childrenStates.isLoaded) {\n normalized.isExpanded = false;\n } else {\n normalized.childrenStates = _objectSpread({}, prev.childrenStates);\n }\n }\n }\n\n return normalized;\n });\n\n if (this.branchNodesFirst) {\n var branchNodes = normalizedOptions.filter(function (option) {\n return option.isBranch;\n });\n var leafNodes = normalizedOptions.filter(function (option) {\n return option.isLeaf;\n });\n normalizedOptions = branchNodes.concat(leafNodes);\n }\n\n return normalizedOptions;\n },\n loadRootOptions: function loadRootOptions() {\n var _this17 = this;\n\n this.callLoadOptionsProp({\n action: LOAD_ROOT_OPTIONS,\n isPending: function isPending() {\n return _this17.rootOptionsStates.isLoading;\n },\n start: function start() {\n _this17.rootOptionsStates.isLoading = true;\n _this17.rootOptionsStates.loadingError = '';\n },\n succeed: function succeed() {\n _this17.rootOptionsStates.isLoaded = true;\n\n _this17.$nextTick(function () {\n _this17.resetHighlightedOptionWhenNecessary(true);\n });\n },\n fail: function fail(err) {\n _this17.rootOptionsStates.loadingError = getErrorMessage(err);\n },\n end: function end() {\n _this17.rootOptionsStates.isLoading = false;\n }\n });\n },\n loadChildrenOptions: function loadChildrenOptions(parentNode) {\n var _this18 = this;\n\n var id = parentNode.id,\n raw = parentNode.raw;\n this.callLoadOptionsProp({\n action: LOAD_CHILDREN_OPTIONS,\n args: {\n parentNode: raw\n },\n isPending: function isPending() {\n return _this18.getNode(id).childrenStates.isLoading;\n },\n start: function start() {\n _this18.getNode(id).childrenStates.isLoading = true;\n _this18.getNode(id).childrenStates.loadingError = '';\n },\n succeed: function succeed() {\n _this18.getNode(id).childrenStates.isLoaded = true;\n },\n fail: function fail(err) {\n _this18.getNode(id).childrenStates.loadingError = getErrorMessage(err);\n },\n end: function end() {\n _this18.getNode(id).childrenStates.isLoading = false;\n }\n });\n },\n callLoadOptionsProp: function callLoadOptionsProp(_ref3) {\n var action = _ref3.action,\n args = _ref3.args,\n isPending = _ref3.isPending,\n start = _ref3.start,\n succeed = _ref3.succeed,\n fail = _ref3.fail,\n end = _ref3.end;\n\n if (!this.loadOptions || isPending()) {\n return;\n }\n\n start();\n var callback = once_default()(function (err, result) {\n if (err) {\n fail(err);\n } else {\n succeed(result);\n }\n\n end();\n });\n var result = this.loadOptions(_objectSpread({\n id: this.getInstanceId(),\n instanceId: this.getInstanceId(),\n action: action\n }, args, {\n callback: callback\n }));\n\n if (external_is_promise_default()(result)) {\n result.then(function () {\n callback();\n }, function (err) {\n callback(err);\n }).catch(function (err) {\n console.error(err);\n });\n }\n },\n checkDuplication: function checkDuplication(node) {\n var _this19 = this;\n\n warning_warning(function () {\n return !(node.id in _this19.forest.nodeMap && !_this19.forest.nodeMap[node.id].isFallbackNode);\n }, function () {\n return \"Detected duplicate presence of node id \".concat(JSON.stringify(node.id), \". \") + \"Their labels are \\\"\".concat(_this19.forest.nodeMap[node.id].label, \"\\\" and \\\"\").concat(node.label, \"\\\" respectively.\");\n });\n },\n verifyNodeShape: function verifyNodeShape(node) {\n warning_warning(function () {\n return !(node.children === undefined && node.isBranch === true);\n }, function () {\n return 'Are you meant to declare an unloaded branch node? ' + '`isBranch: true` is no longer supported, please use `children: null` instead.';\n });\n },\n select: function select(node) {\n if (this.disabled || node.isDisabled) {\n return;\n }\n\n if (this.single) {\n this.clear();\n }\n\n var nextState = this.multiple && !this.flat ? this.forest.checkedStateMap[node.id] === UNCHECKED : !this.isSelected(node);\n\n if (nextState) {\n this._selectNode(node);\n } else {\n this._deselectNode(node);\n }\n\n this.buildForestState();\n\n if (nextState) {\n this.$emit('select', node.raw, this.getInstanceId());\n } else {\n this.$emit('deselect', node.raw, this.getInstanceId());\n }\n\n if (this.localSearch.active && nextState && (this.single || this.clearOnSelect)) {\n this.resetSearchQuery();\n }\n\n if (this.single && this.closeOnSelect) {\n this.closeMenu();\n\n if (this.searchable) {\n this._blurOnSelect = true;\n }\n }\n },\n clear: function clear() {\n var _this20 = this;\n\n if (this.hasValue) {\n if (this.single || this.allowClearingDisabled) {\n this.forest.selectedNodeIds = [];\n } else {\n this.forest.selectedNodeIds = this.forest.selectedNodeIds.filter(function (nodeId) {\n return _this20.getNode(nodeId).isDisabled;\n });\n }\n\n this.buildForestState();\n }\n },\n _selectNode: function _selectNode(node) {\n var _this21 = this;\n\n if (this.single || this.disableBranchNodes) {\n return this.addValue(node);\n }\n\n if (this.flat) {\n this.addValue(node);\n\n if (this.autoSelectAncestors) {\n node.ancestors.forEach(function (ancestor) {\n if (!_this21.isSelected(ancestor) && !ancestor.isDisabled) _this21.addValue(ancestor);\n });\n } else if (this.autoSelectDescendants) {\n this.traverseDescendantsBFS(node, function (descendant) {\n if (!_this21.isSelected(descendant) && !descendant.isDisabled) _this21.addValue(descendant);\n });\n }\n\n return;\n }\n\n var isFullyChecked = node.isLeaf || !node.hasDisabledDescendants || this.allowSelectingDisabledDescendants;\n\n if (isFullyChecked) {\n this.addValue(node);\n }\n\n if (node.isBranch) {\n this.traverseDescendantsBFS(node, function (descendant) {\n if (!descendant.isDisabled || _this21.allowSelectingDisabledDescendants) {\n _this21.addValue(descendant);\n }\n });\n }\n\n if (isFullyChecked) {\n var curr = node;\n\n while ((curr = curr.parentNode) !== NO_PARENT_NODE) {\n if (curr.children.every(this.isSelected)) this.addValue(curr);else break;\n }\n }\n },\n _deselectNode: function _deselectNode(node) {\n var _this22 = this;\n\n if (this.disableBranchNodes) {\n return this.removeValue(node);\n }\n\n if (this.flat) {\n this.removeValue(node);\n\n if (this.autoDeselectAncestors) {\n node.ancestors.forEach(function (ancestor) {\n if (_this22.isSelected(ancestor) && !ancestor.isDisabled) _this22.removeValue(ancestor);\n });\n } else if (this.autoDeselectDescendants) {\n this.traverseDescendantsBFS(node, function (descendant) {\n if (_this22.isSelected(descendant) && !descendant.isDisabled) _this22.removeValue(descendant);\n });\n }\n\n return;\n }\n\n var hasUncheckedSomeDescendants = false;\n\n if (node.isBranch) {\n this.traverseDescendantsDFS(node, function (descendant) {\n if (!descendant.isDisabled || _this22.allowSelectingDisabledDescendants) {\n _this22.removeValue(descendant);\n\n hasUncheckedSomeDescendants = true;\n }\n });\n }\n\n if (node.isLeaf || hasUncheckedSomeDescendants || node.children.length === 0) {\n this.removeValue(node);\n var curr = node;\n\n while ((curr = curr.parentNode) !== NO_PARENT_NODE) {\n if (this.isSelected(curr)) this.removeValue(curr);else break;\n }\n }\n },\n addValue: function addValue(node) {\n this.forest.selectedNodeIds.push(node.id);\n this.forest.selectedNodeMap[node.id] = true;\n },\n removeValue: function removeValue(node) {\n removeFromArray(this.forest.selectedNodeIds, node.id);\n delete this.forest.selectedNodeMap[node.id];\n },\n removeLastValue: function removeLastValue() {\n if (!this.hasValue) return;\n if (this.single) return this.clear();\n var lastValue = last_default()(this.internalValue);\n var lastSelectedNode = this.getNode(lastValue);\n this.select(lastSelectedNode);\n },\n saveMenuScrollPosition: function saveMenuScrollPosition() {\n var $menu = this.getMenu();\n if ($menu) this.menu.lastScrollPosition = $menu.scrollTop;\n },\n restoreMenuScrollPosition: function restoreMenuScrollPosition() {\n var $menu = this.getMenu();\n if ($menu) $menu.scrollTop = this.menu.lastScrollPosition;\n }\n },\n created: function created() {\n this.verifyProps();\n this.resetFlags();\n },\n mounted: function mounted() {\n if (this.autoFocus) this.focusInput();\n if (!this.options && !this.async && this.autoLoadRootOptions) this.loadRootOptions();\n if (this.alwaysOpen) this.openMenu();\n if (this.async && this.defaultOptions) this.handleRemoteSearch();\n },\n destroyed: function destroyed() {\n this.toggleClickOutsideEvent(false);\n }\n});\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/HiddenFields.vue?vue&type=script&lang=js&\n\n\nfunction stringifyValue(value) {\n if (typeof value === 'string') return value;\n if (value != null && !isNaN_isNaN(value)) return JSON.stringify(value);\n return '';\n}\n\n/* harmony default export */ var HiddenFieldsvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--hidden-fields',\n inject: ['instance'],\n functional: true,\n render: function render(_, context) {\n var h = arguments[0];\n var instance = context.injections.instance;\n if (!instance.name || instance.disabled || !instance.hasValue) return null;\n var stringifiedValues = instance.internalValue.map(stringifyValue);\n if (instance.multiple && instance.joinValues) stringifiedValues = [stringifiedValues.join(instance.delimiter)];\n return stringifiedValues.map(function (stringifiedValue, i) {\n return h(\"input\", {\n attrs: {\n type: \"hidden\",\n name: instance.name\n },\n domProps: {\n \"value\": stringifiedValue\n },\n key: 'hidden-field-' + i\n });\n });\n }\n});\n// CONCATENATED MODULE: ./src/components/HiddenFields.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_HiddenFieldsvue_type_script_lang_js_ = (HiddenFieldsvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js\n/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nfunction normalizeComponent (\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier, /* server only */\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options = typeof scriptExports === 'function'\n ? scriptExports.options\n : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) { // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () { injectStyles.call(this, this.$root.$options.shadowRoot) }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functioal component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection (h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing\n ? [].concat(existing, hook)\n : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n\n// CONCATENATED MODULE: ./src/components/HiddenFields.vue\nvar HiddenFields_render, staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar component = normalizeComponent(\n components_HiddenFieldsvue_type_script_lang_js_,\n HiddenFields_render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/components/HiddenFields.vue\"\n/* harmony default export */ var HiddenFields = (component.exports);\n// EXTERNAL MODULE: external \"babel-helper-vue-jsx-merge-props\"\nvar external_babel_helper_vue_jsx_merge_props_ = __webpack_require__(13);\nvar external_babel_helper_vue_jsx_merge_props_default = /*#__PURE__*/__webpack_require__.n(external_babel_helper_vue_jsx_merge_props_);\n\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Input.vue?vue&type=script&lang=js&\n\n\n\nvar keysThatRequireMenuBeingOpen = [KEY_CODES.ENTER, KEY_CODES.END, KEY_CODES.HOME, KEY_CODES.ARROW_LEFT, KEY_CODES.ARROW_UP, KEY_CODES.ARROW_RIGHT, KEY_CODES.ARROW_DOWN];\n/* harmony default export */ var Inputvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--input',\n inject: ['instance'],\n data: function data() {\n return {\n inputWidth: MIN_INPUT_WIDTH,\n value: ''\n };\n },\n computed: {\n needAutoSize: function needAutoSize() {\n var instance = this.instance;\n return instance.searchable && !instance.disabled && instance.multiple;\n },\n inputStyle: function inputStyle() {\n return {\n width: this.needAutoSize ? \"\".concat(this.inputWidth, \"px\") : null\n };\n }\n },\n watch: {\n 'instance.trigger.searchQuery': function instanceTriggerSearchQuery(newValue) {\n this.value = newValue;\n },\n value: function value() {\n if (this.needAutoSize) this.$nextTick(this.updateInputWidth);\n }\n },\n created: function created() {\n this.debouncedCallback = debounce_default()(this.updateSearchQuery, INPUT_DEBOUNCE_DELAY, {\n leading: true,\n trailing: true\n });\n },\n methods: {\n clear: function clear() {\n this.onInput({\n target: {\n value: ''\n }\n });\n },\n focus: function focus() {\n var instance = this.instance;\n\n if (!instance.disabled) {\n this.$refs.input && this.$refs.input.focus();\n }\n },\n blur: function blur() {\n this.$refs.input && this.$refs.input.blur();\n },\n onFocus: function onFocus() {\n var instance = this.instance;\n instance.trigger.isFocused = true;\n if (instance.openOnFocus) instance.openMenu();\n },\n onBlur: function onBlur() {\n var instance = this.instance;\n var menu = instance.getMenu();\n\n if (menu && document.activeElement === menu) {\n return this.focus();\n }\n\n instance.trigger.isFocused = false;\n instance.closeMenu();\n },\n onInput: function onInput(evt) {\n var value = evt.target.value;\n this.value = value;\n\n if (value) {\n this.debouncedCallback();\n } else {\n this.debouncedCallback.cancel();\n this.updateSearchQuery();\n }\n },\n onKeyDown: function onKeyDown(evt) {\n var instance = this.instance;\n var key = 'which' in evt ? evt.which : evt.keyCode;\n if (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) return;\n\n if (!instance.menu.isOpen && includes(keysThatRequireMenuBeingOpen, key)) {\n evt.preventDefault();\n return instance.openMenu();\n }\n\n switch (key) {\n case KEY_CODES.BACKSPACE:\n {\n if (instance.backspaceRemoves && !this.value.length) {\n instance.removeLastValue();\n }\n\n break;\n }\n\n case KEY_CODES.ENTER:\n {\n evt.preventDefault();\n if (instance.menu.current === null) return;\n var current = instance.getNode(instance.menu.current);\n if (current.isBranch && instance.disableBranchNodes) return;\n instance.select(current);\n break;\n }\n\n case KEY_CODES.ESCAPE:\n {\n if (this.value.length) {\n this.clear();\n } else if (instance.menu.isOpen) {\n instance.closeMenu();\n }\n\n break;\n }\n\n case KEY_CODES.END:\n {\n evt.preventDefault();\n instance.highlightLastOption();\n break;\n }\n\n case KEY_CODES.HOME:\n {\n evt.preventDefault();\n instance.highlightFirstOption();\n break;\n }\n\n case KEY_CODES.ARROW_LEFT:\n {\n var _current = instance.getNode(instance.menu.current);\n\n if (_current.isBranch && instance.shouldExpand(_current)) {\n evt.preventDefault();\n instance.toggleExpanded(_current);\n } else if (!_current.isRootNode && (_current.isLeaf || _current.isBranch && !instance.shouldExpand(_current))) {\n evt.preventDefault();\n instance.setCurrentHighlightedOption(_current.parentNode);\n }\n\n break;\n }\n\n case KEY_CODES.ARROW_UP:\n {\n evt.preventDefault();\n instance.highlightPrevOption();\n break;\n }\n\n case KEY_CODES.ARROW_RIGHT:\n {\n var _current2 = instance.getNode(instance.menu.current);\n\n if (_current2.isBranch && !instance.shouldExpand(_current2)) {\n evt.preventDefault();\n instance.toggleExpanded(_current2);\n }\n\n break;\n }\n\n case KEY_CODES.ARROW_DOWN:\n {\n evt.preventDefault();\n instance.highlightNextOption();\n break;\n }\n\n case KEY_CODES.DELETE:\n {\n if (instance.deleteRemoves && !this.value.length) {\n instance.removeLastValue();\n }\n\n break;\n }\n\n default:\n {\n instance.openMenu();\n }\n }\n },\n onMouseDown: function onMouseDown(evt) {\n if (this.value.length) {\n evt.stopPropagation();\n }\n },\n renderInputContainer: function renderInputContainer() {\n var h = this.$createElement;\n var instance = this.instance;\n var props = {};\n var children = [];\n\n if (instance.searchable && !instance.disabled) {\n children.push(this.renderInput());\n if (this.needAutoSize) children.push(this.renderSizer());\n }\n\n if (!instance.searchable) {\n deepExtend(props, {\n on: {\n focus: this.onFocus,\n blur: this.onBlur,\n keydown: this.onKeyDown\n },\n ref: 'input'\n });\n }\n\n if (!instance.searchable && !instance.disabled) {\n deepExtend(props, {\n attrs: {\n tabIndex: instance.tabIndex\n }\n });\n }\n\n return h(\"div\", external_babel_helper_vue_jsx_merge_props_default()([{\n \"class\": \"vue-treeselect__input-container\"\n }, props]), [children]);\n },\n renderInput: function renderInput() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(\"input\", {\n ref: \"input\",\n \"class\": \"vue-treeselect__input\",\n attrs: {\n type: \"text\",\n autocomplete: \"off\",\n tabIndex: instance.tabIndex,\n required: instance.required && !instance.hasValue\n },\n domProps: {\n \"value\": this.value\n },\n style: this.inputStyle,\n on: {\n \"focus\": this.onFocus,\n \"input\": this.onInput,\n \"blur\": this.onBlur,\n \"keydown\": this.onKeyDown,\n \"mousedown\": this.onMouseDown\n }\n });\n },\n renderSizer: function renderSizer() {\n var h = this.$createElement;\n return h(\"div\", {\n ref: \"sizer\",\n \"class\": \"vue-treeselect__sizer\"\n }, [this.value]);\n },\n updateInputWidth: function updateInputWidth() {\n this.inputWidth = Math.max(MIN_INPUT_WIDTH, this.$refs.sizer.scrollWidth + 15);\n },\n updateSearchQuery: function updateSearchQuery() {\n var instance = this.instance;\n instance.trigger.searchQuery = this.value;\n }\n },\n render: function render() {\n return this.renderInputContainer();\n }\n});\n// CONCATENATED MODULE: ./src/components/Input.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Inputvue_type_script_lang_js_ = (Inputvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Input.vue\nvar Input_render, Input_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Input_component = normalizeComponent(\n components_Inputvue_type_script_lang_js_,\n Input_render,\n Input_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Input_api; }\nInput_component.options.__file = \"src/components/Input.vue\"\n/* harmony default export */ var Input = (Input_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Placeholder.vue?vue&type=script&lang=js&\n/* harmony default export */ var Placeholdervue_type_script_lang_js_ = ({\n name: 'vue-treeselect--placeholder',\n inject: ['instance'],\n render: function render() {\n var h = arguments[0];\n var instance = this.instance;\n var placeholderClass = {\n 'vue-treeselect__placeholder': true,\n 'vue-treeselect-helper-zoom-effect-off': true,\n 'vue-treeselect-helper-hide': instance.hasValue || instance.trigger.searchQuery\n };\n return h(\"div\", {\n \"class\": placeholderClass\n }, [instance.placeholder]);\n }\n});\n// CONCATENATED MODULE: ./src/components/Placeholder.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Placeholdervue_type_script_lang_js_ = (Placeholdervue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Placeholder.vue\nvar Placeholder_render, Placeholder_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Placeholder_component = normalizeComponent(\n components_Placeholdervue_type_script_lang_js_,\n Placeholder_render,\n Placeholder_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Placeholder_api; }\nPlaceholder_component.options.__file = \"src/components/Placeholder.vue\"\n/* harmony default export */ var Placeholder = (Placeholder_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/SingleValue.vue?vue&type=script&lang=js&\n\n\n/* harmony default export */ var SingleValuevue_type_script_lang_js_ = ({\n name: 'vue-treeselect--single-value',\n inject: ['instance'],\n methods: {\n renderSingleValueLabel: function renderSingleValueLabel() {\n var instance = this.instance;\n var node = instance.selectedNodes[0];\n var customValueLabelRenderer = instance.$scopedSlots['value-label'];\n return customValueLabelRenderer ? customValueLabelRenderer({\n node: node\n }) : node.label;\n }\n },\n render: function render() {\n var h = arguments[0];\n var instance = this.instance,\n renderValueContainer = this.$parent.renderValueContainer;\n var shouldShowValue = instance.hasValue && !instance.trigger.searchQuery;\n return renderValueContainer([shouldShowValue && h(\"div\", {\n \"class\": \"vue-treeselect__single-value\"\n }, [this.renderSingleValueLabel()]), h(Placeholder), h(Input, {\n ref: \"input\"\n })]);\n }\n});\n// CONCATENATED MODULE: ./src/components/SingleValue.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_SingleValuevue_type_script_lang_js_ = (SingleValuevue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/SingleValue.vue\nvar SingleValue_render, SingleValue_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar SingleValue_component = normalizeComponent(\n components_SingleValuevue_type_script_lang_js_,\n SingleValue_render,\n SingleValue_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var SingleValue_api; }\nSingleValue_component.options.__file = \"src/components/SingleValue.vue\"\n/* harmony default export */ var SingleValue = (SingleValue_component.exports);\n// CONCATENATED MODULE: ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js!./node_modules/vue-loader/lib??vue-loader-options!./src/components/icons/Delete.vue?vue&type=template&id=364b6320&\nvar Deletevue_type_template_id_364b6320_render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"svg\",\n {\n attrs: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 348.333 348.333\"\n }\n },\n [\n _c(\"path\", {\n attrs: {\n d:\n \"M336.559 68.611L231.016 174.165l105.543 105.549c15.699 15.705 15.699 41.145 0 56.85-7.844 7.844-18.128 11.769-28.407 11.769-10.296 0-20.581-3.919-28.419-11.769L174.167 231.003 68.609 336.563c-7.843 7.844-18.128 11.769-28.416 11.769-10.285 0-20.563-3.919-28.413-11.769-15.699-15.698-15.699-41.139 0-56.85l105.54-105.549L11.774 68.611c-15.699-15.699-15.699-41.145 0-56.844 15.696-15.687 41.127-15.687 56.829 0l105.563 105.554L279.721 11.767c15.705-15.687 41.139-15.687 56.832 0 15.705 15.699 15.705 41.145.006 56.844z\"\n }\n })\n ]\n )\n}\nvar Deletevue_type_template_id_364b6320_staticRenderFns = []\nDeletevue_type_template_id_364b6320_render._withStripped = true\n\n\n// CONCATENATED MODULE: ./src/components/icons/Delete.vue?vue&type=template&id=364b6320&\n\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/icons/Delete.vue?vue&type=script&lang=js&\n/* harmony default export */ var Deletevue_type_script_lang_js_ = ({\n name: 'vue-treeselect--x'\n});\n// CONCATENATED MODULE: ./src/components/icons/Delete.vue?vue&type=script&lang=js&\n /* harmony default export */ var icons_Deletevue_type_script_lang_js_ = (Deletevue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/icons/Delete.vue\n\n\n\n\n\n/* normalize component */\n\nvar Delete_component = normalizeComponent(\n icons_Deletevue_type_script_lang_js_,\n Deletevue_type_template_id_364b6320_render,\n Deletevue_type_template_id_364b6320_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Delete_api; }\nDelete_component.options.__file = \"src/components/icons/Delete.vue\"\n/* harmony default export */ var Delete = (Delete_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/MultiValueItem.vue?vue&type=script&lang=js&\n\n\n/* harmony default export */ var MultiValueItemvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--multi-value-item',\n inject: ['instance'],\n props: {\n node: {\n type: Object,\n required: true\n }\n },\n methods: {\n handleMouseDown: onLeftClick(function handleMouseDown() {\n var instance = this.instance,\n node = this.node;\n instance.select(node);\n })\n },\n render: function render() {\n var h = arguments[0];\n var instance = this.instance,\n node = this.node;\n var itemClass = {\n 'vue-treeselect__multi-value-item': true,\n 'vue-treeselect__multi-value-item-disabled': node.isDisabled,\n 'vue-treeselect__multi-value-item-new': node.isNew\n };\n var customValueLabelRenderer = instance.$scopedSlots['value-label'];\n var labelRenderer = customValueLabelRenderer ? customValueLabelRenderer({\n node: node\n }) : node.label;\n return h(\"div\", {\n \"class\": \"vue-treeselect__multi-value-item-container\"\n }, [h(\"div\", {\n \"class\": itemClass,\n on: {\n \"mousedown\": this.handleMouseDown\n }\n }, [h(\"span\", {\n \"class\": \"vue-treeselect__multi-value-label\"\n }, [labelRenderer]), h(\"span\", {\n \"class\": \"vue-treeselect__icon vue-treeselect__value-remove\"\n }, [h(Delete)])])]);\n }\n});\n// CONCATENATED MODULE: ./src/components/MultiValueItem.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_MultiValueItemvue_type_script_lang_js_ = (MultiValueItemvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/MultiValueItem.vue\nvar MultiValueItem_render, MultiValueItem_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar MultiValueItem_component = normalizeComponent(\n components_MultiValueItemvue_type_script_lang_js_,\n MultiValueItem_render,\n MultiValueItem_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var MultiValueItem_api; }\nMultiValueItem_component.options.__file = \"src/components/MultiValueItem.vue\"\n/* harmony default export */ var MultiValueItem = (MultiValueItem_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/MultiValue.vue?vue&type=script&lang=js&\n\n\n\n\n/* harmony default export */ var MultiValuevue_type_script_lang_js_ = ({\n name: 'vue-treeselect--multi-value',\n inject: ['instance'],\n methods: {\n renderMultiValueItems: function renderMultiValueItems() {\n var h = this.$createElement;\n var instance = this.instance;\n return instance.internalValue.slice(0, instance.limit).map(instance.getNode).map(function (node) {\n return h(MultiValueItem, {\n key: \"multi-value-item-\".concat(node.id),\n attrs: {\n node: node\n }\n });\n });\n },\n renderExceedLimitTip: function renderExceedLimitTip() {\n var h = this.$createElement;\n var instance = this.instance;\n var count = instance.internalValue.length - instance.limit;\n if (count <= 0) return null;\n return h(\"div\", {\n \"class\": \"vue-treeselect__limit-tip vue-treeselect-helper-zoom-effect-off\",\n key: \"exceed-limit-tip\"\n }, [h(\"span\", {\n \"class\": \"vue-treeselect__limit-tip-text\"\n }, [instance.limitText(count)])]);\n }\n },\n render: function render() {\n var h = arguments[0];\n var renderValueContainer = this.$parent.renderValueContainer;\n var transitionGroupProps = {\n props: {\n tag: 'div',\n name: 'vue-treeselect__multi-value-item--transition',\n appear: true\n }\n };\n return renderValueContainer(h(\"transition-group\", external_babel_helper_vue_jsx_merge_props_default()([{\n \"class\": \"vue-treeselect__multi-value\"\n }, transitionGroupProps]), [this.renderMultiValueItems(), this.renderExceedLimitTip(), h(Placeholder, {\n key: \"placeholder\"\n }), h(Input, {\n ref: \"input\",\n key: \"input\"\n })]));\n }\n});\n// CONCATENATED MODULE: ./src/components/MultiValue.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_MultiValuevue_type_script_lang_js_ = (MultiValuevue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/MultiValue.vue\nvar MultiValue_render, MultiValue_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar MultiValue_component = normalizeComponent(\n components_MultiValuevue_type_script_lang_js_,\n MultiValue_render,\n MultiValue_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var MultiValue_api; }\nMultiValue_component.options.__file = \"src/components/MultiValue.vue\"\n/* harmony default export */ var MultiValue = (MultiValue_component.exports);\n// CONCATENATED MODULE: ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js!./node_modules/vue-loader/lib??vue-loader-options!./src/components/icons/Arrow.vue?vue&type=template&id=11186cd4&\nvar Arrowvue_type_template_id_11186cd4_render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"svg\",\n {\n attrs: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 292.362 292.362\"\n }\n },\n [\n _c(\"path\", {\n attrs: {\n d:\n \"M286.935 69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952 0-9.233 1.807-12.85 5.424C1.807 72.998 0 77.279 0 82.228c0 4.948 1.807 9.229 5.424 12.847l127.907 127.907c3.621 3.617 7.902 5.428 12.85 5.428s9.233-1.811 12.847-5.428L286.935 95.074c3.613-3.617 5.427-7.898 5.427-12.847 0-4.948-1.814-9.229-5.427-12.85z\"\n }\n })\n ]\n )\n}\nvar Arrowvue_type_template_id_11186cd4_staticRenderFns = []\nArrowvue_type_template_id_11186cd4_render._withStripped = true\n\n\n// CONCATENATED MODULE: ./src/components/icons/Arrow.vue?vue&type=template&id=11186cd4&\n\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/icons/Arrow.vue?vue&type=script&lang=js&\n/* harmony default export */ var Arrowvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--arrow'\n});\n// CONCATENATED MODULE: ./src/components/icons/Arrow.vue?vue&type=script&lang=js&\n /* harmony default export */ var icons_Arrowvue_type_script_lang_js_ = (Arrowvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/icons/Arrow.vue\n\n\n\n\n\n/* normalize component */\n\nvar Arrow_component = normalizeComponent(\n icons_Arrowvue_type_script_lang_js_,\n Arrowvue_type_template_id_11186cd4_render,\n Arrowvue_type_template_id_11186cd4_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Arrow_api; }\nArrow_component.options.__file = \"src/components/icons/Arrow.vue\"\n/* harmony default export */ var Arrow = (Arrow_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Control.vue?vue&type=script&lang=js&\n\n\n\n\n\n/* harmony default export */ var Controlvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--control',\n inject: ['instance'],\n computed: {\n shouldShowX: function shouldShowX() {\n var instance = this.instance;\n return instance.clearable && !instance.disabled && instance.hasValue && (this.hasUndisabledValue || instance.allowClearingDisabled);\n },\n shouldShowArrow: function shouldShowArrow() {\n var instance = this.instance;\n if (!instance.alwaysOpen) return true;\n return !instance.menu.isOpen;\n },\n hasUndisabledValue: function hasUndisabledValue() {\n var instance = this.instance;\n return instance.hasValue && instance.internalValue.some(function (id) {\n return !instance.getNode(id).isDisabled;\n });\n }\n },\n methods: {\n renderX: function renderX() {\n var h = this.$createElement;\n var instance = this.instance;\n var title = instance.multiple ? instance.clearAllText : instance.clearValueText;\n if (!this.shouldShowX) return null;\n return h(\"div\", {\n \"class\": \"vue-treeselect__x-container\",\n attrs: {\n title: title\n },\n on: {\n \"mousedown\": this.handleMouseDownOnX\n }\n }, [h(Delete, {\n \"class\": \"vue-treeselect__x\"\n })]);\n },\n renderArrow: function renderArrow() {\n var h = this.$createElement;\n var instance = this.instance;\n var arrowClass = {\n 'vue-treeselect__control-arrow': true,\n 'vue-treeselect__control-arrow--rotated': instance.menu.isOpen\n };\n if (!this.shouldShowArrow) return null;\n return h(\"div\", {\n \"class\": \"vue-treeselect__control-arrow-container\",\n on: {\n \"mousedown\": this.handleMouseDownOnArrow\n }\n }, [h(Arrow, {\n \"class\": arrowClass\n })]);\n },\n handleMouseDownOnX: onLeftClick(function handleMouseDownOnX(evt) {\n evt.stopPropagation();\n evt.preventDefault();\n var instance = this.instance;\n var result = instance.beforeClearAll();\n\n var handler = function handler(shouldClear) {\n if (shouldClear) instance.clear();\n };\n\n if (external_is_promise_default()(result)) {\n result.then(handler);\n } else {\n setTimeout(function () {\n return handler(result);\n }, 0);\n }\n }),\n handleMouseDownOnArrow: onLeftClick(function handleMouseDownOnArrow(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n var instance = this.instance;\n instance.focusInput();\n instance.toggleMenu();\n }),\n renderValueContainer: function renderValueContainer(children) {\n var h = this.$createElement;\n return h(\"div\", {\n \"class\": \"vue-treeselect__value-container\"\n }, [children]);\n }\n },\n render: function render() {\n var h = arguments[0];\n var instance = this.instance;\n var ValueContainer = instance.single ? SingleValue : MultiValue;\n return h(\"div\", {\n \"class\": \"vue-treeselect__control\",\n on: {\n \"mousedown\": instance.handleMouseDown\n }\n }, [h(ValueContainer, {\n ref: \"value-container\"\n }), this.renderX(), this.renderArrow()]);\n }\n});\n// CONCATENATED MODULE: ./src/components/Control.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Controlvue_type_script_lang_js_ = (Controlvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Control.vue\nvar Control_render, Control_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Control_component = normalizeComponent(\n components_Controlvue_type_script_lang_js_,\n Control_render,\n Control_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Control_api; }\nControl_component.options.__file = \"src/components/Control.vue\"\n/* harmony default export */ var Control = (Control_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Tip.vue?vue&type=script&lang=js&\n/* harmony default export */ var Tipvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--tip',\n functional: true,\n props: {\n type: {\n type: String,\n required: true\n },\n icon: {\n type: String,\n required: true\n }\n },\n render: function render(_, context) {\n var h = arguments[0];\n var props = context.props,\n children = context.children;\n return h(\"div\", {\n \"class\": \"vue-treeselect__tip vue-treeselect__\".concat(props.type, \"-tip\")\n }, [h(\"div\", {\n \"class\": \"vue-treeselect__icon-container\"\n }, [h(\"span\", {\n \"class\": \"vue-treeselect__icon-\".concat(props.icon)\n })]), h(\"span\", {\n \"class\": \"vue-treeselect__tip-text vue-treeselect__\".concat(props.type, \"-tip-text\")\n }, [children])]);\n }\n});\n// CONCATENATED MODULE: ./src/components/Tip.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Tipvue_type_script_lang_js_ = (Tipvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Tip.vue\nvar Tip_render, Tip_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Tip_component = normalizeComponent(\n components_Tipvue_type_script_lang_js_,\n Tip_render,\n Tip_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Tip_api; }\nTip_component.options.__file = \"src/components/Tip.vue\"\n/* harmony default export */ var Tip = (Tip_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Option.vue?vue&type=script&lang=js&\n\n\n\n\n\nvar arrowPlaceholder, checkMark, minusMark;\nvar Option = {\n name: 'vue-treeselect--option',\n inject: ['instance'],\n props: {\n node: {\n type: Object,\n required: true\n }\n },\n computed: {\n shouldExpand: function shouldExpand() {\n var instance = this.instance,\n node = this.node;\n return node.isBranch && instance.shouldExpand(node);\n },\n shouldShow: function shouldShow() {\n var instance = this.instance,\n node = this.node;\n return instance.shouldShowOptionInMenu(node);\n }\n },\n methods: {\n renderOption: function renderOption() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n var optionClass = {\n 'vue-treeselect__option': true,\n 'vue-treeselect__option--disabled': node.isDisabled,\n 'vue-treeselect__option--selected': instance.isSelected(node),\n 'vue-treeselect__option--highlight': node.isHighlighted,\n 'vue-treeselect__option--matched': instance.localSearch.active && node.isMatched,\n 'vue-treeselect__option--hide': !this.shouldShow\n };\n return h(\"div\", {\n \"class\": optionClass,\n on: {\n \"mouseenter\": this.handleMouseEnterOption\n },\n attrs: {\n \"data-id\": node.id\n }\n }, [this.renderArrow(), this.renderLabelContainer([this.renderCheckboxContainer([this.renderCheckbox()]), this.renderLabel()])]);\n },\n renderSubOptionsList: function renderSubOptionsList() {\n var h = this.$createElement;\n if (!this.shouldExpand) return null;\n return h(\"div\", {\n \"class\": \"vue-treeselect__list\"\n }, [this.renderSubOptions(), this.renderNoChildrenTip(), this.renderLoadingChildrenTip(), this.renderLoadingChildrenErrorTip()]);\n },\n renderArrow: function renderArrow() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n if (instance.shouldFlattenOptions && this.shouldShow) return null;\n\n if (node.isBranch) {\n var transitionProps = {\n props: {\n name: 'vue-treeselect__option-arrow--prepare',\n appear: true\n }\n };\n var arrowClass = {\n 'vue-treeselect__option-arrow': true,\n 'vue-treeselect__option-arrow--rotated': this.shouldExpand\n };\n return h(\"div\", {\n \"class\": \"vue-treeselect__option-arrow-container\",\n on: {\n \"mousedown\": this.handleMouseDownOnArrow\n }\n }, [h(\"transition\", transitionProps, [h(Arrow, {\n \"class\": arrowClass\n })])]);\n }\n\n if (instance.hasBranchNodes) {\n if (!arrowPlaceholder) arrowPlaceholder = h(\"div\", {\n \"class\": \"vue-treeselect__option-arrow-placeholder\"\n }, [\"\\xA0\"]);\n return arrowPlaceholder;\n }\n\n return null;\n },\n renderLabelContainer: function renderLabelContainer(children) {\n var h = this.$createElement;\n return h(\"div\", {\n \"class\": \"vue-treeselect__label-container\",\n on: {\n \"mousedown\": this.handleMouseDownOnLabelContainer\n }\n }, [children]);\n },\n renderCheckboxContainer: function renderCheckboxContainer(children) {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n if (instance.single) return null;\n if (instance.disableBranchNodes && node.isBranch) return null;\n return h(\"div\", {\n \"class\": \"vue-treeselect__checkbox-container\"\n }, [children]);\n },\n renderCheckbox: function renderCheckbox() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n var checkedState = instance.forest.checkedStateMap[node.id];\n var checkboxClass = {\n 'vue-treeselect__checkbox': true,\n 'vue-treeselect__checkbox--checked': checkedState === CHECKED,\n 'vue-treeselect__checkbox--indeterminate': checkedState === INDETERMINATE,\n 'vue-treeselect__checkbox--unchecked': checkedState === UNCHECKED,\n 'vue-treeselect__checkbox--disabled': node.isDisabled\n };\n if (!checkMark) checkMark = h(\"span\", {\n \"class\": \"vue-treeselect__check-mark\"\n });\n if (!minusMark) minusMark = h(\"span\", {\n \"class\": \"vue-treeselect__minus-mark\"\n });\n return h(\"span\", {\n \"class\": checkboxClass\n }, [checkMark, minusMark]);\n },\n renderLabel: function renderLabel() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n var shouldShowCount = node.isBranch && (instance.localSearch.active ? instance.showCountOnSearchComputed : instance.showCount);\n var count = shouldShowCount ? instance.localSearch.active ? instance.localSearch.countMap[node.id][instance.showCountOf] : node.count[instance.showCountOf] : NaN;\n var labelClassName = 'vue-treeselect__label';\n var countClassName = 'vue-treeselect__count';\n var customLabelRenderer = instance.$scopedSlots['option-label'];\n if (customLabelRenderer) return customLabelRenderer({\n node: node,\n shouldShowCount: shouldShowCount,\n count: count,\n labelClassName: labelClassName,\n countClassName: countClassName\n });\n return h(\"label\", {\n \"class\": labelClassName\n }, [node.label, shouldShowCount && h(\"span\", {\n \"class\": countClassName\n }, [\"(\", count, \")\"])]);\n },\n renderSubOptions: function renderSubOptions() {\n var h = this.$createElement;\n var node = this.node;\n if (!node.childrenStates.isLoaded) return null;\n return node.children.map(function (childNode) {\n return h(Option, {\n attrs: {\n node: childNode\n },\n key: childNode.id\n });\n });\n },\n renderNoChildrenTip: function renderNoChildrenTip() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n if (!node.childrenStates.isLoaded || node.children.length) return null;\n return h(Tip, {\n attrs: {\n type: \"no-children\",\n icon: \"warning\"\n }\n }, [instance.noChildrenText]);\n },\n renderLoadingChildrenTip: function renderLoadingChildrenTip() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n if (!node.childrenStates.isLoading) return null;\n return h(Tip, {\n attrs: {\n type: \"loading\",\n icon: \"loader\"\n }\n }, [instance.loadingText]);\n },\n renderLoadingChildrenErrorTip: function renderLoadingChildrenErrorTip() {\n var h = this.$createElement;\n var instance = this.instance,\n node = this.node;\n if (!node.childrenStates.loadingError) return null;\n return h(Tip, {\n attrs: {\n type: \"error\",\n icon: \"error\"\n }\n }, [node.childrenStates.loadingError, h(\"a\", {\n \"class\": \"vue-treeselect__retry\",\n attrs: {\n title: instance.retryTitle\n },\n on: {\n \"mousedown\": this.handleMouseDownOnRetry\n }\n }, [instance.retryText])]);\n },\n handleMouseEnterOption: function handleMouseEnterOption(evt) {\n var instance = this.instance,\n node = this.node;\n if (evt.target !== evt.currentTarget) return;\n instance.setCurrentHighlightedOption(node, false);\n },\n handleMouseDownOnArrow: onLeftClick(function handleMouseDownOnOptionArrow() {\n var instance = this.instance,\n node = this.node;\n instance.toggleExpanded(node);\n }),\n handleMouseDownOnLabelContainer: onLeftClick(function handleMouseDownOnLabelContainer() {\n var instance = this.instance,\n node = this.node;\n\n if (node.isBranch && instance.disableBranchNodes) {\n instance.toggleExpanded(node);\n } else {\n instance.select(node);\n }\n }),\n handleMouseDownOnRetry: onLeftClick(function handleMouseDownOnRetry() {\n var instance = this.instance,\n node = this.node;\n instance.loadChildrenOptions(node);\n })\n },\n render: function render() {\n var h = arguments[0];\n var node = this.node;\n var indentLevel = this.instance.shouldFlattenOptions ? 0 : node.level;\n\n var listItemClass = defineProperty_default()({\n 'vue-treeselect__list-item': true\n }, \"vue-treeselect__indent-level-\".concat(indentLevel), true);\n\n var transitionProps = {\n props: {\n name: 'vue-treeselect__list--transition'\n }\n };\n return h(\"div\", {\n \"class\": listItemClass\n }, [this.renderOption(), node.isBranch && h(\"transition\", transitionProps, [this.renderSubOptionsList()])]);\n }\n};\n/* harmony default export */ var Optionvue_type_script_lang_js_ = (Option);\n// CONCATENATED MODULE: ./src/components/Option.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Optionvue_type_script_lang_js_ = (Optionvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Option.vue\nvar Option_render, Option_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Option_component = normalizeComponent(\n components_Optionvue_type_script_lang_js_,\n Option_render,\n Option_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Option_api; }\nOption_component.options.__file = \"src/components/Option.vue\"\n/* harmony default export */ var components_Option = (Option_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Menu.vue?vue&type=script&lang=js&\n\n\n\n\nvar directionMap = {\n top: 'top',\n bottom: 'bottom',\n above: 'top',\n below: 'bottom'\n};\n/* harmony default export */ var Menuvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--menu',\n inject: ['instance'],\n computed: {\n menuStyle: function menuStyle() {\n var instance = this.instance;\n return {\n maxHeight: instance.maxHeight + 'px'\n };\n },\n menuContainerStyle: function menuContainerStyle() {\n var instance = this.instance;\n return {\n zIndex: instance.appendToBody ? null : instance.zIndex\n };\n }\n },\n watch: {\n 'instance.menu.isOpen': function instanceMenuIsOpen(newValue) {\n if (newValue) {\n this.$nextTick(this.onMenuOpen);\n } else {\n this.onMenuClose();\n }\n }\n },\n created: function created() {\n this.menuSizeWatcher = null;\n this.menuResizeAndScrollEventListeners = null;\n },\n mounted: function mounted() {\n var instance = this.instance;\n if (instance.menu.isOpen) this.$nextTick(this.onMenuOpen);\n },\n destroyed: function destroyed() {\n this.onMenuClose();\n },\n methods: {\n renderMenu: function renderMenu() {\n var h = this.$createElement;\n var instance = this.instance;\n if (!instance.menu.isOpen) return null;\n return h(\"div\", {\n ref: \"menu\",\n \"class\": \"vue-treeselect__menu\",\n on: {\n \"mousedown\": instance.handleMouseDown\n },\n style: this.menuStyle\n }, [this.renderBeforeList(), instance.async ? this.renderAsyncSearchMenuInner() : instance.localSearch.active ? this.renderLocalSearchMenuInner() : this.renderNormalMenuInner(), this.renderAfterList()]);\n },\n renderBeforeList: function renderBeforeList() {\n var instance = this.instance;\n var beforeListRenderer = instance.$scopedSlots['before-list'];\n return beforeListRenderer ? beforeListRenderer() : null;\n },\n renderAfterList: function renderAfterList() {\n var instance = this.instance;\n var afterListRenderer = instance.$scopedSlots['after-list'];\n return afterListRenderer ? afterListRenderer() : null;\n },\n renderNormalMenuInner: function renderNormalMenuInner() {\n var instance = this.instance;\n\n if (instance.rootOptionsStates.isLoading) {\n return this.renderLoadingOptionsTip();\n } else if (instance.rootOptionsStates.loadingError) {\n return this.renderLoadingRootOptionsErrorTip();\n } else if (instance.rootOptionsStates.isLoaded && instance.forest.normalizedOptions.length === 0) {\n return this.renderNoAvailableOptionsTip();\n } else {\n return this.renderOptionList();\n }\n },\n renderLocalSearchMenuInner: function renderLocalSearchMenuInner() {\n var instance = this.instance;\n\n if (instance.rootOptionsStates.isLoading) {\n return this.renderLoadingOptionsTip();\n } else if (instance.rootOptionsStates.loadingError) {\n return this.renderLoadingRootOptionsErrorTip();\n } else if (instance.rootOptionsStates.isLoaded && instance.forest.normalizedOptions.length === 0) {\n return this.renderNoAvailableOptionsTip();\n } else if (instance.localSearch.noResults) {\n return this.renderNoResultsTip();\n } else {\n return this.renderOptionList();\n }\n },\n renderAsyncSearchMenuInner: function renderAsyncSearchMenuInner() {\n var instance = this.instance;\n var entry = instance.getRemoteSearchEntry();\n var shouldShowSearchPromptTip = instance.trigger.searchQuery === '' && !instance.defaultOptions;\n var shouldShowNoResultsTip = shouldShowSearchPromptTip ? false : entry.isLoaded && entry.options.length === 0;\n\n if (shouldShowSearchPromptTip) {\n return this.renderSearchPromptTip();\n } else if (entry.isLoading) {\n return this.renderLoadingOptionsTip();\n } else if (entry.loadingError) {\n return this.renderAsyncSearchLoadingErrorTip();\n } else if (shouldShowNoResultsTip) {\n return this.renderNoResultsTip();\n } else {\n return this.renderOptionList();\n }\n },\n renderOptionList: function renderOptionList() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(\"div\", {\n \"class\": \"vue-treeselect__list\"\n }, [instance.forest.normalizedOptions.map(function (rootNode) {\n return h(components_Option, {\n attrs: {\n node: rootNode\n },\n key: rootNode.id\n });\n })]);\n },\n renderSearchPromptTip: function renderSearchPromptTip() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(Tip, {\n attrs: {\n type: \"search-prompt\",\n icon: \"warning\"\n }\n }, [instance.searchPromptText]);\n },\n renderLoadingOptionsTip: function renderLoadingOptionsTip() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(Tip, {\n attrs: {\n type: \"loading\",\n icon: \"loader\"\n }\n }, [instance.loadingText]);\n },\n renderLoadingRootOptionsErrorTip: function renderLoadingRootOptionsErrorTip() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(Tip, {\n attrs: {\n type: \"error\",\n icon: \"error\"\n }\n }, [instance.rootOptionsStates.loadingError, h(\"a\", {\n \"class\": \"vue-treeselect__retry\",\n on: {\n \"click\": instance.loadRootOptions\n },\n attrs: {\n title: instance.retryTitle\n }\n }, [instance.retryText])]);\n },\n renderAsyncSearchLoadingErrorTip: function renderAsyncSearchLoadingErrorTip() {\n var h = this.$createElement;\n var instance = this.instance;\n var entry = instance.getRemoteSearchEntry();\n return h(Tip, {\n attrs: {\n type: \"error\",\n icon: \"error\"\n }\n }, [entry.loadingError, h(\"a\", {\n \"class\": \"vue-treeselect__retry\",\n on: {\n \"click\": instance.handleRemoteSearch\n },\n attrs: {\n title: instance.retryTitle\n }\n }, [instance.retryText])]);\n },\n renderNoAvailableOptionsTip: function renderNoAvailableOptionsTip() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(Tip, {\n attrs: {\n type: \"no-options\",\n icon: \"warning\"\n }\n }, [instance.noOptionsText]);\n },\n renderNoResultsTip: function renderNoResultsTip() {\n var h = this.$createElement;\n var instance = this.instance;\n return h(Tip, {\n attrs: {\n type: \"no-results\",\n icon: \"warning\"\n }\n }, [instance.noResultsText]);\n },\n onMenuOpen: function onMenuOpen() {\n this.adjustMenuOpenDirection();\n this.setupMenuSizeWatcher();\n this.setupMenuResizeAndScrollEventListeners();\n },\n onMenuClose: function onMenuClose() {\n this.removeMenuSizeWatcher();\n this.removeMenuResizeAndScrollEventListeners();\n },\n adjustMenuOpenDirection: function adjustMenuOpenDirection() {\n var instance = this.instance;\n if (!instance.menu.isOpen) return;\n var $menu = instance.getMenu();\n var $control = instance.getControl();\n var menuRect = $menu.getBoundingClientRect();\n var controlRect = $control.getBoundingClientRect();\n var menuHeight = menuRect.height;\n var viewportHeight = window.innerHeight;\n var spaceAbove = controlRect.top;\n var spaceBelow = window.innerHeight - controlRect.bottom;\n var isControlInViewport = controlRect.top >= 0 && controlRect.top <= viewportHeight || controlRect.top < 0 && controlRect.bottom > 0;\n var hasEnoughSpaceBelow = spaceBelow > menuHeight + MENU_BUFFER;\n var hasEnoughSpaceAbove = spaceAbove > menuHeight + MENU_BUFFER;\n\n if (!isControlInViewport) {\n instance.closeMenu();\n } else if (instance.openDirection !== 'auto') {\n instance.menu.placement = directionMap[instance.openDirection];\n } else if (hasEnoughSpaceBelow || !hasEnoughSpaceAbove) {\n instance.menu.placement = 'bottom';\n } else {\n instance.menu.placement = 'top';\n }\n },\n setupMenuSizeWatcher: function setupMenuSizeWatcher() {\n var instance = this.instance;\n var $menu = instance.getMenu();\n if (this.menuSizeWatcher) return;\n this.menuSizeWatcher = {\n remove: watchSize($menu, this.adjustMenuOpenDirection)\n };\n },\n setupMenuResizeAndScrollEventListeners: function setupMenuResizeAndScrollEventListeners() {\n var instance = this.instance;\n var $control = instance.getControl();\n if (this.menuResizeAndScrollEventListeners) return;\n this.menuResizeAndScrollEventListeners = {\n remove: setupResizeAndScrollEventListeners($control, this.adjustMenuOpenDirection)\n };\n },\n removeMenuSizeWatcher: function removeMenuSizeWatcher() {\n if (!this.menuSizeWatcher) return;\n this.menuSizeWatcher.remove();\n this.menuSizeWatcher = null;\n },\n removeMenuResizeAndScrollEventListeners: function removeMenuResizeAndScrollEventListeners() {\n if (!this.menuResizeAndScrollEventListeners) return;\n this.menuResizeAndScrollEventListeners.remove();\n this.menuResizeAndScrollEventListeners = null;\n }\n },\n render: function render() {\n var h = arguments[0];\n return h(\"div\", {\n ref: \"menu-container\",\n \"class\": \"vue-treeselect__menu-container\",\n style: this.menuContainerStyle\n }, [h(\"transition\", {\n attrs: {\n name: \"vue-treeselect__menu--transition\"\n }\n }, [this.renderMenu()])]);\n }\n});\n// CONCATENATED MODULE: ./src/components/Menu.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Menuvue_type_script_lang_js_ = (Menuvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Menu.vue\nvar Menu_render, Menu_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Menu_component = normalizeComponent(\n components_Menuvue_type_script_lang_js_,\n Menu_render,\n Menu_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Menu_api; }\nMenu_component.options.__file = \"src/components/Menu.vue\"\n/* harmony default export */ var Menu = (Menu_component.exports);\n// EXTERNAL MODULE: external \"vue\"\nvar external_vue_ = __webpack_require__(14);\nvar external_vue_default = /*#__PURE__*/__webpack_require__.n(external_vue_);\n\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/MenuPortal.vue?vue&type=script&lang=js&\n\n\nfunction MenuPortalvue_type_script_lang_js_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction MenuPortalvue_type_script_lang_js_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { MenuPortalvue_type_script_lang_js_ownKeys(source, true).forEach(function (key) { defineProperty_default()(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { MenuPortalvue_type_script_lang_js_ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\n\n\n\nvar PortalTarget = {\n name: 'vue-treeselect--portal-target',\n inject: ['instance'],\n watch: {\n 'instance.menu.isOpen': function instanceMenuIsOpen(newValue) {\n if (newValue) {\n this.setupHandlers();\n } else {\n this.removeHandlers();\n }\n },\n 'instance.menu.placement': function instanceMenuPlacement() {\n this.updateMenuContainerOffset();\n }\n },\n created: function created() {\n this.controlResizeAndScrollEventListeners = null;\n this.controlSizeWatcher = null;\n },\n mounted: function mounted() {\n var instance = this.instance;\n if (instance.menu.isOpen) this.setupHandlers();\n },\n methods: {\n setupHandlers: function setupHandlers() {\n this.updateWidth();\n this.updateMenuContainerOffset();\n this.setupControlResizeAndScrollEventListeners();\n this.setupControlSizeWatcher();\n },\n removeHandlers: function removeHandlers() {\n this.removeControlResizeAndScrollEventListeners();\n this.removeControlSizeWatcher();\n },\n setupControlResizeAndScrollEventListeners: function setupControlResizeAndScrollEventListeners() {\n var instance = this.instance;\n var $control = instance.getControl();\n if (this.controlResizeAndScrollEventListeners) return;\n this.controlResizeAndScrollEventListeners = {\n remove: setupResizeAndScrollEventListeners($control, this.updateMenuContainerOffset)\n };\n },\n setupControlSizeWatcher: function setupControlSizeWatcher() {\n var _this = this;\n\n var instance = this.instance;\n var $control = instance.getControl();\n if (this.controlSizeWatcher) return;\n this.controlSizeWatcher = {\n remove: watchSize($control, function () {\n _this.updateWidth();\n\n _this.updateMenuContainerOffset();\n })\n };\n },\n removeControlResizeAndScrollEventListeners: function removeControlResizeAndScrollEventListeners() {\n if (!this.controlResizeAndScrollEventListeners) return;\n this.controlResizeAndScrollEventListeners.remove();\n this.controlResizeAndScrollEventListeners = null;\n },\n removeControlSizeWatcher: function removeControlSizeWatcher() {\n if (!this.controlSizeWatcher) return;\n this.controlSizeWatcher.remove();\n this.controlSizeWatcher = null;\n },\n updateWidth: function updateWidth() {\n var instance = this.instance;\n var $portalTarget = this.$el;\n var $control = instance.getControl();\n var controlRect = $control.getBoundingClientRect();\n $portalTarget.style.width = controlRect.width + 'px';\n },\n updateMenuContainerOffset: function updateMenuContainerOffset() {\n var instance = this.instance;\n var $control = instance.getControl();\n var $portalTarget = this.$el;\n var controlRect = $control.getBoundingClientRect();\n var portalTargetRect = $portalTarget.getBoundingClientRect();\n var offsetY = instance.menu.placement === 'bottom' ? controlRect.height : 0;\n var left = Math.round(controlRect.left - portalTargetRect.left) + 'px';\n var top = Math.round(controlRect.top - portalTargetRect.top + offsetY) + 'px';\n var menuContainerStyle = this.$refs.menu.$refs['menu-container'].style;\n var transformVariations = ['transform', 'webkitTransform', 'MozTransform', 'msTransform'];\n var transform = find(transformVariations, function (t) {\n return t in document.body.style;\n });\n menuContainerStyle[transform] = \"translate(\".concat(left, \", \").concat(top, \")\");\n }\n },\n render: function render() {\n var h = arguments[0];\n var instance = this.instance;\n var portalTargetClass = ['vue-treeselect__portal-target', instance.wrapperClass];\n var portalTargetStyle = {\n zIndex: instance.zIndex\n };\n return h(\"div\", {\n \"class\": portalTargetClass,\n style: portalTargetStyle,\n attrs: {\n \"data-instance-id\": instance.getInstanceId()\n }\n }, [h(Menu, {\n ref: \"menu\"\n })]);\n },\n destroyed: function destroyed() {\n this.removeHandlers();\n }\n};\nvar placeholder;\n/* harmony default export */ var MenuPortalvue_type_script_lang_js_ = ({\n name: 'vue-treeselect--menu-portal',\n created: function created() {\n this.portalTarget = null;\n },\n mounted: function mounted() {\n this.setup();\n },\n destroyed: function destroyed() {\n this.teardown();\n },\n methods: {\n setup: function setup() {\n var el = document.createElement('div');\n document.body.appendChild(el);\n this.portalTarget = new external_vue_default.a(MenuPortalvue_type_script_lang_js_objectSpread({\n el: el,\n parent: this\n }, PortalTarget));\n },\n teardown: function teardown() {\n document.body.removeChild(this.portalTarget.$el);\n this.portalTarget.$el.innerHTML = '';\n this.portalTarget.$destroy();\n this.portalTarget = null;\n }\n },\n render: function render() {\n var h = arguments[0];\n if (!placeholder) placeholder = h(\"div\", {\n \"class\": \"vue-treeselect__menu-placeholder\"\n });\n return placeholder;\n }\n});\n// CONCATENATED MODULE: ./src/components/MenuPortal.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_MenuPortalvue_type_script_lang_js_ = (MenuPortalvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/MenuPortal.vue\nvar MenuPortal_render, MenuPortal_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar MenuPortal_component = normalizeComponent(\n components_MenuPortalvue_type_script_lang_js_,\n MenuPortal_render,\n MenuPortal_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var MenuPortal_api; }\nMenuPortal_component.options.__file = \"src/components/MenuPortal.vue\"\n/* harmony default export */ var MenuPortal = (MenuPortal_component.exports);\n// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Treeselect.vue?vue&type=script&lang=js&\n\n\n\n\n\n/* harmony default export */ var Treeselectvue_type_script_lang_js_ = ({\n name: 'vue-treeselect',\n mixins: [treeselectMixin],\n computed: {\n wrapperClass: function wrapperClass() {\n return {\n 'vue-treeselect': true,\n 'vue-treeselect--single': this.single,\n 'vue-treeselect--multi': this.multiple,\n 'vue-treeselect--searchable': this.searchable,\n 'vue-treeselect--disabled': this.disabled,\n 'vue-treeselect--focused': this.trigger.isFocused,\n 'vue-treeselect--has-value': this.hasValue,\n 'vue-treeselect--open': this.menu.isOpen,\n 'vue-treeselect--open-above': this.menu.placement === 'top',\n 'vue-treeselect--open-below': this.menu.placement === 'bottom',\n 'vue-treeselect--branch-nodes-disabled': this.disableBranchNodes,\n 'vue-treeselect--append-to-body': this.appendToBody\n };\n }\n },\n render: function render() {\n var h = arguments[0];\n return h(\"div\", {\n ref: \"wrapper\",\n \"class\": this.wrapperClass\n }, [h(HiddenFields), h(Control, {\n ref: \"control\"\n }), this.appendToBody ? h(MenuPortal, {\n ref: \"portal\"\n }) : h(Menu, {\n ref: \"menu\"\n })]);\n }\n});\n// CONCATENATED MODULE: ./src/components/Treeselect.vue?vue&type=script&lang=js&\n /* harmony default export */ var components_Treeselectvue_type_script_lang_js_ = (Treeselectvue_type_script_lang_js_); \n// CONCATENATED MODULE: ./src/components/Treeselect.vue\nvar Treeselect_render, Treeselect_staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar Treeselect_component = normalizeComponent(\n components_Treeselectvue_type_script_lang_js_,\n Treeselect_render,\n Treeselect_staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var Treeselect_api; }\nTreeselect_component.options.__file = \"src/components/Treeselect.vue\"\n/* harmony default export */ var Treeselect = (Treeselect_component.exports);\n// EXTERNAL MODULE: ./src/style.less\nvar style = __webpack_require__(15);\n\n// CONCATENATED MODULE: ./src/index.js\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VERSION\", function() { return VERSION; });\n/* concated harmony reexport Treeselect */__webpack_require__.d(__webpack_exports__, \"Treeselect\", function() { return Treeselect; });\n/* concated harmony reexport treeselectMixin */__webpack_require__.d(__webpack_exports__, \"treeselectMixin\", function() { return treeselectMixin; });\n/* concated harmony reexport LOAD_ROOT_OPTIONS */__webpack_require__.d(__webpack_exports__, \"LOAD_ROOT_OPTIONS\", function() { return LOAD_ROOT_OPTIONS; });\n/* concated harmony reexport LOAD_CHILDREN_OPTIONS */__webpack_require__.d(__webpack_exports__, \"LOAD_CHILDREN_OPTIONS\", function() { return LOAD_CHILDREN_OPTIONS; });\n/* concated harmony reexport ASYNC_SEARCH */__webpack_require__.d(__webpack_exports__, \"ASYNC_SEARCH\", function() { return ASYNC_SEARCH; });\n\n\n\n/* harmony default export */ var src = __webpack_exports__[\"default\"] = (Treeselect);\n\n\nvar VERSION = \"0.4.0\";\n\n/***/ })\n/******/ ]);\n//# sourceMappingURL=vue-treeselect.cjs.js.map\n\n//# sourceURL=webpack:///./node_modules/@riophae/vue-treeselect/dist/vue-treeselect.cjs.js?"); + +/***/ }), + +/***/ "./node_modules/@riophae/vue-treeselect/dist/vue-treeselect.css": +/*!**********************************************************************!*\ + !*** ./node_modules/@riophae/vue-treeselect/dist/vue-treeselect.css ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// style-loader: Adds some css to the DOM by adding a in svg, where nodeName is 'style',\n // CSS classes is defined globally wherever the style tags are declared.\n\n if (nodeName === 'defs') {\n // define flag\n this._isDefine = true;\n } else if (nodeName === 'text') {\n this._isText = true;\n }\n\n var el;\n\n if (this._isDefine) {\n var parser = defineParsers[nodeName];\n\n if (parser) {\n var def = parser.call(this, xmlNode);\n var id = xmlNode.getAttribute('id');\n\n if (id) {\n this._defs[id] = def;\n }\n }\n } else {\n var parser = nodeParsers[nodeName];\n\n if (parser) {\n el = parser.call(this, xmlNode, parentGroup);\n parentGroup.add(el);\n }\n }\n\n var child = xmlNode.firstChild;\n\n while (child) {\n if (child.nodeType === 1) {\n this._parseNode(child, el);\n } // Is text\n\n\n if (child.nodeType === 3 && this._isText) {\n this._parseText(child, el);\n }\n\n child = child.nextSibling;\n } // Quit define\n\n\n if (nodeName === 'defs') {\n this._isDefine = false;\n } else if (nodeName === 'text') {\n this._isText = false;\n }\n};\n\nSVGParser.prototype._parseText = function (xmlNode, parentGroup) {\n if (xmlNode.nodeType === 1) {\n var dx = xmlNode.getAttribute('dx') || 0;\n var dy = xmlNode.getAttribute('dy') || 0;\n this._textX += parseFloat(dx);\n this._textY += parseFloat(dy);\n }\n\n var text = new Text({\n style: {\n text: xmlNode.textContent,\n transformText: true\n },\n position: [this._textX || 0, this._textY || 0]\n });\n inheritStyle(parentGroup, text);\n parseAttributes(xmlNode, text, this._defs);\n var fontSize = text.style.fontSize;\n\n if (fontSize && fontSize < 9) {\n // PENDING\n text.style.fontSize = 9;\n text.scale = text.scale || [1, 1];\n text.scale[0] *= fontSize / 9;\n text.scale[1] *= fontSize / 9;\n }\n\n var rect = text.getBoundingRect();\n this._textX += rect.width;\n parentGroup.add(text);\n return text;\n};\n\nvar nodeParsers = {\n 'g': function (xmlNode, parentGroup) {\n var g = new Group();\n inheritStyle(parentGroup, g);\n parseAttributes(xmlNode, g, this._defs);\n return g;\n },\n 'rect': function (xmlNode, parentGroup) {\n var rect = new Rect();\n inheritStyle(parentGroup, rect);\n parseAttributes(xmlNode, rect, this._defs);\n rect.setShape({\n x: parseFloat(xmlNode.getAttribute('x') || 0),\n y: parseFloat(xmlNode.getAttribute('y') || 0),\n width: parseFloat(xmlNode.getAttribute('width') || 0),\n height: parseFloat(xmlNode.getAttribute('height') || 0)\n }); // console.log(xmlNode.getAttribute('transform'));\n // console.log(rect.transform);\n\n return rect;\n },\n 'circle': function (xmlNode, parentGroup) {\n var circle = new Circle();\n inheritStyle(parentGroup, circle);\n parseAttributes(xmlNode, circle, this._defs);\n circle.setShape({\n cx: parseFloat(xmlNode.getAttribute('cx') || 0),\n cy: parseFloat(xmlNode.getAttribute('cy') || 0),\n r: parseFloat(xmlNode.getAttribute('r') || 0)\n });\n return circle;\n },\n 'line': function (xmlNode, parentGroup) {\n var line = new Line();\n inheritStyle(parentGroup, line);\n parseAttributes(xmlNode, line, this._defs);\n line.setShape({\n x1: parseFloat(xmlNode.getAttribute('x1') || 0),\n y1: parseFloat(xmlNode.getAttribute('y1') || 0),\n x2: parseFloat(xmlNode.getAttribute('x2') || 0),\n y2: parseFloat(xmlNode.getAttribute('y2') || 0)\n });\n return line;\n },\n 'ellipse': function (xmlNode, parentGroup) {\n var ellipse = new Ellipse();\n inheritStyle(parentGroup, ellipse);\n parseAttributes(xmlNode, ellipse, this._defs);\n ellipse.setShape({\n cx: parseFloat(xmlNode.getAttribute('cx') || 0),\n cy: parseFloat(xmlNode.getAttribute('cy') || 0),\n rx: parseFloat(xmlNode.getAttribute('rx') || 0),\n ry: parseFloat(xmlNode.getAttribute('ry') || 0)\n });\n return ellipse;\n },\n 'polygon': function (xmlNode, parentGroup) {\n var points = xmlNode.getAttribute('points');\n\n if (points) {\n points = parsePoints(points);\n }\n\n var polygon = new Polygon({\n shape: {\n points: points || []\n }\n });\n inheritStyle(parentGroup, polygon);\n parseAttributes(xmlNode, polygon, this._defs);\n return polygon;\n },\n 'polyline': function (xmlNode, parentGroup) {\n var path = new Path();\n inheritStyle(parentGroup, path);\n parseAttributes(xmlNode, path, this._defs);\n var points = xmlNode.getAttribute('points');\n\n if (points) {\n points = parsePoints(points);\n }\n\n var polyline = new Polyline({\n shape: {\n points: points || []\n }\n });\n return polyline;\n },\n 'image': function (xmlNode, parentGroup) {\n var img = new ZImage();\n inheritStyle(parentGroup, img);\n parseAttributes(xmlNode, img, this._defs);\n img.setStyle({\n image: xmlNode.getAttribute('xlink:href'),\n x: xmlNode.getAttribute('x'),\n y: xmlNode.getAttribute('y'),\n width: xmlNode.getAttribute('width'),\n height: xmlNode.getAttribute('height')\n });\n return img;\n },\n 'text': function (xmlNode, parentGroup) {\n var x = xmlNode.getAttribute('x') || 0;\n var y = xmlNode.getAttribute('y') || 0;\n var dx = xmlNode.getAttribute('dx') || 0;\n var dy = xmlNode.getAttribute('dy') || 0;\n this._textX = parseFloat(x) + parseFloat(dx);\n this._textY = parseFloat(y) + parseFloat(dy);\n var g = new Group();\n inheritStyle(parentGroup, g);\n parseAttributes(xmlNode, g, this._defs);\n return g;\n },\n 'tspan': function (xmlNode, parentGroup) {\n var x = xmlNode.getAttribute('x');\n var y = xmlNode.getAttribute('y');\n\n if (x != null) {\n // new offset x\n this._textX = parseFloat(x);\n }\n\n if (y != null) {\n // new offset y\n this._textY = parseFloat(y);\n }\n\n var dx = xmlNode.getAttribute('dx') || 0;\n var dy = xmlNode.getAttribute('dy') || 0;\n var g = new Group();\n inheritStyle(parentGroup, g);\n parseAttributes(xmlNode, g, this._defs);\n this._textX += dx;\n this._textY += dy;\n return g;\n },\n 'path': function (xmlNode, parentGroup) {\n // TODO svg fill rule\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule\n // path.style.globalCompositeOperation = 'xor';\n var d = xmlNode.getAttribute('d') || ''; // Performance sensitive.\n\n var path = createFromString(d);\n inheritStyle(parentGroup, path);\n parseAttributes(xmlNode, path, this._defs);\n return path;\n }\n};\nvar defineParsers = {\n 'lineargradient': function (xmlNode) {\n var x1 = parseInt(xmlNode.getAttribute('x1') || 0, 10);\n var y1 = parseInt(xmlNode.getAttribute('y1') || 0, 10);\n var x2 = parseInt(xmlNode.getAttribute('x2') || 10, 10);\n var y2 = parseInt(xmlNode.getAttribute('y2') || 0, 10);\n var gradient = new LinearGradient(x1, y1, x2, y2);\n\n _parseGradientColorStops(xmlNode, gradient);\n\n return gradient;\n },\n 'radialgradient': function (xmlNode) {}\n};\n\nfunction _parseGradientColorStops(xmlNode, gradient) {\n var stop = xmlNode.firstChild;\n\n while (stop) {\n if (stop.nodeType === 1) {\n var offset = stop.getAttribute('offset');\n\n if (offset.indexOf('%') > 0) {\n // percentage\n offset = parseInt(offset, 10) / 100;\n } else if (offset) {\n // number from 0 to 1\n offset = parseFloat(offset);\n } else {\n offset = 0;\n }\n\n var stopColor = stop.getAttribute('stop-color') || '#000000';\n gradient.addColorStop(offset, stopColor);\n }\n\n stop = stop.nextSibling;\n }\n}\n\nfunction inheritStyle(parent, child) {\n if (parent && parent.__inheritedStyle) {\n if (!child.__inheritedStyle) {\n child.__inheritedStyle = {};\n }\n\n defaults(child.__inheritedStyle, parent.__inheritedStyle);\n }\n}\n\nfunction parsePoints(pointsString) {\n var list = trim(pointsString).split(DILIMITER_REG);\n var points = [];\n\n for (var i = 0; i < list.length; i += 2) {\n var x = parseFloat(list[i]);\n var y = parseFloat(list[i + 1]);\n points.push([x, y]);\n }\n\n return points;\n}\n\nvar attributesMap = {\n 'fill': 'fill',\n 'stroke': 'stroke',\n 'stroke-width': 'lineWidth',\n 'opacity': 'opacity',\n 'fill-opacity': 'fillOpacity',\n 'stroke-opacity': 'strokeOpacity',\n 'stroke-dasharray': 'lineDash',\n 'stroke-dashoffset': 'lineDashOffset',\n 'stroke-linecap': 'lineCap',\n 'stroke-linejoin': 'lineJoin',\n 'stroke-miterlimit': 'miterLimit',\n 'font-family': 'fontFamily',\n 'font-size': 'fontSize',\n 'font-style': 'fontStyle',\n 'font-weight': 'fontWeight',\n 'text-align': 'textAlign',\n 'alignment-baseline': 'textBaseline'\n};\n\nfunction parseAttributes(xmlNode, el, defs, onlyInlineStyle) {\n var zrStyle = el.__inheritedStyle || {};\n var isTextEl = el.type === 'text'; // TODO Shadow\n\n if (xmlNode.nodeType === 1) {\n parseTransformAttribute(xmlNode, el);\n extend(zrStyle, parseStyleAttribute(xmlNode));\n\n if (!onlyInlineStyle) {\n for (var svgAttrName in attributesMap) {\n if (attributesMap.hasOwnProperty(svgAttrName)) {\n var attrValue = xmlNode.getAttribute(svgAttrName);\n\n if (attrValue != null) {\n zrStyle[attributesMap[svgAttrName]] = attrValue;\n }\n }\n }\n }\n }\n\n var elFillProp = isTextEl ? 'textFill' : 'fill';\n var elStrokeProp = isTextEl ? 'textStroke' : 'stroke';\n el.style = el.style || new Style();\n var elStyle = el.style;\n zrStyle.fill != null && elStyle.set(elFillProp, getPaint(zrStyle.fill, defs));\n zrStyle.stroke != null && elStyle.set(elStrokeProp, getPaint(zrStyle.stroke, defs));\n each(['lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'], function (propName) {\n var elPropName = propName === 'lineWidth' && isTextEl ? 'textStrokeWidth' : propName;\n zrStyle[propName] != null && elStyle.set(elPropName, parseFloat(zrStyle[propName]));\n });\n\n if (!zrStyle.textBaseline || zrStyle.textBaseline === 'auto') {\n zrStyle.textBaseline = 'alphabetic';\n }\n\n if (zrStyle.textBaseline === 'alphabetic') {\n zrStyle.textBaseline = 'bottom';\n }\n\n if (zrStyle.textAlign === 'start') {\n zrStyle.textAlign = 'left';\n }\n\n if (zrStyle.textAlign === 'end') {\n zrStyle.textAlign = 'right';\n }\n\n each(['lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign', 'textBaseline'], function (propName) {\n zrStyle[propName] != null && elStyle.set(propName, zrStyle[propName]);\n });\n\n if (zrStyle.lineDash) {\n el.style.lineDash = trim(zrStyle.lineDash).split(DILIMITER_REG);\n }\n\n if (elStyle[elStrokeProp] && elStyle[elStrokeProp] !== 'none') {\n // enable stroke\n el[elStrokeProp] = true;\n }\n\n el.__inheritedStyle = zrStyle;\n}\n\nvar urlRegex = /url\\(\\s*#(.*?)\\)/;\n\nfunction getPaint(str, defs) {\n // if (str === 'none') {\n // return;\n // }\n var urlMatch = defs && str && str.match(urlRegex);\n\n if (urlMatch) {\n var url = trim(urlMatch[1]);\n var def = defs[url];\n return def;\n }\n\n return str;\n}\n\nvar transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\\(([\\-\\s0-9\\.e,]*)\\)/g;\n\nfunction parseTransformAttribute(xmlNode, node) {\n var transform = xmlNode.getAttribute('transform');\n\n if (transform) {\n transform = transform.replace(/,/g, ' ');\n var m = null;\n var transformOps = [];\n transform.replace(transformRegex, function (str, type, value) {\n transformOps.push(type, value);\n });\n\n for (var i = transformOps.length - 1; i > 0; i -= 2) {\n var value = transformOps[i];\n var type = transformOps[i - 1];\n m = m || matrix.create();\n\n switch (type) {\n case 'translate':\n value = trim(value).split(DILIMITER_REG);\n matrix.translate(m, m, [parseFloat(value[0]), parseFloat(value[1] || 0)]);\n break;\n\n case 'scale':\n value = trim(value).split(DILIMITER_REG);\n matrix.scale(m, m, [parseFloat(value[0]), parseFloat(value[1] || value[0])]);\n break;\n\n case 'rotate':\n value = trim(value).split(DILIMITER_REG);\n matrix.rotate(m, m, parseFloat(value[0]));\n break;\n\n case 'skew':\n value = trim(value).split(DILIMITER_REG);\n console.warn('Skew transform is not supported yet');\n break;\n\n case 'matrix':\n var value = trim(value).split(DILIMITER_REG);\n m[0] = parseFloat(value[0]);\n m[1] = parseFloat(value[1]);\n m[2] = parseFloat(value[2]);\n m[3] = parseFloat(value[3]);\n m[4] = parseFloat(value[4]);\n m[5] = parseFloat(value[5]);\n break;\n }\n }\n\n node.setLocalTransform(m);\n }\n} // Value may contain space.\n\n\nvar styleRegex = /([^\\s:;]+)\\s*:\\s*([^:;]+)/g;\n\nfunction parseStyleAttribute(xmlNode) {\n var style = xmlNode.getAttribute('style');\n var result = {};\n\n if (!style) {\n return result;\n }\n\n var styleList = {};\n styleRegex.lastIndex = 0;\n var styleRegResult;\n\n while ((styleRegResult = styleRegex.exec(style)) != null) {\n styleList[styleRegResult[1]] = styleRegResult[2];\n }\n\n for (var svgAttrName in attributesMap) {\n if (attributesMap.hasOwnProperty(svgAttrName) && styleList[svgAttrName] != null) {\n result[attributesMap[svgAttrName]] = styleList[svgAttrName];\n }\n }\n\n return result;\n}\n/**\n * @param {Array.} viewBoxRect\n * @param {number} width\n * @param {number} height\n * @return {Object} {scale, position}\n */\n\n\nfunction makeViewBoxTransform(viewBoxRect, width, height) {\n var scaleX = width / viewBoxRect.width;\n var scaleY = height / viewBoxRect.height;\n var scale = Math.min(scaleX, scaleY); // preserveAspectRatio 'xMidYMid'\n\n var viewBoxScale = [scale, scale];\n var viewBoxPosition = [-(viewBoxRect.x + viewBoxRect.width / 2) * scale + width / 2, -(viewBoxRect.y + viewBoxRect.height / 2) * scale + height / 2];\n return {\n scale: viewBoxScale,\n position: viewBoxPosition\n };\n}\n/**\n * @param {string|XMLElement} xml\n * @param {Object} [opt]\n * @param {number} [opt.width] Default width if svg width not specified or is a percent value.\n * @param {number} [opt.height] Default height if svg height not specified or is a percent value.\n * @param {boolean} [opt.ignoreViewBox]\n * @param {boolean} [opt.ignoreRootClip]\n * @return {Object} result:\n * {\n * root: Group, The root of the the result tree of zrender shapes,\n * width: number, the viewport width of the SVG,\n * height: number, the viewport height of the SVG,\n * viewBoxRect: {x, y, width, height}, the declared viewBox rect of the SVG, if exists,\n * viewBoxTransform: the {scale, position} calculated by viewBox and viewport, is exists.\n * }\n */\n\n\nfunction parseSVG(xml, opt) {\n var parser = new SVGParser();\n return parser.parse(xml, opt);\n}\n\nexports.parseXML = parseXML;\nexports.makeViewBoxTransform = makeViewBoxTransform;\nexports.parseSVG = parseSVG;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/tool/parseSVG.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/tool/path.js": +/*!***********************************************!*\ + !*** ./node_modules/zrender/lib/tool/path.js ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var Path = __webpack_require__(/*! ../graphic/Path */ \"./node_modules/zrender/lib/graphic/Path.js\");\n\nvar PathProxy = __webpack_require__(/*! ../core/PathProxy */ \"./node_modules/zrender/lib/core/PathProxy.js\");\n\nvar transformPath = __webpack_require__(/*! ./transformPath */ \"./node_modules/zrender/lib/tool/transformPath.js\");\n\n// command chars\n// var cc = [\n// 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',\n// 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'\n// ];\nvar mathSqrt = Math.sqrt;\nvar mathSin = Math.sin;\nvar mathCos = Math.cos;\nvar PI = Math.PI;\n\nvar vMag = function (v) {\n return Math.sqrt(v[0] * v[0] + v[1] * v[1]);\n};\n\nvar vRatio = function (u, v) {\n return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));\n};\n\nvar vAngle = function (u, v) {\n return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v));\n};\n\nfunction processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {\n var psi = psiDeg * (PI / 180.0);\n var xp = mathCos(psi) * (x1 - x2) / 2.0 + mathSin(psi) * (y1 - y2) / 2.0;\n var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0 + mathCos(psi) * (y1 - y2) / 2.0;\n var lambda = xp * xp / (rx * rx) + yp * yp / (ry * ry);\n\n if (lambda > 1) {\n rx *= mathSqrt(lambda);\n ry *= mathSqrt(lambda);\n }\n\n var f = (fa === fs ? -1 : 1) * mathSqrt((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (yp * yp) + ry * ry * (xp * xp))) || 0;\n var cxp = f * rx * yp / ry;\n var cyp = f * -ry * xp / rx;\n var cx = (x1 + x2) / 2.0 + mathCos(psi) * cxp - mathSin(psi) * cyp;\n var cy = (y1 + y2) / 2.0 + mathSin(psi) * cxp + mathCos(psi) * cyp;\n var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]);\n var u = [(xp - cxp) / rx, (yp - cyp) / ry];\n var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];\n var dTheta = vAngle(u, v);\n\n if (vRatio(u, v) <= -1) {\n dTheta = PI;\n }\n\n if (vRatio(u, v) >= 1) {\n dTheta = 0;\n }\n\n if (fs === 0 && dTheta > 0) {\n dTheta = dTheta - 2 * PI;\n }\n\n if (fs === 1 && dTheta < 0) {\n dTheta = dTheta + 2 * PI;\n }\n\n path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);\n}\n\nvar commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig; // Consider case:\n// (1) delimiter can be comma or space, where continuous commas\n// or spaces should be seen as one comma.\n// (2) value can be like:\n// '2e-4', 'l.5.9' (ignore 0), 'M-10-10', 'l-2.43e-1,34.9983',\n// 'l-.5E1,54', '121-23-44-11' (no delimiter)\n\nvar numberReg = /-?([0-9]*\\.)?[0-9]+([eE]-?[0-9]+)?/g; // var valueSplitReg = /[\\s,]+/;\n\nfunction createPathProxyFromString(data) {\n if (!data) {\n return new PathProxy();\n } // var data = data.replace(/-/g, ' -')\n // .replace(/ /g, ' ')\n // .replace(/ /g, ',')\n // .replace(/,,/g, ',');\n // var n;\n // create pipes so that we can split the data\n // for (n = 0; n < cc.length; n++) {\n // cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);\n // }\n // data = data.replace(/-/g, ',-');\n // create array\n // var arr = cs.split('|');\n // init context point\n\n\n var cpx = 0;\n var cpy = 0;\n var subpathX = cpx;\n var subpathY = cpy;\n var prevCmd;\n var path = new PathProxy();\n var CMD = PathProxy.CMD; // commandReg.lastIndex = 0;\n // var cmdResult;\n // while ((cmdResult = commandReg.exec(data)) != null) {\n // var cmdStr = cmdResult[1];\n // var cmdContent = cmdResult[2];\n\n var cmdList = data.match(commandReg);\n\n for (var l = 0; l < cmdList.length; l++) {\n var cmdText = cmdList[l];\n var cmdStr = cmdText.charAt(0);\n var cmd; // String#split is faster a little bit than String#replace or RegExp#exec.\n // var p = cmdContent.split(valueSplitReg);\n // var pLen = 0;\n // for (var i = 0; i < p.length; i++) {\n // // '' and other invalid str => NaN\n // var val = parseFloat(p[i]);\n // !isNaN(val) && (p[pLen++] = val);\n // }\n\n var p = cmdText.match(numberReg) || [];\n var pLen = p.length;\n\n for (var i = 0; i < pLen; i++) {\n p[i] = parseFloat(p[i]);\n }\n\n var off = 0;\n\n while (off < pLen) {\n var ctlPtx;\n var ctlPty;\n var rx;\n var ry;\n var psi;\n var fa;\n var fs;\n var x1 = cpx;\n var y1 = cpy; // convert l, H, h, V, and v to L\n\n switch (cmdStr) {\n case 'l':\n cpx += p[off++];\n cpy += p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'L':\n cpx = p[off++];\n cpy = p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'm':\n cpx += p[off++];\n cpy += p[off++];\n cmd = CMD.M;\n path.addData(cmd, cpx, cpy);\n subpathX = cpx;\n subpathY = cpy;\n cmdStr = 'l';\n break;\n\n case 'M':\n cpx = p[off++];\n cpy = p[off++];\n cmd = CMD.M;\n path.addData(cmd, cpx, cpy);\n subpathX = cpx;\n subpathY = cpy;\n cmdStr = 'L';\n break;\n\n case 'h':\n cpx += p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'H':\n cpx = p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'v':\n cpy += p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'V':\n cpy = p[off++];\n cmd = CMD.L;\n path.addData(cmd, cpx, cpy);\n break;\n\n case 'C':\n cmd = CMD.C;\n path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]);\n cpx = p[off - 2];\n cpy = p[off - 1];\n break;\n\n case 'c':\n cmd = CMD.C;\n path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy);\n cpx += p[off - 2];\n cpy += p[off - 1];\n break;\n\n case 'S':\n ctlPtx = cpx;\n ctlPty = cpy;\n var len = path.len();\n var pathData = path.data;\n\n if (prevCmd === CMD.C) {\n ctlPtx += cpx - pathData[len - 4];\n ctlPty += cpy - pathData[len - 3];\n }\n\n cmd = CMD.C;\n x1 = p[off++];\n y1 = p[off++];\n cpx = p[off++];\n cpy = p[off++];\n path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);\n break;\n\n case 's':\n ctlPtx = cpx;\n ctlPty = cpy;\n var len = path.len();\n var pathData = path.data;\n\n if (prevCmd === CMD.C) {\n ctlPtx += cpx - pathData[len - 4];\n ctlPty += cpy - pathData[len - 3];\n }\n\n cmd = CMD.C;\n x1 = cpx + p[off++];\n y1 = cpy + p[off++];\n cpx += p[off++];\n cpy += p[off++];\n path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);\n break;\n\n case 'Q':\n x1 = p[off++];\n y1 = p[off++];\n cpx = p[off++];\n cpy = p[off++];\n cmd = CMD.Q;\n path.addData(cmd, x1, y1, cpx, cpy);\n break;\n\n case 'q':\n x1 = p[off++] + cpx;\n y1 = p[off++] + cpy;\n cpx += p[off++];\n cpy += p[off++];\n cmd = CMD.Q;\n path.addData(cmd, x1, y1, cpx, cpy);\n break;\n\n case 'T':\n ctlPtx = cpx;\n ctlPty = cpy;\n var len = path.len();\n var pathData = path.data;\n\n if (prevCmd === CMD.Q) {\n ctlPtx += cpx - pathData[len - 4];\n ctlPty += cpy - pathData[len - 3];\n }\n\n cpx = p[off++];\n cpy = p[off++];\n cmd = CMD.Q;\n path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);\n break;\n\n case 't':\n ctlPtx = cpx;\n ctlPty = cpy;\n var len = path.len();\n var pathData = path.data;\n\n if (prevCmd === CMD.Q) {\n ctlPtx += cpx - pathData[len - 4];\n ctlPty += cpy - pathData[len - 3];\n }\n\n cpx += p[off++];\n cpy += p[off++];\n cmd = CMD.Q;\n path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);\n break;\n\n case 'A':\n rx = p[off++];\n ry = p[off++];\n psi = p[off++];\n fa = p[off++];\n fs = p[off++];\n x1 = cpx, y1 = cpy;\n cpx = p[off++];\n cpy = p[off++];\n cmd = CMD.A;\n processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);\n break;\n\n case 'a':\n rx = p[off++];\n ry = p[off++];\n psi = p[off++];\n fa = p[off++];\n fs = p[off++];\n x1 = cpx, y1 = cpy;\n cpx += p[off++];\n cpy += p[off++];\n cmd = CMD.A;\n processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path);\n break;\n }\n }\n\n if (cmdStr === 'z' || cmdStr === 'Z') {\n cmd = CMD.Z;\n path.addData(cmd); // z may be in the middle of the path.\n\n cpx = subpathX;\n cpy = subpathY;\n }\n\n prevCmd = cmd;\n }\n\n path.toStatic();\n return path;\n} // TODO Optimize double memory cost problem\n\n\nfunction createPathOptions(str, opts) {\n var pathProxy = createPathProxyFromString(str);\n opts = opts || {};\n\n opts.buildPath = function (path) {\n if (path.setData) {\n path.setData(pathProxy.data); // Svg and vml renderer don't have context\n\n var ctx = path.getContext();\n\n if (ctx) {\n path.rebuildPath(ctx);\n }\n } else {\n var ctx = path;\n pathProxy.rebuildPath(ctx);\n }\n };\n\n opts.applyTransform = function (m) {\n transformPath(pathProxy, m);\n this.dirty(true);\n };\n\n return opts;\n}\n/**\n * Create a Path object from path string data\n * http://www.w3.org/TR/SVG/paths.html#PathData\n * @param {Object} opts Other options\n */\n\n\nfunction createFromString(str, opts) {\n return new Path(createPathOptions(str, opts));\n}\n/**\n * Create a Path class from path string data\n * @param {string} str\n * @param {Object} opts Other options\n */\n\n\nfunction extendFromString(str, opts) {\n return Path.extend(createPathOptions(str, opts));\n}\n/**\n * Merge multiple paths\n */\n// TODO Apply transform\n// TODO stroke dash\n// TODO Optimize double memory cost problem\n\n\nfunction mergePath(pathEls, opts) {\n var pathList = [];\n var len = pathEls.length;\n\n for (var i = 0; i < len; i++) {\n var pathEl = pathEls[i];\n\n if (!pathEl.path) {\n pathEl.createPathProxy();\n }\n\n if (pathEl.__dirtyPath) {\n pathEl.buildPath(pathEl.path, pathEl.shape, true);\n }\n\n pathList.push(pathEl.path);\n }\n\n var pathBundle = new Path(opts); // Need path proxy.\n\n pathBundle.createPathProxy();\n\n pathBundle.buildPath = function (path) {\n path.appendPath(pathList); // Svg and vml renderer don't have context\n\n var ctx = path.getContext();\n\n if (ctx) {\n path.rebuildPath(ctx);\n }\n };\n\n return pathBundle;\n}\n\nexports.createFromString = createFromString;\nexports.extendFromString = extendFromString;\nexports.mergePath = mergePath;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/tool/path.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/tool/transformPath.js": +/*!********************************************************!*\ + !*** ./node_modules/zrender/lib/tool/transformPath.js ***! + \********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var PathProxy = __webpack_require__(/*! ../core/PathProxy */ \"./node_modules/zrender/lib/core/PathProxy.js\");\n\nvar _vector = __webpack_require__(/*! ../core/vector */ \"./node_modules/zrender/lib/core/vector.js\");\n\nvar v2ApplyTransform = _vector.applyTransform;\nvar CMD = PathProxy.CMD;\nvar points = [[], [], []];\nvar mathSqrt = Math.sqrt;\nvar mathAtan2 = Math.atan2;\n\nfunction _default(path, m) {\n var data = path.data;\n var cmd;\n var nPoint;\n var i;\n var j;\n var k;\n var p;\n var M = CMD.M;\n var C = CMD.C;\n var L = CMD.L;\n var R = CMD.R;\n var A = CMD.A;\n var Q = CMD.Q;\n\n for (i = 0, j = 0; i < data.length;) {\n cmd = data[i++];\n j = i;\n nPoint = 0;\n\n switch (cmd) {\n case M:\n nPoint = 1;\n break;\n\n case L:\n nPoint = 1;\n break;\n\n case C:\n nPoint = 3;\n break;\n\n case Q:\n nPoint = 2;\n break;\n\n case A:\n var x = m[4];\n var y = m[5];\n var sx = mathSqrt(m[0] * m[0] + m[1] * m[1]);\n var sy = mathSqrt(m[2] * m[2] + m[3] * m[3]);\n var angle = mathAtan2(-m[1] / sy, m[0] / sx); // cx\n\n data[i] *= sx;\n data[i++] += x; // cy\n\n data[i] *= sy;\n data[i++] += y; // Scale rx and ry\n // FIXME Assume psi is 0 here\n\n data[i++] *= sx;\n data[i++] *= sy; // Start angle\n\n data[i++] += angle; // end angle\n\n data[i++] += angle; // FIXME psi\n\n i += 2;\n j = i;\n break;\n\n case R:\n // x0, y0\n p[0] = data[i++];\n p[1] = data[i++];\n v2ApplyTransform(p, p, m);\n data[j++] = p[0];\n data[j++] = p[1]; // x1, y1\n\n p[0] += data[i++];\n p[1] += data[i++];\n v2ApplyTransform(p, p, m);\n data[j++] = p[0];\n data[j++] = p[1];\n }\n\n for (k = 0; k < nPoint; k++) {\n var p = points[k];\n p[0] = data[i++];\n p[1] = data[i++];\n v2ApplyTransform(p, p, m); // Write back\n\n data[j++] = p[0];\n data[j++] = p[1];\n }\n }\n}\n\nmodule.exports = _default;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/tool/transformPath.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/vml/Painter.js": +/*!*************************************************!*\ + !*** ./node_modules/zrender/lib/vml/Painter.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var logError = __webpack_require__(/*! ../core/log */ \"./node_modules/zrender/lib/core/log.js\");\n\nvar vmlCore = __webpack_require__(/*! ./core */ \"./node_modules/zrender/lib/vml/core.js\");\n\nvar _util = __webpack_require__(/*! ../core/util */ \"./node_modules/zrender/lib/core/util.js\");\n\nvar each = _util.each;\n\n/**\n * VML Painter.\n *\n * @module zrender/vml/Painter\n */\nfunction parseInt10(val) {\n return parseInt(val, 10);\n}\n/**\n * @alias module:zrender/vml/Painter\n */\n\n\nfunction VMLPainter(root, storage) {\n vmlCore.initVML();\n this.root = root;\n this.storage = storage;\n var vmlViewport = document.createElement('div');\n var vmlRoot = document.createElement('div');\n vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;';\n vmlRoot.style.cssText = 'position:absolute;left:0;top:0;';\n root.appendChild(vmlViewport);\n this._vmlRoot = vmlRoot;\n this._vmlViewport = vmlViewport;\n this.resize(); // Modify storage\n\n var oldDelFromStorage = storage.delFromStorage;\n var oldAddToStorage = storage.addToStorage;\n\n storage.delFromStorage = function (el) {\n oldDelFromStorage.call(storage, el);\n\n if (el) {\n el.onRemove && el.onRemove(vmlRoot);\n }\n };\n\n storage.addToStorage = function (el) {\n // Displayable already has a vml node\n el.onAdd && el.onAdd(vmlRoot);\n oldAddToStorage.call(storage, el);\n };\n\n this._firstPaint = true;\n}\n\nVMLPainter.prototype = {\n constructor: VMLPainter,\n getType: function () {\n return 'vml';\n },\n\n /**\n * @return {HTMLDivElement}\n */\n getViewportRoot: function () {\n return this._vmlViewport;\n },\n getViewportRootOffset: function () {\n var viewportRoot = this.getViewportRoot();\n\n if (viewportRoot) {\n return {\n offsetLeft: viewportRoot.offsetLeft || 0,\n offsetTop: viewportRoot.offsetTop || 0\n };\n }\n },\n\n /**\n * 刷新\n */\n refresh: function () {\n var list = this.storage.getDisplayList(true, true);\n\n this._paintList(list);\n },\n _paintList: function (list) {\n var vmlRoot = this._vmlRoot;\n\n for (var i = 0; i < list.length; i++) {\n var el = list[i];\n\n if (el.invisible || el.ignore) {\n if (!el.__alreadyNotVisible) {\n el.onRemove(vmlRoot);\n } // Set as already invisible\n\n\n el.__alreadyNotVisible = true;\n } else {\n if (el.__alreadyNotVisible) {\n el.onAdd(vmlRoot);\n }\n\n el.__alreadyNotVisible = false;\n\n if (el.__dirty) {\n el.beforeBrush && el.beforeBrush();\n (el.brushVML || el.brush).call(el, vmlRoot);\n el.afterBrush && el.afterBrush();\n }\n }\n\n el.__dirty = false;\n }\n\n if (this._firstPaint) {\n // Detached from document at first time\n // to avoid page refreshing too many times\n // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变\n this._vmlViewport.appendChild(vmlRoot);\n\n this._firstPaint = false;\n }\n },\n resize: function (width, height) {\n var width = width == null ? this._getWidth() : width;\n var height = height == null ? this._getHeight() : height;\n\n if (this._width !== width || this._height !== height) {\n this._width = width;\n this._height = height;\n var vmlViewportStyle = this._vmlViewport.style;\n vmlViewportStyle.width = width + 'px';\n vmlViewportStyle.height = height + 'px';\n }\n },\n dispose: function () {\n this.root.innerHTML = '';\n this._vmlRoot = this._vmlViewport = this.storage = null;\n },\n getWidth: function () {\n return this._width;\n },\n getHeight: function () {\n return this._height;\n },\n clear: function () {\n if (this._vmlViewport) {\n this.root.removeChild(this._vmlViewport);\n }\n },\n _getWidth: function () {\n var root = this.root;\n var stl = root.currentStyle;\n return (root.clientWidth || parseInt10(stl.width)) - parseInt10(stl.paddingLeft) - parseInt10(stl.paddingRight) | 0;\n },\n _getHeight: function () {\n var root = this.root;\n var stl = root.currentStyle;\n return (root.clientHeight || parseInt10(stl.height)) - parseInt10(stl.paddingTop) - parseInt10(stl.paddingBottom) | 0;\n }\n}; // Not supported methods\n\nfunction createMethodNotSupport(method) {\n return function () {\n logError('In IE8.0 VML mode painter not support method \"' + method + '\"');\n };\n} // Unsupported methods\n\n\neach(['getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers', 'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage'], function (name) {\n VMLPainter.prototype[name] = createMethodNotSupport(name);\n});\nvar _default = VMLPainter;\nmodule.exports = _default;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/vml/Painter.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/vml/core.js": +/*!**********************************************!*\ + !*** ./node_modules/zrender/lib/vml/core.js ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var env = __webpack_require__(/*! ../core/env */ \"./node_modules/zrender/lib/core/env.js\");\n\nvar urn = 'urn:schemas-microsoft-com:vml';\nvar win = typeof window === 'undefined' ? null : window;\nvar vmlInited = false;\nvar doc = win && win.document;\n\nfunction createNode(tagName) {\n return doCreateNode(tagName);\n} // Avoid assign to an exported variable, for transforming to cjs.\n\n\nvar doCreateNode;\n\nif (doc && !env.canvasSupported) {\n try {\n !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn);\n\n doCreateNode = function (tagName) {\n return doc.createElement('');\n };\n } catch (e) {\n doCreateNode = function (tagName) {\n return doc.createElement('<' + tagName + ' xmlns=\"' + urn + '\" class=\"zrvml\">');\n };\n }\n} // From raphael\n\n\nfunction initVML() {\n if (vmlInited || !doc) {\n return;\n }\n\n vmlInited = true;\n var styleSheets = doc.styleSheets;\n\n if (styleSheets.length < 31) {\n doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)');\n } else {\n // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx\n styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)');\n }\n}\n\nexports.doc = doc;\nexports.createNode = createNode;\nexports.initVML = initVML;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/vml/core.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/vml/graphic.js": +/*!*************************************************!*\ + !*** ./node_modules/zrender/lib/vml/graphic.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var env = __webpack_require__(/*! ../core/env */ \"./node_modules/zrender/lib/core/env.js\");\n\nvar _vector = __webpack_require__(/*! ../core/vector */ \"./node_modules/zrender/lib/core/vector.js\");\n\nvar applyTransform = _vector.applyTransform;\n\nvar BoundingRect = __webpack_require__(/*! ../core/BoundingRect */ \"./node_modules/zrender/lib/core/BoundingRect.js\");\n\nvar colorTool = __webpack_require__(/*! ../tool/color */ \"./node_modules/zrender/lib/tool/color.js\");\n\nvar textContain = __webpack_require__(/*! ../contain/text */ \"./node_modules/zrender/lib/contain/text.js\");\n\nvar textHelper = __webpack_require__(/*! ../graphic/helper/text */ \"./node_modules/zrender/lib/graphic/helper/text.js\");\n\nvar RectText = __webpack_require__(/*! ../graphic/mixin/RectText */ \"./node_modules/zrender/lib/graphic/mixin/RectText.js\");\n\nvar Displayable = __webpack_require__(/*! ../graphic/Displayable */ \"./node_modules/zrender/lib/graphic/Displayable.js\");\n\nvar ZImage = __webpack_require__(/*! ../graphic/Image */ \"./node_modules/zrender/lib/graphic/Image.js\");\n\nvar Text = __webpack_require__(/*! ../graphic/Text */ \"./node_modules/zrender/lib/graphic/Text.js\");\n\nvar Path = __webpack_require__(/*! ../graphic/Path */ \"./node_modules/zrender/lib/graphic/Path.js\");\n\nvar PathProxy = __webpack_require__(/*! ../core/PathProxy */ \"./node_modules/zrender/lib/core/PathProxy.js\");\n\nvar Gradient = __webpack_require__(/*! ../graphic/Gradient */ \"./node_modules/zrender/lib/graphic/Gradient.js\");\n\nvar vmlCore = __webpack_require__(/*! ./core */ \"./node_modules/zrender/lib/vml/core.js\");\n\n// http://www.w3.org/TR/NOTE-VML\n// TODO Use proxy like svg instead of overwrite brush methods\nvar CMD = PathProxy.CMD;\nvar round = Math.round;\nvar sqrt = Math.sqrt;\nvar abs = Math.abs;\nvar cos = Math.cos;\nvar sin = Math.sin;\nvar mathMax = Math.max;\n\nif (!env.canvasSupported) {\n var comma = ',';\n var imageTransformPrefix = 'progid:DXImageTransform.Microsoft';\n var Z = 21600;\n var Z2 = Z / 2;\n var ZLEVEL_BASE = 100000;\n var Z_BASE = 1000;\n\n var initRootElStyle = function (el) {\n el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;';\n el.coordsize = Z + ',' + Z;\n el.coordorigin = '0,0';\n };\n\n var encodeHtmlAttribute = function (s) {\n return String(s).replace(/&/g, '&').replace(/\"/g, '"');\n };\n\n var rgb2Str = function (r, g, b) {\n return 'rgb(' + [r, g, b].join(',') + ')';\n };\n\n var append = function (parent, child) {\n if (child && parent && child.parentNode !== parent) {\n parent.appendChild(child);\n }\n };\n\n var remove = function (parent, child) {\n if (child && parent && child.parentNode === parent) {\n parent.removeChild(child);\n }\n };\n\n var getZIndex = function (zlevel, z, z2) {\n // z 的取值范围为 [0, 1000]\n return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE + z2;\n };\n\n var parsePercent = textHelper.parsePercent;\n /***************************************************\n * PATH\n **************************************************/\n\n var setColorAndOpacity = function (el, color, opacity) {\n var colorArr = colorTool.parse(color);\n opacity = +opacity;\n\n if (isNaN(opacity)) {\n opacity = 1;\n }\n\n if (colorArr) {\n el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]);\n el.opacity = opacity * colorArr[3];\n }\n };\n\n var getColorAndAlpha = function (color) {\n var colorArr = colorTool.parse(color);\n return [rgb2Str(colorArr[0], colorArr[1], colorArr[2]), colorArr[3]];\n };\n\n var updateFillNode = function (el, style, zrEl) {\n // TODO pattern\n var fill = style.fill;\n\n if (fill != null) {\n // Modified from excanvas\n if (fill instanceof Gradient) {\n var gradientType;\n var angle = 0;\n var focus = [0, 0]; // additional offset\n\n var shift = 0; // scale factor for offset\n\n var expansion = 1;\n var rect = zrEl.getBoundingRect();\n var rectWidth = rect.width;\n var rectHeight = rect.height;\n\n if (fill.type === 'linear') {\n gradientType = 'gradient';\n var transform = zrEl.transform;\n var p0 = [fill.x * rectWidth, fill.y * rectHeight];\n var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight];\n\n if (transform) {\n applyTransform(p0, p0, transform);\n applyTransform(p1, p1, transform);\n }\n\n var dx = p1[0] - p0[0];\n var dy = p1[1] - p0[1];\n angle = Math.atan2(dx, dy) * 180 / Math.PI; // The angle should be a non-negative number.\n\n if (angle < 0) {\n angle += 360;\n } // Very small angles produce an unexpected result because they are\n // converted to a scientific notation string.\n\n\n if (angle < 1e-6) {\n angle = 0;\n }\n } else {\n gradientType = 'gradientradial';\n var p0 = [fill.x * rectWidth, fill.y * rectHeight];\n var transform = zrEl.transform;\n var scale = zrEl.scale;\n var width = rectWidth;\n var height = rectHeight;\n focus = [// Percent in bounding rect\n (p0[0] - rect.x) / width, (p0[1] - rect.y) / height];\n\n if (transform) {\n applyTransform(p0, p0, transform);\n }\n\n width /= scale[0] * Z;\n height /= scale[1] * Z;\n var dimension = mathMax(width, height);\n shift = 2 * 0 / dimension;\n expansion = 2 * fill.r / dimension - shift;\n } // We need to sort the color stops in ascending order by offset,\n // otherwise IE won't interpret it correctly.\n\n\n var stops = fill.colorStops.slice();\n stops.sort(function (cs1, cs2) {\n return cs1.offset - cs2.offset;\n });\n var length = stops.length; // Color and alpha list of first and last stop\n\n var colorAndAlphaList = [];\n var colors = [];\n\n for (var i = 0; i < length; i++) {\n var stop = stops[i];\n var colorAndAlpha = getColorAndAlpha(stop.color);\n colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]);\n\n if (i === 0 || i === length - 1) {\n colorAndAlphaList.push(colorAndAlpha);\n }\n }\n\n if (length >= 2) {\n var color1 = colorAndAlphaList[0][0];\n var color2 = colorAndAlphaList[1][0];\n var opacity1 = colorAndAlphaList[0][1] * style.opacity;\n var opacity2 = colorAndAlphaList[1][1] * style.opacity;\n el.type = gradientType;\n el.method = 'none';\n el.focus = '100%';\n el.angle = angle;\n el.color = color1;\n el.color2 = color2;\n el.colors = colors.join(','); // When colors attribute is used, the meanings of opacity and o:opacity2\n // are reversed.\n\n el.opacity = opacity2; // FIXME g_o_:opacity ?\n\n el.opacity2 = opacity1;\n }\n\n if (gradientType === 'radial') {\n el.focusposition = focus.join(',');\n }\n } else {\n // FIXME Change from Gradient fill to color fill\n setColorAndOpacity(el, fill, style.opacity);\n }\n }\n };\n\n var updateStrokeNode = function (el, style) {\n // if (style.lineJoin != null) {\n // el.joinstyle = style.lineJoin;\n // }\n // if (style.miterLimit != null) {\n // el.miterlimit = style.miterLimit * Z;\n // }\n // if (style.lineCap != null) {\n // el.endcap = style.lineCap;\n // }\n if (style.lineDash) {\n el.dashstyle = style.lineDash.join(' ');\n }\n\n if (style.stroke != null && !(style.stroke instanceof Gradient)) {\n setColorAndOpacity(el, style.stroke, style.opacity);\n }\n };\n\n var updateFillAndStroke = function (vmlEl, type, style, zrEl) {\n var isFill = type === 'fill';\n var el = vmlEl.getElementsByTagName(type)[0]; // Stroke must have lineWidth\n\n if (style[type] != null && style[type] !== 'none' && (isFill || !isFill && style.lineWidth)) {\n vmlEl[isFill ? 'filled' : 'stroked'] = 'true'; // FIXME Remove before updating, or set `colors` will throw error\n\n if (style[type] instanceof Gradient) {\n remove(vmlEl, el);\n }\n\n if (!el) {\n el = vmlCore.createNode(type);\n }\n\n isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style);\n append(vmlEl, el);\n } else {\n vmlEl[isFill ? 'filled' : 'stroked'] = 'false';\n remove(vmlEl, el);\n }\n };\n\n var points = [[], [], []];\n\n var pathDataToString = function (path, m) {\n var M = CMD.M;\n var C = CMD.C;\n var L = CMD.L;\n var A = CMD.A;\n var Q = CMD.Q;\n var str = [];\n var nPoint;\n var cmdStr;\n var cmd;\n var i;\n var xi;\n var yi;\n var data = path.data;\n var dataLength = path.len();\n\n for (i = 0; i < dataLength;) {\n cmd = data[i++];\n cmdStr = '';\n nPoint = 0;\n\n switch (cmd) {\n case M:\n cmdStr = ' m ';\n nPoint = 1;\n xi = data[i++];\n yi = data[i++];\n points[0][0] = xi;\n points[0][1] = yi;\n break;\n\n case L:\n cmdStr = ' l ';\n nPoint = 1;\n xi = data[i++];\n yi = data[i++];\n points[0][0] = xi;\n points[0][1] = yi;\n break;\n\n case Q:\n case C:\n cmdStr = ' c ';\n nPoint = 3;\n var x1 = data[i++];\n var y1 = data[i++];\n var x2 = data[i++];\n var y2 = data[i++];\n var x3;\n var y3;\n\n if (cmd === Q) {\n // Convert quadratic to cubic using degree elevation\n x3 = x2;\n y3 = y2;\n x2 = (x2 + 2 * x1) / 3;\n y2 = (y2 + 2 * y1) / 3;\n x1 = (xi + 2 * x1) / 3;\n y1 = (yi + 2 * y1) / 3;\n } else {\n x3 = data[i++];\n y3 = data[i++];\n }\n\n points[0][0] = x1;\n points[0][1] = y1;\n points[1][0] = x2;\n points[1][1] = y2;\n points[2][0] = x3;\n points[2][1] = y3;\n xi = x3;\n yi = y3;\n break;\n\n case A:\n var x = 0;\n var y = 0;\n var sx = 1;\n var sy = 1;\n var angle = 0;\n\n if (m) {\n // Extract SRT from matrix\n x = m[4];\n y = m[5];\n sx = sqrt(m[0] * m[0] + m[1] * m[1]);\n sy = sqrt(m[2] * m[2] + m[3] * m[3]);\n angle = Math.atan2(-m[1] / sy, m[0] / sx);\n }\n\n var cx = data[i++];\n var cy = data[i++];\n var rx = data[i++];\n var ry = data[i++];\n var startAngle = data[i++] + angle;\n var endAngle = data[i++] + startAngle + angle; // FIXME\n // var psi = data[i++];\n\n i++;\n var clockwise = data[i++];\n var x0 = cx + cos(startAngle) * rx;\n var y0 = cy + sin(startAngle) * ry;\n var x1 = cx + cos(endAngle) * rx;\n var y1 = cy + sin(endAngle) * ry;\n var type = clockwise ? ' wa ' : ' at ';\n\n if (Math.abs(x0 - x1) < 1e-4) {\n // IE won't render arches drawn counter clockwise if x0 == x1.\n if (Math.abs(endAngle - startAngle) > 1e-2) {\n // Offset x0 by 1/80 of a pixel. Use something\n // that can be represented in binary\n if (clockwise) {\n x0 += 270 / Z;\n }\n } else {\n // Avoid case draw full circle\n if (Math.abs(y0 - cy) < 1e-4) {\n if (clockwise && x0 < cx || !clockwise && x0 > cx) {\n y1 -= 270 / Z;\n } else {\n y1 += 270 / Z;\n }\n } else if (clockwise && y0 < cy || !clockwise && y0 > cy) {\n x1 += 270 / Z;\n } else {\n x1 -= 270 / Z;\n }\n }\n }\n\n str.push(type, round(((cx - rx) * sx + x) * Z - Z2), comma, round(((cy - ry) * sy + y) * Z - Z2), comma, round(((cx + rx) * sx + x) * Z - Z2), comma, round(((cy + ry) * sy + y) * Z - Z2), comma, round((x0 * sx + x) * Z - Z2), comma, round((y0 * sy + y) * Z - Z2), comma, round((x1 * sx + x) * Z - Z2), comma, round((y1 * sy + y) * Z - Z2));\n xi = x1;\n yi = y1;\n break;\n\n case CMD.R:\n var p0 = points[0];\n var p1 = points[1]; // x0, y0\n\n p0[0] = data[i++];\n p0[1] = data[i++]; // x1, y1\n\n p1[0] = p0[0] + data[i++];\n p1[1] = p0[1] + data[i++];\n\n if (m) {\n applyTransform(p0, p0, m);\n applyTransform(p1, p1, m);\n }\n\n p0[0] = round(p0[0] * Z - Z2);\n p1[0] = round(p1[0] * Z - Z2);\n p0[1] = round(p0[1] * Z - Z2);\n p1[1] = round(p1[1] * Z - Z2);\n str.push( // x0, y0\n ' m ', p0[0], comma, p0[1], // x1, y0\n ' l ', p1[0], comma, p0[1], // x1, y1\n ' l ', p1[0], comma, p1[1], // x0, y1\n ' l ', p0[0], comma, p1[1]);\n break;\n\n case CMD.Z:\n // FIXME Update xi, yi\n str.push(' x ');\n }\n\n if (nPoint > 0) {\n str.push(cmdStr);\n\n for (var k = 0; k < nPoint; k++) {\n var p = points[k];\n m && applyTransform(p, p, m); // 不 round 会非常慢\n\n str.push(round(p[0] * Z - Z2), comma, round(p[1] * Z - Z2), k < nPoint - 1 ? comma : '');\n }\n }\n }\n\n return str.join('');\n }; // Rewrite the original path method\n\n\n Path.prototype.brushVML = function (vmlRoot) {\n var style = this.style;\n var vmlEl = this._vmlEl;\n\n if (!vmlEl) {\n vmlEl = vmlCore.createNode('shape');\n initRootElStyle(vmlEl);\n this._vmlEl = vmlEl;\n }\n\n updateFillAndStroke(vmlEl, 'fill', style, this);\n updateFillAndStroke(vmlEl, 'stroke', style, this);\n var m = this.transform;\n var needTransform = m != null;\n var strokeEl = vmlEl.getElementsByTagName('stroke')[0];\n\n if (strokeEl) {\n var lineWidth = style.lineWidth; // Get the line scale.\n // Determinant of this.m_ means how much the area is enlarged by the\n // transformation. So its square root can be used as a scale factor\n // for width.\n\n if (needTransform && !style.strokeNoScale) {\n var det = m[0] * m[3] - m[1] * m[2];\n lineWidth *= sqrt(abs(det));\n }\n\n strokeEl.weight = lineWidth + 'px';\n }\n\n var path = this.path || (this.path = new PathProxy());\n\n if (this.__dirtyPath) {\n path.beginPath();\n path.subPixelOptimize = false;\n this.buildPath(path, this.shape);\n path.toStatic();\n this.__dirtyPath = false;\n }\n\n vmlEl.path = pathDataToString(path, this.transform);\n vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); // Append to root\n\n append(vmlRoot, vmlEl); // Text\n\n if (style.text != null) {\n this.drawRectText(vmlRoot, this.getBoundingRect());\n } else {\n this.removeRectText(vmlRoot);\n }\n };\n\n Path.prototype.onRemove = function (vmlRoot) {\n remove(vmlRoot, this._vmlEl);\n this.removeRectText(vmlRoot);\n };\n\n Path.prototype.onAdd = function (vmlRoot) {\n append(vmlRoot, this._vmlEl);\n this.appendRectText(vmlRoot);\n };\n /***************************************************\n * IMAGE\n **************************************************/\n\n\n var isImage = function (img) {\n // FIXME img instanceof Image 如果 img 是一个字符串的时候,IE8 下会报错\n return typeof img === 'object' && img.tagName && img.tagName.toUpperCase() === 'IMG'; // return img instanceof Image;\n }; // Rewrite the original path method\n\n\n ZImage.prototype.brushVML = function (vmlRoot) {\n var style = this.style;\n var image = style.image; // Image original width, height\n\n var ow;\n var oh;\n\n if (isImage(image)) {\n var src = image.src;\n\n if (src === this._imageSrc) {\n ow = this._imageWidth;\n oh = this._imageHeight;\n } else {\n var imageRuntimeStyle = image.runtimeStyle;\n var oldRuntimeWidth = imageRuntimeStyle.width;\n var oldRuntimeHeight = imageRuntimeStyle.height;\n imageRuntimeStyle.width = 'auto';\n imageRuntimeStyle.height = 'auto'; // get the original size\n\n ow = image.width;\n oh = image.height; // and remove overides\n\n imageRuntimeStyle.width = oldRuntimeWidth;\n imageRuntimeStyle.height = oldRuntimeHeight; // Caching image original width, height and src\n\n this._imageSrc = src;\n this._imageWidth = ow;\n this._imageHeight = oh;\n }\n\n image = src;\n } else {\n if (image === this._imageSrc) {\n ow = this._imageWidth;\n oh = this._imageHeight;\n }\n }\n\n if (!image) {\n return;\n }\n\n var x = style.x || 0;\n var y = style.y || 0;\n var dw = style.width;\n var dh = style.height;\n var sw = style.sWidth;\n var sh = style.sHeight;\n var sx = style.sx || 0;\n var sy = style.sy || 0;\n var hasCrop = sw && sh;\n var vmlEl = this._vmlEl;\n\n if (!vmlEl) {\n // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。\n // vmlEl = vmlCore.createNode('group');\n vmlEl = vmlCore.doc.createElement('div');\n initRootElStyle(vmlEl);\n this._vmlEl = vmlEl;\n }\n\n var vmlElStyle = vmlEl.style;\n var hasRotation = false;\n var m;\n var scaleX = 1;\n var scaleY = 1;\n\n if (this.transform) {\n m = this.transform;\n scaleX = sqrt(m[0] * m[0] + m[1] * m[1]);\n scaleY = sqrt(m[2] * m[2] + m[3] * m[3]);\n hasRotation = m[1] || m[2];\n }\n\n if (hasRotation) {\n // If filters are necessary (rotation exists), create them\n // filters are bog-slow, so only create them if abbsolutely necessary\n // The following check doesn't account for skews (which don't exist\n // in the canvas spec (yet) anyway.\n // From excanvas\n var p0 = [x, y];\n var p1 = [x + dw, y];\n var p2 = [x, y + dh];\n var p3 = [x + dw, y + dh];\n applyTransform(p0, p0, m);\n applyTransform(p1, p1, m);\n applyTransform(p2, p2, m);\n applyTransform(p3, p3, m);\n var maxX = mathMax(p0[0], p1[0], p2[0], p3[0]);\n var maxY = mathMax(p0[1], p1[1], p2[1], p3[1]);\n var transformFilter = [];\n transformFilter.push('M11=', m[0] / scaleX, comma, 'M12=', m[2] / scaleY, comma, 'M21=', m[1] / scaleX, comma, 'M22=', m[3] / scaleY, comma, 'Dx=', round(x * scaleX + m[4]), comma, 'Dy=', round(y * scaleY + m[5]));\n vmlElStyle.padding = '0 ' + round(maxX) + 'px ' + round(maxY) + 'px 0'; // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用\n\n vmlElStyle.filter = imageTransformPrefix + '.Matrix(' + transformFilter.join('') + ', SizingMethod=clip)';\n } else {\n if (m) {\n x = x * scaleX + m[4];\n y = y * scaleY + m[5];\n }\n\n vmlElStyle.filter = '';\n vmlElStyle.left = round(x) + 'px';\n vmlElStyle.top = round(y) + 'px';\n }\n\n var imageEl = this._imageEl;\n var cropEl = this._cropEl;\n\n if (!imageEl) {\n imageEl = vmlCore.doc.createElement('div');\n this._imageEl = imageEl;\n }\n\n var imageELStyle = imageEl.style;\n\n if (hasCrop) {\n // Needs know image original width and height\n if (!(ow && oh)) {\n var tmpImage = new Image();\n var self = this;\n\n tmpImage.onload = function () {\n tmpImage.onload = null;\n ow = tmpImage.width;\n oh = tmpImage.height; // Adjust image width and height to fit the ratio destinationSize / sourceSize\n\n imageELStyle.width = round(scaleX * ow * dw / sw) + 'px';\n imageELStyle.height = round(scaleY * oh * dh / sh) + 'px'; // Caching image original width, height and src\n\n self._imageWidth = ow;\n self._imageHeight = oh;\n self._imageSrc = image;\n };\n\n tmpImage.src = image;\n } else {\n imageELStyle.width = round(scaleX * ow * dw / sw) + 'px';\n imageELStyle.height = round(scaleY * oh * dh / sh) + 'px';\n }\n\n if (!cropEl) {\n cropEl = vmlCore.doc.createElement('div');\n cropEl.style.overflow = 'hidden';\n this._cropEl = cropEl;\n }\n\n var cropElStyle = cropEl.style;\n cropElStyle.width = round((dw + sx * dw / sw) * scaleX);\n cropElStyle.height = round((dh + sy * dh / sh) * scaleY);\n cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx=' + -sx * dw / sw * scaleX + ',Dy=' + -sy * dh / sh * scaleY + ')';\n\n if (!cropEl.parentNode) {\n vmlEl.appendChild(cropEl);\n }\n\n if (imageEl.parentNode !== cropEl) {\n cropEl.appendChild(imageEl);\n }\n } else {\n imageELStyle.width = round(scaleX * dw) + 'px';\n imageELStyle.height = round(scaleY * dh) + 'px';\n vmlEl.appendChild(imageEl);\n\n if (cropEl && cropEl.parentNode) {\n vmlEl.removeChild(cropEl);\n this._cropEl = null;\n }\n }\n\n var filterStr = '';\n var alpha = style.opacity;\n\n if (alpha < 1) {\n filterStr += '.Alpha(opacity=' + round(alpha * 100) + ') ';\n }\n\n filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)';\n imageELStyle.filter = filterStr;\n vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); // Append to root\n\n append(vmlRoot, vmlEl); // Text\n\n if (style.text != null) {\n this.drawRectText(vmlRoot, this.getBoundingRect());\n }\n };\n\n ZImage.prototype.onRemove = function (vmlRoot) {\n remove(vmlRoot, this._vmlEl);\n this._vmlEl = null;\n this._cropEl = null;\n this._imageEl = null;\n this.removeRectText(vmlRoot);\n };\n\n ZImage.prototype.onAdd = function (vmlRoot) {\n append(vmlRoot, this._vmlEl);\n this.appendRectText(vmlRoot);\n };\n /***************************************************\n * TEXT\n **************************************************/\n\n\n var DEFAULT_STYLE_NORMAL = 'normal';\n var fontStyleCache = {};\n var fontStyleCacheCount = 0;\n var MAX_FONT_CACHE_SIZE = 100;\n var fontEl = document.createElement('div');\n\n var getFontStyle = function (fontString) {\n var fontStyle = fontStyleCache[fontString];\n\n if (!fontStyle) {\n // Clear cache\n if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) {\n fontStyleCacheCount = 0;\n fontStyleCache = {};\n }\n\n var style = fontEl.style;\n var fontFamily;\n\n try {\n style.font = fontString;\n fontFamily = style.fontFamily.split(',')[0];\n } catch (e) {}\n\n fontStyle = {\n style: style.fontStyle || DEFAULT_STYLE_NORMAL,\n variant: style.fontVariant || DEFAULT_STYLE_NORMAL,\n weight: style.fontWeight || DEFAULT_STYLE_NORMAL,\n size: parseFloat(style.fontSize || 12) | 0,\n family: fontFamily || 'Microsoft YaHei'\n };\n fontStyleCache[fontString] = fontStyle;\n fontStyleCacheCount++;\n }\n\n return fontStyle;\n };\n\n var textMeasureEl; // Overwrite measure text method\n\n textContain.$override('measureText', function (text, textFont) {\n var doc = vmlCore.doc;\n\n if (!textMeasureEl) {\n textMeasureEl = doc.createElement('div');\n textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;' + 'padding:0;margin:0;border:none;white-space:pre;';\n vmlCore.doc.body.appendChild(textMeasureEl);\n }\n\n try {\n textMeasureEl.style.font = textFont;\n } catch (ex) {// Ignore failures to set to invalid font.\n }\n\n textMeasureEl.innerHTML = ''; // Don't use innerHTML or innerText because they allow markup/whitespace.\n\n textMeasureEl.appendChild(doc.createTextNode(text));\n return {\n width: textMeasureEl.offsetWidth\n };\n });\n var tmpRect = new BoundingRect();\n\n var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) {\n var style = this.style; // Optimize, avoid normalize every time.\n\n this.__dirty && textHelper.normalizeTextStyle(style, true);\n var text = style.text; // Convert to string\n\n text != null && (text += '');\n\n if (!text) {\n return;\n } // Convert rich text to plain text. Rich text is not supported in\n // IE8-, but tags in rich text template will be removed.\n\n\n if (style.rich) {\n var contentBlock = textContain.parseRichText(text, style);\n text = [];\n\n for (var i = 0; i < contentBlock.lines.length; i++) {\n var tokens = contentBlock.lines[i].tokens;\n var textLine = [];\n\n for (var j = 0; j < tokens.length; j++) {\n textLine.push(tokens[j].text);\n }\n\n text.push(textLine.join(''));\n }\n\n text = text.join('\\n');\n }\n\n var x;\n var y;\n var align = style.textAlign;\n var verticalAlign = style.textVerticalAlign;\n var fontStyle = getFontStyle(style.font); // FIXME encodeHtmlAttribute ?\n\n var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' ' + fontStyle.size + 'px \"' + fontStyle.family + '\"';\n textRect = textRect || textContain.getBoundingRect(text, font, align, verticalAlign, style.textPadding, style.textLineHeight); // Transform rect to view space\n\n var m = this.transform; // Ignore transform for text in other element\n\n if (m && !fromTextEl) {\n tmpRect.copy(rect);\n tmpRect.applyTransform(m);\n rect = tmpRect;\n }\n\n if (!fromTextEl) {\n var textPosition = style.textPosition; // Text position represented by coord\n\n if (textPosition instanceof Array) {\n x = rect.x + parsePercent(textPosition[0], rect.width);\n y = rect.y + parsePercent(textPosition[1], rect.height);\n align = align || 'left';\n } else {\n var res = this.calculateTextPosition ? this.calculateTextPosition({}, style, rect) : textContain.calculateTextPosition({}, style, rect);\n x = res.x;\n y = res.y; // Default align and baseline when has textPosition\n\n align = align || res.textAlign;\n verticalAlign = verticalAlign || res.textVerticalAlign;\n }\n } else {\n x = rect.x;\n y = rect.y;\n }\n\n x = textContain.adjustTextX(x, textRect.width, align);\n y = textContain.adjustTextY(y, textRect.height, verticalAlign); // Force baseline 'middle'\n\n y += textRect.height / 2; // var fontSize = fontStyle.size;\n // 1.75 is an arbitrary number, as there is no info about the text baseline\n // switch (baseline) {\n // case 'hanging':\n // case 'top':\n // y += fontSize / 1.75;\n // break;\n // case 'middle':\n // break;\n // default:\n // // case null:\n // // case 'alphabetic':\n // // case 'ideographic':\n // // case 'bottom':\n // y -= fontSize / 2.25;\n // break;\n // }\n // switch (align) {\n // case 'left':\n // break;\n // case 'center':\n // x -= textRect.width / 2;\n // break;\n // case 'right':\n // x -= textRect.width;\n // break;\n // case 'end':\n // align = elementStyle.direction == 'ltr' ? 'right' : 'left';\n // break;\n // case 'start':\n // align = elementStyle.direction == 'rtl' ? 'right' : 'left';\n // break;\n // default:\n // align = 'left';\n // }\n\n var createNode = vmlCore.createNode;\n var textVmlEl = this._textVmlEl;\n var pathEl;\n var textPathEl;\n var skewEl;\n\n if (!textVmlEl) {\n textVmlEl = createNode('line');\n pathEl = createNode('path');\n textPathEl = createNode('textpath');\n skewEl = createNode('skew'); // FIXME Why here is not cammel case\n // Align 'center' seems wrong\n\n textPathEl.style['v-text-align'] = 'left';\n initRootElStyle(textVmlEl);\n pathEl.textpathok = true;\n textPathEl.on = true;\n textVmlEl.from = '0 0';\n textVmlEl.to = '1000 0.05';\n append(textVmlEl, skewEl);\n append(textVmlEl, pathEl);\n append(textVmlEl, textPathEl);\n this._textVmlEl = textVmlEl;\n } else {\n // 这里是在前面 appendChild 保证顺序的前提下\n skewEl = textVmlEl.firstChild;\n pathEl = skewEl.nextSibling;\n textPathEl = pathEl.nextSibling;\n }\n\n var coords = [x, y];\n var textVmlElStyle = textVmlEl.style; // Ignore transform for text in other element\n\n if (m && fromTextEl) {\n applyTransform(coords, coords, m);\n skewEl.on = true;\n skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma + m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0'; // Text position\n\n skewEl.offset = (round(coords[0]) || 0) + ',' + (round(coords[1]) || 0); // Left top point as origin\n\n skewEl.origin = '0 0';\n textVmlElStyle.left = '0px';\n textVmlElStyle.top = '0px';\n } else {\n skewEl.on = false;\n textVmlElStyle.left = round(x) + 'px';\n textVmlElStyle.top = round(y) + 'px';\n }\n\n textPathEl.string = encodeHtmlAttribute(text); // TODO\n\n try {\n textPathEl.style.font = font;\n } // Error font format\n catch (e) {}\n\n updateFillAndStroke(textVmlEl, 'fill', {\n fill: style.textFill,\n opacity: style.opacity\n }, this);\n updateFillAndStroke(textVmlEl, 'stroke', {\n stroke: style.textStroke,\n opacity: style.opacity,\n lineDash: style.lineDash || null // style.lineDash can be `false`.\n\n }, this);\n textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2); // Attached to root\n\n append(vmlRoot, textVmlEl);\n };\n\n var removeRectText = function (vmlRoot) {\n remove(vmlRoot, this._textVmlEl);\n this._textVmlEl = null;\n };\n\n var appendRectText = function (vmlRoot) {\n append(vmlRoot, this._textVmlEl);\n };\n\n var list = [RectText, Displayable, ZImage, Path, Text]; // In case Displayable has been mixed in RectText\n\n for (var i = 0; i < list.length; i++) {\n var proto = list[i].prototype;\n proto.drawRectText = drawRectText;\n proto.removeRectText = removeRectText;\n proto.appendRectText = appendRectText;\n }\n\n Text.prototype.brushVML = function (vmlRoot) {\n var style = this.style;\n\n if (style.text != null) {\n this.drawRectText(vmlRoot, {\n x: style.x || 0,\n y: style.y || 0,\n width: 0,\n height: 0\n }, this.getBoundingRect(), true);\n } else {\n this.removeRectText(vmlRoot);\n }\n };\n\n Text.prototype.onRemove = function (vmlRoot) {\n this.removeRectText(vmlRoot);\n };\n\n Text.prototype.onAdd = function (vmlRoot) {\n this.appendRectText(vmlRoot);\n };\n}\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/vml/graphic.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/vml/vml.js": +/*!*********************************************!*\ + !*** ./node_modules/zrender/lib/vml/vml.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("__webpack_require__(/*! ./graphic */ \"./node_modules/zrender/lib/vml/graphic.js\");\n\nvar _zrender = __webpack_require__(/*! ../zrender */ \"./node_modules/zrender/lib/zrender.js\");\n\nvar registerPainter = _zrender.registerPainter;\n\nvar Painter = __webpack_require__(/*! ./Painter */ \"./node_modules/zrender/lib/vml/Painter.js\");\n\nregisterPainter('vml', Painter);\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/vml/vml.js?"); + +/***/ }), + +/***/ "./node_modules/zrender/lib/zrender.js": +/*!*********************************************!*\ + !*** ./node_modules/zrender/lib/zrender.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("var guid = __webpack_require__(/*! ./core/guid */ \"./node_modules/zrender/lib/core/guid.js\");\n\nvar env = __webpack_require__(/*! ./core/env */ \"./node_modules/zrender/lib/core/env.js\");\n\nvar zrUtil = __webpack_require__(/*! ./core/util */ \"./node_modules/zrender/lib/core/util.js\");\n\nvar Handler = __webpack_require__(/*! ./Handler */ \"./node_modules/zrender/lib/Handler.js\");\n\nvar Storage = __webpack_require__(/*! ./Storage */ \"./node_modules/zrender/lib/Storage.js\");\n\nvar Painter = __webpack_require__(/*! ./Painter */ \"./node_modules/zrender/lib/Painter.js\");\n\nvar Animation = __webpack_require__(/*! ./animation/Animation */ \"./node_modules/zrender/lib/animation/Animation.js\");\n\nvar HandlerProxy = __webpack_require__(/*! ./dom/HandlerProxy */ \"./node_modules/zrender/lib/dom/HandlerProxy.js\");\n\n/*!\n* ZRender, a high performance 2d drawing library.\n*\n* Copyright (c) 2013, Baidu Inc.\n* All rights reserved.\n*\n* LICENSE\n* https://github.com/ecomfe/zrender/blob/master/LICENSE.txt\n*/\nvar useVML = !env.canvasSupported;\nvar painterCtors = {\n canvas: Painter\n};\nvar instances = {}; // ZRender实例map索引\n\n/**\n * @type {string}\n */\n\nvar version = '4.3.2';\n/**\n * Initializing a zrender instance\n * @param {HTMLElement} dom\n * @param {Object} [opts]\n * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'\n * @param {number} [opts.devicePixelRatio]\n * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)\n * @return {module:zrender/ZRender}\n */\n\nfunction init(dom, opts) {\n var zr = new ZRender(guid(), dom, opts);\n instances[zr.id] = zr;\n return zr;\n}\n/**\n * Dispose zrender instance\n * @param {module:zrender/ZRender} zr\n */\n\n\nfunction dispose(zr) {\n if (zr) {\n zr.dispose();\n } else {\n for (var key in instances) {\n if (instances.hasOwnProperty(key)) {\n instances[key].dispose();\n }\n }\n\n instances = {};\n }\n\n return this;\n}\n/**\n * Get zrender instance by id\n * @param {string} id zrender instance id\n * @return {module:zrender/ZRender}\n */\n\n\nfunction getInstance(id) {\n return instances[id];\n}\n\nfunction registerPainter(name, Ctor) {\n painterCtors[name] = Ctor;\n}\n\nfunction delInstance(id) {\n delete instances[id];\n}\n/**\n * @module zrender/ZRender\n */\n\n/**\n * @constructor\n * @alias module:zrender/ZRender\n * @param {string} id\n * @param {HTMLElement} dom\n * @param {Object} opts\n * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'\n * @param {number} [opts.devicePixelRatio]\n * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)\n */\n\n\nvar ZRender = function (id, dom, opts) {\n opts = opts || {};\n /**\n * @type {HTMLDomElement}\n */\n\n this.dom = dom;\n /**\n * @type {string}\n */\n\n this.id = id;\n var self = this;\n var storage = new Storage();\n var rendererType = opts.renderer; // TODO WebGL\n\n if (useVML) {\n if (!painterCtors.vml) {\n throw new Error('You need to require \\'zrender/vml/vml\\' to support IE8');\n }\n\n rendererType = 'vml';\n } else if (!rendererType || !painterCtors[rendererType]) {\n rendererType = 'canvas';\n }\n\n var painter = new painterCtors[rendererType](dom, storage, opts, id);\n this.storage = storage;\n this.painter = painter;\n var handerProxy = !env.node && !env.worker ? new HandlerProxy(painter.getViewportRoot(), painter.root) : null;\n this.handler = new Handler(storage, painter, handerProxy, painter.root);\n /**\n * @type {module:zrender/animation/Animation}\n */\n\n this.animation = new Animation({\n stage: {\n update: zrUtil.bind(this.flush, this)\n }\n });\n this.animation.start();\n /**\n * @type {boolean}\n * @private\n */\n\n this._needsRefresh; // 修改 storage.delFromStorage, 每次删除元素之前删除动画\n // FIXME 有点ugly\n\n var oldDelFromStorage = storage.delFromStorage;\n var oldAddToStorage = storage.addToStorage;\n\n storage.delFromStorage = function (el) {\n oldDelFromStorage.call(storage, el);\n el && el.removeSelfFromZr(self);\n };\n\n storage.addToStorage = function (el) {\n oldAddToStorage.call(storage, el);\n el.addSelfToZr(self);\n };\n};\n\nZRender.prototype = {\n constructor: ZRender,\n\n /**\n * 获取实例唯一标识\n * @return {string}\n */\n getId: function () {\n return this.id;\n },\n\n /**\n * 添加元素\n * @param {module:zrender/Element} el\n */\n add: function (el) {\n this.storage.addRoot(el);\n this._needsRefresh = true;\n },\n\n /**\n * 删除元素\n * @param {module:zrender/Element} el\n */\n remove: function (el) {\n this.storage.delRoot(el);\n this._needsRefresh = true;\n },\n\n /**\n * Change configuration of layer\n * @param {string} zLevel\n * @param {Object} config\n * @param {string} [config.clearColor=0] Clear color\n * @param {string} [config.motionBlur=false] If enable motion blur\n * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer\n */\n configLayer: function (zLevel, config) {\n if (this.painter.configLayer) {\n this.painter.configLayer(zLevel, config);\n }\n\n this._needsRefresh = true;\n },\n\n /**\n * Set background color\n * @param {string} backgroundColor\n */\n setBackgroundColor: function (backgroundColor) {\n if (this.painter.setBackgroundColor) {\n this.painter.setBackgroundColor(backgroundColor);\n }\n\n this._needsRefresh = true;\n },\n\n /**\n * Repaint the canvas immediately\n */\n refreshImmediately: function () {\n // var start = new Date();\n // Clear needsRefresh ahead to avoid something wrong happens in refresh\n // Or it will cause zrender refreshes again and again.\n this._needsRefresh = this._needsRefreshHover = false;\n this.painter.refresh(); // Avoid trigger zr.refresh in Element#beforeUpdate hook\n\n this._needsRefresh = this._needsRefreshHover = false; // var end = new Date();\n // var log = document.getElementById('log');\n // if (log) {\n // log.innerHTML = log.innerHTML + '
' + (end - start);\n // }\n },\n\n /**\n * Mark and repaint the canvas in the next frame of browser\n */\n refresh: function () {\n this._needsRefresh = true;\n },\n\n /**\n * Perform all refresh\n */\n flush: function () {\n var triggerRendered;\n\n if (this._needsRefresh) {\n triggerRendered = true;\n this.refreshImmediately();\n }\n\n if (this._needsRefreshHover) {\n triggerRendered = true;\n this.refreshHoverImmediately();\n }\n\n triggerRendered && this.trigger('rendered');\n },\n\n /**\n * Add element to hover layer\n * @param {module:zrender/Element} el\n * @param {Object} style\n */\n addHover: function (el, style) {\n if (this.painter.addHover) {\n var elMirror = this.painter.addHover(el, style);\n this.refreshHover();\n return elMirror;\n }\n },\n\n /**\n * Add element from hover layer\n * @param {module:zrender/Element} el\n */\n removeHover: function (el) {\n if (this.painter.removeHover) {\n this.painter.removeHover(el);\n this.refreshHover();\n }\n },\n\n /**\n * Clear all hover elements in hover layer\n * @param {module:zrender/Element} el\n */\n clearHover: function () {\n if (this.painter.clearHover) {\n this.painter.clearHover();\n this.refreshHover();\n }\n },\n\n /**\n * Refresh hover in next frame\n */\n refreshHover: function () {\n this._needsRefreshHover = true;\n },\n\n /**\n * Refresh hover immediately\n */\n refreshHoverImmediately: function () {\n this._needsRefreshHover = false;\n this.painter.refreshHover && this.painter.refreshHover();\n },\n\n /**\n * Resize the canvas.\n * Should be invoked when container size is changed\n * @param {Object} [opts]\n * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)\n * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)\n */\n resize: function (opts) {\n opts = opts || {};\n this.painter.resize(opts.width, opts.height);\n this.handler.resize();\n },\n\n /**\n * Stop and clear all animation immediately\n */\n clearAnimation: function () {\n this.animation.clear();\n },\n\n /**\n * Get container width\n */\n getWidth: function () {\n return this.painter.getWidth();\n },\n\n /**\n * Get container height\n */\n getHeight: function () {\n return this.painter.getHeight();\n },\n\n /**\n * Export the canvas as Base64 URL\n * @param {string} type\n * @param {string} [backgroundColor='#fff']\n * @return {string} Base64 URL\n */\n // toDataURL: function(type, backgroundColor) {\n // return this.painter.getRenderedCanvas({\n // backgroundColor: backgroundColor\n // }).toDataURL(type);\n // },\n\n /**\n * Converting a path to image.\n * It has much better performance of drawing image rather than drawing a vector path.\n * @param {module:zrender/graphic/Path} e\n * @param {number} width\n * @param {number} height\n */\n pathToImage: function (e, dpr) {\n return this.painter.pathToImage(e, dpr);\n },\n\n /**\n * Set default cursor\n * @param {string} [cursorStyle='default'] 例如 crosshair\n */\n setCursorStyle: function (cursorStyle) {\n this.handler.setCursorStyle(cursorStyle);\n },\n\n /**\n * Find hovered element\n * @param {number} x\n * @param {number} y\n * @return {Object} {target, topTarget}\n */\n findHover: function (x, y) {\n return this.handler.findHover(x, y);\n },\n\n /**\n * Bind event\n *\n * @param {string} eventName Event name\n * @param {Function} eventHandler Handler function\n * @param {Object} [context] Context object\n */\n on: function (eventName, eventHandler, context) {\n this.handler.on(eventName, eventHandler, context);\n },\n\n /**\n * Unbind event\n * @param {string} eventName Event name\n * @param {Function} [eventHandler] Handler function\n */\n off: function (eventName, eventHandler) {\n this.handler.off(eventName, eventHandler);\n },\n\n /**\n * Trigger event manually\n *\n * @param {string} eventName Event name\n * @param {event=} event Event object\n */\n trigger: function (eventName, event) {\n this.handler.trigger(eventName, event);\n },\n\n /**\n * Clear all objects and the canvas.\n */\n clear: function () {\n this.storage.delRoot();\n this.painter.clear();\n },\n\n /**\n * Dispose self.\n */\n dispose: function () {\n this.animation.stop();\n this.clear();\n this.storage.dispose();\n this.painter.dispose();\n this.handler.dispose();\n this.animation = this.storage = this.painter = this.handler = null;\n delInstance(this.id);\n }\n};\nexports.version = version;\nexports.init = init;\nexports.dispose = dispose;\nexports.getInstance = getInstance;\nexports.registerPainter = registerPainter;\n\n//# sourceURL=webpack:///./node_modules/zrender/lib/zrender.js?"); + +/***/ }), + +/***/ "./src/views/dashboard/BarChart.vue": +/*!******************************************!*\ + !*** ./src/views/dashboard/BarChart.vue ***! + \******************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BarChart.vue?vue&type=template&id=397bf160& */ \"./src/views/dashboard/BarChart.vue?vue&type=template&id=397bf160&\");\n/* harmony import */ var _BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BarChart.vue?vue&type=script&lang=js& */ \"./src/views/dashboard/BarChart.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/dashboard/BarChart.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/dashboard/BarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/BarChart.vue?vue&type=script&lang=js&": +/*!*******************************************************************!*\ + !*** ./src/views/dashboard/BarChart.vue?vue&type=script&lang=js& ***! + \*******************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/babel-loader/lib!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./BarChart.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/BarChart.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/dashboard/BarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/BarChart.vue?vue&type=template&id=397bf160&": +/*!*************************************************************************!*\ + !*** ./src/views/dashboard/BarChart.vue?vue&type=template&id=397bf160& ***! + \*************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./BarChart.vue?vue&type=template&id=397bf160& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/BarChart.vue?vue&type=template&id=397bf160&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_BarChart_vue_vue_type_template_id_397bf160___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/dashboard/BarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/LineChart.vue": +/*!*******************************************!*\ + !*** ./src/views/dashboard/LineChart.vue ***! + \*******************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./LineChart.vue?vue&type=template&id=edb3ae76& */ \"./src/views/dashboard/LineChart.vue?vue&type=template&id=edb3ae76&\");\n/* harmony import */ var _LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LineChart.vue?vue&type=script&lang=js& */ \"./src/views/dashboard/LineChart.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/dashboard/LineChart.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/dashboard/LineChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/LineChart.vue?vue&type=script&lang=js&": +/*!********************************************************************!*\ + !*** ./src/views/dashboard/LineChart.vue?vue&type=script&lang=js& ***! + \********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/babel-loader/lib!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./LineChart.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/LineChart.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/dashboard/LineChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/LineChart.vue?vue&type=template&id=edb3ae76&": +/*!**************************************************************************!*\ + !*** ./src/views/dashboard/LineChart.vue?vue&type=template&id=edb3ae76& ***! + \**************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./LineChart.vue?vue&type=template&id=edb3ae76& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/LineChart.vue?vue&type=template&id=edb3ae76&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_LineChart_vue_vue_type_template_id_edb3ae76___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/dashboard/LineChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PanelGroup.vue": +/*!********************************************!*\ + !*** ./src/views/dashboard/PanelGroup.vue ***! + \********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PanelGroup.vue?vue&type=template&id=0333a520&scoped=true& */ \"./src/views/dashboard/PanelGroup.vue?vue&type=template&id=0333a520&scoped=true&\");\n/* harmony import */ var _PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PanelGroup.vue?vue&type=script&lang=js& */ \"./src/views/dashboard/PanelGroup.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true& */ \"./src/views/dashboard/PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"0333a520\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/dashboard/PanelGroup.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/dashboard/PanelGroup.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PanelGroup.vue?vue&type=script&lang=js&": +/*!*********************************************************************!*\ + !*** ./src/views/dashboard/PanelGroup.vue?vue&type=script&lang=js& ***! + \*********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/babel-loader/lib!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./PanelGroup.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/PanelGroup.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/dashboard/PanelGroup.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true&": +/*!******************************************************************************************************!*\ + !*** ./src/views/dashboard/PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true& ***! + \******************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/PanelGroup.vue?vue&type=style&index=0&id=0333a520&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_style_index_0_id_0333a520_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/dashboard/PanelGroup.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PanelGroup.vue?vue&type=template&id=0333a520&scoped=true&": +/*!***************************************************************************************!*\ + !*** ./src/views/dashboard/PanelGroup.vue?vue&type=template&id=0333a520&scoped=true& ***! + \***************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./PanelGroup.vue?vue&type=template&id=0333a520&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/PanelGroup.vue?vue&type=template&id=0333a520&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PanelGroup_vue_vue_type_template_id_0333a520_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/dashboard/PanelGroup.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PieChart.vue": +/*!******************************************!*\ + !*** ./src/views/dashboard/PieChart.vue ***! + \******************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PieChart.vue?vue&type=template&id=36c457f2& */ \"./src/views/dashboard/PieChart.vue?vue&type=template&id=36c457f2&\");\n/* harmony import */ var _PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PieChart.vue?vue&type=script&lang=js& */ \"./src/views/dashboard/PieChart.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/dashboard/PieChart.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/dashboard/PieChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PieChart.vue?vue&type=script&lang=js&": +/*!*******************************************************************!*\ + !*** ./src/views/dashboard/PieChart.vue?vue&type=script&lang=js& ***! + \*******************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/babel-loader/lib!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./PieChart.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/PieChart.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/dashboard/PieChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/PieChart.vue?vue&type=template&id=36c457f2&": +/*!*************************************************************************!*\ + !*** ./src/views/dashboard/PieChart.vue?vue&type=template&id=36c457f2& ***! + \*************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./PieChart.vue?vue&type=template&id=36c457f2& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/PieChart.vue?vue&type=template&id=36c457f2&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PieChart_vue_vue_type_template_id_36c457f2___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/dashboard/PieChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/RaddarChart.vue": +/*!*********************************************!*\ + !*** ./src/views/dashboard/RaddarChart.vue ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./RaddarChart.vue?vue&type=template&id=bd9223ce& */ \"./src/views/dashboard/RaddarChart.vue?vue&type=template&id=bd9223ce&\");\n/* harmony import */ var _RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RaddarChart.vue?vue&type=script&lang=js& */ \"./src/views/dashboard/RaddarChart.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/dashboard/RaddarChart.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/dashboard/RaddarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/RaddarChart.vue?vue&type=script&lang=js&": +/*!**********************************************************************!*\ + !*** ./src/views/dashboard/RaddarChart.vue?vue&type=script&lang=js& ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/babel-loader/lib!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./RaddarChart.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/RaddarChart.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/dashboard/RaddarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/RaddarChart.vue?vue&type=template&id=bd9223ce&": +/*!****************************************************************************!*\ + !*** ./src/views/dashboard/RaddarChart.vue?vue&type=template&id=bd9223ce& ***! + \****************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib??vue-loader-options!./RaddarChart.vue?vue&type=template&id=bd9223ce& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/dashboard/RaddarChart.vue?vue&type=template&id=bd9223ce&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RaddarChart_vue_vue_type_template_id_bd9223ce___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/dashboard/RaddarChart.vue?"); + +/***/ }), + +/***/ "./src/views/dashboard/mixins/resize.js": +/*!**********************************************!*\ + !*** ./src/views/dashboard/mixins/resize.js ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _utils = __webpack_require__(/*! @/utils */ \"./src/utils/index.js\");\n\nvar _default = {\n data: function data() {\n return {\n $_sidebarElm: null,\n $_resizeHandler: null\n };\n },\n mounted: function mounted() {\n this.initListener();\n },\n activated: function activated() {\n if (!this.$_resizeHandler) {\n // avoid duplication init\n this.initListener();\n } // when keep-alive chart activated, auto resize\n\n\n this.resize();\n },\n beforeDestroy: function beforeDestroy() {\n this.destroyListener();\n },\n deactivated: function deactivated() {\n this.destroyListener();\n },\n methods: {\n // use $_ for mixins properties\n // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential\n $_sidebarResizeHandler: function $_sidebarResizeHandler(e) {\n if (e.propertyName === 'width') {\n this.$_resizeHandler();\n }\n },\n initListener: function initListener() {\n var _this = this;\n\n this.$_resizeHandler = (0, _utils.debounce)(function () {\n _this.resize();\n }, 100);\n window.addEventListener('resize', this.$_resizeHandler);\n this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0];\n this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler);\n },\n destroyListener: function destroyListener() {\n window.removeEventListener('resize', this.$_resizeHandler);\n this.$_resizeHandler = null;\n this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler);\n },\n resize: function resize() {\n var chart = this.chart;\n chart && chart.resize();\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/dashboard/mixins/resize.js?"); + +/***/ }), + +/***/ "./src/views/index.vue": +/*!*****************************!*\ + !*** ./src/views/index.vue ***! + \*****************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index.vue?vue&type=template&id=a83bd3b0&scoped=true& */ \"./src/views/index.vue?vue&type=template&id=a83bd3b0&scoped=true&\");\n/* harmony import */ var _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./index.vue?vue&type=script&lang=js& */ \"./src/views/index.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true& */ \"./src/views/index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"a83bd3b0\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/index.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/index.vue?"); + +/***/ }), + +/***/ "./src/views/index.vue?vue&type=script&lang=js&": +/*!******************************************************!*\ + !*** ./src/views/index.vue?vue&type=script&lang=js& ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/babel-loader/lib!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib??vue-loader-options!./index.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/index.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/index.vue?"); + +/***/ }), + +/***/ "./src/views/index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true&": +/*!***************************************************************************************!*\ + !*** ./src/views/index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true& ***! + \***************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib??vue-loader-options!./index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/index.vue?vue&type=style&index=0&id=a83bd3b0&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_style_index_0_id_a83bd3b0_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/index.vue?"); + +/***/ }), + +/***/ "./src/views/index.vue?vue&type=template&id=a83bd3b0&scoped=true&": +/*!************************************************************************!*\ + !*** ./src/views/index.vue?vue&type=template&id=a83bd3b0&scoped=true& ***! + \************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib??vue-loader-options!./index.vue?vue&type=template&id=a83bd3b0&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/index.vue?vue&type=template&id=a83bd3b0&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_a83bd3b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/index.vue?"); + +/***/ }) + +}]); \ No newline at end of file diff --git a/yudao-server/src/main/resources/admin-ui/static/js/5.js b/yudao-server/src/main/resources/admin-ui/static/js/5.js new file mode 100644 index 0000000000..01fae1e4b9 --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/js/5.js @@ -0,0 +1,956 @@ +(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[5],{ + +/***/ "./node_modules/@babel/parser/lib/index.js": +/*!*************************************************!*\ + !*** ./node_modules/@babel/parser/lib/index.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nclass Position {\n constructor(line, col, index) {\n this.line = void 0;\n this.column = void 0;\n this.index = void 0;\n this.line = line;\n this.column = col;\n indexes.set(this, index);\n }\n\n}\nclass SourceLocation {\n constructor(start, end) {\n this.start = void 0;\n this.end = void 0;\n this.filename = void 0;\n this.identifierName = void 0;\n this.start = start;\n this.end = end;\n }\n\n}\nconst indexes = new WeakMap();\nfunction createPositionWithColumnOffset(position, columnOffset) {\n const {\n line,\n column\n } = position;\n return new Position(line, column + columnOffset, indexes.get(position) + columnOffset);\n}\n\nclass BaseParser {\n constructor() {\n this.sawUnambiguousESM = false;\n this.ambiguousScriptDifferentAst = false;\n }\n\n hasPlugin(pluginConfig) {\n if (typeof pluginConfig === \"string\") {\n return this.plugins.has(pluginConfig);\n } else {\n const [pluginName, pluginOptions] = pluginConfig;\n\n if (!this.hasPlugin(pluginName)) {\n return false;\n }\n\n const actualOptions = this.plugins.get(pluginName);\n\n for (const key of Object.keys(pluginOptions)) {\n if ((actualOptions == null ? void 0 : actualOptions[key]) !== pluginOptions[key]) {\n return false;\n }\n }\n\n return true;\n }\n }\n\n getPluginOption(plugin, name) {\n var _this$plugins$get;\n\n return (_this$plugins$get = this.plugins.get(plugin)) == null ? void 0 : _this$plugins$get[name];\n }\n\n}\n\nfunction setTrailingComments(node, comments) {\n if (node.trailingComments === undefined) {\n node.trailingComments = comments;\n } else {\n node.trailingComments.unshift(...comments);\n }\n}\n\nfunction setLeadingComments(node, comments) {\n if (node.leadingComments === undefined) {\n node.leadingComments = comments;\n } else {\n node.leadingComments.unshift(...comments);\n }\n}\n\nfunction setInnerComments(node, comments) {\n if (node.innerComments === undefined) {\n node.innerComments = comments;\n } else {\n node.innerComments.unshift(...comments);\n }\n}\n\nfunction adjustInnerComments(node, elements, commentWS) {\n let lastElement = null;\n let i = elements.length;\n\n while (lastElement === null && i > 0) {\n lastElement = elements[--i];\n }\n\n if (lastElement === null || lastElement.start > commentWS.start) {\n setInnerComments(node, commentWS.comments);\n } else {\n setTrailingComments(lastElement, commentWS.comments);\n }\n}\n\nclass CommentsParser extends BaseParser {\n addComment(comment) {\n if (this.filename) comment.loc.filename = this.filename;\n this.state.comments.push(comment);\n }\n\n processComment(node) {\n const {\n commentStack\n } = this.state;\n const commentStackLength = commentStack.length;\n if (commentStackLength === 0) return;\n let i = commentStackLength - 1;\n const lastCommentWS = commentStack[i];\n\n if (lastCommentWS.start === node.end) {\n lastCommentWS.leadingNode = node;\n i--;\n }\n\n const {\n start: nodeStart\n } = node;\n\n for (; i >= 0; i--) {\n const commentWS = commentStack[i];\n const commentEnd = commentWS.end;\n\n if (commentEnd > nodeStart) {\n commentWS.containingNode = node;\n this.finalizeComment(commentWS);\n commentStack.splice(i, 1);\n } else {\n if (commentEnd === nodeStart) {\n commentWS.trailingNode = node;\n }\n\n break;\n }\n }\n }\n\n finalizeComment(commentWS) {\n const {\n comments\n } = commentWS;\n\n if (commentWS.leadingNode !== null || commentWS.trailingNode !== null) {\n if (commentWS.leadingNode !== null) {\n setTrailingComments(commentWS.leadingNode, comments);\n }\n\n if (commentWS.trailingNode !== null) {\n setLeadingComments(commentWS.trailingNode, comments);\n }\n } else {\n const {\n containingNode: node,\n start: commentStart\n } = commentWS;\n\n if (this.input.charCodeAt(commentStart - 1) === 44) {\n switch (node.type) {\n case \"ObjectExpression\":\n case \"ObjectPattern\":\n case \"RecordExpression\":\n adjustInnerComments(node, node.properties, commentWS);\n break;\n\n case \"CallExpression\":\n case \"OptionalCallExpression\":\n adjustInnerComments(node, node.arguments, commentWS);\n break;\n\n case \"FunctionDeclaration\":\n case \"FunctionExpression\":\n case \"ArrowFunctionExpression\":\n case \"ObjectMethod\":\n case \"ClassMethod\":\n case \"ClassPrivateMethod\":\n adjustInnerComments(node, node.params, commentWS);\n break;\n\n case \"ArrayExpression\":\n case \"ArrayPattern\":\n case \"TupleExpression\":\n adjustInnerComments(node, node.elements, commentWS);\n break;\n\n case \"ExportNamedDeclaration\":\n case \"ImportDeclaration\":\n adjustInnerComments(node, node.specifiers, commentWS);\n break;\n\n default:\n {\n setInnerComments(node, comments);\n }\n }\n } else {\n setInnerComments(node, comments);\n }\n }\n }\n\n finalizeRemainingComments() {\n const {\n commentStack\n } = this.state;\n\n for (let i = commentStack.length - 1; i >= 0; i--) {\n this.finalizeComment(commentStack[i]);\n }\n\n this.state.commentStack = [];\n }\n\n resetPreviousNodeTrailingComments(node) {\n const {\n commentStack\n } = this.state;\n const {\n length\n } = commentStack;\n if (length === 0) return;\n const commentWS = commentStack[length - 1];\n\n if (commentWS.leadingNode === node) {\n commentWS.leadingNode = null;\n }\n }\n\n takeSurroundingComments(node, start, end) {\n const {\n commentStack\n } = this.state;\n const commentStackLength = commentStack.length;\n if (commentStackLength === 0) return;\n let i = commentStackLength - 1;\n\n for (; i >= 0; i--) {\n const commentWS = commentStack[i];\n const commentEnd = commentWS.end;\n const commentStart = commentWS.start;\n\n if (commentStart === end) {\n commentWS.leadingNode = node;\n } else if (commentEnd === start) {\n commentWS.trailingNode = node;\n } else if (commentEnd < start) {\n break;\n }\n }\n }\n\n}\n\nconst ErrorCodes = Object.freeze({\n SyntaxError: \"BABEL_PARSER_SYNTAX_ERROR\",\n SourceTypeModuleError: \"BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED\"\n});\n\nconst ErrorMessages = makeErrorTemplates({\n AccessorIsGenerator: \"A %0ter cannot be a generator.\",\n ArgumentsInClass: \"'arguments' is only allowed in functions and class methods.\",\n AsyncFunctionInSingleStatementContext: \"Async functions can only be declared at the top level or inside a block.\",\n AwaitBindingIdentifier: \"Can not use 'await' as identifier inside an async function.\",\n AwaitBindingIdentifierInStaticBlock: \"Can not use 'await' as identifier inside a static block.\",\n AwaitExpressionFormalParameter: \"'await' is not allowed in async function parameters.\",\n AwaitNotInAsyncContext: \"'await' is only allowed within async functions and at the top levels of modules.\",\n AwaitNotInAsyncFunction: \"'await' is only allowed within async functions.\",\n BadGetterArity: \"A 'get' accesor must not have any formal parameters.\",\n BadSetterArity: \"A 'set' accesor must have exactly one formal parameter.\",\n BadSetterRestParameter: \"A 'set' accesor function argument must not be a rest parameter.\",\n ConstructorClassField: \"Classes may not have a field named 'constructor'.\",\n ConstructorClassPrivateField: \"Classes may not have a private field named '#constructor'.\",\n ConstructorIsAccessor: \"Class constructor may not be an accessor.\",\n ConstructorIsAsync: \"Constructor can't be an async function.\",\n ConstructorIsGenerator: \"Constructor can't be a generator.\",\n DeclarationMissingInitializer: \"'%0' require an initialization value.\",\n DecoratorBeforeExport: \"Decorators must be placed *before* the 'export' keyword. You can set the 'decoratorsBeforeExport' option to false to use the 'export @decorator class {}' syntax.\",\n DecoratorConstructor: \"Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?\",\n DecoratorExportClass: \"Using the export keyword between a decorator and a class is not allowed. Please use `export @dec class` instead.\",\n DecoratorSemicolon: \"Decorators must not be followed by a semicolon.\",\n DecoratorStaticBlock: \"Decorators can't be used with a static block.\",\n DeletePrivateField: \"Deleting a private field is not allowed.\",\n DestructureNamedImport: \"ES2015 named imports do not destructure. Use another statement for destructuring after the import.\",\n DuplicateConstructor: \"Duplicate constructor in the same class.\",\n DuplicateDefaultExport: \"Only one default export allowed per module.\",\n DuplicateExport: \"`%0` has already been exported. Exported identifiers must be unique.\",\n DuplicateProto: \"Redefinition of __proto__ property.\",\n DuplicateRegExpFlags: \"Duplicate regular expression flag.\",\n ElementAfterRest: \"Rest element must be last element.\",\n EscapedCharNotAnIdentifier: \"Invalid Unicode escape.\",\n ExportBindingIsString: \"A string literal cannot be used as an exported binding without `from`.\\n- Did you mean `export { '%0' as '%1' } from 'some-module'`?\",\n ExportDefaultFromAsIdentifier: \"'from' is not allowed as an identifier after 'export default'.\",\n ForInOfLoopInitializer: \"'%0' loop variable declaration may not have an initializer.\",\n ForOfAsync: \"The left-hand side of a for-of loop may not be 'async'.\",\n ForOfLet: \"The left-hand side of a for-of loop may not start with 'let'.\",\n GeneratorInSingleStatementContext: \"Generators can only be declared at the top level or inside a block.\",\n IllegalBreakContinue: \"Unsyntactic %0.\",\n IllegalLanguageModeDirective: \"Illegal 'use strict' directive in function with non-simple parameter list.\",\n IllegalReturn: \"'return' outside of function.\",\n ImportBindingIsString: 'A string literal cannot be used as an imported binding.\\n- Did you mean `import { \"%0\" as foo }`?',\n ImportCallArgumentTrailingComma: \"Trailing comma is disallowed inside import(...) arguments.\",\n ImportCallArity: \"`import()` requires exactly %0.\",\n ImportCallNotNewExpression: \"Cannot use new with import(...).\",\n ImportCallSpreadArgument: \"`...` is not allowed in `import()`.\",\n InvalidBigIntLiteral: \"Invalid BigIntLiteral.\",\n InvalidCodePoint: \"Code point out of bounds.\",\n InvalidCoverInitializedName: \"Invalid shorthand property initializer.\",\n InvalidDecimal: \"Invalid decimal.\",\n InvalidDigit: \"Expected number in radix %0.\",\n InvalidEscapeSequence: \"Bad character escape sequence.\",\n InvalidEscapeSequenceTemplate: \"Invalid escape sequence in template.\",\n InvalidEscapedReservedWord: \"Escape sequence in keyword %0.\",\n InvalidIdentifier: \"Invalid identifier %0.\",\n InvalidLhs: \"Invalid left-hand side in %0.\",\n InvalidLhsBinding: \"Binding invalid left-hand side in %0.\",\n InvalidNumber: \"Invalid number.\",\n InvalidOrMissingExponent: \"Floating-point numbers require a valid exponent after the 'e'.\",\n InvalidOrUnexpectedToken: \"Unexpected character '%0'.\",\n InvalidParenthesizedAssignment: \"Invalid parenthesized assignment pattern.\",\n InvalidPrivateFieldResolution: \"Private name #%0 is not defined.\",\n InvalidPropertyBindingPattern: \"Binding member expression.\",\n InvalidRecordProperty: \"Only properties and spread elements are allowed in record definitions.\",\n InvalidRestAssignmentPattern: \"Invalid rest operator's argument.\",\n LabelRedeclaration: \"Label '%0' is already declared.\",\n LetInLexicalBinding: \"'let' is not allowed to be used as a name in 'let' or 'const' declarations.\",\n LineTerminatorBeforeArrow: \"No line break is allowed before '=>'.\",\n MalformedRegExpFlags: \"Invalid regular expression flag.\",\n MissingClassName: \"A class name is required.\",\n MissingEqInAssignment: \"Only '=' operator can be used for specifying default value.\",\n MissingSemicolon: \"Missing semicolon.\",\n MissingUnicodeEscape: \"Expecting Unicode escape sequence \\\\uXXXX.\",\n MixingCoalesceWithLogical: \"Nullish coalescing operator(??) requires parens when mixing with logical operators.\",\n ModuleAttributeDifferentFromType: \"The only accepted module attribute is `type`.\",\n ModuleAttributeInvalidValue: \"Only string literals are allowed as module attribute values.\",\n ModuleAttributesWithDuplicateKeys: 'Duplicate key \"%0\" is not allowed in module attributes.',\n ModuleExportNameHasLoneSurrogate: \"An export name cannot include a lone surrogate, found '\\\\u%0'.\",\n ModuleExportUndefined: \"Export '%0' is not defined.\",\n MultipleDefaultsInSwitch: \"Multiple default clauses.\",\n NewlineAfterThrow: \"Illegal newline after throw.\",\n NoCatchOrFinally: \"Missing catch or finally clause.\",\n NumberIdentifier: \"Identifier directly after number.\",\n NumericSeparatorInEscapeSequence: \"Numeric separators are not allowed inside unicode escape sequences or hex escape sequences.\",\n ObsoleteAwaitStar: \"'await*' has been removed from the async functions proposal. Use Promise.all() instead.\",\n OptionalChainingNoNew: \"Constructors in/after an Optional Chain are not allowed.\",\n OptionalChainingNoTemplate: \"Tagged Template Literals are not allowed in optionalChain.\",\n OverrideOnConstructor: \"'override' modifier cannot appear on a constructor declaration.\",\n ParamDupe: \"Argument name clash.\",\n PatternHasAccessor: \"Object pattern can't contain getter or setter.\",\n PatternHasMethod: \"Object pattern can't contain methods.\",\n PipeBodyIsTighter: \"Unexpected %0 after pipeline body; any %0 expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence.\",\n PipeTopicRequiresHackPipes: 'Topic reference is used, but the pipelineOperator plugin was not passed a \"proposal\": \"hack\" or \"smart\" option.',\n PipeTopicUnbound: \"Topic reference is unbound; it must be inside a pipe body.\",\n PipeTopicUnconfiguredToken: 'Invalid topic token %0. In order to use %0 as a topic reference, the pipelineOperator plugin must be configured with { \"proposal\": \"hack\", \"topicToken\": \"%0\" }.',\n PipeTopicUnused: \"Hack-style pipe body does not contain a topic reference; Hack-style pipes must use topic at least once.\",\n PipeUnparenthesizedBody: \"Hack-style pipe body cannot be an unparenthesized %0 expression; please wrap it in parentheses.\",\n PipelineBodyNoArrow: 'Unexpected arrow \"=>\" after pipeline body; arrow function in pipeline body must be parenthesized.',\n PipelineBodySequenceExpression: \"Pipeline body may not be a comma-separated sequence expression.\",\n PipelineHeadSequenceExpression: \"Pipeline head should not be a comma-separated sequence expression.\",\n PipelineTopicUnused: \"Pipeline is in topic style but does not use topic reference.\",\n PrimaryTopicNotAllowed: \"Topic reference was used in a lexical context without topic binding.\",\n PrimaryTopicRequiresSmartPipeline: 'Topic reference is used, but the pipelineOperator plugin was not passed a \"proposal\": \"hack\" or \"smart\" option.',\n PrivateInExpectedIn: \"Private names are only allowed in property accesses (`obj.#%0`) or in `in` expressions (`#%0 in obj`).\",\n PrivateNameRedeclaration: \"Duplicate private name #%0.\",\n RecordExpressionBarIncorrectEndSyntaxType: \"Record expressions ending with '|}' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.\",\n RecordExpressionBarIncorrectStartSyntaxType: \"Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.\",\n RecordExpressionHashIncorrectStartSyntaxType: \"Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'.\",\n RecordNoProto: \"'__proto__' is not allowed in Record expressions.\",\n RestTrailingComma: \"Unexpected trailing comma after rest element.\",\n SloppyFunction: \"In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.\",\n StaticPrototype: \"Classes may not have static property named prototype.\",\n StrictDelete: \"Deleting local variable in strict mode.\",\n StrictEvalArguments: \"Assigning to '%0' in strict mode.\",\n StrictEvalArgumentsBinding: \"Binding '%0' in strict mode.\",\n StrictFunction: \"In strict mode code, functions can only be declared at top level or inside a block.\",\n StrictNumericEscape: \"The only valid numeric escape in strict mode is '\\\\0'.\",\n StrictOctalLiteral: \"Legacy octal literals are not allowed in strict mode.\",\n StrictWith: \"'with' in strict mode.\",\n SuperNotAllowed: \"`super()` is only valid inside a class constructor of a subclass. Maybe a typo in the method name ('constructor') or not extending another class?\",\n SuperPrivateField: \"Private fields can't be accessed on super.\",\n TrailingDecorator: \"Decorators must be attached to a class element.\",\n TupleExpressionBarIncorrectEndSyntaxType: \"Tuple expressions ending with '|]' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.\",\n TupleExpressionBarIncorrectStartSyntaxType: \"Tuple expressions starting with '[|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.\",\n TupleExpressionHashIncorrectStartSyntaxType: \"Tuple expressions starting with '#[' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'.\",\n UnexpectedArgumentPlaceholder: \"Unexpected argument placeholder.\",\n UnexpectedAwaitAfterPipelineBody: 'Unexpected \"await\" after pipeline body; await must have parentheses in minimal proposal.',\n UnexpectedDigitAfterHash: \"Unexpected digit after hash token.\",\n UnexpectedImportExport: \"'import' and 'export' may only appear at the top level.\",\n UnexpectedKeyword: \"Unexpected keyword '%0'.\",\n UnexpectedLeadingDecorator: \"Leading decorators must be attached to a class declaration.\",\n UnexpectedLexicalDeclaration: \"Lexical declaration cannot appear in a single-statement context.\",\n UnexpectedNewTarget: \"`new.target` can only be used in functions or class properties.\",\n UnexpectedNumericSeparator: \"A numeric separator is only allowed between two digits.\",\n UnexpectedPrivateField: \"Unexpected private name.\",\n UnexpectedReservedWord: \"Unexpected reserved word '%0'.\",\n UnexpectedSuper: \"'super' is only allowed in object methods and classes.\",\n UnexpectedToken: \"Unexpected token '%0'.\",\n UnexpectedTokenUnaryExponentiation: \"Illegal expression. Wrap left hand side or entire exponentiation in parentheses.\",\n UnsupportedBind: \"Binding should be performed on object property.\",\n UnsupportedDecoratorExport: \"A decorated export must export a class declaration.\",\n UnsupportedDefaultExport: \"Only expressions, functions or classes are allowed as the `default` export.\",\n UnsupportedImport: \"`import` can only be used in `import()` or `import.meta`.\",\n UnsupportedMetaProperty: \"The only valid meta property for %0 is %0.%1.\",\n UnsupportedParameterDecorator: \"Decorators cannot be used to decorate parameters.\",\n UnsupportedPropertyDecorator: \"Decorators cannot be used to decorate object literal properties.\",\n UnsupportedSuper: \"'super' can only be used with function calls (i.e. super()) or in property accesses (i.e. super.prop or super[prop]).\",\n UnterminatedComment: \"Unterminated comment.\",\n UnterminatedRegExp: \"Unterminated regular expression.\",\n UnterminatedString: \"Unterminated string constant.\",\n UnterminatedTemplate: \"Unterminated template.\",\n VarRedeclaration: \"Identifier '%0' has already been declared.\",\n YieldBindingIdentifier: \"Can not use 'yield' as identifier inside a generator.\",\n YieldInParameter: \"Yield expression is not allowed in formal parameters.\",\n ZeroDigitNumericSeparator: \"Numeric separator can not be used after leading 0.\"\n}, ErrorCodes.SyntaxError);\nconst SourceTypeModuleErrorMessages = makeErrorTemplates({\n ImportMetaOutsideModule: `import.meta may appear only with 'sourceType: \"module\"'`,\n ImportOutsideModule: `'import' and 'export' may appear only with 'sourceType: \"module\"'`\n}, ErrorCodes.SourceTypeModuleError);\n\nfunction keepReasonCodeCompat(reasonCode, syntaxPlugin) {\n {\n if (syntaxPlugin === \"flow\" && reasonCode === \"PatternIsOptional\") {\n return \"OptionalBindingPattern\";\n }\n }\n return reasonCode;\n}\n\nfunction makeErrorTemplates(messages, code, syntaxPlugin) {\n const templates = {};\n Object.keys(messages).forEach(reasonCode => {\n templates[reasonCode] = Object.freeze({\n code,\n reasonCode: keepReasonCodeCompat(reasonCode, syntaxPlugin),\n template: messages[reasonCode]\n });\n });\n return Object.freeze(templates);\n}\nclass ParserError extends CommentsParser {\n raise({\n code,\n reasonCode,\n template\n }, origin, ...params) {\n return this.raiseWithData(origin.node ? origin.node.loc.start : origin.at, {\n code,\n reasonCode\n }, template, ...params);\n }\n\n raiseOverwrite(loc, {\n code,\n template\n }, ...params) {\n const pos = indexes.get(loc);\n const message = template.replace(/%(\\d+)/g, (_, i) => params[i]) + ` (${loc.line}:${loc.column})`;\n\n if (this.options.errorRecovery) {\n const errors = this.state.errors;\n\n for (let i = errors.length - 1; i >= 0; i--) {\n const error = errors[i];\n\n if (error.pos === pos) {\n return Object.assign(error, {\n message\n });\n } else if (error.pos < pos) {\n break;\n }\n }\n }\n\n return this._raise({\n code,\n loc,\n pos\n }, message);\n }\n\n raiseWithData(loc, data, errorTemplate, ...params) {\n const pos = indexes.get(loc);\n const message = errorTemplate.replace(/%(\\d+)/g, (_, i) => params[i]) + ` (${loc.line}:${loc.column})`;\n return this._raise(Object.assign({\n loc,\n pos\n }, data), message);\n }\n\n _raise(errorContext, message) {\n const err = new SyntaxError(message);\n Object.assign(err, errorContext);\n\n if (this.options.errorRecovery) {\n if (!this.isLookahead) this.state.errors.push(err);\n return err;\n } else {\n throw err;\n }\n }\n\n}\n\nvar estree = (superClass => class extends superClass {\n parseRegExpLiteral({\n pattern,\n flags\n }) {\n let regex = null;\n\n try {\n regex = new RegExp(pattern, flags);\n } catch (e) {}\n\n const node = this.estreeParseLiteral(regex);\n node.regex = {\n pattern,\n flags\n };\n return node;\n }\n\n parseBigIntLiteral(value) {\n let bigInt;\n\n try {\n bigInt = BigInt(value);\n } catch (_unused) {\n bigInt = null;\n }\n\n const node = this.estreeParseLiteral(bigInt);\n node.bigint = String(node.value || value);\n return node;\n }\n\n parseDecimalLiteral(value) {\n const decimal = null;\n const node = this.estreeParseLiteral(decimal);\n node.decimal = String(node.value || value);\n return node;\n }\n\n estreeParseLiteral(value) {\n return this.parseLiteral(value, \"Literal\");\n }\n\n parseStringLiteral(value) {\n return this.estreeParseLiteral(value);\n }\n\n parseNumericLiteral(value) {\n return this.estreeParseLiteral(value);\n }\n\n parseNullLiteral() {\n return this.estreeParseLiteral(null);\n }\n\n parseBooleanLiteral(value) {\n return this.estreeParseLiteral(value);\n }\n\n directiveToStmt(directive) {\n const directiveLiteral = directive.value;\n const stmt = this.startNodeAt(directive.start, directive.loc.start);\n const expression = this.startNodeAt(directiveLiteral.start, directiveLiteral.loc.start);\n expression.value = directiveLiteral.extra.expressionValue;\n expression.raw = directiveLiteral.extra.raw;\n stmt.expression = this.finishNodeAt(expression, \"Literal\", directiveLiteral.loc.end);\n stmt.directive = directiveLiteral.extra.raw.slice(1, -1);\n return this.finishNodeAt(stmt, \"ExpressionStatement\", directive.loc.end);\n }\n\n initFunction(node, isAsync) {\n super.initFunction(node, isAsync);\n node.expression = false;\n }\n\n checkDeclaration(node) {\n if (node != null && this.isObjectProperty(node)) {\n this.checkDeclaration(node.value);\n } else {\n super.checkDeclaration(node);\n }\n }\n\n getObjectOrClassMethodParams(method) {\n return method.value.params;\n }\n\n isValidDirective(stmt) {\n var _stmt$expression$extr;\n\n return stmt.type === \"ExpressionStatement\" && stmt.expression.type === \"Literal\" && typeof stmt.expression.value === \"string\" && !((_stmt$expression$extr = stmt.expression.extra) != null && _stmt$expression$extr.parenthesized);\n }\n\n parseBlockBody(node, ...args) {\n super.parseBlockBody(node, ...args);\n const directiveStatements = node.directives.map(d => this.directiveToStmt(d));\n node.body = directiveStatements.concat(node.body);\n delete node.directives;\n }\n\n pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper) {\n this.parseMethod(method, isGenerator, isAsync, isConstructor, allowsDirectSuper, \"ClassMethod\", true);\n\n if (method.typeParameters) {\n method.value.typeParameters = method.typeParameters;\n delete method.typeParameters;\n }\n\n classBody.body.push(method);\n }\n\n parsePrivateName() {\n const node = super.parsePrivateName();\n {\n if (!this.getPluginOption(\"estree\", \"classFeatures\")) {\n return node;\n }\n }\n return this.convertPrivateNameToPrivateIdentifier(node);\n }\n\n convertPrivateNameToPrivateIdentifier(node) {\n const name = super.getPrivateNameSV(node);\n node = node;\n delete node.id;\n node.name = name;\n node.type = \"PrivateIdentifier\";\n return node;\n }\n\n isPrivateName(node) {\n {\n if (!this.getPluginOption(\"estree\", \"classFeatures\")) {\n return super.isPrivateName(node);\n }\n }\n return node.type === \"PrivateIdentifier\";\n }\n\n getPrivateNameSV(node) {\n {\n if (!this.getPluginOption(\"estree\", \"classFeatures\")) {\n return super.getPrivateNameSV(node);\n }\n }\n return node.name;\n }\n\n parseLiteral(value, type) {\n const node = super.parseLiteral(value, type);\n node.raw = node.extra.raw;\n delete node.extra;\n return node;\n }\n\n parseFunctionBody(node, allowExpression, isMethod = false) {\n super.parseFunctionBody(node, allowExpression, isMethod);\n node.expression = node.body.type !== \"BlockStatement\";\n }\n\n parseMethod(node, isGenerator, isAsync, isConstructor, allowDirectSuper, type, inClassScope = false) {\n let funcNode = this.startNode();\n funcNode.kind = node.kind;\n funcNode = super.parseMethod(funcNode, isGenerator, isAsync, isConstructor, allowDirectSuper, type, inClassScope);\n funcNode.type = \"FunctionExpression\";\n delete funcNode.kind;\n node.value = funcNode;\n\n if (type === \"ClassPrivateMethod\") {\n node.computed = false;\n }\n\n type = \"MethodDefinition\";\n return this.finishNode(node, type);\n }\n\n parseClassProperty(...args) {\n const propertyNode = super.parseClassProperty(...args);\n {\n if (!this.getPluginOption(\"estree\", \"classFeatures\")) {\n return propertyNode;\n }\n }\n propertyNode.type = \"PropertyDefinition\";\n return propertyNode;\n }\n\n parseClassPrivateProperty(...args) {\n const propertyNode = super.parseClassPrivateProperty(...args);\n {\n if (!this.getPluginOption(\"estree\", \"classFeatures\")) {\n return propertyNode;\n }\n }\n propertyNode.type = \"PropertyDefinition\";\n propertyNode.computed = false;\n return propertyNode;\n }\n\n parseObjectMethod(prop, isGenerator, isAsync, isPattern, isAccessor) {\n const node = super.parseObjectMethod(prop, isGenerator, isAsync, isPattern, isAccessor);\n\n if (node) {\n node.type = \"Property\";\n if (node.kind === \"method\") node.kind = \"init\";\n node.shorthand = false;\n }\n\n return node;\n }\n\n parseObjectProperty(prop, startPos, startLoc, isPattern, refExpressionErrors) {\n const node = super.parseObjectProperty(prop, startPos, startLoc, isPattern, refExpressionErrors);\n\n if (node) {\n node.kind = \"init\";\n node.type = \"Property\";\n }\n\n return node;\n }\n\n isAssignable(node, isBinding) {\n if (node != null && this.isObjectProperty(node)) {\n return this.isAssignable(node.value, isBinding);\n }\n\n return super.isAssignable(node, isBinding);\n }\n\n toAssignable(node, isLHS = false) {\n if (node != null && this.isObjectProperty(node)) {\n this.toAssignable(node.value, isLHS);\n return node;\n }\n\n return super.toAssignable(node, isLHS);\n }\n\n toAssignableObjectExpressionProp(prop, ...args) {\n if (prop.kind === \"get\" || prop.kind === \"set\") {\n this.raise(ErrorMessages.PatternHasAccessor, {\n node: prop.key\n });\n } else if (prop.method) {\n this.raise(ErrorMessages.PatternHasMethod, {\n node: prop.key\n });\n } else {\n super.toAssignableObjectExpressionProp(prop, ...args);\n }\n }\n\n finishCallExpression(node, optional) {\n super.finishCallExpression(node, optional);\n\n if (node.callee.type === \"Import\") {\n node.type = \"ImportExpression\";\n node.source = node.arguments[0];\n\n if (this.hasPlugin(\"importAssertions\")) {\n var _node$arguments$;\n\n node.attributes = (_node$arguments$ = node.arguments[1]) != null ? _node$arguments$ : null;\n }\n\n delete node.arguments;\n delete node.callee;\n }\n\n return node;\n }\n\n toReferencedArguments(node) {\n if (node.type === \"ImportExpression\") {\n return;\n }\n\n super.toReferencedArguments(node);\n }\n\n parseExport(node) {\n super.parseExport(node);\n\n switch (node.type) {\n case \"ExportAllDeclaration\":\n node.exported = null;\n break;\n\n case \"ExportNamedDeclaration\":\n if (node.specifiers.length === 1 && node.specifiers[0].type === \"ExportNamespaceSpecifier\") {\n node.type = \"ExportAllDeclaration\";\n node.exported = node.specifiers[0].exported;\n delete node.specifiers;\n }\n\n break;\n }\n\n return node;\n }\n\n parseSubscript(base, startPos, startLoc, noCalls, state) {\n const node = super.parseSubscript(base, startPos, startLoc, noCalls, state);\n\n if (state.optionalChainMember) {\n if (node.type === \"OptionalMemberExpression\" || node.type === \"OptionalCallExpression\") {\n node.type = node.type.substring(8);\n }\n\n if (state.stop) {\n const chain = this.startNodeAtNode(node);\n chain.expression = node;\n return this.finishNode(chain, \"ChainExpression\");\n }\n } else if (node.type === \"MemberExpression\" || node.type === \"CallExpression\") {\n node.optional = false;\n }\n\n return node;\n }\n\n hasPropertyAsPrivateName(node) {\n if (node.type === \"ChainExpression\") {\n node = node.expression;\n }\n\n return super.hasPropertyAsPrivateName(node);\n }\n\n isOptionalChain(node) {\n return node.type === \"ChainExpression\";\n }\n\n isObjectProperty(node) {\n return node.type === \"Property\" && node.kind === \"init\" && !node.method;\n }\n\n isObjectMethod(node) {\n return node.method || node.kind === \"get\" || node.kind === \"set\";\n }\n\n});\n\nclass TokContext {\n constructor(token, preserveSpace) {\n this.token = void 0;\n this.preserveSpace = void 0;\n this.token = token;\n this.preserveSpace = !!preserveSpace;\n }\n\n}\nconst types = {\n brace: new TokContext(\"{\"),\n j_oTag: new TokContext(\"...\", true)\n};\n{\n types.template = new TokContext(\"`\", true);\n}\n\nconst beforeExpr = true;\nconst startsExpr = true;\nconst isLoop = true;\nconst isAssign = true;\nconst prefix = true;\nconst postfix = true;\nclass ExportedTokenType {\n constructor(label, conf = {}) {\n this.label = void 0;\n this.keyword = void 0;\n this.beforeExpr = void 0;\n this.startsExpr = void 0;\n this.rightAssociative = void 0;\n this.isLoop = void 0;\n this.isAssign = void 0;\n this.prefix = void 0;\n this.postfix = void 0;\n this.binop = void 0;\n this.label = label;\n this.keyword = conf.keyword;\n this.beforeExpr = !!conf.beforeExpr;\n this.startsExpr = !!conf.startsExpr;\n this.rightAssociative = !!conf.rightAssociative;\n this.isLoop = !!conf.isLoop;\n this.isAssign = !!conf.isAssign;\n this.prefix = !!conf.prefix;\n this.postfix = !!conf.postfix;\n this.binop = conf.binop != null ? conf.binop : null;\n {\n this.updateContext = null;\n }\n }\n\n}\nconst keywords$1 = new Map();\n\nfunction createKeyword(name, options = {}) {\n options.keyword = name;\n const token = createToken(name, options);\n keywords$1.set(name, token);\n return token;\n}\n\nfunction createBinop(name, binop) {\n return createToken(name, {\n beforeExpr,\n binop\n });\n}\n\nlet tokenTypeCounter = -1;\nconst tokenTypes = [];\nconst tokenLabels = [];\nconst tokenBinops = [];\nconst tokenBeforeExprs = [];\nconst tokenStartsExprs = [];\nconst tokenPrefixes = [];\n\nfunction createToken(name, options = {}) {\n var _options$binop, _options$beforeExpr, _options$startsExpr, _options$prefix;\n\n ++tokenTypeCounter;\n tokenLabels.push(name);\n tokenBinops.push((_options$binop = options.binop) != null ? _options$binop : -1);\n tokenBeforeExprs.push((_options$beforeExpr = options.beforeExpr) != null ? _options$beforeExpr : false);\n tokenStartsExprs.push((_options$startsExpr = options.startsExpr) != null ? _options$startsExpr : false);\n tokenPrefixes.push((_options$prefix = options.prefix) != null ? _options$prefix : false);\n tokenTypes.push(new ExportedTokenType(name, options));\n return tokenTypeCounter;\n}\n\nfunction createKeywordLike(name, options = {}) {\n var _options$binop2, _options$beforeExpr2, _options$startsExpr2, _options$prefix2;\n\n ++tokenTypeCounter;\n keywords$1.set(name, tokenTypeCounter);\n tokenLabels.push(name);\n tokenBinops.push((_options$binop2 = options.binop) != null ? _options$binop2 : -1);\n tokenBeforeExprs.push((_options$beforeExpr2 = options.beforeExpr) != null ? _options$beforeExpr2 : false);\n tokenStartsExprs.push((_options$startsExpr2 = options.startsExpr) != null ? _options$startsExpr2 : false);\n tokenPrefixes.push((_options$prefix2 = options.prefix) != null ? _options$prefix2 : false);\n tokenTypes.push(new ExportedTokenType(\"name\", options));\n return tokenTypeCounter;\n}\n\nconst tt = {\n bracketL: createToken(\"[\", {\n beforeExpr,\n startsExpr\n }),\n bracketHashL: createToken(\"#[\", {\n beforeExpr,\n startsExpr\n }),\n bracketBarL: createToken(\"[|\", {\n beforeExpr,\n startsExpr\n }),\n bracketR: createToken(\"]\"),\n bracketBarR: createToken(\"|]\"),\n braceL: createToken(\"{\", {\n beforeExpr,\n startsExpr\n }),\n braceBarL: createToken(\"{|\", {\n beforeExpr,\n startsExpr\n }),\n braceHashL: createToken(\"#{\", {\n beforeExpr,\n startsExpr\n }),\n braceR: createToken(\"}\", {\n beforeExpr\n }),\n braceBarR: createToken(\"|}\"),\n parenL: createToken(\"(\", {\n beforeExpr,\n startsExpr\n }),\n parenR: createToken(\")\"),\n comma: createToken(\",\", {\n beforeExpr\n }),\n semi: createToken(\";\", {\n beforeExpr\n }),\n colon: createToken(\":\", {\n beforeExpr\n }),\n doubleColon: createToken(\"::\", {\n beforeExpr\n }),\n dot: createToken(\".\"),\n question: createToken(\"?\", {\n beforeExpr\n }),\n questionDot: createToken(\"?.\"),\n arrow: createToken(\"=>\", {\n beforeExpr\n }),\n template: createToken(\"template\"),\n ellipsis: createToken(\"...\", {\n beforeExpr\n }),\n backQuote: createToken(\"`\", {\n startsExpr\n }),\n dollarBraceL: createToken(\"${\", {\n beforeExpr,\n startsExpr\n }),\n templateTail: createToken(\"...`\", {\n startsExpr\n }),\n templateNonTail: createToken(\"...${\", {\n beforeExpr,\n startsExpr\n }),\n at: createToken(\"@\"),\n hash: createToken(\"#\", {\n startsExpr\n }),\n interpreterDirective: createToken(\"#!...\"),\n eq: createToken(\"=\", {\n beforeExpr,\n isAssign\n }),\n assign: createToken(\"_=\", {\n beforeExpr,\n isAssign\n }),\n slashAssign: createToken(\"_=\", {\n beforeExpr,\n isAssign\n }),\n xorAssign: createToken(\"_=\", {\n beforeExpr,\n isAssign\n }),\n moduloAssign: createToken(\"_=\", {\n beforeExpr,\n isAssign\n }),\n incDec: createToken(\"++/--\", {\n prefix,\n postfix,\n startsExpr\n }),\n bang: createToken(\"!\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n tilde: createToken(\"~\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n pipeline: createBinop(\"|>\", 0),\n nullishCoalescing: createBinop(\"??\", 1),\n logicalOR: createBinop(\"||\", 1),\n logicalAND: createBinop(\"&&\", 2),\n bitwiseOR: createBinop(\"|\", 3),\n bitwiseXOR: createBinop(\"^\", 4),\n bitwiseAND: createBinop(\"&\", 5),\n equality: createBinop(\"==/!=/===/!==\", 6),\n lt: createBinop(\"/<=/>=\", 7),\n gt: createBinop(\"/<=/>=\", 7),\n relational: createBinop(\"/<=/>=\", 7),\n bitShift: createBinop(\"<>/>>>\", 8),\n plusMin: createToken(\"+/-\", {\n beforeExpr,\n binop: 9,\n prefix,\n startsExpr\n }),\n modulo: createToken(\"%\", {\n binop: 10,\n startsExpr\n }),\n star: createToken(\"*\", {\n binop: 10\n }),\n slash: createBinop(\"/\", 10),\n exponent: createToken(\"**\", {\n beforeExpr,\n binop: 11,\n rightAssociative: true\n }),\n _in: createKeyword(\"in\", {\n beforeExpr,\n binop: 7\n }),\n _instanceof: createKeyword(\"instanceof\", {\n beforeExpr,\n binop: 7\n }),\n _break: createKeyword(\"break\"),\n _case: createKeyword(\"case\", {\n beforeExpr\n }),\n _catch: createKeyword(\"catch\"),\n _continue: createKeyword(\"continue\"),\n _debugger: createKeyword(\"debugger\"),\n _default: createKeyword(\"default\", {\n beforeExpr\n }),\n _else: createKeyword(\"else\", {\n beforeExpr\n }),\n _finally: createKeyword(\"finally\"),\n _function: createKeyword(\"function\", {\n startsExpr\n }),\n _if: createKeyword(\"if\"),\n _return: createKeyword(\"return\", {\n beforeExpr\n }),\n _switch: createKeyword(\"switch\"),\n _throw: createKeyword(\"throw\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n _try: createKeyword(\"try\"),\n _var: createKeyword(\"var\"),\n _const: createKeyword(\"const\"),\n _with: createKeyword(\"with\"),\n _new: createKeyword(\"new\", {\n beforeExpr,\n startsExpr\n }),\n _this: createKeyword(\"this\", {\n startsExpr\n }),\n _super: createKeyword(\"super\", {\n startsExpr\n }),\n _class: createKeyword(\"class\", {\n startsExpr\n }),\n _extends: createKeyword(\"extends\", {\n beforeExpr\n }),\n _export: createKeyword(\"export\"),\n _import: createKeyword(\"import\", {\n startsExpr\n }),\n _null: createKeyword(\"null\", {\n startsExpr\n }),\n _true: createKeyword(\"true\", {\n startsExpr\n }),\n _false: createKeyword(\"false\", {\n startsExpr\n }),\n _typeof: createKeyword(\"typeof\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n _void: createKeyword(\"void\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n _delete: createKeyword(\"delete\", {\n beforeExpr,\n prefix,\n startsExpr\n }),\n _do: createKeyword(\"do\", {\n isLoop,\n beforeExpr\n }),\n _for: createKeyword(\"for\", {\n isLoop\n }),\n _while: createKeyword(\"while\", {\n isLoop\n }),\n _as: createKeywordLike(\"as\", {\n startsExpr\n }),\n _assert: createKeywordLike(\"assert\", {\n startsExpr\n }),\n _async: createKeywordLike(\"async\", {\n startsExpr\n }),\n _await: createKeywordLike(\"await\", {\n startsExpr\n }),\n _from: createKeywordLike(\"from\", {\n startsExpr\n }),\n _get: createKeywordLike(\"get\", {\n startsExpr\n }),\n _let: createKeywordLike(\"let\", {\n startsExpr\n }),\n _meta: createKeywordLike(\"meta\", {\n startsExpr\n }),\n _of: createKeywordLike(\"of\", {\n startsExpr\n }),\n _sent: createKeywordLike(\"sent\", {\n startsExpr\n }),\n _set: createKeywordLike(\"set\", {\n startsExpr\n }),\n _static: createKeywordLike(\"static\", {\n startsExpr\n }),\n _yield: createKeywordLike(\"yield\", {\n startsExpr\n }),\n _asserts: createKeywordLike(\"asserts\", {\n startsExpr\n }),\n _checks: createKeywordLike(\"checks\", {\n startsExpr\n }),\n _exports: createKeywordLike(\"exports\", {\n startsExpr\n }),\n _global: createKeywordLike(\"global\", {\n startsExpr\n }),\n _implements: createKeywordLike(\"implements\", {\n startsExpr\n }),\n _intrinsic: createKeywordLike(\"intrinsic\", {\n startsExpr\n }),\n _infer: createKeywordLike(\"infer\", {\n startsExpr\n }),\n _is: createKeywordLike(\"is\", {\n startsExpr\n }),\n _mixins: createKeywordLike(\"mixins\", {\n startsExpr\n }),\n _proto: createKeywordLike(\"proto\", {\n startsExpr\n }),\n _require: createKeywordLike(\"require\", {\n startsExpr\n }),\n _keyof: createKeywordLike(\"keyof\", {\n startsExpr\n }),\n _readonly: createKeywordLike(\"readonly\", {\n startsExpr\n }),\n _unique: createKeywordLike(\"unique\", {\n startsExpr\n }),\n _abstract: createKeywordLike(\"abstract\", {\n startsExpr\n }),\n _declare: createKeywordLike(\"declare\", {\n startsExpr\n }),\n _enum: createKeywordLike(\"enum\", {\n startsExpr\n }),\n _module: createKeywordLike(\"module\", {\n startsExpr\n }),\n _namespace: createKeywordLike(\"namespace\", {\n startsExpr\n }),\n _interface: createKeywordLike(\"interface\", {\n startsExpr\n }),\n _type: createKeywordLike(\"type\", {\n startsExpr\n }),\n _opaque: createKeywordLike(\"opaque\", {\n startsExpr\n }),\n name: createToken(\"name\", {\n startsExpr\n }),\n string: createToken(\"string\", {\n startsExpr\n }),\n num: createToken(\"num\", {\n startsExpr\n }),\n bigint: createToken(\"bigint\", {\n startsExpr\n }),\n decimal: createToken(\"decimal\", {\n startsExpr\n }),\n regexp: createToken(\"regexp\", {\n startsExpr\n }),\n privateName: createToken(\"#name\", {\n startsExpr\n }),\n eof: createToken(\"eof\"),\n jsxName: createToken(\"jsxName\"),\n jsxText: createToken(\"jsxText\", {\n beforeExpr: true\n }),\n jsxTagStart: createToken(\"jsxTagStart\", {\n startsExpr: true\n }),\n jsxTagEnd: createToken(\"jsxTagEnd\"),\n placeholder: createToken(\"%%\", {\n startsExpr: true\n })\n};\nfunction tokenIsIdentifier(token) {\n return token >= 89 && token <= 124;\n}\nfunction tokenKeywordOrIdentifierIsKeyword(token) {\n return token <= 88;\n}\nfunction tokenIsKeywordOrIdentifier(token) {\n return token >= 54 && token <= 124;\n}\nfunction tokenIsLiteralPropertyName(token) {\n return token >= 54 && token <= 128;\n}\nfunction tokenComesBeforeExpression(token) {\n return tokenBeforeExprs[token];\n}\nfunction tokenCanStartExpression(token) {\n return tokenStartsExprs[token];\n}\nfunction tokenIsAssignment(token) {\n return token >= 29 && token <= 33;\n}\nfunction tokenIsFlowInterfaceOrTypeOrOpaque(token) {\n return token >= 121 && token <= 123;\n}\nfunction tokenIsLoop(token) {\n return token >= 86 && token <= 88;\n}\nfunction tokenIsKeyword(token) {\n return token >= 54 && token <= 88;\n}\nfunction tokenIsOperator(token) {\n return token >= 37 && token <= 55;\n}\nfunction tokenIsPostfix(token) {\n return token === 34;\n}\nfunction tokenIsPrefix(token) {\n return tokenPrefixes[token];\n}\nfunction tokenIsTSTypeOperator(token) {\n return token >= 113 && token <= 115;\n}\nfunction tokenIsTSDeclarationStart(token) {\n return token >= 116 && token <= 122;\n}\nfunction tokenLabelName(token) {\n return tokenLabels[token];\n}\nfunction tokenOperatorPrecedence(token) {\n return tokenBinops[token];\n}\nfunction tokenIsRightAssociative(token) {\n return token === 53;\n}\nfunction tokenIsTemplate(token) {\n return token >= 24 && token <= 25;\n}\nfunction getExportedToken(token) {\n return tokenTypes[token];\n}\n{\n tokenTypes[8].updateContext = context => {\n context.pop();\n };\n\n tokenTypes[5].updateContext = tokenTypes[7].updateContext = tokenTypes[23].updateContext = context => {\n context.push(types.brace);\n };\n\n tokenTypes[22].updateContext = context => {\n if (context[context.length - 1] === types.template) {\n context.pop();\n } else {\n context.push(types.template);\n }\n };\n\n tokenTypes[134].updateContext = context => {\n context.push(types.j_expr, types.j_oTag);\n };\n}\n\nlet nonASCIIidentifierStartChars = \"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u037f\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u052f\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05d0-\\u05ea\\u05ef-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086a\\u0870-\\u0887\\u0889-\\u088e\\u08a0-\\u08c9\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u09fc\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0af9\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c39\\u0c3d\\u0c58-\\u0c5a\\u0c5d\\u0c60\\u0c61\\u0c80\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cdd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d04-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d54-\\u0d56\\u0d5f-\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e86-\\u0e8a\\u0e8c-\\u0ea3\\u0ea5\\u0ea7-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f5\\u13f8-\\u13fd\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f8\\u1700-\\u1711\\u171f-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1878\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191e\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19b0-\\u19c9\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4c\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1c80-\\u1c88\\u1c90-\\u1cba\\u1cbd-\\u1cbf\\u1ce9-\\u1cec\\u1cee-\\u1cf3\\u1cf5\\u1cf6\\u1cfa\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2118-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309b-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312f\\u3131-\\u318e\\u31a0-\\u31bf\\u31f0-\\u31ff\\u3400-\\u4dbf\\u4e00-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua69d\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua7ca\\ua7d0\\ua7d1\\ua7d3\\ua7d5-\\ua7d9\\ua7f2-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua8fd\\ua8fe\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\ua9e0-\\ua9e4\\ua9e6-\\ua9ef\\ua9fa-\\ua9fe\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa7e-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uab30-\\uab5a\\uab5c-\\uab69\\uab70-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc\";\nlet nonASCIIidentifierChars = \"\\u200c\\u200d\\xb7\\u0300-\\u036f\\u0387\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u0669\\u0670\\u06d6-\\u06dc\\u06df-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u06f0-\\u06f9\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07c0-\\u07c9\\u07eb-\\u07f3\\u07fd\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0859-\\u085b\\u0898-\\u089f\\u08ca-\\u08e1\\u08e3-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09cb-\\u09cd\\u09d7\\u09e2\\u09e3\\u09e6-\\u09ef\\u09fe\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2\\u0ae3\\u0ae6-\\u0aef\\u0afa-\\u0aff\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b55-\\u0b57\\u0b62\\u0b63\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c00-\\u0c04\\u0c3c\\u0c3e-\\u0c44\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0c66-\\u0c6f\\u0c81-\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0ce6-\\u0cef\\u0d00-\\u0d03\\u0d3b\\u0d3c\\u0d3e-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4d\\u0d57\\u0d62\\u0d63\\u0d66-\\u0d6f\\u0d81-\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0de6-\\u0def\\u0df2\\u0df3\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0e50-\\u0e59\\u0eb1\\u0eb4-\\u0ebc\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f3e\\u0f3f\\u0f71-\\u0f84\\u0f86\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102b-\\u103e\\u1040-\\u1049\\u1056-\\u1059\\u105e-\\u1060\\u1062-\\u1064\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u1369-\\u1371\\u1712-\\u1715\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b4-\\u17d3\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u180f-\\u1819\\u18a9\\u1920-\\u192b\\u1930-\\u193b\\u1946-\\u194f\\u19d0-\\u19da\\u1a17-\\u1a1b\\u1a55-\\u1a5e\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1ab0-\\u1abd\\u1abf-\\u1ace\\u1b00-\\u1b04\\u1b34-\\u1b44\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1b82\\u1ba1-\\u1bad\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c24-\\u1c37\\u1c40-\\u1c49\\u1c50-\\u1c59\\u1cd0-\\u1cd2\\u1cd4-\\u1ce8\\u1ced\\u1cf4\\u1cf7-\\u1cf9\\u1dc0-\\u1dff\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2cef-\\u2cf1\\u2d7f\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua620-\\ua629\\ua66f\\ua674-\\ua67d\\ua69e\\ua69f\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua823-\\ua827\\ua82c\\ua880\\ua881\\ua8b4-\\ua8c5\\ua8d0-\\ua8d9\\ua8e0-\\ua8f1\\ua8ff-\\ua909\\ua926-\\ua92d\\ua947-\\ua953\\ua980-\\ua983\\ua9b3-\\ua9c0\\ua9d0-\\ua9d9\\ua9e5\\ua9f0-\\ua9f9\\uaa29-\\uaa36\\uaa43\\uaa4c\\uaa4d\\uaa50-\\uaa59\\uaa7b-\\uaa7d\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uaaeb-\\uaaef\\uaaf5\\uaaf6\\uabe3-\\uabea\\uabec\\uabed\\uabf0-\\uabf9\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe2f\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f\";\nconst nonASCIIidentifierStart = new RegExp(\"[\" + nonASCIIidentifierStartChars + \"]\");\nconst nonASCIIidentifier = new RegExp(\"[\" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + \"]\");\nnonASCIIidentifierStartChars = nonASCIIidentifierChars = null;\nconst astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1070, 4050, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 46, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 482, 44, 11, 6, 17, 0, 322, 29, 19, 43, 1269, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4152, 8, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938];\nconst astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 357, 0, 62, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];\n\nfunction isInAstralSet(code, set) {\n let pos = 0x10000;\n\n for (let i = 0, length = set.length; i < length; i += 2) {\n pos += set[i];\n if (pos > code) return false;\n pos += set[i + 1];\n if (pos >= code) return true;\n }\n\n return false;\n}\n\nfunction isIdentifierStart(code) {\n if (code < 65) return code === 36;\n if (code <= 90) return true;\n if (code < 97) return code === 95;\n if (code <= 122) return true;\n\n if (code <= 0xffff) {\n return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n }\n\n return isInAstralSet(code, astralIdentifierStartCodes);\n}\nfunction isIdentifierChar(code) {\n if (code < 48) return code === 36;\n if (code < 58) return true;\n if (code < 65) return false;\n if (code <= 90) return true;\n if (code < 97) return code === 95;\n if (code <= 122) return true;\n\n if (code <= 0xffff) {\n return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n }\n\n return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);\n}\n\nconst reservedWords = {\n keyword: [\"break\", \"case\", \"catch\", \"continue\", \"debugger\", \"default\", \"do\", \"else\", \"finally\", \"for\", \"function\", \"if\", \"return\", \"switch\", \"throw\", \"try\", \"var\", \"const\", \"while\", \"with\", \"new\", \"this\", \"super\", \"class\", \"extends\", \"export\", \"import\", \"null\", \"true\", \"false\", \"in\", \"instanceof\", \"typeof\", \"void\", \"delete\"],\n strict: [\"implements\", \"interface\", \"let\", \"package\", \"private\", \"protected\", \"public\", \"static\", \"yield\"],\n strictBind: [\"eval\", \"arguments\"]\n};\nconst keywords = new Set(reservedWords.keyword);\nconst reservedWordsStrictSet = new Set(reservedWords.strict);\nconst reservedWordsStrictBindSet = new Set(reservedWords.strictBind);\nfunction isReservedWord(word, inModule) {\n return inModule && word === \"await\" || word === \"enum\";\n}\nfunction isStrictReservedWord(word, inModule) {\n return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);\n}\nfunction isStrictBindOnlyReservedWord(word) {\n return reservedWordsStrictBindSet.has(word);\n}\nfunction isStrictBindReservedWord(word, inModule) {\n return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);\n}\nfunction isKeyword(word) {\n return keywords.has(word);\n}\n\nfunction isIteratorStart(current, next) {\n return current === 64 && next === 64;\n}\nconst reservedWordLikeSet = new Set([\"break\", \"case\", \"catch\", \"continue\", \"debugger\", \"default\", \"do\", \"else\", \"finally\", \"for\", \"function\", \"if\", \"return\", \"switch\", \"throw\", \"try\", \"var\", \"const\", \"while\", \"with\", \"new\", \"this\", \"super\", \"class\", \"extends\", \"export\", \"import\", \"null\", \"true\", \"false\", \"in\", \"instanceof\", \"typeof\", \"void\", \"delete\", \"implements\", \"interface\", \"let\", \"package\", \"private\", \"protected\", \"public\", \"static\", \"yield\", \"eval\", \"arguments\", \"enum\", \"await\"]);\nfunction canBeReservedWord(word) {\n return reservedWordLikeSet.has(word);\n}\n\nconst SCOPE_OTHER = 0b000000000,\n SCOPE_PROGRAM = 0b000000001,\n SCOPE_FUNCTION = 0b000000010,\n SCOPE_ARROW = 0b000000100,\n SCOPE_SIMPLE_CATCH = 0b000001000,\n SCOPE_SUPER = 0b000010000,\n SCOPE_DIRECT_SUPER = 0b000100000,\n SCOPE_CLASS = 0b001000000,\n SCOPE_STATIC_BLOCK = 0b010000000,\n SCOPE_TS_MODULE = 0b100000000,\n SCOPE_VAR = SCOPE_PROGRAM | SCOPE_FUNCTION | SCOPE_TS_MODULE;\nconst BIND_KIND_VALUE = 0b000000000001,\n BIND_KIND_TYPE = 0b000000000010,\n BIND_SCOPE_VAR = 0b000000000100,\n BIND_SCOPE_LEXICAL = 0b000000001000,\n BIND_SCOPE_FUNCTION = 0b000000010000,\n BIND_FLAGS_NONE = 0b000001000000,\n BIND_FLAGS_CLASS = 0b000010000000,\n BIND_FLAGS_TS_ENUM = 0b000100000000,\n BIND_FLAGS_TS_CONST_ENUM = 0b001000000000,\n BIND_FLAGS_TS_EXPORT_ONLY = 0b010000000000,\n BIND_FLAGS_FLOW_DECLARE_FN = 0b100000000000;\nconst BIND_CLASS = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_CLASS,\n BIND_LEXICAL = BIND_KIND_VALUE | 0 | BIND_SCOPE_LEXICAL | 0,\n BIND_VAR = BIND_KIND_VALUE | 0 | BIND_SCOPE_VAR | 0,\n BIND_FUNCTION = BIND_KIND_VALUE | 0 | BIND_SCOPE_FUNCTION | 0,\n BIND_TS_INTERFACE = 0 | BIND_KIND_TYPE | 0 | BIND_FLAGS_CLASS,\n BIND_TS_TYPE = 0 | BIND_KIND_TYPE | 0 | 0,\n BIND_TS_ENUM = BIND_KIND_VALUE | BIND_KIND_TYPE | BIND_SCOPE_LEXICAL | BIND_FLAGS_TS_ENUM,\n BIND_TS_AMBIENT = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,\n BIND_NONE = 0 | 0 | 0 | BIND_FLAGS_NONE,\n BIND_OUTSIDE = BIND_KIND_VALUE | 0 | 0 | BIND_FLAGS_NONE,\n BIND_TS_CONST_ENUM = BIND_TS_ENUM | BIND_FLAGS_TS_CONST_ENUM,\n BIND_TS_NAMESPACE = 0 | 0 | 0 | BIND_FLAGS_TS_EXPORT_ONLY,\n BIND_FLOW_DECLARE_FN = BIND_FLAGS_FLOW_DECLARE_FN;\nconst CLASS_ELEMENT_FLAG_STATIC = 0b100,\n CLASS_ELEMENT_KIND_GETTER = 0b010,\n CLASS_ELEMENT_KIND_SETTER = 0b001,\n CLASS_ELEMENT_KIND_ACCESSOR = CLASS_ELEMENT_KIND_GETTER | CLASS_ELEMENT_KIND_SETTER;\nconst CLASS_ELEMENT_STATIC_GETTER = CLASS_ELEMENT_KIND_GETTER | CLASS_ELEMENT_FLAG_STATIC,\n CLASS_ELEMENT_STATIC_SETTER = CLASS_ELEMENT_KIND_SETTER | CLASS_ELEMENT_FLAG_STATIC,\n CLASS_ELEMENT_INSTANCE_GETTER = CLASS_ELEMENT_KIND_GETTER,\n CLASS_ELEMENT_INSTANCE_SETTER = CLASS_ELEMENT_KIND_SETTER,\n CLASS_ELEMENT_OTHER = 0;\n\nclass Scope {\n constructor(flags) {\n this.var = new Set();\n this.lexical = new Set();\n this.functions = new Set();\n this.flags = flags;\n }\n\n}\nclass ScopeHandler {\n constructor(raise, inModule) {\n this.scopeStack = [];\n this.undefinedExports = new Map();\n this.raise = raise;\n this.inModule = inModule;\n }\n\n get inFunction() {\n return (this.currentVarScopeFlags() & SCOPE_FUNCTION) > 0;\n }\n\n get allowSuper() {\n return (this.currentThisScopeFlags() & SCOPE_SUPER) > 0;\n }\n\n get allowDirectSuper() {\n return (this.currentThisScopeFlags() & SCOPE_DIRECT_SUPER) > 0;\n }\n\n get inClass() {\n return (this.currentThisScopeFlags() & SCOPE_CLASS) > 0;\n }\n\n get inClassAndNotInNonArrowFunction() {\n const flags = this.currentThisScopeFlags();\n return (flags & SCOPE_CLASS) > 0 && (flags & SCOPE_FUNCTION) === 0;\n }\n\n get inStaticBlock() {\n for (let i = this.scopeStack.length - 1;; i--) {\n const {\n flags\n } = this.scopeStack[i];\n\n if (flags & SCOPE_STATIC_BLOCK) {\n return true;\n }\n\n if (flags & (SCOPE_VAR | SCOPE_CLASS)) {\n return false;\n }\n }\n }\n\n get inNonArrowFunction() {\n return (this.currentThisScopeFlags() & SCOPE_FUNCTION) > 0;\n }\n\n get treatFunctionsAsVar() {\n return this.treatFunctionsAsVarInScope(this.currentScope());\n }\n\n createScope(flags) {\n return new Scope(flags);\n }\n\n enter(flags) {\n this.scopeStack.push(this.createScope(flags));\n }\n\n exit() {\n this.scopeStack.pop();\n }\n\n treatFunctionsAsVarInScope(scope) {\n return !!(scope.flags & SCOPE_FUNCTION || !this.inModule && scope.flags & SCOPE_PROGRAM);\n }\n\n declareName(name, bindingType, loc) {\n let scope = this.currentScope();\n\n if (bindingType & BIND_SCOPE_LEXICAL || bindingType & BIND_SCOPE_FUNCTION) {\n this.checkRedeclarationInScope(scope, name, bindingType, loc);\n\n if (bindingType & BIND_SCOPE_FUNCTION) {\n scope.functions.add(name);\n } else {\n scope.lexical.add(name);\n }\n\n if (bindingType & BIND_SCOPE_LEXICAL) {\n this.maybeExportDefined(scope, name);\n }\n } else if (bindingType & BIND_SCOPE_VAR) {\n for (let i = this.scopeStack.length - 1; i >= 0; --i) {\n scope = this.scopeStack[i];\n this.checkRedeclarationInScope(scope, name, bindingType, loc);\n scope.var.add(name);\n this.maybeExportDefined(scope, name);\n if (scope.flags & SCOPE_VAR) break;\n }\n }\n\n if (this.inModule && scope.flags & SCOPE_PROGRAM) {\n this.undefinedExports.delete(name);\n }\n }\n\n maybeExportDefined(scope, name) {\n if (this.inModule && scope.flags & SCOPE_PROGRAM) {\n this.undefinedExports.delete(name);\n }\n }\n\n checkRedeclarationInScope(scope, name, bindingType, loc) {\n if (this.isRedeclaredInScope(scope, name, bindingType)) {\n this.raise(ErrorMessages.VarRedeclaration, {\n at: loc\n }, name);\n }\n }\n\n isRedeclaredInScope(scope, name, bindingType) {\n if (!(bindingType & BIND_KIND_VALUE)) return false;\n\n if (bindingType & BIND_SCOPE_LEXICAL) {\n return scope.lexical.has(name) || scope.functions.has(name) || scope.var.has(name);\n }\n\n if (bindingType & BIND_SCOPE_FUNCTION) {\n return scope.lexical.has(name) || !this.treatFunctionsAsVarInScope(scope) && scope.var.has(name);\n }\n\n return scope.lexical.has(name) && !(scope.flags & SCOPE_SIMPLE_CATCH && scope.lexical.values().next().value === name) || !this.treatFunctionsAsVarInScope(scope) && scope.functions.has(name);\n }\n\n checkLocalExport(id) {\n const {\n name\n } = id;\n const topLevelScope = this.scopeStack[0];\n\n if (!topLevelScope.lexical.has(name) && !topLevelScope.var.has(name) && !topLevelScope.functions.has(name)) {\n this.undefinedExports.set(name, id.loc.start);\n }\n }\n\n currentScope() {\n return this.scopeStack[this.scopeStack.length - 1];\n }\n\n currentVarScopeFlags() {\n for (let i = this.scopeStack.length - 1;; i--) {\n const {\n flags\n } = this.scopeStack[i];\n\n if (flags & SCOPE_VAR) {\n return flags;\n }\n }\n }\n\n currentThisScopeFlags() {\n for (let i = this.scopeStack.length - 1;; i--) {\n const {\n flags\n } = this.scopeStack[i];\n\n if (flags & (SCOPE_VAR | SCOPE_CLASS) && !(flags & SCOPE_ARROW)) {\n return flags;\n }\n }\n }\n\n}\n\nclass FlowScope extends Scope {\n constructor(...args) {\n super(...args);\n this.declareFunctions = new Set();\n }\n\n}\n\nclass FlowScopeHandler extends ScopeHandler {\n createScope(flags) {\n return new FlowScope(flags);\n }\n\n declareName(name, bindingType, loc) {\n const scope = this.currentScope();\n\n if (bindingType & BIND_FLAGS_FLOW_DECLARE_FN) {\n this.checkRedeclarationInScope(scope, name, bindingType, loc);\n this.maybeExportDefined(scope, name);\n scope.declareFunctions.add(name);\n return;\n }\n\n super.declareName(...arguments);\n }\n\n isRedeclaredInScope(scope, name, bindingType) {\n if (super.isRedeclaredInScope(...arguments)) return true;\n\n if (bindingType & BIND_FLAGS_FLOW_DECLARE_FN) {\n return !scope.declareFunctions.has(name) && (scope.lexical.has(name) || scope.functions.has(name));\n }\n\n return false;\n }\n\n checkLocalExport(id) {\n if (!this.scopeStack[0].declareFunctions.has(id.name)) {\n super.checkLocalExport(id);\n }\n }\n\n}\n\nconst lineBreak = /\\r\\n?|[\\n\\u2028\\u2029]/;\nconst lineBreakG = new RegExp(lineBreak.source, \"g\");\nfunction isNewLine(code) {\n switch (code) {\n case 10:\n case 13:\n case 8232:\n case 8233:\n return true;\n\n default:\n return false;\n }\n}\nconst skipWhiteSpace = /(?:\\s|\\/\\/.*|\\/\\*[^]*?\\*\\/)*/g;\nconst skipWhiteSpaceInLine = /(?:[^\\S\\n\\r\\u2028\\u2029]|\\/\\/.*|\\/\\*.*?\\*\\/)*/y;\nconst skipWhiteSpaceToLineBreak = new RegExp(\"(?=(\" + skipWhiteSpaceInLine.source + \"))\\\\1\" + /(?=[\\n\\r\\u2028\\u2029]|\\/\\*(?!.*?\\*\\/)|$)/.source, \"y\");\nfunction isWhitespace(code) {\n switch (code) {\n case 0x0009:\n case 0x000b:\n case 0x000c:\n case 32:\n case 160:\n case 5760:\n case 0x2000:\n case 0x2001:\n case 0x2002:\n case 0x2003:\n case 0x2004:\n case 0x2005:\n case 0x2006:\n case 0x2007:\n case 0x2008:\n case 0x2009:\n case 0x200a:\n case 0x202f:\n case 0x205f:\n case 0x3000:\n case 0xfeff:\n return true;\n\n default:\n return false;\n }\n}\n\nclass State {\n constructor() {\n this.strict = void 0;\n this.curLine = void 0;\n this.lineStart = void 0;\n this.startLoc = void 0;\n this.endLoc = void 0;\n this.errors = [];\n this.potentialArrowAt = -1;\n this.noArrowAt = [];\n this.noArrowParamsConversionAt = [];\n this.maybeInArrowParameters = false;\n this.inType = false;\n this.noAnonFunctionType = false;\n this.hasFlowComment = false;\n this.isAmbientContext = false;\n this.inAbstractClass = false;\n this.topicContext = {\n maxNumOfResolvableTopics: 0,\n maxTopicIndex: null\n };\n this.soloAwait = false;\n this.inFSharpPipelineDirectBody = false;\n this.labels = [];\n this.decoratorStack = [[]];\n this.comments = [];\n this.commentStack = [];\n this.pos = 0;\n this.type = 131;\n this.value = null;\n this.start = 0;\n this.end = 0;\n this.lastTokEndLoc = null;\n this.lastTokStartLoc = null;\n this.lastTokStart = 0;\n this.context = [types.brace];\n this.canStartJSXElement = true;\n this.containsEsc = false;\n this.strictErrors = new Map();\n this.tokensLength = 0;\n }\n\n init({\n strictMode,\n sourceType,\n startLine,\n startColumn\n }) {\n this.strict = strictMode === false ? false : strictMode === true ? true : sourceType === \"module\";\n this.curLine = startLine;\n this.lineStart = -startColumn;\n this.startLoc = this.endLoc = new Position(startLine, startColumn, 0);\n }\n\n curPosition() {\n return new Position(this.curLine, this.pos - this.lineStart, this.pos);\n }\n\n clone(skipArrays) {\n const state = new State();\n const keys = Object.keys(this);\n\n for (let i = 0, length = keys.length; i < length; i++) {\n const key = keys[i];\n let val = this[key];\n\n if (!skipArrays && Array.isArray(val)) {\n val = val.slice();\n }\n\n state[key] = val;\n }\n\n return state;\n }\n\n}\n\nvar _isDigit = function isDigit(code) {\n return code >= 48 && code <= 57;\n};\nconst VALID_REGEX_FLAGS = new Set([103, 109, 115, 105, 121, 117, 100]);\nconst forbiddenNumericSeparatorSiblings = {\n decBinOct: [46, 66, 69, 79, 95, 98, 101, 111],\n hex: [46, 88, 95, 120]\n};\nconst allowedNumericSeparatorSiblings = {};\nallowedNumericSeparatorSiblings.bin = [48, 49];\nallowedNumericSeparatorSiblings.oct = [...allowedNumericSeparatorSiblings.bin, 50, 51, 52, 53, 54, 55];\nallowedNumericSeparatorSiblings.dec = [...allowedNumericSeparatorSiblings.oct, 56, 57];\nallowedNumericSeparatorSiblings.hex = [...allowedNumericSeparatorSiblings.dec, 65, 66, 67, 68, 69, 70, 97, 98, 99, 100, 101, 102];\nclass Token {\n constructor(state) {\n this.type = state.type;\n this.value = state.value;\n this.start = state.start;\n this.end = state.end;\n this.loc = new SourceLocation(state.startLoc, state.endLoc);\n }\n\n}\nclass Tokenizer extends ParserError {\n constructor(options, input) {\n super();\n this.isLookahead = void 0;\n this.tokens = [];\n this.state = new State();\n this.state.init(options);\n this.input = input;\n this.length = input.length;\n this.isLookahead = false;\n }\n\n pushToken(token) {\n this.tokens.length = this.state.tokensLength;\n this.tokens.push(token);\n ++this.state.tokensLength;\n }\n\n next() {\n this.checkKeywordEscapes();\n\n if (this.options.tokens) {\n this.pushToken(new Token(this.state));\n }\n\n this.state.lastTokStart = this.state.start;\n this.state.lastTokEndLoc = this.state.endLoc;\n this.state.lastTokStartLoc = this.state.startLoc;\n this.nextToken();\n }\n\n eat(type) {\n if (this.match(type)) {\n this.next();\n return true;\n } else {\n return false;\n }\n }\n\n match(type) {\n return this.state.type === type;\n }\n\n createLookaheadState(state) {\n return {\n pos: state.pos,\n value: null,\n type: state.type,\n start: state.start,\n end: state.end,\n context: [this.curContext()],\n inType: state.inType,\n startLoc: state.startLoc,\n lastTokEndLoc: state.lastTokEndLoc,\n curLine: state.curLine,\n lineStart: state.lineStart,\n curPosition: state.curPosition\n };\n }\n\n lookahead() {\n const old = this.state;\n this.state = this.createLookaheadState(old);\n this.isLookahead = true;\n this.nextToken();\n this.isLookahead = false;\n const curr = this.state;\n this.state = old;\n return curr;\n }\n\n nextTokenStart() {\n return this.nextTokenStartSince(this.state.pos);\n }\n\n nextTokenStartSince(pos) {\n skipWhiteSpace.lastIndex = pos;\n return skipWhiteSpace.test(this.input) ? skipWhiteSpace.lastIndex : pos;\n }\n\n lookaheadCharCode() {\n return this.input.charCodeAt(this.nextTokenStart());\n }\n\n codePointAtPos(pos) {\n let cp = this.input.charCodeAt(pos);\n\n if ((cp & 0xfc00) === 0xd800 && ++pos < this.input.length) {\n const trail = this.input.charCodeAt(pos);\n\n if ((trail & 0xfc00) === 0xdc00) {\n cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);\n }\n }\n\n return cp;\n }\n\n setStrict(strict) {\n this.state.strict = strict;\n\n if (strict) {\n this.state.strictErrors.forEach(({\n message,\n loc\n }) => this.raise(message, {\n at: loc\n }));\n this.state.strictErrors.clear();\n }\n }\n\n curContext() {\n return this.state.context[this.state.context.length - 1];\n }\n\n nextToken() {\n this.skipSpace();\n this.state.start = this.state.pos;\n if (!this.isLookahead) this.state.startLoc = this.state.curPosition();\n\n if (this.state.pos >= this.length) {\n this.finishToken(131);\n return;\n }\n\n this.getTokenFromCode(this.codePointAtPos(this.state.pos));\n }\n\n skipBlockComment() {\n let startLoc;\n if (!this.isLookahead) startLoc = this.state.curPosition();\n const start = this.state.pos;\n const end = this.input.indexOf(\"*/\", start + 2);\n\n if (end === -1) {\n throw this.raise(ErrorMessages.UnterminatedComment, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos = end + 2;\n lineBreakG.lastIndex = start + 2;\n\n while (lineBreakG.test(this.input) && lineBreakG.lastIndex <= end) {\n ++this.state.curLine;\n this.state.lineStart = lineBreakG.lastIndex;\n }\n\n if (this.isLookahead) return;\n const comment = {\n type: \"CommentBlock\",\n value: this.input.slice(start + 2, end),\n start,\n end: end + 2,\n loc: new SourceLocation(startLoc, this.state.curPosition())\n };\n if (this.options.tokens) this.pushToken(comment);\n return comment;\n }\n\n skipLineComment(startSkip) {\n const start = this.state.pos;\n let startLoc;\n if (!this.isLookahead) startLoc = this.state.curPosition();\n let ch = this.input.charCodeAt(this.state.pos += startSkip);\n\n if (this.state.pos < this.length) {\n while (!isNewLine(ch) && ++this.state.pos < this.length) {\n ch = this.input.charCodeAt(this.state.pos);\n }\n }\n\n if (this.isLookahead) return;\n const end = this.state.pos;\n const value = this.input.slice(start + startSkip, end);\n const comment = {\n type: \"CommentLine\",\n value,\n start,\n end,\n loc: new SourceLocation(startLoc, this.state.curPosition())\n };\n if (this.options.tokens) this.pushToken(comment);\n return comment;\n }\n\n skipSpace() {\n const spaceStart = this.state.pos;\n const comments = [];\n\n loop: while (this.state.pos < this.length) {\n const ch = this.input.charCodeAt(this.state.pos);\n\n switch (ch) {\n case 32:\n case 160:\n case 9:\n ++this.state.pos;\n break;\n\n case 13:\n if (this.input.charCodeAt(this.state.pos + 1) === 10) {\n ++this.state.pos;\n }\n\n case 10:\n case 8232:\n case 8233:\n ++this.state.pos;\n ++this.state.curLine;\n this.state.lineStart = this.state.pos;\n break;\n\n case 47:\n switch (this.input.charCodeAt(this.state.pos + 1)) {\n case 42:\n {\n const comment = this.skipBlockComment();\n\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n\n break;\n }\n\n case 47:\n {\n const comment = this.skipLineComment(2);\n\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n\n break;\n }\n\n default:\n break loop;\n }\n\n break;\n\n default:\n if (isWhitespace(ch)) {\n ++this.state.pos;\n } else if (ch === 45 && !this.inModule) {\n const pos = this.state.pos;\n\n if (this.input.charCodeAt(pos + 1) === 45 && this.input.charCodeAt(pos + 2) === 62 && (spaceStart === 0 || this.state.lineStart > spaceStart)) {\n const comment = this.skipLineComment(3);\n\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n } else {\n break loop;\n }\n } else if (ch === 60 && !this.inModule) {\n const pos = this.state.pos;\n\n if (this.input.charCodeAt(pos + 1) === 33 && this.input.charCodeAt(pos + 2) === 45 && this.input.charCodeAt(pos + 3) === 45) {\n const comment = this.skipLineComment(4);\n\n if (comment !== undefined) {\n this.addComment(comment);\n if (this.options.attachComment) comments.push(comment);\n }\n } else {\n break loop;\n }\n } else {\n break loop;\n }\n\n }\n }\n\n if (comments.length > 0) {\n const end = this.state.pos;\n const CommentWhitespace = {\n start: spaceStart,\n end,\n comments,\n leadingNode: null,\n trailingNode: null,\n containingNode: null\n };\n this.state.commentStack.push(CommentWhitespace);\n }\n }\n\n finishToken(type, val) {\n this.state.end = this.state.pos;\n this.state.endLoc = this.state.curPosition();\n const prevType = this.state.type;\n this.state.type = type;\n this.state.value = val;\n\n if (!this.isLookahead) {\n this.updateContext(prevType);\n }\n }\n\n replaceToken(type) {\n this.state.type = type;\n this.updateContext();\n }\n\n readToken_numberSign() {\n if (this.state.pos === 0 && this.readToken_interpreter()) {\n return;\n }\n\n const nextPos = this.state.pos + 1;\n const next = this.codePointAtPos(nextPos);\n\n if (next >= 48 && next <= 57) {\n throw this.raise(ErrorMessages.UnexpectedDigitAfterHash, {\n at: this.state.curPosition()\n });\n }\n\n if (next === 123 || next === 91 && this.hasPlugin(\"recordAndTuple\")) {\n this.expectPlugin(\"recordAndTuple\");\n\n if (this.getPluginOption(\"recordAndTuple\", \"syntaxType\") !== \"hash\") {\n throw this.raise(next === 123 ? ErrorMessages.RecordExpressionHashIncorrectStartSyntaxType : ErrorMessages.TupleExpressionHashIncorrectStartSyntaxType, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos += 2;\n\n if (next === 123) {\n this.finishToken(7);\n } else {\n this.finishToken(1);\n }\n } else if (isIdentifierStart(next)) {\n ++this.state.pos;\n this.finishToken(130, this.readWord1(next));\n } else if (next === 92) {\n ++this.state.pos;\n this.finishToken(130, this.readWord1());\n } else {\n this.finishOp(27, 1);\n }\n }\n\n readToken_dot() {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next >= 48 && next <= 57) {\n this.readNumber(true);\n return;\n }\n\n if (next === 46 && this.input.charCodeAt(this.state.pos + 2) === 46) {\n this.state.pos += 3;\n this.finishToken(21);\n } else {\n ++this.state.pos;\n this.finishToken(16);\n }\n }\n\n readToken_slash() {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === 61) {\n this.finishOp(31, 2);\n } else {\n this.finishOp(52, 1);\n }\n }\n\n readToken_interpreter() {\n if (this.state.pos !== 0 || this.length < 2) return false;\n let ch = this.input.charCodeAt(this.state.pos + 1);\n if (ch !== 33) return false;\n const start = this.state.pos;\n this.state.pos += 1;\n\n while (!isNewLine(ch) && ++this.state.pos < this.length) {\n ch = this.input.charCodeAt(this.state.pos);\n }\n\n const value = this.input.slice(start + 2, this.state.pos);\n this.finishToken(28, value);\n return true;\n }\n\n readToken_mult_modulo(code) {\n let type = code === 42 ? 51 : 50;\n let width = 1;\n let next = this.input.charCodeAt(this.state.pos + 1);\n\n if (code === 42 && next === 42) {\n width++;\n next = this.input.charCodeAt(this.state.pos + 2);\n type = 53;\n }\n\n if (next === 61 && !this.state.inType) {\n width++;\n type = code === 37 ? 33 : 30;\n }\n\n this.finishOp(type, width);\n }\n\n readToken_pipe_amp(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === code) {\n if (this.input.charCodeAt(this.state.pos + 2) === 61) {\n this.finishOp(30, 3);\n } else {\n this.finishOp(code === 124 ? 39 : 40, 2);\n }\n\n return;\n }\n\n if (code === 124) {\n if (next === 62) {\n this.finishOp(37, 2);\n return;\n }\n\n if (this.hasPlugin(\"recordAndTuple\") && next === 125) {\n if (this.getPluginOption(\"recordAndTuple\", \"syntaxType\") !== \"bar\") {\n throw this.raise(ErrorMessages.RecordExpressionBarIncorrectEndSyntaxType, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos += 2;\n this.finishToken(9);\n return;\n }\n\n if (this.hasPlugin(\"recordAndTuple\") && next === 93) {\n if (this.getPluginOption(\"recordAndTuple\", \"syntaxType\") !== \"bar\") {\n throw this.raise(ErrorMessages.TupleExpressionBarIncorrectEndSyntaxType, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos += 2;\n this.finishToken(4);\n return;\n }\n }\n\n if (next === 61) {\n this.finishOp(30, 2);\n return;\n }\n\n this.finishOp(code === 124 ? 41 : 43, 1);\n }\n\n readToken_caret() {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === 61 && !this.state.inType) {\n this.finishOp(32, 2);\n } else {\n this.finishOp(42, 1);\n }\n }\n\n readToken_plus_min(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === code) {\n this.finishOp(34, 2);\n return;\n }\n\n if (next === 61) {\n this.finishOp(30, 2);\n } else {\n this.finishOp(49, 1);\n }\n }\n\n readToken_lt() {\n const {\n pos\n } = this.state;\n const next = this.input.charCodeAt(pos + 1);\n\n if (next === 60) {\n if (this.input.charCodeAt(pos + 2) === 61) {\n this.finishOp(30, 3);\n return;\n }\n\n this.finishOp(48, 2);\n return;\n }\n\n if (next === 61) {\n this.finishOp(47, 2);\n return;\n }\n\n this.finishOp(45, 1);\n }\n\n readToken_gt() {\n const {\n pos\n } = this.state;\n const next = this.input.charCodeAt(pos + 1);\n\n if (next === 62) {\n const size = this.input.charCodeAt(pos + 2) === 62 ? 3 : 2;\n\n if (this.input.charCodeAt(pos + size) === 61) {\n this.finishOp(30, size + 1);\n return;\n }\n\n this.finishOp(48, size);\n return;\n }\n\n if (next === 61) {\n this.finishOp(47, 2);\n return;\n }\n\n this.finishOp(46, 1);\n }\n\n readToken_eq_excl(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === 61) {\n this.finishOp(44, this.input.charCodeAt(this.state.pos + 2) === 61 ? 3 : 2);\n return;\n }\n\n if (code === 61 && next === 62) {\n this.state.pos += 2;\n this.finishToken(19);\n return;\n }\n\n this.finishOp(code === 61 ? 29 : 35, 1);\n }\n\n readToken_question() {\n const next = this.input.charCodeAt(this.state.pos + 1);\n const next2 = this.input.charCodeAt(this.state.pos + 2);\n\n if (next === 63) {\n if (next2 === 61) {\n this.finishOp(30, 3);\n } else {\n this.finishOp(38, 2);\n }\n } else if (next === 46 && !(next2 >= 48 && next2 <= 57)) {\n this.state.pos += 2;\n this.finishToken(18);\n } else {\n ++this.state.pos;\n this.finishToken(17);\n }\n }\n\n getTokenFromCode(code) {\n switch (code) {\n case 46:\n this.readToken_dot();\n return;\n\n case 40:\n ++this.state.pos;\n this.finishToken(10);\n return;\n\n case 41:\n ++this.state.pos;\n this.finishToken(11);\n return;\n\n case 59:\n ++this.state.pos;\n this.finishToken(13);\n return;\n\n case 44:\n ++this.state.pos;\n this.finishToken(12);\n return;\n\n case 91:\n if (this.hasPlugin(\"recordAndTuple\") && this.input.charCodeAt(this.state.pos + 1) === 124) {\n if (this.getPluginOption(\"recordAndTuple\", \"syntaxType\") !== \"bar\") {\n throw this.raise(ErrorMessages.TupleExpressionBarIncorrectStartSyntaxType, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos += 2;\n this.finishToken(2);\n } else {\n ++this.state.pos;\n this.finishToken(0);\n }\n\n return;\n\n case 93:\n ++this.state.pos;\n this.finishToken(3);\n return;\n\n case 123:\n if (this.hasPlugin(\"recordAndTuple\") && this.input.charCodeAt(this.state.pos + 1) === 124) {\n if (this.getPluginOption(\"recordAndTuple\", \"syntaxType\") !== \"bar\") {\n throw this.raise(ErrorMessages.RecordExpressionBarIncorrectStartSyntaxType, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos += 2;\n this.finishToken(6);\n } else {\n ++this.state.pos;\n this.finishToken(5);\n }\n\n return;\n\n case 125:\n ++this.state.pos;\n this.finishToken(8);\n return;\n\n case 58:\n if (this.hasPlugin(\"functionBind\") && this.input.charCodeAt(this.state.pos + 1) === 58) {\n this.finishOp(15, 2);\n } else {\n ++this.state.pos;\n this.finishToken(14);\n }\n\n return;\n\n case 63:\n this.readToken_question();\n return;\n\n case 96:\n this.readTemplateToken();\n return;\n\n case 48:\n {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (next === 120 || next === 88) {\n this.readRadixNumber(16);\n return;\n }\n\n if (next === 111 || next === 79) {\n this.readRadixNumber(8);\n return;\n }\n\n if (next === 98 || next === 66) {\n this.readRadixNumber(2);\n return;\n }\n }\n\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n this.readNumber(false);\n return;\n\n case 34:\n case 39:\n this.readString(code);\n return;\n\n case 47:\n this.readToken_slash();\n return;\n\n case 37:\n case 42:\n this.readToken_mult_modulo(code);\n return;\n\n case 124:\n case 38:\n this.readToken_pipe_amp(code);\n return;\n\n case 94:\n this.readToken_caret();\n return;\n\n case 43:\n case 45:\n this.readToken_plus_min(code);\n return;\n\n case 60:\n this.readToken_lt();\n return;\n\n case 62:\n this.readToken_gt();\n return;\n\n case 61:\n case 33:\n this.readToken_eq_excl(code);\n return;\n\n case 126:\n this.finishOp(36, 1);\n return;\n\n case 64:\n ++this.state.pos;\n this.finishToken(26);\n return;\n\n case 35:\n this.readToken_numberSign();\n return;\n\n case 92:\n this.readWord();\n return;\n\n default:\n if (isIdentifierStart(code)) {\n this.readWord(code);\n return;\n }\n\n }\n\n throw this.raise(ErrorMessages.InvalidOrUnexpectedToken, {\n at: this.state.curPosition()\n }, String.fromCodePoint(code));\n }\n\n finishOp(type, size) {\n const str = this.input.slice(this.state.pos, this.state.pos + size);\n this.state.pos += size;\n this.finishToken(type, str);\n }\n\n readRegexp() {\n const startLoc = this.state.startLoc;\n const start = this.state.start + 1;\n let escaped, inClass;\n let {\n pos\n } = this.state;\n\n for (;; ++pos) {\n if (pos >= this.length) {\n throw this.raise(ErrorMessages.UnterminatedRegExp, {\n at: createPositionWithColumnOffset(startLoc, 1)\n });\n }\n\n const ch = this.input.charCodeAt(pos);\n\n if (isNewLine(ch)) {\n throw this.raise(ErrorMessages.UnterminatedRegExp, {\n at: createPositionWithColumnOffset(startLoc, 1)\n });\n }\n\n if (escaped) {\n escaped = false;\n } else {\n if (ch === 91) {\n inClass = true;\n } else if (ch === 93 && inClass) {\n inClass = false;\n } else if (ch === 47 && !inClass) {\n break;\n }\n\n escaped = ch === 92;\n }\n }\n\n const content = this.input.slice(start, pos);\n ++pos;\n let mods = \"\";\n\n while (pos < this.length) {\n const cp = this.codePointAtPos(pos);\n const char = String.fromCharCode(cp);\n\n if (VALID_REGEX_FLAGS.has(cp)) {\n if (mods.includes(char)) {\n this.raise(ErrorMessages.DuplicateRegExpFlags, {\n at: createPositionWithColumnOffset(startLoc, pos + 2 - start)\n });\n }\n } else if (isIdentifierChar(cp) || cp === 92) {\n this.raise(ErrorMessages.MalformedRegExpFlags, {\n at: createPositionWithColumnOffset(startLoc, pos + 2 - start)\n });\n } else {\n break;\n }\n\n ++pos;\n mods += char;\n }\n\n this.state.pos = pos;\n this.finishToken(129, {\n pattern: content,\n flags: mods\n });\n }\n\n readInt(radix, len, forceLen, allowNumSeparator = true) {\n const start = this.state.pos;\n const forbiddenSiblings = radix === 16 ? forbiddenNumericSeparatorSiblings.hex : forbiddenNumericSeparatorSiblings.decBinOct;\n const allowedSiblings = radix === 16 ? allowedNumericSeparatorSiblings.hex : radix === 10 ? allowedNumericSeparatorSiblings.dec : radix === 8 ? allowedNumericSeparatorSiblings.oct : allowedNumericSeparatorSiblings.bin;\n let invalid = false;\n let total = 0;\n\n for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {\n const code = this.input.charCodeAt(this.state.pos);\n let val;\n\n if (code === 95) {\n const prev = this.input.charCodeAt(this.state.pos - 1);\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (allowedSiblings.indexOf(next) === -1) {\n this.raise(ErrorMessages.UnexpectedNumericSeparator, {\n at: this.state.curPosition()\n });\n } else if (forbiddenSiblings.indexOf(prev) > -1 || forbiddenSiblings.indexOf(next) > -1 || Number.isNaN(next)) {\n this.raise(ErrorMessages.UnexpectedNumericSeparator, {\n at: this.state.curPosition()\n });\n }\n\n if (!allowNumSeparator) {\n this.raise(ErrorMessages.NumericSeparatorInEscapeSequence, {\n at: this.state.curPosition()\n });\n }\n\n ++this.state.pos;\n continue;\n }\n\n if (code >= 97) {\n val = code - 97 + 10;\n } else if (code >= 65) {\n val = code - 65 + 10;\n } else if (_isDigit(code)) {\n val = code - 48;\n } else {\n val = Infinity;\n }\n\n if (val >= radix) {\n if (this.options.errorRecovery && val <= 9) {\n val = 0;\n this.raise(ErrorMessages.InvalidDigit, {\n at: this.state.curPosition()\n }, radix);\n } else if (forceLen) {\n val = 0;\n invalid = true;\n } else {\n break;\n }\n }\n\n ++this.state.pos;\n total = total * radix + val;\n }\n\n if (this.state.pos === start || len != null && this.state.pos - start !== len || invalid) {\n return null;\n }\n\n return total;\n }\n\n readRadixNumber(radix) {\n const startLoc = this.state.curPosition();\n let isBigInt = false;\n this.state.pos += 2;\n const val = this.readInt(radix);\n\n if (val == null) {\n this.raise(ErrorMessages.InvalidDigit, {\n at: createPositionWithColumnOffset(startLoc, 2)\n }, radix);\n }\n\n const next = this.input.charCodeAt(this.state.pos);\n\n if (next === 110) {\n ++this.state.pos;\n isBigInt = true;\n } else if (next === 109) {\n throw this.raise(ErrorMessages.InvalidDecimal, {\n at: startLoc\n });\n }\n\n if (isIdentifierStart(this.codePointAtPos(this.state.pos))) {\n throw this.raise(ErrorMessages.NumberIdentifier, {\n at: this.state.curPosition()\n });\n }\n\n if (isBigInt) {\n const str = this.input.slice(indexes.get(startLoc), this.state.pos).replace(/[_n]/g, \"\");\n this.finishToken(127, str);\n return;\n }\n\n this.finishToken(126, val);\n }\n\n readNumber(startsWithDot) {\n const start = this.state.pos;\n const startLoc = this.state.curPosition();\n let isFloat = false;\n let isBigInt = false;\n let isDecimal = false;\n let hasExponent = false;\n let isOctal = false;\n\n if (!startsWithDot && this.readInt(10) === null) {\n this.raise(ErrorMessages.InvalidNumber, {\n at: this.state.curPosition()\n });\n }\n\n const hasLeadingZero = this.state.pos - start >= 2 && this.input.charCodeAt(start) === 48;\n\n if (hasLeadingZero) {\n const integer = this.input.slice(start, this.state.pos);\n this.recordStrictModeErrors(ErrorMessages.StrictOctalLiteral, startLoc);\n\n if (!this.state.strict) {\n const underscorePos = integer.indexOf(\"_\");\n\n if (underscorePos > 0) {\n this.raise(ErrorMessages.ZeroDigitNumericSeparator, {\n at: createPositionWithColumnOffset(startLoc, underscorePos)\n });\n }\n }\n\n isOctal = hasLeadingZero && !/[89]/.test(integer);\n }\n\n let next = this.input.charCodeAt(this.state.pos);\n\n if (next === 46 && !isOctal) {\n ++this.state.pos;\n this.readInt(10);\n isFloat = true;\n next = this.input.charCodeAt(this.state.pos);\n }\n\n if ((next === 69 || next === 101) && !isOctal) {\n next = this.input.charCodeAt(++this.state.pos);\n\n if (next === 43 || next === 45) {\n ++this.state.pos;\n }\n\n if (this.readInt(10) === null) {\n this.raise(ErrorMessages.InvalidOrMissingExponent, {\n at: startLoc\n });\n }\n\n isFloat = true;\n hasExponent = true;\n next = this.input.charCodeAt(this.state.pos);\n }\n\n if (next === 110) {\n if (isFloat || hasLeadingZero) {\n this.raise(ErrorMessages.InvalidBigIntLiteral, {\n at: startLoc\n });\n }\n\n ++this.state.pos;\n isBigInt = true;\n }\n\n if (next === 109) {\n this.expectPlugin(\"decimal\", this.state.curPosition());\n\n if (hasExponent || hasLeadingZero) {\n this.raise(ErrorMessages.InvalidDecimal, {\n at: startLoc\n });\n }\n\n ++this.state.pos;\n isDecimal = true;\n }\n\n if (isIdentifierStart(this.codePointAtPos(this.state.pos))) {\n throw this.raise(ErrorMessages.NumberIdentifier, {\n at: this.state.curPosition()\n });\n }\n\n const str = this.input.slice(start, this.state.pos).replace(/[_mn]/g, \"\");\n\n if (isBigInt) {\n this.finishToken(127, str);\n return;\n }\n\n if (isDecimal) {\n this.finishToken(128, str);\n return;\n }\n\n const val = isOctal ? parseInt(str, 8) : parseFloat(str);\n this.finishToken(126, val);\n }\n\n readCodePoint(throwOnInvalid) {\n const ch = this.input.charCodeAt(this.state.pos);\n let code;\n\n if (ch === 123) {\n ++this.state.pos;\n code = this.readHexChar(this.input.indexOf(\"}\", this.state.pos) - this.state.pos, true, throwOnInvalid);\n ++this.state.pos;\n\n if (code !== null && code > 0x10ffff) {\n if (throwOnInvalid) {\n this.raise(ErrorMessages.InvalidCodePoint, {\n at: this.state.curPosition()\n });\n } else {\n return null;\n }\n }\n } else {\n code = this.readHexChar(4, false, throwOnInvalid);\n }\n\n return code;\n }\n\n readString(quote) {\n let out = \"\",\n chunkStart = ++this.state.pos;\n\n for (;;) {\n if (this.state.pos >= this.length) {\n throw this.raise(ErrorMessages.UnterminatedString, {\n at: this.state.startLoc\n });\n }\n\n const ch = this.input.charCodeAt(this.state.pos);\n if (ch === quote) break;\n\n if (ch === 92) {\n out += this.input.slice(chunkStart, this.state.pos);\n out += this.readEscapedChar(false);\n chunkStart = this.state.pos;\n } else if (ch === 8232 || ch === 8233) {\n ++this.state.pos;\n ++this.state.curLine;\n this.state.lineStart = this.state.pos;\n } else if (isNewLine(ch)) {\n throw this.raise(ErrorMessages.UnterminatedString, {\n at: this.state.startLoc\n });\n } else {\n ++this.state.pos;\n }\n }\n\n out += this.input.slice(chunkStart, this.state.pos++);\n this.finishToken(125, out);\n }\n\n readTemplateContinuation() {\n if (!this.match(8)) {\n this.unexpected(null, 8);\n }\n\n this.state.pos--;\n this.readTemplateToken();\n }\n\n readTemplateToken() {\n let out = \"\",\n chunkStart = this.state.pos,\n containsInvalid = false;\n ++this.state.pos;\n\n for (;;) {\n if (this.state.pos >= this.length) {\n throw this.raise(ErrorMessages.UnterminatedTemplate, {\n at: createPositionWithColumnOffset(this.state.startLoc, 1)\n });\n }\n\n const ch = this.input.charCodeAt(this.state.pos);\n\n if (ch === 96) {\n ++this.state.pos;\n out += this.input.slice(chunkStart, this.state.pos);\n this.finishToken(24, containsInvalid ? null : out);\n return;\n }\n\n if (ch === 36 && this.input.charCodeAt(this.state.pos + 1) === 123) {\n this.state.pos += 2;\n out += this.input.slice(chunkStart, this.state.pos);\n this.finishToken(25, containsInvalid ? null : out);\n return;\n }\n\n if (ch === 92) {\n out += this.input.slice(chunkStart, this.state.pos);\n const escaped = this.readEscapedChar(true);\n\n if (escaped === null) {\n containsInvalid = true;\n } else {\n out += escaped;\n }\n\n chunkStart = this.state.pos;\n } else if (isNewLine(ch)) {\n out += this.input.slice(chunkStart, this.state.pos);\n ++this.state.pos;\n\n switch (ch) {\n case 13:\n if (this.input.charCodeAt(this.state.pos) === 10) {\n ++this.state.pos;\n }\n\n case 10:\n out += \"\\n\";\n break;\n\n default:\n out += String.fromCharCode(ch);\n break;\n }\n\n ++this.state.curLine;\n this.state.lineStart = this.state.pos;\n chunkStart = this.state.pos;\n } else {\n ++this.state.pos;\n }\n }\n }\n\n recordStrictModeErrors(message, loc) {\n const index = indexes.get(loc);\n\n if (this.state.strict && !this.state.strictErrors.has(index)) {\n this.raise(message, {\n at: loc\n });\n } else {\n this.state.strictErrors.set(index, {\n loc,\n message\n });\n }\n }\n\n readEscapedChar(inTemplate) {\n const throwOnInvalid = !inTemplate;\n const ch = this.input.charCodeAt(++this.state.pos);\n ++this.state.pos;\n\n switch (ch) {\n case 110:\n return \"\\n\";\n\n case 114:\n return \"\\r\";\n\n case 120:\n {\n const code = this.readHexChar(2, false, throwOnInvalid);\n return code === null ? null : String.fromCharCode(code);\n }\n\n case 117:\n {\n const code = this.readCodePoint(throwOnInvalid);\n return code === null ? null : String.fromCodePoint(code);\n }\n\n case 116:\n return \"\\t\";\n\n case 98:\n return \"\\b\";\n\n case 118:\n return \"\\u000b\";\n\n case 102:\n return \"\\f\";\n\n case 13:\n if (this.input.charCodeAt(this.state.pos) === 10) {\n ++this.state.pos;\n }\n\n case 10:\n this.state.lineStart = this.state.pos;\n ++this.state.curLine;\n\n case 8232:\n case 8233:\n return \"\";\n\n case 56:\n case 57:\n if (inTemplate) {\n return null;\n } else {\n this.recordStrictModeErrors(ErrorMessages.StrictNumericEscape, createPositionWithColumnOffset(this.state.curPosition(), -1));\n }\n\n default:\n if (ch >= 48 && ch <= 55) {\n const codePos = createPositionWithColumnOffset(this.state.curPosition(), -1);\n const match = this.input.substr(this.state.pos - 1, 3).match(/^[0-7]+/);\n let octalStr = match[0];\n let octal = parseInt(octalStr, 8);\n\n if (octal > 255) {\n octalStr = octalStr.slice(0, -1);\n octal = parseInt(octalStr, 8);\n }\n\n this.state.pos += octalStr.length - 1;\n const next = this.input.charCodeAt(this.state.pos);\n\n if (octalStr !== \"0\" || next === 56 || next === 57) {\n if (inTemplate) {\n return null;\n } else {\n this.recordStrictModeErrors(ErrorMessages.StrictNumericEscape, codePos);\n }\n }\n\n return String.fromCharCode(octal);\n }\n\n return String.fromCharCode(ch);\n }\n }\n\n readHexChar(len, forceLen, throwOnInvalid) {\n const codeLoc = this.state.curPosition();\n const n = this.readInt(16, len, forceLen, false);\n\n if (n === null) {\n if (throwOnInvalid) {\n this.raise(ErrorMessages.InvalidEscapeSequence, {\n at: codeLoc\n });\n } else {\n this.state.pos = indexes.get(codeLoc) - 1;\n }\n }\n\n return n;\n }\n\n readWord1(firstCode) {\n this.state.containsEsc = false;\n let word = \"\";\n const start = this.state.pos;\n let chunkStart = this.state.pos;\n\n if (firstCode !== undefined) {\n this.state.pos += firstCode <= 0xffff ? 1 : 2;\n }\n\n while (this.state.pos < this.length) {\n const ch = this.codePointAtPos(this.state.pos);\n\n if (isIdentifierChar(ch)) {\n this.state.pos += ch <= 0xffff ? 1 : 2;\n } else if (ch === 92) {\n this.state.containsEsc = true;\n word += this.input.slice(chunkStart, this.state.pos);\n const escStart = this.state.curPosition();\n const identifierCheck = this.state.pos === start ? isIdentifierStart : isIdentifierChar;\n\n if (this.input.charCodeAt(++this.state.pos) !== 117) {\n this.raise(ErrorMessages.MissingUnicodeEscape, {\n at: this.state.curPosition()\n });\n chunkStart = this.state.pos - 1;\n continue;\n }\n\n ++this.state.pos;\n const esc = this.readCodePoint(true);\n\n if (esc !== null) {\n if (!identifierCheck(esc)) {\n this.raise(ErrorMessages.EscapedCharNotAnIdentifier, {\n at: escStart\n });\n }\n\n word += String.fromCodePoint(esc);\n }\n\n chunkStart = this.state.pos;\n } else {\n break;\n }\n }\n\n return word + this.input.slice(chunkStart, this.state.pos);\n }\n\n readWord(firstCode) {\n const word = this.readWord1(firstCode);\n const type = keywords$1.get(word);\n\n if (type !== undefined) {\n this.finishToken(type, tokenLabelName(type));\n } else {\n this.finishToken(124, word);\n }\n }\n\n checkKeywordEscapes() {\n const {\n type\n } = this.state;\n\n if (tokenIsKeyword(type) && this.state.containsEsc) {\n this.raise(ErrorMessages.InvalidEscapedReservedWord, {\n at: this.state.startLoc\n }, tokenLabelName(type));\n }\n }\n\n updateContext(prevType) {}\n\n}\n\nclass ClassScope {\n constructor() {\n this.privateNames = new Set();\n this.loneAccessors = new Map();\n this.undefinedPrivateNames = new Map();\n }\n\n}\nclass ClassScopeHandler {\n constructor(raise) {\n this.stack = [];\n this.undefinedPrivateNames = new Map();\n this.raise = raise;\n }\n\n current() {\n return this.stack[this.stack.length - 1];\n }\n\n enter() {\n this.stack.push(new ClassScope());\n }\n\n exit() {\n const oldClassScope = this.stack.pop();\n const current = this.current();\n\n for (const [name, loc] of Array.from(oldClassScope.undefinedPrivateNames)) {\n if (current) {\n if (!current.undefinedPrivateNames.has(name)) {\n current.undefinedPrivateNames.set(name, loc);\n }\n } else {\n this.raise(ErrorMessages.InvalidPrivateFieldResolution, {\n at: loc\n }, name);\n }\n }\n }\n\n declarePrivateName(name, elementType, loc) {\n const {\n privateNames,\n loneAccessors,\n undefinedPrivateNames\n } = this.current();\n let redefined = privateNames.has(name);\n\n if (elementType & CLASS_ELEMENT_KIND_ACCESSOR) {\n const accessor = redefined && loneAccessors.get(name);\n\n if (accessor) {\n const oldStatic = accessor & CLASS_ELEMENT_FLAG_STATIC;\n const newStatic = elementType & CLASS_ELEMENT_FLAG_STATIC;\n const oldKind = accessor & CLASS_ELEMENT_KIND_ACCESSOR;\n const newKind = elementType & CLASS_ELEMENT_KIND_ACCESSOR;\n redefined = oldKind === newKind || oldStatic !== newStatic;\n if (!redefined) loneAccessors.delete(name);\n } else if (!redefined) {\n loneAccessors.set(name, elementType);\n }\n }\n\n if (redefined) {\n this.raise(ErrorMessages.PrivateNameRedeclaration, {\n at: loc\n }, name);\n }\n\n privateNames.add(name);\n undefinedPrivateNames.delete(name);\n }\n\n usePrivateName(name, loc) {\n let classScope;\n\n for (classScope of this.stack) {\n if (classScope.privateNames.has(name)) return;\n }\n\n if (classScope) {\n classScope.undefinedPrivateNames.set(name, loc);\n } else {\n this.raise(ErrorMessages.InvalidPrivateFieldResolution, {\n at: loc\n }, name);\n }\n }\n\n}\n\nconst kExpression = 0,\n kMaybeArrowParameterDeclaration = 1,\n kMaybeAsyncArrowParameterDeclaration = 2,\n kParameterDeclaration = 3;\n\nclass ExpressionScope {\n constructor(type = kExpression) {\n this.type = void 0;\n this.type = type;\n }\n\n canBeArrowParameterDeclaration() {\n return this.type === kMaybeAsyncArrowParameterDeclaration || this.type === kMaybeArrowParameterDeclaration;\n }\n\n isCertainlyParameterDeclaration() {\n return this.type === kParameterDeclaration;\n }\n\n}\n\nclass ArrowHeadParsingScope extends ExpressionScope {\n constructor(type) {\n super(type);\n this.errors = new Map();\n }\n\n recordDeclarationError(message, loc) {\n this.errors.set(indexes.get(loc), {\n message,\n loc\n });\n }\n\n clearDeclarationError(loc) {\n this.errors.delete(indexes.get(loc));\n }\n\n iterateErrors(iterator) {\n this.errors.forEach(iterator);\n }\n\n}\n\nclass ExpressionScopeHandler {\n constructor(raise) {\n this.stack = [new ExpressionScope()];\n this.raise = raise;\n }\n\n enter(scope) {\n this.stack.push(scope);\n }\n\n exit() {\n this.stack.pop();\n }\n\n recordParameterInitializerError(loc, template) {\n const {\n stack\n } = this;\n let i = stack.length - 1;\n let scope = stack[i];\n\n while (!scope.isCertainlyParameterDeclaration()) {\n if (scope.canBeArrowParameterDeclaration()) {\n scope.recordDeclarationError(template, loc);\n } else {\n return;\n }\n\n scope = stack[--i];\n }\n\n this.raise(template, {\n at: loc\n });\n }\n\n recordParenthesizedIdentifierError(template, loc) {\n const {\n stack\n } = this;\n const scope = stack[stack.length - 1];\n\n if (scope.isCertainlyParameterDeclaration()) {\n this.raise(template, {\n at: loc\n });\n } else if (scope.canBeArrowParameterDeclaration()) {\n scope.recordDeclarationError(template, loc);\n } else {\n return;\n }\n }\n\n recordAsyncArrowParametersError(template, loc) {\n const {\n stack\n } = this;\n let i = stack.length - 1;\n let scope = stack[i];\n\n while (scope.canBeArrowParameterDeclaration()) {\n if (scope.type === kMaybeAsyncArrowParameterDeclaration) {\n scope.recordDeclarationError(template, loc);\n }\n\n scope = stack[--i];\n }\n }\n\n validateAsPattern() {\n const {\n stack\n } = this;\n const currentScope = stack[stack.length - 1];\n if (!currentScope.canBeArrowParameterDeclaration()) return;\n currentScope.iterateErrors(({\n message,\n loc\n }) => {\n this.raise(message, {\n at: loc\n });\n let i = stack.length - 2;\n let scope = stack[i];\n\n while (scope.canBeArrowParameterDeclaration()) {\n scope.clearDeclarationError(loc);\n scope = stack[--i];\n }\n });\n }\n\n}\nfunction newParameterDeclarationScope() {\n return new ExpressionScope(kParameterDeclaration);\n}\nfunction newArrowHeadScope() {\n return new ArrowHeadParsingScope(kMaybeArrowParameterDeclaration);\n}\nfunction newAsyncArrowScope() {\n return new ArrowHeadParsingScope(kMaybeAsyncArrowParameterDeclaration);\n}\nfunction newExpressionScope() {\n return new ExpressionScope();\n}\n\nconst PARAM = 0b0000,\n PARAM_YIELD = 0b0001,\n PARAM_AWAIT = 0b0010,\n PARAM_RETURN = 0b0100,\n PARAM_IN = 0b1000;\nclass ProductionParameterHandler {\n constructor() {\n this.stacks = [];\n }\n\n enter(flags) {\n this.stacks.push(flags);\n }\n\n exit() {\n this.stacks.pop();\n }\n\n currentFlags() {\n return this.stacks[this.stacks.length - 1];\n }\n\n get hasAwait() {\n return (this.currentFlags() & PARAM_AWAIT) > 0;\n }\n\n get hasYield() {\n return (this.currentFlags() & PARAM_YIELD) > 0;\n }\n\n get hasReturn() {\n return (this.currentFlags() & PARAM_RETURN) > 0;\n }\n\n get hasIn() {\n return (this.currentFlags() & PARAM_IN) > 0;\n }\n\n}\nfunction functionFlags(isAsync, isGenerator) {\n return (isAsync ? PARAM_AWAIT : 0) | (isGenerator ? PARAM_YIELD : 0);\n}\n\nclass UtilParser extends Tokenizer {\n addExtra(node, key, value, enumerable = true) {\n if (!node) return;\n const extra = node.extra = node.extra || {};\n\n if (enumerable) {\n extra[key] = value;\n } else {\n Object.defineProperty(extra, key, {\n enumerable,\n value\n });\n }\n }\n\n isContextual(token) {\n return this.state.type === token && !this.state.containsEsc;\n }\n\n isUnparsedContextual(nameStart, name) {\n const nameEnd = nameStart + name.length;\n\n if (this.input.slice(nameStart, nameEnd) === name) {\n const nextCh = this.input.charCodeAt(nameEnd);\n return !(isIdentifierChar(nextCh) || (nextCh & 0xfc00) === 0xd800);\n }\n\n return false;\n }\n\n isLookaheadContextual(name) {\n const next = this.nextTokenStart();\n return this.isUnparsedContextual(next, name);\n }\n\n eatContextual(token) {\n if (this.isContextual(token)) {\n this.next();\n return true;\n }\n\n return false;\n }\n\n expectContextual(token, template) {\n if (!this.eatContextual(token)) {\n if (template != null) {\n throw this.raise(template, {\n at: this.state.startLoc\n });\n }\n\n throw this.unexpected(null, token);\n }\n }\n\n canInsertSemicolon() {\n return this.match(131) || this.match(8) || this.hasPrecedingLineBreak();\n }\n\n hasPrecedingLineBreak() {\n return lineBreak.test(this.input.slice(indexes.get(this.state.lastTokEndLoc), this.state.start));\n }\n\n hasFollowingLineBreak() {\n skipWhiteSpaceToLineBreak.lastIndex = this.state.end;\n return skipWhiteSpaceToLineBreak.test(this.input);\n }\n\n isLineTerminator() {\n return this.eat(13) || this.canInsertSemicolon();\n }\n\n semicolon(allowAsi = true) {\n if (allowAsi ? this.isLineTerminator() : this.eat(13)) return;\n this.raise(ErrorMessages.MissingSemicolon, {\n at: this.state.lastTokEndLoc\n });\n }\n\n expect(type, loc) {\n this.eat(type) || this.unexpected(loc, type);\n }\n\n assertNoSpace(message = \"Unexpected space.\") {\n if (this.state.start > indexes.get(this.state.lastTokEndLoc)) {\n this.raise({\n code: ErrorCodes.SyntaxError,\n reasonCode: \"UnexpectedSpace\",\n template: message\n }, {\n at: this.state.lastTokEndLoc\n });\n }\n }\n\n unexpected(loc, type) {\n throw this.raise({\n code: ErrorCodes.SyntaxError,\n reasonCode: \"UnexpectedToken\",\n template: type != null ? `Unexpected token, expected \"${tokenLabelName(type)}\"` : \"Unexpected token\"\n }, {\n at: loc != null ? loc : this.state.startLoc\n });\n }\n\n getPluginNamesFromConfigs(pluginConfigs) {\n return pluginConfigs.map(c => {\n if (typeof c === \"string\") {\n return c;\n } else {\n return c[0];\n }\n });\n }\n\n expectPlugin(pluginConfig, loc) {\n if (!this.hasPlugin(pluginConfig)) {\n throw this.raiseWithData(loc != null ? loc : this.state.startLoc, {\n missingPlugin: this.getPluginNamesFromConfigs([pluginConfig])\n }, `This experimental syntax requires enabling the parser plugin: ${JSON.stringify(pluginConfig)}.`);\n }\n\n return true;\n }\n\n expectOnePlugin(pluginConfigs) {\n if (!pluginConfigs.some(c => this.hasPlugin(c))) {\n throw this.raiseWithData(this.state.startLoc, {\n missingPlugin: this.getPluginNamesFromConfigs(pluginConfigs)\n }, `This experimental syntax requires enabling one of the following parser plugin(s): ${pluginConfigs.map(c => JSON.stringify(c)).join(\", \")}.`);\n }\n }\n\n tryParse(fn, oldState = this.state.clone()) {\n const abortSignal = {\n node: null\n };\n\n try {\n const node = fn((node = null) => {\n abortSignal.node = node;\n throw abortSignal;\n });\n\n if (this.state.errors.length > oldState.errors.length) {\n const failState = this.state;\n this.state = oldState;\n this.state.tokensLength = failState.tokensLength;\n return {\n node,\n error: failState.errors[oldState.errors.length],\n thrown: false,\n aborted: false,\n failState\n };\n }\n\n return {\n node,\n error: null,\n thrown: false,\n aborted: false,\n failState: null\n };\n } catch (error) {\n const failState = this.state;\n this.state = oldState;\n\n if (error instanceof SyntaxError) {\n return {\n node: null,\n error,\n thrown: true,\n aborted: false,\n failState\n };\n }\n\n if (error === abortSignal) {\n return {\n node: abortSignal.node,\n error: null,\n thrown: false,\n aborted: true,\n failState\n };\n }\n\n throw error;\n }\n }\n\n checkExpressionErrors(refExpressionErrors, andThrow) {\n if (!refExpressionErrors) return false;\n const {\n shorthandAssignLoc,\n doubleProtoLoc,\n optionalParametersLoc\n } = refExpressionErrors;\n const hasErrors = !!shorthandAssignLoc || !!doubleProtoLoc || !!optionalParametersLoc;\n\n if (!andThrow) {\n return hasErrors;\n }\n\n if (shorthandAssignLoc != null) {\n this.raise(ErrorMessages.InvalidCoverInitializedName, {\n at: shorthandAssignLoc\n });\n }\n\n if (doubleProtoLoc != null) {\n this.raise(ErrorMessages.DuplicateProto, {\n at: doubleProtoLoc\n });\n }\n\n if (optionalParametersLoc != null) {\n this.unexpected(optionalParametersLoc);\n }\n }\n\n isLiteralPropertyName() {\n return tokenIsLiteralPropertyName(this.state.type);\n }\n\n isPrivateName(node) {\n return node.type === \"PrivateName\";\n }\n\n getPrivateNameSV(node) {\n return node.id.name;\n }\n\n hasPropertyAsPrivateName(node) {\n return (node.type === \"MemberExpression\" || node.type === \"OptionalMemberExpression\") && this.isPrivateName(node.property);\n }\n\n isOptionalChain(node) {\n return node.type === \"OptionalMemberExpression\" || node.type === \"OptionalCallExpression\";\n }\n\n isObjectProperty(node) {\n return node.type === \"ObjectProperty\";\n }\n\n isObjectMethod(node) {\n return node.type === \"ObjectMethod\";\n }\n\n initializeScopes(inModule = this.options.sourceType === \"module\") {\n const oldLabels = this.state.labels;\n this.state.labels = [];\n const oldExportedIdentifiers = this.exportedIdentifiers;\n this.exportedIdentifiers = new Set();\n const oldInModule = this.inModule;\n this.inModule = inModule;\n const oldScope = this.scope;\n const ScopeHandler = this.getScopeHandler();\n this.scope = new ScopeHandler(this.raise.bind(this), this.inModule);\n const oldProdParam = this.prodParam;\n this.prodParam = new ProductionParameterHandler();\n const oldClassScope = this.classScope;\n this.classScope = new ClassScopeHandler(this.raise.bind(this));\n const oldExpressionScope = this.expressionScope;\n this.expressionScope = new ExpressionScopeHandler(this.raise.bind(this));\n return () => {\n this.state.labels = oldLabels;\n this.exportedIdentifiers = oldExportedIdentifiers;\n this.inModule = oldInModule;\n this.scope = oldScope;\n this.prodParam = oldProdParam;\n this.classScope = oldClassScope;\n this.expressionScope = oldExpressionScope;\n };\n }\n\n enterInitialScopes() {\n let paramFlags = PARAM;\n\n if (this.inModule) {\n paramFlags |= PARAM_AWAIT;\n }\n\n this.scope.enter(SCOPE_PROGRAM);\n this.prodParam.enter(paramFlags);\n }\n\n}\nclass ExpressionErrors {\n constructor() {\n this.shorthandAssignLoc = null;\n this.doubleProtoLoc = null;\n this.optionalParametersLoc = null;\n }\n\n}\n\nclass Node {\n constructor(parser, pos, loc) {\n this.type = \"\";\n this.start = pos;\n this.end = 0;\n this.loc = new SourceLocation(loc);\n if (parser != null && parser.options.ranges) this.range = [pos, 0];\n if (parser != null && parser.filename) this.loc.filename = parser.filename;\n }\n\n}\n\nconst NodePrototype = Node.prototype;\n{\n NodePrototype.__clone = function () {\n const newNode = new Node();\n const keys = Object.keys(this);\n\n for (let i = 0, length = keys.length; i < length; i++) {\n const key = keys[i];\n\n if (key !== \"leadingComments\" && key !== \"trailingComments\" && key !== \"innerComments\") {\n newNode[key] = this[key];\n }\n }\n\n return newNode;\n };\n}\n\nfunction clonePlaceholder(node) {\n return cloneIdentifier(node);\n}\n\nfunction cloneIdentifier(node) {\n const {\n type,\n start,\n end,\n loc,\n range,\n extra,\n name\n } = node;\n const cloned = Object.create(NodePrototype);\n cloned.type = type;\n cloned.start = start;\n cloned.end = end;\n cloned.loc = loc;\n cloned.range = range;\n cloned.extra = extra;\n cloned.name = name;\n\n if (type === \"Placeholder\") {\n cloned.expectedNode = node.expectedNode;\n }\n\n return cloned;\n}\nfunction cloneStringLiteral(node) {\n const {\n type,\n start,\n end,\n loc,\n range,\n extra\n } = node;\n\n if (type === \"Placeholder\") {\n return clonePlaceholder(node);\n }\n\n const cloned = Object.create(NodePrototype);\n cloned.type = type;\n cloned.start = start;\n cloned.end = end;\n cloned.loc = loc;\n cloned.range = range;\n\n if (node.raw !== undefined) {\n cloned.raw = node.raw;\n } else {\n cloned.extra = extra;\n }\n\n cloned.value = node.value;\n return cloned;\n}\nclass NodeUtils extends UtilParser {\n startNode() {\n return new Node(this, this.state.start, this.state.startLoc);\n }\n\n startNodeAt(pos, loc) {\n return new Node(this, pos, loc);\n }\n\n startNodeAtNode(type) {\n return this.startNodeAt(type.start, type.loc.start);\n }\n\n finishNode(node, type) {\n return this.finishNodeAt(node, type, this.state.lastTokEndLoc);\n }\n\n finishNodeAt(node, type, endLoc) {\n\n node.type = type;\n node.end = indexes.get(endLoc);\n node.loc.end = endLoc;\n if (this.options.ranges) node.range[1] = node.end;\n if (this.options.attachComment) this.processComment(node);\n return node;\n }\n\n resetStartLocation(node, start, startLoc) {\n node.start = start;\n node.loc.start = startLoc;\n if (this.options.ranges) node.range[0] = start;\n }\n\n resetEndLocation(node, endLoc = this.state.lastTokEndLoc) {\n node.end = indexes.get(endLoc);\n node.loc.end = endLoc;\n if (this.options.ranges) node.range[1] = node.end;\n }\n\n resetStartLocationFromNode(node, locationNode) {\n this.resetStartLocation(node, locationNode.start, locationNode.loc.start);\n }\n\n}\n\nconst reservedTypes = new Set([\"_\", \"any\", \"bool\", \"boolean\", \"empty\", \"extends\", \"false\", \"interface\", \"mixed\", \"null\", \"number\", \"static\", \"string\", \"true\", \"typeof\", \"void\"]);\nconst FlowErrors = makeErrorTemplates({\n AmbiguousConditionalArrow: \"Ambiguous expression: wrap the arrow functions in parentheses to disambiguate.\",\n AmbiguousDeclareModuleKind: \"Found both `declare module.exports` and `declare export` in the same module. Modules can only have 1 since they are either an ES module or they are a CommonJS module.\",\n AssignReservedType: \"Cannot overwrite reserved type %0.\",\n DeclareClassElement: \"The `declare` modifier can only appear on class fields.\",\n DeclareClassFieldInitializer: \"Initializers are not allowed in fields with the `declare` modifier.\",\n DuplicateDeclareModuleExports: \"Duplicate `declare module.exports` statement.\",\n EnumBooleanMemberNotInitialized: \"Boolean enum members need to be initialized. Use either `%0 = true,` or `%0 = false,` in enum `%1`.\",\n EnumDuplicateMemberName: \"Enum member names need to be unique, but the name `%0` has already been used before in enum `%1`.\",\n EnumInconsistentMemberValues: \"Enum `%0` has inconsistent member initializers. Either use no initializers, or consistently use literals (either booleans, numbers, or strings) for all member initializers.\",\n EnumInvalidExplicitType: \"Enum type `%1` is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `%0`.\",\n EnumInvalidExplicitTypeUnknownSupplied: \"Supplied enum type is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `%0`.\",\n EnumInvalidMemberInitializerPrimaryType: \"Enum `%0` has type `%2`, so the initializer of `%1` needs to be a %2 literal.\",\n EnumInvalidMemberInitializerSymbolType: \"Symbol enum members cannot be initialized. Use `%1,` in enum `%0`.\",\n EnumInvalidMemberInitializerUnknownType: \"The enum member initializer for `%1` needs to be a literal (either a boolean, number, or string) in enum `%0`.\",\n EnumInvalidMemberName: \"Enum member names cannot start with lowercase 'a' through 'z'. Instead of using `%0`, consider using `%1`, in enum `%2`.\",\n EnumNumberMemberNotInitialized: \"Number enum members need to be initialized, e.g. `%1 = 1` in enum `%0`.\",\n EnumStringMemberInconsistentlyInitailized: \"String enum members need to consistently either all use initializers, or use no initializers, in enum `%0`.\",\n GetterMayNotHaveThisParam: \"A getter cannot have a `this` parameter.\",\n ImportTypeShorthandOnlyInPureImport: \"The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements.\",\n InexactInsideExact: \"Explicit inexact syntax cannot appear inside an explicit exact object type.\",\n InexactInsideNonObject: \"Explicit inexact syntax cannot appear in class or interface definitions.\",\n InexactVariance: \"Explicit inexact syntax cannot have variance.\",\n InvalidNonTypeImportInDeclareModule: \"Imports within a `declare module` body must always be `import type` or `import typeof`.\",\n MissingTypeParamDefault: \"Type parameter declaration needs a default, since a preceding type parameter declaration has a default.\",\n NestedDeclareModule: \"`declare module` cannot be used inside another `declare module`.\",\n NestedFlowComment: \"Cannot have a flow comment inside another flow comment.\",\n PatternIsOptional: \"A binding pattern parameter cannot be optional in an implementation signature.\",\n SetterMayNotHaveThisParam: \"A setter cannot have a `this` parameter.\",\n SpreadVariance: \"Spread properties cannot have variance.\",\n ThisParamAnnotationRequired: \"A type annotation is required for the `this` parameter.\",\n ThisParamBannedInConstructor: \"Constructors cannot have a `this` parameter; constructors don't bind `this` like other functions.\",\n ThisParamMayNotBeOptional: \"The `this` parameter cannot be optional.\",\n ThisParamMustBeFirst: \"The `this` parameter must be the first function parameter.\",\n ThisParamNoDefault: \"The `this` parameter may not have a default value.\",\n TypeBeforeInitializer: \"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.\",\n TypeCastInPattern: \"The type cast expression is expected to be wrapped with parenthesis.\",\n UnexpectedExplicitInexactInObject: \"Explicit inexact syntax must appear at the end of an inexact object.\",\n UnexpectedReservedType: \"Unexpected reserved type %0.\",\n UnexpectedReservedUnderscore: \"`_` is only allowed as a type argument to call or new.\",\n UnexpectedSpaceBetweenModuloChecks: \"Spaces between `%` and `checks` are not allowed here.\",\n UnexpectedSpreadType: \"Spread operator cannot appear in class or interface definitions.\",\n UnexpectedSubtractionOperand: 'Unexpected token, expected \"number\" or \"bigint\".',\n UnexpectedTokenAfterTypeParameter: \"Expected an arrow function after this type parameter declaration.\",\n UnexpectedTypeParameterBeforeAsyncArrowFunction: \"Type parameters must come after the async keyword, e.g. instead of ` async () => {}`, use `async () => {}`.\",\n UnsupportedDeclareExportKind: \"`declare export %0` is not supported. Use `%1` instead.\",\n UnsupportedStatementInDeclareModule: \"Only declares and type imports are allowed inside declare module.\",\n UnterminatedFlowComment: \"Unterminated flow-comment.\"\n}, ErrorCodes.SyntaxError, \"flow\");\n\nfunction isEsModuleType(bodyElement) {\n return bodyElement.type === \"DeclareExportAllDeclaration\" || bodyElement.type === \"DeclareExportDeclaration\" && (!bodyElement.declaration || bodyElement.declaration.type !== \"TypeAlias\" && bodyElement.declaration.type !== \"InterfaceDeclaration\");\n}\n\nfunction hasTypeImportKind(node) {\n return node.importKind === \"type\" || node.importKind === \"typeof\";\n}\n\nfunction isMaybeDefaultImport(type) {\n return tokenIsKeywordOrIdentifier(type) && type !== 93;\n}\n\nconst exportSuggestions = {\n const: \"declare export var\",\n let: \"declare export var\",\n type: \"export type\",\n interface: \"export interface\"\n};\n\nfunction partition(list, test) {\n const list1 = [];\n const list2 = [];\n\n for (let i = 0; i < list.length; i++) {\n (test(list[i], i, list) ? list1 : list2).push(list[i]);\n }\n\n return [list1, list2];\n}\n\nconst FLOW_PRAGMA_REGEX = /\\*?\\s*@((?:no)?flow)\\b/;\nvar flow = (superClass => class extends superClass {\n constructor(...args) {\n super(...args);\n this.flowPragma = undefined;\n }\n\n getScopeHandler() {\n return FlowScopeHandler;\n }\n\n shouldParseTypes() {\n return this.getPluginOption(\"flow\", \"all\") || this.flowPragma === \"flow\";\n }\n\n shouldParseEnums() {\n return !!this.getPluginOption(\"flow\", \"enums\");\n }\n\n finishToken(type, val) {\n if (type !== 125 && type !== 13 && type !== 28) {\n if (this.flowPragma === undefined) {\n this.flowPragma = null;\n }\n }\n\n return super.finishToken(type, val);\n }\n\n addComment(comment) {\n if (this.flowPragma === undefined) {\n const matches = FLOW_PRAGMA_REGEX.exec(comment.value);\n\n if (!matches) ; else if (matches[1] === \"flow\") {\n this.flowPragma = \"flow\";\n } else if (matches[1] === \"noflow\") {\n this.flowPragma = \"noflow\";\n } else {\n throw new Error(\"Unexpected flow pragma\");\n }\n }\n\n return super.addComment(comment);\n }\n\n flowParseTypeInitialiser(tok) {\n const oldInType = this.state.inType;\n this.state.inType = true;\n this.expect(tok || 14);\n const type = this.flowParseType();\n this.state.inType = oldInType;\n return type;\n }\n\n flowParsePredicate() {\n const node = this.startNode();\n const moduloLoc = this.state.startLoc;\n this.next();\n this.expectContextual(103);\n\n if (this.state.lastTokStart > indexes.get(moduloLoc) + 1) {\n this.raise(FlowErrors.UnexpectedSpaceBetweenModuloChecks, {\n at: moduloLoc\n });\n }\n\n if (this.eat(10)) {\n node.value = this.parseExpression();\n this.expect(11);\n return this.finishNode(node, \"DeclaredPredicate\");\n } else {\n return this.finishNode(node, \"InferredPredicate\");\n }\n }\n\n flowParseTypeAndPredicateInitialiser() {\n const oldInType = this.state.inType;\n this.state.inType = true;\n this.expect(14);\n let type = null;\n let predicate = null;\n\n if (this.match(50)) {\n this.state.inType = oldInType;\n predicate = this.flowParsePredicate();\n } else {\n type = this.flowParseType();\n this.state.inType = oldInType;\n\n if (this.match(50)) {\n predicate = this.flowParsePredicate();\n }\n }\n\n return [type, predicate];\n }\n\n flowParseDeclareClass(node) {\n this.next();\n this.flowParseInterfaceish(node, true);\n return this.finishNode(node, \"DeclareClass\");\n }\n\n flowParseDeclareFunction(node) {\n this.next();\n const id = node.id = this.parseIdentifier();\n const typeNode = this.startNode();\n const typeContainer = this.startNode();\n\n if (this.match(45)) {\n typeNode.typeParameters = this.flowParseTypeParameterDeclaration();\n } else {\n typeNode.typeParameters = null;\n }\n\n this.expect(10);\n const tmp = this.flowParseFunctionTypeParams();\n typeNode.params = tmp.params;\n typeNode.rest = tmp.rest;\n typeNode.this = tmp._this;\n this.expect(11);\n [typeNode.returnType, node.predicate] = this.flowParseTypeAndPredicateInitialiser();\n typeContainer.typeAnnotation = this.finishNode(typeNode, \"FunctionTypeAnnotation\");\n id.typeAnnotation = this.finishNode(typeContainer, \"TypeAnnotation\");\n this.resetEndLocation(id);\n this.semicolon();\n this.scope.declareName(node.id.name, BIND_FLOW_DECLARE_FN, node.id.loc.start);\n return this.finishNode(node, \"DeclareFunction\");\n }\n\n flowParseDeclare(node, insideModule) {\n if (this.match(76)) {\n return this.flowParseDeclareClass(node);\n } else if (this.match(64)) {\n return this.flowParseDeclareFunction(node);\n } else if (this.match(70)) {\n return this.flowParseDeclareVariable(node);\n } else if (this.eatContextual(119)) {\n if (this.match(16)) {\n return this.flowParseDeclareModuleExports(node);\n } else {\n if (insideModule) {\n this.raise(FlowErrors.NestedDeclareModule, {\n at: this.state.lastTokStartLoc\n });\n }\n\n return this.flowParseDeclareModule(node);\n }\n } else if (this.isContextual(122)) {\n return this.flowParseDeclareTypeAlias(node);\n } else if (this.isContextual(123)) {\n return this.flowParseDeclareOpaqueType(node);\n } else if (this.isContextual(121)) {\n return this.flowParseDeclareInterface(node);\n } else if (this.match(78)) {\n return this.flowParseDeclareExportDeclaration(node, insideModule);\n } else {\n throw this.unexpected();\n }\n }\n\n flowParseDeclareVariable(node) {\n this.next();\n node.id = this.flowParseTypeAnnotatableIdentifier(true);\n this.scope.declareName(node.id.name, BIND_VAR, node.id.loc.start);\n this.semicolon();\n return this.finishNode(node, \"DeclareVariable\");\n }\n\n flowParseDeclareModule(node) {\n this.scope.enter(SCOPE_OTHER);\n\n if (this.match(125)) {\n node.id = this.parseExprAtom();\n } else {\n node.id = this.parseIdentifier();\n }\n\n const bodyNode = node.body = this.startNode();\n const body = bodyNode.body = [];\n this.expect(5);\n\n while (!this.match(8)) {\n let bodyNode = this.startNode();\n\n if (this.match(79)) {\n this.next();\n\n if (!this.isContextual(122) && !this.match(83)) {\n this.raise(FlowErrors.InvalidNonTypeImportInDeclareModule, {\n at: this.state.lastTokStartLoc\n });\n }\n\n this.parseImport(bodyNode);\n } else {\n this.expectContextual(117, FlowErrors.UnsupportedStatementInDeclareModule);\n bodyNode = this.flowParseDeclare(bodyNode, true);\n }\n\n body.push(bodyNode);\n }\n\n this.scope.exit();\n this.expect(8);\n this.finishNode(bodyNode, \"BlockStatement\");\n let kind = null;\n let hasModuleExport = false;\n body.forEach(bodyElement => {\n if (isEsModuleType(bodyElement)) {\n if (kind === \"CommonJS\") {\n this.raise(FlowErrors.AmbiguousDeclareModuleKind, {\n node: bodyElement\n });\n }\n\n kind = \"ES\";\n } else if (bodyElement.type === \"DeclareModuleExports\") {\n if (hasModuleExport) {\n this.raise(FlowErrors.DuplicateDeclareModuleExports, {\n node: bodyElement\n });\n }\n\n if (kind === \"ES\") {\n this.raise(FlowErrors.AmbiguousDeclareModuleKind, {\n node: bodyElement\n });\n }\n\n kind = \"CommonJS\";\n hasModuleExport = true;\n }\n });\n node.kind = kind || \"CommonJS\";\n return this.finishNode(node, \"DeclareModule\");\n }\n\n flowParseDeclareExportDeclaration(node, insideModule) {\n this.expect(78);\n\n if (this.eat(61)) {\n if (this.match(64) || this.match(76)) {\n node.declaration = this.flowParseDeclare(this.startNode());\n } else {\n node.declaration = this.flowParseType();\n this.semicolon();\n }\n\n node.default = true;\n return this.finishNode(node, \"DeclareExportDeclaration\");\n } else {\n if (this.match(71) || this.isLet() || (this.isContextual(122) || this.isContextual(121)) && !insideModule) {\n const label = this.state.value;\n const suggestion = exportSuggestions[label];\n throw this.raise(FlowErrors.UnsupportedDeclareExportKind, {\n at: this.state.startLoc\n }, label, suggestion);\n }\n\n if (this.match(70) || this.match(64) || this.match(76) || this.isContextual(123)) {\n node.declaration = this.flowParseDeclare(this.startNode());\n node.default = false;\n return this.finishNode(node, \"DeclareExportDeclaration\");\n } else if (this.match(51) || this.match(5) || this.isContextual(121) || this.isContextual(122) || this.isContextual(123)) {\n node = this.parseExport(node);\n\n if (node.type === \"ExportNamedDeclaration\") {\n node.type = \"ExportDeclaration\";\n node.default = false;\n delete node.exportKind;\n }\n\n node.type = \"Declare\" + node.type;\n return node;\n }\n }\n\n throw this.unexpected();\n }\n\n flowParseDeclareModuleExports(node) {\n this.next();\n this.expectContextual(104);\n node.typeAnnotation = this.flowParseTypeAnnotation();\n this.semicolon();\n return this.finishNode(node, \"DeclareModuleExports\");\n }\n\n flowParseDeclareTypeAlias(node) {\n this.next();\n this.flowParseTypeAlias(node);\n node.type = \"DeclareTypeAlias\";\n return node;\n }\n\n flowParseDeclareOpaqueType(node) {\n this.next();\n this.flowParseOpaqueType(node, true);\n node.type = \"DeclareOpaqueType\";\n return node;\n }\n\n flowParseDeclareInterface(node) {\n this.next();\n this.flowParseInterfaceish(node);\n return this.finishNode(node, \"DeclareInterface\");\n }\n\n flowParseInterfaceish(node, isClass = false) {\n node.id = this.flowParseRestrictedIdentifier(!isClass, true);\n this.scope.declareName(node.id.name, isClass ? BIND_FUNCTION : BIND_LEXICAL, node.id.loc.start);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n } else {\n node.typeParameters = null;\n }\n\n node.extends = [];\n node.implements = [];\n node.mixins = [];\n\n if (this.eat(77)) {\n do {\n node.extends.push(this.flowParseInterfaceExtends());\n } while (!isClass && this.eat(12));\n }\n\n if (this.isContextual(110)) {\n this.next();\n\n do {\n node.mixins.push(this.flowParseInterfaceExtends());\n } while (this.eat(12));\n }\n\n if (this.isContextual(106)) {\n this.next();\n\n do {\n node.implements.push(this.flowParseInterfaceExtends());\n } while (this.eat(12));\n }\n\n node.body = this.flowParseObjectType({\n allowStatic: isClass,\n allowExact: false,\n allowSpread: false,\n allowProto: isClass,\n allowInexact: false\n });\n }\n\n flowParseInterfaceExtends() {\n const node = this.startNode();\n node.id = this.flowParseQualifiedTypeIdentifier();\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterInstantiation();\n } else {\n node.typeParameters = null;\n }\n\n return this.finishNode(node, \"InterfaceExtends\");\n }\n\n flowParseInterface(node) {\n this.flowParseInterfaceish(node);\n return this.finishNode(node, \"InterfaceDeclaration\");\n }\n\n checkNotUnderscore(word) {\n if (word === \"_\") {\n this.raise(FlowErrors.UnexpectedReservedUnderscore, {\n at: this.state.startLoc\n });\n }\n }\n\n checkReservedType(word, startLoc, declaration) {\n if (!reservedTypes.has(word)) return;\n this.raise(declaration ? FlowErrors.AssignReservedType : FlowErrors.UnexpectedReservedType, {\n at: startLoc\n }, word);\n }\n\n flowParseRestrictedIdentifier(liberal, declaration) {\n this.checkReservedType(this.state.value, this.state.startLoc, declaration);\n return this.parseIdentifier(liberal);\n }\n\n flowParseTypeAlias(node) {\n node.id = this.flowParseRestrictedIdentifier(false, true);\n this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.loc.start);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n } else {\n node.typeParameters = null;\n }\n\n node.right = this.flowParseTypeInitialiser(29);\n this.semicolon();\n return this.finishNode(node, \"TypeAlias\");\n }\n\n flowParseOpaqueType(node, declare) {\n this.expectContextual(122);\n node.id = this.flowParseRestrictedIdentifier(true, true);\n this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.loc.start);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n } else {\n node.typeParameters = null;\n }\n\n node.supertype = null;\n\n if (this.match(14)) {\n node.supertype = this.flowParseTypeInitialiser(14);\n }\n\n node.impltype = null;\n\n if (!declare) {\n node.impltype = this.flowParseTypeInitialiser(29);\n }\n\n this.semicolon();\n return this.finishNode(node, \"OpaqueType\");\n }\n\n flowParseTypeParameter(requireDefault = false) {\n const nodeStartLoc = this.state.startLoc;\n const node = this.startNode();\n const variance = this.flowParseVariance();\n const ident = this.flowParseTypeAnnotatableIdentifier();\n node.name = ident.name;\n node.variance = variance;\n node.bound = ident.typeAnnotation;\n\n if (this.match(29)) {\n this.eat(29);\n node.default = this.flowParseType();\n } else {\n if (requireDefault) {\n this.raise(FlowErrors.MissingTypeParamDefault, {\n at: nodeStartLoc\n });\n }\n }\n\n return this.finishNode(node, \"TypeParameter\");\n }\n\n flowParseTypeParameterDeclaration() {\n const oldInType = this.state.inType;\n const node = this.startNode();\n node.params = [];\n this.state.inType = true;\n\n if (this.match(45) || this.match(134)) {\n this.next();\n } else {\n this.unexpected();\n }\n\n let defaultRequired = false;\n\n do {\n const typeParameter = this.flowParseTypeParameter(defaultRequired);\n node.params.push(typeParameter);\n\n if (typeParameter.default) {\n defaultRequired = true;\n }\n\n if (!this.match(46)) {\n this.expect(12);\n }\n } while (!this.match(46));\n\n this.expect(46);\n this.state.inType = oldInType;\n return this.finishNode(node, \"TypeParameterDeclaration\");\n }\n\n flowParseTypeParameterInstantiation() {\n const node = this.startNode();\n const oldInType = this.state.inType;\n node.params = [];\n this.state.inType = true;\n this.expect(45);\n const oldNoAnonFunctionType = this.state.noAnonFunctionType;\n this.state.noAnonFunctionType = false;\n\n while (!this.match(46)) {\n node.params.push(this.flowParseType());\n\n if (!this.match(46)) {\n this.expect(12);\n }\n }\n\n this.state.noAnonFunctionType = oldNoAnonFunctionType;\n this.expect(46);\n this.state.inType = oldInType;\n return this.finishNode(node, \"TypeParameterInstantiation\");\n }\n\n flowParseTypeParameterInstantiationCallOrNew() {\n const node = this.startNode();\n const oldInType = this.state.inType;\n node.params = [];\n this.state.inType = true;\n this.expect(45);\n\n while (!this.match(46)) {\n node.params.push(this.flowParseTypeOrImplicitInstantiation());\n\n if (!this.match(46)) {\n this.expect(12);\n }\n }\n\n this.expect(46);\n this.state.inType = oldInType;\n return this.finishNode(node, \"TypeParameterInstantiation\");\n }\n\n flowParseInterfaceType() {\n const node = this.startNode();\n this.expectContextual(121);\n node.extends = [];\n\n if (this.eat(77)) {\n do {\n node.extends.push(this.flowParseInterfaceExtends());\n } while (this.eat(12));\n }\n\n node.body = this.flowParseObjectType({\n allowStatic: false,\n allowExact: false,\n allowSpread: false,\n allowProto: false,\n allowInexact: false\n });\n return this.finishNode(node, \"InterfaceTypeAnnotation\");\n }\n\n flowParseObjectPropertyKey() {\n return this.match(126) || this.match(125) ? this.parseExprAtom() : this.parseIdentifier(true);\n }\n\n flowParseObjectTypeIndexer(node, isStatic, variance) {\n node.static = isStatic;\n\n if (this.lookahead().type === 14) {\n node.id = this.flowParseObjectPropertyKey();\n node.key = this.flowParseTypeInitialiser();\n } else {\n node.id = null;\n node.key = this.flowParseType();\n }\n\n this.expect(3);\n node.value = this.flowParseTypeInitialiser();\n node.variance = variance;\n return this.finishNode(node, \"ObjectTypeIndexer\");\n }\n\n flowParseObjectTypeInternalSlot(node, isStatic) {\n node.static = isStatic;\n node.id = this.flowParseObjectPropertyKey();\n this.expect(3);\n this.expect(3);\n\n if (this.match(45) || this.match(10)) {\n node.method = true;\n node.optional = false;\n node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(node.start, node.loc.start));\n } else {\n node.method = false;\n\n if (this.eat(17)) {\n node.optional = true;\n }\n\n node.value = this.flowParseTypeInitialiser();\n }\n\n return this.finishNode(node, \"ObjectTypeInternalSlot\");\n }\n\n flowParseObjectTypeMethodish(node) {\n node.params = [];\n node.rest = null;\n node.typeParameters = null;\n node.this = null;\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n }\n\n this.expect(10);\n\n if (this.match(74)) {\n node.this = this.flowParseFunctionTypeParam(true);\n node.this.name = null;\n\n if (!this.match(11)) {\n this.expect(12);\n }\n }\n\n while (!this.match(11) && !this.match(21)) {\n node.params.push(this.flowParseFunctionTypeParam(false));\n\n if (!this.match(11)) {\n this.expect(12);\n }\n }\n\n if (this.eat(21)) {\n node.rest = this.flowParseFunctionTypeParam(false);\n }\n\n this.expect(11);\n node.returnType = this.flowParseTypeInitialiser();\n return this.finishNode(node, \"FunctionTypeAnnotation\");\n }\n\n flowParseObjectTypeCallProperty(node, isStatic) {\n const valueNode = this.startNode();\n node.static = isStatic;\n node.value = this.flowParseObjectTypeMethodish(valueNode);\n return this.finishNode(node, \"ObjectTypeCallProperty\");\n }\n\n flowParseObjectType({\n allowStatic,\n allowExact,\n allowSpread,\n allowProto,\n allowInexact\n }) {\n const oldInType = this.state.inType;\n this.state.inType = true;\n const nodeStart = this.startNode();\n nodeStart.callProperties = [];\n nodeStart.properties = [];\n nodeStart.indexers = [];\n nodeStart.internalSlots = [];\n let endDelim;\n let exact;\n let inexact = false;\n\n if (allowExact && this.match(6)) {\n this.expect(6);\n endDelim = 9;\n exact = true;\n } else {\n this.expect(5);\n endDelim = 8;\n exact = false;\n }\n\n nodeStart.exact = exact;\n\n while (!this.match(endDelim)) {\n let isStatic = false;\n let protoStartLoc = null;\n let inexactStartLoc = null;\n const node = this.startNode();\n\n if (allowProto && this.isContextual(111)) {\n const lookahead = this.lookahead();\n\n if (lookahead.type !== 14 && lookahead.type !== 17) {\n this.next();\n protoStartLoc = this.state.startLoc;\n allowStatic = false;\n }\n }\n\n if (allowStatic && this.isContextual(100)) {\n const lookahead = this.lookahead();\n\n if (lookahead.type !== 14 && lookahead.type !== 17) {\n this.next();\n isStatic = true;\n }\n }\n\n const variance = this.flowParseVariance();\n\n if (this.eat(0)) {\n if (protoStartLoc != null) {\n this.unexpected(protoStartLoc);\n }\n\n if (this.eat(0)) {\n if (variance) {\n this.unexpected(variance.loc.start);\n }\n\n nodeStart.internalSlots.push(this.flowParseObjectTypeInternalSlot(node, isStatic));\n } else {\n nodeStart.indexers.push(this.flowParseObjectTypeIndexer(node, isStatic, variance));\n }\n } else if (this.match(10) || this.match(45)) {\n if (protoStartLoc != null) {\n this.unexpected(protoStartLoc);\n }\n\n if (variance) {\n this.unexpected(variance.loc.start);\n }\n\n nodeStart.callProperties.push(this.flowParseObjectTypeCallProperty(node, isStatic));\n } else {\n let kind = \"init\";\n\n if (this.isContextual(94) || this.isContextual(99)) {\n const lookahead = this.lookahead();\n\n if (tokenIsLiteralPropertyName(lookahead.type)) {\n kind = this.state.value;\n this.next();\n }\n }\n\n const propOrInexact = this.flowParseObjectTypeProperty(node, isStatic, protoStartLoc, variance, kind, allowSpread, allowInexact != null ? allowInexact : !exact);\n\n if (propOrInexact === null) {\n inexact = true;\n inexactStartLoc = this.state.lastTokStartLoc;\n } else {\n nodeStart.properties.push(propOrInexact);\n }\n }\n\n this.flowObjectTypeSemicolon();\n\n if (inexactStartLoc && !this.match(8) && !this.match(9)) {\n this.raise(FlowErrors.UnexpectedExplicitInexactInObject, {\n at: inexactStartLoc\n });\n }\n }\n\n this.expect(endDelim);\n\n if (allowSpread) {\n nodeStart.inexact = inexact;\n }\n\n const out = this.finishNode(nodeStart, \"ObjectTypeAnnotation\");\n this.state.inType = oldInType;\n return out;\n }\n\n flowParseObjectTypeProperty(node, isStatic, protoStartLoc, variance, kind, allowSpread, allowInexact) {\n if (this.eat(21)) {\n const isInexactToken = this.match(12) || this.match(13) || this.match(8) || this.match(9);\n\n if (isInexactToken) {\n if (!allowSpread) {\n this.raise(FlowErrors.InexactInsideNonObject, {\n at: this.state.lastTokStartLoc\n });\n } else if (!allowInexact) {\n this.raise(FlowErrors.InexactInsideExact, {\n at: this.state.lastTokStartLoc\n });\n }\n\n if (variance) {\n this.raise(FlowErrors.InexactVariance, {\n node: variance\n });\n }\n\n return null;\n }\n\n if (!allowSpread) {\n this.raise(FlowErrors.UnexpectedSpreadType, {\n at: this.state.lastTokStartLoc\n });\n }\n\n if (protoStartLoc != null) {\n this.unexpected(protoStartLoc);\n }\n\n if (variance) {\n this.raise(FlowErrors.SpreadVariance, {\n node: variance\n });\n }\n\n node.argument = this.flowParseType();\n return this.finishNode(node, \"ObjectTypeSpreadProperty\");\n } else {\n node.key = this.flowParseObjectPropertyKey();\n node.static = isStatic;\n node.proto = protoStartLoc != null;\n node.kind = kind;\n let optional = false;\n\n if (this.match(45) || this.match(10)) {\n node.method = true;\n\n if (protoStartLoc != null) {\n this.unexpected(protoStartLoc);\n }\n\n if (variance) {\n this.unexpected(variance.loc.start);\n }\n\n node.value = this.flowParseObjectTypeMethodish(this.startNodeAt(node.start, node.loc.start));\n\n if (kind === \"get\" || kind === \"set\") {\n this.flowCheckGetterSetterParams(node);\n }\n\n if (!allowSpread && node.key.name === \"constructor\" && node.value.this) {\n this.raise(FlowErrors.ThisParamBannedInConstructor, {\n node: node.value.this\n });\n }\n } else {\n if (kind !== \"init\") this.unexpected();\n node.method = false;\n\n if (this.eat(17)) {\n optional = true;\n }\n\n node.value = this.flowParseTypeInitialiser();\n node.variance = variance;\n }\n\n node.optional = optional;\n return this.finishNode(node, \"ObjectTypeProperty\");\n }\n }\n\n flowCheckGetterSetterParams(property) {\n const paramCount = property.kind === \"get\" ? 0 : 1;\n const length = property.value.params.length + (property.value.rest ? 1 : 0);\n\n if (property.value.this) {\n this.raise(property.kind === \"get\" ? FlowErrors.GetterMayNotHaveThisParam : FlowErrors.SetterMayNotHaveThisParam, {\n node: property.value.this\n });\n }\n\n if (length !== paramCount) {\n this.raise(property.kind === \"get\" ? ErrorMessages.BadGetterArity : ErrorMessages.BadSetterArity, {\n node: property\n });\n }\n\n if (property.kind === \"set\" && property.value.rest) {\n this.raise(ErrorMessages.BadSetterRestParameter, {\n node: property\n });\n }\n }\n\n flowObjectTypeSemicolon() {\n if (!this.eat(13) && !this.eat(12) && !this.match(8) && !this.match(9)) {\n this.unexpected();\n }\n }\n\n flowParseQualifiedTypeIdentifier(startPos, startLoc, id) {\n startPos = startPos || this.state.start;\n startLoc = startLoc || this.state.startLoc;\n let node = id || this.flowParseRestrictedIdentifier(true);\n\n while (this.eat(16)) {\n const node2 = this.startNodeAt(startPos, startLoc);\n node2.qualification = node;\n node2.id = this.flowParseRestrictedIdentifier(true);\n node = this.finishNode(node2, \"QualifiedTypeIdentifier\");\n }\n\n return node;\n }\n\n flowParseGenericType(startPos, startLoc, id) {\n const node = this.startNodeAt(startPos, startLoc);\n node.typeParameters = null;\n node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterInstantiation();\n }\n\n return this.finishNode(node, \"GenericTypeAnnotation\");\n }\n\n flowParseTypeofType() {\n const node = this.startNode();\n this.expect(83);\n node.argument = this.flowParsePrimaryType();\n return this.finishNode(node, \"TypeofTypeAnnotation\");\n }\n\n flowParseTupleType() {\n const node = this.startNode();\n node.types = [];\n this.expect(0);\n\n while (this.state.pos < this.length && !this.match(3)) {\n node.types.push(this.flowParseType());\n if (this.match(3)) break;\n this.expect(12);\n }\n\n this.expect(3);\n return this.finishNode(node, \"TupleTypeAnnotation\");\n }\n\n flowParseFunctionTypeParam(first) {\n let name = null;\n let optional = false;\n let typeAnnotation = null;\n const node = this.startNode();\n const lh = this.lookahead();\n const isThis = this.state.type === 74;\n\n if (lh.type === 14 || lh.type === 17) {\n if (isThis && !first) {\n this.raise(FlowErrors.ThisParamMustBeFirst, {\n node\n });\n }\n\n name = this.parseIdentifier(isThis);\n\n if (this.eat(17)) {\n optional = true;\n\n if (isThis) {\n this.raise(FlowErrors.ThisParamMayNotBeOptional, {\n node\n });\n }\n }\n\n typeAnnotation = this.flowParseTypeInitialiser();\n } else {\n typeAnnotation = this.flowParseType();\n }\n\n node.name = name;\n node.optional = optional;\n node.typeAnnotation = typeAnnotation;\n return this.finishNode(node, \"FunctionTypeParam\");\n }\n\n reinterpretTypeAsFunctionTypeParam(type) {\n const node = this.startNodeAt(type.start, type.loc.start);\n node.name = null;\n node.optional = false;\n node.typeAnnotation = type;\n return this.finishNode(node, \"FunctionTypeParam\");\n }\n\n flowParseFunctionTypeParams(params = []) {\n let rest = null;\n let _this = null;\n\n if (this.match(74)) {\n _this = this.flowParseFunctionTypeParam(true);\n _this.name = null;\n\n if (!this.match(11)) {\n this.expect(12);\n }\n }\n\n while (!this.match(11) && !this.match(21)) {\n params.push(this.flowParseFunctionTypeParam(false));\n\n if (!this.match(11)) {\n this.expect(12);\n }\n }\n\n if (this.eat(21)) {\n rest = this.flowParseFunctionTypeParam(false);\n }\n\n return {\n params,\n rest,\n _this\n };\n }\n\n flowIdentToTypeAnnotation(startPos, startLoc, node, id) {\n switch (id.name) {\n case \"any\":\n return this.finishNode(node, \"AnyTypeAnnotation\");\n\n case \"bool\":\n case \"boolean\":\n return this.finishNode(node, \"BooleanTypeAnnotation\");\n\n case \"mixed\":\n return this.finishNode(node, \"MixedTypeAnnotation\");\n\n case \"empty\":\n return this.finishNode(node, \"EmptyTypeAnnotation\");\n\n case \"number\":\n return this.finishNode(node, \"NumberTypeAnnotation\");\n\n case \"string\":\n return this.finishNode(node, \"StringTypeAnnotation\");\n\n case \"symbol\":\n return this.finishNode(node, \"SymbolTypeAnnotation\");\n\n default:\n this.checkNotUnderscore(id.name);\n return this.flowParseGenericType(startPos, startLoc, id);\n }\n }\n\n flowParsePrimaryType() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const node = this.startNode();\n let tmp;\n let type;\n let isGroupedType = false;\n const oldNoAnonFunctionType = this.state.noAnonFunctionType;\n\n switch (this.state.type) {\n case 5:\n return this.flowParseObjectType({\n allowStatic: false,\n allowExact: false,\n allowSpread: true,\n allowProto: false,\n allowInexact: true\n });\n\n case 6:\n return this.flowParseObjectType({\n allowStatic: false,\n allowExact: true,\n allowSpread: true,\n allowProto: false,\n allowInexact: false\n });\n\n case 0:\n this.state.noAnonFunctionType = false;\n type = this.flowParseTupleType();\n this.state.noAnonFunctionType = oldNoAnonFunctionType;\n return type;\n\n case 45:\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n this.expect(10);\n tmp = this.flowParseFunctionTypeParams();\n node.params = tmp.params;\n node.rest = tmp.rest;\n node.this = tmp._this;\n this.expect(11);\n this.expect(19);\n node.returnType = this.flowParseType();\n return this.finishNode(node, \"FunctionTypeAnnotation\");\n\n case 10:\n this.next();\n\n if (!this.match(11) && !this.match(21)) {\n if (tokenIsIdentifier(this.state.type) || this.match(74)) {\n const token = this.lookahead().type;\n isGroupedType = token !== 17 && token !== 14;\n } else {\n isGroupedType = true;\n }\n }\n\n if (isGroupedType) {\n this.state.noAnonFunctionType = false;\n type = this.flowParseType();\n this.state.noAnonFunctionType = oldNoAnonFunctionType;\n\n if (this.state.noAnonFunctionType || !(this.match(12) || this.match(11) && this.lookahead().type === 19)) {\n this.expect(11);\n return type;\n } else {\n this.eat(12);\n }\n }\n\n if (type) {\n tmp = this.flowParseFunctionTypeParams([this.reinterpretTypeAsFunctionTypeParam(type)]);\n } else {\n tmp = this.flowParseFunctionTypeParams();\n }\n\n node.params = tmp.params;\n node.rest = tmp.rest;\n node.this = tmp._this;\n this.expect(11);\n this.expect(19);\n node.returnType = this.flowParseType();\n node.typeParameters = null;\n return this.finishNode(node, \"FunctionTypeAnnotation\");\n\n case 125:\n return this.parseLiteral(this.state.value, \"StringLiteralTypeAnnotation\");\n\n case 81:\n case 82:\n node.value = this.match(81);\n this.next();\n return this.finishNode(node, \"BooleanLiteralTypeAnnotation\");\n\n case 49:\n if (this.state.value === \"-\") {\n this.next();\n\n if (this.match(126)) {\n return this.parseLiteralAtNode(-this.state.value, \"NumberLiteralTypeAnnotation\", node);\n }\n\n if (this.match(127)) {\n return this.parseLiteralAtNode(-this.state.value, \"BigIntLiteralTypeAnnotation\", node);\n }\n\n throw this.raise(FlowErrors.UnexpectedSubtractionOperand, {\n at: this.state.startLoc\n });\n }\n\n throw this.unexpected();\n\n case 126:\n return this.parseLiteral(this.state.value, \"NumberLiteralTypeAnnotation\");\n\n case 127:\n return this.parseLiteral(this.state.value, \"BigIntLiteralTypeAnnotation\");\n\n case 84:\n this.next();\n return this.finishNode(node, \"VoidTypeAnnotation\");\n\n case 80:\n this.next();\n return this.finishNode(node, \"NullLiteralTypeAnnotation\");\n\n case 74:\n this.next();\n return this.finishNode(node, \"ThisTypeAnnotation\");\n\n case 51:\n this.next();\n return this.finishNode(node, \"ExistsTypeAnnotation\");\n\n case 83:\n return this.flowParseTypeofType();\n\n default:\n if (tokenIsKeyword(this.state.type)) {\n const label = tokenLabelName(this.state.type);\n this.next();\n return super.createIdentifier(node, label);\n } else if (tokenIsIdentifier(this.state.type)) {\n if (this.isContextual(121)) {\n return this.flowParseInterfaceType();\n }\n\n return this.flowIdentToTypeAnnotation(startPos, startLoc, node, this.parseIdentifier());\n }\n\n }\n\n throw this.unexpected();\n }\n\n flowParsePostfixType() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let type = this.flowParsePrimaryType();\n let seenOptionalIndexedAccess = false;\n\n while ((this.match(0) || this.match(18)) && !this.canInsertSemicolon()) {\n const node = this.startNodeAt(startPos, startLoc);\n const optional = this.eat(18);\n seenOptionalIndexedAccess = seenOptionalIndexedAccess || optional;\n this.expect(0);\n\n if (!optional && this.match(3)) {\n node.elementType = type;\n this.next();\n type = this.finishNode(node, \"ArrayTypeAnnotation\");\n } else {\n node.objectType = type;\n node.indexType = this.flowParseType();\n this.expect(3);\n\n if (seenOptionalIndexedAccess) {\n node.optional = optional;\n type = this.finishNode(node, \"OptionalIndexedAccessType\");\n } else {\n type = this.finishNode(node, \"IndexedAccessType\");\n }\n }\n }\n\n return type;\n }\n\n flowParsePrefixType() {\n const node = this.startNode();\n\n if (this.eat(17)) {\n node.typeAnnotation = this.flowParsePrefixType();\n return this.finishNode(node, \"NullableTypeAnnotation\");\n } else {\n return this.flowParsePostfixType();\n }\n }\n\n flowParseAnonFunctionWithoutParens() {\n const param = this.flowParsePrefixType();\n\n if (!this.state.noAnonFunctionType && this.eat(19)) {\n const node = this.startNodeAt(param.start, param.loc.start);\n node.params = [this.reinterpretTypeAsFunctionTypeParam(param)];\n node.rest = null;\n node.this = null;\n node.returnType = this.flowParseType();\n node.typeParameters = null;\n return this.finishNode(node, \"FunctionTypeAnnotation\");\n }\n\n return param;\n }\n\n flowParseIntersectionType() {\n const node = this.startNode();\n this.eat(43);\n const type = this.flowParseAnonFunctionWithoutParens();\n node.types = [type];\n\n while (this.eat(43)) {\n node.types.push(this.flowParseAnonFunctionWithoutParens());\n }\n\n return node.types.length === 1 ? type : this.finishNode(node, \"IntersectionTypeAnnotation\");\n }\n\n flowParseUnionType() {\n const node = this.startNode();\n this.eat(41);\n const type = this.flowParseIntersectionType();\n node.types = [type];\n\n while (this.eat(41)) {\n node.types.push(this.flowParseIntersectionType());\n }\n\n return node.types.length === 1 ? type : this.finishNode(node, \"UnionTypeAnnotation\");\n }\n\n flowParseType() {\n const oldInType = this.state.inType;\n this.state.inType = true;\n const type = this.flowParseUnionType();\n this.state.inType = oldInType;\n return type;\n }\n\n flowParseTypeOrImplicitInstantiation() {\n if (this.state.type === 124 && this.state.value === \"_\") {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const node = this.parseIdentifier();\n return this.flowParseGenericType(startPos, startLoc, node);\n } else {\n return this.flowParseType();\n }\n }\n\n flowParseTypeAnnotation() {\n const node = this.startNode();\n node.typeAnnotation = this.flowParseTypeInitialiser();\n return this.finishNode(node, \"TypeAnnotation\");\n }\n\n flowParseTypeAnnotatableIdentifier(allowPrimitiveOverride) {\n const ident = allowPrimitiveOverride ? this.parseIdentifier() : this.flowParseRestrictedIdentifier();\n\n if (this.match(14)) {\n ident.typeAnnotation = this.flowParseTypeAnnotation();\n this.resetEndLocation(ident);\n }\n\n return ident;\n }\n\n typeCastToParameter(node) {\n node.expression.typeAnnotation = node.typeAnnotation;\n this.resetEndLocation(node.expression, node.typeAnnotation.loc.end);\n return node.expression;\n }\n\n flowParseVariance() {\n let variance = null;\n\n if (this.match(49)) {\n variance = this.startNode();\n\n if (this.state.value === \"+\") {\n variance.kind = \"plus\";\n } else {\n variance.kind = \"minus\";\n }\n\n this.next();\n this.finishNode(variance, \"Variance\");\n }\n\n return variance;\n }\n\n parseFunctionBody(node, allowExpressionBody, isMethod = false) {\n if (allowExpressionBody) {\n return this.forwardNoArrowParamsConversionAt(node, () => super.parseFunctionBody(node, true, isMethod));\n }\n\n return super.parseFunctionBody(node, false, isMethod);\n }\n\n parseFunctionBodyAndFinish(node, type, isMethod = false) {\n if (this.match(14)) {\n const typeNode = this.startNode();\n [typeNode.typeAnnotation, node.predicate] = this.flowParseTypeAndPredicateInitialiser();\n node.returnType = typeNode.typeAnnotation ? this.finishNode(typeNode, \"TypeAnnotation\") : null;\n }\n\n super.parseFunctionBodyAndFinish(node, type, isMethod);\n }\n\n parseStatement(context, topLevel) {\n if (this.state.strict && this.isContextual(121)) {\n const lookahead = this.lookahead();\n\n if (tokenIsKeywordOrIdentifier(lookahead.type)) {\n const node = this.startNode();\n this.next();\n return this.flowParseInterface(node);\n }\n } else if (this.shouldParseEnums() && this.isContextual(118)) {\n const node = this.startNode();\n this.next();\n return this.flowParseEnumDeclaration(node);\n }\n\n const stmt = super.parseStatement(context, topLevel);\n\n if (this.flowPragma === undefined && !this.isValidDirective(stmt)) {\n this.flowPragma = null;\n }\n\n return stmt;\n }\n\n parseExpressionStatement(node, expr) {\n if (expr.type === \"Identifier\") {\n if (expr.name === \"declare\") {\n if (this.match(76) || tokenIsIdentifier(this.state.type) || this.match(64) || this.match(70) || this.match(78)) {\n return this.flowParseDeclare(node);\n }\n } else if (tokenIsIdentifier(this.state.type)) {\n if (expr.name === \"interface\") {\n return this.flowParseInterface(node);\n } else if (expr.name === \"type\") {\n return this.flowParseTypeAlias(node);\n } else if (expr.name === \"opaque\") {\n return this.flowParseOpaqueType(node, false);\n }\n }\n }\n\n return super.parseExpressionStatement(node, expr);\n }\n\n shouldParseExportDeclaration() {\n const {\n type\n } = this.state;\n\n if (tokenIsFlowInterfaceOrTypeOrOpaque(type) || this.shouldParseEnums() && type === 118) {\n return !this.state.containsEsc;\n }\n\n return super.shouldParseExportDeclaration();\n }\n\n isExportDefaultSpecifier() {\n const {\n type\n } = this.state;\n\n if (tokenIsFlowInterfaceOrTypeOrOpaque(type) || this.shouldParseEnums() && type === 118) {\n return this.state.containsEsc;\n }\n\n return super.isExportDefaultSpecifier();\n }\n\n parseExportDefaultExpression() {\n if (this.shouldParseEnums() && this.isContextual(118)) {\n const node = this.startNode();\n this.next();\n return this.flowParseEnumDeclaration(node);\n }\n\n return super.parseExportDefaultExpression();\n }\n\n parseConditional(expr, startPos, startLoc, refExpressionErrors) {\n if (!this.match(17)) return expr;\n\n if (this.state.maybeInArrowParameters) {\n const nextCh = this.lookaheadCharCode();\n\n if (nextCh === 44 || nextCh === 61 || nextCh === 58 || nextCh === 41) {\n this.setOptionalParametersError(refExpressionErrors);\n return expr;\n }\n }\n\n this.expect(17);\n const state = this.state.clone();\n const originalNoArrowAt = this.state.noArrowAt;\n const node = this.startNodeAt(startPos, startLoc);\n let {\n consequent,\n failed\n } = this.tryParseConditionalConsequent();\n let [valid, invalid] = this.getArrowLikeExpressions(consequent);\n\n if (failed || invalid.length > 0) {\n const noArrowAt = [...originalNoArrowAt];\n\n if (invalid.length > 0) {\n this.state = state;\n this.state.noArrowAt = noArrowAt;\n\n for (let i = 0; i < invalid.length; i++) {\n noArrowAt.push(invalid[i].start);\n }\n\n ({\n consequent,\n failed\n } = this.tryParseConditionalConsequent());\n [valid, invalid] = this.getArrowLikeExpressions(consequent);\n }\n\n if (failed && valid.length > 1) {\n this.raise(FlowErrors.AmbiguousConditionalArrow, {\n at: state.startLoc\n });\n }\n\n if (failed && valid.length === 1) {\n this.state = state;\n noArrowAt.push(valid[0].start);\n this.state.noArrowAt = noArrowAt;\n ({\n consequent,\n failed\n } = this.tryParseConditionalConsequent());\n }\n }\n\n this.getArrowLikeExpressions(consequent, true);\n this.state.noArrowAt = originalNoArrowAt;\n this.expect(14);\n node.test = expr;\n node.consequent = consequent;\n node.alternate = this.forwardNoArrowParamsConversionAt(node, () => this.parseMaybeAssign(undefined, undefined));\n return this.finishNode(node, \"ConditionalExpression\");\n }\n\n tryParseConditionalConsequent() {\n this.state.noArrowParamsConversionAt.push(this.state.start);\n const consequent = this.parseMaybeAssignAllowIn();\n const failed = !this.match(14);\n this.state.noArrowParamsConversionAt.pop();\n return {\n consequent,\n failed\n };\n }\n\n getArrowLikeExpressions(node, disallowInvalid) {\n const stack = [node];\n const arrows = [];\n\n while (stack.length !== 0) {\n const node = stack.pop();\n\n if (node.type === \"ArrowFunctionExpression\") {\n if (node.typeParameters || !node.returnType) {\n this.finishArrowValidation(node);\n } else {\n arrows.push(node);\n }\n\n stack.push(node.body);\n } else if (node.type === \"ConditionalExpression\") {\n stack.push(node.consequent);\n stack.push(node.alternate);\n }\n }\n\n if (disallowInvalid) {\n arrows.forEach(node => this.finishArrowValidation(node));\n return [arrows, []];\n }\n\n return partition(arrows, node => node.params.every(param => this.isAssignable(param, true)));\n }\n\n finishArrowValidation(node) {\n var _node$extra;\n\n this.toAssignableList(node.params, (_node$extra = node.extra) == null ? void 0 : _node$extra.trailingCommaLoc, false);\n this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);\n super.checkParams(node, false, true);\n this.scope.exit();\n }\n\n forwardNoArrowParamsConversionAt(node, parse) {\n let result;\n\n if (this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {\n this.state.noArrowParamsConversionAt.push(this.state.start);\n result = parse();\n this.state.noArrowParamsConversionAt.pop();\n } else {\n result = parse();\n }\n\n return result;\n }\n\n parseParenItem(node, startPos, startLoc) {\n node = super.parseParenItem(node, startPos, startLoc);\n\n if (this.eat(17)) {\n node.optional = true;\n this.resetEndLocation(node);\n }\n\n if (this.match(14)) {\n const typeCastNode = this.startNodeAt(startPos, startLoc);\n typeCastNode.expression = node;\n typeCastNode.typeAnnotation = this.flowParseTypeAnnotation();\n return this.finishNode(typeCastNode, \"TypeCastExpression\");\n }\n\n return node;\n }\n\n assertModuleNodeAllowed(node) {\n if (node.type === \"ImportDeclaration\" && (node.importKind === \"type\" || node.importKind === \"typeof\") || node.type === \"ExportNamedDeclaration\" && node.exportKind === \"type\" || node.type === \"ExportAllDeclaration\" && node.exportKind === \"type\") {\n return;\n }\n\n super.assertModuleNodeAllowed(node);\n }\n\n parseExport(node) {\n const decl = super.parseExport(node);\n\n if (decl.type === \"ExportNamedDeclaration\" || decl.type === \"ExportAllDeclaration\") {\n decl.exportKind = decl.exportKind || \"value\";\n }\n\n return decl;\n }\n\n parseExportDeclaration(node) {\n if (this.isContextual(122)) {\n node.exportKind = \"type\";\n const declarationNode = this.startNode();\n this.next();\n\n if (this.match(5)) {\n node.specifiers = this.parseExportSpecifiers(true);\n this.parseExportFrom(node);\n return null;\n } else {\n return this.flowParseTypeAlias(declarationNode);\n }\n } else if (this.isContextual(123)) {\n node.exportKind = \"type\";\n const declarationNode = this.startNode();\n this.next();\n return this.flowParseOpaqueType(declarationNode, false);\n } else if (this.isContextual(121)) {\n node.exportKind = \"type\";\n const declarationNode = this.startNode();\n this.next();\n return this.flowParseInterface(declarationNode);\n } else if (this.shouldParseEnums() && this.isContextual(118)) {\n node.exportKind = \"value\";\n const declarationNode = this.startNode();\n this.next();\n return this.flowParseEnumDeclaration(declarationNode);\n } else {\n return super.parseExportDeclaration(node);\n }\n }\n\n eatExportStar(node) {\n if (super.eatExportStar(...arguments)) return true;\n\n if (this.isContextual(122) && this.lookahead().type === 51) {\n node.exportKind = \"type\";\n this.next();\n this.next();\n return true;\n }\n\n return false;\n }\n\n maybeParseExportNamespaceSpecifier(node) {\n const {\n startLoc\n } = this.state;\n const hasNamespace = super.maybeParseExportNamespaceSpecifier(node);\n\n if (hasNamespace && node.exportKind === \"type\") {\n this.unexpected(startLoc);\n }\n\n return hasNamespace;\n }\n\n parseClassId(node, isStatement, optionalId) {\n super.parseClassId(node, isStatement, optionalId);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n }\n }\n\n parseClassMember(classBody, member, state) {\n const {\n startLoc\n } = this.state;\n\n if (this.isContextual(117)) {\n if (this.parseClassMemberFromModifier(classBody, member)) {\n return;\n }\n\n member.declare = true;\n }\n\n super.parseClassMember(classBody, member, state);\n\n if (member.declare) {\n if (member.type !== \"ClassProperty\" && member.type !== \"ClassPrivateProperty\" && member.type !== \"PropertyDefinition\") {\n this.raise(FlowErrors.DeclareClassElement, {\n at: startLoc\n });\n } else if (member.value) {\n this.raise(FlowErrors.DeclareClassFieldInitializer, {\n node: member.value\n });\n }\n }\n }\n\n isIterator(word) {\n return word === \"iterator\" || word === \"asyncIterator\";\n }\n\n readIterator() {\n const word = super.readWord1();\n const fullWord = \"@@\" + word;\n\n if (!this.isIterator(word) || !this.state.inType) {\n this.raise(ErrorMessages.InvalidIdentifier, {\n at: this.state.curPosition()\n }, fullWord);\n }\n\n this.finishToken(124, fullWord);\n }\n\n getTokenFromCode(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (code === 123 && next === 124) {\n return this.finishOp(6, 2);\n } else if (this.state.inType && (code === 62 || code === 60)) {\n return this.finishOp(code === 62 ? 46 : 45, 1);\n } else if (this.state.inType && code === 63) {\n if (next === 46) {\n return this.finishOp(18, 2);\n }\n\n return this.finishOp(17, 1);\n } else if (isIteratorStart(code, next)) {\n this.state.pos += 2;\n return this.readIterator();\n } else {\n return super.getTokenFromCode(code);\n }\n }\n\n isAssignable(node, isBinding) {\n if (node.type === \"TypeCastExpression\") {\n return this.isAssignable(node.expression, isBinding);\n } else {\n return super.isAssignable(node, isBinding);\n }\n }\n\n toAssignable(node, isLHS = false) {\n if (node.type === \"TypeCastExpression\") {\n return super.toAssignable(this.typeCastToParameter(node), isLHS);\n } else {\n return super.toAssignable(node, isLHS);\n }\n }\n\n toAssignableList(exprList, trailingCommaLoc, isLHS) {\n for (let i = 0; i < exprList.length; i++) {\n const expr = exprList[i];\n\n if ((expr == null ? void 0 : expr.type) === \"TypeCastExpression\") {\n exprList[i] = this.typeCastToParameter(expr);\n }\n }\n\n return super.toAssignableList(exprList, trailingCommaLoc, isLHS);\n }\n\n toReferencedList(exprList, isParenthesizedExpr) {\n for (let i = 0; i < exprList.length; i++) {\n var _expr$extra;\n\n const expr = exprList[i];\n\n if (expr && expr.type === \"TypeCastExpression\" && !((_expr$extra = expr.extra) != null && _expr$extra.parenthesized) && (exprList.length > 1 || !isParenthesizedExpr)) {\n this.raise(FlowErrors.TypeCastInPattern, {\n node: expr.typeAnnotation\n });\n }\n }\n\n return exprList;\n }\n\n parseArrayLike(close, canBePattern, isTuple, refExpressionErrors) {\n const node = super.parseArrayLike(close, canBePattern, isTuple, refExpressionErrors);\n\n if (canBePattern && !this.state.maybeInArrowParameters) {\n this.toReferencedList(node.elements);\n }\n\n return node;\n }\n\n checkLVal(expr, ...args) {\n if (expr.type !== \"TypeCastExpression\") {\n return super.checkLVal(expr, ...args);\n }\n }\n\n parseClassProperty(node) {\n if (this.match(14)) {\n node.typeAnnotation = this.flowParseTypeAnnotation();\n }\n\n return super.parseClassProperty(node);\n }\n\n parseClassPrivateProperty(node) {\n if (this.match(14)) {\n node.typeAnnotation = this.flowParseTypeAnnotation();\n }\n\n return super.parseClassPrivateProperty(node);\n }\n\n isClassMethod() {\n return this.match(45) || super.isClassMethod();\n }\n\n isClassProperty() {\n return this.match(14) || super.isClassProperty();\n }\n\n isNonstaticConstructor(method) {\n return !this.match(14) && super.isNonstaticConstructor(method);\n }\n\n pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper) {\n if (method.variance) {\n this.unexpected(method.variance.loc.start);\n }\n\n delete method.variance;\n\n if (this.match(45)) {\n method.typeParameters = this.flowParseTypeParameterDeclaration();\n }\n\n super.pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper);\n\n if (method.params && isConstructor) {\n const params = method.params;\n\n if (params.length > 0 && this.isThisParam(params[0])) {\n this.raise(FlowErrors.ThisParamBannedInConstructor, {\n node: method\n });\n }\n } else if (method.type === \"MethodDefinition\" && isConstructor && method.value.params) {\n const params = method.value.params;\n\n if (params.length > 0 && this.isThisParam(params[0])) {\n this.raise(FlowErrors.ThisParamBannedInConstructor, {\n node: method\n });\n }\n }\n }\n\n pushClassPrivateMethod(classBody, method, isGenerator, isAsync) {\n if (method.variance) {\n this.unexpected(method.variance.loc.start);\n }\n\n delete method.variance;\n\n if (this.match(45)) {\n method.typeParameters = this.flowParseTypeParameterDeclaration();\n }\n\n super.pushClassPrivateMethod(classBody, method, isGenerator, isAsync);\n }\n\n parseClassSuper(node) {\n super.parseClassSuper(node);\n\n if (node.superClass && this.match(45)) {\n node.superTypeParameters = this.flowParseTypeParameterInstantiation();\n }\n\n if (this.isContextual(106)) {\n this.next();\n const implemented = node.implements = [];\n\n do {\n const node = this.startNode();\n node.id = this.flowParseRestrictedIdentifier(true);\n\n if (this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterInstantiation();\n } else {\n node.typeParameters = null;\n }\n\n implemented.push(this.finishNode(node, \"ClassImplements\"));\n } while (this.eat(12));\n }\n }\n\n checkGetterSetterParams(method) {\n super.checkGetterSetterParams(method);\n const params = this.getObjectOrClassMethodParams(method);\n\n if (params.length > 0) {\n const param = params[0];\n\n if (this.isThisParam(param) && method.kind === \"get\") {\n this.raise(FlowErrors.GetterMayNotHaveThisParam, {\n node: param\n });\n } else if (this.isThisParam(param)) {\n this.raise(FlowErrors.SetterMayNotHaveThisParam, {\n node: param\n });\n }\n }\n }\n\n parsePropertyNamePrefixOperator(node) {\n node.variance = this.flowParseVariance();\n }\n\n parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, isAccessor, refExpressionErrors) {\n if (prop.variance) {\n this.unexpected(prop.variance.loc.start);\n }\n\n delete prop.variance;\n let typeParameters;\n\n if (this.match(45) && !isAccessor) {\n typeParameters = this.flowParseTypeParameterDeclaration();\n if (!this.match(10)) this.unexpected();\n }\n\n super.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, isAccessor, refExpressionErrors);\n\n if (typeParameters) {\n (prop.value || prop).typeParameters = typeParameters;\n }\n }\n\n parseAssignableListItemTypes(param) {\n if (this.eat(17)) {\n if (param.type !== \"Identifier\") {\n this.raise(FlowErrors.PatternIsOptional, {\n node: param\n });\n }\n\n if (this.isThisParam(param)) {\n this.raise(FlowErrors.ThisParamMayNotBeOptional, {\n node: param\n });\n }\n\n param.optional = true;\n }\n\n if (this.match(14)) {\n param.typeAnnotation = this.flowParseTypeAnnotation();\n } else if (this.isThisParam(param)) {\n this.raise(FlowErrors.ThisParamAnnotationRequired, {\n node: param\n });\n }\n\n if (this.match(29) && this.isThisParam(param)) {\n this.raise(FlowErrors.ThisParamNoDefault, {\n node: param\n });\n }\n\n this.resetEndLocation(param);\n return param;\n }\n\n parseMaybeDefault(startPos, startLoc, left) {\n const node = super.parseMaybeDefault(startPos, startLoc, left);\n\n if (node.type === \"AssignmentPattern\" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) {\n this.raise(FlowErrors.TypeBeforeInitializer, {\n node: node.typeAnnotation\n });\n }\n\n return node;\n }\n\n shouldParseDefaultImport(node) {\n if (!hasTypeImportKind(node)) {\n return super.shouldParseDefaultImport(node);\n }\n\n return isMaybeDefaultImport(this.state.type);\n }\n\n parseImportSpecifierLocal(node, specifier, type, contextDescription) {\n specifier.local = hasTypeImportKind(node) ? this.flowParseRestrictedIdentifier(true, true) : this.parseIdentifier();\n this.checkLVal(specifier.local, contextDescription, BIND_LEXICAL);\n node.specifiers.push(this.finishNode(specifier, type));\n }\n\n maybeParseDefaultImportSpecifier(node) {\n node.importKind = \"value\";\n let kind = null;\n\n if (this.match(83)) {\n kind = \"typeof\";\n } else if (this.isContextual(122)) {\n kind = \"type\";\n }\n\n if (kind) {\n const lh = this.lookahead();\n const {\n type\n } = lh;\n\n if (kind === \"type\" && type === 51) {\n this.unexpected(null, lh.type);\n }\n\n if (isMaybeDefaultImport(type) || type === 5 || type === 51) {\n this.next();\n node.importKind = kind;\n }\n }\n\n return super.maybeParseDefaultImportSpecifier(node);\n }\n\n parseImportSpecifier(specifier, importedIsString, isInTypeOnlyImport, isMaybeTypeOnly) {\n const firstIdent = specifier.imported;\n let specifierTypeKind = null;\n\n if (firstIdent.type === \"Identifier\") {\n if (firstIdent.name === \"type\") {\n specifierTypeKind = \"type\";\n } else if (firstIdent.name === \"typeof\") {\n specifierTypeKind = \"typeof\";\n }\n }\n\n let isBinding = false;\n\n if (this.isContextual(89) && !this.isLookaheadContextual(\"as\")) {\n const as_ident = this.parseIdentifier(true);\n\n if (specifierTypeKind !== null && !tokenIsKeywordOrIdentifier(this.state.type)) {\n specifier.imported = as_ident;\n specifier.importKind = specifierTypeKind;\n specifier.local = cloneIdentifier(as_ident);\n } else {\n specifier.imported = firstIdent;\n specifier.importKind = null;\n specifier.local = this.parseIdentifier();\n }\n } else {\n if (specifierTypeKind !== null && tokenIsKeywordOrIdentifier(this.state.type)) {\n specifier.imported = this.parseIdentifier(true);\n specifier.importKind = specifierTypeKind;\n } else {\n if (importedIsString) {\n throw this.raise(ErrorMessages.ImportBindingIsString, {\n node: specifier\n }, firstIdent.value);\n }\n\n specifier.imported = firstIdent;\n specifier.importKind = null;\n }\n\n if (this.eatContextual(89)) {\n specifier.local = this.parseIdentifier();\n } else {\n isBinding = true;\n specifier.local = cloneIdentifier(specifier.imported);\n }\n }\n\n const specifierIsTypeImport = hasTypeImportKind(specifier);\n\n if (isInTypeOnlyImport && specifierIsTypeImport) {\n this.raise(FlowErrors.ImportTypeShorthandOnlyInPureImport, {\n node: specifier\n });\n }\n\n if (isInTypeOnlyImport || specifierIsTypeImport) {\n this.checkReservedType(specifier.local.name, specifier.local.loc.start, true);\n }\n\n if (isBinding && !isInTypeOnlyImport && !specifierIsTypeImport) {\n this.checkReservedWord(specifier.local.name, specifier.loc.start, true, true);\n }\n\n this.checkLVal(specifier.local, \"import specifier\", BIND_LEXICAL);\n return this.finishNode(specifier, \"ImportSpecifier\");\n }\n\n parseBindingAtom() {\n switch (this.state.type) {\n case 74:\n return this.parseIdentifier(true);\n\n default:\n return super.parseBindingAtom();\n }\n }\n\n parseFunctionParams(node, allowModifiers) {\n const kind = node.kind;\n\n if (kind !== \"get\" && kind !== \"set\" && this.match(45)) {\n node.typeParameters = this.flowParseTypeParameterDeclaration();\n }\n\n super.parseFunctionParams(node, allowModifiers);\n }\n\n parseVarId(decl, kind) {\n super.parseVarId(decl, kind);\n\n if (this.match(14)) {\n decl.id.typeAnnotation = this.flowParseTypeAnnotation();\n this.resetEndLocation(decl.id);\n }\n }\n\n parseAsyncArrowFromCallExpression(node, call) {\n if (this.match(14)) {\n const oldNoAnonFunctionType = this.state.noAnonFunctionType;\n this.state.noAnonFunctionType = true;\n node.returnType = this.flowParseTypeAnnotation();\n this.state.noAnonFunctionType = oldNoAnonFunctionType;\n }\n\n return super.parseAsyncArrowFromCallExpression(node, call);\n }\n\n shouldParseAsyncArrow() {\n return this.match(14) || super.shouldParseAsyncArrow();\n }\n\n parseMaybeAssign(refExpressionErrors, afterLeftParse) {\n var _jsx;\n\n let state = null;\n let jsx;\n\n if (this.hasPlugin(\"jsx\") && (this.match(134) || this.match(45))) {\n state = this.state.clone();\n jsx = this.tryParse(() => super.parseMaybeAssign(refExpressionErrors, afterLeftParse), state);\n if (!jsx.error) return jsx.node;\n const {\n context\n } = this.state;\n const currentContext = context[context.length - 1];\n\n if (currentContext === types.j_oTag || currentContext === types.j_expr) {\n context.pop();\n }\n }\n\n if ((_jsx = jsx) != null && _jsx.error || this.match(45)) {\n var _jsx2, _jsx3;\n\n state = state || this.state.clone();\n let typeParameters;\n const arrow = this.tryParse(abort => {\n var _arrowExpression$extr;\n\n typeParameters = this.flowParseTypeParameterDeclaration();\n const arrowExpression = this.forwardNoArrowParamsConversionAt(typeParameters, () => {\n const result = super.parseMaybeAssign(refExpressionErrors, afterLeftParse);\n this.resetStartLocationFromNode(result, typeParameters);\n return result;\n });\n if ((_arrowExpression$extr = arrowExpression.extra) != null && _arrowExpression$extr.parenthesized) abort();\n const expr = this.maybeUnwrapTypeCastExpression(arrowExpression);\n if (expr.type !== \"ArrowFunctionExpression\") abort();\n expr.typeParameters = typeParameters;\n this.resetStartLocationFromNode(expr, typeParameters);\n return arrowExpression;\n }, state);\n let arrowExpression = null;\n\n if (arrow.node && this.maybeUnwrapTypeCastExpression(arrow.node).type === \"ArrowFunctionExpression\") {\n if (!arrow.error && !arrow.aborted) {\n if (arrow.node.async) {\n this.raise(FlowErrors.UnexpectedTypeParameterBeforeAsyncArrowFunction, {\n node: typeParameters\n });\n }\n\n return arrow.node;\n }\n\n arrowExpression = arrow.node;\n }\n\n if ((_jsx2 = jsx) != null && _jsx2.node) {\n this.state = jsx.failState;\n return jsx.node;\n }\n\n if (arrowExpression) {\n this.state = arrow.failState;\n return arrowExpression;\n }\n\n if ((_jsx3 = jsx) != null && _jsx3.thrown) throw jsx.error;\n if (arrow.thrown) throw arrow.error;\n throw this.raise(FlowErrors.UnexpectedTokenAfterTypeParameter, {\n node: typeParameters\n });\n }\n\n return super.parseMaybeAssign(refExpressionErrors, afterLeftParse);\n }\n\n parseArrow(node) {\n if (this.match(14)) {\n const result = this.tryParse(() => {\n const oldNoAnonFunctionType = this.state.noAnonFunctionType;\n this.state.noAnonFunctionType = true;\n const typeNode = this.startNode();\n [typeNode.typeAnnotation, node.predicate] = this.flowParseTypeAndPredicateInitialiser();\n this.state.noAnonFunctionType = oldNoAnonFunctionType;\n if (this.canInsertSemicolon()) this.unexpected();\n if (!this.match(19)) this.unexpected();\n return typeNode;\n });\n if (result.thrown) return null;\n if (result.error) this.state = result.failState;\n node.returnType = result.node.typeAnnotation ? this.finishNode(result.node, \"TypeAnnotation\") : null;\n }\n\n return super.parseArrow(node);\n }\n\n shouldParseArrow(params) {\n return this.match(14) || super.shouldParseArrow(params);\n }\n\n setArrowFunctionParameters(node, params) {\n if (this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {\n node.params = params;\n } else {\n super.setArrowFunctionParameters(node, params);\n }\n }\n\n checkParams(node, allowDuplicates, isArrowFunction) {\n if (isArrowFunction && this.state.noArrowParamsConversionAt.indexOf(node.start) !== -1) {\n return;\n }\n\n for (let i = 0; i < node.params.length; i++) {\n if (this.isThisParam(node.params[i]) && i > 0) {\n this.raise(FlowErrors.ThisParamMustBeFirst, {\n node: node.params[i]\n });\n }\n }\n\n return super.checkParams(...arguments);\n }\n\n parseParenAndDistinguishExpression(canBeArrow) {\n return super.parseParenAndDistinguishExpression(canBeArrow && this.state.noArrowAt.indexOf(this.state.start) === -1);\n }\n\n parseSubscripts(base, startPos, startLoc, noCalls) {\n if (base.type === \"Identifier\" && base.name === \"async\" && this.state.noArrowAt.indexOf(startPos) !== -1) {\n this.next();\n const node = this.startNodeAt(startPos, startLoc);\n node.callee = base;\n node.arguments = this.parseCallExpressionArguments(11, false);\n base = this.finishNode(node, \"CallExpression\");\n } else if (base.type === \"Identifier\" && base.name === \"async\" && this.match(45)) {\n const state = this.state.clone();\n const arrow = this.tryParse(abort => this.parseAsyncArrowWithTypeParameters(startPos, startLoc) || abort(), state);\n if (!arrow.error && !arrow.aborted) return arrow.node;\n const result = this.tryParse(() => super.parseSubscripts(base, startPos, startLoc, noCalls), state);\n if (result.node && !result.error) return result.node;\n\n if (arrow.node) {\n this.state = arrow.failState;\n return arrow.node;\n }\n\n if (result.node) {\n this.state = result.failState;\n return result.node;\n }\n\n throw arrow.error || result.error;\n }\n\n return super.parseSubscripts(base, startPos, startLoc, noCalls);\n }\n\n parseSubscript(base, startPos, startLoc, noCalls, subscriptState) {\n if (this.match(18) && this.isLookaheadToken_lt()) {\n subscriptState.optionalChainMember = true;\n\n if (noCalls) {\n subscriptState.stop = true;\n return base;\n }\n\n this.next();\n const node = this.startNodeAt(startPos, startLoc);\n node.callee = base;\n node.typeArguments = this.flowParseTypeParameterInstantiation();\n this.expect(10);\n node.arguments = this.parseCallExpressionArguments(11, false);\n node.optional = true;\n return this.finishCallExpression(node, true);\n } else if (!noCalls && this.shouldParseTypes() && this.match(45)) {\n const node = this.startNodeAt(startPos, startLoc);\n node.callee = base;\n const result = this.tryParse(() => {\n node.typeArguments = this.flowParseTypeParameterInstantiationCallOrNew();\n this.expect(10);\n node.arguments = this.parseCallExpressionArguments(11, false);\n if (subscriptState.optionalChainMember) node.optional = false;\n return this.finishCallExpression(node, subscriptState.optionalChainMember);\n });\n\n if (result.node) {\n if (result.error) this.state = result.failState;\n return result.node;\n }\n }\n\n return super.parseSubscript(base, startPos, startLoc, noCalls, subscriptState);\n }\n\n parseNewArguments(node) {\n let targs = null;\n\n if (this.shouldParseTypes() && this.match(45)) {\n targs = this.tryParse(() => this.flowParseTypeParameterInstantiationCallOrNew()).node;\n }\n\n node.typeArguments = targs;\n super.parseNewArguments(node);\n }\n\n parseAsyncArrowWithTypeParameters(startPos, startLoc) {\n const node = this.startNodeAt(startPos, startLoc);\n this.parseFunctionParams(node);\n if (!this.parseArrow(node)) return;\n return this.parseArrowExpression(node, undefined, true);\n }\n\n readToken_mult_modulo(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (code === 42 && next === 47 && this.state.hasFlowComment) {\n this.state.hasFlowComment = false;\n this.state.pos += 2;\n this.nextToken();\n return;\n }\n\n super.readToken_mult_modulo(code);\n }\n\n readToken_pipe_amp(code) {\n const next = this.input.charCodeAt(this.state.pos + 1);\n\n if (code === 124 && next === 125) {\n this.finishOp(9, 2);\n return;\n }\n\n super.readToken_pipe_amp(code);\n }\n\n parseTopLevel(file, program) {\n const fileNode = super.parseTopLevel(file, program);\n\n if (this.state.hasFlowComment) {\n this.raise(FlowErrors.UnterminatedFlowComment, {\n at: this.state.curPosition()\n });\n }\n\n return fileNode;\n }\n\n skipBlockComment() {\n if (this.hasPlugin(\"flowComments\") && this.skipFlowComment()) {\n if (this.state.hasFlowComment) {\n throw this.raise(FlowErrors.NestedFlowComment, {\n at: this.state.startLoc\n });\n }\n\n this.hasFlowCommentCompletion();\n this.state.pos += this.skipFlowComment();\n this.state.hasFlowComment = true;\n return;\n }\n\n if (this.state.hasFlowComment) {\n const end = this.input.indexOf(\"*-/\", this.state.pos + 2);\n\n if (end === -1) {\n throw this.raise(ErrorMessages.UnterminatedComment, {\n at: this.state.curPosition()\n });\n }\n\n this.state.pos = end + 2 + 3;\n return;\n }\n\n return super.skipBlockComment();\n }\n\n skipFlowComment() {\n const {\n pos\n } = this.state;\n let shiftToFirstNonWhiteSpace = 2;\n\n while ([32, 9].includes(this.input.charCodeAt(pos + shiftToFirstNonWhiteSpace))) {\n shiftToFirstNonWhiteSpace++;\n }\n\n const ch2 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);\n const ch3 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos + 1);\n\n if (ch2 === 58 && ch3 === 58) {\n return shiftToFirstNonWhiteSpace + 2;\n }\n\n if (this.input.slice(shiftToFirstNonWhiteSpace + pos, shiftToFirstNonWhiteSpace + pos + 12) === \"flow-include\") {\n return shiftToFirstNonWhiteSpace + 12;\n }\n\n if (ch2 === 58 && ch3 !== 58) {\n return shiftToFirstNonWhiteSpace;\n }\n\n return false;\n }\n\n hasFlowCommentCompletion() {\n const end = this.input.indexOf(\"*/\", this.state.pos);\n\n if (end === -1) {\n throw this.raise(ErrorMessages.UnterminatedComment, {\n at: this.state.curPosition()\n });\n }\n }\n\n flowEnumErrorBooleanMemberNotInitialized(loc, {\n enumName,\n memberName\n }) {\n this.raise(FlowErrors.EnumBooleanMemberNotInitialized, {\n at: loc\n }, memberName, enumName);\n }\n\n flowEnumErrorInvalidExplicitType(loc, {\n enumName,\n suppliedType\n }) {\n return this.raise(suppliedType === null ? FlowErrors.EnumInvalidExplicitTypeUnknownSupplied : FlowErrors.EnumInvalidExplicitType, {\n at: loc\n }, enumName, suppliedType);\n }\n\n flowEnumErrorInvalidMemberInitializer(loc, {\n enumName,\n explicitType,\n memberName\n }) {\n return this.raise(explicitType === \"boolean\" || explicitType === \"number\" || explicitType === \"string\" ? FlowErrors.EnumInvalidMemberInitializerPrimaryType : explicitType === \"symbol\" ? FlowErrors.EnumInvalidMemberInitializerSymbolType : FlowErrors.EnumInvalidMemberInitializerUnknownType, {\n at: loc\n }, enumName, memberName, explicitType);\n }\n\n flowEnumErrorNumberMemberNotInitialized(loc, {\n enumName,\n memberName\n }) {\n this.raise(FlowErrors.EnumNumberMemberNotInitialized, {\n at: loc\n }, enumName, memberName);\n }\n\n flowEnumErrorStringMemberInconsistentlyInitailized(node, {\n enumName\n }) {\n this.raise(FlowErrors.EnumStringMemberInconsistentlyInitailized, {\n node\n }, enumName);\n }\n\n flowEnumMemberInit() {\n const startLoc = this.state.startLoc;\n\n const endOfInit = () => this.match(12) || this.match(8);\n\n switch (this.state.type) {\n case 126:\n {\n const literal = this.parseNumericLiteral(this.state.value);\n\n if (endOfInit()) {\n return {\n type: \"number\",\n loc: literal.loc.start,\n value: literal\n };\n }\n\n return {\n type: \"invalid\",\n loc: startLoc\n };\n }\n\n case 125:\n {\n const literal = this.parseStringLiteral(this.state.value);\n\n if (endOfInit()) {\n return {\n type: \"string\",\n loc: literal.loc.start,\n value: literal\n };\n }\n\n return {\n type: \"invalid\",\n loc: startLoc\n };\n }\n\n case 81:\n case 82:\n {\n const literal = this.parseBooleanLiteral(this.match(81));\n\n if (endOfInit()) {\n return {\n type: \"boolean\",\n loc: literal.loc.start,\n value: literal\n };\n }\n\n return {\n type: \"invalid\",\n loc: startLoc\n };\n }\n\n default:\n return {\n type: \"invalid\",\n loc: startLoc\n };\n }\n }\n\n flowEnumMemberRaw() {\n const loc = this.state.startLoc;\n const id = this.parseIdentifier(true);\n const init = this.eat(29) ? this.flowEnumMemberInit() : {\n type: \"none\",\n loc\n };\n return {\n id,\n init\n };\n }\n\n flowEnumCheckExplicitTypeMismatch(loc, context, expectedType) {\n const {\n explicitType\n } = context;\n\n if (explicitType === null) {\n return;\n }\n\n if (explicitType !== expectedType) {\n this.flowEnumErrorInvalidMemberInitializer(loc, context);\n }\n }\n\n flowEnumMembers({\n enumName,\n explicitType\n }) {\n const seenNames = new Set();\n const members = {\n booleanMembers: [],\n numberMembers: [],\n stringMembers: [],\n defaultedMembers: []\n };\n let hasUnknownMembers = false;\n\n while (!this.match(8)) {\n if (this.eat(21)) {\n hasUnknownMembers = true;\n break;\n }\n\n const memberNode = this.startNode();\n const {\n id,\n init\n } = this.flowEnumMemberRaw();\n const memberName = id.name;\n\n if (memberName === \"\") {\n continue;\n }\n\n if (/^[a-z]/.test(memberName)) {\n this.raise(FlowErrors.EnumInvalidMemberName, {\n node: id\n }, memberName, memberName[0].toUpperCase() + memberName.slice(1), enumName);\n }\n\n if (seenNames.has(memberName)) {\n this.raise(FlowErrors.EnumDuplicateMemberName, {\n node: id\n }, memberName, enumName);\n }\n\n seenNames.add(memberName);\n const context = {\n enumName,\n explicitType,\n memberName\n };\n memberNode.id = id;\n\n switch (init.type) {\n case \"boolean\":\n {\n this.flowEnumCheckExplicitTypeMismatch(init.loc, context, \"boolean\");\n memberNode.init = init.value;\n members.booleanMembers.push(this.finishNode(memberNode, \"EnumBooleanMember\"));\n break;\n }\n\n case \"number\":\n {\n this.flowEnumCheckExplicitTypeMismatch(init.loc, context, \"number\");\n memberNode.init = init.value;\n members.numberMembers.push(this.finishNode(memberNode, \"EnumNumberMember\"));\n break;\n }\n\n case \"string\":\n {\n this.flowEnumCheckExplicitTypeMismatch(init.loc, context, \"string\");\n memberNode.init = init.value;\n members.stringMembers.push(this.finishNode(memberNode, \"EnumStringMember\"));\n break;\n }\n\n case \"invalid\":\n {\n throw this.flowEnumErrorInvalidMemberInitializer(init.loc, context);\n }\n\n case \"none\":\n {\n switch (explicitType) {\n case \"boolean\":\n this.flowEnumErrorBooleanMemberNotInitialized(init.loc, context);\n break;\n\n case \"number\":\n this.flowEnumErrorNumberMemberNotInitialized(init.loc, context);\n break;\n\n default:\n members.defaultedMembers.push(this.finishNode(memberNode, \"EnumDefaultedMember\"));\n }\n }\n }\n\n if (!this.match(8)) {\n this.expect(12);\n }\n }\n\n return {\n members,\n hasUnknownMembers\n };\n }\n\n flowEnumStringMembers(initializedMembers, defaultedMembers, {\n enumName\n }) {\n if (initializedMembers.length === 0) {\n return defaultedMembers;\n } else if (defaultedMembers.length === 0) {\n return initializedMembers;\n } else if (defaultedMembers.length > initializedMembers.length) {\n for (const member of initializedMembers) {\n this.flowEnumErrorStringMemberInconsistentlyInitailized(member, {\n enumName\n });\n }\n\n return defaultedMembers;\n } else {\n for (const member of defaultedMembers) {\n this.flowEnumErrorStringMemberInconsistentlyInitailized(member, {\n enumName\n });\n }\n\n return initializedMembers;\n }\n }\n\n flowEnumParseExplicitType({\n enumName\n }) {\n if (this.eatContextual(97)) {\n if (!tokenIsIdentifier(this.state.type)) {\n throw this.flowEnumErrorInvalidExplicitType(this.state.startLoc, {\n enumName,\n suppliedType: null\n });\n }\n\n const {\n value\n } = this.state;\n this.next();\n\n if (value !== \"boolean\" && value !== \"number\" && value !== \"string\" && value !== \"symbol\") {\n this.flowEnumErrorInvalidExplicitType(this.state.startLoc, {\n enumName,\n suppliedType: value\n });\n }\n\n return value;\n }\n\n return null;\n }\n\n flowEnumBody(node, id) {\n const enumName = id.name;\n const nameLoc = id.loc.start;\n const explicitType = this.flowEnumParseExplicitType({\n enumName\n });\n this.expect(5);\n const {\n members,\n hasUnknownMembers\n } = this.flowEnumMembers({\n enumName,\n explicitType\n });\n node.hasUnknownMembers = hasUnknownMembers;\n\n switch (explicitType) {\n case \"boolean\":\n node.explicitType = true;\n node.members = members.booleanMembers;\n this.expect(8);\n return this.finishNode(node, \"EnumBooleanBody\");\n\n case \"number\":\n node.explicitType = true;\n node.members = members.numberMembers;\n this.expect(8);\n return this.finishNode(node, \"EnumNumberBody\");\n\n case \"string\":\n node.explicitType = true;\n node.members = this.flowEnumStringMembers(members.stringMembers, members.defaultedMembers, {\n enumName\n });\n this.expect(8);\n return this.finishNode(node, \"EnumStringBody\");\n\n case \"symbol\":\n node.members = members.defaultedMembers;\n this.expect(8);\n return this.finishNode(node, \"EnumSymbolBody\");\n\n default:\n {\n const empty = () => {\n node.members = [];\n this.expect(8);\n return this.finishNode(node, \"EnumStringBody\");\n };\n\n node.explicitType = false;\n const boolsLen = members.booleanMembers.length;\n const numsLen = members.numberMembers.length;\n const strsLen = members.stringMembers.length;\n const defaultedLen = members.defaultedMembers.length;\n\n if (!boolsLen && !numsLen && !strsLen && !defaultedLen) {\n return empty();\n } else if (!boolsLen && !numsLen) {\n node.members = this.flowEnumStringMembers(members.stringMembers, members.defaultedMembers, {\n enumName\n });\n this.expect(8);\n return this.finishNode(node, \"EnumStringBody\");\n } else if (!numsLen && !strsLen && boolsLen >= defaultedLen) {\n for (const member of members.defaultedMembers) {\n this.flowEnumErrorBooleanMemberNotInitialized(member.loc.start, {\n enumName,\n memberName: member.id.name\n });\n }\n\n node.members = members.booleanMembers;\n this.expect(8);\n return this.finishNode(node, \"EnumBooleanBody\");\n } else if (!boolsLen && !strsLen && numsLen >= defaultedLen) {\n for (const member of members.defaultedMembers) {\n this.flowEnumErrorNumberMemberNotInitialized(member.loc.start, {\n enumName,\n memberName: member.id.name\n });\n }\n\n node.members = members.numberMembers;\n this.expect(8);\n return this.finishNode(node, \"EnumNumberBody\");\n } else {\n this.raise(FlowErrors.EnumInconsistentMemberValues, {\n at: nameLoc\n }, enumName);\n return empty();\n }\n }\n }\n }\n\n flowParseEnumDeclaration(node) {\n const id = this.parseIdentifier();\n node.id = id;\n node.body = this.flowEnumBody(this.startNode(), id);\n return this.finishNode(node, \"EnumDeclaration\");\n }\n\n isLookaheadToken_lt() {\n const next = this.nextTokenStart();\n\n if (this.input.charCodeAt(next) === 60) {\n const afterNext = this.input.charCodeAt(next + 1);\n return afterNext !== 60 && afterNext !== 61;\n }\n\n return false;\n }\n\n maybeUnwrapTypeCastExpression(node) {\n return node.type === \"TypeCastExpression\" ? node.expression : node;\n }\n\n});\n\nconst entities = {\n quot: \"\\u0022\",\n amp: \"&\",\n apos: \"\\u0027\",\n lt: \"<\",\n gt: \">\",\n nbsp: \"\\u00A0\",\n iexcl: \"\\u00A1\",\n cent: \"\\u00A2\",\n pound: \"\\u00A3\",\n curren: \"\\u00A4\",\n yen: \"\\u00A5\",\n brvbar: \"\\u00A6\",\n sect: \"\\u00A7\",\n uml: \"\\u00A8\",\n copy: \"\\u00A9\",\n ordf: \"\\u00AA\",\n laquo: \"\\u00AB\",\n not: \"\\u00AC\",\n shy: \"\\u00AD\",\n reg: \"\\u00AE\",\n macr: \"\\u00AF\",\n deg: \"\\u00B0\",\n plusmn: \"\\u00B1\",\n sup2: \"\\u00B2\",\n sup3: \"\\u00B3\",\n acute: \"\\u00B4\",\n micro: \"\\u00B5\",\n para: \"\\u00B6\",\n middot: \"\\u00B7\",\n cedil: \"\\u00B8\",\n sup1: \"\\u00B9\",\n ordm: \"\\u00BA\",\n raquo: \"\\u00BB\",\n frac14: \"\\u00BC\",\n frac12: \"\\u00BD\",\n frac34: \"\\u00BE\",\n iquest: \"\\u00BF\",\n Agrave: \"\\u00C0\",\n Aacute: \"\\u00C1\",\n Acirc: \"\\u00C2\",\n Atilde: \"\\u00C3\",\n Auml: \"\\u00C4\",\n Aring: \"\\u00C5\",\n AElig: \"\\u00C6\",\n Ccedil: \"\\u00C7\",\n Egrave: \"\\u00C8\",\n Eacute: \"\\u00C9\",\n Ecirc: \"\\u00CA\",\n Euml: \"\\u00CB\",\n Igrave: \"\\u00CC\",\n Iacute: \"\\u00CD\",\n Icirc: \"\\u00CE\",\n Iuml: \"\\u00CF\",\n ETH: \"\\u00D0\",\n Ntilde: \"\\u00D1\",\n Ograve: \"\\u00D2\",\n Oacute: \"\\u00D3\",\n Ocirc: \"\\u00D4\",\n Otilde: \"\\u00D5\",\n Ouml: \"\\u00D6\",\n times: \"\\u00D7\",\n Oslash: \"\\u00D8\",\n Ugrave: \"\\u00D9\",\n Uacute: \"\\u00DA\",\n Ucirc: \"\\u00DB\",\n Uuml: \"\\u00DC\",\n Yacute: \"\\u00DD\",\n THORN: \"\\u00DE\",\n szlig: \"\\u00DF\",\n agrave: \"\\u00E0\",\n aacute: \"\\u00E1\",\n acirc: \"\\u00E2\",\n atilde: \"\\u00E3\",\n auml: \"\\u00E4\",\n aring: \"\\u00E5\",\n aelig: \"\\u00E6\",\n ccedil: \"\\u00E7\",\n egrave: \"\\u00E8\",\n eacute: \"\\u00E9\",\n ecirc: \"\\u00EA\",\n euml: \"\\u00EB\",\n igrave: \"\\u00EC\",\n iacute: \"\\u00ED\",\n icirc: \"\\u00EE\",\n iuml: \"\\u00EF\",\n eth: \"\\u00F0\",\n ntilde: \"\\u00F1\",\n ograve: \"\\u00F2\",\n oacute: \"\\u00F3\",\n ocirc: \"\\u00F4\",\n otilde: \"\\u00F5\",\n ouml: \"\\u00F6\",\n divide: \"\\u00F7\",\n oslash: \"\\u00F8\",\n ugrave: \"\\u00F9\",\n uacute: \"\\u00FA\",\n ucirc: \"\\u00FB\",\n uuml: \"\\u00FC\",\n yacute: \"\\u00FD\",\n thorn: \"\\u00FE\",\n yuml: \"\\u00FF\",\n OElig: \"\\u0152\",\n oelig: \"\\u0153\",\n Scaron: \"\\u0160\",\n scaron: \"\\u0161\",\n Yuml: \"\\u0178\",\n fnof: \"\\u0192\",\n circ: \"\\u02C6\",\n tilde: \"\\u02DC\",\n Alpha: \"\\u0391\",\n Beta: \"\\u0392\",\n Gamma: \"\\u0393\",\n Delta: \"\\u0394\",\n Epsilon: \"\\u0395\",\n Zeta: \"\\u0396\",\n Eta: \"\\u0397\",\n Theta: \"\\u0398\",\n Iota: \"\\u0399\",\n Kappa: \"\\u039A\",\n Lambda: \"\\u039B\",\n Mu: \"\\u039C\",\n Nu: \"\\u039D\",\n Xi: \"\\u039E\",\n Omicron: \"\\u039F\",\n Pi: \"\\u03A0\",\n Rho: \"\\u03A1\",\n Sigma: \"\\u03A3\",\n Tau: \"\\u03A4\",\n Upsilon: \"\\u03A5\",\n Phi: \"\\u03A6\",\n Chi: \"\\u03A7\",\n Psi: \"\\u03A8\",\n Omega: \"\\u03A9\",\n alpha: \"\\u03B1\",\n beta: \"\\u03B2\",\n gamma: \"\\u03B3\",\n delta: \"\\u03B4\",\n epsilon: \"\\u03B5\",\n zeta: \"\\u03B6\",\n eta: \"\\u03B7\",\n theta: \"\\u03B8\",\n iota: \"\\u03B9\",\n kappa: \"\\u03BA\",\n lambda: \"\\u03BB\",\n mu: \"\\u03BC\",\n nu: \"\\u03BD\",\n xi: \"\\u03BE\",\n omicron: \"\\u03BF\",\n pi: \"\\u03C0\",\n rho: \"\\u03C1\",\n sigmaf: \"\\u03C2\",\n sigma: \"\\u03C3\",\n tau: \"\\u03C4\",\n upsilon: \"\\u03C5\",\n phi: \"\\u03C6\",\n chi: \"\\u03C7\",\n psi: \"\\u03C8\",\n omega: \"\\u03C9\",\n thetasym: \"\\u03D1\",\n upsih: \"\\u03D2\",\n piv: \"\\u03D6\",\n ensp: \"\\u2002\",\n emsp: \"\\u2003\",\n thinsp: \"\\u2009\",\n zwnj: \"\\u200C\",\n zwj: \"\\u200D\",\n lrm: \"\\u200E\",\n rlm: \"\\u200F\",\n ndash: \"\\u2013\",\n mdash: \"\\u2014\",\n lsquo: \"\\u2018\",\n rsquo: \"\\u2019\",\n sbquo: \"\\u201A\",\n ldquo: \"\\u201C\",\n rdquo: \"\\u201D\",\n bdquo: \"\\u201E\",\n dagger: \"\\u2020\",\n Dagger: \"\\u2021\",\n bull: \"\\u2022\",\n hellip: \"\\u2026\",\n permil: \"\\u2030\",\n prime: \"\\u2032\",\n Prime: \"\\u2033\",\n lsaquo: \"\\u2039\",\n rsaquo: \"\\u203A\",\n oline: \"\\u203E\",\n frasl: \"\\u2044\",\n euro: \"\\u20AC\",\n image: \"\\u2111\",\n weierp: \"\\u2118\",\n real: \"\\u211C\",\n trade: \"\\u2122\",\n alefsym: \"\\u2135\",\n larr: \"\\u2190\",\n uarr: \"\\u2191\",\n rarr: \"\\u2192\",\n darr: \"\\u2193\",\n harr: \"\\u2194\",\n crarr: \"\\u21B5\",\n lArr: \"\\u21D0\",\n uArr: \"\\u21D1\",\n rArr: \"\\u21D2\",\n dArr: \"\\u21D3\",\n hArr: \"\\u21D4\",\n forall: \"\\u2200\",\n part: \"\\u2202\",\n exist: \"\\u2203\",\n empty: \"\\u2205\",\n nabla: \"\\u2207\",\n isin: \"\\u2208\",\n notin: \"\\u2209\",\n ni: \"\\u220B\",\n prod: \"\\u220F\",\n sum: \"\\u2211\",\n minus: \"\\u2212\",\n lowast: \"\\u2217\",\n radic: \"\\u221A\",\n prop: \"\\u221D\",\n infin: \"\\u221E\",\n ang: \"\\u2220\",\n and: \"\\u2227\",\n or: \"\\u2228\",\n cap: \"\\u2229\",\n cup: \"\\u222A\",\n int: \"\\u222B\",\n there4: \"\\u2234\",\n sim: \"\\u223C\",\n cong: \"\\u2245\",\n asymp: \"\\u2248\",\n ne: \"\\u2260\",\n equiv: \"\\u2261\",\n le: \"\\u2264\",\n ge: \"\\u2265\",\n sub: \"\\u2282\",\n sup: \"\\u2283\",\n nsub: \"\\u2284\",\n sube: \"\\u2286\",\n supe: \"\\u2287\",\n oplus: \"\\u2295\",\n otimes: \"\\u2297\",\n perp: \"\\u22A5\",\n sdot: \"\\u22C5\",\n lceil: \"\\u2308\",\n rceil: \"\\u2309\",\n lfloor: \"\\u230A\",\n rfloor: \"\\u230B\",\n lang: \"\\u2329\",\n rang: \"\\u232A\",\n loz: \"\\u25CA\",\n spades: \"\\u2660\",\n clubs: \"\\u2663\",\n hearts: \"\\u2665\",\n diams: \"\\u2666\"\n};\n\nconst HEX_NUMBER = /^[\\da-fA-F]+$/;\nconst DECIMAL_NUMBER = /^\\d+$/;\nconst JsxErrors = makeErrorTemplates({\n AttributeIsEmpty: \"JSX attributes must only be assigned a non-empty expression.\",\n MissingClosingTagElement: \"Expected corresponding JSX closing tag for <%0>.\",\n MissingClosingTagFragment: \"Expected corresponding JSX closing tag for <>.\",\n UnexpectedSequenceExpression: \"Sequence expressions cannot be directly nested inside JSX. Did you mean to wrap it in parentheses (...)?\",\n UnsupportedJsxValue: \"JSX value should be either an expression or a quoted JSX text.\",\n UnterminatedJsxContent: \"Unterminated JSX contents.\",\n UnwrappedAdjacentJSXElements: \"Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...?\"\n}, ErrorCodes.SyntaxError, \"jsx\");\n\nfunction isFragment(object) {\n return object ? object.type === \"JSXOpeningFragment\" || object.type === \"JSXClosingFragment\" : false;\n}\n\nfunction getQualifiedJSXName(object) {\n if (object.type === \"JSXIdentifier\") {\n return object.name;\n }\n\n if (object.type === \"JSXNamespacedName\") {\n return object.namespace.name + \":\" + object.name.name;\n }\n\n if (object.type === \"JSXMemberExpression\") {\n return getQualifiedJSXName(object.object) + \".\" + getQualifiedJSXName(object.property);\n }\n\n throw new Error(\"Node had unexpected type: \" + object.type);\n}\n\nvar jsx = (superClass => class extends superClass {\n jsxReadToken() {\n let out = \"\";\n let chunkStart = this.state.pos;\n\n for (;;) {\n if (this.state.pos >= this.length) {\n throw this.raise(JsxErrors.UnterminatedJsxContent, {\n at: this.state.startLoc\n });\n }\n\n const ch = this.input.charCodeAt(this.state.pos);\n\n switch (ch) {\n case 60:\n case 123:\n if (this.state.pos === this.state.start) {\n if (ch === 60 && this.state.canStartJSXElement) {\n ++this.state.pos;\n return this.finishToken(134);\n }\n\n return super.getTokenFromCode(ch);\n }\n\n out += this.input.slice(chunkStart, this.state.pos);\n return this.finishToken(133, out);\n\n case 38:\n out += this.input.slice(chunkStart, this.state.pos);\n out += this.jsxReadEntity();\n chunkStart = this.state.pos;\n break;\n\n case 62:\n case 125:\n\n default:\n if (isNewLine(ch)) {\n out += this.input.slice(chunkStart, this.state.pos);\n out += this.jsxReadNewLine(true);\n chunkStart = this.state.pos;\n } else {\n ++this.state.pos;\n }\n\n }\n }\n }\n\n jsxReadNewLine(normalizeCRLF) {\n const ch = this.input.charCodeAt(this.state.pos);\n let out;\n ++this.state.pos;\n\n if (ch === 13 && this.input.charCodeAt(this.state.pos) === 10) {\n ++this.state.pos;\n out = normalizeCRLF ? \"\\n\" : \"\\r\\n\";\n } else {\n out = String.fromCharCode(ch);\n }\n\n ++this.state.curLine;\n this.state.lineStart = this.state.pos;\n return out;\n }\n\n jsxReadString(quote) {\n let out = \"\";\n let chunkStart = ++this.state.pos;\n\n for (;;) {\n if (this.state.pos >= this.length) {\n throw this.raise(ErrorMessages.UnterminatedString, {\n at: this.state.startLoc\n });\n }\n\n const ch = this.input.charCodeAt(this.state.pos);\n if (ch === quote) break;\n\n if (ch === 38) {\n out += this.input.slice(chunkStart, this.state.pos);\n out += this.jsxReadEntity();\n chunkStart = this.state.pos;\n } else if (isNewLine(ch)) {\n out += this.input.slice(chunkStart, this.state.pos);\n out += this.jsxReadNewLine(false);\n chunkStart = this.state.pos;\n } else {\n ++this.state.pos;\n }\n }\n\n out += this.input.slice(chunkStart, this.state.pos++);\n return this.finishToken(125, out);\n }\n\n jsxReadEntity() {\n let str = \"\";\n let count = 0;\n let entity;\n let ch = this.input[this.state.pos];\n const startPos = ++this.state.pos;\n\n while (this.state.pos < this.length && count++ < 10) {\n ch = this.input[this.state.pos++];\n\n if (ch === \";\") {\n if (str[0] === \"#\") {\n if (str[1] === \"x\") {\n str = str.substr(2);\n\n if (HEX_NUMBER.test(str)) {\n entity = String.fromCodePoint(parseInt(str, 16));\n }\n } else {\n str = str.substr(1);\n\n if (DECIMAL_NUMBER.test(str)) {\n entity = String.fromCodePoint(parseInt(str, 10));\n }\n }\n } else {\n entity = entities[str];\n }\n\n break;\n }\n\n str += ch;\n }\n\n if (!entity) {\n this.state.pos = startPos;\n return \"&\";\n }\n\n return entity;\n }\n\n jsxReadWord() {\n let ch;\n const start = this.state.pos;\n\n do {\n ch = this.input.charCodeAt(++this.state.pos);\n } while (isIdentifierChar(ch) || ch === 45);\n\n return this.finishToken(132, this.input.slice(start, this.state.pos));\n }\n\n jsxParseIdentifier() {\n const node = this.startNode();\n\n if (this.match(132)) {\n node.name = this.state.value;\n } else if (tokenIsKeyword(this.state.type)) {\n node.name = tokenLabelName(this.state.type);\n } else {\n this.unexpected();\n }\n\n this.next();\n return this.finishNode(node, \"JSXIdentifier\");\n }\n\n jsxParseNamespacedName() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const name = this.jsxParseIdentifier();\n if (!this.eat(14)) return name;\n const node = this.startNodeAt(startPos, startLoc);\n node.namespace = name;\n node.name = this.jsxParseIdentifier();\n return this.finishNode(node, \"JSXNamespacedName\");\n }\n\n jsxParseElementName() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let node = this.jsxParseNamespacedName();\n\n if (node.type === \"JSXNamespacedName\") {\n return node;\n }\n\n while (this.eat(16)) {\n const newNode = this.startNodeAt(startPos, startLoc);\n newNode.object = node;\n newNode.property = this.jsxParseIdentifier();\n node = this.finishNode(newNode, \"JSXMemberExpression\");\n }\n\n return node;\n }\n\n jsxParseAttributeValue() {\n let node;\n\n switch (this.state.type) {\n case 5:\n node = this.startNode();\n this.setContext(types.brace);\n this.next();\n node = this.jsxParseExpressionContainer(node, types.j_oTag);\n\n if (node.expression.type === \"JSXEmptyExpression\") {\n this.raise(JsxErrors.AttributeIsEmpty, {\n node\n });\n }\n\n return node;\n\n case 134:\n case 125:\n return this.parseExprAtom();\n\n default:\n throw this.raise(JsxErrors.UnsupportedJsxValue, {\n at: this.state.startLoc\n });\n }\n }\n\n jsxParseEmptyExpression() {\n const node = this.startNodeAt(indexes.get(this.state.lastTokEndLoc), this.state.lastTokEndLoc);\n return this.finishNodeAt(node, \"JSXEmptyExpression\", this.state.startLoc);\n }\n\n jsxParseSpreadChild(node) {\n this.next();\n node.expression = this.parseExpression();\n this.setContext(types.j_oTag);\n this.expect(8);\n return this.finishNode(node, \"JSXSpreadChild\");\n }\n\n jsxParseExpressionContainer(node, previousContext) {\n if (this.match(8)) {\n node.expression = this.jsxParseEmptyExpression();\n } else {\n const expression = this.parseExpression();\n node.expression = expression;\n }\n\n this.setContext(previousContext);\n this.expect(8);\n return this.finishNode(node, \"JSXExpressionContainer\");\n }\n\n jsxParseAttribute() {\n const node = this.startNode();\n\n if (this.match(5)) {\n this.setContext(types.brace);\n this.next();\n this.expect(21);\n node.argument = this.parseMaybeAssignAllowIn();\n this.setContext(types.j_oTag);\n this.expect(8);\n return this.finishNode(node, \"JSXSpreadAttribute\");\n }\n\n node.name = this.jsxParseNamespacedName();\n node.value = this.eat(29) ? this.jsxParseAttributeValue() : null;\n return this.finishNode(node, \"JSXAttribute\");\n }\n\n jsxParseOpeningElementAt(startPos, startLoc) {\n const node = this.startNodeAt(startPos, startLoc);\n\n if (this.match(135)) {\n this.expect(135);\n return this.finishNode(node, \"JSXOpeningFragment\");\n }\n\n node.name = this.jsxParseElementName();\n return this.jsxParseOpeningElementAfterName(node);\n }\n\n jsxParseOpeningElementAfterName(node) {\n const attributes = [];\n\n while (!this.match(52) && !this.match(135)) {\n attributes.push(this.jsxParseAttribute());\n }\n\n node.attributes = attributes;\n node.selfClosing = this.eat(52);\n this.expect(135);\n return this.finishNode(node, \"JSXOpeningElement\");\n }\n\n jsxParseClosingElementAt(startPos, startLoc) {\n const node = this.startNodeAt(startPos, startLoc);\n\n if (this.match(135)) {\n this.expect(135);\n return this.finishNode(node, \"JSXClosingFragment\");\n }\n\n node.name = this.jsxParseElementName();\n this.expect(135);\n return this.finishNode(node, \"JSXClosingElement\");\n }\n\n jsxParseElementAt(startPos, startLoc) {\n const node = this.startNodeAt(startPos, startLoc);\n const children = [];\n const openingElement = this.jsxParseOpeningElementAt(startPos, startLoc);\n let closingElement = null;\n\n if (!openingElement.selfClosing) {\n contents: for (;;) {\n switch (this.state.type) {\n case 134:\n startPos = this.state.start;\n startLoc = this.state.startLoc;\n this.next();\n\n if (this.eat(52)) {\n closingElement = this.jsxParseClosingElementAt(startPos, startLoc);\n break contents;\n }\n\n children.push(this.jsxParseElementAt(startPos, startLoc));\n break;\n\n case 133:\n children.push(this.parseExprAtom());\n break;\n\n case 5:\n {\n const node = this.startNode();\n this.setContext(types.brace);\n this.next();\n\n if (this.match(21)) {\n children.push(this.jsxParseSpreadChild(node));\n } else {\n children.push(this.jsxParseExpressionContainer(node, types.j_expr));\n }\n\n break;\n }\n\n default:\n throw this.unexpected();\n }\n }\n\n if (isFragment(openingElement) && !isFragment(closingElement) && closingElement !== null) {\n this.raise(JsxErrors.MissingClosingTagFragment, {\n node: closingElement\n });\n } else if (!isFragment(openingElement) && isFragment(closingElement)) {\n this.raise(JsxErrors.MissingClosingTagElement, {\n node: closingElement\n }, getQualifiedJSXName(openingElement.name));\n } else if (!isFragment(openingElement) && !isFragment(closingElement)) {\n if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {\n this.raise(JsxErrors.MissingClosingTagElement, {\n node: closingElement\n }, getQualifiedJSXName(openingElement.name));\n }\n }\n }\n\n if (isFragment(openingElement)) {\n node.openingFragment = openingElement;\n node.closingFragment = closingElement;\n } else {\n node.openingElement = openingElement;\n node.closingElement = closingElement;\n }\n\n node.children = children;\n\n if (this.match(45)) {\n throw this.raise(JsxErrors.UnwrappedAdjacentJSXElements, {\n at: this.state.startLoc\n });\n }\n\n return isFragment(openingElement) ? this.finishNode(node, \"JSXFragment\") : this.finishNode(node, \"JSXElement\");\n }\n\n jsxParseElement() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n this.next();\n return this.jsxParseElementAt(startPos, startLoc);\n }\n\n setContext(newContext) {\n const {\n context\n } = this.state;\n context[context.length - 1] = newContext;\n }\n\n parseExprAtom(refExpressionErrors) {\n if (this.match(133)) {\n return this.parseLiteral(this.state.value, \"JSXText\");\n } else if (this.match(134)) {\n return this.jsxParseElement();\n } else if (this.match(45) && this.input.charCodeAt(this.state.pos) !== 33) {\n this.replaceToken(134);\n return this.jsxParseElement();\n } else {\n return super.parseExprAtom(refExpressionErrors);\n }\n }\n\n skipSpace() {\n const curContext = this.curContext();\n if (!curContext.preserveSpace) super.skipSpace();\n }\n\n getTokenFromCode(code) {\n const context = this.curContext();\n\n if (context === types.j_expr) {\n return this.jsxReadToken();\n }\n\n if (context === types.j_oTag || context === types.j_cTag) {\n if (isIdentifierStart(code)) {\n return this.jsxReadWord();\n }\n\n if (code === 62) {\n ++this.state.pos;\n return this.finishToken(135);\n }\n\n if ((code === 34 || code === 39) && context === types.j_oTag) {\n return this.jsxReadString(code);\n }\n }\n\n if (code === 60 && this.state.canStartJSXElement && this.input.charCodeAt(this.state.pos + 1) !== 33) {\n ++this.state.pos;\n return this.finishToken(134);\n }\n\n return super.getTokenFromCode(code);\n }\n\n updateContext(prevType) {\n const {\n context,\n type\n } = this.state;\n\n if (type === 52 && prevType === 134) {\n context.splice(-2, 2, types.j_cTag);\n this.state.canStartJSXElement = false;\n } else if (type === 134) {\n context.push(types.j_oTag);\n } else if (type === 135) {\n const out = context[context.length - 1];\n\n if (out === types.j_oTag && prevType === 52 || out === types.j_cTag) {\n context.pop();\n this.state.canStartJSXElement = context[context.length - 1] === types.j_expr;\n } else {\n this.setContext(types.j_expr);\n this.state.canStartJSXElement = true;\n }\n } else {\n this.state.canStartJSXElement = tokenComesBeforeExpression(type);\n }\n }\n\n});\n\nclass TypeScriptScope extends Scope {\n constructor(...args) {\n super(...args);\n this.types = new Set();\n this.enums = new Set();\n this.constEnums = new Set();\n this.classes = new Set();\n this.exportOnlyBindings = new Set();\n }\n\n}\n\nclass TypeScriptScopeHandler extends ScopeHandler {\n createScope(flags) {\n return new TypeScriptScope(flags);\n }\n\n declareName(name, bindingType, loc) {\n const scope = this.currentScope();\n\n if (bindingType & BIND_FLAGS_TS_EXPORT_ONLY) {\n this.maybeExportDefined(scope, name);\n scope.exportOnlyBindings.add(name);\n return;\n }\n\n super.declareName(...arguments);\n\n if (bindingType & BIND_KIND_TYPE) {\n if (!(bindingType & BIND_KIND_VALUE)) {\n this.checkRedeclarationInScope(scope, name, bindingType, loc);\n this.maybeExportDefined(scope, name);\n }\n\n scope.types.add(name);\n }\n\n if (bindingType & BIND_FLAGS_TS_ENUM) scope.enums.add(name);\n if (bindingType & BIND_FLAGS_TS_CONST_ENUM) scope.constEnums.add(name);\n if (bindingType & BIND_FLAGS_CLASS) scope.classes.add(name);\n }\n\n isRedeclaredInScope(scope, name, bindingType) {\n if (scope.enums.has(name)) {\n if (bindingType & BIND_FLAGS_TS_ENUM) {\n const isConst = !!(bindingType & BIND_FLAGS_TS_CONST_ENUM);\n const wasConst = scope.constEnums.has(name);\n return isConst !== wasConst;\n }\n\n return true;\n }\n\n if (bindingType & BIND_FLAGS_CLASS && scope.classes.has(name)) {\n if (scope.lexical.has(name)) {\n return !!(bindingType & BIND_KIND_VALUE);\n } else {\n return false;\n }\n }\n\n if (bindingType & BIND_KIND_TYPE && scope.types.has(name)) {\n return true;\n }\n\n return super.isRedeclaredInScope(...arguments);\n }\n\n checkLocalExport(id) {\n const topLevelScope = this.scopeStack[0];\n const {\n name\n } = id;\n\n if (!topLevelScope.types.has(name) && !topLevelScope.exportOnlyBindings.has(name)) {\n super.checkLocalExport(id);\n }\n }\n\n}\n\nfunction nonNull(x) {\n if (x == null) {\n throw new Error(`Unexpected ${x} value.`);\n }\n\n return x;\n}\n\nfunction assert(x) {\n if (!x) {\n throw new Error(\"Assert fail\");\n }\n}\n\nconst TSErrors = makeErrorTemplates({\n AbstractMethodHasImplementation: \"Method '%0' cannot have an implementation because it is marked abstract.\",\n AbstractPropertyHasInitializer: \"Property '%0' cannot have an initializer because it is marked abstract.\",\n AccesorCannotDeclareThisParameter: \"'get' and 'set' accessors cannot declare 'this' parameters.\",\n AccesorCannotHaveTypeParameters: \"An accessor cannot have type parameters.\",\n ClassMethodHasDeclare: \"Class methods cannot have the 'declare' modifier.\",\n ClassMethodHasReadonly: \"Class methods cannot have the 'readonly' modifier.\",\n ConstructorHasTypeParameters: \"Type parameters cannot appear on a constructor declaration.\",\n DeclareAccessor: \"'declare' is not allowed in %0ters.\",\n DeclareClassFieldHasInitializer: \"Initializers are not allowed in ambient contexts.\",\n DeclareFunctionHasImplementation: \"An implementation cannot be declared in ambient contexts.\",\n DuplicateAccessibilityModifier: \"Accessibility modifier already seen.\",\n DuplicateModifier: \"Duplicate modifier: '%0'.\",\n EmptyHeritageClauseType: \"'%0' list cannot be empty.\",\n EmptyTypeArguments: \"Type argument list cannot be empty.\",\n EmptyTypeParameters: \"Type parameter list cannot be empty.\",\n ExpectedAmbientAfterExportDeclare: \"'export declare' must be followed by an ambient declaration.\",\n ImportAliasHasImportType: \"An import alias can not use 'import type'.\",\n IncompatibleModifiers: \"'%0' modifier cannot be used with '%1' modifier.\",\n IndexSignatureHasAbstract: \"Index signatures cannot have the 'abstract' modifier.\",\n IndexSignatureHasAccessibility: \"Index signatures cannot have an accessibility modifier ('%0').\",\n IndexSignatureHasDeclare: \"Index signatures cannot have the 'declare' modifier.\",\n IndexSignatureHasOverride: \"'override' modifier cannot appear on an index signature.\",\n IndexSignatureHasStatic: \"Index signatures cannot have the 'static' modifier.\",\n InvalidModifierOnTypeMember: \"'%0' modifier cannot appear on a type member.\",\n InvalidModifiersOrder: \"'%0' modifier must precede '%1' modifier.\",\n InvalidTupleMemberLabel: \"Tuple members must be labeled with a simple identifier.\",\n MissingInterfaceName: \"'interface' declarations must be followed by an identifier.\",\n MixedLabeledAndUnlabeledElements: \"Tuple members must all have names or all not have names.\",\n NonAbstractClassHasAbstractMethod: \"Abstract methods can only appear within an abstract class.\",\n NonClassMethodPropertyHasAbstractModifer: \"'abstract' modifier can only appear on a class, method, or property declaration.\",\n OptionalTypeBeforeRequired: \"A required element cannot follow an optional element.\",\n OverrideNotInSubClass: \"This member cannot have an 'override' modifier because its containing class does not extend another class.\",\n PatternIsOptional: \"A binding pattern parameter cannot be optional in an implementation signature.\",\n PrivateElementHasAbstract: \"Private elements cannot have the 'abstract' modifier.\",\n PrivateElementHasAccessibility: \"Private elements cannot have an accessibility modifier ('%0').\",\n ReadonlyForMethodSignature: \"'readonly' modifier can only appear on a property declaration or index signature.\",\n ReservedArrowTypeParam: \"This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `() => ...`.\",\n ReservedTypeAssertion: \"This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.\",\n SetAccesorCannotHaveOptionalParameter: \"A 'set' accessor cannot have an optional parameter.\",\n SetAccesorCannotHaveRestParameter: \"A 'set' accessor cannot have rest parameter.\",\n SetAccesorCannotHaveReturnType: \"A 'set' accessor cannot have a return type annotation.\",\n StaticBlockCannotHaveModifier: \"Static class blocks cannot have any modifier.\",\n TypeAnnotationAfterAssign: \"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.\",\n TypeImportCannotSpecifyDefaultAndNamed: \"A type-only import can specify a default import or named bindings, but not both.\",\n TypeModifierIsUsedInTypeExports: \"The 'type' modifier cannot be used on a named export when 'export type' is used on its export statement.\",\n TypeModifierIsUsedInTypeImports: \"The 'type' modifier cannot be used on a named import when 'import type' is used on its import statement.\",\n UnexpectedParameterModifier: \"A parameter property is only allowed in a constructor implementation.\",\n UnexpectedReadonly: \"'readonly' type modifier is only permitted on array and tuple literal types.\",\n UnexpectedTypeAnnotation: \"Did not expect a type annotation here.\",\n UnexpectedTypeCastInParameter: \"Unexpected type cast in parameter position.\",\n UnsupportedImportTypeArgument: \"Argument in a type import must be a string literal.\",\n UnsupportedParameterPropertyKind: \"A parameter property may not be declared using a binding pattern.\",\n UnsupportedSignatureParameterKind: \"Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got %0.\"\n}, ErrorCodes.SyntaxError, \"typescript\");\n\nfunction keywordTypeFromName(value) {\n switch (value) {\n case \"any\":\n return \"TSAnyKeyword\";\n\n case \"boolean\":\n return \"TSBooleanKeyword\";\n\n case \"bigint\":\n return \"TSBigIntKeyword\";\n\n case \"never\":\n return \"TSNeverKeyword\";\n\n case \"number\":\n return \"TSNumberKeyword\";\n\n case \"object\":\n return \"TSObjectKeyword\";\n\n case \"string\":\n return \"TSStringKeyword\";\n\n case \"symbol\":\n return \"TSSymbolKeyword\";\n\n case \"undefined\":\n return \"TSUndefinedKeyword\";\n\n case \"unknown\":\n return \"TSUnknownKeyword\";\n\n default:\n return undefined;\n }\n}\n\nfunction tsIsAccessModifier(modifier) {\n return modifier === \"private\" || modifier === \"public\" || modifier === \"protected\";\n}\n\nvar typescript = (superClass => class extends superClass {\n getScopeHandler() {\n return TypeScriptScopeHandler;\n }\n\n tsIsIdentifier() {\n return tokenIsIdentifier(this.state.type);\n }\n\n tsTokenCanFollowModifier() {\n return (this.match(0) || this.match(5) || this.match(51) || this.match(21) || this.match(130) || this.isLiteralPropertyName()) && !this.hasPrecedingLineBreak();\n }\n\n tsNextTokenCanFollowModifier() {\n this.next();\n return this.tsTokenCanFollowModifier();\n }\n\n tsParseModifier(allowedModifiers, stopOnStartOfClassStaticBlock) {\n if (!tokenIsIdentifier(this.state.type)) {\n return undefined;\n }\n\n const modifier = this.state.value;\n\n if (allowedModifiers.indexOf(modifier) !== -1) {\n if (stopOnStartOfClassStaticBlock && this.tsIsStartOfStaticBlocks()) {\n return undefined;\n }\n\n if (this.tsTryParse(this.tsNextTokenCanFollowModifier.bind(this))) {\n return modifier;\n }\n }\n\n return undefined;\n }\n\n tsParseModifiers(modified, allowedModifiers, disallowedModifiers, errorTemplate, stopOnStartOfClassStaticBlock) {\n const enforceOrder = (loc, modifier, before, after) => {\n if (modifier === before && modified[after]) {\n this.raise(TSErrors.InvalidModifiersOrder, {\n at: loc\n }, before, after);\n }\n };\n\n const incompatible = (loc, modifier, mod1, mod2) => {\n if (modified[mod1] && modifier === mod2 || modified[mod2] && modifier === mod1) {\n this.raise(TSErrors.IncompatibleModifiers, {\n at: loc\n }, mod1, mod2);\n }\n };\n\n for (;;) {\n const {\n startLoc\n } = this.state;\n const modifier = this.tsParseModifier(allowedModifiers.concat(disallowedModifiers != null ? disallowedModifiers : []), stopOnStartOfClassStaticBlock);\n if (!modifier) break;\n\n if (tsIsAccessModifier(modifier)) {\n if (modified.accessibility) {\n this.raise(TSErrors.DuplicateAccessibilityModifier, {\n at: startLoc\n });\n } else {\n enforceOrder(startLoc, modifier, modifier, \"override\");\n enforceOrder(startLoc, modifier, modifier, \"static\");\n enforceOrder(startLoc, modifier, modifier, \"readonly\");\n modified.accessibility = modifier;\n }\n } else {\n if (Object.hasOwnProperty.call(modified, modifier)) {\n this.raise(TSErrors.DuplicateModifier, {\n at: startLoc\n }, modifier);\n } else {\n enforceOrder(startLoc, modifier, \"static\", \"readonly\");\n enforceOrder(startLoc, modifier, \"static\", \"override\");\n enforceOrder(startLoc, modifier, \"override\", \"readonly\");\n enforceOrder(startLoc, modifier, \"abstract\", \"override\");\n incompatible(startLoc, modifier, \"declare\", \"override\");\n incompatible(startLoc, modifier, \"static\", \"abstract\");\n }\n\n modified[modifier] = true;\n }\n\n if (disallowedModifiers != null && disallowedModifiers.includes(modifier)) {\n this.raise(errorTemplate, {\n at: startLoc\n }, modifier);\n }\n }\n }\n\n tsIsListTerminator(kind) {\n switch (kind) {\n case \"EnumMembers\":\n case \"TypeMembers\":\n return this.match(8);\n\n case \"HeritageClauseElement\":\n return this.match(5);\n\n case \"TupleElementTypes\":\n return this.match(3);\n\n case \"TypeParametersOrArguments\":\n return this.match(46);\n }\n\n throw new Error(\"Unreachable\");\n }\n\n tsParseList(kind, parseElement) {\n const result = [];\n\n while (!this.tsIsListTerminator(kind)) {\n result.push(parseElement());\n }\n\n return result;\n }\n\n tsParseDelimitedList(kind, parseElement, refTrailingCommaPos) {\n return nonNull(this.tsParseDelimitedListWorker(kind, parseElement, true, refTrailingCommaPos));\n }\n\n tsParseDelimitedListWorker(kind, parseElement, expectSuccess, refTrailingCommaPos) {\n const result = [];\n let trailingCommaPos = -1;\n\n for (;;) {\n if (this.tsIsListTerminator(kind)) {\n break;\n }\n\n trailingCommaPos = -1;\n const element = parseElement();\n\n if (element == null) {\n return undefined;\n }\n\n result.push(element);\n\n if (this.eat(12)) {\n trailingCommaPos = this.state.lastTokStart;\n continue;\n }\n\n if (this.tsIsListTerminator(kind)) {\n break;\n }\n\n if (expectSuccess) {\n this.expect(12);\n }\n\n return undefined;\n }\n\n if (refTrailingCommaPos) {\n refTrailingCommaPos.value = trailingCommaPos;\n }\n\n return result;\n }\n\n tsParseBracketedList(kind, parseElement, bracket, skipFirstToken, refTrailingCommaPos) {\n if (!skipFirstToken) {\n if (bracket) {\n this.expect(0);\n } else {\n this.expect(45);\n }\n }\n\n const result = this.tsParseDelimitedList(kind, parseElement, refTrailingCommaPos);\n\n if (bracket) {\n this.expect(3);\n } else {\n this.expect(46);\n }\n\n return result;\n }\n\n tsParseImportType() {\n const node = this.startNode();\n this.expect(79);\n this.expect(10);\n\n if (!this.match(125)) {\n this.raise(TSErrors.UnsupportedImportTypeArgument, {\n at: this.state.startLoc\n });\n }\n\n node.argument = this.parseExprAtom();\n this.expect(11);\n\n if (this.eat(16)) {\n node.qualifier = this.tsParseEntityName(true);\n }\n\n if (this.match(45)) {\n node.typeParameters = this.tsParseTypeArguments();\n }\n\n return this.finishNode(node, \"TSImportType\");\n }\n\n tsParseEntityName(allowReservedWords) {\n let entity = this.parseIdentifier();\n\n while (this.eat(16)) {\n const node = this.startNodeAtNode(entity);\n node.left = entity;\n node.right = this.parseIdentifier(allowReservedWords);\n entity = this.finishNode(node, \"TSQualifiedName\");\n }\n\n return entity;\n }\n\n tsParseTypeReference() {\n const node = this.startNode();\n node.typeName = this.tsParseEntityName(false);\n\n if (!this.hasPrecedingLineBreak() && this.match(45)) {\n node.typeParameters = this.tsParseTypeArguments();\n }\n\n return this.finishNode(node, \"TSTypeReference\");\n }\n\n tsParseThisTypePredicate(lhs) {\n this.next();\n const node = this.startNodeAtNode(lhs);\n node.parameterName = lhs;\n node.typeAnnotation = this.tsParseTypeAnnotation(false);\n node.asserts = false;\n return this.finishNode(node, \"TSTypePredicate\");\n }\n\n tsParseThisTypeNode() {\n const node = this.startNode();\n this.next();\n return this.finishNode(node, \"TSThisType\");\n }\n\n tsParseTypeQuery() {\n const node = this.startNode();\n this.expect(83);\n\n if (this.match(79)) {\n node.exprName = this.tsParseImportType();\n } else {\n node.exprName = this.tsParseEntityName(true);\n }\n\n return this.finishNode(node, \"TSTypeQuery\");\n }\n\n tsParseTypeParameter() {\n const node = this.startNode();\n node.name = this.tsParseTypeParameterName();\n node.constraint = this.tsEatThenParseType(77);\n node.default = this.tsEatThenParseType(29);\n return this.finishNode(node, \"TSTypeParameter\");\n }\n\n tsTryParseTypeParameters() {\n if (this.match(45)) {\n return this.tsParseTypeParameters();\n }\n }\n\n tsParseTypeParameters() {\n const node = this.startNode();\n\n if (this.match(45) || this.match(134)) {\n this.next();\n } else {\n this.unexpected();\n }\n\n const refTrailingCommaPos = {\n value: -1\n };\n node.params = this.tsParseBracketedList(\"TypeParametersOrArguments\", this.tsParseTypeParameter.bind(this), false, true, refTrailingCommaPos);\n\n if (node.params.length === 0) {\n this.raise(TSErrors.EmptyTypeParameters, {\n node\n });\n }\n\n if (refTrailingCommaPos.value !== -1) {\n this.addExtra(node, \"trailingComma\", refTrailingCommaPos.value);\n }\n\n return this.finishNode(node, \"TSTypeParameterDeclaration\");\n }\n\n tsTryNextParseConstantContext() {\n if (this.lookahead().type === 71) {\n this.next();\n return this.tsParseTypeReference();\n }\n\n return null;\n }\n\n tsFillSignature(returnToken, signature) {\n const returnTokenRequired = returnToken === 19;\n const paramsKey = \"parameters\";\n const returnTypeKey = \"typeAnnotation\";\n signature.typeParameters = this.tsTryParseTypeParameters();\n this.expect(10);\n signature[paramsKey] = this.tsParseBindingListForSignature();\n\n if (returnTokenRequired) {\n signature[returnTypeKey] = this.tsParseTypeOrTypePredicateAnnotation(returnToken);\n } else if (this.match(returnToken)) {\n signature[returnTypeKey] = this.tsParseTypeOrTypePredicateAnnotation(returnToken);\n }\n }\n\n tsParseBindingListForSignature() {\n return this.parseBindingList(11, 41).map(pattern => {\n if (pattern.type !== \"Identifier\" && pattern.type !== \"RestElement\" && pattern.type !== \"ObjectPattern\" && pattern.type !== \"ArrayPattern\") {\n this.raise(TSErrors.UnsupportedSignatureParameterKind, {\n node: pattern\n }, pattern.type);\n }\n\n return pattern;\n });\n }\n\n tsParseTypeMemberSemicolon() {\n if (!this.eat(12) && !this.isLineTerminator()) {\n this.expect(13);\n }\n }\n\n tsParseSignatureMember(kind, node) {\n this.tsFillSignature(14, node);\n this.tsParseTypeMemberSemicolon();\n return this.finishNode(node, kind);\n }\n\n tsIsUnambiguouslyIndexSignature() {\n this.next();\n\n if (tokenIsIdentifier(this.state.type)) {\n this.next();\n return this.match(14);\n }\n\n return false;\n }\n\n tsTryParseIndexSignature(node) {\n if (!(this.match(0) && this.tsLookAhead(this.tsIsUnambiguouslyIndexSignature.bind(this)))) {\n return undefined;\n }\n\n this.expect(0);\n const id = this.parseIdentifier();\n id.typeAnnotation = this.tsParseTypeAnnotation();\n this.resetEndLocation(id);\n this.expect(3);\n node.parameters = [id];\n const type = this.tsTryParseTypeAnnotation();\n if (type) node.typeAnnotation = type;\n this.tsParseTypeMemberSemicolon();\n return this.finishNode(node, \"TSIndexSignature\");\n }\n\n tsParsePropertyOrMethodSignature(node, readonly) {\n if (this.eat(17)) node.optional = true;\n const nodeAny = node;\n\n if (this.match(10) || this.match(45)) {\n if (readonly) {\n this.raise(TSErrors.ReadonlyForMethodSignature, {\n node\n });\n }\n\n const method = nodeAny;\n\n if (method.kind && this.match(45)) {\n this.raise(TSErrors.AccesorCannotHaveTypeParameters, {\n at: this.state.curPosition()\n });\n }\n\n this.tsFillSignature(14, method);\n this.tsParseTypeMemberSemicolon();\n const paramsKey = \"parameters\";\n const returnTypeKey = \"typeAnnotation\";\n\n if (method.kind === \"get\") {\n if (method[paramsKey].length > 0) {\n this.raise(ErrorMessages.BadGetterArity, {\n at: this.state.curPosition()\n });\n\n if (this.isThisParam(method[paramsKey][0])) {\n this.raise(TSErrors.AccesorCannotDeclareThisParameter, {\n at: this.state.curPosition()\n });\n }\n }\n } else if (method.kind === \"set\") {\n if (method[paramsKey].length !== 1) {\n this.raise(ErrorMessages.BadSetterArity, {\n at: this.state.curPosition()\n });\n } else {\n const firstParameter = method[paramsKey][0];\n\n if (this.isThisParam(firstParameter)) {\n this.raise(TSErrors.AccesorCannotDeclareThisParameter, {\n at: this.state.curPosition()\n });\n }\n\n if (firstParameter.type === \"Identifier\" && firstParameter.optional) {\n this.raise(TSErrors.SetAccesorCannotHaveOptionalParameter, {\n at: this.state.curPosition()\n });\n }\n\n if (firstParameter.type === \"RestElement\") {\n this.raise(TSErrors.SetAccesorCannotHaveRestParameter, {\n at: this.state.curPosition()\n });\n }\n }\n\n if (method[returnTypeKey]) {\n this.raise(TSErrors.SetAccesorCannotHaveReturnType, {\n node: method[returnTypeKey]\n });\n }\n } else {\n method.kind = \"method\";\n }\n\n return this.finishNode(method, \"TSMethodSignature\");\n } else {\n const property = nodeAny;\n if (readonly) property.readonly = true;\n const type = this.tsTryParseTypeAnnotation();\n if (type) property.typeAnnotation = type;\n this.tsParseTypeMemberSemicolon();\n return this.finishNode(property, \"TSPropertySignature\");\n }\n }\n\n tsParseTypeMember() {\n const node = this.startNode();\n\n if (this.match(10) || this.match(45)) {\n return this.tsParseSignatureMember(\"TSCallSignatureDeclaration\", node);\n }\n\n if (this.match(73)) {\n const id = this.startNode();\n this.next();\n\n if (this.match(10) || this.match(45)) {\n return this.tsParseSignatureMember(\"TSConstructSignatureDeclaration\", node);\n } else {\n node.key = this.createIdentifier(id, \"new\");\n return this.tsParsePropertyOrMethodSignature(node, false);\n }\n }\n\n this.tsParseModifiers(node, [\"readonly\"], [\"declare\", \"abstract\", \"private\", \"protected\", \"public\", \"static\", \"override\"], TSErrors.InvalidModifierOnTypeMember);\n const idx = this.tsTryParseIndexSignature(node);\n\n if (idx) {\n return idx;\n }\n\n this.parsePropertyName(node);\n\n if (!node.computed && node.key.type === \"Identifier\" && (node.key.name === \"get\" || node.key.name === \"set\") && this.tsTokenCanFollowModifier()) {\n node.kind = node.key.name;\n this.parsePropertyName(node);\n }\n\n return this.tsParsePropertyOrMethodSignature(node, !!node.readonly);\n }\n\n tsParseTypeLiteral() {\n const node = this.startNode();\n node.members = this.tsParseObjectTypeMembers();\n return this.finishNode(node, \"TSTypeLiteral\");\n }\n\n tsParseObjectTypeMembers() {\n this.expect(5);\n const members = this.tsParseList(\"TypeMembers\", this.tsParseTypeMember.bind(this));\n this.expect(8);\n return members;\n }\n\n tsIsStartOfMappedType() {\n this.next();\n\n if (this.eat(49)) {\n return this.isContextual(114);\n }\n\n if (this.isContextual(114)) {\n this.next();\n }\n\n if (!this.match(0)) {\n return false;\n }\n\n this.next();\n\n if (!this.tsIsIdentifier()) {\n return false;\n }\n\n this.next();\n return this.match(54);\n }\n\n tsParseMappedTypeParameter() {\n const node = this.startNode();\n node.name = this.tsParseTypeParameterName();\n node.constraint = this.tsExpectThenParseType(54);\n return this.finishNode(node, \"TSTypeParameter\");\n }\n\n tsParseMappedType() {\n const node = this.startNode();\n this.expect(5);\n\n if (this.match(49)) {\n node.readonly = this.state.value;\n this.next();\n this.expectContextual(114);\n } else if (this.eatContextual(114)) {\n node.readonly = true;\n }\n\n this.expect(0);\n node.typeParameter = this.tsParseMappedTypeParameter();\n node.nameType = this.eatContextual(89) ? this.tsParseType() : null;\n this.expect(3);\n\n if (this.match(49)) {\n node.optional = this.state.value;\n this.next();\n this.expect(17);\n } else if (this.eat(17)) {\n node.optional = true;\n }\n\n node.typeAnnotation = this.tsTryParseType();\n this.semicolon();\n this.expect(8);\n return this.finishNode(node, \"TSMappedType\");\n }\n\n tsParseTupleType() {\n const node = this.startNode();\n node.elementTypes = this.tsParseBracketedList(\"TupleElementTypes\", this.tsParseTupleElementType.bind(this), true, false);\n let seenOptionalElement = false;\n let labeledElements = null;\n node.elementTypes.forEach(elementNode => {\n var _labeledElements;\n\n let {\n type\n } = elementNode;\n\n if (seenOptionalElement && type !== \"TSRestType\" && type !== \"TSOptionalType\" && !(type === \"TSNamedTupleMember\" && elementNode.optional)) {\n this.raise(TSErrors.OptionalTypeBeforeRequired, {\n node: elementNode\n });\n }\n\n seenOptionalElement = seenOptionalElement || type === \"TSNamedTupleMember\" && elementNode.optional || type === \"TSOptionalType\";\n\n if (type === \"TSRestType\") {\n elementNode = elementNode.typeAnnotation;\n type = elementNode.type;\n }\n\n const isLabeled = type === \"TSNamedTupleMember\";\n labeledElements = (_labeledElements = labeledElements) != null ? _labeledElements : isLabeled;\n\n if (labeledElements !== isLabeled) {\n this.raise(TSErrors.MixedLabeledAndUnlabeledElements, {\n node: elementNode\n });\n }\n });\n return this.finishNode(node, \"TSTupleType\");\n }\n\n tsParseTupleElementType() {\n const {\n start: startPos,\n startLoc\n } = this.state;\n const rest = this.eat(21);\n let type = this.tsParseType();\n const optional = this.eat(17);\n const labeled = this.eat(14);\n\n if (labeled) {\n const labeledNode = this.startNodeAtNode(type);\n labeledNode.optional = optional;\n\n if (type.type === \"TSTypeReference\" && !type.typeParameters && type.typeName.type === \"Identifier\") {\n labeledNode.label = type.typeName;\n } else {\n this.raise(TSErrors.InvalidTupleMemberLabel, {\n node: type\n });\n labeledNode.label = type;\n }\n\n labeledNode.elementType = this.tsParseType();\n type = this.finishNode(labeledNode, \"TSNamedTupleMember\");\n } else if (optional) {\n const optionalTypeNode = this.startNodeAtNode(type);\n optionalTypeNode.typeAnnotation = type;\n type = this.finishNode(optionalTypeNode, \"TSOptionalType\");\n }\n\n if (rest) {\n const restNode = this.startNodeAt(startPos, startLoc);\n restNode.typeAnnotation = type;\n type = this.finishNode(restNode, \"TSRestType\");\n }\n\n return type;\n }\n\n tsParseParenthesizedType() {\n const node = this.startNode();\n this.expect(10);\n node.typeAnnotation = this.tsParseType();\n this.expect(11);\n return this.finishNode(node, \"TSParenthesizedType\");\n }\n\n tsParseFunctionOrConstructorType(type, abstract) {\n const node = this.startNode();\n\n if (type === \"TSConstructorType\") {\n node.abstract = !!abstract;\n if (abstract) this.next();\n this.next();\n }\n\n this.tsFillSignature(19, node);\n return this.finishNode(node, type);\n }\n\n tsParseLiteralTypeNode() {\n const node = this.startNode();\n\n node.literal = (() => {\n switch (this.state.type) {\n case 126:\n case 127:\n case 125:\n case 81:\n case 82:\n return this.parseExprAtom();\n\n default:\n throw this.unexpected();\n }\n })();\n\n return this.finishNode(node, \"TSLiteralType\");\n }\n\n tsParseTemplateLiteralType() {\n const node = this.startNode();\n node.literal = this.parseTemplate(false);\n return this.finishNode(node, \"TSLiteralType\");\n }\n\n parseTemplateSubstitution() {\n if (this.state.inType) return this.tsParseType();\n return super.parseTemplateSubstitution();\n }\n\n tsParseThisTypeOrThisTypePredicate() {\n const thisKeyword = this.tsParseThisTypeNode();\n\n if (this.isContextual(109) && !this.hasPrecedingLineBreak()) {\n return this.tsParseThisTypePredicate(thisKeyword);\n } else {\n return thisKeyword;\n }\n }\n\n tsParseNonArrayType() {\n switch (this.state.type) {\n case 125:\n case 126:\n case 127:\n case 81:\n case 82:\n return this.tsParseLiteralTypeNode();\n\n case 49:\n if (this.state.value === \"-\") {\n const node = this.startNode();\n const nextToken = this.lookahead();\n\n if (nextToken.type !== 126 && nextToken.type !== 127) {\n throw this.unexpected();\n }\n\n node.literal = this.parseMaybeUnary();\n return this.finishNode(node, \"TSLiteralType\");\n }\n\n break;\n\n case 74:\n return this.tsParseThisTypeOrThisTypePredicate();\n\n case 83:\n return this.tsParseTypeQuery();\n\n case 79:\n return this.tsParseImportType();\n\n case 5:\n return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this)) ? this.tsParseMappedType() : this.tsParseTypeLiteral();\n\n case 0:\n return this.tsParseTupleType();\n\n case 10:\n return this.tsParseParenthesizedType();\n\n case 25:\n case 24:\n return this.tsParseTemplateLiteralType();\n\n default:\n {\n const {\n type\n } = this.state;\n\n if (tokenIsIdentifier(type) || type === 84 || type === 80) {\n const nodeType = type === 84 ? \"TSVoidKeyword\" : type === 80 ? \"TSNullKeyword\" : keywordTypeFromName(this.state.value);\n\n if (nodeType !== undefined && this.lookaheadCharCode() !== 46) {\n const node = this.startNode();\n this.next();\n return this.finishNode(node, nodeType);\n }\n\n return this.tsParseTypeReference();\n }\n }\n }\n\n throw this.unexpected();\n }\n\n tsParseArrayTypeOrHigher() {\n let type = this.tsParseNonArrayType();\n\n while (!this.hasPrecedingLineBreak() && this.eat(0)) {\n if (this.match(3)) {\n const node = this.startNodeAtNode(type);\n node.elementType = type;\n this.expect(3);\n type = this.finishNode(node, \"TSArrayType\");\n } else {\n const node = this.startNodeAtNode(type);\n node.objectType = type;\n node.indexType = this.tsParseType();\n this.expect(3);\n type = this.finishNode(node, \"TSIndexedAccessType\");\n }\n }\n\n return type;\n }\n\n tsParseTypeOperator() {\n const node = this.startNode();\n const operator = this.state.value;\n this.next();\n node.operator = operator;\n node.typeAnnotation = this.tsParseTypeOperatorOrHigher();\n\n if (operator === \"readonly\") {\n this.tsCheckTypeAnnotationForReadOnly(node);\n }\n\n return this.finishNode(node, \"TSTypeOperator\");\n }\n\n tsCheckTypeAnnotationForReadOnly(node) {\n switch (node.typeAnnotation.type) {\n case \"TSTupleType\":\n case \"TSArrayType\":\n return;\n\n default:\n this.raise(TSErrors.UnexpectedReadonly, {\n node\n });\n }\n }\n\n tsParseInferType() {\n const node = this.startNode();\n this.expectContextual(108);\n const typeParameter = this.startNode();\n typeParameter.name = this.tsParseTypeParameterName();\n node.typeParameter = this.finishNode(typeParameter, \"TSTypeParameter\");\n return this.finishNode(node, \"TSInferType\");\n }\n\n tsParseTypeOperatorOrHigher() {\n const isTypeOperator = tokenIsTSTypeOperator(this.state.type) && !this.state.containsEsc;\n return isTypeOperator ? this.tsParseTypeOperator() : this.isContextual(108) ? this.tsParseInferType() : this.tsParseArrayTypeOrHigher();\n }\n\n tsParseUnionOrIntersectionType(kind, parseConstituentType, operator) {\n const node = this.startNode();\n const hasLeadingOperator = this.eat(operator);\n const types = [];\n\n do {\n types.push(parseConstituentType());\n } while (this.eat(operator));\n\n if (types.length === 1 && !hasLeadingOperator) {\n return types[0];\n }\n\n node.types = types;\n return this.finishNode(node, kind);\n }\n\n tsParseIntersectionTypeOrHigher() {\n return this.tsParseUnionOrIntersectionType(\"TSIntersectionType\", this.tsParseTypeOperatorOrHigher.bind(this), 43);\n }\n\n tsParseUnionTypeOrHigher() {\n return this.tsParseUnionOrIntersectionType(\"TSUnionType\", this.tsParseIntersectionTypeOrHigher.bind(this), 41);\n }\n\n tsIsStartOfFunctionType() {\n if (this.match(45)) {\n return true;\n }\n\n return this.match(10) && this.tsLookAhead(this.tsIsUnambiguouslyStartOfFunctionType.bind(this));\n }\n\n tsSkipParameterStart() {\n if (tokenIsIdentifier(this.state.type) || this.match(74)) {\n this.next();\n return true;\n }\n\n if (this.match(5)) {\n let braceStackCounter = 1;\n this.next();\n\n while (braceStackCounter > 0) {\n if (this.match(5)) {\n ++braceStackCounter;\n } else if (this.match(8)) {\n --braceStackCounter;\n }\n\n this.next();\n }\n\n return true;\n }\n\n if (this.match(0)) {\n let braceStackCounter = 1;\n this.next();\n\n while (braceStackCounter > 0) {\n if (this.match(0)) {\n ++braceStackCounter;\n } else if (this.match(3)) {\n --braceStackCounter;\n }\n\n this.next();\n }\n\n return true;\n }\n\n return false;\n }\n\n tsIsUnambiguouslyStartOfFunctionType() {\n this.next();\n\n if (this.match(11) || this.match(21)) {\n return true;\n }\n\n if (this.tsSkipParameterStart()) {\n if (this.match(14) || this.match(12) || this.match(17) || this.match(29)) {\n return true;\n }\n\n if (this.match(11)) {\n this.next();\n\n if (this.match(19)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n tsParseTypeOrTypePredicateAnnotation(returnToken) {\n return this.tsInType(() => {\n const t = this.startNode();\n this.expect(returnToken);\n const node = this.startNode();\n const asserts = !!this.tsTryParse(this.tsParseTypePredicateAsserts.bind(this));\n\n if (asserts && this.match(74)) {\n let thisTypePredicate = this.tsParseThisTypeOrThisTypePredicate();\n\n if (thisTypePredicate.type === \"TSThisType\") {\n node.parameterName = thisTypePredicate;\n node.asserts = true;\n node.typeAnnotation = null;\n thisTypePredicate = this.finishNode(node, \"TSTypePredicate\");\n } else {\n this.resetStartLocationFromNode(thisTypePredicate, node);\n thisTypePredicate.asserts = true;\n }\n\n t.typeAnnotation = thisTypePredicate;\n return this.finishNode(t, \"TSTypeAnnotation\");\n }\n\n const typePredicateVariable = this.tsIsIdentifier() && this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this));\n\n if (!typePredicateVariable) {\n if (!asserts) {\n return this.tsParseTypeAnnotation(false, t);\n }\n\n node.parameterName = this.parseIdentifier();\n node.asserts = asserts;\n node.typeAnnotation = null;\n t.typeAnnotation = this.finishNode(node, \"TSTypePredicate\");\n return this.finishNode(t, \"TSTypeAnnotation\");\n }\n\n const type = this.tsParseTypeAnnotation(false);\n node.parameterName = typePredicateVariable;\n node.typeAnnotation = type;\n node.asserts = asserts;\n t.typeAnnotation = this.finishNode(node, \"TSTypePredicate\");\n return this.finishNode(t, \"TSTypeAnnotation\");\n });\n }\n\n tsTryParseTypeOrTypePredicateAnnotation() {\n return this.match(14) ? this.tsParseTypeOrTypePredicateAnnotation(14) : undefined;\n }\n\n tsTryParseTypeAnnotation() {\n return this.match(14) ? this.tsParseTypeAnnotation() : undefined;\n }\n\n tsTryParseType() {\n return this.tsEatThenParseType(14);\n }\n\n tsParseTypePredicatePrefix() {\n const id = this.parseIdentifier();\n\n if (this.isContextual(109) && !this.hasPrecedingLineBreak()) {\n this.next();\n return id;\n }\n }\n\n tsParseTypePredicateAsserts() {\n if (this.state.type !== 102) {\n return false;\n }\n\n const containsEsc = this.state.containsEsc;\n this.next();\n\n if (!tokenIsIdentifier(this.state.type) && !this.match(74)) {\n return false;\n }\n\n if (containsEsc) {\n this.raise(ErrorMessages.InvalidEscapedReservedWord, {\n at: this.state.lastTokStartLoc\n }, \"asserts\");\n }\n\n return true;\n }\n\n tsParseTypeAnnotation(eatColon = true, t = this.startNode()) {\n this.tsInType(() => {\n if (eatColon) this.expect(14);\n t.typeAnnotation = this.tsParseType();\n });\n return this.finishNode(t, \"TSTypeAnnotation\");\n }\n\n tsParseType() {\n assert(this.state.inType);\n const type = this.tsParseNonConditionalType();\n\n if (this.hasPrecedingLineBreak() || !this.eat(77)) {\n return type;\n }\n\n const node = this.startNodeAtNode(type);\n node.checkType = type;\n node.extendsType = this.tsParseNonConditionalType();\n this.expect(17);\n node.trueType = this.tsParseType();\n this.expect(14);\n node.falseType = this.tsParseType();\n return this.finishNode(node, \"TSConditionalType\");\n }\n\n isAbstractConstructorSignature() {\n return this.isContextual(116) && this.lookahead().type === 73;\n }\n\n tsParseNonConditionalType() {\n if (this.tsIsStartOfFunctionType()) {\n return this.tsParseFunctionOrConstructorType(\"TSFunctionType\");\n }\n\n if (this.match(73)) {\n return this.tsParseFunctionOrConstructorType(\"TSConstructorType\");\n } else if (this.isAbstractConstructorSignature()) {\n return this.tsParseFunctionOrConstructorType(\"TSConstructorType\", true);\n }\n\n return this.tsParseUnionTypeOrHigher();\n }\n\n tsParseTypeAssertion() {\n if (this.getPluginOption(\"typescript\", \"disallowAmbiguousJSXLike\")) {\n this.raise(TSErrors.ReservedTypeAssertion, {\n at: this.state.startLoc\n });\n }\n\n const node = this.startNode();\n\n const _const = this.tsTryNextParseConstantContext();\n\n node.typeAnnotation = _const || this.tsNextThenParseType();\n this.expect(46);\n node.expression = this.parseMaybeUnary();\n return this.finishNode(node, \"TSTypeAssertion\");\n }\n\n tsParseHeritageClause(descriptor) {\n const originalStartLoc = this.state.startLoc;\n const delimitedList = this.tsParseDelimitedList(\"HeritageClauseElement\", this.tsParseExpressionWithTypeArguments.bind(this));\n\n if (!delimitedList.length) {\n this.raise(TSErrors.EmptyHeritageClauseType, {\n at: originalStartLoc\n }, descriptor);\n }\n\n return delimitedList;\n }\n\n tsParseExpressionWithTypeArguments() {\n const node = this.startNode();\n node.expression = this.tsParseEntityName(false);\n\n if (this.match(45)) {\n node.typeParameters = this.tsParseTypeArguments();\n }\n\n return this.finishNode(node, \"TSExpressionWithTypeArguments\");\n }\n\n tsParseInterfaceDeclaration(node) {\n if (tokenIsIdentifier(this.state.type)) {\n node.id = this.parseIdentifier();\n this.checkLVal(node.id, \"typescript interface declaration\", BIND_TS_INTERFACE);\n } else {\n node.id = null;\n this.raise(TSErrors.MissingInterfaceName, {\n at: this.state.startLoc\n });\n }\n\n node.typeParameters = this.tsTryParseTypeParameters();\n\n if (this.eat(77)) {\n node.extends = this.tsParseHeritageClause(\"extends\");\n }\n\n const body = this.startNode();\n body.body = this.tsInType(this.tsParseObjectTypeMembers.bind(this));\n node.body = this.finishNode(body, \"TSInterfaceBody\");\n return this.finishNode(node, \"TSInterfaceDeclaration\");\n }\n\n tsParseTypeAliasDeclaration(node) {\n node.id = this.parseIdentifier();\n this.checkLVal(node.id, \"typescript type alias\", BIND_TS_TYPE);\n node.typeParameters = this.tsTryParseTypeParameters();\n node.typeAnnotation = this.tsInType(() => {\n this.expect(29);\n\n if (this.isContextual(107) && this.lookahead().type !== 16) {\n const node = this.startNode();\n this.next();\n return this.finishNode(node, \"TSIntrinsicKeyword\");\n }\n\n return this.tsParseType();\n });\n this.semicolon();\n return this.finishNode(node, \"TSTypeAliasDeclaration\");\n }\n\n tsInNoContext(cb) {\n const oldContext = this.state.context;\n this.state.context = [oldContext[0]];\n\n try {\n return cb();\n } finally {\n this.state.context = oldContext;\n }\n }\n\n tsInType(cb) {\n const oldInType = this.state.inType;\n this.state.inType = true;\n\n try {\n return cb();\n } finally {\n this.state.inType = oldInType;\n }\n }\n\n tsEatThenParseType(token) {\n return !this.match(token) ? undefined : this.tsNextThenParseType();\n }\n\n tsExpectThenParseType(token) {\n return this.tsDoThenParseType(() => this.expect(token));\n }\n\n tsNextThenParseType() {\n return this.tsDoThenParseType(() => this.next());\n }\n\n tsDoThenParseType(cb) {\n return this.tsInType(() => {\n cb();\n return this.tsParseType();\n });\n }\n\n tsParseEnumMember() {\n const node = this.startNode();\n node.id = this.match(125) ? this.parseExprAtom() : this.parseIdentifier(true);\n\n if (this.eat(29)) {\n node.initializer = this.parseMaybeAssignAllowIn();\n }\n\n return this.finishNode(node, \"TSEnumMember\");\n }\n\n tsParseEnumDeclaration(node, isConst) {\n if (isConst) node.const = true;\n node.id = this.parseIdentifier();\n this.checkLVal(node.id, \"typescript enum declaration\", isConst ? BIND_TS_CONST_ENUM : BIND_TS_ENUM);\n this.expect(5);\n node.members = this.tsParseDelimitedList(\"EnumMembers\", this.tsParseEnumMember.bind(this));\n this.expect(8);\n return this.finishNode(node, \"TSEnumDeclaration\");\n }\n\n tsParseModuleBlock() {\n const node = this.startNode();\n this.scope.enter(SCOPE_OTHER);\n this.expect(5);\n this.parseBlockOrModuleBlockBody(node.body = [], undefined, true, 8);\n this.scope.exit();\n return this.finishNode(node, \"TSModuleBlock\");\n }\n\n tsParseModuleOrNamespaceDeclaration(node, nested = false) {\n node.id = this.parseIdentifier();\n\n if (!nested) {\n this.checkLVal(node.id, \"module or namespace declaration\", BIND_TS_NAMESPACE);\n }\n\n if (this.eat(16)) {\n const inner = this.startNode();\n this.tsParseModuleOrNamespaceDeclaration(inner, true);\n node.body = inner;\n } else {\n this.scope.enter(SCOPE_TS_MODULE);\n this.prodParam.enter(PARAM);\n node.body = this.tsParseModuleBlock();\n this.prodParam.exit();\n this.scope.exit();\n }\n\n return this.finishNode(node, \"TSModuleDeclaration\");\n }\n\n tsParseAmbientExternalModuleDeclaration(node) {\n if (this.isContextual(105)) {\n node.global = true;\n node.id = this.parseIdentifier();\n } else if (this.match(125)) {\n node.id = this.parseExprAtom();\n } else {\n this.unexpected();\n }\n\n if (this.match(5)) {\n this.scope.enter(SCOPE_TS_MODULE);\n this.prodParam.enter(PARAM);\n node.body = this.tsParseModuleBlock();\n this.prodParam.exit();\n this.scope.exit();\n } else {\n this.semicolon();\n }\n\n return this.finishNode(node, \"TSModuleDeclaration\");\n }\n\n tsParseImportEqualsDeclaration(node, isExport) {\n node.isExport = isExport || false;\n node.id = this.parseIdentifier();\n this.checkLVal(node.id, \"import equals declaration\", BIND_LEXICAL);\n this.expect(29);\n const moduleReference = this.tsParseModuleReference();\n\n if (node.importKind === \"type\" && moduleReference.type !== \"TSExternalModuleReference\") {\n this.raise(TSErrors.ImportAliasHasImportType, {\n node: moduleReference\n });\n }\n\n node.moduleReference = moduleReference;\n this.semicolon();\n return this.finishNode(node, \"TSImportEqualsDeclaration\");\n }\n\n tsIsExternalModuleReference() {\n return this.isContextual(112) && this.lookaheadCharCode() === 40;\n }\n\n tsParseModuleReference() {\n return this.tsIsExternalModuleReference() ? this.tsParseExternalModuleReference() : this.tsParseEntityName(false);\n }\n\n tsParseExternalModuleReference() {\n const node = this.startNode();\n this.expectContextual(112);\n this.expect(10);\n\n if (!this.match(125)) {\n throw this.unexpected();\n }\n\n node.expression = this.parseExprAtom();\n this.expect(11);\n return this.finishNode(node, \"TSExternalModuleReference\");\n }\n\n tsLookAhead(f) {\n const state = this.state.clone();\n const res = f();\n this.state = state;\n return res;\n }\n\n tsTryParseAndCatch(f) {\n const result = this.tryParse(abort => f() || abort());\n if (result.aborted || !result.node) return undefined;\n if (result.error) this.state = result.failState;\n return result.node;\n }\n\n tsTryParse(f) {\n const state = this.state.clone();\n const result = f();\n\n if (result !== undefined && result !== false) {\n return result;\n } else {\n this.state = state;\n return undefined;\n }\n }\n\n tsTryParseDeclare(nany) {\n if (this.isLineTerminator()) {\n return;\n }\n\n let starttype = this.state.type;\n let kind;\n\n if (this.isContextual(95)) {\n starttype = 70;\n kind = \"let\";\n }\n\n return this.tsInAmbientContext(() => {\n switch (starttype) {\n case 64:\n nany.declare = true;\n return this.parseFunctionStatement(nany, false, true);\n\n case 76:\n nany.declare = true;\n return this.parseClass(nany, true, false);\n\n case 71:\n if (this.match(71) && this.isLookaheadContextual(\"enum\")) {\n this.expect(71);\n this.expectContextual(118);\n return this.tsParseEnumDeclaration(nany, true);\n }\n\n case 70:\n kind = kind || this.state.value;\n return this.parseVarStatement(nany, kind);\n\n case 105:\n return this.tsParseAmbientExternalModuleDeclaration(nany);\n\n default:\n {\n if (tokenIsIdentifier(starttype)) {\n return this.tsParseDeclaration(nany, this.state.value, true);\n }\n }\n }\n });\n }\n\n tsTryParseExportDeclaration() {\n return this.tsParseDeclaration(this.startNode(), this.state.value, true);\n }\n\n tsParseExpressionStatement(node, expr) {\n switch (expr.name) {\n case \"declare\":\n {\n const declaration = this.tsTryParseDeclare(node);\n\n if (declaration) {\n declaration.declare = true;\n return declaration;\n }\n\n break;\n }\n\n case \"global\":\n if (this.match(5)) {\n this.scope.enter(SCOPE_TS_MODULE);\n this.prodParam.enter(PARAM);\n const mod = node;\n mod.global = true;\n mod.id = expr;\n mod.body = this.tsParseModuleBlock();\n this.scope.exit();\n this.prodParam.exit();\n return this.finishNode(mod, \"TSModuleDeclaration\");\n }\n\n break;\n\n default:\n return this.tsParseDeclaration(node, expr.name, false);\n }\n }\n\n tsParseDeclaration(node, value, next) {\n switch (value) {\n case \"abstract\":\n if (this.tsCheckLineTerminator(next) && (this.match(76) || tokenIsIdentifier(this.state.type))) {\n return this.tsParseAbstractDeclaration(node);\n }\n\n break;\n\n case \"enum\":\n if (next || tokenIsIdentifier(this.state.type)) {\n if (next) this.next();\n return this.tsParseEnumDeclaration(node, false);\n }\n\n break;\n\n case \"interface\":\n if (this.tsCheckLineTerminator(next) && tokenIsIdentifier(this.state.type)) {\n return this.tsParseInterfaceDeclaration(node);\n }\n\n break;\n\n case \"module\":\n if (this.tsCheckLineTerminator(next)) {\n if (this.match(125)) {\n return this.tsParseAmbientExternalModuleDeclaration(node);\n } else if (tokenIsIdentifier(this.state.type)) {\n return this.tsParseModuleOrNamespaceDeclaration(node);\n }\n }\n\n break;\n\n case \"namespace\":\n if (this.tsCheckLineTerminator(next) && tokenIsIdentifier(this.state.type)) {\n return this.tsParseModuleOrNamespaceDeclaration(node);\n }\n\n break;\n\n case \"type\":\n if (this.tsCheckLineTerminator(next) && tokenIsIdentifier(this.state.type)) {\n return this.tsParseTypeAliasDeclaration(node);\n }\n\n break;\n }\n }\n\n tsCheckLineTerminator(next) {\n if (next) {\n if (this.hasFollowingLineBreak()) return false;\n this.next();\n return true;\n }\n\n return !this.isLineTerminator();\n }\n\n tsTryParseGenericAsyncArrowFunction(startPos, startLoc) {\n if (!this.match(45)) {\n return undefined;\n }\n\n const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;\n this.state.maybeInArrowParameters = true;\n const res = this.tsTryParseAndCatch(() => {\n const node = this.startNodeAt(startPos, startLoc);\n node.typeParameters = this.tsParseTypeParameters();\n super.parseFunctionParams(node);\n node.returnType = this.tsTryParseTypeOrTypePredicateAnnotation();\n this.expect(19);\n return node;\n });\n this.state.maybeInArrowParameters = oldMaybeInArrowParameters;\n\n if (!res) {\n return undefined;\n }\n\n return this.parseArrowExpression(res, null, true);\n }\n\n tsParseTypeArguments() {\n const node = this.startNode();\n node.params = this.tsInType(() => this.tsInNoContext(() => {\n this.expect(45);\n return this.tsParseDelimitedList(\"TypeParametersOrArguments\", this.tsParseType.bind(this));\n }));\n\n if (node.params.length === 0) {\n this.raise(TSErrors.EmptyTypeArguments, {\n node\n });\n }\n\n this.expect(46);\n return this.finishNode(node, \"TSTypeParameterInstantiation\");\n }\n\n tsIsDeclarationStart() {\n return tokenIsTSDeclarationStart(this.state.type);\n }\n\n isExportDefaultSpecifier() {\n if (this.tsIsDeclarationStart()) return false;\n return super.isExportDefaultSpecifier();\n }\n\n parseAssignableListItem(allowModifiers, decorators) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let accessibility;\n let readonly = false;\n let override = false;\n\n if (allowModifiers !== undefined) {\n const modified = {};\n this.tsParseModifiers(modified, [\"public\", \"private\", \"protected\", \"override\", \"readonly\"]);\n accessibility = modified.accessibility;\n override = modified.override;\n readonly = modified.readonly;\n\n if (allowModifiers === false && (accessibility || readonly || override)) {\n this.raise(TSErrors.UnexpectedParameterModifier, {\n at: startLoc\n });\n }\n }\n\n const left = this.parseMaybeDefault();\n this.parseAssignableListItemTypes(left);\n const elt = this.parseMaybeDefault(left.start, left.loc.start, left);\n\n if (accessibility || readonly || override) {\n const pp = this.startNodeAt(startPos, startLoc);\n\n if (decorators.length) {\n pp.decorators = decorators;\n }\n\n if (accessibility) pp.accessibility = accessibility;\n if (readonly) pp.readonly = readonly;\n if (override) pp.override = override;\n\n if (elt.type !== \"Identifier\" && elt.type !== \"AssignmentPattern\") {\n this.raise(TSErrors.UnsupportedParameterPropertyKind, {\n node: pp\n });\n }\n\n pp.parameter = elt;\n return this.finishNode(pp, \"TSParameterProperty\");\n }\n\n if (decorators.length) {\n left.decorators = decorators;\n }\n\n return elt;\n }\n\n parseFunctionBodyAndFinish(node, type, isMethod = false) {\n if (this.match(14)) {\n node.returnType = this.tsParseTypeOrTypePredicateAnnotation(14);\n }\n\n const bodilessType = type === \"FunctionDeclaration\" ? \"TSDeclareFunction\" : type === \"ClassMethod\" || type === \"ClassPrivateMethod\" ? \"TSDeclareMethod\" : undefined;\n\n if (bodilessType && !this.match(5) && this.isLineTerminator()) {\n this.finishNode(node, bodilessType);\n return;\n }\n\n if (bodilessType === \"TSDeclareFunction\" && this.state.isAmbientContext) {\n this.raise(TSErrors.DeclareFunctionHasImplementation, {\n node\n });\n\n if (node.declare) {\n super.parseFunctionBodyAndFinish(node, bodilessType, isMethod);\n return;\n }\n }\n\n super.parseFunctionBodyAndFinish(node, type, isMethod);\n }\n\n registerFunctionStatementId(node) {\n if (!node.body && node.id) {\n this.checkLVal(node.id, \"function name\", BIND_TS_AMBIENT);\n } else {\n super.registerFunctionStatementId(...arguments);\n }\n }\n\n tsCheckForInvalidTypeCasts(items) {\n items.forEach(node => {\n if ((node == null ? void 0 : node.type) === \"TSTypeCastExpression\") {\n this.raise(TSErrors.UnexpectedTypeAnnotation, {\n node: node.typeAnnotation\n });\n }\n });\n }\n\n toReferencedList(exprList, isInParens) {\n this.tsCheckForInvalidTypeCasts(exprList);\n return exprList;\n }\n\n parseArrayLike(...args) {\n const node = super.parseArrayLike(...args);\n\n if (node.type === \"ArrayExpression\") {\n this.tsCheckForInvalidTypeCasts(node.elements);\n }\n\n return node;\n }\n\n parseSubscript(base, startPos, startLoc, noCalls, state) {\n if (!this.hasPrecedingLineBreak() && this.match(35)) {\n this.state.canStartJSXElement = false;\n this.next();\n const nonNullExpression = this.startNodeAt(startPos, startLoc);\n nonNullExpression.expression = base;\n return this.finishNode(nonNullExpression, \"TSNonNullExpression\");\n }\n\n let isOptionalCall = false;\n\n if (this.match(18) && this.lookaheadCharCode() === 60) {\n if (noCalls) {\n state.stop = true;\n return base;\n }\n\n state.optionalChainMember = isOptionalCall = true;\n this.next();\n }\n\n if (this.match(45)) {\n let missingParenErrorLoc;\n const result = this.tsTryParseAndCatch(() => {\n if (!noCalls && this.atPossibleAsyncArrow(base)) {\n const asyncArrowFn = this.tsTryParseGenericAsyncArrowFunction(startPos, startLoc);\n\n if (asyncArrowFn) {\n return asyncArrowFn;\n }\n }\n\n const node = this.startNodeAt(startPos, startLoc);\n node.callee = base;\n const typeArguments = this.tsParseTypeArguments();\n\n if (typeArguments) {\n if (isOptionalCall && !this.match(10)) {\n missingParenErrorLoc = this.state.curPosition();\n this.unexpected();\n }\n\n if (!noCalls && this.eat(10)) {\n node.arguments = this.parseCallExpressionArguments(11, false);\n this.tsCheckForInvalidTypeCasts(node.arguments);\n node.typeParameters = typeArguments;\n\n if (state.optionalChainMember) {\n node.optional = isOptionalCall;\n }\n\n return this.finishCallExpression(node, state.optionalChainMember);\n } else if (tokenIsTemplate(this.state.type)) {\n const result = this.parseTaggedTemplateExpression(base, startPos, startLoc, state);\n result.typeParameters = typeArguments;\n return result;\n }\n }\n\n this.unexpected();\n });\n\n if (missingParenErrorLoc) {\n this.unexpected(missingParenErrorLoc, 10);\n }\n\n if (result) return result;\n }\n\n return super.parseSubscript(base, startPos, startLoc, noCalls, state);\n }\n\n parseNewArguments(node) {\n if (this.match(45)) {\n const typeParameters = this.tsTryParseAndCatch(() => {\n const args = this.tsParseTypeArguments();\n if (!this.match(10)) this.unexpected();\n return args;\n });\n\n if (typeParameters) {\n node.typeParameters = typeParameters;\n }\n }\n\n super.parseNewArguments(node);\n }\n\n parseExprOp(left, leftStartPos, leftStartLoc, minPrec) {\n if (tokenOperatorPrecedence(54) > minPrec && !this.hasPrecedingLineBreak() && this.isContextual(89)) {\n const node = this.startNodeAt(leftStartPos, leftStartLoc);\n node.expression = left;\n\n const _const = this.tsTryNextParseConstantContext();\n\n if (_const) {\n node.typeAnnotation = _const;\n } else {\n node.typeAnnotation = this.tsNextThenParseType();\n }\n\n this.finishNode(node, \"TSAsExpression\");\n this.reScan_lt_gt();\n return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec);\n }\n\n return super.parseExprOp(left, leftStartPos, leftStartLoc, minPrec);\n }\n\n checkReservedWord(word, startLoc, checkKeywords, isBinding) {}\n\n checkDuplicateExports() {}\n\n parseImport(node) {\n node.importKind = \"value\";\n\n if (tokenIsIdentifier(this.state.type) || this.match(51) || this.match(5)) {\n let ahead = this.lookahead();\n\n if (this.isContextual(122) && ahead.type !== 12 && ahead.type !== 93 && ahead.type !== 29) {\n node.importKind = \"type\";\n this.next();\n ahead = this.lookahead();\n }\n\n if (tokenIsIdentifier(this.state.type) && ahead.type === 29) {\n return this.tsParseImportEqualsDeclaration(node);\n }\n }\n\n const importNode = super.parseImport(node);\n\n if (importNode.importKind === \"type\" && importNode.specifiers.length > 1 && importNode.specifiers[0].type === \"ImportDefaultSpecifier\") {\n this.raise(TSErrors.TypeImportCannotSpecifyDefaultAndNamed, {\n node: importNode\n });\n }\n\n return importNode;\n }\n\n parseExport(node) {\n if (this.match(79)) {\n this.next();\n\n if (this.isContextual(122) && this.lookaheadCharCode() !== 61) {\n node.importKind = \"type\";\n this.next();\n } else {\n node.importKind = \"value\";\n }\n\n return this.tsParseImportEqualsDeclaration(node, true);\n } else if (this.eat(29)) {\n const assign = node;\n assign.expression = this.parseExpression();\n this.semicolon();\n return this.finishNode(assign, \"TSExportAssignment\");\n } else if (this.eatContextual(89)) {\n const decl = node;\n this.expectContextual(120);\n decl.id = this.parseIdentifier();\n this.semicolon();\n return this.finishNode(decl, \"TSNamespaceExportDeclaration\");\n } else {\n if (this.isContextual(122) && this.lookahead().type === 5) {\n this.next();\n node.exportKind = \"type\";\n } else {\n node.exportKind = \"value\";\n }\n\n return super.parseExport(node);\n }\n }\n\n isAbstractClass() {\n return this.isContextual(116) && this.lookahead().type === 76;\n }\n\n parseExportDefaultExpression() {\n if (this.isAbstractClass()) {\n const cls = this.startNode();\n this.next();\n cls.abstract = true;\n this.parseClass(cls, true, true);\n return cls;\n }\n\n if (this.match(121)) {\n const interfaceNode = this.startNode();\n this.next();\n const result = this.tsParseInterfaceDeclaration(interfaceNode);\n if (result) return result;\n }\n\n return super.parseExportDefaultExpression();\n }\n\n parseStatementContent(context, topLevel) {\n if (this.state.type === 71) {\n const ahead = this.lookahead();\n\n if (ahead.type === 118) {\n const node = this.startNode();\n this.next();\n this.expectContextual(118);\n return this.tsParseEnumDeclaration(node, true);\n }\n }\n\n return super.parseStatementContent(context, topLevel);\n }\n\n parseAccessModifier() {\n return this.tsParseModifier([\"public\", \"protected\", \"private\"]);\n }\n\n tsHasSomeModifiers(member, modifiers) {\n return modifiers.some(modifier => {\n if (tsIsAccessModifier(modifier)) {\n return member.accessibility === modifier;\n }\n\n return !!member[modifier];\n });\n }\n\n tsIsStartOfStaticBlocks() {\n return this.isContextual(100) && this.lookaheadCharCode() === 123;\n }\n\n parseClassMember(classBody, member, state) {\n const modifiers = [\"declare\", \"private\", \"public\", \"protected\", \"override\", \"abstract\", \"readonly\", \"static\"];\n this.tsParseModifiers(member, modifiers, undefined, undefined, true);\n\n const callParseClassMemberWithIsStatic = () => {\n if (this.tsIsStartOfStaticBlocks()) {\n this.next();\n this.next();\n\n if (this.tsHasSomeModifiers(member, modifiers)) {\n this.raise(TSErrors.StaticBlockCannotHaveModifier, {\n at: this.state.curPosition()\n });\n }\n\n this.parseClassStaticBlock(classBody, member);\n } else {\n this.parseClassMemberWithIsStatic(classBody, member, state, !!member.static);\n }\n };\n\n if (member.declare) {\n this.tsInAmbientContext(callParseClassMemberWithIsStatic);\n } else {\n callParseClassMemberWithIsStatic();\n }\n }\n\n parseClassMemberWithIsStatic(classBody, member, state, isStatic) {\n const idx = this.tsTryParseIndexSignature(member);\n\n if (idx) {\n classBody.body.push(idx);\n\n if (member.abstract) {\n this.raise(TSErrors.IndexSignatureHasAbstract, {\n node: member\n });\n }\n\n if (member.accessibility) {\n this.raise(TSErrors.IndexSignatureHasAccessibility, {\n node: member\n }, member.accessibility);\n }\n\n if (member.declare) {\n this.raise(TSErrors.IndexSignatureHasDeclare, {\n node: member\n });\n }\n\n if (member.override) {\n this.raise(TSErrors.IndexSignatureHasOverride, {\n node: member\n });\n }\n\n return;\n }\n\n if (!this.state.inAbstractClass && member.abstract) {\n this.raise(TSErrors.NonAbstractClassHasAbstractMethod, {\n node: member\n });\n }\n\n if (member.override) {\n if (!state.hadSuperClass) {\n this.raise(TSErrors.OverrideNotInSubClass, {\n node: member\n });\n }\n }\n\n super.parseClassMemberWithIsStatic(classBody, member, state, isStatic);\n }\n\n parsePostMemberNameModifiers(methodOrProp) {\n const optional = this.eat(17);\n if (optional) methodOrProp.optional = true;\n\n if (methodOrProp.readonly && this.match(10)) {\n this.raise(TSErrors.ClassMethodHasReadonly, {\n node: methodOrProp\n });\n }\n\n if (methodOrProp.declare && this.match(10)) {\n this.raise(TSErrors.ClassMethodHasDeclare, {\n node: methodOrProp\n });\n }\n }\n\n parseExpressionStatement(node, expr) {\n const decl = expr.type === \"Identifier\" ? this.tsParseExpressionStatement(node, expr) : undefined;\n return decl || super.parseExpressionStatement(node, expr);\n }\n\n shouldParseExportDeclaration() {\n if (this.tsIsDeclarationStart()) return true;\n return super.shouldParseExportDeclaration();\n }\n\n parseConditional(expr, startPos, startLoc, refExpressionErrors) {\n if (!this.state.maybeInArrowParameters || !this.match(17)) {\n return super.parseConditional(expr, startPos, startLoc, refExpressionErrors);\n }\n\n const result = this.tryParse(() => super.parseConditional(expr, startPos, startLoc));\n\n if (!result.node) {\n if (result.error) {\n super.setOptionalParametersError(refExpressionErrors, result.error);\n }\n\n return expr;\n }\n\n if (result.error) this.state = result.failState;\n return result.node;\n }\n\n parseParenItem(node, startPos, startLoc) {\n node = super.parseParenItem(node, startPos, startLoc);\n\n if (this.eat(17)) {\n node.optional = true;\n this.resetEndLocation(node);\n }\n\n if (this.match(14)) {\n const typeCastNode = this.startNodeAt(startPos, startLoc);\n typeCastNode.expression = node;\n typeCastNode.typeAnnotation = this.tsParseTypeAnnotation();\n return this.finishNode(typeCastNode, \"TSTypeCastExpression\");\n }\n\n return node;\n }\n\n parseExportDeclaration(node) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const isDeclare = this.eatContextual(117);\n\n if (isDeclare && (this.isContextual(117) || !this.shouldParseExportDeclaration())) {\n throw this.raise(TSErrors.ExpectedAmbientAfterExportDeclare, {\n at: this.state.startLoc\n });\n }\n\n let declaration;\n\n if (tokenIsIdentifier(this.state.type)) {\n declaration = this.tsTryParseExportDeclaration();\n }\n\n if (!declaration) {\n declaration = super.parseExportDeclaration(node);\n }\n\n if (declaration && (declaration.type === \"TSInterfaceDeclaration\" || declaration.type === \"TSTypeAliasDeclaration\" || isDeclare)) {\n node.exportKind = \"type\";\n }\n\n if (declaration && isDeclare) {\n this.resetStartLocation(declaration, startPos, startLoc);\n declaration.declare = true;\n }\n\n return declaration;\n }\n\n parseClassId(node, isStatement, optionalId) {\n if ((!isStatement || optionalId) && this.isContextual(106)) {\n return;\n }\n\n super.parseClassId(node, isStatement, optionalId, node.declare ? BIND_TS_AMBIENT : BIND_CLASS);\n const typeParameters = this.tsTryParseTypeParameters();\n if (typeParameters) node.typeParameters = typeParameters;\n }\n\n parseClassPropertyAnnotation(node) {\n if (!node.optional && this.eat(35)) {\n node.definite = true;\n }\n\n const type = this.tsTryParseTypeAnnotation();\n if (type) node.typeAnnotation = type;\n }\n\n parseClassProperty(node) {\n this.parseClassPropertyAnnotation(node);\n\n if (this.state.isAmbientContext && this.match(29)) {\n this.raise(TSErrors.DeclareClassFieldHasInitializer, {\n at: this.state.startLoc\n });\n }\n\n if (node.abstract && this.match(29)) {\n const {\n key\n } = node;\n this.raise(TSErrors.AbstractPropertyHasInitializer, {\n at: this.state.startLoc\n }, key.type === \"Identifier\" && !node.computed ? key.name : `[${this.input.slice(key.start, key.end)}]`);\n }\n\n return super.parseClassProperty(node);\n }\n\n parseClassPrivateProperty(node) {\n if (node.abstract) {\n this.raise(TSErrors.PrivateElementHasAbstract, {\n node\n });\n }\n\n if (node.accessibility) {\n this.raise(TSErrors.PrivateElementHasAccessibility, {\n node\n }, node.accessibility);\n }\n\n this.parseClassPropertyAnnotation(node);\n return super.parseClassPrivateProperty(node);\n }\n\n pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper) {\n const typeParameters = this.tsTryParseTypeParameters();\n\n if (typeParameters && isConstructor) {\n this.raise(TSErrors.ConstructorHasTypeParameters, {\n node: typeParameters\n });\n }\n\n if (method.declare && (method.kind === \"get\" || method.kind === \"set\")) {\n this.raise(TSErrors.DeclareAccessor, {\n node: method\n }, method.kind);\n }\n\n if (typeParameters) method.typeParameters = typeParameters;\n super.pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper);\n }\n\n pushClassPrivateMethod(classBody, method, isGenerator, isAsync) {\n const typeParameters = this.tsTryParseTypeParameters();\n if (typeParameters) method.typeParameters = typeParameters;\n super.pushClassPrivateMethod(classBody, method, isGenerator, isAsync);\n }\n\n declareClassPrivateMethodInScope(node, kind) {\n if (node.type === \"TSDeclareMethod\") return;\n if (node.type === \"MethodDefinition\" && !node.value.body) return;\n super.declareClassPrivateMethodInScope(node, kind);\n }\n\n parseClassSuper(node) {\n super.parseClassSuper(node);\n\n if (node.superClass && this.match(45)) {\n node.superTypeParameters = this.tsParseTypeArguments();\n }\n\n if (this.eatContextual(106)) {\n node.implements = this.tsParseHeritageClause(\"implements\");\n }\n }\n\n parseObjPropValue(prop, ...args) {\n const typeParameters = this.tsTryParseTypeParameters();\n if (typeParameters) prop.typeParameters = typeParameters;\n super.parseObjPropValue(prop, ...args);\n }\n\n parseFunctionParams(node, allowModifiers) {\n const typeParameters = this.tsTryParseTypeParameters();\n if (typeParameters) node.typeParameters = typeParameters;\n super.parseFunctionParams(node, allowModifiers);\n }\n\n parseVarId(decl, kind) {\n super.parseVarId(decl, kind);\n\n if (decl.id.type === \"Identifier\" && !this.hasPrecedingLineBreak() && this.eat(35)) {\n decl.definite = true;\n }\n\n const type = this.tsTryParseTypeAnnotation();\n\n if (type) {\n decl.id.typeAnnotation = type;\n this.resetEndLocation(decl.id);\n }\n }\n\n parseAsyncArrowFromCallExpression(node, call) {\n if (this.match(14)) {\n node.returnType = this.tsParseTypeAnnotation();\n }\n\n return super.parseAsyncArrowFromCallExpression(node, call);\n }\n\n parseMaybeAssign(...args) {\n var _jsx, _jsx2, _typeCast, _jsx3, _typeCast2, _jsx4, _typeCast3;\n\n let state;\n let jsx;\n let typeCast;\n\n if (this.hasPlugin(\"jsx\") && (this.match(134) || this.match(45))) {\n state = this.state.clone();\n jsx = this.tryParse(() => super.parseMaybeAssign(...args), state);\n if (!jsx.error) return jsx.node;\n const {\n context\n } = this.state;\n const currentContext = context[context.length - 1];\n\n if (currentContext === types.j_oTag || currentContext === types.j_expr) {\n context.pop();\n }\n }\n\n if (!((_jsx = jsx) != null && _jsx.error) && !this.match(45)) {\n return super.parseMaybeAssign(...args);\n }\n\n let typeParameters;\n state = state || this.state.clone();\n const arrow = this.tryParse(abort => {\n var _expr$extra, _typeParameters;\n\n typeParameters = this.tsParseTypeParameters();\n const expr = super.parseMaybeAssign(...args);\n\n if (expr.type !== \"ArrowFunctionExpression\" || (_expr$extra = expr.extra) != null && _expr$extra.parenthesized) {\n abort();\n }\n\n if (((_typeParameters = typeParameters) == null ? void 0 : _typeParameters.params.length) !== 0) {\n this.resetStartLocationFromNode(expr, typeParameters);\n }\n\n expr.typeParameters = typeParameters;\n return expr;\n }, state);\n\n if (!arrow.error && !arrow.aborted) {\n if (typeParameters) this.reportReservedArrowTypeParam(typeParameters);\n return arrow.node;\n }\n\n if (!jsx) {\n assert(!this.hasPlugin(\"jsx\"));\n typeCast = this.tryParse(() => super.parseMaybeAssign(...args), state);\n if (!typeCast.error) return typeCast.node;\n }\n\n if ((_jsx2 = jsx) != null && _jsx2.node) {\n this.state = jsx.failState;\n return jsx.node;\n }\n\n if (arrow.node) {\n this.state = arrow.failState;\n if (typeParameters) this.reportReservedArrowTypeParam(typeParameters);\n return arrow.node;\n }\n\n if ((_typeCast = typeCast) != null && _typeCast.node) {\n this.state = typeCast.failState;\n return typeCast.node;\n }\n\n if ((_jsx3 = jsx) != null && _jsx3.thrown) throw jsx.error;\n if (arrow.thrown) throw arrow.error;\n if ((_typeCast2 = typeCast) != null && _typeCast2.thrown) throw typeCast.error;\n throw ((_jsx4 = jsx) == null ? void 0 : _jsx4.error) || arrow.error || ((_typeCast3 = typeCast) == null ? void 0 : _typeCast3.error);\n }\n\n reportReservedArrowTypeParam(node) {\n var _node$extra;\n\n if (node.params.length === 1 && !((_node$extra = node.extra) != null && _node$extra.trailingComma) && this.getPluginOption(\"typescript\", \"disallowAmbiguousJSXLike\")) {\n this.raise(TSErrors.ReservedArrowTypeParam, {\n node\n });\n }\n }\n\n parseMaybeUnary(refExpressionErrors) {\n if (!this.hasPlugin(\"jsx\") && this.match(45)) {\n return this.tsParseTypeAssertion();\n } else {\n return super.parseMaybeUnary(refExpressionErrors);\n }\n }\n\n parseArrow(node) {\n if (this.match(14)) {\n const result = this.tryParse(abort => {\n const returnType = this.tsParseTypeOrTypePredicateAnnotation(14);\n if (this.canInsertSemicolon() || !this.match(19)) abort();\n return returnType;\n });\n if (result.aborted) return;\n\n if (!result.thrown) {\n if (result.error) this.state = result.failState;\n node.returnType = result.node;\n }\n }\n\n return super.parseArrow(node);\n }\n\n parseAssignableListItemTypes(param) {\n if (this.eat(17)) {\n if (param.type !== \"Identifier\" && !this.state.isAmbientContext && !this.state.inType) {\n this.raise(TSErrors.PatternIsOptional, {\n node: param\n });\n }\n\n param.optional = true;\n }\n\n const type = this.tsTryParseTypeAnnotation();\n if (type) param.typeAnnotation = type;\n this.resetEndLocation(param);\n return param;\n }\n\n isAssignable(node, isBinding) {\n switch (node.type) {\n case \"TSTypeCastExpression\":\n return this.isAssignable(node.expression, isBinding);\n\n case \"TSParameterProperty\":\n return true;\n\n default:\n return super.isAssignable(node, isBinding);\n }\n }\n\n toAssignable(node, isLHS = false) {\n switch (node.type) {\n case \"TSTypeCastExpression\":\n return super.toAssignable(this.typeCastToParameter(node), isLHS);\n\n case \"TSParameterProperty\":\n return super.toAssignable(node, isLHS);\n\n case \"ParenthesizedExpression\":\n return this.toAssignableParenthesizedExpression(node, isLHS);\n\n case \"TSAsExpression\":\n case \"TSNonNullExpression\":\n case \"TSTypeAssertion\":\n node.expression = this.toAssignable(node.expression, isLHS);\n return node;\n\n default:\n return super.toAssignable(node, isLHS);\n }\n }\n\n toAssignableParenthesizedExpression(node, isLHS) {\n switch (node.expression.type) {\n case \"TSAsExpression\":\n case \"TSNonNullExpression\":\n case \"TSTypeAssertion\":\n case \"ParenthesizedExpression\":\n node.expression = this.toAssignable(node.expression, isLHS);\n return node;\n\n default:\n return super.toAssignable(node, isLHS);\n }\n }\n\n checkLVal(expr, contextDescription, ...args) {\n var _expr$extra2;\n\n switch (expr.type) {\n case \"TSTypeCastExpression\":\n return;\n\n case \"TSParameterProperty\":\n this.checkLVal(expr.parameter, \"parameter property\", ...args);\n return;\n\n case \"TSAsExpression\":\n case \"TSTypeAssertion\":\n if (!args[0] && contextDescription !== \"parenthesized expression\" && !((_expr$extra2 = expr.extra) != null && _expr$extra2.parenthesized)) {\n this.raise(ErrorMessages.InvalidLhs, {\n node: expr\n }, contextDescription);\n break;\n }\n\n this.checkLVal(expr.expression, \"parenthesized expression\", ...args);\n return;\n\n case \"TSNonNullExpression\":\n this.checkLVal(expr.expression, contextDescription, ...args);\n return;\n\n default:\n super.checkLVal(expr, contextDescription, ...args);\n return;\n }\n }\n\n parseBindingAtom() {\n switch (this.state.type) {\n case 74:\n return this.parseIdentifier(true);\n\n default:\n return super.parseBindingAtom();\n }\n }\n\n parseMaybeDecoratorArguments(expr) {\n if (this.match(45)) {\n const typeArguments = this.tsParseTypeArguments();\n\n if (this.match(10)) {\n const call = super.parseMaybeDecoratorArguments(expr);\n call.typeParameters = typeArguments;\n return call;\n }\n\n this.unexpected(null, 10);\n }\n\n return super.parseMaybeDecoratorArguments(expr);\n }\n\n checkCommaAfterRest(close) {\n if (this.state.isAmbientContext && this.match(12) && this.lookaheadCharCode() === close) {\n this.next();\n return false;\n } else {\n return super.checkCommaAfterRest(close);\n }\n }\n\n isClassMethod() {\n return this.match(45) || super.isClassMethod();\n }\n\n isClassProperty() {\n return this.match(35) || this.match(14) || super.isClassProperty();\n }\n\n parseMaybeDefault(...args) {\n const node = super.parseMaybeDefault(...args);\n\n if (node.type === \"AssignmentPattern\" && node.typeAnnotation && node.right.start < node.typeAnnotation.start) {\n this.raise(TSErrors.TypeAnnotationAfterAssign, {\n node: node.typeAnnotation\n });\n }\n\n return node;\n }\n\n getTokenFromCode(code) {\n if (this.state.inType) {\n if (code === 62) {\n return this.finishOp(46, 1);\n }\n\n if (code === 60) {\n return this.finishOp(45, 1);\n }\n }\n\n return super.getTokenFromCode(code);\n }\n\n reScan_lt_gt() {\n const {\n type\n } = this.state;\n\n if (type === 45) {\n this.state.pos -= 1;\n this.readToken_lt();\n } else if (type === 46) {\n this.state.pos -= 1;\n this.readToken_gt();\n }\n }\n\n toAssignableList(exprList) {\n for (let i = 0; i < exprList.length; i++) {\n const expr = exprList[i];\n if (!expr) continue;\n\n switch (expr.type) {\n case \"TSTypeCastExpression\":\n exprList[i] = this.typeCastToParameter(expr);\n break;\n\n case \"TSAsExpression\":\n case \"TSTypeAssertion\":\n if (!this.state.maybeInArrowParameters) {\n exprList[i] = this.typeCastToParameter(expr);\n } else {\n this.raise(TSErrors.UnexpectedTypeCastInParameter, {\n node: expr\n });\n }\n\n break;\n }\n }\n\n return super.toAssignableList(...arguments);\n }\n\n typeCastToParameter(node) {\n node.expression.typeAnnotation = node.typeAnnotation;\n this.resetEndLocation(node.expression, node.typeAnnotation.loc.end);\n return node.expression;\n }\n\n shouldParseArrow(params) {\n if (this.match(14)) {\n return params.every(expr => this.isAssignable(expr, true));\n }\n\n return super.shouldParseArrow(params);\n }\n\n shouldParseAsyncArrow() {\n return this.match(14) || super.shouldParseAsyncArrow();\n }\n\n canHaveLeadingDecorator() {\n return super.canHaveLeadingDecorator() || this.isAbstractClass();\n }\n\n jsxParseOpeningElementAfterName(node) {\n if (this.match(45)) {\n const typeArguments = this.tsTryParseAndCatch(() => this.tsParseTypeArguments());\n if (typeArguments) node.typeParameters = typeArguments;\n }\n\n return super.jsxParseOpeningElementAfterName(node);\n }\n\n getGetterSetterExpectedParamCount(method) {\n const baseCount = super.getGetterSetterExpectedParamCount(method);\n const params = this.getObjectOrClassMethodParams(method);\n const firstParam = params[0];\n const hasContextParam = firstParam && this.isThisParam(firstParam);\n return hasContextParam ? baseCount + 1 : baseCount;\n }\n\n parseCatchClauseParam() {\n const param = super.parseCatchClauseParam();\n const type = this.tsTryParseTypeAnnotation();\n\n if (type) {\n param.typeAnnotation = type;\n this.resetEndLocation(param);\n }\n\n return param;\n }\n\n tsInAmbientContext(cb) {\n const oldIsAmbientContext = this.state.isAmbientContext;\n this.state.isAmbientContext = true;\n\n try {\n return cb();\n } finally {\n this.state.isAmbientContext = oldIsAmbientContext;\n }\n }\n\n parseClass(node, ...args) {\n const oldInAbstractClass = this.state.inAbstractClass;\n this.state.inAbstractClass = !!node.abstract;\n\n try {\n return super.parseClass(node, ...args);\n } finally {\n this.state.inAbstractClass = oldInAbstractClass;\n }\n }\n\n tsParseAbstractDeclaration(node) {\n if (this.match(76)) {\n node.abstract = true;\n return this.parseClass(node, true, false);\n } else if (this.isContextual(121)) {\n if (!this.hasFollowingLineBreak()) {\n node.abstract = true;\n this.raise(TSErrors.NonClassMethodPropertyHasAbstractModifer, {\n node\n });\n this.next();\n return this.tsParseInterfaceDeclaration(node);\n }\n } else {\n this.unexpected(null, 76);\n }\n }\n\n parseMethod(...args) {\n const method = super.parseMethod(...args);\n\n if (method.abstract) {\n const hasBody = this.hasPlugin(\"estree\") ? !!method.value.body : !!method.body;\n\n if (hasBody) {\n const {\n key\n } = method;\n this.raise(TSErrors.AbstractMethodHasImplementation, {\n node: method\n }, key.type === \"Identifier\" && !method.computed ? key.name : `[${this.input.slice(key.start, key.end)}]`);\n }\n }\n\n return method;\n }\n\n tsParseTypeParameterName() {\n const typeName = this.parseIdentifier();\n return typeName.name;\n }\n\n shouldParseAsAmbientContext() {\n return !!this.getPluginOption(\"typescript\", \"dts\");\n }\n\n parse() {\n if (this.shouldParseAsAmbientContext()) {\n this.state.isAmbientContext = true;\n }\n\n return super.parse();\n }\n\n getExpression() {\n if (this.shouldParseAsAmbientContext()) {\n this.state.isAmbientContext = true;\n }\n\n return super.getExpression();\n }\n\n parseExportSpecifier(node, isString, isInTypeExport, isMaybeTypeOnly) {\n if (!isString && isMaybeTypeOnly) {\n this.parseTypeOnlyImportExportSpecifier(node, false, isInTypeExport);\n return this.finishNode(node, \"ExportSpecifier\");\n }\n\n node.exportKind = \"value\";\n return super.parseExportSpecifier(node, isString, isInTypeExport, isMaybeTypeOnly);\n }\n\n parseImportSpecifier(specifier, importedIsString, isInTypeOnlyImport, isMaybeTypeOnly) {\n if (!importedIsString && isMaybeTypeOnly) {\n this.parseTypeOnlyImportExportSpecifier(specifier, true, isInTypeOnlyImport);\n return this.finishNode(specifier, \"ImportSpecifier\");\n }\n\n specifier.importKind = \"value\";\n return super.parseImportSpecifier(specifier, importedIsString, isInTypeOnlyImport, isMaybeTypeOnly);\n }\n\n parseTypeOnlyImportExportSpecifier(node, isImport, isInTypeOnlyImportExport) {\n const leftOfAsKey = isImport ? \"imported\" : \"local\";\n const rightOfAsKey = isImport ? \"local\" : \"exported\";\n let leftOfAs = node[leftOfAsKey];\n let rightOfAs;\n let hasTypeSpecifier = false;\n let canParseAsKeyword = true;\n const loc = leftOfAs.loc.start;\n\n if (this.isContextual(89)) {\n const firstAs = this.parseIdentifier();\n\n if (this.isContextual(89)) {\n const secondAs = this.parseIdentifier();\n\n if (tokenIsKeywordOrIdentifier(this.state.type)) {\n hasTypeSpecifier = true;\n leftOfAs = firstAs;\n rightOfAs = this.parseIdentifier();\n canParseAsKeyword = false;\n } else {\n rightOfAs = secondAs;\n canParseAsKeyword = false;\n }\n } else if (tokenIsKeywordOrIdentifier(this.state.type)) {\n canParseAsKeyword = false;\n rightOfAs = this.parseIdentifier();\n } else {\n hasTypeSpecifier = true;\n leftOfAs = firstAs;\n }\n } else if (tokenIsKeywordOrIdentifier(this.state.type)) {\n hasTypeSpecifier = true;\n leftOfAs = this.parseIdentifier();\n }\n\n if (hasTypeSpecifier && isInTypeOnlyImportExport) {\n this.raise(isImport ? TSErrors.TypeModifierIsUsedInTypeImports : TSErrors.TypeModifierIsUsedInTypeExports, {\n at: loc\n });\n }\n\n node[leftOfAsKey] = leftOfAs;\n node[rightOfAsKey] = rightOfAs;\n const kindKey = isImport ? \"importKind\" : \"exportKind\";\n node[kindKey] = hasTypeSpecifier ? \"type\" : \"value\";\n\n if (canParseAsKeyword && this.eatContextual(89)) {\n node[rightOfAsKey] = isImport ? this.parseIdentifier() : this.parseModuleExportName();\n }\n\n if (!node[rightOfAsKey]) {\n node[rightOfAsKey] = cloneIdentifier(node[leftOfAsKey]);\n }\n\n if (isImport) {\n this.checkLVal(node[rightOfAsKey], \"import specifier\", BIND_LEXICAL);\n }\n }\n\n});\n\nconst PlaceholderErrors = makeErrorTemplates({\n ClassNameIsRequired: \"A class name is required.\"\n}, ErrorCodes.SyntaxError, \"placeholders\");\nvar placeholders = (superClass => class extends superClass {\n parsePlaceholder(expectedNode) {\n if (this.match(136)) {\n const node = this.startNode();\n this.next();\n this.assertNoSpace(\"Unexpected space in placeholder.\");\n node.name = super.parseIdentifier(true);\n this.assertNoSpace(\"Unexpected space in placeholder.\");\n this.expect(136);\n return this.finishPlaceholder(node, expectedNode);\n }\n }\n\n finishPlaceholder(node, expectedNode) {\n const isFinished = !!(node.expectedNode && node.type === \"Placeholder\");\n node.expectedNode = expectedNode;\n return isFinished ? node : this.finishNode(node, \"Placeholder\");\n }\n\n getTokenFromCode(code) {\n if (code === 37 && this.input.charCodeAt(this.state.pos + 1) === 37) {\n return this.finishOp(136, 2);\n }\n\n return super.getTokenFromCode(...arguments);\n }\n\n parseExprAtom() {\n return this.parsePlaceholder(\"Expression\") || super.parseExprAtom(...arguments);\n }\n\n parseIdentifier() {\n return this.parsePlaceholder(\"Identifier\") || super.parseIdentifier(...arguments);\n }\n\n checkReservedWord(word) {\n if (word !== undefined) super.checkReservedWord(...arguments);\n }\n\n parseBindingAtom() {\n return this.parsePlaceholder(\"Pattern\") || super.parseBindingAtom(...arguments);\n }\n\n checkLVal(expr) {\n if (expr.type !== \"Placeholder\") super.checkLVal(...arguments);\n }\n\n toAssignable(node) {\n if (node && node.type === \"Placeholder\" && node.expectedNode === \"Expression\") {\n node.expectedNode = \"Pattern\";\n return node;\n }\n\n return super.toAssignable(...arguments);\n }\n\n isLet(context) {\n if (super.isLet(context)) {\n return true;\n }\n\n if (!this.isContextual(95)) {\n return false;\n }\n\n if (context) return false;\n const nextToken = this.lookahead();\n\n if (nextToken.type === 136) {\n return true;\n }\n\n return false;\n }\n\n verifyBreakContinue(node) {\n if (node.label && node.label.type === \"Placeholder\") return;\n super.verifyBreakContinue(...arguments);\n }\n\n parseExpressionStatement(node, expr) {\n if (expr.type !== \"Placeholder\" || expr.extra && expr.extra.parenthesized) {\n return super.parseExpressionStatement(...arguments);\n }\n\n if (this.match(14)) {\n const stmt = node;\n stmt.label = this.finishPlaceholder(expr, \"Identifier\");\n this.next();\n stmt.body = this.parseStatement(\"label\");\n return this.finishNode(stmt, \"LabeledStatement\");\n }\n\n this.semicolon();\n node.name = expr.name;\n return this.finishPlaceholder(node, \"Statement\");\n }\n\n parseBlock() {\n return this.parsePlaceholder(\"BlockStatement\") || super.parseBlock(...arguments);\n }\n\n parseFunctionId() {\n return this.parsePlaceholder(\"Identifier\") || super.parseFunctionId(...arguments);\n }\n\n parseClass(node, isStatement, optionalId) {\n const type = isStatement ? \"ClassDeclaration\" : \"ClassExpression\";\n this.next();\n this.takeDecorators(node);\n const oldStrict = this.state.strict;\n const placeholder = this.parsePlaceholder(\"Identifier\");\n\n if (placeholder) {\n if (this.match(77) || this.match(136) || this.match(5)) {\n node.id = placeholder;\n } else if (optionalId || !isStatement) {\n node.id = null;\n node.body = this.finishPlaceholder(placeholder, \"ClassBody\");\n return this.finishNode(node, type);\n } else {\n throw this.raise(PlaceholderErrors.ClassNameIsRequired, {\n at: this.state.startLoc\n });\n }\n } else {\n this.parseClassId(node, isStatement, optionalId);\n }\n\n this.parseClassSuper(node);\n node.body = this.parsePlaceholder(\"ClassBody\") || this.parseClassBody(!!node.superClass, oldStrict);\n return this.finishNode(node, type);\n }\n\n parseExport(node) {\n const placeholder = this.parsePlaceholder(\"Identifier\");\n if (!placeholder) return super.parseExport(...arguments);\n\n if (!this.isContextual(93) && !this.match(12)) {\n node.specifiers = [];\n node.source = null;\n node.declaration = this.finishPlaceholder(placeholder, \"Declaration\");\n return this.finishNode(node, \"ExportNamedDeclaration\");\n }\n\n this.expectPlugin(\"exportDefaultFrom\");\n const specifier = this.startNode();\n specifier.exported = placeholder;\n node.specifiers = [this.finishNode(specifier, \"ExportDefaultSpecifier\")];\n return super.parseExport(node);\n }\n\n isExportDefaultSpecifier() {\n if (this.match(61)) {\n const next = this.nextTokenStart();\n\n if (this.isUnparsedContextual(next, \"from\")) {\n if (this.input.startsWith(tokenLabelName(136), this.nextTokenStartSince(next + 4))) {\n return true;\n }\n }\n }\n\n return super.isExportDefaultSpecifier();\n }\n\n maybeParseExportDefaultSpecifier(node) {\n if (node.specifiers && node.specifiers.length > 0) {\n return true;\n }\n\n return super.maybeParseExportDefaultSpecifier(...arguments);\n }\n\n checkExport(node) {\n const {\n specifiers\n } = node;\n\n if (specifiers != null && specifiers.length) {\n node.specifiers = specifiers.filter(node => node.exported.type === \"Placeholder\");\n }\n\n super.checkExport(node);\n node.specifiers = specifiers;\n }\n\n parseImport(node) {\n const placeholder = this.parsePlaceholder(\"Identifier\");\n if (!placeholder) return super.parseImport(...arguments);\n node.specifiers = [];\n\n if (!this.isContextual(93) && !this.match(12)) {\n node.source = this.finishPlaceholder(placeholder, \"StringLiteral\");\n this.semicolon();\n return this.finishNode(node, \"ImportDeclaration\");\n }\n\n const specifier = this.startNodeAtNode(placeholder);\n specifier.local = placeholder;\n this.finishNode(specifier, \"ImportDefaultSpecifier\");\n node.specifiers.push(specifier);\n\n if (this.eat(12)) {\n const hasStarImport = this.maybeParseStarImportSpecifier(node);\n if (!hasStarImport) this.parseNamedImportSpecifiers(node);\n }\n\n this.expectContextual(93);\n node.source = this.parseImportSource();\n this.semicolon();\n return this.finishNode(node, \"ImportDeclaration\");\n }\n\n parseImportSource() {\n return this.parsePlaceholder(\"StringLiteral\") || super.parseImportSource(...arguments);\n }\n\n});\n\nvar v8intrinsic = (superClass => class extends superClass {\n parseV8Intrinsic() {\n if (this.match(50)) {\n const v8IntrinsicStartLoc = this.state.startLoc;\n const node = this.startNode();\n this.next();\n\n if (tokenIsIdentifier(this.state.type)) {\n const name = this.parseIdentifierName(this.state.start);\n const identifier = this.createIdentifier(node, name);\n identifier.type = \"V8IntrinsicIdentifier\";\n\n if (this.match(10)) {\n return identifier;\n }\n }\n\n this.unexpected(v8IntrinsicStartLoc);\n }\n }\n\n parseExprAtom() {\n return this.parseV8Intrinsic() || super.parseExprAtom(...arguments);\n }\n\n});\n\nfunction hasPlugin(plugins, expectedConfig) {\n const [expectedName, expectedOptions] = typeof expectedConfig === \"string\" ? [expectedConfig, {}] : expectedConfig;\n const expectedKeys = Object.keys(expectedOptions);\n const expectedOptionsIsEmpty = expectedKeys.length === 0;\n return plugins.some(p => {\n if (typeof p === \"string\") {\n return expectedOptionsIsEmpty && p === expectedName;\n } else {\n const [pluginName, pluginOptions] = p;\n\n if (pluginName !== expectedName) {\n return false;\n }\n\n for (const key of expectedKeys) {\n if (pluginOptions[key] !== expectedOptions[key]) {\n return false;\n }\n }\n\n return true;\n }\n });\n}\nfunction getPluginOption(plugins, name, option) {\n const plugin = plugins.find(plugin => {\n if (Array.isArray(plugin)) {\n return plugin[0] === name;\n } else {\n return plugin === name;\n }\n });\n\n if (plugin && Array.isArray(plugin)) {\n return plugin[1][option];\n }\n\n return null;\n}\nconst PIPELINE_PROPOSALS = [\"minimal\", \"fsharp\", \"hack\", \"smart\"];\nconst TOPIC_TOKENS = [\"^\", \"%\", \"#\"];\nconst RECORD_AND_TUPLE_SYNTAX_TYPES = [\"hash\", \"bar\"];\nfunction validatePlugins(plugins) {\n if (hasPlugin(plugins, \"decorators\")) {\n if (hasPlugin(plugins, \"decorators-legacy\")) {\n throw new Error(\"Cannot use the decorators and decorators-legacy plugin together\");\n }\n\n const decoratorsBeforeExport = getPluginOption(plugins, \"decorators\", \"decoratorsBeforeExport\");\n\n if (decoratorsBeforeExport == null) {\n throw new Error(\"The 'decorators' plugin requires a 'decoratorsBeforeExport' option,\" + \" whose value must be a boolean. If you are migrating from\" + \" Babylon/Babel 6 or want to use the old decorators proposal, you\" + \" should use the 'decorators-legacy' plugin instead of 'decorators'.\");\n } else if (typeof decoratorsBeforeExport !== \"boolean\") {\n throw new Error(\"'decoratorsBeforeExport' must be a boolean.\");\n }\n }\n\n if (hasPlugin(plugins, \"flow\") && hasPlugin(plugins, \"typescript\")) {\n throw new Error(\"Cannot combine flow and typescript plugins.\");\n }\n\n if (hasPlugin(plugins, \"placeholders\") && hasPlugin(plugins, \"v8intrinsic\")) {\n throw new Error(\"Cannot combine placeholders and v8intrinsic plugins.\");\n }\n\n if (hasPlugin(plugins, \"pipelineOperator\")) {\n const proposal = getPluginOption(plugins, \"pipelineOperator\", \"proposal\");\n\n if (!PIPELINE_PROPOSALS.includes(proposal)) {\n const proposalList = PIPELINE_PROPOSALS.map(p => `\"${p}\"`).join(\", \");\n throw new Error(`\"pipelineOperator\" requires \"proposal\" option whose value must be one of: ${proposalList}.`);\n }\n\n const tupleSyntaxIsHash = hasPlugin(plugins, [\"recordAndTuple\", {\n syntaxType: \"hash\"\n }]);\n\n if (proposal === \"hack\") {\n if (hasPlugin(plugins, \"placeholders\")) {\n throw new Error(\"Cannot combine placeholders plugin and Hack-style pipes.\");\n }\n\n if (hasPlugin(plugins, \"v8intrinsic\")) {\n throw new Error(\"Cannot combine v8intrinsic plugin and Hack-style pipes.\");\n }\n\n const topicToken = getPluginOption(plugins, \"pipelineOperator\", \"topicToken\");\n\n if (!TOPIC_TOKENS.includes(topicToken)) {\n const tokenList = TOPIC_TOKENS.map(t => `\"${t}\"`).join(\", \");\n throw new Error(`\"pipelineOperator\" in \"proposal\": \"hack\" mode also requires a \"topicToken\" option whose value must be one of: ${tokenList}.`);\n }\n\n if (topicToken === \"#\" && tupleSyntaxIsHash) {\n throw new Error('Plugin conflict between `[\"pipelineOperator\", { proposal: \"hack\", topicToken: \"#\" }]` and `[\"recordAndtuple\", { syntaxType: \"hash\"}]`.');\n }\n } else if (proposal === \"smart\" && tupleSyntaxIsHash) {\n throw new Error('Plugin conflict between `[\"pipelineOperator\", { proposal: \"smart\" }]` and `[\"recordAndtuple\", { syntaxType: \"hash\"}]`.');\n }\n }\n\n if (hasPlugin(plugins, \"moduleAttributes\")) {\n {\n if (hasPlugin(plugins, \"importAssertions\")) {\n throw new Error(\"Cannot combine importAssertions and moduleAttributes plugins.\");\n }\n\n const moduleAttributesVerionPluginOption = getPluginOption(plugins, \"moduleAttributes\", \"version\");\n\n if (moduleAttributesVerionPluginOption !== \"may-2020\") {\n throw new Error(\"The 'moduleAttributes' plugin requires a 'version' option,\" + \" representing the last proposal update. Currently, the\" + \" only supported value is 'may-2020'.\");\n }\n }\n }\n\n if (hasPlugin(plugins, \"recordAndTuple\") && !RECORD_AND_TUPLE_SYNTAX_TYPES.includes(getPluginOption(plugins, \"recordAndTuple\", \"syntaxType\"))) {\n throw new Error(\"'recordAndTuple' requires 'syntaxType' option whose value should be one of: \" + RECORD_AND_TUPLE_SYNTAX_TYPES.map(p => `'${p}'`).join(\", \"));\n }\n\n if (hasPlugin(plugins, \"asyncDoExpressions\") && !hasPlugin(plugins, \"doExpressions\")) {\n const error = new Error(\"'asyncDoExpressions' requires 'doExpressions', please add 'doExpressions' to parser plugins.\");\n error.missingPlugins = \"doExpressions\";\n throw error;\n }\n}\nconst mixinPlugins = {\n estree,\n jsx,\n flow,\n typescript,\n v8intrinsic,\n placeholders\n};\nconst mixinPluginNames = Object.keys(mixinPlugins);\n\nconst defaultOptions = {\n sourceType: \"script\",\n sourceFilename: undefined,\n startColumn: 0,\n startLine: 1,\n allowAwaitOutsideFunction: false,\n allowReturnOutsideFunction: false,\n allowImportExportEverywhere: false,\n allowSuperOutsideMethod: false,\n allowUndeclaredExports: false,\n plugins: [],\n strictMode: null,\n ranges: false,\n tokens: false,\n createParenthesizedExpressions: false,\n errorRecovery: false,\n attachComment: true\n};\nfunction getOptions(opts) {\n const options = {};\n\n for (const key of Object.keys(defaultOptions)) {\n options[key] = opts && opts[key] != null ? opts[key] : defaultOptions[key];\n }\n\n return options;\n}\n\nconst unwrapParenthesizedExpression = node => {\n return node.type === \"ParenthesizedExpression\" ? unwrapParenthesizedExpression(node.expression) : node;\n};\n\nclass LValParser extends NodeUtils {\n toAssignable(node, isLHS = false) {\n var _node$extra, _node$extra3;\n\n let parenthesized = undefined;\n\n if (node.type === \"ParenthesizedExpression\" || (_node$extra = node.extra) != null && _node$extra.parenthesized) {\n parenthesized = unwrapParenthesizedExpression(node);\n\n if (isLHS) {\n if (parenthesized.type === \"Identifier\") {\n this.expressionScope.recordParenthesizedIdentifierError(ErrorMessages.InvalidParenthesizedAssignment, node.loc.start);\n } else if (parenthesized.type !== \"MemberExpression\") {\n this.raise(ErrorMessages.InvalidParenthesizedAssignment, {\n node\n });\n }\n } else {\n this.raise(ErrorMessages.InvalidParenthesizedAssignment, {\n node\n });\n }\n }\n\n switch (node.type) {\n case \"Identifier\":\n case \"ObjectPattern\":\n case \"ArrayPattern\":\n case \"AssignmentPattern\":\n case \"RestElement\":\n break;\n\n case \"ObjectExpression\":\n node.type = \"ObjectPattern\";\n\n for (let i = 0, length = node.properties.length, last = length - 1; i < length; i++) {\n var _node$extra2;\n\n const prop = node.properties[i];\n const isLast = i === last;\n this.toAssignableObjectExpressionProp(prop, isLast, isLHS);\n\n if (isLast && prop.type === \"RestElement\" && (_node$extra2 = node.extra) != null && _node$extra2.trailingCommaLoc) {\n this.raise(ErrorMessages.RestTrailingComma, {\n at: node.extra.trailingCommaLoc\n });\n }\n }\n\n break;\n\n case \"ObjectProperty\":\n this.toAssignable(node.value, isLHS);\n break;\n\n case \"SpreadElement\":\n {\n this.checkToRestConversion(node);\n node.type = \"RestElement\";\n const arg = node.argument;\n this.toAssignable(arg, isLHS);\n break;\n }\n\n case \"ArrayExpression\":\n node.type = \"ArrayPattern\";\n this.toAssignableList(node.elements, (_node$extra3 = node.extra) == null ? void 0 : _node$extra3.trailingCommaLoc, isLHS);\n break;\n\n case \"AssignmentExpression\":\n if (node.operator !== \"=\") {\n this.raise(ErrorMessages.MissingEqInAssignment, {\n at: node.left.loc.end\n });\n }\n\n node.type = \"AssignmentPattern\";\n delete node.operator;\n this.toAssignable(node.left, isLHS);\n break;\n\n case \"ParenthesizedExpression\":\n this.toAssignable(parenthesized, isLHS);\n break;\n }\n\n return node;\n }\n\n toAssignableObjectExpressionProp(prop, isLast, isLHS) {\n if (prop.type === \"ObjectMethod\") {\n this.raise(prop.kind === \"get\" || prop.kind === \"set\" ? ErrorMessages.PatternHasAccessor : ErrorMessages.PatternHasMethod, {\n node: prop.key\n });\n } else if (prop.type === \"SpreadElement\" && !isLast) {\n this.raise(ErrorMessages.RestTrailingComma, {\n node: prop\n });\n } else {\n this.toAssignable(prop, isLHS);\n }\n }\n\n toAssignableList(exprList, trailingCommaLoc, isLHS) {\n let end = exprList.length;\n\n if (end) {\n const last = exprList[end - 1];\n\n if ((last == null ? void 0 : last.type) === \"RestElement\") {\n --end;\n } else if ((last == null ? void 0 : last.type) === \"SpreadElement\") {\n last.type = \"RestElement\";\n let arg = last.argument;\n this.toAssignable(arg, isLHS);\n arg = unwrapParenthesizedExpression(arg);\n\n if (arg.type !== \"Identifier\" && arg.type !== \"MemberExpression\" && arg.type !== \"ArrayPattern\" && arg.type !== \"ObjectPattern\") {\n this.unexpected(arg.start);\n }\n\n if (trailingCommaLoc) {\n this.raise(ErrorMessages.RestTrailingComma, {\n at: trailingCommaLoc\n });\n }\n\n --end;\n }\n }\n\n for (let i = 0; i < end; i++) {\n const elt = exprList[i];\n\n if (elt) {\n this.toAssignable(elt, isLHS);\n\n if (elt.type === \"RestElement\") {\n this.raise(ErrorMessages.RestTrailingComma, {\n node: elt\n });\n }\n }\n }\n\n return exprList;\n }\n\n isAssignable(node, isBinding) {\n switch (node.type) {\n case \"Identifier\":\n case \"ObjectPattern\":\n case \"ArrayPattern\":\n case \"AssignmentPattern\":\n case \"RestElement\":\n return true;\n\n case \"ObjectExpression\":\n {\n const last = node.properties.length - 1;\n return node.properties.every((prop, i) => {\n return prop.type !== \"ObjectMethod\" && (i === last || prop.type !== \"SpreadElement\") && this.isAssignable(prop);\n });\n }\n\n case \"ObjectProperty\":\n return this.isAssignable(node.value);\n\n case \"SpreadElement\":\n return this.isAssignable(node.argument);\n\n case \"ArrayExpression\":\n return node.elements.every(element => element === null || this.isAssignable(element));\n\n case \"AssignmentExpression\":\n return node.operator === \"=\";\n\n case \"ParenthesizedExpression\":\n return this.isAssignable(node.expression);\n\n case \"MemberExpression\":\n case \"OptionalMemberExpression\":\n return !isBinding;\n\n default:\n return false;\n }\n }\n\n toReferencedList(exprList, isParenthesizedExpr) {\n return exprList;\n }\n\n toReferencedListDeep(exprList, isParenthesizedExpr) {\n this.toReferencedList(exprList, isParenthesizedExpr);\n\n for (const expr of exprList) {\n if ((expr == null ? void 0 : expr.type) === \"ArrayExpression\") {\n this.toReferencedListDeep(expr.elements);\n }\n }\n }\n\n parseSpread(refExpressionErrors, refNeedsArrowPos) {\n const node = this.startNode();\n this.next();\n node.argument = this.parseMaybeAssignAllowIn(refExpressionErrors, undefined, refNeedsArrowPos);\n return this.finishNode(node, \"SpreadElement\");\n }\n\n parseRestBinding() {\n const node = this.startNode();\n this.next();\n node.argument = this.parseBindingAtom();\n return this.finishNode(node, \"RestElement\");\n }\n\n parseBindingAtom() {\n switch (this.state.type) {\n case 0:\n {\n const node = this.startNode();\n this.next();\n node.elements = this.parseBindingList(3, 93, true);\n return this.finishNode(node, \"ArrayPattern\");\n }\n\n case 5:\n return this.parseObjectLike(8, true);\n }\n\n return this.parseIdentifier();\n }\n\n parseBindingList(close, closeCharCode, allowEmpty, allowModifiers) {\n const elts = [];\n let first = true;\n\n while (!this.eat(close)) {\n if (first) {\n first = false;\n } else {\n this.expect(12);\n }\n\n if (allowEmpty && this.match(12)) {\n elts.push(null);\n } else if (this.eat(close)) {\n break;\n } else if (this.match(21)) {\n elts.push(this.parseAssignableListItemTypes(this.parseRestBinding()));\n\n if (!this.checkCommaAfterRest(closeCharCode)) {\n this.expect(close);\n break;\n }\n } else {\n const decorators = [];\n\n if (this.match(26) && this.hasPlugin(\"decorators\")) {\n this.raise(ErrorMessages.UnsupportedParameterDecorator, {\n at: this.state.startLoc\n });\n }\n\n while (this.match(26)) {\n decorators.push(this.parseDecorator());\n }\n\n elts.push(this.parseAssignableListItem(allowModifiers, decorators));\n }\n }\n\n return elts;\n }\n\n parseBindingRestProperty(prop) {\n this.next();\n prop.argument = this.parseIdentifier();\n this.checkCommaAfterRest(125);\n return this.finishNode(prop, \"RestElement\");\n }\n\n parseBindingProperty() {\n const prop = this.startNode();\n const {\n type,\n start: startPos,\n startLoc\n } = this.state;\n\n if (type === 21) {\n return this.parseBindingRestProperty(prop);\n } else {\n this.parsePropertyName(prop);\n }\n\n prop.method = false;\n this.parseObjPropValue(prop, startPos, startLoc, false, false, true, false);\n return prop;\n }\n\n parseAssignableListItem(allowModifiers, decorators) {\n const left = this.parseMaybeDefault();\n this.parseAssignableListItemTypes(left);\n const elt = this.parseMaybeDefault(left.start, left.loc.start, left);\n\n if (decorators.length) {\n left.decorators = decorators;\n }\n\n return elt;\n }\n\n parseAssignableListItemTypes(param) {\n return param;\n }\n\n parseMaybeDefault(startPos, startLoc, left) {\n var _startLoc, _startPos, _left;\n\n startLoc = (_startLoc = startLoc) != null ? _startLoc : this.state.startLoc;\n startPos = (_startPos = startPos) != null ? _startPos : this.state.start;\n left = (_left = left) != null ? _left : this.parseBindingAtom();\n if (!this.eat(29)) return left;\n const node = this.startNodeAt(startPos, startLoc);\n node.left = left;\n node.right = this.parseMaybeAssignAllowIn();\n return this.finishNode(node, \"AssignmentPattern\");\n }\n\n checkLVal(expr, contextDescription, bindingType = BIND_NONE, checkClashes, disallowLetBinding, strictModeChanged = false) {\n switch (expr.type) {\n case \"Identifier\":\n {\n const {\n name\n } = expr;\n\n if (this.state.strict && (strictModeChanged ? isStrictBindReservedWord(name, this.inModule) : isStrictBindOnlyReservedWord(name))) {\n this.raise(bindingType === BIND_NONE ? ErrorMessages.StrictEvalArguments : ErrorMessages.StrictEvalArgumentsBinding, {\n node: expr\n }, name);\n }\n\n if (checkClashes) {\n if (checkClashes.has(name)) {\n this.raise(ErrorMessages.ParamDupe, {\n node: expr\n });\n } else {\n checkClashes.add(name);\n }\n }\n\n if (disallowLetBinding && name === \"let\") {\n this.raise(ErrorMessages.LetInLexicalBinding, {\n node: expr\n });\n }\n\n if (!(bindingType & BIND_NONE)) {\n this.scope.declareName(name, bindingType, expr.loc.start);\n }\n\n break;\n }\n\n case \"MemberExpression\":\n if (bindingType !== BIND_NONE) {\n this.raise(ErrorMessages.InvalidPropertyBindingPattern, {\n node: expr\n });\n }\n\n break;\n\n case \"ObjectPattern\":\n for (let prop of expr.properties) {\n if (this.isObjectProperty(prop)) prop = prop.value;else if (this.isObjectMethod(prop)) continue;\n this.checkLVal(prop, \"object destructuring pattern\", bindingType, checkClashes, disallowLetBinding);\n }\n\n break;\n\n case \"ArrayPattern\":\n for (const elem of expr.elements) {\n if (elem) {\n this.checkLVal(elem, \"array destructuring pattern\", bindingType, checkClashes, disallowLetBinding);\n }\n }\n\n break;\n\n case \"AssignmentPattern\":\n this.checkLVal(expr.left, \"assignment pattern\", bindingType, checkClashes);\n break;\n\n case \"RestElement\":\n this.checkLVal(expr.argument, \"rest element\", bindingType, checkClashes);\n break;\n\n case \"ParenthesizedExpression\":\n this.checkLVal(expr.expression, \"parenthesized expression\", bindingType, checkClashes);\n break;\n\n default:\n {\n this.raise(bindingType === BIND_NONE ? ErrorMessages.InvalidLhs : ErrorMessages.InvalidLhsBinding, {\n node: expr\n }, contextDescription);\n }\n }\n }\n\n checkToRestConversion(node) {\n if (node.argument.type !== \"Identifier\" && node.argument.type !== \"MemberExpression\") {\n this.raise(ErrorMessages.InvalidRestAssignmentPattern, {\n node: node.argument\n });\n }\n }\n\n checkCommaAfterRest(close) {\n if (!this.match(12)) {\n return false;\n }\n\n this.raise(this.lookaheadCharCode() === close ? ErrorMessages.RestTrailingComma : ErrorMessages.ElementAfterRest, {\n at: this.state.startLoc\n });\n return true;\n }\n\n}\n\nconst invalidHackPipeBodies = new Map([[\"ArrowFunctionExpression\", \"arrow function\"], [\"AssignmentExpression\", \"assignment\"], [\"ConditionalExpression\", \"conditional\"], [\"YieldExpression\", \"yield\"]]);\nclass ExpressionParser extends LValParser {\n checkProto(prop, isRecord, protoRef, refExpressionErrors) {\n if (prop.type === \"SpreadElement\" || this.isObjectMethod(prop) || prop.computed || prop.shorthand) {\n return;\n }\n\n const key = prop.key;\n const name = key.type === \"Identifier\" ? key.name : key.value;\n\n if (name === \"__proto__\") {\n if (isRecord) {\n this.raise(ErrorMessages.RecordNoProto, {\n node: key\n });\n return;\n }\n\n if (protoRef.used) {\n if (refExpressionErrors) {\n if (refExpressionErrors.doubleProtoLoc === null) {\n refExpressionErrors.doubleProtoLoc = key.loc.start;\n }\n } else {\n this.raise(ErrorMessages.DuplicateProto, {\n node: key\n });\n }\n }\n\n protoRef.used = true;\n }\n }\n\n shouldExitDescending(expr, potentialArrowAt) {\n return expr.type === \"ArrowFunctionExpression\" && expr.start === potentialArrowAt;\n }\n\n getExpression() {\n this.enterInitialScopes();\n this.nextToken();\n const expr = this.parseExpression();\n\n if (!this.match(131)) {\n this.unexpected();\n }\n\n this.finalizeRemainingComments();\n expr.comments = this.state.comments;\n expr.errors = this.state.errors;\n\n if (this.options.tokens) {\n expr.tokens = this.tokens;\n }\n\n return expr;\n }\n\n parseExpression(disallowIn, refExpressionErrors) {\n if (disallowIn) {\n return this.disallowInAnd(() => this.parseExpressionBase(refExpressionErrors));\n }\n\n return this.allowInAnd(() => this.parseExpressionBase(refExpressionErrors));\n }\n\n parseExpressionBase(refExpressionErrors) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const expr = this.parseMaybeAssign(refExpressionErrors);\n\n if (this.match(12)) {\n const node = this.startNodeAt(startPos, startLoc);\n node.expressions = [expr];\n\n while (this.eat(12)) {\n node.expressions.push(this.parseMaybeAssign(refExpressionErrors));\n }\n\n this.toReferencedList(node.expressions);\n return this.finishNode(node, \"SequenceExpression\");\n }\n\n return expr;\n }\n\n parseMaybeAssignDisallowIn(refExpressionErrors, afterLeftParse) {\n return this.disallowInAnd(() => this.parseMaybeAssign(refExpressionErrors, afterLeftParse));\n }\n\n parseMaybeAssignAllowIn(refExpressionErrors, afterLeftParse) {\n return this.allowInAnd(() => this.parseMaybeAssign(refExpressionErrors, afterLeftParse));\n }\n\n setOptionalParametersError(refExpressionErrors, resultError) {\n var _resultError$loc;\n\n refExpressionErrors.optionalParametersLoc = (_resultError$loc = resultError == null ? void 0 : resultError.loc) != null ? _resultError$loc : this.state.startLoc;\n }\n\n parseMaybeAssign(refExpressionErrors, afterLeftParse) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n\n if (this.isContextual(101)) {\n if (this.prodParam.hasYield) {\n let left = this.parseYield();\n\n if (afterLeftParse) {\n left = afterLeftParse.call(this, left, startPos, startLoc);\n }\n\n return left;\n }\n }\n\n let ownExpressionErrors;\n\n if (refExpressionErrors) {\n ownExpressionErrors = false;\n } else {\n refExpressionErrors = new ExpressionErrors();\n ownExpressionErrors = true;\n }\n\n const {\n type\n } = this.state;\n\n if (type === 10 || tokenIsIdentifier(type)) {\n this.state.potentialArrowAt = this.state.start;\n }\n\n let left = this.parseMaybeConditional(refExpressionErrors);\n\n if (afterLeftParse) {\n left = afterLeftParse.call(this, left, startPos, startLoc);\n }\n\n if (tokenIsAssignment(this.state.type)) {\n const node = this.startNodeAt(startPos, startLoc);\n const operator = this.state.value;\n node.operator = operator;\n\n if (this.match(29)) {\n node.left = this.toAssignable(left, true);\n\n if (refExpressionErrors.doubleProtoLoc != null && indexes.get(refExpressionErrors.doubleProtoLoc) >= startPos) {\n refExpressionErrors.doubleProtoLoc = null;\n }\n\n if (refExpressionErrors.shorthandAssignLoc != null && indexes.get(refExpressionErrors.shorthandAssignLoc) >= startPos) {\n refExpressionErrors.shorthandAssignLoc = null;\n }\n } else {\n node.left = left;\n }\n\n this.checkLVal(left, \"assignment expression\");\n this.next();\n node.right = this.parseMaybeAssign();\n return this.finishNode(node, \"AssignmentExpression\");\n } else if (ownExpressionErrors) {\n this.checkExpressionErrors(refExpressionErrors, true);\n }\n\n return left;\n }\n\n parseMaybeConditional(refExpressionErrors) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const potentialArrowAt = this.state.potentialArrowAt;\n const expr = this.parseExprOps(refExpressionErrors);\n\n if (this.shouldExitDescending(expr, potentialArrowAt)) {\n return expr;\n }\n\n return this.parseConditional(expr, startPos, startLoc, refExpressionErrors);\n }\n\n parseConditional(expr, startPos, startLoc, refExpressionErrors) {\n if (this.eat(17)) {\n const node = this.startNodeAt(startPos, startLoc);\n node.test = expr;\n node.consequent = this.parseMaybeAssignAllowIn();\n this.expect(14);\n node.alternate = this.parseMaybeAssign();\n return this.finishNode(node, \"ConditionalExpression\");\n }\n\n return expr;\n }\n\n parseMaybeUnaryOrPrivate(refExpressionErrors) {\n return this.match(130) ? this.parsePrivateName() : this.parseMaybeUnary(refExpressionErrors);\n }\n\n parseExprOps(refExpressionErrors) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const potentialArrowAt = this.state.potentialArrowAt;\n const expr = this.parseMaybeUnaryOrPrivate(refExpressionErrors);\n\n if (this.shouldExitDescending(expr, potentialArrowAt)) {\n return expr;\n }\n\n return this.parseExprOp(expr, startPos, startLoc, -1);\n }\n\n parseExprOp(left, leftStartPos, leftStartLoc, minPrec) {\n if (this.isPrivateName(left)) {\n const value = this.getPrivateNameSV(left);\n\n if (minPrec >= tokenOperatorPrecedence(54) || !this.prodParam.hasIn || !this.match(54)) {\n this.raise(ErrorMessages.PrivateInExpectedIn, {\n node: left\n }, value);\n }\n\n this.classScope.usePrivateName(value, left.loc.start);\n }\n\n const op = this.state.type;\n\n if (tokenIsOperator(op) && (this.prodParam.hasIn || !this.match(54))) {\n let prec = tokenOperatorPrecedence(op);\n\n if (prec > minPrec) {\n if (op === 37) {\n this.expectPlugin(\"pipelineOperator\");\n\n if (this.state.inFSharpPipelineDirectBody) {\n return left;\n }\n\n this.checkPipelineAtInfixOperator(left, leftStartLoc);\n }\n\n const node = this.startNodeAt(leftStartPos, leftStartLoc);\n node.left = left;\n node.operator = this.state.value;\n const logical = op === 39 || op === 40;\n const coalesce = op === 38;\n\n if (coalesce) {\n prec = tokenOperatorPrecedence(40);\n }\n\n this.next();\n\n if (op === 37 && this.hasPlugin([\"pipelineOperator\", {\n proposal: \"minimal\"\n }])) {\n if (this.state.type === 92 && this.prodParam.hasAwait) {\n throw this.raise(ErrorMessages.UnexpectedAwaitAfterPipelineBody, {\n at: this.state.startLoc\n });\n }\n }\n\n node.right = this.parseExprOpRightExpr(op, prec);\n this.finishNode(node, logical || coalesce ? \"LogicalExpression\" : \"BinaryExpression\");\n const nextOp = this.state.type;\n\n if (coalesce && (nextOp === 39 || nextOp === 40) || logical && nextOp === 38) {\n throw this.raise(ErrorMessages.MixingCoalesceWithLogical, {\n at: this.state.startLoc\n });\n }\n\n return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec);\n }\n }\n\n return left;\n }\n\n parseExprOpRightExpr(op, prec) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n\n switch (op) {\n case 37:\n switch (this.getPluginOption(\"pipelineOperator\", \"proposal\")) {\n case \"hack\":\n return this.withTopicBindingContext(() => {\n return this.parseHackPipeBody();\n });\n\n case \"smart\":\n return this.withTopicBindingContext(() => {\n if (this.prodParam.hasYield && this.isContextual(101)) {\n throw this.raise(ErrorMessages.PipeBodyIsTighter, {\n at: this.state.startLoc\n }, this.state.value);\n }\n\n return this.parseSmartPipelineBodyInStyle(this.parseExprOpBaseRightExpr(op, prec), startPos, startLoc);\n });\n\n case \"fsharp\":\n return this.withSoloAwaitPermittingContext(() => {\n return this.parseFSharpPipelineBody(prec);\n });\n }\n\n default:\n return this.parseExprOpBaseRightExpr(op, prec);\n }\n }\n\n parseExprOpBaseRightExpr(op, prec) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n return this.parseExprOp(this.parseMaybeUnaryOrPrivate(), startPos, startLoc, tokenIsRightAssociative(op) ? prec - 1 : prec);\n }\n\n parseHackPipeBody() {\n var _body$extra;\n\n const {\n startLoc\n } = this.state;\n const body = this.parseMaybeAssign();\n\n if (invalidHackPipeBodies.has(body.type) && !((_body$extra = body.extra) != null && _body$extra.parenthesized)) {\n this.raise(ErrorMessages.PipeUnparenthesizedBody, {\n at: startLoc\n }, invalidHackPipeBodies.get(body.type));\n }\n\n if (!this.topicReferenceWasUsedInCurrentContext()) {\n this.raise(ErrorMessages.PipeTopicUnused, {\n at: startLoc\n });\n }\n\n return body;\n }\n\n checkExponentialAfterUnary(node) {\n if (this.match(53)) {\n this.raise(ErrorMessages.UnexpectedTokenUnaryExponentiation, {\n node: node.argument\n });\n }\n }\n\n parseMaybeUnary(refExpressionErrors, sawUnary) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const isAwait = this.isContextual(92);\n\n if (isAwait && this.isAwaitAllowed()) {\n this.next();\n const expr = this.parseAwait(startPos, startLoc);\n if (!sawUnary) this.checkExponentialAfterUnary(expr);\n return expr;\n }\n\n const update = this.match(34);\n const node = this.startNode();\n\n if (tokenIsPrefix(this.state.type)) {\n node.operator = this.state.value;\n node.prefix = true;\n\n if (this.match(68)) {\n this.expectPlugin(\"throwExpressions\");\n }\n\n const isDelete = this.match(85);\n this.next();\n node.argument = this.parseMaybeUnary(null, true);\n this.checkExpressionErrors(refExpressionErrors, true);\n\n if (this.state.strict && isDelete) {\n const arg = node.argument;\n\n if (arg.type === \"Identifier\") {\n this.raise(ErrorMessages.StrictDelete, {\n node\n });\n } else if (this.hasPropertyAsPrivateName(arg)) {\n this.raise(ErrorMessages.DeletePrivateField, {\n node\n });\n }\n }\n\n if (!update) {\n if (!sawUnary) this.checkExponentialAfterUnary(node);\n return this.finishNode(node, \"UnaryExpression\");\n }\n }\n\n const expr = this.parseUpdate(node, update, refExpressionErrors);\n\n if (isAwait) {\n const {\n type\n } = this.state;\n const startsExpr = this.hasPlugin(\"v8intrinsic\") ? tokenCanStartExpression(type) : tokenCanStartExpression(type) && !this.match(50);\n\n if (startsExpr && !this.isAmbiguousAwait()) {\n this.raiseOverwrite(startLoc, ErrorMessages.AwaitNotInAsyncContext);\n return this.parseAwait(startPos, startLoc);\n }\n }\n\n return expr;\n }\n\n parseUpdate(node, update, refExpressionErrors) {\n if (update) {\n this.checkLVal(node.argument, \"prefix operation\");\n return this.finishNode(node, \"UpdateExpression\");\n }\n\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let expr = this.parseExprSubscripts(refExpressionErrors);\n if (this.checkExpressionErrors(refExpressionErrors, false)) return expr;\n\n while (tokenIsPostfix(this.state.type) && !this.canInsertSemicolon()) {\n const node = this.startNodeAt(startPos, startLoc);\n node.operator = this.state.value;\n node.prefix = false;\n node.argument = expr;\n this.checkLVal(expr, \"postfix operation\");\n this.next();\n expr = this.finishNode(node, \"UpdateExpression\");\n }\n\n return expr;\n }\n\n parseExprSubscripts(refExpressionErrors) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n const potentialArrowAt = this.state.potentialArrowAt;\n const expr = this.parseExprAtom(refExpressionErrors);\n\n if (this.shouldExitDescending(expr, potentialArrowAt)) {\n return expr;\n }\n\n return this.parseSubscripts(expr, startPos, startLoc);\n }\n\n parseSubscripts(base, startPos, startLoc, noCalls) {\n const state = {\n optionalChainMember: false,\n maybeAsyncArrow: this.atPossibleAsyncArrow(base),\n stop: false\n };\n\n do {\n base = this.parseSubscript(base, startPos, startLoc, noCalls, state);\n state.maybeAsyncArrow = false;\n } while (!state.stop);\n\n return base;\n }\n\n parseSubscript(base, startPos, startLoc, noCalls, state) {\n const {\n type\n } = this.state;\n\n if (!noCalls && type === 15) {\n return this.parseBind(base, startPos, startLoc, noCalls, state);\n } else if (tokenIsTemplate(type)) {\n return this.parseTaggedTemplateExpression(base, startPos, startLoc, state);\n }\n\n let optional = false;\n\n if (type === 18) {\n if (noCalls && this.lookaheadCharCode() === 40) {\n state.stop = true;\n return base;\n }\n\n state.optionalChainMember = optional = true;\n this.next();\n }\n\n if (!noCalls && this.match(10)) {\n return this.parseCoverCallAndAsyncArrowHead(base, startPos, startLoc, state, optional);\n } else {\n const computed = this.eat(0);\n\n if (computed || optional || this.eat(16)) {\n return this.parseMember(base, startPos, startLoc, state, computed, optional);\n } else {\n state.stop = true;\n return base;\n }\n }\n }\n\n parseMember(base, startPos, startLoc, state, computed, optional) {\n const node = this.startNodeAt(startPos, startLoc);\n node.object = base;\n node.computed = computed;\n\n if (computed) {\n node.property = this.parseExpression();\n this.expect(3);\n } else if (this.match(130)) {\n if (base.type === \"Super\") {\n this.raise(ErrorMessages.SuperPrivateField, {\n at: startLoc\n });\n }\n\n this.classScope.usePrivateName(this.state.value, this.state.startLoc);\n node.property = this.parsePrivateName();\n } else {\n node.property = this.parseIdentifier(true);\n }\n\n if (state.optionalChainMember) {\n node.optional = optional;\n return this.finishNode(node, \"OptionalMemberExpression\");\n } else {\n return this.finishNode(node, \"MemberExpression\");\n }\n }\n\n parseBind(base, startPos, startLoc, noCalls, state) {\n const node = this.startNodeAt(startPos, startLoc);\n node.object = base;\n this.next();\n node.callee = this.parseNoCallExpr();\n state.stop = true;\n return this.parseSubscripts(this.finishNode(node, \"BindExpression\"), startPos, startLoc, noCalls);\n }\n\n parseCoverCallAndAsyncArrowHead(base, startPos, startLoc, state, optional) {\n const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;\n let refExpressionErrors = null;\n this.state.maybeInArrowParameters = true;\n this.next();\n let node = this.startNodeAt(startPos, startLoc);\n node.callee = base;\n\n if (state.maybeAsyncArrow) {\n this.expressionScope.enter(newAsyncArrowScope());\n refExpressionErrors = new ExpressionErrors();\n }\n\n if (state.optionalChainMember) {\n node.optional = optional;\n }\n\n if (optional) {\n node.arguments = this.parseCallExpressionArguments(11);\n } else {\n node.arguments = this.parseCallExpressionArguments(11, base.type === \"Import\", base.type !== \"Super\", node, refExpressionErrors);\n }\n\n this.finishCallExpression(node, state.optionalChainMember);\n\n if (state.maybeAsyncArrow && this.shouldParseAsyncArrow() && !optional) {\n state.stop = true;\n this.expressionScope.validateAsPattern();\n this.expressionScope.exit();\n node = this.parseAsyncArrowFromCallExpression(this.startNodeAt(startPos, startLoc), node);\n } else {\n if (state.maybeAsyncArrow) {\n this.checkExpressionErrors(refExpressionErrors, true);\n this.expressionScope.exit();\n }\n\n this.toReferencedArguments(node);\n }\n\n this.state.maybeInArrowParameters = oldMaybeInArrowParameters;\n return node;\n }\n\n toReferencedArguments(node, isParenthesizedExpr) {\n this.toReferencedListDeep(node.arguments, isParenthesizedExpr);\n }\n\n parseTaggedTemplateExpression(base, startPos, startLoc, state) {\n const node = this.startNodeAt(startPos, startLoc);\n node.tag = base;\n node.quasi = this.parseTemplate(true);\n\n if (state.optionalChainMember) {\n this.raise(ErrorMessages.OptionalChainingNoTemplate, {\n at: startLoc\n });\n }\n\n return this.finishNode(node, \"TaggedTemplateExpression\");\n }\n\n atPossibleAsyncArrow(base) {\n return base.type === \"Identifier\" && base.name === \"async\" && indexes.get(this.state.lastTokEndLoc) === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && base.start === this.state.potentialArrowAt;\n }\n\n finishCallExpression(node, optional) {\n if (node.callee.type === \"Import\") {\n if (node.arguments.length === 2) {\n {\n if (!this.hasPlugin(\"moduleAttributes\")) {\n this.expectPlugin(\"importAssertions\");\n }\n }\n }\n\n if (node.arguments.length === 0 || node.arguments.length > 2) {\n this.raise(ErrorMessages.ImportCallArity, {\n node\n }, this.hasPlugin(\"importAssertions\") || this.hasPlugin(\"moduleAttributes\") ? \"one or two arguments\" : \"one argument\");\n } else {\n for (const arg of node.arguments) {\n if (arg.type === \"SpreadElement\") {\n this.raise(ErrorMessages.ImportCallSpreadArgument, {\n node: arg\n });\n }\n }\n }\n }\n\n return this.finishNode(node, optional ? \"OptionalCallExpression\" : \"CallExpression\");\n }\n\n parseCallExpressionArguments(close, dynamicImport, allowPlaceholder, nodeForExtra, refExpressionErrors) {\n const elts = [];\n let first = true;\n const oldInFSharpPipelineDirectBody = this.state.inFSharpPipelineDirectBody;\n this.state.inFSharpPipelineDirectBody = false;\n\n while (!this.eat(close)) {\n if (first) {\n first = false;\n } else {\n this.expect(12);\n\n if (this.match(close)) {\n if (dynamicImport && !this.hasPlugin(\"importAssertions\") && !this.hasPlugin(\"moduleAttributes\")) {\n this.raise(ErrorMessages.ImportCallArgumentTrailingComma, {\n at: this.state.lastTokStartLoc\n });\n }\n\n if (nodeForExtra) {\n this.addTrailingCommaExtraToNode(nodeForExtra);\n }\n\n this.next();\n break;\n }\n }\n\n elts.push(this.parseExprListItem(false, refExpressionErrors, allowPlaceholder));\n }\n\n this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;\n return elts;\n }\n\n shouldParseAsyncArrow() {\n return this.match(19) && !this.canInsertSemicolon();\n }\n\n parseAsyncArrowFromCallExpression(node, call) {\n var _call$extra;\n\n this.resetPreviousNodeTrailingComments(call);\n this.expect(19);\n this.parseArrowExpression(node, call.arguments, true, (_call$extra = call.extra) == null ? void 0 : _call$extra.trailingCommaLoc);\n\n if (call.innerComments) {\n setInnerComments(node, call.innerComments);\n }\n\n if (call.callee.trailingComments) {\n setInnerComments(node, call.callee.trailingComments);\n }\n\n return node;\n }\n\n parseNoCallExpr() {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n return this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);\n }\n\n parseExprAtom(refExpressionErrors) {\n let node;\n const {\n type\n } = this.state;\n\n switch (type) {\n case 75:\n return this.parseSuper();\n\n case 79:\n node = this.startNode();\n this.next();\n\n if (this.match(16)) {\n return this.parseImportMetaProperty(node);\n }\n\n if (!this.match(10)) {\n this.raise(ErrorMessages.UnsupportedImport, {\n at: this.state.lastTokStartLoc\n });\n }\n\n return this.finishNode(node, \"Import\");\n\n case 74:\n node = this.startNode();\n this.next();\n return this.finishNode(node, \"ThisExpression\");\n\n case 86:\n {\n return this.parseDo(this.startNode(), false);\n }\n\n case 52:\n case 31:\n {\n this.readRegexp();\n return this.parseRegExpLiteral(this.state.value);\n }\n\n case 126:\n return this.parseNumericLiteral(this.state.value);\n\n case 127:\n return this.parseBigIntLiteral(this.state.value);\n\n case 128:\n return this.parseDecimalLiteral(this.state.value);\n\n case 125:\n return this.parseStringLiteral(this.state.value);\n\n case 80:\n return this.parseNullLiteral();\n\n case 81:\n return this.parseBooleanLiteral(true);\n\n case 82:\n return this.parseBooleanLiteral(false);\n\n case 10:\n {\n const canBeArrow = this.state.potentialArrowAt === this.state.start;\n return this.parseParenAndDistinguishExpression(canBeArrow);\n }\n\n case 2:\n case 1:\n {\n return this.parseArrayLike(this.state.type === 2 ? 4 : 3, false, true);\n }\n\n case 0:\n {\n return this.parseArrayLike(3, true, false, refExpressionErrors);\n }\n\n case 6:\n case 7:\n {\n return this.parseObjectLike(this.state.type === 6 ? 9 : 8, false, true);\n }\n\n case 5:\n {\n return this.parseObjectLike(8, false, false, refExpressionErrors);\n }\n\n case 64:\n return this.parseFunctionOrFunctionSent();\n\n case 26:\n this.parseDecorators();\n\n case 76:\n node = this.startNode();\n this.takeDecorators(node);\n return this.parseClass(node, false);\n\n case 73:\n return this.parseNewOrNewTarget();\n\n case 25:\n case 24:\n return this.parseTemplate(false);\n\n case 15:\n {\n node = this.startNode();\n this.next();\n node.object = null;\n const callee = node.callee = this.parseNoCallExpr();\n\n if (callee.type === \"MemberExpression\") {\n return this.finishNode(node, \"BindExpression\");\n } else {\n throw this.raise(ErrorMessages.UnsupportedBind, {\n node: callee\n });\n }\n }\n\n case 130:\n {\n this.raise(ErrorMessages.PrivateInExpectedIn, {\n at: this.state.startLoc\n }, this.state.value);\n return this.parsePrivateName();\n }\n\n case 33:\n {\n return this.parseTopicReferenceThenEqualsSign(50, \"%\");\n }\n\n case 32:\n {\n return this.parseTopicReferenceThenEqualsSign(42, \"^\");\n }\n\n case 42:\n case 50:\n case 27:\n {\n const pipeProposal = this.getPluginOption(\"pipelineOperator\", \"proposal\");\n\n if (pipeProposal) {\n return this.parseTopicReference(pipeProposal);\n } else {\n throw this.unexpected();\n }\n }\n\n case 45:\n {\n const lookaheadCh = this.input.codePointAt(this.nextTokenStart());\n\n if (isIdentifierStart(lookaheadCh) || lookaheadCh === 62) {\n this.expectOnePlugin([\"jsx\", \"flow\", \"typescript\"]);\n break;\n } else {\n throw this.unexpected();\n }\n }\n\n default:\n if (tokenIsIdentifier(type)) {\n if (this.isContextual(119) && this.lookaheadCharCode() === 123 && !this.hasFollowingLineBreak()) {\n return this.parseModuleExpression();\n }\n\n const canBeArrow = this.state.potentialArrowAt === this.state.start;\n const containsEsc = this.state.containsEsc;\n const id = this.parseIdentifier();\n\n if (!containsEsc && id.name === \"async\" && !this.canInsertSemicolon()) {\n const {\n type\n } = this.state;\n\n if (type === 64) {\n this.resetPreviousNodeTrailingComments(id);\n this.next();\n return this.parseFunction(this.startNodeAtNode(id), undefined, true);\n } else if (tokenIsIdentifier(type)) {\n if (this.lookaheadCharCode() === 61) {\n return this.parseAsyncArrowUnaryFunction(this.startNodeAtNode(id));\n } else {\n return id;\n }\n } else if (type === 86) {\n this.resetPreviousNodeTrailingComments(id);\n return this.parseDo(this.startNodeAtNode(id), true);\n }\n }\n\n if (canBeArrow && this.match(19) && !this.canInsertSemicolon()) {\n this.next();\n return this.parseArrowExpression(this.startNodeAtNode(id), [id], false);\n }\n\n return id;\n } else {\n throw this.unexpected();\n }\n\n }\n }\n\n parseTopicReferenceThenEqualsSign(topicTokenType, topicTokenValue) {\n const pipeProposal = this.getPluginOption(\"pipelineOperator\", \"proposal\");\n\n if (pipeProposal) {\n this.state.type = topicTokenType;\n this.state.value = topicTokenValue;\n this.state.pos--;\n this.state.end--;\n this.state.endLoc = createPositionWithColumnOffset(this.state.endLoc, -1);\n return this.parseTopicReference(pipeProposal);\n } else {\n throw this.unexpected();\n }\n }\n\n parseTopicReference(pipeProposal) {\n const node = this.startNode();\n const startLoc = this.state.startLoc;\n const tokenType = this.state.type;\n this.next();\n return this.finishTopicReference(node, startLoc, pipeProposal, tokenType);\n }\n\n finishTopicReference(node, startLoc, pipeProposal, tokenType) {\n if (this.testTopicReferenceConfiguration(pipeProposal, startLoc, tokenType)) {\n const nodeType = pipeProposal === \"smart\" ? \"PipelinePrimaryTopicReference\" : \"TopicReference\";\n\n if (!this.topicReferenceIsAllowedInCurrentContext()) {\n this.raise(pipeProposal === \"smart\" ? ErrorMessages.PrimaryTopicNotAllowed : ErrorMessages.PipeTopicUnbound, {\n at: startLoc\n });\n }\n\n this.registerTopicReference();\n return this.finishNode(node, nodeType);\n } else {\n throw this.raise(ErrorMessages.PipeTopicUnconfiguredToken, {\n at: startLoc\n }, tokenLabelName(tokenType));\n }\n }\n\n testTopicReferenceConfiguration(pipeProposal, startLoc, tokenType) {\n switch (pipeProposal) {\n case \"hack\":\n {\n return this.hasPlugin([\"pipelineOperator\", {\n topicToken: tokenLabelName(tokenType)\n }]);\n }\n\n case \"smart\":\n return tokenType === 27;\n\n default:\n throw this.raise(ErrorMessages.PipeTopicRequiresHackPipes, {\n at: startLoc\n });\n }\n }\n\n parseAsyncArrowUnaryFunction(node) {\n this.prodParam.enter(functionFlags(true, this.prodParam.hasYield));\n const params = [this.parseIdentifier()];\n this.prodParam.exit();\n\n if (this.hasPrecedingLineBreak()) {\n this.raise(ErrorMessages.LineTerminatorBeforeArrow, {\n at: this.state.curPosition()\n });\n }\n\n this.expect(19);\n this.parseArrowExpression(node, params, true);\n return node;\n }\n\n parseDo(node, isAsync) {\n this.expectPlugin(\"doExpressions\");\n\n if (isAsync) {\n this.expectPlugin(\"asyncDoExpressions\");\n }\n\n node.async = isAsync;\n this.next();\n const oldLabels = this.state.labels;\n this.state.labels = [];\n\n if (isAsync) {\n this.prodParam.enter(PARAM_AWAIT);\n node.body = this.parseBlock();\n this.prodParam.exit();\n } else {\n node.body = this.parseBlock();\n }\n\n this.state.labels = oldLabels;\n return this.finishNode(node, \"DoExpression\");\n }\n\n parseSuper() {\n const node = this.startNode();\n this.next();\n\n if (this.match(10) && !this.scope.allowDirectSuper && !this.options.allowSuperOutsideMethod) {\n this.raise(ErrorMessages.SuperNotAllowed, {\n node\n });\n } else if (!this.scope.allowSuper && !this.options.allowSuperOutsideMethod) {\n this.raise(ErrorMessages.UnexpectedSuper, {\n node\n });\n }\n\n if (!this.match(10) && !this.match(0) && !this.match(16)) {\n this.raise(ErrorMessages.UnsupportedSuper, {\n node\n });\n }\n\n return this.finishNode(node, \"Super\");\n }\n\n parsePrivateName() {\n const node = this.startNode();\n const id = this.startNodeAt(this.state.start + 1, new Position(this.state.curLine, this.state.start + 1 - this.state.lineStart, this.state.start + 1));\n const name = this.state.value;\n this.next();\n node.id = this.createIdentifier(id, name);\n return this.finishNode(node, \"PrivateName\");\n }\n\n parseFunctionOrFunctionSent() {\n const node = this.startNode();\n this.next();\n\n if (this.prodParam.hasYield && this.match(16)) {\n const meta = this.createIdentifier(this.startNodeAtNode(node), \"function\");\n this.next();\n\n if (this.match(98)) {\n this.expectPlugin(\"functionSent\");\n } else if (!this.hasPlugin(\"functionSent\")) {\n this.unexpected();\n }\n\n return this.parseMetaProperty(node, meta, \"sent\");\n }\n\n return this.parseFunction(node);\n }\n\n parseMetaProperty(node, meta, propertyName) {\n node.meta = meta;\n const containsEsc = this.state.containsEsc;\n node.property = this.parseIdentifier(true);\n\n if (node.property.name !== propertyName || containsEsc) {\n this.raise(ErrorMessages.UnsupportedMetaProperty, {\n node: node.property\n }, meta.name, propertyName);\n }\n\n return this.finishNode(node, \"MetaProperty\");\n }\n\n parseImportMetaProperty(node) {\n const id = this.createIdentifier(this.startNodeAtNode(node), \"import\");\n this.next();\n\n if (this.isContextual(96)) {\n if (!this.inModule) {\n this.raise(SourceTypeModuleErrorMessages.ImportMetaOutsideModule, {\n node: id\n });\n }\n\n this.sawUnambiguousESM = true;\n }\n\n return this.parseMetaProperty(node, id, \"meta\");\n }\n\n parseLiteralAtNode(value, type, node) {\n this.addExtra(node, \"rawValue\", value);\n this.addExtra(node, \"raw\", this.input.slice(node.start, this.state.end));\n node.value = value;\n this.next();\n return this.finishNode(node, type);\n }\n\n parseLiteral(value, type) {\n const node = this.startNode();\n return this.parseLiteralAtNode(value, type, node);\n }\n\n parseStringLiteral(value) {\n return this.parseLiteral(value, \"StringLiteral\");\n }\n\n parseNumericLiteral(value) {\n return this.parseLiteral(value, \"NumericLiteral\");\n }\n\n parseBigIntLiteral(value) {\n return this.parseLiteral(value, \"BigIntLiteral\");\n }\n\n parseDecimalLiteral(value) {\n return this.parseLiteral(value, \"DecimalLiteral\");\n }\n\n parseRegExpLiteral(value) {\n const node = this.parseLiteral(value.value, \"RegExpLiteral\");\n node.pattern = value.pattern;\n node.flags = value.flags;\n return node;\n }\n\n parseBooleanLiteral(value) {\n const node = this.startNode();\n node.value = value;\n this.next();\n return this.finishNode(node, \"BooleanLiteral\");\n }\n\n parseNullLiteral() {\n const node = this.startNode();\n this.next();\n return this.finishNode(node, \"NullLiteral\");\n }\n\n parseParenAndDistinguishExpression(canBeArrow) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let val;\n this.next();\n this.expressionScope.enter(newArrowHeadScope());\n const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;\n const oldInFSharpPipelineDirectBody = this.state.inFSharpPipelineDirectBody;\n this.state.maybeInArrowParameters = true;\n this.state.inFSharpPipelineDirectBody = false;\n const innerStartPos = this.state.start;\n const innerStartLoc = this.state.startLoc;\n const exprList = [];\n const refExpressionErrors = new ExpressionErrors();\n let first = true;\n let spreadStartLoc;\n let optionalCommaStartLoc;\n\n while (!this.match(11)) {\n if (first) {\n first = false;\n } else {\n this.expect(12, refExpressionErrors.optionalParametersLoc === null ? null : refExpressionErrors.optionalParametersLoc);\n\n if (this.match(11)) {\n optionalCommaStartLoc = this.state.startLoc;\n break;\n }\n }\n\n if (this.match(21)) {\n const spreadNodeStartPos = this.state.start;\n const spreadNodeStartLoc = this.state.startLoc;\n spreadStartLoc = this.state.startLoc;\n exprList.push(this.parseParenItem(this.parseRestBinding(), spreadNodeStartPos, spreadNodeStartLoc));\n\n if (!this.checkCommaAfterRest(41)) {\n break;\n }\n } else {\n exprList.push(this.parseMaybeAssignAllowIn(refExpressionErrors, this.parseParenItem));\n }\n }\n\n const innerEndLoc = this.state.lastTokEndLoc;\n this.expect(11);\n this.state.maybeInArrowParameters = oldMaybeInArrowParameters;\n this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;\n let arrowNode = this.startNodeAt(startPos, startLoc);\n\n if (canBeArrow && this.shouldParseArrow(exprList) && (arrowNode = this.parseArrow(arrowNode))) {\n this.expressionScope.validateAsPattern();\n this.expressionScope.exit();\n this.parseArrowExpression(arrowNode, exprList, false);\n return arrowNode;\n }\n\n this.expressionScope.exit();\n\n if (!exprList.length) {\n this.unexpected(this.state.lastTokStartLoc);\n }\n\n if (optionalCommaStartLoc) this.unexpected(optionalCommaStartLoc);\n if (spreadStartLoc) this.unexpected(spreadStartLoc);\n this.checkExpressionErrors(refExpressionErrors, true);\n this.toReferencedListDeep(exprList, true);\n\n if (exprList.length > 1) {\n val = this.startNodeAt(innerStartPos, innerStartLoc);\n val.expressions = exprList;\n this.finishNode(val, \"SequenceExpression\");\n this.resetEndLocation(val, innerEndLoc);\n } else {\n val = exprList[0];\n }\n\n if (!this.options.createParenthesizedExpressions) {\n this.addExtra(val, \"parenthesized\", true);\n this.addExtra(val, \"parenStart\", startPos);\n this.takeSurroundingComments(val, startPos, indexes.get(this.state.lastTokEndLoc));\n return val;\n }\n\n const parenExpression = this.startNodeAt(startPos, startLoc);\n parenExpression.expression = val;\n this.finishNode(parenExpression, \"ParenthesizedExpression\");\n return parenExpression;\n }\n\n shouldParseArrow(params) {\n return !this.canInsertSemicolon();\n }\n\n parseArrow(node) {\n if (this.eat(19)) {\n return node;\n }\n }\n\n parseParenItem(node, startPos, startLoc) {\n return node;\n }\n\n parseNewOrNewTarget() {\n const node = this.startNode();\n this.next();\n\n if (this.match(16)) {\n const meta = this.createIdentifier(this.startNodeAtNode(node), \"new\");\n this.next();\n const metaProp = this.parseMetaProperty(node, meta, \"target\");\n\n if (!this.scope.inNonArrowFunction && !this.scope.inClass) {\n this.raise(ErrorMessages.UnexpectedNewTarget, {\n node: metaProp\n });\n }\n\n return metaProp;\n }\n\n return this.parseNew(node);\n }\n\n parseNew(node) {\n node.callee = this.parseNoCallExpr();\n\n if (node.callee.type === \"Import\") {\n this.raise(ErrorMessages.ImportCallNotNewExpression, {\n node: node.callee\n });\n } else if (this.isOptionalChain(node.callee)) {\n this.raise(ErrorMessages.OptionalChainingNoNew, {\n at: this.state.lastTokEndLoc\n });\n } else if (this.eat(18)) {\n this.raise(ErrorMessages.OptionalChainingNoNew, {\n at: this.state.startLoc\n });\n }\n\n this.parseNewArguments(node);\n return this.finishNode(node, \"NewExpression\");\n }\n\n parseNewArguments(node) {\n if (this.eat(10)) {\n const args = this.parseExprList(11);\n this.toReferencedList(args);\n node.arguments = args;\n } else {\n node.arguments = [];\n }\n }\n\n parseTemplateElement(isTagged) {\n const {\n start,\n startLoc,\n end,\n value\n } = this.state;\n const elemStart = start + 1;\n const elem = this.startNodeAt(elemStart, createPositionWithColumnOffset(startLoc, 1));\n\n if (value === null) {\n if (!isTagged) {\n this.raise(ErrorMessages.InvalidEscapeSequenceTemplate, {\n at: createPositionWithColumnOffset(startLoc, 2)\n });\n }\n }\n\n const isTail = this.match(24);\n const endOffset = isTail ? -1 : -2;\n const elemEnd = end + endOffset;\n elem.value = {\n raw: this.input.slice(elemStart, elemEnd).replace(/\\r\\n?/g, \"\\n\"),\n cooked: value === null ? null : value.slice(1, endOffset)\n };\n elem.tail = isTail;\n this.next();\n this.finishNode(elem, \"TemplateElement\");\n this.resetEndLocation(elem, createPositionWithColumnOffset(this.state.lastTokEndLoc, endOffset));\n return elem;\n }\n\n parseTemplate(isTagged) {\n const node = this.startNode();\n node.expressions = [];\n let curElt = this.parseTemplateElement(isTagged);\n node.quasis = [curElt];\n\n while (!curElt.tail) {\n node.expressions.push(this.parseTemplateSubstitution());\n this.readTemplateContinuation();\n node.quasis.push(curElt = this.parseTemplateElement(isTagged));\n }\n\n return this.finishNode(node, \"TemplateLiteral\");\n }\n\n parseTemplateSubstitution() {\n return this.parseExpression();\n }\n\n parseObjectLike(close, isPattern, isRecord, refExpressionErrors) {\n if (isRecord) {\n this.expectPlugin(\"recordAndTuple\");\n }\n\n const oldInFSharpPipelineDirectBody = this.state.inFSharpPipelineDirectBody;\n this.state.inFSharpPipelineDirectBody = false;\n const propHash = Object.create(null);\n let first = true;\n const node = this.startNode();\n node.properties = [];\n this.next();\n\n while (!this.match(close)) {\n if (first) {\n first = false;\n } else {\n this.expect(12);\n\n if (this.match(close)) {\n this.addTrailingCommaExtraToNode(node);\n break;\n }\n }\n\n let prop;\n\n if (isPattern) {\n prop = this.parseBindingProperty();\n } else {\n prop = this.parsePropertyDefinition(refExpressionErrors);\n this.checkProto(prop, isRecord, propHash, refExpressionErrors);\n }\n\n if (isRecord && !this.isObjectProperty(prop) && prop.type !== \"SpreadElement\") {\n this.raise(ErrorMessages.InvalidRecordProperty, {\n node: prop\n });\n }\n\n if (prop.shorthand) {\n this.addExtra(prop, \"shorthand\", true);\n }\n\n node.properties.push(prop);\n }\n\n this.next();\n this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;\n let type = \"ObjectExpression\";\n\n if (isPattern) {\n type = \"ObjectPattern\";\n } else if (isRecord) {\n type = \"RecordExpression\";\n }\n\n return this.finishNode(node, type);\n }\n\n addTrailingCommaExtraToNode(node) {\n this.addExtra(node, \"trailingComma\", this.state.lastTokStart);\n this.addExtra(node, \"trailingCommaLoc\", this.state.lastTokStartLoc, false);\n }\n\n maybeAsyncOrAccessorProp(prop) {\n return !prop.computed && prop.key.type === \"Identifier\" && (this.isLiteralPropertyName() || this.match(0) || this.match(51));\n }\n\n parsePropertyDefinition(refExpressionErrors) {\n let decorators = [];\n\n if (this.match(26)) {\n if (this.hasPlugin(\"decorators\")) {\n this.raise(ErrorMessages.UnsupportedPropertyDecorator, {\n at: this.state.startLoc\n });\n }\n\n while (this.match(26)) {\n decorators.push(this.parseDecorator());\n }\n }\n\n const prop = this.startNode();\n let isAsync = false;\n let isAccessor = false;\n let startPos;\n let startLoc;\n\n if (this.match(21)) {\n if (decorators.length) this.unexpected();\n return this.parseSpread();\n }\n\n if (decorators.length) {\n prop.decorators = decorators;\n decorators = [];\n }\n\n prop.method = false;\n\n if (refExpressionErrors) {\n startPos = this.state.start;\n startLoc = this.state.startLoc;\n }\n\n let isGenerator = this.eat(51);\n this.parsePropertyNamePrefixOperator(prop);\n const containsEsc = this.state.containsEsc;\n const key = this.parsePropertyName(prop);\n\n if (!isGenerator && !containsEsc && this.maybeAsyncOrAccessorProp(prop)) {\n const keyName = key.name;\n\n if (keyName === \"async\" && !this.hasPrecedingLineBreak()) {\n isAsync = true;\n this.resetPreviousNodeTrailingComments(key);\n isGenerator = this.eat(51);\n this.parsePropertyName(prop);\n }\n\n if (keyName === \"get\" || keyName === \"set\") {\n isAccessor = true;\n this.resetPreviousNodeTrailingComments(key);\n prop.kind = keyName;\n\n if (this.match(51)) {\n isGenerator = true;\n this.raise(ErrorMessages.AccessorIsGenerator, {\n at: this.state.curPosition()\n }, keyName);\n this.next();\n }\n\n this.parsePropertyName(prop);\n }\n }\n\n this.parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, false, isAccessor, refExpressionErrors);\n return prop;\n }\n\n getGetterSetterExpectedParamCount(method) {\n return method.kind === \"get\" ? 0 : 1;\n }\n\n getObjectOrClassMethodParams(method) {\n return method.params;\n }\n\n checkGetterSetterParams(method) {\n var _params;\n\n const paramCount = this.getGetterSetterExpectedParamCount(method);\n const params = this.getObjectOrClassMethodParams(method);\n\n if (params.length !== paramCount) {\n this.raise(method.kind === \"get\" ? ErrorMessages.BadGetterArity : ErrorMessages.BadSetterArity, {\n node: method\n });\n }\n\n if (method.kind === \"set\" && ((_params = params[params.length - 1]) == null ? void 0 : _params.type) === \"RestElement\") {\n this.raise(ErrorMessages.BadSetterRestParameter, {\n node: method\n });\n }\n }\n\n parseObjectMethod(prop, isGenerator, isAsync, isPattern, isAccessor) {\n if (isAccessor) {\n this.parseMethod(prop, isGenerator, false, false, false, \"ObjectMethod\");\n this.checkGetterSetterParams(prop);\n return prop;\n }\n\n if (isAsync || isGenerator || this.match(10)) {\n if (isPattern) this.unexpected();\n prop.kind = \"method\";\n prop.method = true;\n return this.parseMethod(prop, isGenerator, isAsync, false, false, \"ObjectMethod\");\n }\n }\n\n parseObjectProperty(prop, startPos, startLoc, isPattern, refExpressionErrors) {\n prop.shorthand = false;\n\n if (this.eat(14)) {\n prop.value = isPattern ? this.parseMaybeDefault(this.state.start, this.state.startLoc) : this.parseMaybeAssignAllowIn(refExpressionErrors);\n return this.finishNode(prop, \"ObjectProperty\");\n }\n\n if (!prop.computed && prop.key.type === \"Identifier\") {\n this.checkReservedWord(prop.key.name, prop.key.loc.start, true, false);\n\n if (isPattern) {\n prop.value = this.parseMaybeDefault(startPos, startLoc, cloneIdentifier(prop.key));\n } else if (this.match(29)) {\n const shorthandAssignLoc = this.state.startLoc;\n\n if (refExpressionErrors != null) {\n if (refExpressionErrors.shorthandAssignLoc === null) {\n refExpressionErrors.shorthandAssignLoc = shorthandAssignLoc;\n }\n } else {\n this.raise(ErrorMessages.InvalidCoverInitializedName, {\n at: shorthandAssignLoc\n });\n }\n\n prop.value = this.parseMaybeDefault(startPos, startLoc, cloneIdentifier(prop.key));\n } else {\n prop.value = cloneIdentifier(prop.key);\n }\n\n prop.shorthand = true;\n return this.finishNode(prop, \"ObjectProperty\");\n }\n }\n\n parseObjPropValue(prop, startPos, startLoc, isGenerator, isAsync, isPattern, isAccessor, refExpressionErrors) {\n const node = this.parseObjectMethod(prop, isGenerator, isAsync, isPattern, isAccessor) || this.parseObjectProperty(prop, startPos, startLoc, isPattern, refExpressionErrors);\n if (!node) this.unexpected();\n return node;\n }\n\n parsePropertyName(prop) {\n if (this.eat(0)) {\n prop.computed = true;\n prop.key = this.parseMaybeAssignAllowIn();\n this.expect(3);\n } else {\n const {\n type,\n value\n } = this.state;\n let key;\n\n if (tokenIsKeywordOrIdentifier(type)) {\n key = this.parseIdentifier(true);\n } else {\n switch (type) {\n case 126:\n key = this.parseNumericLiteral(value);\n break;\n\n case 125:\n key = this.parseStringLiteral(value);\n break;\n\n case 127:\n key = this.parseBigIntLiteral(value);\n break;\n\n case 128:\n key = this.parseDecimalLiteral(value);\n break;\n\n case 130:\n {\n this.raise(ErrorMessages.UnexpectedPrivateField, {\n at: createPositionWithColumnOffset(this.state.startLoc, 1)\n });\n key = this.parsePrivateName();\n break;\n }\n\n default:\n throw this.unexpected();\n }\n }\n\n prop.key = key;\n\n if (type !== 130) {\n prop.computed = false;\n }\n }\n\n return prop.key;\n }\n\n initFunction(node, isAsync) {\n node.id = null;\n node.generator = false;\n node.async = !!isAsync;\n }\n\n parseMethod(node, isGenerator, isAsync, isConstructor, allowDirectSuper, type, inClassScope = false) {\n this.initFunction(node, isAsync);\n node.generator = !!isGenerator;\n const allowModifiers = isConstructor;\n this.scope.enter(SCOPE_FUNCTION | SCOPE_SUPER | (inClassScope ? SCOPE_CLASS : 0) | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));\n this.prodParam.enter(functionFlags(isAsync, node.generator));\n this.parseFunctionParams(node, allowModifiers);\n this.parseFunctionBodyAndFinish(node, type, true);\n this.prodParam.exit();\n this.scope.exit();\n return node;\n }\n\n parseArrayLike(close, canBePattern, isTuple, refExpressionErrors) {\n if (isTuple) {\n this.expectPlugin(\"recordAndTuple\");\n }\n\n const oldInFSharpPipelineDirectBody = this.state.inFSharpPipelineDirectBody;\n this.state.inFSharpPipelineDirectBody = false;\n const node = this.startNode();\n this.next();\n node.elements = this.parseExprList(close, !isTuple, refExpressionErrors, node);\n this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;\n return this.finishNode(node, isTuple ? \"TupleExpression\" : \"ArrayExpression\");\n }\n\n parseArrowExpression(node, params, isAsync, trailingCommaLoc) {\n this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW);\n let flags = functionFlags(isAsync, false);\n\n if (!this.match(5) && this.prodParam.hasIn) {\n flags |= PARAM_IN;\n }\n\n this.prodParam.enter(flags);\n this.initFunction(node, isAsync);\n const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;\n\n if (params) {\n this.state.maybeInArrowParameters = true;\n this.setArrowFunctionParameters(node, params, trailingCommaLoc);\n }\n\n this.state.maybeInArrowParameters = false;\n this.parseFunctionBody(node, true);\n this.prodParam.exit();\n this.scope.exit();\n this.state.maybeInArrowParameters = oldMaybeInArrowParameters;\n return this.finishNode(node, \"ArrowFunctionExpression\");\n }\n\n setArrowFunctionParameters(node, params, trailingCommaLoc) {\n node.params = this.toAssignableList(params, trailingCommaLoc, false);\n }\n\n parseFunctionBodyAndFinish(node, type, isMethod = false) {\n this.parseFunctionBody(node, false, isMethod);\n this.finishNode(node, type);\n }\n\n parseFunctionBody(node, allowExpression, isMethod = false) {\n const isExpression = allowExpression && !this.match(5);\n this.expressionScope.enter(newExpressionScope());\n\n if (isExpression) {\n node.body = this.parseMaybeAssign();\n this.checkParams(node, false, allowExpression, false);\n } else {\n const oldStrict = this.state.strict;\n const oldLabels = this.state.labels;\n this.state.labels = [];\n this.prodParam.enter(this.prodParam.currentFlags() | PARAM_RETURN);\n node.body = this.parseBlock(true, false, hasStrictModeDirective => {\n const nonSimple = !this.isSimpleParamList(node.params);\n\n if (hasStrictModeDirective && nonSimple) {\n const errorOrigin = (node.kind === \"method\" || node.kind === \"constructor\") && !!node.key ? {\n at: node.key.loc.end\n } : {\n node\n };\n this.raise(ErrorMessages.IllegalLanguageModeDirective, errorOrigin);\n }\n\n const strictModeChanged = !oldStrict && this.state.strict;\n this.checkParams(node, !this.state.strict && !allowExpression && !isMethod && !nonSimple, allowExpression, strictModeChanged);\n\n if (this.state.strict && node.id) {\n this.checkLVal(node.id, \"function name\", BIND_OUTSIDE, undefined, undefined, strictModeChanged);\n }\n });\n this.prodParam.exit();\n this.state.labels = oldLabels;\n }\n\n this.expressionScope.exit();\n }\n\n isSimpleParamList(params) {\n for (let i = 0, len = params.length; i < len; i++) {\n if (params[i].type !== \"Identifier\") return false;\n }\n\n return true;\n }\n\n checkParams(node, allowDuplicates, isArrowFunction, strictModeChanged = true) {\n const checkClashes = new Set();\n\n for (const param of node.params) {\n this.checkLVal(param, \"function parameter list\", BIND_VAR, allowDuplicates ? null : checkClashes, undefined, strictModeChanged);\n }\n }\n\n parseExprList(close, allowEmpty, refExpressionErrors, nodeForExtra) {\n const elts = [];\n let first = true;\n\n while (!this.eat(close)) {\n if (first) {\n first = false;\n } else {\n this.expect(12);\n\n if (this.match(close)) {\n if (nodeForExtra) {\n this.addTrailingCommaExtraToNode(nodeForExtra);\n }\n\n this.next();\n break;\n }\n }\n\n elts.push(this.parseExprListItem(allowEmpty, refExpressionErrors));\n }\n\n return elts;\n }\n\n parseExprListItem(allowEmpty, refExpressionErrors, allowPlaceholder) {\n let elt;\n\n if (this.match(12)) {\n if (!allowEmpty) {\n this.raise(ErrorMessages.UnexpectedToken, {\n at: this.state.curPosition()\n }, \",\");\n }\n\n elt = null;\n } else if (this.match(21)) {\n const spreadNodeStartPos = this.state.start;\n const spreadNodeStartLoc = this.state.startLoc;\n elt = this.parseParenItem(this.parseSpread(refExpressionErrors), spreadNodeStartPos, spreadNodeStartLoc);\n } else if (this.match(17)) {\n this.expectPlugin(\"partialApplication\");\n\n if (!allowPlaceholder) {\n this.raise(ErrorMessages.UnexpectedArgumentPlaceholder, {\n at: this.state.startLoc\n });\n }\n\n const node = this.startNode();\n this.next();\n elt = this.finishNode(node, \"ArgumentPlaceholder\");\n } else {\n elt = this.parseMaybeAssignAllowIn(refExpressionErrors, this.parseParenItem);\n }\n\n return elt;\n }\n\n parseIdentifier(liberal) {\n const node = this.startNode();\n const name = this.parseIdentifierName(node.start, liberal);\n return this.createIdentifier(node, name);\n }\n\n createIdentifier(node, name) {\n node.name = name;\n node.loc.identifierName = name;\n return this.finishNode(node, \"Identifier\");\n }\n\n parseIdentifierName(pos, liberal) {\n let name;\n const {\n startLoc,\n type\n } = this.state;\n\n if (tokenIsKeywordOrIdentifier(type)) {\n name = this.state.value;\n } else {\n throw this.unexpected();\n }\n\n const tokenIsKeyword = tokenKeywordOrIdentifierIsKeyword(type);\n\n if (liberal) {\n if (tokenIsKeyword) {\n this.replaceToken(124);\n }\n } else {\n this.checkReservedWord(name, startLoc, tokenIsKeyword, false);\n }\n\n this.next();\n return name;\n }\n\n checkReservedWord(word, startLoc, checkKeywords, isBinding) {\n if (word.length > 10) {\n return;\n }\n\n if (!canBeReservedWord(word)) {\n return;\n }\n\n if (word === \"yield\") {\n if (this.prodParam.hasYield) {\n this.raise(ErrorMessages.YieldBindingIdentifier, {\n at: startLoc\n });\n return;\n }\n } else if (word === \"await\") {\n if (this.prodParam.hasAwait) {\n this.raise(ErrorMessages.AwaitBindingIdentifier, {\n at: startLoc\n });\n return;\n }\n\n if (this.scope.inStaticBlock) {\n this.raise(ErrorMessages.AwaitBindingIdentifierInStaticBlock, {\n at: startLoc\n });\n return;\n }\n\n this.expressionScope.recordAsyncArrowParametersError(ErrorMessages.AwaitBindingIdentifier, startLoc);\n } else if (word === \"arguments\") {\n if (this.scope.inClassAndNotInNonArrowFunction) {\n this.raise(ErrorMessages.ArgumentsInClass, {\n at: startLoc\n });\n return;\n }\n }\n\n if (checkKeywords && isKeyword(word)) {\n this.raise(ErrorMessages.UnexpectedKeyword, {\n at: startLoc\n }, word);\n return;\n }\n\n const reservedTest = !this.state.strict ? isReservedWord : isBinding ? isStrictBindReservedWord : isStrictReservedWord;\n\n if (reservedTest(word, this.inModule)) {\n this.raise(ErrorMessages.UnexpectedReservedWord, {\n at: startLoc\n }, word);\n }\n }\n\n isAwaitAllowed() {\n if (this.prodParam.hasAwait) return true;\n\n if (this.options.allowAwaitOutsideFunction && !this.scope.inFunction) {\n return true;\n }\n\n return false;\n }\n\n parseAwait(startPos, startLoc) {\n const node = this.startNodeAt(startPos, startLoc);\n this.expressionScope.recordParameterInitializerError(node.loc.start, ErrorMessages.AwaitExpressionFormalParameter);\n\n if (this.eat(51)) {\n this.raise(ErrorMessages.ObsoleteAwaitStar, {\n node\n });\n }\n\n if (!this.scope.inFunction && !this.options.allowAwaitOutsideFunction) {\n if (this.isAmbiguousAwait()) {\n this.ambiguousScriptDifferentAst = true;\n } else {\n this.sawUnambiguousESM = true;\n }\n }\n\n if (!this.state.soloAwait) {\n node.argument = this.parseMaybeUnary(null, true);\n }\n\n return this.finishNode(node, \"AwaitExpression\");\n }\n\n isAmbiguousAwait() {\n if (this.hasPrecedingLineBreak()) return true;\n const {\n type\n } = this.state;\n return type === 49 || type === 10 || type === 0 || tokenIsTemplate(type) || type === 129 || type === 52 || this.hasPlugin(\"v8intrinsic\") && type === 50;\n }\n\n parseYield() {\n const node = this.startNode();\n this.expressionScope.recordParameterInitializerError(node.loc.start, ErrorMessages.YieldInParameter);\n this.next();\n let delegating = false;\n let argument = null;\n\n if (!this.hasPrecedingLineBreak()) {\n delegating = this.eat(51);\n\n switch (this.state.type) {\n case 13:\n case 131:\n case 8:\n case 11:\n case 3:\n case 9:\n case 14:\n case 12:\n if (!delegating) break;\n\n default:\n argument = this.parseMaybeAssign();\n }\n }\n\n node.delegate = delegating;\n node.argument = argument;\n return this.finishNode(node, \"YieldExpression\");\n }\n\n checkPipelineAtInfixOperator(left, leftStartLoc) {\n if (this.hasPlugin([\"pipelineOperator\", {\n proposal: \"smart\"\n }])) {\n if (left.type === \"SequenceExpression\") {\n this.raise(ErrorMessages.PipelineHeadSequenceExpression, {\n at: leftStartLoc\n });\n }\n }\n }\n\n parseSmartPipelineBodyInStyle(childExpr, startPos, startLoc) {\n const bodyNode = this.startNodeAt(startPos, startLoc);\n\n if (this.isSimpleReference(childExpr)) {\n bodyNode.callee = childExpr;\n return this.finishNode(bodyNode, \"PipelineBareFunction\");\n } else {\n this.checkSmartPipeTopicBodyEarlyErrors(startLoc);\n bodyNode.expression = childExpr;\n return this.finishNode(bodyNode, \"PipelineTopicExpression\");\n }\n }\n\n isSimpleReference(expression) {\n switch (expression.type) {\n case \"MemberExpression\":\n return !expression.computed && this.isSimpleReference(expression.object);\n\n case \"Identifier\":\n return true;\n\n default:\n return false;\n }\n }\n\n checkSmartPipeTopicBodyEarlyErrors(startLoc) {\n if (this.match(19)) {\n throw this.raise(ErrorMessages.PipelineBodyNoArrow, {\n at: this.state.startLoc\n });\n }\n\n if (!this.topicReferenceWasUsedInCurrentContext()) {\n this.raise(ErrorMessages.PipelineTopicUnused, {\n at: startLoc\n });\n }\n }\n\n withTopicBindingContext(callback) {\n const outerContextTopicState = this.state.topicContext;\n this.state.topicContext = {\n maxNumOfResolvableTopics: 1,\n maxTopicIndex: null\n };\n\n try {\n return callback();\n } finally {\n this.state.topicContext = outerContextTopicState;\n }\n }\n\n withSmartMixTopicForbiddingContext(callback) {\n if (this.hasPlugin([\"pipelineOperator\", {\n proposal: \"smart\"\n }])) {\n const outerContextTopicState = this.state.topicContext;\n this.state.topicContext = {\n maxNumOfResolvableTopics: 0,\n maxTopicIndex: null\n };\n\n try {\n return callback();\n } finally {\n this.state.topicContext = outerContextTopicState;\n }\n } else {\n return callback();\n }\n }\n\n withSoloAwaitPermittingContext(callback) {\n const outerContextSoloAwaitState = this.state.soloAwait;\n this.state.soloAwait = true;\n\n try {\n return callback();\n } finally {\n this.state.soloAwait = outerContextSoloAwaitState;\n }\n }\n\n allowInAnd(callback) {\n const flags = this.prodParam.currentFlags();\n const prodParamToSet = PARAM_IN & ~flags;\n\n if (prodParamToSet) {\n this.prodParam.enter(flags | PARAM_IN);\n\n try {\n return callback();\n } finally {\n this.prodParam.exit();\n }\n }\n\n return callback();\n }\n\n disallowInAnd(callback) {\n const flags = this.prodParam.currentFlags();\n const prodParamToClear = PARAM_IN & flags;\n\n if (prodParamToClear) {\n this.prodParam.enter(flags & ~PARAM_IN);\n\n try {\n return callback();\n } finally {\n this.prodParam.exit();\n }\n }\n\n return callback();\n }\n\n registerTopicReference() {\n this.state.topicContext.maxTopicIndex = 0;\n }\n\n topicReferenceIsAllowedInCurrentContext() {\n return this.state.topicContext.maxNumOfResolvableTopics >= 1;\n }\n\n topicReferenceWasUsedInCurrentContext() {\n return this.state.topicContext.maxTopicIndex != null && this.state.topicContext.maxTopicIndex >= 0;\n }\n\n parseFSharpPipelineBody(prec) {\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n this.state.potentialArrowAt = this.state.start;\n const oldInFSharpPipelineDirectBody = this.state.inFSharpPipelineDirectBody;\n this.state.inFSharpPipelineDirectBody = true;\n const ret = this.parseExprOp(this.parseMaybeUnaryOrPrivate(), startPos, startLoc, prec);\n this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody;\n return ret;\n }\n\n parseModuleExpression() {\n this.expectPlugin(\"moduleBlocks\");\n const node = this.startNode();\n this.next();\n this.eat(5);\n const revertScopes = this.initializeScopes(true);\n this.enterInitialScopes();\n const program = this.startNode();\n\n try {\n node.body = this.parseProgram(program, 8, \"module\");\n } finally {\n revertScopes();\n }\n\n this.eat(8);\n return this.finishNode(node, \"ModuleExpression\");\n }\n\n parsePropertyNamePrefixOperator(prop) {}\n\n}\n\nconst loopLabel = {\n kind: \"loop\"\n},\n switchLabel = {\n kind: \"switch\"\n};\nconst FUNC_NO_FLAGS = 0b000,\n FUNC_STATEMENT = 0b001,\n FUNC_HANGING_STATEMENT = 0b010,\n FUNC_NULLABLE_ID = 0b100;\nconst loneSurrogate = /[\\uD800-\\uDFFF]/u;\nconst keywordRelationalOperator = /in(?:stanceof)?/y;\n\nfunction babel7CompatTokens(tokens, input) {\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const {\n type\n } = token;\n\n if (typeof type === \"number\") {\n {\n if (type === 130) {\n const {\n loc,\n start,\n value,\n end\n } = token;\n const hashEndPos = start + 1;\n const hashEndLoc = createPositionWithColumnOffset(loc.start, 1);\n tokens.splice(i, 1, new Token({\n type: getExportedToken(27),\n value: \"#\",\n start: start,\n end: hashEndPos,\n startLoc: loc.start,\n endLoc: hashEndLoc\n }), new Token({\n type: getExportedToken(124),\n value: value,\n start: hashEndPos,\n end: end,\n startLoc: hashEndLoc,\n endLoc: loc.end\n }));\n i++;\n continue;\n }\n\n if (tokenIsTemplate(type)) {\n const {\n loc,\n start,\n value,\n end\n } = token;\n const backquoteEnd = start + 1;\n const backquoteEndLoc = createPositionWithColumnOffset(loc.start, 1);\n let startToken;\n\n if (input.charCodeAt(start) === 96) {\n startToken = new Token({\n type: getExportedToken(22),\n value: \"`\",\n start: start,\n end: backquoteEnd,\n startLoc: loc.start,\n endLoc: backquoteEndLoc\n });\n } else {\n startToken = new Token({\n type: getExportedToken(8),\n value: \"}\",\n start: start,\n end: backquoteEnd,\n startLoc: loc.start,\n endLoc: backquoteEndLoc\n });\n }\n\n let templateValue, templateElementEnd, templateElementEndLoc, endToken;\n\n if (type === 24) {\n templateElementEnd = end - 1;\n templateElementEndLoc = createPositionWithColumnOffset(loc.end, -1);\n templateValue = value === null ? null : value.slice(1, -1);\n endToken = new Token({\n type: getExportedToken(22),\n value: \"`\",\n start: templateElementEnd,\n end: end,\n startLoc: templateElementEndLoc,\n endLoc: loc.end\n });\n } else {\n templateElementEnd = end - 2;\n templateElementEndLoc = createPositionWithColumnOffset(loc.end, -2);\n templateValue = value === null ? null : value.slice(1, -2);\n endToken = new Token({\n type: getExportedToken(23),\n value: \"${\",\n start: templateElementEnd,\n end: end,\n startLoc: templateElementEndLoc,\n endLoc: loc.end\n });\n }\n\n tokens.splice(i, 1, startToken, new Token({\n type: getExportedToken(20),\n value: templateValue,\n start: backquoteEnd,\n end: templateElementEnd,\n startLoc: backquoteEndLoc,\n endLoc: templateElementEndLoc\n }), endToken);\n i += 2;\n continue;\n }\n }\n token.type = getExportedToken(type);\n }\n }\n\n return tokens;\n}\n\nclass StatementParser extends ExpressionParser {\n parseTopLevel(file, program) {\n file.program = this.parseProgram(program);\n file.comments = this.state.comments;\n\n if (this.options.tokens) {\n file.tokens = babel7CompatTokens(this.tokens, this.input);\n }\n\n return this.finishNode(file, \"File\");\n }\n\n parseProgram(program, end = 131, sourceType = this.options.sourceType) {\n program.sourceType = sourceType;\n program.interpreter = this.parseInterpreterDirective();\n this.parseBlockBody(program, true, true, end);\n\n if (this.inModule && !this.options.allowUndeclaredExports && this.scope.undefinedExports.size > 0) {\n for (const [name, loc] of Array.from(this.scope.undefinedExports)) {\n this.raise(ErrorMessages.ModuleExportUndefined, {\n at: loc\n }, name);\n }\n }\n\n return this.finishNode(program, \"Program\");\n }\n\n stmtToDirective(stmt) {\n const directive = stmt;\n directive.type = \"Directive\";\n directive.value = directive.expression;\n delete directive.expression;\n const directiveLiteral = directive.value;\n const expressionValue = directiveLiteral.value;\n const raw = this.input.slice(directiveLiteral.start, directiveLiteral.end);\n const val = directiveLiteral.value = raw.slice(1, -1);\n this.addExtra(directiveLiteral, \"raw\", raw);\n this.addExtra(directiveLiteral, \"rawValue\", val);\n this.addExtra(directiveLiteral, \"expressionValue\", expressionValue);\n directiveLiteral.type = \"DirectiveLiteral\";\n return directive;\n }\n\n parseInterpreterDirective() {\n if (!this.match(28)) {\n return null;\n }\n\n const node = this.startNode();\n node.value = this.state.value;\n this.next();\n return this.finishNode(node, \"InterpreterDirective\");\n }\n\n isLet(context) {\n if (!this.isContextual(95)) {\n return false;\n }\n\n return this.isLetKeyword(context);\n }\n\n isLetKeyword(context) {\n const next = this.nextTokenStart();\n const nextCh = this.codePointAtPos(next);\n\n if (nextCh === 92 || nextCh === 91) {\n return true;\n }\n\n if (context) return false;\n if (nextCh === 123) return true;\n\n if (isIdentifierStart(nextCh)) {\n keywordRelationalOperator.lastIndex = next;\n\n if (keywordRelationalOperator.test(this.input)) {\n const endCh = this.codePointAtPos(keywordRelationalOperator.lastIndex);\n\n if (!isIdentifierChar(endCh) && endCh !== 92) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n }\n\n parseStatement(context, topLevel) {\n if (this.match(26)) {\n this.parseDecorators(true);\n }\n\n return this.parseStatementContent(context, topLevel);\n }\n\n parseStatementContent(context, topLevel) {\n let starttype = this.state.type;\n const node = this.startNode();\n let kind;\n\n if (this.isLet(context)) {\n starttype = 70;\n kind = \"let\";\n }\n\n switch (starttype) {\n case 56:\n return this.parseBreakContinueStatement(node, true);\n\n case 59:\n return this.parseBreakContinueStatement(node, false);\n\n case 60:\n return this.parseDebuggerStatement(node);\n\n case 86:\n return this.parseDoStatement(node);\n\n case 87:\n return this.parseForStatement(node);\n\n case 64:\n if (this.lookaheadCharCode() === 46) break;\n\n if (context) {\n if (this.state.strict) {\n this.raise(ErrorMessages.StrictFunction, {\n at: this.state.startLoc\n });\n } else if (context !== \"if\" && context !== \"label\") {\n this.raise(ErrorMessages.SloppyFunction, {\n at: this.state.startLoc\n });\n }\n }\n\n return this.parseFunctionStatement(node, false, !context);\n\n case 76:\n if (context) this.unexpected();\n return this.parseClass(node, true);\n\n case 65:\n return this.parseIfStatement(node);\n\n case 66:\n return this.parseReturnStatement(node);\n\n case 67:\n return this.parseSwitchStatement(node);\n\n case 68:\n return this.parseThrowStatement(node);\n\n case 69:\n return this.parseTryStatement(node);\n\n case 71:\n case 70:\n kind = kind || this.state.value;\n\n if (context && kind !== \"var\") {\n this.raise(ErrorMessages.UnexpectedLexicalDeclaration, {\n at: this.state.startLoc\n });\n }\n\n return this.parseVarStatement(node, kind);\n\n case 88:\n return this.parseWhileStatement(node);\n\n case 72:\n return this.parseWithStatement(node);\n\n case 5:\n return this.parseBlock();\n\n case 13:\n return this.parseEmptyStatement(node);\n\n case 79:\n {\n const nextTokenCharCode = this.lookaheadCharCode();\n\n if (nextTokenCharCode === 40 || nextTokenCharCode === 46) {\n break;\n }\n }\n\n case 78:\n {\n if (!this.options.allowImportExportEverywhere && !topLevel) {\n this.raise(ErrorMessages.UnexpectedImportExport, {\n at: this.state.startLoc\n });\n }\n\n this.next();\n let result;\n\n if (starttype === 79) {\n result = this.parseImport(node);\n\n if (result.type === \"ImportDeclaration\" && (!result.importKind || result.importKind === \"value\")) {\n this.sawUnambiguousESM = true;\n }\n } else {\n result = this.parseExport(node);\n\n if (result.type === \"ExportNamedDeclaration\" && (!result.exportKind || result.exportKind === \"value\") || result.type === \"ExportAllDeclaration\" && (!result.exportKind || result.exportKind === \"value\") || result.type === \"ExportDefaultDeclaration\") {\n this.sawUnambiguousESM = true;\n }\n }\n\n this.assertModuleNodeAllowed(node);\n return result;\n }\n\n default:\n {\n if (this.isAsyncFunction()) {\n if (context) {\n this.raise(ErrorMessages.AsyncFunctionInSingleStatementContext, {\n at: this.state.startLoc\n });\n }\n\n this.next();\n return this.parseFunctionStatement(node, true, !context);\n }\n }\n }\n\n const maybeName = this.state.value;\n const expr = this.parseExpression();\n\n if (tokenIsIdentifier(starttype) && expr.type === \"Identifier\" && this.eat(14)) {\n return this.parseLabeledStatement(node, maybeName, expr, context);\n } else {\n return this.parseExpressionStatement(node, expr);\n }\n }\n\n assertModuleNodeAllowed(node) {\n if (!this.options.allowImportExportEverywhere && !this.inModule) {\n this.raise(SourceTypeModuleErrorMessages.ImportOutsideModule, {\n node\n });\n }\n }\n\n takeDecorators(node) {\n const decorators = this.state.decoratorStack[this.state.decoratorStack.length - 1];\n\n if (decorators.length) {\n node.decorators = decorators;\n this.resetStartLocationFromNode(node, decorators[0]);\n this.state.decoratorStack[this.state.decoratorStack.length - 1] = [];\n }\n }\n\n canHaveLeadingDecorator() {\n return this.match(76);\n }\n\n parseDecorators(allowExport) {\n const currentContextDecorators = this.state.decoratorStack[this.state.decoratorStack.length - 1];\n\n while (this.match(26)) {\n const decorator = this.parseDecorator();\n currentContextDecorators.push(decorator);\n }\n\n if (this.match(78)) {\n if (!allowExport) {\n this.unexpected();\n }\n\n if (this.hasPlugin(\"decorators\") && !this.getPluginOption(\"decorators\", \"decoratorsBeforeExport\")) {\n this.raise(ErrorMessages.DecoratorExportClass, {\n at: this.state.startLoc\n });\n }\n } else if (!this.canHaveLeadingDecorator()) {\n throw this.raise(ErrorMessages.UnexpectedLeadingDecorator, {\n at: this.state.startLoc\n });\n }\n }\n\n parseDecorator() {\n this.expectOnePlugin([\"decorators-legacy\", \"decorators\"]);\n const node = this.startNode();\n this.next();\n\n if (this.hasPlugin(\"decorators\")) {\n this.state.decoratorStack.push([]);\n const startPos = this.state.start;\n const startLoc = this.state.startLoc;\n let expr;\n\n if (this.eat(10)) {\n expr = this.parseExpression();\n this.expect(11);\n } else {\n expr = this.parseIdentifier(false);\n\n while (this.eat(16)) {\n const node = this.startNodeAt(startPos, startLoc);\n node.object = expr;\n node.property = this.parseIdentifier(true);\n node.computed = false;\n expr = this.finishNode(node, \"MemberExpression\");\n }\n }\n\n node.expression = this.parseMaybeDecoratorArguments(expr);\n this.state.decoratorStack.pop();\n } else {\n node.expression = this.parseExprSubscripts();\n }\n\n return this.finishNode(node, \"Decorator\");\n }\n\n parseMaybeDecoratorArguments(expr) {\n if (this.eat(10)) {\n const node = this.startNodeAtNode(expr);\n node.callee = expr;\n node.arguments = this.parseCallExpressionArguments(11, false);\n this.toReferencedList(node.arguments);\n return this.finishNode(node, \"CallExpression\");\n }\n\n return expr;\n }\n\n parseBreakContinueStatement(node, isBreak) {\n this.next();\n\n if (this.isLineTerminator()) {\n node.label = null;\n } else {\n node.label = this.parseIdentifier();\n this.semicolon();\n }\n\n this.verifyBreakContinue(node, isBreak);\n return this.finishNode(node, isBreak ? \"BreakStatement\" : \"ContinueStatement\");\n }\n\n verifyBreakContinue(node, isBreak) {\n let i;\n\n for (i = 0; i < this.state.labels.length; ++i) {\n const lab = this.state.labels[i];\n\n if (node.label == null || lab.name === node.label.name) {\n if (lab.kind != null && (isBreak || lab.kind === \"loop\")) break;\n if (node.label && isBreak) break;\n }\n }\n\n if (i === this.state.labels.length) {\n this.raise(ErrorMessages.IllegalBreakContinue, {\n node\n }, isBreak ? \"break\" : \"continue\");\n }\n }\n\n parseDebuggerStatement(node) {\n this.next();\n this.semicolon();\n return this.finishNode(node, \"DebuggerStatement\");\n }\n\n parseHeaderExpression() {\n this.expect(10);\n const val = this.parseExpression();\n this.expect(11);\n return val;\n }\n\n parseDoStatement(node) {\n this.next();\n this.state.labels.push(loopLabel);\n node.body = this.withSmartMixTopicForbiddingContext(() => this.parseStatement(\"do\"));\n this.state.labels.pop();\n this.expect(88);\n node.test = this.parseHeaderExpression();\n this.eat(13);\n return this.finishNode(node, \"DoWhileStatement\");\n }\n\n parseForStatement(node) {\n this.next();\n this.state.labels.push(loopLabel);\n let awaitAt = null;\n\n if (this.isAwaitAllowed() && this.eatContextual(92)) {\n awaitAt = this.state.lastTokStartLoc;\n }\n\n this.scope.enter(SCOPE_OTHER);\n this.expect(10);\n\n if (this.match(13)) {\n if (awaitAt !== null) {\n this.unexpected(awaitAt);\n }\n\n return this.parseFor(node, null);\n }\n\n const startsWithLet = this.isContextual(95);\n const isLet = startsWithLet && this.isLetKeyword();\n\n if (this.match(70) || this.match(71) || isLet) {\n const init = this.startNode();\n const kind = isLet ? \"let\" : this.state.value;\n this.next();\n this.parseVar(init, true, kind);\n this.finishNode(init, \"VariableDeclaration\");\n\n if ((this.match(54) || this.isContextual(97)) && init.declarations.length === 1) {\n return this.parseForIn(node, init, awaitAt);\n }\n\n if (awaitAt !== null) {\n this.unexpected(awaitAt);\n }\n\n return this.parseFor(node, init);\n }\n\n const startsWithAsync = this.isContextual(91);\n const refExpressionErrors = new ExpressionErrors();\n const init = this.parseExpression(true, refExpressionErrors);\n const isForOf = this.isContextual(97);\n\n if (isForOf) {\n if (startsWithLet) {\n this.raise(ErrorMessages.ForOfLet, {\n node: init\n });\n }\n\n if (awaitAt === null && startsWithAsync && init.type === \"Identifier\") {\n this.raise(ErrorMessages.ForOfAsync, {\n node: init\n });\n }\n }\n\n if (isForOf || this.match(54)) {\n this.toAssignable(init, true);\n const description = isForOf ? \"for-of statement\" : \"for-in statement\";\n this.checkLVal(init, description);\n return this.parseForIn(node, init, awaitAt);\n } else {\n this.checkExpressionErrors(refExpressionErrors, true);\n }\n\n if (awaitAt !== null) {\n this.unexpected(awaitAt);\n }\n\n return this.parseFor(node, init);\n }\n\n parseFunctionStatement(node, isAsync, declarationPosition) {\n this.next();\n return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), isAsync);\n }\n\n parseIfStatement(node) {\n this.next();\n node.test = this.parseHeaderExpression();\n node.consequent = this.parseStatement(\"if\");\n node.alternate = this.eat(62) ? this.parseStatement(\"if\") : null;\n return this.finishNode(node, \"IfStatement\");\n }\n\n parseReturnStatement(node) {\n if (!this.prodParam.hasReturn && !this.options.allowReturnOutsideFunction) {\n this.raise(ErrorMessages.IllegalReturn, {\n at: this.state.startLoc\n });\n }\n\n this.next();\n\n if (this.isLineTerminator()) {\n node.argument = null;\n } else {\n node.argument = this.parseExpression();\n this.semicolon();\n }\n\n return this.finishNode(node, \"ReturnStatement\");\n }\n\n parseSwitchStatement(node) {\n this.next();\n node.discriminant = this.parseHeaderExpression();\n const cases = node.cases = [];\n this.expect(5);\n this.state.labels.push(switchLabel);\n this.scope.enter(SCOPE_OTHER);\n let cur;\n\n for (let sawDefault; !this.match(8);) {\n if (this.match(57) || this.match(61)) {\n const isCase = this.match(57);\n if (cur) this.finishNode(cur, \"SwitchCase\");\n cases.push(cur = this.startNode());\n cur.consequent = [];\n this.next();\n\n if (isCase) {\n cur.test = this.parseExpression();\n } else {\n if (sawDefault) {\n this.raise(ErrorMessages.MultipleDefaultsInSwitch, {\n at: this.state.lastTokStartLoc\n });\n }\n\n sawDefault = true;\n cur.test = null;\n }\n\n this.expect(14);\n } else {\n if (cur) {\n cur.consequent.push(this.parseStatement(null));\n } else {\n this.unexpected();\n }\n }\n }\n\n this.scope.exit();\n if (cur) this.finishNode(cur, \"SwitchCase\");\n this.next();\n this.state.labels.pop();\n return this.finishNode(node, \"SwitchStatement\");\n }\n\n parseThrowStatement(node) {\n this.next();\n\n if (this.hasPrecedingLineBreak()) {\n this.raise(ErrorMessages.NewlineAfterThrow, {\n at: this.state.lastTokEndLoc\n });\n }\n\n node.argument = this.parseExpression();\n this.semicolon();\n return this.finishNode(node, \"ThrowStatement\");\n }\n\n parseCatchClauseParam() {\n const param = this.parseBindingAtom();\n const simple = param.type === \"Identifier\";\n this.scope.enter(simple ? SCOPE_SIMPLE_CATCH : 0);\n this.checkLVal(param, \"catch clause\", BIND_LEXICAL);\n return param;\n }\n\n parseTryStatement(node) {\n this.next();\n node.block = this.parseBlock();\n node.handler = null;\n\n if (this.match(58)) {\n const clause = this.startNode();\n this.next();\n\n if (this.match(10)) {\n this.expect(10);\n clause.param = this.parseCatchClauseParam();\n this.expect(11);\n } else {\n clause.param = null;\n this.scope.enter(SCOPE_OTHER);\n }\n\n clause.body = this.withSmartMixTopicForbiddingContext(() => this.parseBlock(false, false));\n this.scope.exit();\n node.handler = this.finishNode(clause, \"CatchClause\");\n }\n\n node.finalizer = this.eat(63) ? this.parseBlock() : null;\n\n if (!node.handler && !node.finalizer) {\n this.raise(ErrorMessages.NoCatchOrFinally, {\n node\n });\n }\n\n return this.finishNode(node, \"TryStatement\");\n }\n\n parseVarStatement(node, kind) {\n this.next();\n this.parseVar(node, false, kind);\n this.semicolon();\n return this.finishNode(node, \"VariableDeclaration\");\n }\n\n parseWhileStatement(node) {\n this.next();\n node.test = this.parseHeaderExpression();\n this.state.labels.push(loopLabel);\n node.body = this.withSmartMixTopicForbiddingContext(() => this.parseStatement(\"while\"));\n this.state.labels.pop();\n return this.finishNode(node, \"WhileStatement\");\n }\n\n parseWithStatement(node) {\n if (this.state.strict) {\n this.raise(ErrorMessages.StrictWith, {\n at: this.state.startLoc\n });\n }\n\n this.next();\n node.object = this.parseHeaderExpression();\n node.body = this.withSmartMixTopicForbiddingContext(() => this.parseStatement(\"with\"));\n return this.finishNode(node, \"WithStatement\");\n }\n\n parseEmptyStatement(node) {\n this.next();\n return this.finishNode(node, \"EmptyStatement\");\n }\n\n parseLabeledStatement(node, maybeName, expr, context) {\n for (const label of this.state.labels) {\n if (label.name === maybeName) {\n this.raise(ErrorMessages.LabelRedeclaration, {\n node: expr\n }, maybeName);\n }\n }\n\n const kind = tokenIsLoop(this.state.type) ? \"loop\" : this.match(67) ? \"switch\" : null;\n\n for (let i = this.state.labels.length - 1; i >= 0; i--) {\n const label = this.state.labels[i];\n\n if (label.statementStart === node.start) {\n label.statementStart = this.state.start;\n label.kind = kind;\n } else {\n break;\n }\n }\n\n this.state.labels.push({\n name: maybeName,\n kind: kind,\n statementStart: this.state.start\n });\n node.body = this.parseStatement(context ? context.indexOf(\"label\") === -1 ? context + \"label\" : context : \"label\");\n this.state.labels.pop();\n node.label = expr;\n return this.finishNode(node, \"LabeledStatement\");\n }\n\n parseExpressionStatement(node, expr) {\n node.expression = expr;\n this.semicolon();\n return this.finishNode(node, \"ExpressionStatement\");\n }\n\n parseBlock(allowDirectives = false, createNewLexicalScope = true, afterBlockParse) {\n const node = this.startNode();\n\n if (allowDirectives) {\n this.state.strictErrors.clear();\n }\n\n this.expect(5);\n\n if (createNewLexicalScope) {\n this.scope.enter(SCOPE_OTHER);\n }\n\n this.parseBlockBody(node, allowDirectives, false, 8, afterBlockParse);\n\n if (createNewLexicalScope) {\n this.scope.exit();\n }\n\n return this.finishNode(node, \"BlockStatement\");\n }\n\n isValidDirective(stmt) {\n return stmt.type === \"ExpressionStatement\" && stmt.expression.type === \"StringLiteral\" && !stmt.expression.extra.parenthesized;\n }\n\n parseBlockBody(node, allowDirectives, topLevel, end, afterBlockParse) {\n const body = node.body = [];\n const directives = node.directives = [];\n this.parseBlockOrModuleBlockBody(body, allowDirectives ? directives : undefined, topLevel, end, afterBlockParse);\n }\n\n parseBlockOrModuleBlockBody(body, directives, topLevel, end, afterBlockParse) {\n const oldStrict = this.state.strict;\n let hasStrictModeDirective = false;\n let parsedNonDirective = false;\n\n while (!this.match(end)) {\n const stmt = this.parseStatement(null, topLevel);\n\n if (directives && !parsedNonDirective) {\n if (this.isValidDirective(stmt)) {\n const directive = this.stmtToDirective(stmt);\n directives.push(directive);\n\n if (!hasStrictModeDirective && directive.value.value === \"use strict\") {\n hasStrictModeDirective = true;\n this.setStrict(true);\n }\n\n continue;\n }\n\n parsedNonDirective = true;\n this.state.strictErrors.clear();\n }\n\n body.push(stmt);\n }\n\n if (afterBlockParse) {\n afterBlockParse.call(this, hasStrictModeDirective);\n }\n\n if (!oldStrict) {\n this.setStrict(false);\n }\n\n this.next();\n }\n\n parseFor(node, init) {\n node.init = init;\n this.semicolon(false);\n node.test = this.match(13) ? null : this.parseExpression();\n this.semicolon(false);\n node.update = this.match(11) ? null : this.parseExpression();\n this.expect(11);\n node.body = this.withSmartMixTopicForbiddingContext(() => this.parseStatement(\"for\"));\n this.scope.exit();\n this.state.labels.pop();\n return this.finishNode(node, \"ForStatement\");\n }\n\n parseForIn(node, init, awaitAt) {\n const isForIn = this.match(54);\n this.next();\n\n if (isForIn) {\n if (awaitAt !== null) this.unexpected(awaitAt);\n } else {\n node.await = awaitAt !== null;\n }\n\n if (init.type === \"VariableDeclaration\" && init.declarations[0].init != null && (!isForIn || this.state.strict || init.kind !== \"var\" || init.declarations[0].id.type !== \"Identifier\")) {\n this.raise(ErrorMessages.ForInOfLoopInitializer, {\n node: init\n }, isForIn ? \"for-in\" : \"for-of\");\n }\n\n if (init.type === \"AssignmentPattern\") {\n this.raise(ErrorMessages.InvalidLhs, {\n node: init\n }, \"for-loop\");\n }\n\n node.left = init;\n node.right = isForIn ? this.parseExpression() : this.parseMaybeAssignAllowIn();\n this.expect(11);\n node.body = this.withSmartMixTopicForbiddingContext(() => this.parseStatement(\"for\"));\n this.scope.exit();\n this.state.labels.pop();\n return this.finishNode(node, isForIn ? \"ForInStatement\" : \"ForOfStatement\");\n }\n\n parseVar(node, isFor, kind) {\n const declarations = node.declarations = [];\n const isTypescript = this.hasPlugin(\"typescript\");\n node.kind = kind;\n\n for (;;) {\n const decl = this.startNode();\n this.parseVarId(decl, kind);\n\n if (this.eat(29)) {\n decl.init = isFor ? this.parseMaybeAssignDisallowIn() : this.parseMaybeAssignAllowIn();\n } else {\n if (kind === \"const\" && !(this.match(54) || this.isContextual(97))) {\n if (!isTypescript) {\n this.raise(ErrorMessages.DeclarationMissingInitializer, {\n at: this.state.lastTokEndLoc\n }, \"Const declarations\");\n }\n } else if (decl.id.type !== \"Identifier\" && !(isFor && (this.match(54) || this.isContextual(97)))) {\n this.raise(ErrorMessages.DeclarationMissingInitializer, {\n at: this.state.lastTokEndLoc\n }, \"Complex binding patterns\");\n }\n\n decl.init = null;\n }\n\n declarations.push(this.finishNode(decl, \"VariableDeclarator\"));\n if (!this.eat(12)) break;\n }\n\n return node;\n }\n\n parseVarId(decl, kind) {\n decl.id = this.parseBindingAtom();\n this.checkLVal(decl.id, \"variable declaration\", kind === \"var\" ? BIND_VAR : BIND_LEXICAL, undefined, kind !== \"var\");\n }\n\n parseFunction(node, statement = FUNC_NO_FLAGS, isAsync = false) {\n const isStatement = statement & FUNC_STATEMENT;\n const isHangingStatement = statement & FUNC_HANGING_STATEMENT;\n const requireId = !!isStatement && !(statement & FUNC_NULLABLE_ID);\n this.initFunction(node, isAsync);\n\n if (this.match(51) && isHangingStatement) {\n this.raise(ErrorMessages.GeneratorInSingleStatementContext, {\n at: this.state.startLoc\n });\n }\n\n node.generator = this.eat(51);\n\n if (isStatement) {\n node.id = this.parseFunctionId(requireId);\n }\n\n const oldMaybeInArrowParameters = this.state.maybeInArrowParameters;\n this.state.maybeInArrowParameters = false;\n this.scope.enter(SCOPE_FUNCTION);\n this.prodParam.enter(functionFlags(isAsync, node.generator));\n\n if (!isStatement) {\n node.id = this.parseFunctionId();\n }\n\n this.parseFunctionParams(node, false);\n this.withSmartMixTopicForbiddingContext(() => {\n this.parseFunctionBodyAndFinish(node, isStatement ? \"FunctionDeclaration\" : \"FunctionExpression\");\n });\n this.prodParam.exit();\n this.scope.exit();\n\n if (isStatement && !isHangingStatement) {\n this.registerFunctionStatementId(node);\n }\n\n this.state.maybeInArrowParameters = oldMaybeInArrowParameters;\n return node;\n }\n\n parseFunctionId(requireId) {\n return requireId || tokenIsIdentifier(this.state.type) ? this.parseIdentifier() : null;\n }\n\n parseFunctionParams(node, allowModifiers) {\n this.expect(10);\n this.expressionScope.enter(newParameterDeclarationScope());\n node.params = this.parseBindingList(11, 41, false, allowModifiers);\n this.expressionScope.exit();\n }\n\n registerFunctionStatementId(node) {\n if (!node.id) return;\n this.scope.declareName(node.id.name, this.state.strict || node.generator || node.async ? this.scope.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION, node.id.loc.start);\n }\n\n parseClass(node, isStatement, optionalId) {\n this.next();\n this.takeDecorators(node);\n const oldStrict = this.state.strict;\n this.state.strict = true;\n this.parseClassId(node, isStatement, optionalId);\n this.parseClassSuper(node);\n node.body = this.parseClassBody(!!node.superClass, oldStrict);\n return this.finishNode(node, isStatement ? \"ClassDeclaration\" : \"ClassExpression\");\n }\n\n isClassProperty() {\n return this.match(29) || this.match(13) || this.match(8);\n }\n\n isClassMethod() {\n return this.match(10);\n }\n\n isNonstaticConstructor(method) {\n return !method.computed && !method.static && (method.key.name === \"constructor\" || method.key.value === \"constructor\");\n }\n\n parseClassBody(hadSuperClass, oldStrict) {\n this.classScope.enter();\n const state = {\n hadConstructor: false,\n hadSuperClass\n };\n let decorators = [];\n const classBody = this.startNode();\n classBody.body = [];\n this.expect(5);\n this.withSmartMixTopicForbiddingContext(() => {\n while (!this.match(8)) {\n if (this.eat(13)) {\n if (decorators.length > 0) {\n throw this.raise(ErrorMessages.DecoratorSemicolon, {\n at: this.state.lastTokEndLoc\n });\n }\n\n continue;\n }\n\n if (this.match(26)) {\n decorators.push(this.parseDecorator());\n continue;\n }\n\n const member = this.startNode();\n\n if (decorators.length) {\n member.decorators = decorators;\n this.resetStartLocationFromNode(member, decorators[0]);\n decorators = [];\n }\n\n this.parseClassMember(classBody, member, state);\n\n if (member.kind === \"constructor\" && member.decorators && member.decorators.length > 0) {\n this.raise(ErrorMessages.DecoratorConstructor, {\n node: member\n });\n }\n }\n });\n this.state.strict = oldStrict;\n this.next();\n\n if (decorators.length) {\n throw this.raise(ErrorMessages.TrailingDecorator, {\n at: this.state.startLoc\n });\n }\n\n this.classScope.exit();\n return this.finishNode(classBody, \"ClassBody\");\n }\n\n parseClassMemberFromModifier(classBody, member) {\n const key = this.parseIdentifier(true);\n\n if (this.isClassMethod()) {\n const method = member;\n method.kind = \"method\";\n method.computed = false;\n method.key = key;\n method.static = false;\n this.pushClassMethod(classBody, method, false, false, false, false);\n return true;\n } else if (this.isClassProperty()) {\n const prop = member;\n prop.computed = false;\n prop.key = key;\n prop.static = false;\n classBody.body.push(this.parseClassProperty(prop));\n return true;\n }\n\n this.resetPreviousNodeTrailingComments(key);\n return false;\n }\n\n parseClassMember(classBody, member, state) {\n const isStatic = this.isContextual(100);\n\n if (isStatic) {\n if (this.parseClassMemberFromModifier(classBody, member)) {\n return;\n }\n\n if (this.eat(5)) {\n this.parseClassStaticBlock(classBody, member);\n return;\n }\n }\n\n this.parseClassMemberWithIsStatic(classBody, member, state, isStatic);\n }\n\n parseClassMemberWithIsStatic(classBody, member, state, isStatic) {\n const publicMethod = member;\n const privateMethod = member;\n const publicProp = member;\n const privateProp = member;\n const method = publicMethod;\n const publicMember = publicMethod;\n member.static = isStatic;\n this.parsePropertyNamePrefixOperator(member);\n\n if (this.eat(51)) {\n method.kind = \"method\";\n const isPrivateName = this.match(130);\n this.parseClassElementName(method);\n\n if (isPrivateName) {\n this.pushClassPrivateMethod(classBody, privateMethod, true, false);\n return;\n }\n\n if (this.isNonstaticConstructor(publicMethod)) {\n this.raise(ErrorMessages.ConstructorIsGenerator, {\n node: publicMethod.key\n });\n }\n\n this.pushClassMethod(classBody, publicMethod, true, false, false, false);\n return;\n }\n\n const isContextual = tokenIsIdentifier(this.state.type) && !this.state.containsEsc;\n const isPrivate = this.match(130);\n const key = this.parseClassElementName(member);\n const maybeQuestionTokenStartLoc = this.state.startLoc;\n this.parsePostMemberNameModifiers(publicMember);\n\n if (this.isClassMethod()) {\n method.kind = \"method\";\n\n if (isPrivate) {\n this.pushClassPrivateMethod(classBody, privateMethod, false, false);\n return;\n }\n\n const isConstructor = this.isNonstaticConstructor(publicMethod);\n let allowsDirectSuper = false;\n\n if (isConstructor) {\n publicMethod.kind = \"constructor\";\n\n if (state.hadConstructor && !this.hasPlugin(\"typescript\")) {\n this.raise(ErrorMessages.DuplicateConstructor, {\n node: key\n });\n }\n\n if (isConstructor && this.hasPlugin(\"typescript\") && member.override) {\n this.raise(ErrorMessages.OverrideOnConstructor, {\n node: key\n });\n }\n\n state.hadConstructor = true;\n allowsDirectSuper = state.hadSuperClass;\n }\n\n this.pushClassMethod(classBody, publicMethod, false, false, isConstructor, allowsDirectSuper);\n } else if (this.isClassProperty()) {\n if (isPrivate) {\n this.pushClassPrivateProperty(classBody, privateProp);\n } else {\n this.pushClassProperty(classBody, publicProp);\n }\n } else if (isContextual && key.name === \"async\" && !this.isLineTerminator()) {\n this.resetPreviousNodeTrailingComments(key);\n const isGenerator = this.eat(51);\n\n if (publicMember.optional) {\n this.unexpected(maybeQuestionTokenStartLoc);\n }\n\n method.kind = \"method\";\n const isPrivate = this.match(130);\n this.parseClassElementName(method);\n this.parsePostMemberNameModifiers(publicMember);\n\n if (isPrivate) {\n this.pushClassPrivateMethod(classBody, privateMethod, isGenerator, true);\n } else {\n if (this.isNonstaticConstructor(publicMethod)) {\n this.raise(ErrorMessages.ConstructorIsAsync, {\n node: publicMethod.key\n });\n }\n\n this.pushClassMethod(classBody, publicMethod, isGenerator, true, false, false);\n }\n } else if (isContextual && (key.name === \"get\" || key.name === \"set\") && !(this.match(51) && this.isLineTerminator())) {\n this.resetPreviousNodeTrailingComments(key);\n method.kind = key.name;\n const isPrivate = this.match(130);\n this.parseClassElementName(publicMethod);\n\n if (isPrivate) {\n this.pushClassPrivateMethod(classBody, privateMethod, false, false);\n } else {\n if (this.isNonstaticConstructor(publicMethod)) {\n this.raise(ErrorMessages.ConstructorIsAccessor, {\n node: publicMethod.key\n });\n }\n\n this.pushClassMethod(classBody, publicMethod, false, false, false, false);\n }\n\n this.checkGetterSetterParams(publicMethod);\n } else if (this.isLineTerminator()) {\n if (isPrivate) {\n this.pushClassPrivateProperty(classBody, privateProp);\n } else {\n this.pushClassProperty(classBody, publicProp);\n }\n } else {\n this.unexpected();\n }\n }\n\n parseClassElementName(member) {\n const {\n type,\n value\n } = this.state;\n\n if ((type === 124 || type === 125) && member.static && value === \"prototype\") {\n this.raise(ErrorMessages.StaticPrototype, {\n at: this.state.startLoc\n });\n }\n\n if (type === 130) {\n if (value === \"constructor\") {\n this.raise(ErrorMessages.ConstructorClassPrivateField, {\n at: this.state.startLoc\n });\n }\n\n const key = this.parsePrivateName();\n member.key = key;\n return key;\n }\n\n return this.parsePropertyName(member);\n }\n\n parseClassStaticBlock(classBody, member) {\n var _member$decorators;\n\n this.scope.enter(SCOPE_CLASS | SCOPE_STATIC_BLOCK | SCOPE_SUPER);\n const oldLabels = this.state.labels;\n this.state.labels = [];\n this.prodParam.enter(PARAM);\n const body = member.body = [];\n this.parseBlockOrModuleBlockBody(body, undefined, false, 8);\n this.prodParam.exit();\n this.scope.exit();\n this.state.labels = oldLabels;\n classBody.body.push(this.finishNode(member, \"StaticBlock\"));\n\n if ((_member$decorators = member.decorators) != null && _member$decorators.length) {\n this.raise(ErrorMessages.DecoratorStaticBlock, {\n node: member\n });\n }\n }\n\n pushClassProperty(classBody, prop) {\n if (!prop.computed && (prop.key.name === \"constructor\" || prop.key.value === \"constructor\")) {\n this.raise(ErrorMessages.ConstructorClassField, {\n node: prop.key\n });\n }\n\n classBody.body.push(this.parseClassProperty(prop));\n }\n\n pushClassPrivateProperty(classBody, prop) {\n const node = this.parseClassPrivateProperty(prop);\n classBody.body.push(node);\n this.classScope.declarePrivateName(this.getPrivateNameSV(node.key), CLASS_ELEMENT_OTHER, node.key.loc.start);\n }\n\n pushClassMethod(classBody, method, isGenerator, isAsync, isConstructor, allowsDirectSuper) {\n classBody.body.push(this.parseMethod(method, isGenerator, isAsync, isConstructor, allowsDirectSuper, \"ClassMethod\", true));\n }\n\n pushClassPrivateMethod(classBody, method, isGenerator, isAsync) {\n const node = this.parseMethod(method, isGenerator, isAsync, false, false, \"ClassPrivateMethod\", true);\n classBody.body.push(node);\n const kind = node.kind === \"get\" ? node.static ? CLASS_ELEMENT_STATIC_GETTER : CLASS_ELEMENT_INSTANCE_GETTER : node.kind === \"set\" ? node.static ? CLASS_ELEMENT_STATIC_SETTER : CLASS_ELEMENT_INSTANCE_SETTER : CLASS_ELEMENT_OTHER;\n this.declareClassPrivateMethodInScope(node, kind);\n }\n\n declareClassPrivateMethodInScope(node, kind) {\n this.classScope.declarePrivateName(this.getPrivateNameSV(node.key), kind, node.key.loc.start);\n }\n\n parsePostMemberNameModifiers(methodOrProp) {}\n\n parseClassPrivateProperty(node) {\n this.parseInitializer(node);\n this.semicolon();\n return this.finishNode(node, \"ClassPrivateProperty\");\n }\n\n parseClassProperty(node) {\n this.parseInitializer(node);\n this.semicolon();\n return this.finishNode(node, \"ClassProperty\");\n }\n\n parseInitializer(node) {\n this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);\n this.expressionScope.enter(newExpressionScope());\n this.prodParam.enter(PARAM);\n node.value = this.eat(29) ? this.parseMaybeAssignAllowIn() : null;\n this.expressionScope.exit();\n this.prodParam.exit();\n this.scope.exit();\n }\n\n parseClassId(node, isStatement, optionalId, bindingType = BIND_CLASS) {\n if (tokenIsIdentifier(this.state.type)) {\n node.id = this.parseIdentifier();\n\n if (isStatement) {\n this.checkLVal(node.id, \"class name\", bindingType);\n }\n } else {\n if (optionalId || !isStatement) {\n node.id = null;\n } else {\n throw this.raise(ErrorMessages.MissingClassName, {\n at: this.state.startLoc\n });\n }\n }\n }\n\n parseClassSuper(node) {\n node.superClass = this.eat(77) ? this.parseExprSubscripts() : null;\n }\n\n parseExport(node) {\n const hasDefault = this.maybeParseExportDefaultSpecifier(node);\n const parseAfterDefault = !hasDefault || this.eat(12);\n const hasStar = parseAfterDefault && this.eatExportStar(node);\n const hasNamespace = hasStar && this.maybeParseExportNamespaceSpecifier(node);\n const parseAfterNamespace = parseAfterDefault && (!hasNamespace || this.eat(12));\n const isFromRequired = hasDefault || hasStar;\n\n if (hasStar && !hasNamespace) {\n if (hasDefault) this.unexpected();\n this.parseExportFrom(node, true);\n return this.finishNode(node, \"ExportAllDeclaration\");\n }\n\n const hasSpecifiers = this.maybeParseExportNamedSpecifiers(node);\n\n if (hasDefault && parseAfterDefault && !hasStar && !hasSpecifiers || hasNamespace && parseAfterNamespace && !hasSpecifiers) {\n throw this.unexpected(null, 5);\n }\n\n let hasDeclaration;\n\n if (isFromRequired || hasSpecifiers) {\n hasDeclaration = false;\n this.parseExportFrom(node, isFromRequired);\n } else {\n hasDeclaration = this.maybeParseExportDeclaration(node);\n }\n\n if (isFromRequired || hasSpecifiers || hasDeclaration) {\n this.checkExport(node, true, false, !!node.source);\n return this.finishNode(node, \"ExportNamedDeclaration\");\n }\n\n if (this.eat(61)) {\n node.declaration = this.parseExportDefaultExpression();\n this.checkExport(node, true, true);\n return this.finishNode(node, \"ExportDefaultDeclaration\");\n }\n\n throw this.unexpected(null, 5);\n }\n\n eatExportStar(node) {\n return this.eat(51);\n }\n\n maybeParseExportDefaultSpecifier(node) {\n if (this.isExportDefaultSpecifier()) {\n this.expectPlugin(\"exportDefaultFrom\");\n const specifier = this.startNode();\n specifier.exported = this.parseIdentifier(true);\n node.specifiers = [this.finishNode(specifier, \"ExportDefaultSpecifier\")];\n return true;\n }\n\n return false;\n }\n\n maybeParseExportNamespaceSpecifier(node) {\n if (this.isContextual(89)) {\n if (!node.specifiers) node.specifiers = [];\n const specifier = this.startNodeAt(this.state.lastTokStart, this.state.lastTokStartLoc);\n this.next();\n specifier.exported = this.parseModuleExportName();\n node.specifiers.push(this.finishNode(specifier, \"ExportNamespaceSpecifier\"));\n return true;\n }\n\n return false;\n }\n\n maybeParseExportNamedSpecifiers(node) {\n if (this.match(5)) {\n if (!node.specifiers) node.specifiers = [];\n const isTypeExport = node.exportKind === \"type\";\n node.specifiers.push(...this.parseExportSpecifiers(isTypeExport));\n node.source = null;\n node.declaration = null;\n\n if (this.hasPlugin(\"importAssertions\")) {\n node.assertions = [];\n }\n\n return true;\n }\n\n return false;\n }\n\n maybeParseExportDeclaration(node) {\n if (this.shouldParseExportDeclaration()) {\n node.specifiers = [];\n node.source = null;\n\n if (this.hasPlugin(\"importAssertions\")) {\n node.assertions = [];\n }\n\n node.declaration = this.parseExportDeclaration(node);\n return true;\n }\n\n return false;\n }\n\n isAsyncFunction() {\n if (!this.isContextual(91)) return false;\n const next = this.nextTokenStart();\n return !lineBreak.test(this.input.slice(this.state.pos, next)) && this.isUnparsedContextual(next, \"function\");\n }\n\n parseExportDefaultExpression() {\n const expr = this.startNode();\n const isAsync = this.isAsyncFunction();\n\n if (this.match(64) || isAsync) {\n this.next();\n\n if (isAsync) {\n this.next();\n }\n\n return this.parseFunction(expr, FUNC_STATEMENT | FUNC_NULLABLE_ID, isAsync);\n }\n\n if (this.match(76)) {\n return this.parseClass(expr, true, true);\n }\n\n if (this.match(26)) {\n if (this.hasPlugin(\"decorators\") && this.getPluginOption(\"decorators\", \"decoratorsBeforeExport\")) {\n this.raise(ErrorMessages.DecoratorBeforeExport, {\n at: this.state.startLoc\n });\n }\n\n this.parseDecorators(false);\n return this.parseClass(expr, true, true);\n }\n\n if (this.match(71) || this.match(70) || this.isLet()) {\n throw this.raise(ErrorMessages.UnsupportedDefaultExport, {\n at: this.state.startLoc\n });\n }\n\n const res = this.parseMaybeAssignAllowIn();\n this.semicolon();\n return res;\n }\n\n parseExportDeclaration(node) {\n return this.parseStatement(null);\n }\n\n isExportDefaultSpecifier() {\n const {\n type\n } = this.state;\n\n if (tokenIsIdentifier(type)) {\n if (type === 91 && !this.state.containsEsc || type === 95) {\n return false;\n }\n\n if ((type === 122 || type === 121) && !this.state.containsEsc) {\n const {\n type: nextType\n } = this.lookahead();\n\n if (tokenIsIdentifier(nextType) && nextType !== 93 || nextType === 5) {\n this.expectOnePlugin([\"flow\", \"typescript\"]);\n return false;\n }\n }\n } else if (!this.match(61)) {\n return false;\n }\n\n const next = this.nextTokenStart();\n const hasFrom = this.isUnparsedContextual(next, \"from\");\n\n if (this.input.charCodeAt(next) === 44 || tokenIsIdentifier(this.state.type) && hasFrom) {\n return true;\n }\n\n if (this.match(61) && hasFrom) {\n const nextAfterFrom = this.input.charCodeAt(this.nextTokenStartSince(next + 4));\n return nextAfterFrom === 34 || nextAfterFrom === 39;\n }\n\n return false;\n }\n\n parseExportFrom(node, expect) {\n if (this.eatContextual(93)) {\n node.source = this.parseImportSource();\n this.checkExport(node);\n const assertions = this.maybeParseImportAssertions();\n\n if (assertions) {\n node.assertions = assertions;\n }\n } else if (expect) {\n this.unexpected();\n }\n\n this.semicolon();\n }\n\n shouldParseExportDeclaration() {\n const {\n type\n } = this.state;\n\n if (type === 26) {\n this.expectOnePlugin([\"decorators\", \"decorators-legacy\"]);\n\n if (this.hasPlugin(\"decorators\")) {\n if (this.getPluginOption(\"decorators\", \"decoratorsBeforeExport\")) {\n throw this.raise(ErrorMessages.DecoratorBeforeExport, {\n at: this.state.startLoc\n });\n }\n\n return true;\n }\n }\n\n return type === 70 || type === 71 || type === 64 || type === 76 || this.isLet() || this.isAsyncFunction();\n }\n\n checkExport(node, checkNames, isDefault, isFrom) {\n if (checkNames) {\n if (isDefault) {\n this.checkDuplicateExports(node, \"default\");\n\n if (this.hasPlugin(\"exportDefaultFrom\")) {\n var _declaration$extra;\n\n const declaration = node.declaration;\n\n if (declaration.type === \"Identifier\" && declaration.name === \"from\" && declaration.end - declaration.start === 4 && !((_declaration$extra = declaration.extra) != null && _declaration$extra.parenthesized)) {\n this.raise(ErrorMessages.ExportDefaultFromAsIdentifier, {\n node: declaration\n });\n }\n }\n } else if (node.specifiers && node.specifiers.length) {\n for (const specifier of node.specifiers) {\n const {\n exported\n } = specifier;\n const exportedName = exported.type === \"Identifier\" ? exported.name : exported.value;\n this.checkDuplicateExports(specifier, exportedName);\n\n if (!isFrom && specifier.local) {\n const {\n local\n } = specifier;\n\n if (local.type !== \"Identifier\") {\n this.raise(ErrorMessages.ExportBindingIsString, {\n node: specifier\n }, local.value, exportedName);\n } else {\n this.checkReservedWord(local.name, local.loc.start, true, false);\n this.scope.checkLocalExport(local);\n }\n }\n }\n } else if (node.declaration) {\n if (node.declaration.type === \"FunctionDeclaration\" || node.declaration.type === \"ClassDeclaration\") {\n const id = node.declaration.id;\n if (!id) throw new Error(\"Assertion failure\");\n this.checkDuplicateExports(node, id.name);\n } else if (node.declaration.type === \"VariableDeclaration\") {\n for (const declaration of node.declaration.declarations) {\n this.checkDeclaration(declaration.id);\n }\n }\n }\n }\n\n const currentContextDecorators = this.state.decoratorStack[this.state.decoratorStack.length - 1];\n\n if (currentContextDecorators.length) {\n throw this.raise(ErrorMessages.UnsupportedDecoratorExport, {\n node\n });\n }\n }\n\n checkDeclaration(node) {\n if (node.type === \"Identifier\") {\n this.checkDuplicateExports(node, node.name);\n } else if (node.type === \"ObjectPattern\") {\n for (const prop of node.properties) {\n this.checkDeclaration(prop);\n }\n } else if (node.type === \"ArrayPattern\") {\n for (const elem of node.elements) {\n if (elem) {\n this.checkDeclaration(elem);\n }\n }\n } else if (node.type === \"ObjectProperty\") {\n this.checkDeclaration(node.value);\n } else if (node.type === \"RestElement\") {\n this.checkDeclaration(node.argument);\n } else if (node.type === \"AssignmentPattern\") {\n this.checkDeclaration(node.left);\n }\n }\n\n checkDuplicateExports(node, name) {\n if (this.exportedIdentifiers.has(name)) {\n this.raise(name === \"default\" ? ErrorMessages.DuplicateDefaultExport : ErrorMessages.DuplicateExport, {\n node\n }, name);\n }\n\n this.exportedIdentifiers.add(name);\n }\n\n parseExportSpecifiers(isInTypeExport) {\n const nodes = [];\n let first = true;\n this.expect(5);\n\n while (!this.eat(8)) {\n if (first) {\n first = false;\n } else {\n this.expect(12);\n if (this.eat(8)) break;\n }\n\n const isMaybeTypeOnly = this.isContextual(122);\n const isString = this.match(125);\n const node = this.startNode();\n node.local = this.parseModuleExportName();\n nodes.push(this.parseExportSpecifier(node, isString, isInTypeExport, isMaybeTypeOnly));\n }\n\n return nodes;\n }\n\n parseExportSpecifier(node, isString, isInTypeExport, isMaybeTypeOnly) {\n if (this.eatContextual(89)) {\n node.exported = this.parseModuleExportName();\n } else if (isString) {\n node.exported = cloneStringLiteral(node.local);\n } else if (!node.exported) {\n node.exported = cloneIdentifier(node.local);\n }\n\n return this.finishNode(node, \"ExportSpecifier\");\n }\n\n parseModuleExportName() {\n if (this.match(125)) {\n const result = this.parseStringLiteral(this.state.value);\n const surrogate = result.value.match(loneSurrogate);\n\n if (surrogate) {\n this.raise(ErrorMessages.ModuleExportNameHasLoneSurrogate, {\n node: result\n }, surrogate[0].charCodeAt(0).toString(16));\n }\n\n return result;\n }\n\n return this.parseIdentifier(true);\n }\n\n parseImport(node) {\n node.specifiers = [];\n\n if (!this.match(125)) {\n const hasDefault = this.maybeParseDefaultImportSpecifier(node);\n const parseNext = !hasDefault || this.eat(12);\n const hasStar = parseNext && this.maybeParseStarImportSpecifier(node);\n if (parseNext && !hasStar) this.parseNamedImportSpecifiers(node);\n this.expectContextual(93);\n }\n\n node.source = this.parseImportSource();\n const assertions = this.maybeParseImportAssertions();\n\n if (assertions) {\n node.assertions = assertions;\n } else {\n const attributes = this.maybeParseModuleAttributes();\n\n if (attributes) {\n node.attributes = attributes;\n }\n }\n\n this.semicolon();\n return this.finishNode(node, \"ImportDeclaration\");\n }\n\n parseImportSource() {\n if (!this.match(125)) this.unexpected();\n return this.parseExprAtom();\n }\n\n shouldParseDefaultImport(node) {\n return tokenIsIdentifier(this.state.type);\n }\n\n parseImportSpecifierLocal(node, specifier, type, contextDescription) {\n specifier.local = this.parseIdentifier();\n this.checkLVal(specifier.local, contextDescription, BIND_LEXICAL);\n node.specifiers.push(this.finishNode(specifier, type));\n }\n\n parseAssertEntries() {\n const attrs = [];\n const attrNames = new Set();\n\n do {\n if (this.match(8)) {\n break;\n }\n\n const node = this.startNode();\n const keyName = this.state.value;\n\n if (attrNames.has(keyName)) {\n this.raise(ErrorMessages.ModuleAttributesWithDuplicateKeys, {\n at: this.state.startLoc\n }, keyName);\n }\n\n attrNames.add(keyName);\n\n if (this.match(125)) {\n node.key = this.parseStringLiteral(keyName);\n } else {\n node.key = this.parseIdentifier(true);\n }\n\n this.expect(14);\n\n if (!this.match(125)) {\n throw this.raise(ErrorMessages.ModuleAttributeInvalidValue, {\n at: this.state.startLoc\n });\n }\n\n node.value = this.parseStringLiteral(this.state.value);\n this.finishNode(node, \"ImportAttribute\");\n attrs.push(node);\n } while (this.eat(12));\n\n return attrs;\n }\n\n maybeParseModuleAttributes() {\n if (this.match(72) && !this.hasPrecedingLineBreak()) {\n this.expectPlugin(\"moduleAttributes\");\n this.next();\n } else {\n if (this.hasPlugin(\"moduleAttributes\")) return [];\n return null;\n }\n\n const attrs = [];\n const attributes = new Set();\n\n do {\n const node = this.startNode();\n node.key = this.parseIdentifier(true);\n\n if (node.key.name !== \"type\") {\n this.raise(ErrorMessages.ModuleAttributeDifferentFromType, {\n node: node.key\n }, node.key.name);\n }\n\n if (attributes.has(node.key.name)) {\n this.raise(ErrorMessages.ModuleAttributesWithDuplicateKeys, {\n node: node.key\n }, node.key.name);\n }\n\n attributes.add(node.key.name);\n this.expect(14);\n\n if (!this.match(125)) {\n throw this.raise(ErrorMessages.ModuleAttributeInvalidValue, {\n at: this.state.startLoc\n });\n }\n\n node.value = this.parseStringLiteral(this.state.value);\n this.finishNode(node, \"ImportAttribute\");\n attrs.push(node);\n } while (this.eat(12));\n\n return attrs;\n }\n\n maybeParseImportAssertions() {\n if (this.isContextual(90) && !this.hasPrecedingLineBreak()) {\n this.expectPlugin(\"importAssertions\");\n this.next();\n } else {\n if (this.hasPlugin(\"importAssertions\")) return [];\n return null;\n }\n\n this.eat(5);\n const attrs = this.parseAssertEntries();\n this.eat(8);\n return attrs;\n }\n\n maybeParseDefaultImportSpecifier(node) {\n if (this.shouldParseDefaultImport(node)) {\n this.parseImportSpecifierLocal(node, this.startNode(), \"ImportDefaultSpecifier\", \"default import specifier\");\n return true;\n }\n\n return false;\n }\n\n maybeParseStarImportSpecifier(node) {\n if (this.match(51)) {\n const specifier = this.startNode();\n this.next();\n this.expectContextual(89);\n this.parseImportSpecifierLocal(node, specifier, \"ImportNamespaceSpecifier\", \"import namespace specifier\");\n return true;\n }\n\n return false;\n }\n\n parseNamedImportSpecifiers(node) {\n let first = true;\n this.expect(5);\n\n while (!this.eat(8)) {\n if (first) {\n first = false;\n } else {\n if (this.eat(14)) {\n throw this.raise(ErrorMessages.DestructureNamedImport, {\n at: this.state.startLoc\n });\n }\n\n this.expect(12);\n if (this.eat(8)) break;\n }\n\n const specifier = this.startNode();\n const importedIsString = this.match(125);\n const isMaybeTypeOnly = this.isContextual(122);\n specifier.imported = this.parseModuleExportName();\n const importSpecifier = this.parseImportSpecifier(specifier, importedIsString, node.importKind === \"type\" || node.importKind === \"typeof\", isMaybeTypeOnly);\n node.specifiers.push(importSpecifier);\n }\n }\n\n parseImportSpecifier(specifier, importedIsString, isInTypeOnlyImport, isMaybeTypeOnly) {\n if (this.eatContextual(89)) {\n specifier.local = this.parseIdentifier();\n } else {\n const {\n imported\n } = specifier;\n\n if (importedIsString) {\n throw this.raise(ErrorMessages.ImportBindingIsString, {\n node: specifier\n }, imported.value);\n }\n\n this.checkReservedWord(imported.name, specifier.loc.start, true, true);\n\n if (!specifier.local) {\n specifier.local = cloneIdentifier(imported);\n }\n }\n\n this.checkLVal(specifier.local, \"import specifier\", BIND_LEXICAL);\n return this.finishNode(specifier, \"ImportSpecifier\");\n }\n\n isThisParam(param) {\n return param.type === \"Identifier\" && param.name === \"this\";\n }\n\n}\n\nclass Parser extends StatementParser {\n constructor(options, input) {\n options = getOptions(options);\n super(options, input);\n this.options = options;\n this.initializeScopes();\n this.plugins = pluginsMap(this.options.plugins);\n this.filename = options.sourceFilename;\n }\n\n getScopeHandler() {\n return ScopeHandler;\n }\n\n parse() {\n this.enterInitialScopes();\n const file = this.startNode();\n const program = this.startNode();\n this.nextToken();\n file.errors = null;\n this.parseTopLevel(file, program);\n file.errors = this.state.errors;\n return file;\n }\n\n}\n\nfunction pluginsMap(plugins) {\n const pluginMap = new Map();\n\n for (const plugin of plugins) {\n const [name, options] = Array.isArray(plugin) ? plugin : [plugin, {}];\n if (!pluginMap.has(name)) pluginMap.set(name, options || {});\n }\n\n return pluginMap;\n}\n\nfunction parse(input, options) {\n var _options;\n\n if (((_options = options) == null ? void 0 : _options.sourceType) === \"unambiguous\") {\n options = Object.assign({}, options);\n\n try {\n options.sourceType = \"module\";\n const parser = getParser(options, input);\n const ast = parser.parse();\n\n if (parser.sawUnambiguousESM) {\n return ast;\n }\n\n if (parser.ambiguousScriptDifferentAst) {\n try {\n options.sourceType = \"script\";\n return getParser(options, input).parse();\n } catch (_unused) {}\n } else {\n ast.program.sourceType = \"script\";\n }\n\n return ast;\n } catch (moduleError) {\n try {\n options.sourceType = \"script\";\n return getParser(options, input).parse();\n } catch (_unused2) {}\n\n throw moduleError;\n }\n } else {\n return getParser(options, input).parse();\n }\n}\nfunction parseExpression(input, options) {\n const parser = getParser(options, input);\n\n if (parser.options.strictMode) {\n parser.state.strict = true;\n }\n\n return parser.getExpression();\n}\n\nfunction generateExportedTokenTypes(internalTokenTypes) {\n const tokenTypes = {};\n\n for (const typeName of Object.keys(internalTokenTypes)) {\n tokenTypes[typeName] = getExportedToken(internalTokenTypes[typeName]);\n }\n\n return tokenTypes;\n}\n\nconst tokTypes = generateExportedTokenTypes(tt);\n\nfunction getParser(options, input) {\n let cls = Parser;\n\n if (options != null && options.plugins) {\n validatePlugins(options.plugins);\n cls = getParserClass(options.plugins);\n }\n\n return new cls(options, input);\n}\n\nconst parserClassCache = {};\n\nfunction getParserClass(pluginsFromOptions) {\n const pluginList = mixinPluginNames.filter(name => hasPlugin(pluginsFromOptions, name));\n const key = pluginList.join(\"/\");\n let cls = parserClassCache[key];\n\n if (!cls) {\n cls = Parser;\n\n for (const plugin of pluginList) {\n cls = mixinPlugins[plugin](cls);\n }\n\n parserClassCache[key] = cls;\n }\n\n return cls;\n}\n\nexports.parse = parse;\nexports.parseExpression = parseExpression;\nexports.tokTypes = tokTypes;\n//# sourceMappingURL=index.js.map\n\n\n//# sourceURL=webpack:///./node_modules/@babel/parser/lib/index.js?"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js&": +/*!***********************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js& ***! + \***********************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _typeof2 = _interopRequireDefault(__webpack_require__(/*! ./node_modules/@babel/runtime/helpers/typeof.js */ \"./node_modules/@babel/runtime/helpers/typeof.js\"));\n\nvar _objectSpread2 = _interopRequireDefault(__webpack_require__(/*! ./node_modules/@babel/runtime/helpers/objectSpread2.js */ \"./node_modules/@babel/runtime/helpers/objectSpread2.js\"));\n\n__webpack_require__(/*! core-js/modules/es.regexp.exec.js */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n\n__webpack_require__(/*! core-js/modules/es.function.name.js */ \"./node_modules/core-js/modules/es.function.name.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.split.js */ \"./node_modules/core-js/modules/es.string.split.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.find-index.js */ \"./node_modules/core-js/modules/es.array.find-index.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.find.js */ \"./node_modules/core-js/modules/es.array.find.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.concat.js */ \"./node_modules/core-js/modules/es.array.concat.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.map.js */ \"./node_modules/core-js/modules/es.array.map.js\");\n\n__webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n\n__webpack_require__(/*! core-js/modules/web.dom-collections.for-each.js */ \"./node_modules/core-js/modules/web.dom-collections.for-each.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.splice.js */ \"./node_modules/core-js/modules/es.array.splice.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.keys.js */ \"./node_modules/core-js/modules/es.object.keys.js\");\n\nvar _vuedraggable = _interopRequireDefault(__webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\"));\n\nvar _throttleDebounce = __webpack_require__(/*! throttle-debounce */ \"./node_modules/throttle-debounce/index.umd.js\");\n\nvar _fileSaver = __webpack_require__(/*! file-saver */ \"./node_modules/file-saver/dist/FileSaver.min.js\");\n\nvar _clipboard = _interopRequireDefault(__webpack_require__(/*! clipboard */ \"./node_modules/clipboard/dist/clipboard.js\"));\n\nvar _render = _interopRequireDefault(__webpack_require__(/*! @/components/render/render */ \"./src/components/render/render.js\"));\n\nvar _FormDrawer = _interopRequireDefault(__webpack_require__(/*! @/views/tool/build/FormDrawer */ \"./src/views/tool/build/FormDrawer.vue\"));\n\nvar _JsonDrawer = _interopRequireDefault(__webpack_require__(/*! @/views/tool/build/JsonDrawer */ \"./src/views/tool/build/JsonDrawer.vue\"));\n\nvar _RightPanel = _interopRequireDefault(__webpack_require__(/*! @/views/tool/build/RightPanel */ \"./src/views/tool/build/RightPanel.vue\"));\n\nvar _config = __webpack_require__(/*! @/components/generator/config */ \"./src/components/generator/config.js\");\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _html = __webpack_require__(/*! @/components/generator/html */ \"./src/components/generator/html.js\");\n\nvar _js = __webpack_require__(/*! @/components/generator/js */ \"./src/components/generator/js.js\");\n\nvar _css = __webpack_require__(/*! @/components/generator/css */ \"./src/components/generator/css.js\");\n\nvar _drawingDefalut = _interopRequireDefault(__webpack_require__(/*! @/components/generator/drawingDefalut */ \"./src/components/generator/drawingDefalut.js\"));\n\nvar _logo = _interopRequireDefault(__webpack_require__(/*! @/assets/logo/logo.png */ \"./src/assets/logo/logo.png\"));\n\nvar _CodeTypeDialog = _interopRequireDefault(__webpack_require__(/*! @/views/tool/build/CodeTypeDialog */ \"./src/views/tool/build/CodeTypeDialog.vue\"));\n\nvar _DraggableItem = _interopRequireDefault(__webpack_require__(/*! @/views/tool/build/DraggableItem */ \"./src/views/tool/build/DraggableItem.vue\"));\n\nvar _db = __webpack_require__(/*! @/utils/db */ \"./src/utils/db.js\");\n\nvar _loadBeautifier = _interopRequireDefault(__webpack_require__(/*! @/utils/loadBeautifier */ \"./src/utils/loadBeautifier.js\"));\n\nvar _constants = __webpack_require__(/*! @/utils/constants */ \"./src/utils/constants.js\");\n\nvar _form = __webpack_require__(/*! @/api/bpm/form */ \"./src/api/bpm/form.js\");\n\nvar _formGenerator = __webpack_require__(/*! @/utils/formGenerator */ \"./src/utils/formGenerator.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar beautifier;\nvar emptyActiveData = {\n style: {},\n autosize: {}\n};\nvar oldActiveId;\nvar tempActiveData;\nvar drawingListInDB = (0, _db.getDrawingList)();\nvar formConfInDB = (0, _db.getFormConf)();\nvar idGlobal = (0, _db.getIdGlobal)();\nvar _default = {\n components: {\n draggable: _vuedraggable.default,\n render: _render.default,\n FormDrawer: _FormDrawer.default,\n JsonDrawer: _JsonDrawer.default,\n RightPanel: _RightPanel.default,\n CodeTypeDialog: _CodeTypeDialog.default,\n DraggableItem: _DraggableItem.default\n },\n data: function data() {\n return {\n logo: _logo.default,\n idGlobal: idGlobal,\n formConf: _config.formConf,\n inputComponents: _config.inputComponents,\n selectComponents: _config.selectComponents,\n layoutComponents: _config.layoutComponents,\n labelWidth: 100,\n // drawingList: drawingDefalut,\n drawingData: {},\n // 生成后的表单数据\n activeId: _drawingDefalut.default[0].__config__.formId,\n drawingList: [],\n // 表单项的数组\n // activeId: undefined,\n // activeData: {},\n drawerVisible: false,\n formData: {},\n dialogVisible: false,\n jsonDrawerVisible: false,\n generateConf: null,\n showFileName: false,\n activeData: _drawingDefalut.default[0],\n // 右边编辑器激活的表单项\n saveDrawingListDebounce: (0, _throttleDebounce.debounce)(340, _db.saveDrawingList),\n saveIdGlobalDebounce: (0, _throttleDebounce.debounce)(340, _db.saveIdGlobal),\n leftComponents: [{\n title: '输入型组件',\n list: _config.inputComponents\n }, {\n title: '选择型组件',\n list: _config.selectComponents\n }, {\n title: '布局型组件',\n list: _config.layoutComponents\n }],\n // 表单参数\n form: {\n status: _constants.CommonStatusEnum.ENABLE\n },\n // 表单校验\n rules: {\n name: [{\n required: true,\n message: \"表单名不能为空\",\n trigger: \"blur\"\n }],\n status: [{\n required: true,\n message: \"开启状态不能为空\",\n trigger: \"blur\"\n }]\n }\n };\n },\n computed: {},\n watch: {\n // eslint-disable-next-line func-names\n 'activeData.__config__.label': function activeData__config__Label(val, oldVal) {\n if (this.activeData.placeholder === undefined || !this.activeData.__config__.tag || oldActiveId !== this.activeId) {\n return;\n }\n\n this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val;\n },\n activeId: {\n handler: function handler(val) {\n oldActiveId = val;\n },\n immediate: true\n },\n drawingList: {\n handler: function handler(val) {\n this.saveDrawingListDebounce(val);\n if (val.length === 0) this.idGlobal = 100;\n },\n deep: true\n },\n idGlobal: {\n handler: function handler(val) {\n this.saveIdGlobalDebounce(val);\n },\n immediate: true\n }\n },\n mounted: function mounted() {\n var _this = this;\n\n // 【add by 芋道源码】不读缓存\n // if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {\n // this.drawingList = drawingListInDB\n // } else {\n // this.drawingList = drawingDefalut\n // }\n // this.activeFormItem(this.drawingList[0])\n // if (formConfInDB) {\n // this.formConf = formConfInDB\n // }\n (0, _loadBeautifier.default)(function (btf) {\n beautifier = btf;\n });\n var clipboard = new _clipboard.default('#copyNode', {\n text: function text(trigger) {\n var codeStr = _this.generateCode();\n\n _this.$notify({\n title: '成功',\n message: '代码已复制到剪切板,可粘贴。',\n type: 'success'\n });\n\n return codeStr;\n }\n });\n clipboard.on('error', function (e) {\n _this.$message.error('代码复制失败');\n });\n },\n created: function created() {\n var _this2 = this;\n\n // 读取表单配置\n var formId = this.$route.query && this.$route.query.formId;\n\n if (formId) {\n (0, _form.getForm)(formId).then(function (response) {\n var data = response.data;\n _this2.form = {\n id: data.id,\n name: data.name,\n status: data.status,\n remark: data.remark\n };\n _this2.formConf = JSON.parse(data.conf);\n _this2.drawingList = (0, _formGenerator.decodeFields)(data.fields); // 设置激活的表单项\n\n _this2.activeData = _this2.drawingList[0];\n _this2.activeId = _this2.activeData.__config__.formId; // 设置 idGlobal,避免重复\n\n _this2.idGlobal += _this2.drawingList.length;\n });\n }\n },\n methods: {\n setObjectValueReduce: function setObjectValueReduce(obj, strKeys, data) {\n var arr = strKeys.split('.');\n arr.reduce(function (pre, item, i) {\n if (arr.length === i + 1) {\n pre[item] = data;\n } else if (!(0, _index.isObjectObject)(pre[item])) {\n pre[item] = {};\n }\n\n return pre[item];\n }, obj);\n },\n setRespData: function setRespData(component, resp) {\n var _component$__config__ = component.__config__,\n dataPath = _component$__config__.dataPath,\n renderKey = _component$__config__.renderKey,\n dataConsumer = _component$__config__.dataConsumer;\n if (!dataPath || !dataConsumer) return;\n var respData = dataPath.split('.').reduce(function (pre, item) {\n return pre[item];\n }, resp); // 将请求回来的数据,赋值到指定属性。\n // 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';\n // 此时赋值代码可写成 component[dataConsumer] = respData;\n // 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce\n\n this.setObjectValueReduce(component, dataConsumer, respData);\n var i = this.drawingList.findIndex(function (item) {\n return item.__config__.renderKey === renderKey;\n });\n if (i > -1) this.$set(this.drawingList, i, component);\n },\n fetchData: function fetchData(component) {\n var _this3 = this;\n\n var _component$__config__2 = component.__config__,\n dataType = _component$__config__2.dataType,\n method = _component$__config__2.method,\n url = _component$__config__2.url;\n\n if (dataType === 'dynamic' && method && url) {\n this.setLoading(component, true);\n this.$axios({\n method: method,\n url: url\n }).then(function (resp) {\n _this3.setLoading(component, false);\n\n _this3.setRespData(component, resp.data);\n });\n }\n },\n setLoading: function setLoading(component, val) {\n var directives = component.directives;\n\n if (Array.isArray(directives)) {\n var t = directives.find(function (d) {\n return d.name === 'loading';\n });\n if (t) t.value = val;\n }\n },\n activeFormItem: function activeFormItem(currentItem) {\n this.activeData = currentItem;\n this.activeId = currentItem.__config__.formId;\n },\n onEnd: function onEnd(obj) {\n if (obj.from !== obj.to) {\n this.fetchData(tempActiveData);\n this.activeData = tempActiveData;\n this.activeId = this.idGlobal;\n }\n },\n addComponent: function addComponent(item) {\n var clone = this.cloneComponent(item);\n this.fetchData(clone);\n this.drawingList.push(clone);\n this.activeFormItem(clone);\n },\n cloneComponent: function cloneComponent(origin) {\n var clone = (0, _index.deepClone)(origin);\n var config = clone.__config__;\n config.span = this.formConf.span; // 生成代码时,会根据span做精简判断\n\n this.createIdAndKey(clone);\n clone.placeholder !== undefined && (clone.placeholder += config.label);\n tempActiveData = clone;\n return tempActiveData;\n },\n createIdAndKey: function createIdAndKey(item) {\n var _this4 = this;\n\n var config = item.__config__;\n config.formId = ++this.idGlobal;\n config.renderKey = \"\".concat(config.formId).concat(+new Date()); // 改变renderKey后可以实现强制更新组件\n\n if (config.layout === 'colFormItem') {\n item.__vModel__ = \"field\".concat(this.idGlobal);\n } else if (config.layout === 'rowFormItem') {\n config.componentName = \"row\".concat(this.idGlobal);\n !Array.isArray(config.children) && (config.children = []);\n delete config.label; // rowFormItem无需配置label属性\n }\n\n if (Array.isArray(config.children)) {\n config.children = config.children.map(function (childItem) {\n return _this4.createIdAndKey(childItem);\n });\n }\n\n return item;\n },\n // 获得表单数据\n AssembleFormData: function AssembleFormData() {\n this.formData = (0, _objectSpread2.default)({\n fields: (0, _index.deepClone)(this.drawingList)\n }, this.formConf);\n },\n save: function save() {\n var _this5 = this;\n\n // this.AssembleFormData()\n // console.log(this.formData)\n this.$refs[\"form\"].validate(function (valid) {\n if (!valid) {\n return;\n }\n\n var form = (0, _objectSpread2.default)({\n conf: JSON.stringify(_this5.formConf),\n // 表单配置\n fields: _this5.encodeFields()\n }, _this5.form); // 修改的提交\n\n if (_this5.form.id != null) {\n (0, _form.updateForm)(form).then(function (response) {\n _this5.msgSuccess(\"修改成功\");\n\n _this5.close();\n });\n return;\n } // 添加的提交\n\n\n (0, _form.createForm)(form).then(function (response) {\n _this5.msgSuccess(\"新增成功\");\n\n _this5.close();\n });\n });\n },\n\n /** 关闭按钮 */\n close: function close() {\n this.$store.dispatch(\"tagsView/delView\", this.$route);\n this.$router.push({\n path: \"/bpm/manager/form\",\n query: {\n t: Date.now()\n }\n });\n },\n encodeFields: function encodeFields() {\n var fields = [];\n this.drawingList.forEach(function (item) {\n fields.push(JSON.stringify(item));\n });\n return fields;\n },\n generate: function generate(data) {\n var func = this[\"exec\".concat((0, _index.titleCase)(this.operationType))];\n this.generateConf = data;\n func && func(data);\n },\n execRun: function execRun(data) {\n this.AssembleFormData();\n this.drawerVisible = true;\n },\n execDownload: function execDownload(data) {\n var codeStr = this.generateCode();\n var blob = new Blob([codeStr], {\n type: 'text/plain;charset=utf-8'\n });\n (0, _fileSaver.saveAs)(blob, data.fileName);\n },\n execCopy: function execCopy(data) {\n document.getElementById('copyNode').click();\n },\n empty: function empty() {\n var _this6 = this;\n\n this.$confirm('确定要清空所有组件吗?', '提示', {\n type: 'warning'\n }).then(function () {\n _this6.drawingList = [];\n _this6.idGlobal = 100;\n });\n },\n drawingItemCopy: function drawingItemCopy(item, list) {\n var clone = (0, _index.deepClone)(item);\n clone = this.createIdAndKey(clone);\n list.push(clone);\n this.activeFormItem(clone);\n },\n drawingItemDelete: function drawingItemDelete(index, list) {\n var _this7 = this;\n\n list.splice(index, 1);\n this.$nextTick(function () {\n var len = _this7.drawingList.length;\n\n if (len) {\n _this7.activeFormItem(_this7.drawingList[len - 1]);\n }\n });\n },\n generateCode: function generateCode() {\n var type = this.generateConf.type;\n this.AssembleFormData();\n var script = (0, _html.vueScript)((0, _js.makeUpJs)(this.formData, type));\n var html = (0, _html.vueTemplate)((0, _html.makeUpHtml)(this.formData, type));\n var css = (0, _html.cssStyle)((0, _css.makeUpCss)(this.formData));\n return beautifier.html(html + script + css, _index.beautifierConf.html);\n },\n showJson: function showJson() {\n this.AssembleFormData();\n this.jsonDrawerVisible = true;\n },\n download: function download() {\n this.dialogVisible = true;\n this.showFileName = true;\n this.operationType = 'download';\n },\n run: function run() {\n this.dialogVisible = true;\n this.showFileName = false;\n this.operationType = 'run';\n },\n copy: function copy() {\n this.dialogVisible = true;\n this.showFileName = false;\n this.operationType = 'copy';\n },\n tagChange: function tagChange(newTag) {\n var _this8 = this;\n\n newTag = this.cloneComponent(newTag);\n var config = newTag.__config__;\n newTag.__vModel__ = this.activeData.__vModel__;\n config.formId = this.activeId;\n config.span = this.activeData.__config__.span;\n this.activeData.__config__.tag = config.tag;\n this.activeData.__config__.tagIcon = config.tagIcon;\n this.activeData.__config__.document = config.document;\n\n if ((0, _typeof2.default)(this.activeData.__config__.defaultValue) === (0, _typeof2.default)(config.defaultValue)) {\n config.defaultValue = this.activeData.__config__.defaultValue;\n }\n\n Object.keys(newTag).forEach(function (key) {\n if (_this8.activeData[key] !== undefined) {\n newTag[key] = _this8.activeData[key];\n }\n });\n this.activeData = newTag;\n this.updateDrawingList(newTag, this.drawingList);\n },\n updateDrawingList: function updateDrawingList(newTag, list) {\n var _this9 = this;\n\n var index = list.findIndex(function (item) {\n return item.__config__.formId === _this9.activeId;\n });\n\n if (index > -1) {\n list.splice(index, 1, newTag);\n } else {\n list.forEach(function (item) {\n if (Array.isArray(item.__config__.children)) _this9.updateDrawingList(newTag, item.__config__.children);\n });\n }\n },\n refreshJson: function refreshJson(data) {\n this.drawingList = (0, _index.deepClone)(data.fields);\n delete data.fields;\n this.formConf = data;\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _objectSpread2 = _interopRequireDefault(__webpack_require__(/*! ./node_modules/@babel/runtime/helpers/objectSpread2.js */ \"./node_modules/@babel/runtime/helpers/objectSpread2.js\"));\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n inheritAttrs: false,\n props: ['showFileName'],\n data: function data() {\n return {\n formData: {\n fileName: undefined,\n type: 'file'\n },\n rules: {\n fileName: [{\n required: true,\n message: '请输入文件名',\n trigger: 'blur'\n }],\n type: [{\n required: true,\n message: '生成类型不能为空',\n trigger: 'change'\n }]\n },\n typeOptions: [{\n label: '页面',\n value: 'file'\n }, {\n label: '弹窗',\n value: 'dialog'\n }]\n };\n },\n computed: {},\n watch: {},\n mounted: function mounted() {},\n methods: {\n onOpen: function onOpen() {\n if (this.showFileName) {\n this.formData.fileName = \"\".concat(+new Date(), \".vue\");\n }\n },\n onClose: function onClose() {},\n close: function close(e) {\n this.$emit('update:visible', false);\n },\n handelConfirm: function handelConfirm() {\n var _this = this;\n\n this.$refs.elForm.validate(function (valid) {\n if (!valid) return;\n\n _this.$emit('confirm', (0, _objectSpread2.default)({}, _this.formData));\n\n _this.close();\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/CodeTypeDialog.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js&": +/*!****************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js& ***! + \****************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.array.map.js */ \"./node_modules/core-js/modules/es.array.map.js\");\n\nvar _vuedraggable = _interopRequireDefault(__webpack_require__(/*! vuedraggable */ \"./node_modules/vuedraggable/dist/vuedraggable.umd.js\"));\n\nvar _render = _interopRequireDefault(__webpack_require__(/*! @/components/render/render */ \"./src/components/render/render.js\"));\n\nvar components = {\n itemBtns: function itemBtns(h, currentItem, index, list) {\n var _this$$listeners = this.$listeners,\n copyItem = _this$$listeners.copyItem,\n deleteItem = _this$$listeners.deleteItem;\n return [h(\"span\", {\n \"class\": \"drawing-item-copy\",\n \"attrs\": {\n \"title\": \"复制\"\n },\n \"on\": {\n \"click\": function click(event) {\n copyItem(currentItem, list);\n event.stopPropagation();\n }\n }\n }, [h(\"i\", {\n \"class\": \"el-icon-copy-document\"\n })]), h(\"span\", {\n \"class\": \"drawing-item-delete\",\n \"attrs\": {\n \"title\": \"删除\"\n },\n \"on\": {\n \"click\": function click(event) {\n deleteItem(index, list);\n event.stopPropagation();\n }\n }\n }, [h(\"i\", {\n \"class\": \"el-icon-delete\"\n })])];\n }\n};\nvar layouts = {\n colFormItem: function colFormItem(h, currentItem, index, list) {\n var _this = this;\n\n var activeItem = this.$listeners.activeItem;\n var config = currentItem.__config__;\n var child = renderChildren.apply(this, arguments);\n var className = this.activeId === config.formId ? 'drawing-item active-from-item' : 'drawing-item';\n if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered';\n var labelWidth = config.labelWidth ? \"\".concat(config.labelWidth, \"px\") : null;\n if (config.showLabel === false) labelWidth = '0';\n return h(\"el-col\", {\n \"attrs\": {\n \"span\": config.span\n },\n \"class\": className,\n \"nativeOn\": {\n \"click\": function click(event) {\n activeItem(currentItem);\n event.stopPropagation();\n }\n }\n }, [h(\"el-form-item\", {\n \"attrs\": {\n \"label-width\": labelWidth,\n \"label\": config.showLabel ? config.label : '',\n \"required\": config.required\n }\n }, [h(_render.default, {\n \"key\": config.renderKey,\n \"attrs\": {\n \"conf\": currentItem\n },\n \"on\": {\n \"input\": function input(event) {\n _this.$set(config, 'defaultValue', event);\n }\n }\n }, [child])]), components.itemBtns.apply(this, arguments)]);\n },\n rowFormItem: function rowFormItem(h, currentItem, index, list) {\n var activeItem = this.$listeners.activeItem;\n var config = currentItem.__config__;\n var className = this.activeId === config.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item';\n var child = renderChildren.apply(this, arguments);\n\n if (currentItem.type === 'flex') {\n child = h(\"el-row\", {\n \"attrs\": {\n \"type\": currentItem.type,\n \"justify\": currentItem.justify,\n \"align\": currentItem.align\n }\n }, [child]);\n }\n\n return h(\"el-col\", {\n \"attrs\": {\n \"span\": config.span\n }\n }, [h(\"el-row\", {\n \"attrs\": {\n \"gutter\": config.gutter\n },\n \"class\": className,\n \"nativeOn\": {\n \"click\": function click(event) {\n activeItem(currentItem);\n event.stopPropagation();\n }\n }\n }, [h(\"span\", {\n \"class\": \"component-name\"\n }, [config.componentName]), h(_vuedraggable.default, {\n \"attrs\": {\n \"list\": config.children || [],\n \"animation\": 340,\n \"group\": \"componentsGroup\"\n },\n \"class\": \"drag-wrapper\"\n }, [child]), components.itemBtns.apply(this, arguments)])]);\n },\n raw: function raw(h, currentItem, index, list) {\n var _this2 = this;\n\n var config = currentItem.__config__;\n var child = renderChildren.apply(this, arguments);\n return h(_render.default, {\n \"key\": config.renderKey,\n \"attrs\": {\n \"conf\": currentItem\n },\n \"on\": {\n \"input\": function input(event) {\n _this2.$set(config, 'defaultValue', event);\n }\n }\n }, [child]);\n }\n};\n\nfunction renderChildren(h, currentItem, index, list) {\n var _this3 = this;\n\n var config = currentItem.__config__;\n if (!Array.isArray(config.children)) return null;\n return config.children.map(function (el, i) {\n var layout = layouts[el.__config__.layout];\n\n if (layout) {\n return layout.call(_this3, h, el, i, config.children);\n }\n\n return layoutIsNotFound.call(_this3);\n });\n}\n\nfunction layoutIsNotFound() {\n throw new Error(\"\\u6CA1\\u6709\\u4E0E\".concat(this.currentItem.__config__.layout, \"\\u5339\\u914D\\u7684layout\"));\n}\n\nvar _default = {\n components: {\n render: _render.default,\n draggable: _vuedraggable.default\n },\n props: ['currentItem', 'index', 'drawingList', 'activeId', 'formConf'],\n render: function render(h) {\n var layout = layouts[this.currentItem.__config__.layout];\n\n if (layout) {\n return layout.call(this, h, this.currentItem, this.index, this.drawingList);\n }\n\n return layoutIsNotFound.call(this);\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/DraggableItem.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.array.concat.js */ \"./node_modules/core-js/modules/es.array.concat.js\");\n\n__webpack_require__(/*! core-js/modules/es.regexp.exec.js */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\n__webpack_require__(/*! core-js/modules/web.dom-collections.for-each.js */ \"./node_modules/core-js/modules/web.dom-collections.for-each.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.ends-with.js */ \"./node_modules/core-js/modules/es.string.ends-with.js\");\n\nvar _parser = __webpack_require__(/*! @babel/parser */ \"./node_modules/@babel/parser/lib/index.js\");\n\nvar _clipboard = _interopRequireDefault(__webpack_require__(/*! clipboard */ \"./node_modules/clipboard/dist/clipboard.js\"));\n\nvar _fileSaver = __webpack_require__(/*! file-saver */ \"./node_modules/file-saver/dist/FileSaver.min.js\");\n\nvar _html = __webpack_require__(/*! @/components/generator/html */ \"./src/components/generator/html.js\");\n\nvar _js = __webpack_require__(/*! @/components/generator/js */ \"./src/components/generator/js.js\");\n\nvar _css = __webpack_require__(/*! @/components/generator/css */ \"./src/components/generator/css.js\");\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _ResourceDialog = _interopRequireDefault(__webpack_require__(/*! ./ResourceDialog */ \"./src/views/tool/build/ResourceDialog.vue\"));\n\nvar _loadMonaco = _interopRequireDefault(__webpack_require__(/*! @/utils/loadMonaco */ \"./src/utils/loadMonaco.js\"));\n\nvar _loadBeautifier = _interopRequireDefault(__webpack_require__(/*! @/utils/loadBeautifier */ \"./src/utils/loadBeautifier.js\"));\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar editorObj = {\n html: null,\n js: null,\n css: null\n};\nvar mode = {\n html: 'html',\n js: 'javascript',\n css: 'css'\n};\nvar beautifier;\nvar monaco;\nvar _default = {\n components: {\n ResourceDialog: _ResourceDialog.default\n },\n props: ['formData', 'generateConf'],\n data: function data() {\n return {\n activeTab: 'html',\n htmlCode: '',\n jsCode: '',\n cssCode: '',\n codeFrame: '',\n isIframeLoaded: false,\n isInitcode: false,\n // 保证open后两个异步只执行一次runcode\n isRefreshCode: false,\n // 每次打开都需要重新刷新代码\n resourceVisible: false,\n scripts: [],\n links: [],\n monaco: null\n };\n },\n computed: {\n resources: function resources() {\n return this.scripts.concat(this.links);\n }\n },\n watch: {},\n created: function created() {},\n mounted: function mounted() {\n var _this = this;\n\n window.addEventListener('keydown', this.preventDefaultSave);\n var clipboard = new _clipboard.default('.copy-btn', {\n text: function text(trigger) {\n var codeStr = _this.generateCode();\n\n _this.$notify({\n title: '成功',\n message: '代码已复制到剪切板,可粘贴。',\n type: 'success'\n });\n\n return codeStr;\n }\n });\n clipboard.on('error', function (e) {\n _this.$message.error('代码复制失败');\n });\n },\n beforeDestroy: function beforeDestroy() {\n window.removeEventListener('keydown', this.preventDefaultSave);\n },\n methods: {\n preventDefaultSave: function preventDefaultSave(e) {\n if (e.key === 's' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n }\n },\n onOpen: function onOpen() {\n var _this2 = this;\n\n var type = this.generateConf.type;\n this.htmlCode = (0, _html.makeUpHtml)(this.formData, type);\n this.jsCode = (0, _js.makeUpJs)(this.formData, type);\n this.cssCode = (0, _css.makeUpCss)(this.formData);\n (0, _loadBeautifier.default)(function (btf) {\n beautifier = btf;\n _this2.htmlCode = beautifier.html(_this2.htmlCode, _index.beautifierConf.html);\n _this2.jsCode = beautifier.js(_this2.jsCode, _index.beautifierConf.js);\n _this2.cssCode = beautifier.css(_this2.cssCode, _index.beautifierConf.html);\n (0, _loadMonaco.default)(function (val) {\n monaco = val;\n\n _this2.setEditorValue('editorHtml', 'html', _this2.htmlCode);\n\n _this2.setEditorValue('editorJs', 'js', _this2.jsCode);\n\n _this2.setEditorValue('editorCss', 'css', _this2.cssCode);\n\n if (!_this2.isInitcode) {\n _this2.isRefreshCode = true;\n _this2.isIframeLoaded && (_this2.isInitcode = true) && _this2.runCode();\n }\n });\n });\n },\n onClose: function onClose() {\n this.isInitcode = false;\n this.isRefreshCode = false;\n },\n iframeLoad: function iframeLoad() {\n if (!this.isInitcode) {\n this.isIframeLoaded = true;\n this.isRefreshCode && (this.isInitcode = true) && this.runCode();\n }\n },\n setEditorValue: function setEditorValue(id, type, codeStr) {\n var _this3 = this;\n\n if (editorObj[type]) {\n editorObj[type].setValue(codeStr);\n } else {\n editorObj[type] = monaco.editor.create(document.getElementById(id), {\n value: codeStr,\n theme: 'vs-dark',\n language: mode[type],\n automaticLayout: true\n });\n } // ctrl + s 刷新\n\n\n editorObj[type].onKeyDown(function (e) {\n if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {\n _this3.runCode();\n }\n });\n },\n runCode: function runCode() {\n var jsCodeStr = editorObj.js.getValue();\n\n try {\n var ast = (0, _parser.parse)(jsCodeStr, {\n sourceType: 'module'\n });\n var astBody = ast.program.body;\n\n if (astBody.length > 1) {\n this.$confirm('js格式不能识别,仅支持修改export default的对象内容', '提示', {\n type: 'warning'\n });\n return;\n }\n\n if (astBody[0].type === 'ExportDefaultDeclaration') {\n var postData = {\n type: 'refreshFrame',\n data: {\n generateConf: this.generateConf,\n html: editorObj.html.getValue(),\n js: jsCodeStr.replace(_index.exportDefault, ''),\n css: editorObj.css.getValue(),\n scripts: this.scripts,\n links: this.links\n }\n };\n this.$refs.previewPage.contentWindow.postMessage(postData, location.origin);\n } else {\n this.$message.error('请使用export default');\n }\n } catch (err) {\n this.$message.error(\"js\\u9519\\u8BEF\\uFF1A\".concat(err));\n console.error(err);\n }\n },\n generateCode: function generateCode() {\n var html = (0, _html.vueTemplate)(editorObj.html.getValue());\n var script = (0, _html.vueScript)(editorObj.js.getValue());\n var css = (0, _html.cssStyle)(editorObj.css.getValue());\n return beautifier.html(html + script + css, _index.beautifierConf.html);\n },\n exportFile: function exportFile() {\n var _this4 = this;\n\n this.$prompt('文件名:', '导出文件', {\n inputValue: \"\".concat(+new Date(), \".vue\"),\n closeOnClickModal: false,\n inputPlaceholder: '请输入文件名'\n }).then(function (_ref) {\n var value = _ref.value;\n if (!value) value = \"\".concat(+new Date(), \".vue\");\n\n var codeStr = _this4.generateCode();\n\n var blob = new Blob([codeStr], {\n type: 'text/plain;charset=utf-8'\n });\n (0, _fileSaver.saveAs)(blob, value);\n });\n },\n showResource: function showResource() {\n this.resourceVisible = true;\n },\n setResource: function setResource(arr) {\n var scripts = [];\n var links = [];\n\n if (Array.isArray(arr)) {\n arr.forEach(function (item) {\n if (item.endsWith('.css')) {\n links.push(item);\n } else {\n scripts.push(item);\n }\n });\n this.scripts = scripts;\n this.links = links;\n } else {\n this.scripts = [];\n this.links = [];\n }\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js&": +/*!**************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js& ***! + \**************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.array.map.js */ \"./node_modules/core-js/modules/es.array.map.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.filter.js */ \"./node_modules/core-js/modules/es.array.filter.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\nvar _icon = _interopRequireDefault(__webpack_require__(/*! @/utils/icon.json */ \"./src/utils/icon.json\"));\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar originList = _icon.default.map(function (name) {\n return \"el-icon-\".concat(name);\n});\n\nvar _default = {\n inheritAttrs: false,\n props: ['current'],\n data: function data() {\n return {\n iconList: originList,\n active: null,\n key: ''\n };\n },\n watch: {\n key: function key(val) {\n if (val) {\n this.iconList = originList.filter(function (name) {\n return name.indexOf(val) > -1;\n });\n } else {\n this.iconList = originList;\n }\n }\n },\n methods: {\n onOpen: function onOpen() {\n this.active = this.current;\n this.key = '';\n },\n onClose: function onClose() {},\n onSelect: function onSelect(icon) {\n this.active = icon;\n this.$emit('select', icon);\n this.$emit('update:visible', false);\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _clipboard = _interopRequireDefault(__webpack_require__(/*! clipboard */ \"./node_modules/clipboard/dist/clipboard.js\"));\n\nvar _fileSaver = __webpack_require__(/*! file-saver */ \"./node_modules/file-saver/dist/FileSaver.min.js\");\n\nvar _loadMonaco = _interopRequireDefault(__webpack_require__(/*! @/utils/loadMonaco */ \"./src/utils/loadMonaco.js\"));\n\nvar _loadBeautifier = _interopRequireDefault(__webpack_require__(/*! @/utils/loadBeautifier */ \"./src/utils/loadBeautifier.js\"));\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar beautifier;\nvar monaco;\nvar _default = {\n components: {},\n props: {\n jsonStr: {\n type: String,\n required: true\n }\n },\n data: function data() {\n return {};\n },\n computed: {},\n watch: {},\n created: function created() {},\n mounted: function mounted() {\n var _this = this;\n\n window.addEventListener('keydown', this.preventDefaultSave);\n var clipboard = new _clipboard.default('.copy-json-btn', {\n text: function text(trigger) {\n _this.$notify({\n title: '成功',\n message: '代码已复制到剪切板,可粘贴。',\n type: 'success'\n });\n\n return _this.beautifierJson;\n }\n });\n clipboard.on('error', function (e) {\n _this.$message.error('代码复制失败');\n });\n },\n beforeDestroy: function beforeDestroy() {\n window.removeEventListener('keydown', this.preventDefaultSave);\n },\n methods: {\n preventDefaultSave: function preventDefaultSave(e) {\n if (e.key === 's' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n }\n },\n onOpen: function onOpen() {\n var _this2 = this;\n\n (0, _loadBeautifier.default)(function (btf) {\n beautifier = btf;\n _this2.beautifierJson = beautifier.js(_this2.jsonStr, _index.beautifierConf.js);\n (0, _loadMonaco.default)(function (val) {\n monaco = val;\n\n _this2.setEditorValue('editorJson', _this2.beautifierJson);\n });\n });\n },\n onClose: function onClose() {},\n setEditorValue: function setEditorValue(id, codeStr) {\n var _this3 = this;\n\n if (this.jsonEditor) {\n this.jsonEditor.setValue(codeStr);\n } else {\n this.jsonEditor = monaco.editor.create(document.getElementById(id), {\n value: codeStr,\n theme: 'vs-dark',\n language: 'json',\n automaticLayout: true\n }); // ctrl + s 刷新\n\n this.jsonEditor.onKeyDown(function (e) {\n if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {\n _this3.refresh();\n }\n });\n }\n },\n exportJsonFile: function exportJsonFile() {\n var _this4 = this;\n\n this.$prompt('文件名:', '导出文件', {\n inputValue: \"\".concat(+new Date(), \".json\"),\n closeOnClickModal: false,\n inputPlaceholder: '请输入文件名'\n }).then(function (_ref) {\n var value = _ref.value;\n if (!value) value = \"\".concat(+new Date(), \".json\");\n\n var codeStr = _this4.jsonEditor.getValue();\n\n var blob = new Blob([codeStr], {\n type: 'text/plain;charset=utf-8'\n });\n (0, _fileSaver.saveAs)(blob, value);\n });\n },\n refresh: function refresh() {\n try {\n this.$emit('refresh', JSON.parse(this.jsonEditor.getValue()));\n } catch (error) {\n this.$notify({\n title: '错误',\n message: 'JSON格式错误,请检查',\n type: 'error'\n });\n }\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.array.filter.js */ \"./node_modules/core-js/modules/es.array.filter.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.splice.js */ \"./node_modules/core-js/modules/es.array.splice.js\");\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n components: {},\n inheritAttrs: false,\n props: ['originResource'],\n data: function data() {\n return {\n resources: null\n };\n },\n computed: {},\n watch: {},\n created: function created() {},\n mounted: function mounted() {},\n methods: {\n onOpen: function onOpen() {\n this.resources = this.originResource.length ? (0, _index.deepClone)(this.originResource) : [''];\n },\n onClose: function onClose() {},\n close: function close() {\n this.$emit('update:visible', false);\n },\n handelConfirm: function handelConfirm() {\n var results = this.resources.filter(function (item) {\n return !!item;\n }) || [];\n this.$emit('save', results);\n this.close();\n\n if (results.length) {\n this.resources = results;\n }\n },\n deleteOne: function deleteOne(index) {\n this.resources.splice(index, 1);\n },\n addOne: function addOne(url) {\n if (this.resources.indexOf(url) > -1) {\n this.$message('资源已存在');\n } else {\n this.resources.push(url);\n }\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.array.concat.js */ \"./node_modules/core-js/modules/es.array.concat.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.find-index.js */ \"./node_modules/core-js/modules/es.array.find-index.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.splice.js */ \"./node_modules/core-js/modules/es.array.splice.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.join.js */ \"./node_modules/core-js/modules/es.array.join.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.map.js */ \"./node_modules/core-js/modules/es.array.map.js\");\n\n__webpack_require__(/*! core-js/modules/es.regexp.exec.js */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.split.js */ \"./node_modules/core-js/modules/es.string.split.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.find.js */ \"./node_modules/core-js/modules/es.array.find.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n\nvar _util = __webpack_require__(/*! util */ \"./node_modules/util/util.js\");\n\nvar _TreeNodeDialog = _interopRequireDefault(__webpack_require__(/*! ./TreeNodeDialog */ \"./src/views/tool/build/TreeNodeDialog.vue\"));\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _IconsDialog = _interopRequireDefault(__webpack_require__(/*! ./IconsDialog */ \"./src/views/tool/build/IconsDialog.vue\"));\n\nvar _config = __webpack_require__(/*! @/components/generator/config */ \"./src/components/generator/config.js\");\n\nvar _db = __webpack_require__(/*! @/utils/db */ \"./src/utils/db.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar dateTimeFormat = {\n date: 'yyyy-MM-dd',\n week: 'yyyy 第 WW 周',\n month: 'yyyy-MM',\n year: 'yyyy',\n datetime: 'yyyy-MM-dd HH:mm:ss',\n daterange: 'yyyy-MM-dd',\n monthrange: 'yyyy-MM',\n datetimerange: 'yyyy-MM-dd HH:mm:ss'\n}; // 使changeRenderKey在目标组件改变时可用\n\nvar needRerenderList = ['tinymce'];\nvar _default = {\n components: {\n TreeNodeDialog: _TreeNodeDialog.default,\n IconsDialog: _IconsDialog.default\n },\n props: ['showField', 'activeData', 'formConf'],\n data: function data() {\n return {\n currentTab: 'field',\n currentNode: null,\n dialogVisible: false,\n iconsVisible: false,\n currentIconModel: null,\n dateTypeOptions: [{\n label: '日(date)',\n value: 'date'\n }, {\n label: '周(week)',\n value: 'week'\n }, {\n label: '月(month)',\n value: 'month'\n }, {\n label: '年(year)',\n value: 'year'\n }, {\n label: '日期时间(datetime)',\n value: 'datetime'\n }],\n dateRangeTypeOptions: [{\n label: '日期范围(daterange)',\n value: 'daterange'\n }, {\n label: '月范围(monthrange)',\n value: 'monthrange'\n }, {\n label: '日期时间范围(datetimerange)',\n value: 'datetimerange'\n }],\n colorFormatOptions: [{\n label: 'hex',\n value: 'hex'\n }, {\n label: 'rgb',\n value: 'rgb'\n }, {\n label: 'rgba',\n value: 'rgba'\n }, {\n label: 'hsv',\n value: 'hsv'\n }, {\n label: 'hsl',\n value: 'hsl'\n }],\n justifyOptions: [{\n label: 'start',\n value: 'start'\n }, {\n label: 'end',\n value: 'end'\n }, {\n label: 'center',\n value: 'center'\n }, {\n label: 'space-around',\n value: 'space-around'\n }, {\n label: 'space-between',\n value: 'space-between'\n }],\n layoutTreeProps: {\n label: function label(data, node) {\n var config = data.__config__;\n return data.componentName || \"\".concat(config.label, \": \").concat(data.__vModel__);\n }\n }\n };\n },\n computed: {\n documentLink: function documentLink() {\n return this.activeData.__config__.document || 'https://element.eleme.cn/#/zh-CN/component/installation';\n },\n dateOptions: function dateOptions() {\n if (this.activeData.type !== undefined && this.activeData.__config__.tag === 'el-date-picker') {\n if (this.activeData['start-placeholder'] === undefined) {\n return this.dateTypeOptions;\n }\n\n return this.dateRangeTypeOptions;\n }\n\n return [];\n },\n tagList: function tagList() {\n return [{\n label: '输入型组件',\n options: _config.inputComponents\n }, {\n label: '选择型组件',\n options: _config.selectComponents\n }];\n },\n activeTag: function activeTag() {\n return this.activeData.__config__.tag;\n },\n isShowMin: function isShowMin() {\n return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1;\n },\n isShowMax: function isShowMax() {\n return ['el-input-number', 'el-slider', 'el-rate'].indexOf(this.activeTag) > -1;\n },\n isShowStep: function isShowStep() {\n return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1;\n }\n },\n watch: {\n formConf: {\n handler: function handler(val) {\n (0, _db.saveFormConf)(val);\n },\n deep: true\n }\n },\n methods: {\n addReg: function addReg() {\n this.activeData.__config__.regList.push({\n pattern: '',\n message: ''\n });\n },\n addSelectItem: function addSelectItem() {\n this.activeData.__slot__.options.push({\n label: '',\n value: ''\n });\n },\n addTreeItem: function addTreeItem() {\n ++this.idGlobal;\n this.dialogVisible = true;\n this.currentNode = this.activeData.options;\n },\n renderContent: function renderContent(h, _ref) {\n var _this = this;\n\n var node = _ref.node,\n data = _ref.data,\n store = _ref.store;\n return h(\"div\", {\n \"class\": \"custom-tree-node\"\n }, [h(\"span\", [node.label]), h(\"span\", {\n \"class\": \"node-operation\"\n }, [h(\"i\", {\n \"on\": {\n \"click\": function click() {\n return _this.append(data);\n }\n },\n \"class\": \"el-icon-plus\",\n \"attrs\": {\n \"title\": \"添加\"\n }\n }), h(\"i\", {\n \"on\": {\n \"click\": function click() {\n return _this.remove(node, data);\n }\n },\n \"class\": \"el-icon-delete\",\n \"attrs\": {\n \"title\": \"删除\"\n }\n })])]);\n },\n append: function append(data) {\n if (!data.children) {\n this.$set(data, 'children', []);\n }\n\n this.dialogVisible = true;\n this.currentNode = data.children;\n },\n remove: function remove(node, data) {\n this.activeData.__config__.defaultValue = []; // 避免删除时报错\n\n var parent = node.parent;\n var children = parent.data.children || parent.data;\n var index = children.findIndex(function (d) {\n return d.id === data.id;\n });\n children.splice(index, 1);\n },\n addNode: function addNode(data) {\n this.currentNode.push(data);\n },\n setOptionValue: function setOptionValue(item, val) {\n item.value = (0, _index.isNumberStr)(val) ? +val : val;\n },\n setDefaultValue: function setDefaultValue(val) {\n if (Array.isArray(val)) {\n return val.join(',');\n } // if (['string', 'number'].indexOf(typeof val) > -1) {\n // return val\n // }\n\n\n if (typeof val === 'boolean') {\n return \"\".concat(val);\n }\n\n return val;\n },\n onDefaultValueInput: function onDefaultValueInput(str) {\n if ((0, _util.isArray)(this.activeData.__config__.defaultValue)) {\n // 数组\n this.$set(this.activeData.__config__, 'defaultValue', str.split(',').map(function (val) {\n return (0, _index.isNumberStr)(val) ? +val : val;\n }));\n } else if (['true', 'false'].indexOf(str) > -1) {\n // 布尔\n this.$set(this.activeData.__config__, 'defaultValue', JSON.parse(str));\n } else {\n // 字符串和数字\n this.$set(this.activeData.__config__, 'defaultValue', (0, _index.isNumberStr)(str) ? +str : str);\n }\n },\n onSwitchValueInput: function onSwitchValueInput(val, name) {\n if (['true', 'false'].indexOf(val) > -1) {\n this.$set(this.activeData, name, JSON.parse(val));\n } else {\n this.$set(this.activeData, name, (0, _index.isNumberStr)(val) ? +val : val);\n }\n },\n setTimeValue: function setTimeValue(val, type) {\n var valueFormat = type === 'week' ? dateTimeFormat.date : val;\n this.$set(this.activeData.__config__, 'defaultValue', null);\n this.$set(this.activeData, 'value-format', valueFormat);\n this.$set(this.activeData, 'format', val);\n },\n spanChange: function spanChange(val) {\n this.formConf.span = val;\n },\n multipleChange: function multipleChange(val) {\n this.$set(this.activeData.__config__, 'defaultValue', val ? [] : '');\n },\n dateTypeChange: function dateTypeChange(val) {\n this.setTimeValue(dateTimeFormat[val], val);\n },\n rangeChange: function rangeChange(val) {\n this.$set(this.activeData.__config__, 'defaultValue', val ? [this.activeData.min, this.activeData.max] : this.activeData.min);\n },\n rateTextChange: function rateTextChange(val) {\n if (val) this.activeData['show-score'] = false;\n },\n rateScoreChange: function rateScoreChange(val) {\n if (val) this.activeData['show-text'] = false;\n },\n colorFormatChange: function colorFormatChange(val) {\n this.activeData.__config__.defaultValue = null;\n this.activeData['show-alpha'] = val.indexOf('a') > -1;\n this.activeData.__config__.renderKey = +new Date(); // 更新renderKey,重新渲染该组件\n },\n openIconsDialog: function openIconsDialog(model) {\n this.iconsVisible = true;\n this.currentIconModel = model;\n },\n setIcon: function setIcon(val) {\n this.activeData[this.currentIconModel] = val;\n },\n tagChange: function tagChange(tagIcon) {\n var target = _config.inputComponents.find(function (item) {\n return item.__config__.tagIcon === tagIcon;\n });\n\n if (!target) target = _config.selectComponents.find(function (item) {\n return item.__config__.tagIcon === tagIcon;\n });\n this.$emit('tag-change', target);\n },\n changeRenderKey: function changeRenderKey() {\n if (needRerenderList.includes(this.activeData.__config__.tag)) {\n this.activeData.__config__.renderKey = +new Date();\n }\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _db = __webpack_require__(/*! @/utils/db */ \"./src/utils/db.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar id = (0, _db.getTreeNodeId)();\nvar _default = {\n components: {},\n inheritAttrs: false,\n props: [],\n data: function data() {\n return {\n id: id,\n formData: {\n label: undefined,\n value: undefined\n },\n rules: {\n label: [{\n required: true,\n message: '请输入选项名',\n trigger: 'blur'\n }],\n value: [{\n required: true,\n message: '请输入选项值',\n trigger: 'blur'\n }]\n },\n dataType: 'string',\n dataTypeOptions: [{\n label: '字符串',\n value: 'string'\n }, {\n label: '数字',\n value: 'number'\n }]\n };\n },\n computed: {},\n watch: {\n // eslint-disable-next-line func-names\n 'formData.value': function formDataValue(val) {\n this.dataType = (0, _index.isNumberStr)(val) ? 'number' : 'string';\n },\n id: function id(val) {\n (0, _db.saveTreeNodeId)(val);\n }\n },\n created: function created() {},\n mounted: function mounted() {},\n methods: {\n onOpen: function onOpen() {\n this.formData = {\n label: undefined,\n value: undefined\n };\n },\n onClose: function onClose() {},\n close: function close() {\n this.$emit('update:visible', false);\n },\n handelConfirm: function handelConfirm() {\n var _this = this;\n\n this.$refs.elForm.validate(function (valid) {\n if (!valid) return;\n\n if (_this.dataType === 'number') {\n _this.formData.value = parseFloat(_this.formData.value);\n }\n\n _this.formData.id = _this.id++;\n\n _this.$emit('commit', _this.formData);\n\n _this.close();\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/tool/build/TreeNodeDialog.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122&": +/*!*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122& ***! + \*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"container\" },\n [\n _c(\n \"div\",\n { staticClass: \"left-board\" },\n [\n _vm._m(0),\n _c(\"el-scrollbar\", { staticClass: \"left-scrollbar\" }, [\n _c(\n \"div\",\n { staticClass: \"components-list\" },\n [\n _vm._l(_vm.leftComponents, function (item, listIndex) {\n return _c(\n \"div\",\n { key: listIndex },\n [\n _c(\n \"div\",\n { staticClass: \"components-title\" },\n [\n _c(\"svg-icon\", {\n attrs: { \"icon-class\": \"component\" },\n }),\n _vm._v(\" \" + _vm._s(item.title) + \" \"),\n ],\n 1\n ),\n _c(\n \"draggable\",\n {\n staticClass: \"components-draggable\",\n attrs: {\n list: item.list,\n group: {\n name: \"componentsGroup\",\n pull: \"clone\",\n put: false,\n },\n clone: _vm.cloneComponent,\n draggable: \".components-item\",\n sort: false,\n },\n on: { end: _vm.onEnd },\n },\n _vm._l(item.list, function (element, index) {\n return _c(\n \"div\",\n {\n key: index,\n staticClass: \"components-item\",\n on: {\n click: function ($event) {\n return _vm.addComponent(element)\n },\n },\n },\n [\n _c(\n \"div\",\n { staticClass: \"components-body\" },\n [\n _c(\"svg-icon\", {\n attrs: {\n \"icon-class\": element.__config__.tagIcon,\n },\n }),\n _vm._v(\n \" \" + _vm._s(element.__config__.label) + \" \"\n ),\n ],\n 1\n ),\n ]\n )\n }),\n 0\n ),\n ],\n 1\n )\n }),\n _c(\n \"el-form\",\n {\n ref: \"form\",\n attrs: {\n model: _vm.form,\n rules: _vm.rules,\n \"label-width\": \"80px\",\n },\n },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"表单名\", prop: \"name\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入表单名\" },\n model: {\n value: _vm.form.name,\n callback: function ($$v) {\n _vm.$set(_vm.form, \"name\", $$v)\n },\n expression: \"form.name\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"开启状态\", prop: \"status\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.form.status,\n callback: function ($$v) {\n _vm.$set(_vm.form, \"status\", $$v)\n },\n expression: \"form.status\",\n },\n },\n _vm._l(\n this.getDictDatas(_vm.DICT_TYPE.COMMON_STATUS),\n function (dict) {\n return _c(\n \"el-radio\",\n {\n key: dict.value,\n attrs: { label: parseInt(dict.value) },\n },\n [_vm._v(_vm._s(dict.label))]\n )\n }\n ),\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"备注\", prop: \"remark\" } },\n [\n _c(\"el-input\", {\n attrs: {\n type: \"textarea\",\n placeholder: \"请输入备注\",\n },\n model: {\n value: _vm.form.remark,\n callback: function ($$v) {\n _vm.$set(_vm.form, \"remark\", $$v)\n },\n expression: \"form.remark\",\n },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 2\n ),\n ]),\n ],\n 1\n ),\n _c(\n \"div\",\n { staticClass: \"center-board\" },\n [\n _c(\n \"div\",\n { staticClass: \"action-bar\" },\n [\n _c(\n \"el-button\",\n {\n attrs: { icon: \"el-icon-check\", type: \"text\" },\n on: { click: _vm.save },\n },\n [_vm._v(\"保存\")]\n ),\n _c(\n \"el-button\",\n {\n attrs: { icon: \"el-icon-view\", type: \"text\" },\n on: { click: _vm.showJson },\n },\n [_vm._v(\" 查看json \")]\n ),\n _c(\n \"el-button\",\n {\n staticClass: \"delete-btn\",\n attrs: { icon: \"el-icon-delete\", type: \"text\" },\n on: { click: _vm.empty },\n },\n [_vm._v(\" 清空 \")]\n ),\n ],\n 1\n ),\n _c(\n \"el-scrollbar\",\n { staticClass: \"center-scrollbar\" },\n [\n _c(\n \"el-row\",\n {\n staticClass: \"center-board-row\",\n attrs: { gutter: _vm.formConf.gutter },\n },\n [\n _c(\n \"el-form\",\n {\n attrs: {\n size: _vm.formConf.size,\n \"label-position\": _vm.formConf.labelPosition,\n disabled: _vm.formConf.disabled,\n \"label-width\": _vm.formConf.labelWidth + \"px\",\n },\n },\n [\n _c(\n \"draggable\",\n {\n staticClass: \"drawing-board\",\n attrs: {\n list: _vm.drawingList,\n animation: 340,\n group: \"componentsGroup\",\n },\n },\n _vm._l(_vm.drawingList, function (item, index) {\n return _c(\"draggable-item\", {\n key: item.renderKey,\n attrs: {\n \"drawing-list\": _vm.drawingList,\n \"current-item\": item,\n index: index,\n \"active-id\": _vm.activeId,\n \"form-conf\": _vm.formConf,\n },\n on: {\n activeItem: _vm.activeFormItem,\n copyItem: _vm.drawingItemCopy,\n deleteItem: _vm.drawingItemDelete,\n },\n })\n }),\n 1\n ),\n _c(\n \"div\",\n {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: !_vm.drawingList.length,\n expression: \"!drawingList.length\",\n },\n ],\n staticClass: \"empty-info\",\n },\n [_vm._v(\" 从左侧拖入或点选组件进行表单设计 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\"right-panel\", {\n attrs: {\n \"active-data\": _vm.activeData,\n \"form-conf\": _vm.formConf,\n \"show-field\": !!_vm.drawingList.length,\n },\n on: { \"tag-change\": _vm.tagChange, \"fetch-data\": _vm.fetchData },\n }),\n _c(\"json-drawer\", {\n attrs: {\n size: \"60%\",\n visible: _vm.jsonDrawerVisible,\n \"json-str\": JSON.stringify(_vm.formData),\n },\n on: {\n \"update:visible\": function ($event) {\n _vm.jsonDrawerVisible = $event\n },\n refresh: _vm.refreshJson,\n },\n }),\n ],\n 1\n )\n}\nvar staticRenderFns = [\n function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"logo-wrapper\" }, [\n _c(\"div\", { staticClass: \"logo\" }, [_vm._v(\"流程表单\")]),\n ])\n },\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true&": +/*!*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true& ***! + \*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"el-dialog\",\n _vm._g(\n _vm._b(\n {\n attrs: {\n width: \"500px\",\n \"close-on-click-modal\": false,\n \"modal-append-to-body\": false,\n },\n on: { open: _vm.onOpen, close: _vm.onClose },\n },\n \"el-dialog\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _c(\n \"el-row\",\n { attrs: { gutter: 15 } },\n [\n _c(\n \"el-form\",\n {\n ref: \"elForm\",\n attrs: {\n model: _vm.formData,\n rules: _vm.rules,\n size: \"medium\",\n \"label-width\": \"100px\",\n },\n },\n [\n _c(\n \"el-col\",\n { attrs: { span: 24 } },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"生成类型\", prop: \"type\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.formData.type,\n callback: function ($$v) {\n _vm.$set(_vm.formData, \"type\", $$v)\n },\n expression: \"formData.type\",\n },\n },\n _vm._l(_vm.typeOptions, function (item, index) {\n return _c(\n \"el-radio-button\",\n {\n key: index,\n attrs: {\n label: item.value,\n disabled: item.disabled,\n },\n },\n [_vm._v(\" \" + _vm._s(item.label) + \" \")]\n )\n }),\n 1\n ),\n ],\n 1\n ),\n _vm.showFileName\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"文件名\", prop: \"fileName\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入文件名\",\n clearable: \"\",\n },\n model: {\n value: _vm.formData.fileName,\n callback: function ($$v) {\n _vm.$set(_vm.formData, \"fileName\", $$v)\n },\n expression: \"formData.fileName\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"div\",\n { attrs: { slot: \"footer\" }, slot: \"footer\" },\n [\n _c(\"el-button\", { on: { click: _vm.close } }, [_vm._v(\" 取消 \")]),\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\" },\n on: { click: _vm.handelConfirm },\n },\n [_vm._v(\" 确定 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/CodeTypeDialog.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true&": +/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true& ***! + \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"el-drawer\",\n _vm._g(\n _vm._b(\n { on: { opened: _vm.onOpen, close: _vm.onClose } },\n \"el-drawer\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _c(\n \"div\",\n { staticStyle: { height: \"100%\" } },\n [\n _c(\n \"el-row\",\n { staticStyle: { height: \"100%\", overflow: \"auto\" } },\n [\n _c(\n \"el-col\",\n { staticClass: \"left-editor\", attrs: { md: 24, lg: 12 } },\n [\n _c(\n \"div\",\n {\n staticClass: \"setting\",\n attrs: { title: \"资源引用\" },\n on: { click: _vm.showResource },\n },\n [\n _c(\n \"el-badge\",\n {\n staticClass: \"item\",\n attrs: { \"is-dot\": !!_vm.resources.length },\n },\n [_c(\"i\", { staticClass: \"el-icon-setting\" })]\n ),\n ],\n 1\n ),\n _c(\n \"el-tabs\",\n {\n staticClass: \"editor-tabs\",\n attrs: { type: \"card\" },\n model: {\n value: _vm.activeTab,\n callback: function ($$v) {\n _vm.activeTab = $$v\n },\n expression: \"activeTab\",\n },\n },\n [\n _c(\"el-tab-pane\", { attrs: { name: \"html\" } }, [\n _c(\n \"span\",\n { attrs: { slot: \"label\" }, slot: \"label\" },\n [\n _vm.activeTab === \"html\"\n ? _c(\"i\", { staticClass: \"el-icon-edit\" })\n : _c(\"i\", {\n staticClass: \"el-icon-document\",\n }),\n _vm._v(\" template \"),\n ]\n ),\n ]),\n _c(\"el-tab-pane\", { attrs: { name: \"js\" } }, [\n _c(\n \"span\",\n { attrs: { slot: \"label\" }, slot: \"label\" },\n [\n _vm.activeTab === \"js\"\n ? _c(\"i\", { staticClass: \"el-icon-edit\" })\n : _c(\"i\", {\n staticClass: \"el-icon-document\",\n }),\n _vm._v(\" script \"),\n ]\n ),\n ]),\n _c(\"el-tab-pane\", { attrs: { name: \"css\" } }, [\n _c(\n \"span\",\n { attrs: { slot: \"label\" }, slot: \"label\" },\n [\n _vm.activeTab === \"css\"\n ? _c(\"i\", { staticClass: \"el-icon-edit\" })\n : _c(\"i\", {\n staticClass: \"el-icon-document\",\n }),\n _vm._v(\" css \"),\n ]\n ),\n ]),\n ],\n 1\n ),\n _c(\"div\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.activeTab === \"html\",\n expression: \"activeTab==='html'\",\n },\n ],\n staticClass: \"tab-editor\",\n attrs: { id: \"editorHtml\" },\n }),\n _c(\"div\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.activeTab === \"js\",\n expression: \"activeTab==='js'\",\n },\n ],\n staticClass: \"tab-editor\",\n attrs: { id: \"editorJs\" },\n }),\n _c(\"div\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.activeTab === \"css\",\n expression: \"activeTab==='css'\",\n },\n ],\n staticClass: \"tab-editor\",\n attrs: { id: \"editorCss\" },\n }),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { staticClass: \"right-preview\", attrs: { md: 24, lg: 12 } },\n [\n _c(\n \"div\",\n {\n staticClass: \"action-bar\",\n style: { \"text-align\": \"left\" },\n },\n [\n _c(\n \"span\",\n {\n staticClass: \"bar-btn\",\n on: { click: _vm.runCode },\n },\n [\n _c(\"i\", { staticClass: \"el-icon-refresh\" }),\n _vm._v(\" 刷新 \"),\n ]\n ),\n _c(\n \"span\",\n {\n staticClass: \"bar-btn\",\n on: { click: _vm.exportFile },\n },\n [\n _c(\"i\", { staticClass: \"el-icon-download\" }),\n _vm._v(\" 导出vue文件 \"),\n ]\n ),\n _c(\n \"span\",\n { ref: \"copyBtn\", staticClass: \"bar-btn copy-btn\" },\n [\n _c(\"i\", { staticClass: \"el-icon-document-copy\" }),\n _vm._v(\" 复制代码 \"),\n ]\n ),\n _c(\n \"span\",\n {\n staticClass: \"bar-btn delete-btn\",\n on: {\n click: function ($event) {\n return _vm.$emit(\"update:visible\", false)\n },\n },\n },\n [\n _c(\"i\", { staticClass: \"el-icon-circle-close\" }),\n _vm._v(\" 关闭 \"),\n ]\n ),\n ]\n ),\n _c(\"iframe\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.isIframeLoaded,\n expression: \"isIframeLoaded\",\n },\n ],\n ref: \"previewPage\",\n staticClass: \"result-wrapper\",\n attrs: { frameborder: \"0\", src: \"preview.html\" },\n on: { load: _vm.iframeLoad },\n }),\n _c(\"div\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: !_vm.isIframeLoaded,\n expression: \"!isIframeLoaded\",\n },\n {\n name: \"loading\",\n rawName: \"v-loading\",\n value: true,\n expression: \"true\",\n },\n ],\n staticClass: \"result-wrapper\",\n }),\n ]\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ]\n ),\n _c(\"resource-dialog\", {\n attrs: {\n visible: _vm.resourceVisible,\n \"origin-resource\": _vm.resources,\n },\n on: {\n \"update:visible\": function ($event) {\n _vm.resourceVisible = $event\n },\n save: _vm.setResource,\n },\n }),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true&": +/*!**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true& ***! + \**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"icon-dialog\" },\n [\n _c(\n \"el-dialog\",\n _vm._g(\n _vm._b(\n {\n attrs: { width: \"980px\", \"modal-append-to-body\": false },\n on: { open: _vm.onOpen, close: _vm.onClose },\n },\n \"el-dialog\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _c(\n \"div\",\n { attrs: { slot: \"title\" }, slot: \"title\" },\n [\n _vm._v(\" 选择图标 \"),\n _c(\"el-input\", {\n style: { width: \"260px\" },\n attrs: {\n size: \"mini\",\n placeholder: \"请输入图标名称\",\n \"prefix-icon\": \"el-icon-search\",\n clearable: \"\",\n },\n model: {\n value: _vm.key,\n callback: function ($$v) {\n _vm.key = $$v\n },\n expression: \"key\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"ul\",\n { staticClass: \"icon-ul\" },\n _vm._l(_vm.iconList, function (icon) {\n return _c(\n \"li\",\n {\n key: icon,\n class: _vm.active === icon ? \"active-item\" : \"\",\n on: {\n click: function ($event) {\n return _vm.onSelect(icon)\n },\n },\n },\n [_c(\"i\", { class: icon }), _c(\"div\", [_vm._v(_vm._s(icon))])]\n )\n }),\n 0\n ),\n ]\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true&": +/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true& ***! + \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"el-drawer\",\n _vm._g(\n _vm._b(\n { on: { opened: _vm.onOpen, close: _vm.onClose } },\n \"el-drawer\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _c(\n \"div\",\n { staticClass: \"action-bar\", style: { \"text-align\": \"left\" } },\n [\n _c(\n \"span\",\n { staticClass: \"bar-btn\", on: { click: _vm.refresh } },\n [_c(\"i\", { staticClass: \"el-icon-refresh\" }), _vm._v(\" 刷新 \")]\n ),\n _c(\n \"span\",\n { ref: \"copyBtn\", staticClass: \"bar-btn copy-json-btn\" },\n [\n _c(\"i\", { staticClass: \"el-icon-document-copy\" }),\n _vm._v(\" 复制JSON \"),\n ]\n ),\n _c(\n \"span\",\n { staticClass: \"bar-btn\", on: { click: _vm.exportJsonFile } },\n [\n _c(\"i\", { staticClass: \"el-icon-download\" }),\n _vm._v(\" 导出JSON文件 \"),\n ]\n ),\n _c(\n \"span\",\n {\n staticClass: \"bar-btn delete-btn\",\n on: {\n click: function ($event) {\n return _vm.$emit(\"update:visible\", false)\n },\n },\n },\n [\n _c(\"i\", { staticClass: \"el-icon-circle-close\" }),\n _vm._v(\" 关闭 \"),\n ]\n ),\n ]\n ),\n _c(\"div\", {\n staticClass: \"json-editor\",\n attrs: { id: \"editorJson\" },\n }),\n ]\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true&": +/*!*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true& ***! + \*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"el-dialog\",\n _vm._g(\n _vm._b(\n {\n attrs: {\n title: \"外部资源引用\",\n width: \"600px\",\n \"close-on-click-modal\": false,\n },\n on: { open: _vm.onOpen, close: _vm.onClose },\n },\n \"el-dialog\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _vm._l(_vm.resources, function (item, index) {\n return _c(\n \"el-input\",\n {\n key: index,\n staticClass: \"url-item\",\n attrs: {\n placeholder: \"请输入 css 或 js 资源路径\",\n \"prefix-icon\": \"el-icon-link\",\n clearable: \"\",\n },\n model: {\n value: _vm.resources[index],\n callback: function ($$v) {\n _vm.$set(_vm.resources, index, $$v)\n },\n expression: \"resources[index]\",\n },\n },\n [\n _c(\"el-button\", {\n attrs: { slot: \"append\", icon: \"el-icon-delete\" },\n on: {\n click: function ($event) {\n return _vm.deleteOne(index)\n },\n },\n slot: \"append\",\n }),\n ],\n 1\n )\n }),\n _c(\n \"el-button-group\",\n { staticClass: \"add-item\" },\n [\n _c(\n \"el-button\",\n {\n attrs: { plain: \"\" },\n on: {\n click: function ($event) {\n return _vm.addOne(\n \"https://lib.baomitu.com/jquery/1.8.3/jquery.min.js\"\n )\n },\n },\n },\n [_vm._v(\" jQuery1.8.3 \")]\n ),\n _c(\n \"el-button\",\n {\n attrs: { plain: \"\" },\n on: {\n click: function ($event) {\n return _vm.addOne(\"https://unpkg.com/http-vue-loader\")\n },\n },\n },\n [_vm._v(\" http-vue-loader \")]\n ),\n _c(\n \"el-button\",\n {\n attrs: { icon: \"el-icon-circle-plus-outline\", plain: \"\" },\n on: {\n click: function ($event) {\n return _vm.addOne(\"\")\n },\n },\n },\n [_vm._v(\" 添加其他 \")]\n ),\n ],\n 1\n ),\n _c(\n \"div\",\n { attrs: { slot: \"footer\" }, slot: \"footer\" },\n [\n _c(\"el-button\", { on: { click: _vm.close } }, [_vm._v(\" 取消 \")]),\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\" },\n on: { click: _vm.handelConfirm },\n },\n [_vm._v(\" 确定 \")]\n ),\n ],\n 1\n ),\n ],\n 2\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true&": +/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true& ***! + \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"right-board\" },\n [\n _c(\n \"el-tabs\",\n {\n staticClass: \"center-tabs\",\n model: {\n value: _vm.currentTab,\n callback: function ($$v) {\n _vm.currentTab = $$v\n },\n expression: \"currentTab\",\n },\n },\n [\n _c(\"el-tab-pane\", { attrs: { label: \"组件属性\", name: \"field\" } }),\n _c(\"el-tab-pane\", { attrs: { label: \"表单属性\", name: \"form\" } }),\n ],\n 1\n ),\n _c(\n \"div\",\n { staticClass: \"field-box\" },\n [\n _c(\n \"a\",\n {\n staticClass: \"document-link\",\n attrs: {\n target: \"_blank\",\n href: _vm.documentLink,\n title: \"查看组件文档\",\n },\n },\n [_c(\"i\", { staticClass: \"el-icon-link\" })]\n ),\n _c(\n \"el-scrollbar\",\n { staticClass: \"right-scrollbar\" },\n [\n _c(\n \"el-form\",\n {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.currentTab === \"field\" && _vm.showField,\n expression: \"currentTab==='field' && showField\",\n },\n ],\n attrs: { size: \"small\", \"label-width\": \"90px\" },\n },\n [\n _vm.activeData.__config__.changeTag\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"组件类型\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n attrs: { placeholder: \"请选择组件类型\" },\n on: { change: _vm.tagChange },\n model: {\n value: _vm.activeData.__config__.tagIcon,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"tagIcon\",\n $$v\n )\n },\n expression: \"activeData.__config__.tagIcon\",\n },\n },\n _vm._l(_vm.tagList, function (group) {\n return _c(\n \"el-option-group\",\n {\n key: group.label,\n attrs: { label: group.label },\n },\n _vm._l(group.options, function (item) {\n return _c(\n \"el-option\",\n {\n key: item.__config__.label,\n attrs: {\n label: item.__config__.label,\n value: item.__config__.tagIcon,\n },\n },\n [\n _c(\"svg-icon\", {\n staticClass: \"node-icon\",\n attrs: {\n \"icon-class\": item.__config__.tagIcon,\n },\n }),\n _c(\"span\", [\n _vm._v(\n \" \" + _vm._s(item.__config__.label)\n ),\n ]),\n ],\n 1\n )\n }),\n 1\n )\n }),\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__vModel__ !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"字段名\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入字段名(v-model)\" },\n model: {\n value: _vm.activeData.__vModel__,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"__vModel__\", $$v)\n },\n expression: \"activeData.__vModel__\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.componentName !== undefined\n ? _c(\"el-form-item\", { attrs: { label: \"组件名\" } }, [\n _vm._v(\n \" \" +\n _vm._s(_vm.activeData.__config__.componentName) +\n \" \"\n ),\n ])\n : _vm._e(),\n _vm.activeData.__config__.label !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"标题\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入标题\" },\n on: { input: _vm.changeRenderKey },\n model: {\n value: _vm.activeData.__config__.label,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"label\",\n $$v\n )\n },\n expression: \"activeData.__config__.label\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.placeholder !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"占位提示\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入占位提示\" },\n on: { input: _vm.changeRenderKey },\n model: {\n value: _vm.activeData.placeholder,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"placeholder\", $$v)\n },\n expression: \"activeData.placeholder\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"start-placeholder\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"开始占位\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入占位提示\" },\n model: {\n value: _vm.activeData[\"start-placeholder\"],\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData,\n \"start-placeholder\",\n $$v\n )\n },\n expression: \"activeData['start-placeholder']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"end-placeholder\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"结束占位\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入占位提示\" },\n model: {\n value: _vm.activeData[\"end-placeholder\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"end-placeholder\", $$v)\n },\n expression: \"activeData['end-placeholder']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.span !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"表单栅格\" } },\n [\n _c(\"el-slider\", {\n attrs: { max: 24, min: 1, marks: { 12: \"\" } },\n on: { change: _vm.spanChange },\n model: {\n value: _vm.activeData.__config__.span,\n callback: function ($$v) {\n _vm.$set(_vm.activeData.__config__, \"span\", $$v)\n },\n expression: \"activeData.__config__.span\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.layout === \"rowFormItem\" &&\n _vm.activeData.gutter !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"栅格间隔\" } },\n [\n _c(\"el-input-number\", {\n attrs: { min: 0, placeholder: \"栅格间隔\" },\n model: {\n value: _vm.activeData.gutter,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"gutter\", $$v)\n },\n expression: \"activeData.gutter\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.layout === \"rowFormItem\" &&\n _vm.activeData.type !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"布局模式\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.activeData.type,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"type\", $$v)\n },\n expression: \"activeData.type\",\n },\n },\n [\n _c(\"el-radio-button\", {\n attrs: { label: \"default\" },\n }),\n _c(\"el-radio-button\", {\n attrs: { label: \"flex\" },\n }),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.justify !== undefined &&\n _vm.activeData.type === \"flex\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"水平排列\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n attrs: { placeholder: \"请选择水平排列\" },\n model: {\n value: _vm.activeData.justify,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"justify\", $$v)\n },\n expression: \"activeData.justify\",\n },\n },\n _vm._l(_vm.justifyOptions, function (item, index) {\n return _c(\"el-option\", {\n key: index,\n attrs: { label: item.label, value: item.value },\n })\n }),\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.align !== undefined &&\n _vm.activeData.type === \"flex\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"垂直排列\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.activeData.align,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"align\", $$v)\n },\n expression: \"activeData.align\",\n },\n },\n [\n _c(\"el-radio-button\", {\n attrs: { label: \"top\" },\n }),\n _c(\"el-radio-button\", {\n attrs: { label: \"middle\" },\n }),\n _c(\"el-radio-button\", {\n attrs: { label: \"bottom\" },\n }),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.labelWidth !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"标签宽度\" } },\n [\n _c(\"el-input\", {\n attrs: {\n type: \"number\",\n placeholder: \"请输入标签宽度\",\n },\n model: {\n value: _vm.activeData.__config__.labelWidth,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"labelWidth\",\n _vm._n($$v)\n )\n },\n expression: \"activeData.__config__.labelWidth\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.style &&\n _vm.activeData.style.width !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"组件宽度\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入组件宽度\",\n clearable: \"\",\n },\n model: {\n value: _vm.activeData.style.width,\n callback: function ($$v) {\n _vm.$set(_vm.activeData.style, \"width\", $$v)\n },\n expression: \"activeData.style.width\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__vModel__ !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"默认值\" } },\n [\n _c(\"el-input\", {\n attrs: {\n value: _vm.setDefaultValue(\n _vm.activeData.__config__.defaultValue\n ),\n placeholder: \"请输入默认值\",\n },\n on: { input: _vm.onDefaultValueInput },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-checkbox-group\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"至少应选\" } },\n [\n _c(\"el-input-number\", {\n attrs: {\n value: _vm.activeData.min,\n min: 0,\n placeholder: \"至少应选\",\n },\n on: {\n input: function ($event) {\n return _vm.$set(\n _vm.activeData,\n \"min\",\n $event ? $event : undefined\n )\n },\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-checkbox-group\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最多可选\" } },\n [\n _c(\"el-input-number\", {\n attrs: {\n value: _vm.activeData.max,\n min: 0,\n placeholder: \"最多可选\",\n },\n on: {\n input: function ($event) {\n return _vm.$set(\n _vm.activeData,\n \"max\",\n $event ? $event : undefined\n )\n },\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__slot__ &&\n _vm.activeData.__slot__.prepend !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"前缀\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入前缀\" },\n model: {\n value: _vm.activeData.__slot__.prepend,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__slot__,\n \"prepend\",\n $$v\n )\n },\n expression: \"activeData.__slot__.prepend\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__slot__ &&\n _vm.activeData.__slot__.append !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"后缀\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入后缀\" },\n model: {\n value: _vm.activeData.__slot__.append,\n callback: function ($$v) {\n _vm.$set(_vm.activeData.__slot__, \"append\", $$v)\n },\n expression: \"activeData.__slot__.append\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"prefix-icon\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"前图标\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: { placeholder: \"请输入前图标名称\" },\n model: {\n value: _vm.activeData[\"prefix-icon\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"prefix-icon\", $$v)\n },\n expression: \"activeData['prefix-icon']\",\n },\n },\n [\n _c(\n \"el-button\",\n {\n attrs: {\n slot: \"append\",\n icon: \"el-icon-thumb\",\n },\n on: {\n click: function ($event) {\n return _vm.openIconsDialog(\"prefix-icon\")\n },\n },\n slot: \"append\",\n },\n [_vm._v(\" 选择 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"suffix-icon\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"后图标\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: { placeholder: \"请输入后图标名称\" },\n model: {\n value: _vm.activeData[\"suffix-icon\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"suffix-icon\", $$v)\n },\n expression: \"activeData['suffix-icon']\",\n },\n },\n [\n _c(\n \"el-button\",\n {\n attrs: {\n slot: \"append\",\n icon: \"el-icon-thumb\",\n },\n on: {\n click: function ($event) {\n return _vm.openIconsDialog(\"suffix-icon\")\n },\n },\n slot: \"append\",\n },\n [_vm._v(\" 选择 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"icon\"] !== undefined &&\n _vm.activeData.__config__.tag === \"el-button\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"按钮图标\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: { placeholder: \"请输入按钮图标名称\" },\n model: {\n value: _vm.activeData[\"icon\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"icon\", $$v)\n },\n expression: \"activeData['icon']\",\n },\n },\n [\n _c(\n \"el-button\",\n {\n attrs: {\n slot: \"append\",\n icon: \"el-icon-thumb\",\n },\n on: {\n click: function ($event) {\n return _vm.openIconsDialog(\"icon\")\n },\n },\n slot: \"append\",\n },\n [_vm._v(\" 选择 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-cascader\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"选项分隔符\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入选项分隔符\" },\n model: {\n value: _vm.activeData.separator,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"separator\", $$v)\n },\n expression: \"activeData.separator\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.autosize !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最小行数\" } },\n [\n _c(\"el-input-number\", {\n attrs: { min: 1, placeholder: \"最小行数\" },\n model: {\n value: _vm.activeData.autosize.minRows,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.autosize,\n \"minRows\",\n $$v\n )\n },\n expression: \"activeData.autosize.minRows\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.autosize !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最大行数\" } },\n [\n _c(\"el-input-number\", {\n attrs: { min: 1, placeholder: \"最大行数\" },\n model: {\n value: _vm.activeData.autosize.maxRows,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.autosize,\n \"maxRows\",\n $$v\n )\n },\n expression: \"activeData.autosize.maxRows\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.isShowMin\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最小值\" } },\n [\n _c(\"el-input-number\", {\n attrs: { placeholder: \"最小值\" },\n model: {\n value: _vm.activeData.min,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"min\", $$v)\n },\n expression: \"activeData.min\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.isShowMax\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最大值\" } },\n [\n _c(\"el-input-number\", {\n attrs: { placeholder: \"最大值\" },\n model: {\n value: _vm.activeData.max,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"max\", $$v)\n },\n expression: \"activeData.max\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.height !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"组件高度\" } },\n [\n _c(\"el-input-number\", {\n attrs: { placeholder: \"高度\" },\n on: { input: _vm.changeRenderKey },\n model: {\n value: _vm.activeData.height,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"height\", $$v)\n },\n expression: \"activeData.height\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.isShowStep\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"步长\" } },\n [\n _c(\"el-input-number\", {\n attrs: { placeholder: \"步数\" },\n model: {\n value: _vm.activeData.step,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"step\", $$v)\n },\n expression: \"activeData.step\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-input-number\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"精度\" } },\n [\n _c(\"el-input-number\", {\n attrs: { min: 0, placeholder: \"精度\" },\n model: {\n value: _vm.activeData.precision,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"precision\", $$v)\n },\n expression: \"activeData.precision\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-input-number\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"按钮位置\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.activeData[\"controls-position\"],\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData,\n \"controls-position\",\n $$v\n )\n },\n expression: \"activeData['controls-position']\",\n },\n },\n [\n _c(\"el-radio-button\", { attrs: { label: \"\" } }, [\n _vm._v(\" 默认 \"),\n ]),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"right\" } },\n [_vm._v(\" 右侧 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.maxlength !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"最多输入\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: { placeholder: \"请输入字符长度\" },\n model: {\n value: _vm.activeData.maxlength,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"maxlength\", $$v)\n },\n expression: \"activeData.maxlength\",\n },\n },\n [\n _c(\"template\", { slot: \"append\" }, [\n _vm._v(\" 个字符 \"),\n ]),\n ],\n 2\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"active-text\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"开启提示\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入开启提示\" },\n model: {\n value: _vm.activeData[\"active-text\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"active-text\", $$v)\n },\n expression: \"activeData['active-text']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"inactive-text\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"关闭提示\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入关闭提示\" },\n model: {\n value: _vm.activeData[\"inactive-text\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"inactive-text\", $$v)\n },\n expression: \"activeData['inactive-text']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"active-value\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"开启值\" } },\n [\n _c(\"el-input\", {\n attrs: {\n value: _vm.setDefaultValue(\n _vm.activeData[\"active-value\"]\n ),\n placeholder: \"请输入开启值\",\n },\n on: {\n input: function ($event) {\n return _vm.onSwitchValueInput(\n $event,\n \"active-value\"\n )\n },\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"inactive-value\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"关闭值\" } },\n [\n _c(\"el-input\", {\n attrs: {\n value: _vm.setDefaultValue(\n _vm.activeData[\"inactive-value\"]\n ),\n placeholder: \"请输入关闭值\",\n },\n on: {\n input: function ($event) {\n return _vm.onSwitchValueInput(\n $event,\n \"inactive-value\"\n )\n },\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.type !== undefined &&\n \"el-date-picker\" === _vm.activeData.__config__.tag\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"时间类型\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n attrs: { placeholder: \"请选择时间类型\" },\n on: { change: _vm.dateTypeChange },\n model: {\n value: _vm.activeData.type,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"type\", $$v)\n },\n expression: \"activeData.type\",\n },\n },\n _vm._l(_vm.dateOptions, function (item, index) {\n return _c(\"el-option\", {\n key: index,\n attrs: { label: item.label, value: item.value },\n })\n }),\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.name !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"文件字段名\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入上传文件字段名\" },\n model: {\n value: _vm.activeData.name,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"name\", $$v)\n },\n expression: \"activeData.name\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.accept !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"文件类型\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n attrs: {\n placeholder: \"请选择文件类型\",\n clearable: \"\",\n },\n model: {\n value: _vm.activeData.accept,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"accept\", $$v)\n },\n expression: \"activeData.accept\",\n },\n },\n [\n _c(\"el-option\", {\n attrs: { label: \"图片\", value: \"image/*\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"视频\", value: \"video/*\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"音频\", value: \"audio/*\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"excel\", value: \".xls,.xlsx\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"word\", value: \".doc,.docx\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"pdf\", value: \".pdf\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"txt\", value: \".txt\" },\n }),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.fileSize !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"文件大小\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: { placeholder: \"请输入文件大小\" },\n model: {\n value: _vm.activeData.__config__.fileSize,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"fileSize\",\n _vm._n($$v)\n )\n },\n expression: \"activeData.__config__.fileSize\",\n },\n },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"66px\" },\n attrs: { slot: \"append\" },\n slot: \"append\",\n model: {\n value: _vm.activeData.__config__.sizeUnit,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"sizeUnit\",\n $$v\n )\n },\n expression:\n \"activeData.__config__.sizeUnit\",\n },\n },\n [\n _c(\"el-option\", {\n attrs: { label: \"KB\", value: \"KB\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"MB\", value: \"MB\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"GB\", value: \"GB\" },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.action !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"上传地址\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入上传地址\",\n clearable: \"\",\n },\n model: {\n value: _vm.activeData.action,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"action\", $$v)\n },\n expression: \"activeData.action\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"list-type\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"列表类型\" } },\n [\n _c(\n \"el-radio-group\",\n {\n attrs: { size: \"small\" },\n model: {\n value: _vm.activeData[\"list-type\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"list-type\", $$v)\n },\n expression: \"activeData['list-type']\",\n },\n },\n [\n _c(\n \"el-radio-button\",\n { attrs: { label: \"text\" } },\n [_vm._v(\" text \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"picture\" } },\n [_vm._v(\" picture \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"picture-card\" } },\n [_vm._v(\" picture-card \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.type !== undefined &&\n _vm.activeData.__config__.tag === \"el-button\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"按钮类型\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n model: {\n value: _vm.activeData.type,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"type\", $$v)\n },\n expression: \"activeData.type\",\n },\n },\n [\n _c(\"el-option\", {\n attrs: { label: \"primary\", value: \"primary\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"success\", value: \"success\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"warning\", value: \"warning\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"danger\", value: \"danger\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"info\", value: \"info\" },\n }),\n _c(\"el-option\", {\n attrs: { label: \"text\", value: \"text\" },\n }),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.buttonText !== undefined\n ? _c(\n \"el-form-item\",\n {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value:\n \"picture-card\" !== _vm.activeData[\"list-type\"],\n expression:\n \"'picture-card' !== activeData['list-type']\",\n },\n ],\n attrs: { label: \"按钮文字\" },\n },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入按钮文字\" },\n model: {\n value: _vm.activeData.__config__.buttonText,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"buttonText\",\n $$v\n )\n },\n expression: \"activeData.__config__.buttonText\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-button\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"按钮文字\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入按钮文字\" },\n model: {\n value: _vm.activeData.__slot__.default,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__slot__,\n \"default\",\n $$v\n )\n },\n expression: \"activeData.__slot__.default\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"range-separator\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"分隔符\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入分隔符\" },\n model: {\n value: _vm.activeData[\"range-separator\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"range-separator\", $$v)\n },\n expression: \"activeData['range-separator']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"picker-options\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"时间段\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入时间段\" },\n model: {\n value:\n _vm.activeData[\"picker-options\"]\n .selectableRange,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData[\"picker-options\"],\n \"selectableRange\",\n $$v\n )\n },\n expression:\n \"activeData['picker-options'].selectableRange\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.format !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"时间格式\" } },\n [\n _c(\"el-input\", {\n attrs: {\n value: _vm.activeData.format,\n placeholder: \"请输入时间格式\",\n },\n on: {\n input: function ($event) {\n return _vm.setTimeValue($event)\n },\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n [\"el-checkbox-group\", \"el-radio-group\", \"el-select\"].indexOf(\n _vm.activeData.__config__.tag\n ) > -1\n ? [\n _c(\"el-divider\", [_vm._v(\"选项\")]),\n _c(\n \"draggable\",\n {\n attrs: {\n list: _vm.activeData.__slot__.options,\n animation: 340,\n group: \"selectItem\",\n handle: \".option-drag\",\n },\n },\n _vm._l(\n _vm.activeData.__slot__.options,\n function (item, index) {\n return _c(\n \"div\",\n { key: index, staticClass: \"select-item\" },\n [\n _c(\n \"div\",\n {\n staticClass:\n \"select-line-icon option-drag\",\n },\n [\n _c(\"i\", {\n staticClass: \"el-icon-s-operation\",\n }),\n ]\n ),\n _c(\"el-input\", {\n attrs: {\n placeholder: \"选项名\",\n size: \"small\",\n },\n model: {\n value: item.label,\n callback: function ($$v) {\n _vm.$set(item, \"label\", $$v)\n },\n expression: \"item.label\",\n },\n }),\n _c(\"el-input\", {\n attrs: {\n placeholder: \"选项值\",\n size: \"small\",\n value: item.value,\n },\n on: {\n input: function ($event) {\n return _vm.setOptionValue(item, $event)\n },\n },\n }),\n _c(\n \"div\",\n {\n staticClass: \"close-btn select-line-icon\",\n on: {\n click: function ($event) {\n return _vm.activeData.__slot__.options.splice(\n index,\n 1\n )\n },\n },\n },\n [\n _c(\"i\", {\n staticClass: \"el-icon-remove-outline\",\n }),\n ]\n ),\n ],\n 1\n )\n }\n ),\n 0\n ),\n _c(\n \"div\",\n { staticStyle: { \"margin-left\": \"20px\" } },\n [\n _c(\n \"el-button\",\n {\n staticStyle: { \"padding-bottom\": \"0\" },\n attrs: {\n icon: \"el-icon-circle-plus-outline\",\n type: \"text\",\n },\n on: { click: _vm.addSelectItem },\n },\n [_vm._v(\" 添加选项 \")]\n ),\n ],\n 1\n ),\n _c(\"el-divider\"),\n ]\n : _vm._e(),\n [\"el-cascader\", \"el-table\"].includes(\n _vm.activeData.__config__.tag\n )\n ? [\n _c(\"el-divider\", [_vm._v(\"选项\")]),\n _vm.activeData.__config__.dataType\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"数据类型\" } },\n [\n _c(\n \"el-radio-group\",\n {\n attrs: { size: \"small\" },\n model: {\n value: _vm.activeData.__config__.dataType,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"dataType\",\n $$v\n )\n },\n expression:\n \"activeData.__config__.dataType\",\n },\n },\n [\n _c(\n \"el-radio-button\",\n { attrs: { label: \"dynamic\" } },\n [_vm._v(\" 动态数据 \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"static\" } },\n [_vm._v(\" 静态数据 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.dataType === \"dynamic\"\n ? [\n _c(\n \"el-form-item\",\n { attrs: { label: \"接口地址\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: {\n title: _vm.activeData.__config__.url,\n placeholder: \"请输入接口地址\",\n clearable: \"\",\n },\n on: {\n blur: function ($event) {\n return _vm.$emit(\n \"fetch-data\",\n _vm.activeData\n )\n },\n },\n model: {\n value: _vm.activeData.__config__.url,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"url\",\n $$v\n )\n },\n expression: \"activeData.__config__.url\",\n },\n },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"85px\" },\n attrs: { slot: \"prepend\" },\n on: {\n change: function ($event) {\n return _vm.$emit(\n \"fetch-data\",\n _vm.activeData\n )\n },\n },\n slot: \"prepend\",\n model: {\n value:\n _vm.activeData.__config__.method,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"method\",\n $$v\n )\n },\n expression:\n \"activeData.__config__.method\",\n },\n },\n [\n _c(\"el-option\", {\n attrs: {\n label: \"get\",\n value: \"get\",\n },\n }),\n _c(\"el-option\", {\n attrs: {\n label: \"post\",\n value: \"post\",\n },\n }),\n _c(\"el-option\", {\n attrs: {\n label: \"put\",\n value: \"put\",\n },\n }),\n _c(\"el-option\", {\n attrs: {\n label: \"delete\",\n value: \"delete\",\n },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"数据位置\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入数据位置\" },\n on: {\n blur: function ($event) {\n return _vm.$emit(\n \"fetch-data\",\n _vm.activeData\n )\n },\n },\n model: {\n value: _vm.activeData.__config__.dataPath,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"dataPath\",\n $$v\n )\n },\n expression:\n \"activeData.__config__.dataPath\",\n },\n }),\n ],\n 1\n ),\n _vm.activeData.props && _vm.activeData.props.props\n ? [\n _c(\n \"el-form-item\",\n { attrs: { label: \"标签键名\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入标签键名\",\n },\n model: {\n value:\n _vm.activeData.props.props.label,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.props.props,\n \"label\",\n $$v\n )\n },\n expression:\n \"activeData.props.props.label\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"值键名\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入值键名\",\n },\n model: {\n value:\n _vm.activeData.props.props.value,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.props.props,\n \"value\",\n $$v\n )\n },\n expression:\n \"activeData.props.props.value\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"子级键名\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入子级键名\",\n },\n model: {\n value:\n _vm.activeData.props.props\n .children,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.props.props,\n \"children\",\n $$v\n )\n },\n expression:\n \"activeData.props.props.children\",\n },\n }),\n ],\n 1\n ),\n ]\n : _vm._e(),\n ]\n : _vm._e(),\n _vm.activeData.__config__.dataType === \"static\"\n ? _c(\"el-tree\", {\n attrs: {\n draggable: \"\",\n data: _vm.activeData.options,\n \"node-key\": \"id\",\n \"expand-on-click-node\": false,\n \"render-content\": _vm.renderContent,\n },\n })\n : _vm._e(),\n _vm.activeData.__config__.dataType === \"static\"\n ? _c(\n \"div\",\n { staticStyle: { \"margin-left\": \"20px\" } },\n [\n _c(\n \"el-button\",\n {\n staticStyle: { \"padding-bottom\": \"0\" },\n attrs: {\n icon: \"el-icon-circle-plus-outline\",\n type: \"text\",\n },\n on: { click: _vm.addTreeItem },\n },\n [_vm._v(\" 添加父级 \")]\n ),\n ],\n 1\n )\n : _vm._e(),\n _c(\"el-divider\"),\n ]\n : _vm._e(),\n _vm.activeData.__config__.optionType !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"选项样式\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.activeData.__config__.optionType,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"optionType\",\n $$v\n )\n },\n expression: \"activeData.__config__.optionType\",\n },\n },\n [\n _c(\n \"el-radio-button\",\n { attrs: { label: \"default\" } },\n [_vm._v(\" 默认 \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"button\" } },\n [_vm._v(\" 按钮 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"active-color\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"开启颜色\" } },\n [\n _c(\"el-color-picker\", {\n model: {\n value: _vm.activeData[\"active-color\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"active-color\", $$v)\n },\n expression: \"activeData['active-color']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"inactive-color\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"关闭颜色\" } },\n [\n _c(\"el-color-picker\", {\n model: {\n value: _vm.activeData[\"inactive-color\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"inactive-color\", $$v)\n },\n expression: \"activeData['inactive-color']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.showLabel !== undefined &&\n _vm.activeData.__config__.labelWidth !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"显示标签\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.__config__.showLabel,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"showLabel\",\n $$v\n )\n },\n expression: \"activeData.__config__.showLabel\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.branding !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"品牌烙印\" } },\n [\n _c(\"el-switch\", {\n on: { input: _vm.changeRenderKey },\n model: {\n value: _vm.activeData.branding,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"branding\", $$v)\n },\n expression: \"activeData.branding\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"allow-half\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"允许半选\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"allow-half\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"allow-half\", $$v)\n },\n expression: \"activeData['allow-half']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"show-text\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"辅助文字\" } },\n [\n _c(\"el-switch\", {\n on: { change: _vm.rateTextChange },\n model: {\n value: _vm.activeData[\"show-text\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"show-text\", $$v)\n },\n expression: \"activeData['show-text']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"show-score\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"显示分数\" } },\n [\n _c(\"el-switch\", {\n on: { change: _vm.rateScoreChange },\n model: {\n value: _vm.activeData[\"show-score\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"show-score\", $$v)\n },\n expression: \"activeData['show-score']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"show-stops\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"显示间断点\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"show-stops\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"show-stops\", $$v)\n },\n expression: \"activeData['show-stops']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.range !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"范围选择\" } },\n [\n _c(\"el-switch\", {\n on: { change: _vm.rangeChange },\n model: {\n value: _vm.activeData.range,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"range\", $$v)\n },\n expression: \"activeData.range\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.border !== undefined &&\n _vm.activeData.__config__.optionType === \"default\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否带边框\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.__config__.border,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"border\",\n $$v\n )\n },\n expression: \"activeData.__config__.border\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-color-picker\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"颜色格式\" } },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100%\" },\n attrs: {\n placeholder: \"请选择颜色格式\",\n clearable: \"\",\n },\n on: { change: _vm.colorFormatChange },\n model: {\n value: _vm.activeData[\"color-format\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"color-format\", $$v)\n },\n expression: \"activeData['color-format']\",\n },\n },\n _vm._l(\n _vm.colorFormatOptions,\n function (item, index) {\n return _c(\"el-option\", {\n key: index,\n attrs: {\n label: item.label,\n value: item.value,\n },\n })\n }\n ),\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.size !== undefined &&\n (_vm.activeData.__config__.optionType === \"button\" ||\n _vm.activeData.__config__.border ||\n _vm.activeData.__config__.tag === \"el-color-picker\" ||\n _vm.activeData.__config__.tag === \"el-button\")\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"组件尺寸\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.activeData.size,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"size\", $$v)\n },\n expression: \"activeData.size\",\n },\n },\n [\n _c(\n \"el-radio-button\",\n { attrs: { label: \"medium\" } },\n [_vm._v(\" 中等 \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"small\" } },\n [_vm._v(\" 较小 \")]\n ),\n _c(\n \"el-radio-button\",\n { attrs: { label: \"mini\" } },\n [_vm._v(\" 迷你 \")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"show-word-limit\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"输入统计\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"show-word-limit\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"show-word-limit\", $$v)\n },\n expression: \"activeData['show-word-limit']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-input-number\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"严格步数\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"step-strictly\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"step-strictly\", $$v)\n },\n expression: \"activeData['step-strictly']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-cascader\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"任选层级\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.props.props.checkStrictly,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.props.props,\n \"checkStrictly\",\n $$v\n )\n },\n expression:\n \"activeData.props.props.checkStrictly\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-cascader\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否多选\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.props.props.multiple,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.props.props,\n \"multiple\",\n $$v\n )\n },\n expression: \"activeData.props.props.multiple\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-cascader\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"展示全路径\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"show-all-levels\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"show-all-levels\", $$v)\n },\n expression: \"activeData['show-all-levels']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-cascader\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"可否筛选\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.filterable,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"filterable\", $$v)\n },\n expression: \"activeData.filterable\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.clearable !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"能否清空\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.clearable,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"clearable\", $$v)\n },\n expression: \"activeData.clearable\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.showTip !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"显示提示\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.__config__.showTip,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"showTip\",\n $$v\n )\n },\n expression: \"activeData.__config__.showTip\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-upload\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"多选文件\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.multiple,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"multiple\", $$v)\n },\n expression: \"activeData.multiple\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData[\"auto-upload\"] !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"自动上传\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData[\"auto-upload\"],\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"auto-upload\", $$v)\n },\n expression: \"activeData['auto-upload']\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.readonly !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否只读\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.readonly,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"readonly\", $$v)\n },\n expression: \"activeData.readonly\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.disabled !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否禁用\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.disabled,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"disabled\", $$v)\n },\n expression: \"activeData.disabled\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-select\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"能否搜索\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.filterable,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"filterable\", $$v)\n },\n expression: \"activeData.filterable\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.tag === \"el-select\"\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否多选\" } },\n [\n _c(\"el-switch\", {\n on: { change: _vm.multipleChange },\n model: {\n value: _vm.activeData.multiple,\n callback: function ($$v) {\n _vm.$set(_vm.activeData, \"multiple\", $$v)\n },\n expression: \"activeData.multiple\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.required !== undefined\n ? _c(\n \"el-form-item\",\n { attrs: { label: \"是否必填\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.activeData.__config__.required,\n callback: function ($$v) {\n _vm.$set(\n _vm.activeData.__config__,\n \"required\",\n $$v\n )\n },\n expression: \"activeData.__config__.required\",\n },\n }),\n ],\n 1\n )\n : _vm._e(),\n _vm.activeData.__config__.layoutTree\n ? [\n _c(\"el-divider\", [_vm._v(\"布局结构树\")]),\n _c(\"el-tree\", {\n attrs: {\n data: [_vm.activeData.__config__],\n props: _vm.layoutTreeProps,\n \"node-key\": \"renderKey\",\n \"default-expand-all\": \"\",\n draggable: \"\",\n },\n scopedSlots: _vm._u(\n [\n {\n key: \"default\",\n fn: function (ref) {\n var node = ref.node\n var data = ref.data\n return _c(\"span\", {}, [\n _c(\n \"span\",\n { staticClass: \"node-label\" },\n [\n _c(\"svg-icon\", {\n staticClass: \"node-icon\",\n attrs: {\n \"icon-class\": data.__config__\n ? data.__config__.tagIcon\n : data.tagIcon,\n },\n }),\n _vm._v(\" \" + _vm._s(node.label) + \" \"),\n ],\n 1\n ),\n ])\n },\n },\n ],\n null,\n false,\n 3924665115\n ),\n }),\n ]\n : _vm._e(),\n Array.isArray(_vm.activeData.__config__.regList)\n ? [\n _c(\"el-divider\", [_vm._v(\"正则校验\")]),\n _vm._l(\n _vm.activeData.__config__.regList,\n function (item, index) {\n return _c(\n \"div\",\n { key: index, staticClass: \"reg-item\" },\n [\n _c(\n \"span\",\n {\n staticClass: \"close-btn\",\n on: {\n click: function ($event) {\n return _vm.activeData.__config__.regList.splice(\n index,\n 1\n )\n },\n },\n },\n [_c(\"i\", { staticClass: \"el-icon-close\" })]\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"表达式\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入正则\" },\n model: {\n value: item.pattern,\n callback: function ($$v) {\n _vm.$set(item, \"pattern\", $$v)\n },\n expression: \"item.pattern\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n {\n staticStyle: { \"margin-bottom\": \"0\" },\n attrs: { label: \"错误提示\" },\n },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入错误提示\" },\n model: {\n value: item.message,\n callback: function ($$v) {\n _vm.$set(item, \"message\", $$v)\n },\n expression: \"item.message\",\n },\n }),\n ],\n 1\n ),\n ],\n 1\n )\n }\n ),\n _c(\n \"div\",\n { staticStyle: { \"margin-left\": \"20px\" } },\n [\n _c(\n \"el-button\",\n {\n attrs: {\n icon: \"el-icon-circle-plus-outline\",\n type: \"text\",\n },\n on: { click: _vm.addReg },\n },\n [_vm._v(\" 添加规则 \")]\n ),\n ],\n 1\n ),\n ]\n : _vm._e(),\n ],\n 2\n ),\n _c(\n \"el-form\",\n {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.currentTab === \"form\",\n expression: \"currentTab === 'form'\",\n },\n ],\n attrs: { size: \"small\", \"label-width\": \"90px\" },\n },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"表单名\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入表单名(ref)\" },\n model: {\n value: _vm.formConf.formRef,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"formRef\", $$v)\n },\n expression: \"formConf.formRef\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"表单模型\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入数据模型\" },\n model: {\n value: _vm.formConf.formModel,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"formModel\", $$v)\n },\n expression: \"formConf.formModel\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"校验模型\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入校验模型\" },\n model: {\n value: _vm.formConf.formRules,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"formRules\", $$v)\n },\n expression: \"formConf.formRules\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"表单尺寸\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.formConf.size,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"size\", $$v)\n },\n expression: \"formConf.size\",\n },\n },\n [\n _c(\n \"el-radio-button\",\n { attrs: { label: \"medium\" } },\n [_vm._v(\" 中等 \")]\n ),\n _c(\"el-radio-button\", { attrs: { label: \"small\" } }, [\n _vm._v(\" 较小 \"),\n ]),\n _c(\"el-radio-button\", { attrs: { label: \"mini\" } }, [\n _vm._v(\" 迷你 \"),\n ]),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"标签对齐\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.formConf.labelPosition,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"labelPosition\", $$v)\n },\n expression: \"formConf.labelPosition\",\n },\n },\n [\n _c(\"el-radio-button\", { attrs: { label: \"left\" } }, [\n _vm._v(\" 左对齐 \"),\n ]),\n _c(\"el-radio-button\", { attrs: { label: \"right\" } }, [\n _vm._v(\" 右对齐 \"),\n ]),\n _c(\"el-radio-button\", { attrs: { label: \"top\" } }, [\n _vm._v(\" 顶部对齐 \"),\n ]),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"标签宽度\" } },\n [\n _c(\"el-input\", {\n attrs: {\n type: \"number\",\n placeholder: \"请输入标签宽度\",\n },\n model: {\n value: _vm.formConf.labelWidth,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"labelWidth\", _vm._n($$v))\n },\n expression: \"formConf.labelWidth\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"栅格间隔\" } },\n [\n _c(\"el-input-number\", {\n attrs: { min: 0, placeholder: \"栅格间隔\" },\n model: {\n value: _vm.formConf.gutter,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"gutter\", $$v)\n },\n expression: \"formConf.gutter\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"禁用表单\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.formConf.disabled,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"disabled\", $$v)\n },\n expression: \"formConf.disabled\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"表单按钮\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.formConf.formBtns,\n callback: function ($$v) {\n _vm.$set(_vm.formConf, \"formBtns\", $$v)\n },\n expression: \"formConf.formBtns\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"显示未选中组件边框\" } },\n [\n _c(\"el-switch\", {\n model: {\n value: _vm.formConf.unFocusedComponentBorder,\n callback: function ($$v) {\n _vm.$set(\n _vm.formConf,\n \"unFocusedComponentBorder\",\n $$v\n )\n },\n expression: \"formConf.unFocusedComponentBorder\",\n },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\"treeNode-dialog\", {\n attrs: { visible: _vm.dialogVisible, title: \"添加选项\" },\n on: {\n \"update:visible\": function ($event) {\n _vm.dialogVisible = $event\n },\n commit: _vm.addNode,\n },\n }),\n _c(\"icons-dialog\", {\n attrs: {\n visible: _vm.iconsVisible,\n current: _vm.activeData[_vm.currentIconModel],\n },\n on: {\n \"update:visible\": function ($event) {\n _vm.iconsVisible = $event\n },\n select: _vm.setIcon,\n },\n }),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true&": +/*!*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true& ***! + \*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"el-dialog\",\n _vm._g(\n _vm._b(\n {\n attrs: {\n \"close-on-click-modal\": false,\n \"modal-append-to-body\": false,\n },\n on: { open: _vm.onOpen, close: _vm.onClose },\n },\n \"el-dialog\",\n _vm.$attrs,\n false\n ),\n _vm.$listeners\n ),\n [\n _c(\n \"el-row\",\n { attrs: { gutter: 0 } },\n [\n _c(\n \"el-form\",\n {\n ref: \"elForm\",\n attrs: {\n model: _vm.formData,\n rules: _vm.rules,\n size: \"small\",\n \"label-width\": \"100px\",\n },\n },\n [\n _c(\n \"el-col\",\n { attrs: { span: 24 } },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"选项名\", prop: \"label\" } },\n [\n _c(\"el-input\", {\n attrs: {\n placeholder: \"请输入选项名\",\n clearable: \"\",\n },\n model: {\n value: _vm.formData.label,\n callback: function ($$v) {\n _vm.$set(_vm.formData, \"label\", $$v)\n },\n expression: \"formData.label\",\n },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { span: 24 } },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"选项值\", prop: \"value\" } },\n [\n _c(\n \"el-input\",\n {\n attrs: {\n placeholder: \"请输入选项值\",\n clearable: \"\",\n },\n model: {\n value: _vm.formData.value,\n callback: function ($$v) {\n _vm.$set(_vm.formData, \"value\", $$v)\n },\n expression: \"formData.value\",\n },\n },\n [\n _c(\n \"el-select\",\n {\n style: { width: \"100px\" },\n attrs: { slot: \"append\" },\n slot: \"append\",\n model: {\n value: _vm.dataType,\n callback: function ($$v) {\n _vm.dataType = $$v\n },\n expression: \"dataType\",\n },\n },\n _vm._l(\n _vm.dataTypeOptions,\n function (item, index) {\n return _c(\"el-option\", {\n key: index,\n attrs: {\n label: item.label,\n value: item.value,\n disabled: item.disabled,\n },\n })\n }\n ),\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"div\",\n { attrs: { slot: \"footer\" }, slot: \"footer\" },\n [\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\" },\n on: { click: _vm.handelConfirm },\n },\n [_vm._v(\" 确定 \")]\n ),\n _c(\"el-button\", { on: { click: _vm.close } }, [_vm._v(\" 取消 \")]),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/TreeNodeDialog.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/clipboard/dist/clipboard.js": +/*!**************************************************!*\ + !*** ./node_modules/clipboard/dist/clipboard.js ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("/*!\n * clipboard.js v2.0.6\n * https://clipboardjs.com/\n * \n * Licensed MIT © Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(true)\n\t\tmodule.exports = factory();\n\telse {}\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 6);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar is = __webpack_require__(3);\nvar delegate = __webpack_require__(4);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar closest = __webpack_require__(5);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n__webpack_require__.r(__webpack_exports__);\n\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(0);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n\n// CONCATENATED MODULE: ./src/clipboard-action.js\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n\n\n/**\n * Inner class which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n */\n\nvar clipboard_action_ClipboardAction = function () {\n /**\n * @param {Object} options\n */\n function ClipboardAction(options) {\n _classCallCheck(this, ClipboardAction);\n\n this.resolveOptions(options);\n this.initSelection();\n }\n\n /**\n * Defines base properties passed from constructor.\n * @param {Object} options\n */\n\n\n _createClass(ClipboardAction, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = options.action;\n this.container = options.container;\n this.emitter = options.emitter;\n this.target = options.target;\n this.text = options.text;\n this.trigger = options.trigger;\n\n this.selectedText = '';\n }\n\n /**\n * Decides which selection strategy is going to be applied based\n * on the existence of `text` and `target` properties.\n */\n\n }, {\n key: 'initSelection',\n value: function initSelection() {\n if (this.text) {\n this.selectFake();\n } else if (this.target) {\n this.selectTarget();\n }\n }\n\n /**\n * Creates a fake textarea element, sets its value from `text` property,\n * and makes a selection on it.\n */\n\n }, {\n key: 'selectFake',\n value: function selectFake() {\n var _this = this;\n\n var isRTL = document.documentElement.getAttribute('dir') == 'rtl';\n\n this.removeFake();\n\n this.fakeHandlerCallback = function () {\n return _this.removeFake();\n };\n this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;\n\n this.fakeElem = document.createElement('textarea');\n // Prevent zooming on iOS\n this.fakeElem.style.fontSize = '12pt';\n // Reset box model\n this.fakeElem.style.border = '0';\n this.fakeElem.style.padding = '0';\n this.fakeElem.style.margin = '0';\n // Move element out of screen horizontally\n this.fakeElem.style.position = 'absolute';\n this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';\n // Move element to the same position vertically\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n this.fakeElem.style.top = yPosition + 'px';\n\n this.fakeElem.setAttribute('readonly', '');\n this.fakeElem.value = this.text;\n\n this.container.appendChild(this.fakeElem);\n\n this.selectedText = select_default()(this.fakeElem);\n this.copyText();\n }\n\n /**\n * Only removes the fake element after another click event, that way\n * a user can hit `Ctrl+C` to copy because selection still exists.\n */\n\n }, {\n key: 'removeFake',\n value: function removeFake() {\n if (this.fakeHandler) {\n this.container.removeEventListener('click', this.fakeHandlerCallback);\n this.fakeHandler = null;\n this.fakeHandlerCallback = null;\n }\n\n if (this.fakeElem) {\n this.container.removeChild(this.fakeElem);\n this.fakeElem = null;\n }\n }\n\n /**\n * Selects the content from element passed on `target` property.\n */\n\n }, {\n key: 'selectTarget',\n value: function selectTarget() {\n this.selectedText = select_default()(this.target);\n this.copyText();\n }\n\n /**\n * Executes the copy operation based on the current selection.\n */\n\n }, {\n key: 'copyText',\n value: function copyText() {\n var succeeded = void 0;\n\n try {\n succeeded = document.execCommand(this.action);\n } catch (err) {\n succeeded = false;\n }\n\n this.handleResult(succeeded);\n }\n\n /**\n * Fires an event based on the copy operation result.\n * @param {Boolean} succeeded\n */\n\n }, {\n key: 'handleResult',\n value: function handleResult(succeeded) {\n this.emitter.emit(succeeded ? 'success' : 'error', {\n action: this.action,\n text: this.selectedText,\n trigger: this.trigger,\n clearSelection: this.clearSelection.bind(this)\n });\n }\n\n /**\n * Moves focus away from `target` and back to the trigger, removes current selection.\n */\n\n }, {\n key: 'clearSelection',\n value: function clearSelection() {\n if (this.trigger) {\n this.trigger.focus();\n }\n document.activeElement.blur();\n window.getSelection().removeAllRanges();\n }\n\n /**\n * Sets the `action` to be performed which can be either 'copy' or 'cut'.\n * @param {String} action\n */\n\n }, {\n key: 'destroy',\n\n\n /**\n * Destroy lifecycle.\n */\n value: function destroy() {\n this.removeFake();\n }\n }, {\n key: 'action',\n set: function set() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';\n\n this._action = action;\n\n if (this._action !== 'copy' && this._action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n }\n }\n\n /**\n * Gets the `action` property.\n * @return {String}\n */\n ,\n get: function get() {\n return this._action;\n }\n\n /**\n * Sets the `target` property using an element\n * that will be have its content copied.\n * @param {Element} target\n */\n\n }, {\n key: 'target',\n set: function set(target) {\n if (target !== undefined) {\n if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {\n if (this.action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n\n this._target = target;\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n }\n }\n\n /**\n * Gets the `target` property.\n * @return {String|HTMLElement}\n */\n ,\n get: function get() {\n return this._target;\n }\n }]);\n\n return ClipboardAction;\n}();\n\n/* harmony default export */ var clipboard_action = (clipboard_action_ClipboardAction);\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(1);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(2);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n\n// CONCATENATED MODULE: ./src/clipboard.js\nvar clipboard_typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar clipboard_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction clipboard_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n\n\n\n\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\nvar clipboard_Clipboard = function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n clipboard_classCallCheck(this, Clipboard);\n\n var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));\n\n _this.resolveOptions(options);\n _this.listenClick(trigger);\n return _this;\n }\n\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n clipboard_createClass(Clipboard, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: 'listenClick',\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: 'onClick',\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n\n if (this.clipboardAction) {\n this.clipboardAction = null;\n }\n\n this.clipboardAction = new clipboard_action({\n action: this.action(trigger),\n target: this.target(trigger),\n text: this.text(trigger),\n container: this.container,\n trigger: trigger,\n emitter: this\n });\n }\n\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultAction',\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultTarget',\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: 'defaultText',\n\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: 'destroy',\n value: function destroy() {\n this.listener.destroy();\n\n if (this.clipboardAction) {\n this.clipboardAction.destroy();\n this.clipboardAction = null;\n }\n }\n }], [{\n key: 'isSupported',\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n\n return support;\n }\n }]);\n\n return Clipboard;\n}(tiny_emitter_default.a);\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\n\nfunction getAttributeValue(suffix, element) {\n var attribute = 'data-clipboard-' + suffix;\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n\n/* harmony default export */ var clipboard = __webpack_exports__[\"default\"] = (clipboard_Clipboard);\n\n/***/ })\n/******/ ])[\"default\"];\n});\n\n//# sourceURL=webpack:///./node_modules/clipboard/dist/clipboard.js?"); + +/***/ }), + +/***/ "./node_modules/core-js/modules/es.string.ends-with.js": +/*!*************************************************************!*\ + !*** ./node_modules/core-js/modules/es.string.ends-with.js ***! + \*************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\nvar $ = __webpack_require__(/*! ../internals/export */ \"./node_modules/core-js/internals/export.js\");\nvar uncurryThis = __webpack_require__(/*! ../internals/function-uncurry-this */ \"./node_modules/core-js/internals/function-uncurry-this.js\");\nvar getOwnPropertyDescriptor = __webpack_require__(/*! ../internals/object-get-own-property-descriptor */ \"./node_modules/core-js/internals/object-get-own-property-descriptor.js\").f;\nvar toLength = __webpack_require__(/*! ../internals/to-length */ \"./node_modules/core-js/internals/to-length.js\");\nvar toString = __webpack_require__(/*! ../internals/to-string */ \"./node_modules/core-js/internals/to-string.js\");\nvar notARegExp = __webpack_require__(/*! ../internals/not-a-regexp */ \"./node_modules/core-js/internals/not-a-regexp.js\");\nvar requireObjectCoercible = __webpack_require__(/*! ../internals/require-object-coercible */ \"./node_modules/core-js/internals/require-object-coercible.js\");\nvar correctIsRegExpLogic = __webpack_require__(/*! ../internals/correct-is-regexp-logic */ \"./node_modules/core-js/internals/correct-is-regexp-logic.js\");\nvar IS_PURE = __webpack_require__(/*! ../internals/is-pure */ \"./node_modules/core-js/internals/is-pure.js\");\n\n// eslint-disable-next-line es/no-string-prototype-endswith -- safe\nvar un$EndsWith = uncurryThis(''.endsWith);\nvar slice = uncurryThis(''.slice);\nvar min = Math.min;\n\nvar CORRECT_IS_REGEXP_LOGIC = correctIsRegExpLogic('endsWith');\n// https://github.com/zloirock/core-js/pull/702\nvar MDN_POLYFILL_BUG = !IS_PURE && !CORRECT_IS_REGEXP_LOGIC && !!function () {\n var descriptor = getOwnPropertyDescriptor(String.prototype, 'endsWith');\n return descriptor && !descriptor.writable;\n}();\n\n// `String.prototype.endsWith` method\n// https://tc39.es/ecma262/#sec-string.prototype.endswith\n$({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {\n endsWith: function endsWith(searchString /* , endPosition = @length */) {\n var that = toString(requireObjectCoercible(this));\n notARegExp(searchString);\n var endPosition = arguments.length > 1 ? arguments[1] : undefined;\n var len = that.length;\n var end = endPosition === undefined ? len : min(toLength(endPosition), len);\n var search = toString(searchString);\n return un$EndsWith\n ? un$EndsWith(that, search, end)\n : slice(that, end - search.length, end) === search;\n }\n});\n\n\n//# sourceURL=webpack:///./node_modules/core-js/modules/es.string.ends-with.js?"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss&": +/*!***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss& ***! + \***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".container {\\n position: relative;\\n width: 100%;\\n height: 100%;\\n}\\n.components-list {\\n padding: 8px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n height: 100%;\\n}\\n.components-list .components-item {\\n display: inline-block;\\n width: 48%;\\n margin: 1%;\\n -webkit-transition: -webkit-transform 0ms !important;\\n transition: -webkit-transform 0ms !important;\\n transition: transform 0ms !important;\\n transition: transform 0ms, -webkit-transform 0ms !important;\\n}\\n.components-draggable {\\n padding-bottom: 20px;\\n}\\n.components-title {\\n font-size: 14px;\\n color: #222;\\n margin: 6px 2px;\\n}\\n.components-title .svg-icon {\\n color: #666;\\n font-size: 18px;\\n}\\n.components-body {\\n padding: 8px 10px;\\n background: #f6f7ff;\\n font-size: 12px;\\n cursor: move;\\n border: 1px dashed #f6f7ff;\\n border-radius: 3px;\\n}\\n.components-body .svg-icon {\\n color: #777;\\n font-size: 15px;\\n}\\n.components-body:hover {\\n border: 1px dashed #787be8;\\n color: #787be8;\\n}\\n.components-body:hover .svg-icon {\\n color: #787be8;\\n}\\n.left-board {\\n width: 260px;\\n position: absolute;\\n left: 0;\\n top: 0;\\n height: 100vh;\\n}\\n.left-scrollbar {\\n height: calc(100vh - 42px);\\n overflow: hidden;\\n}\\n.center-scrollbar {\\n height: calc(100vh - 42px);\\n overflow: hidden;\\n border-left: 1px solid #f1e8e8;\\n border-right: 1px solid #f1e8e8;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.center-board {\\n height: 100vh;\\n width: auto;\\n margin: 0 350px 0 260px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.empty-info {\\n position: absolute;\\n top: 46%;\\n left: 0;\\n right: 0;\\n text-align: center;\\n font-size: 18px;\\n color: #ccb1ea;\\n letter-spacing: 4px;\\n}\\n.action-bar {\\n position: relative;\\n height: 42px;\\n text-align: right;\\n padding: 0 15px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n border: 1px solid #f1e8e8;\\n border-top: none;\\n border-left: none;\\n}\\n.action-bar .delete-btn {\\n color: #F56C6C;\\n}\\n.logo-wrapper {\\n position: relative;\\n height: 42px;\\n background: #fff;\\n border-bottom: 1px solid #f1e8e8;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.logo {\\n position: absolute;\\n left: 12px;\\n top: 6px;\\n line-height: 30px;\\n color: #00afff;\\n font-weight: 600;\\n font-size: 17px;\\n white-space: nowrap;\\n}\\n.logo > img {\\n width: 30px;\\n height: 30px;\\n vertical-align: top;\\n}\\n.logo .github {\\n display: inline-block;\\n vertical-align: sub;\\n margin-left: 15px;\\n}\\n.logo .github > img {\\n height: 22px;\\n}\\n.center-board-row {\\n padding: 12px 12px 15px 12px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.center-board-row > .el-form {\\n height: calc(100vh - 69px);\\n}\\n.drawing-board {\\n height: 100%;\\n position: relative;\\n}\\n.drawing-board .components-body {\\n padding: 0;\\n margin: 0;\\n font-size: 0;\\n}\\n.drawing-board .sortable-ghost {\\n position: relative;\\n display: block;\\n overflow: hidden;\\n}\\n.drawing-board .sortable-ghost::before {\\n content: \\\" \\\";\\n position: absolute;\\n left: 0;\\n right: 0;\\n top: 0;\\n height: 3px;\\n background: #5959df;\\n z-index: 2;\\n}\\n.drawing-board .components-item.sortable-ghost {\\n width: 100%;\\n height: 60px;\\n background-color: #f6f7ff;\\n}\\n.drawing-board .active-from-item > .el-form-item {\\n background: #f6f7ff;\\n border-radius: 6px;\\n}\\n.drawing-board .active-from-item > .drawing-item-copy, .drawing-board .active-from-item > .drawing-item-delete {\\n display: initial;\\n}\\n.drawing-board .active-from-item > .component-name {\\n color: #409EFF;\\n}\\n.drawing-board .el-form-item {\\n margin-bottom: 15px;\\n}\\n.drawing-item {\\n position: relative;\\n cursor: move;\\n}\\n.drawing-item.unfocus-bordered:not(.active-from-item) > div:first-child {\\n border: 1px dashed #ccc;\\n}\\n.drawing-item .el-form-item {\\n padding: 12px 10px;\\n}\\n.drawing-row-item {\\n position: relative;\\n cursor: move;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n border: 1px dashed #ccc;\\n border-radius: 3px;\\n padding: 0 2px;\\n margin-bottom: 15px;\\n}\\n.drawing-row-item .drawing-row-item {\\n margin-bottom: 2px;\\n}\\n.drawing-row-item .el-col {\\n margin-top: 22px;\\n}\\n.drawing-row-item .el-form-item {\\n margin-bottom: 0;\\n}\\n.drawing-row-item .drag-wrapper {\\n min-height: 80px;\\n}\\n.drawing-row-item.active-from-item {\\n border: 1px dashed #409EFF;\\n}\\n.drawing-row-item .component-name {\\n position: absolute;\\n top: 0;\\n left: 0;\\n font-size: 12px;\\n color: #bbb;\\n display: inline-block;\\n padding: 0 6px;\\n}\\n.drawing-item:hover > .el-form-item, .drawing-row-item:hover > .el-form-item {\\n background: #f6f7ff;\\n border-radius: 6px;\\n}\\n.drawing-item:hover > .drawing-item-copy, .drawing-item:hover > .drawing-item-delete, .drawing-row-item:hover > .drawing-item-copy, .drawing-row-item:hover > .drawing-item-delete {\\n display: initial;\\n}\\n.drawing-item > .drawing-item-copy, .drawing-item > .drawing-item-delete, .drawing-row-item > .drawing-item-copy, .drawing-row-item > .drawing-item-delete {\\n display: none;\\n position: absolute;\\n top: -10px;\\n width: 22px;\\n height: 22px;\\n line-height: 22px;\\n text-align: center;\\n border-radius: 50%;\\n font-size: 12px;\\n border: 1px solid;\\n cursor: pointer;\\n z-index: 1;\\n}\\n.drawing-item > .drawing-item-copy, .drawing-row-item > .drawing-item-copy {\\n right: 56px;\\n border-color: #409EFF;\\n color: #409EFF;\\n background: #fff;\\n}\\n.drawing-item > .drawing-item-copy:hover, .drawing-row-item > .drawing-item-copy:hover {\\n background: #409EFF;\\n color: #fff;\\n}\\n.drawing-item > .drawing-item-delete, .drawing-row-item > .drawing-item-delete {\\n right: 24px;\\n border-color: #F56C6C;\\n color: #F56C6C;\\n background: #fff;\\n}\\n.drawing-item > .drawing-item-delete:hover, .drawing-row-item > .drawing-item-delete:hover {\\n background: #F56C6C;\\n color: #fff;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".tab-editor[data-v-35027ca3] {\\n position: absolute;\\n top: 33px;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n font-size: 14px;\\n}\\n.left-editor[data-v-35027ca3] {\\n position: relative;\\n height: 100%;\\n background: #1e1e1e;\\n overflow: hidden;\\n}\\n.setting[data-v-35027ca3] {\\n position: absolute;\\n right: 15px;\\n top: 3px;\\n color: #a9f122;\\n font-size: 18px;\\n cursor: pointer;\\n z-index: 1;\\n}\\n.right-preview[data-v-35027ca3] {\\n height: 100%;\\n}\\n.right-preview .result-wrapper[data-v-35027ca3] {\\n height: calc(100vh - 33px);\\n width: 100%;\\n overflow: auto;\\n padding: 12px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.action-bar[data-v-35027ca3] {\\n height: 33px;\\n background: #f2fafb;\\n padding: 0 15px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.action-bar .bar-btn[data-v-35027ca3] {\\n display: inline-block;\\n padding: 0 6px;\\n line-height: 32px;\\n color: #8285f5;\\n cursor: pointer;\\n font-size: 14px;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none;\\n}\\n.action-bar .bar-btn i[data-v-35027ca3] {\\n font-size: 20px;\\n}\\n.action-bar .bar-btn[data-v-35027ca3]:hover {\\n color: #4348d4;\\n}\\n.action-bar .bar-btn + .bar-btn[data-v-35027ca3] {\\n margin-left: 8px;\\n}\\n.action-bar .delete-btn[data-v-35027ca3] {\\n color: #f56c6c;\\n}\\n.action-bar .delete-btn[data-v-35027ca3]:hover {\\n color: #ea0b30;\\n}\\n[data-v-35027ca3] .el-drawer__header {\\n display: none;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true&": +/*!******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true& ***! + \******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".icon-ul[data-v-9733a8b8] {\\n margin: 0;\\n padding: 0;\\n font-size: 0;\\n}\\n.icon-ul li[data-v-9733a8b8] {\\n list-style-type: none;\\n text-align: center;\\n font-size: 14px;\\n display: inline-block;\\n width: 16.66%;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n height: 108px;\\n padding: 15px 6px 6px 6px;\\n cursor: pointer;\\n overflow: hidden;\\n}\\n.icon-ul li[data-v-9733a8b8]:hover {\\n background: #f2f2f2;\\n}\\n.icon-ul li.active-item[data-v-9733a8b8] {\\n background: #e1f3fb;\\n color: #7a6df0;\\n}\\n.icon-ul li > i[data-v-9733a8b8] {\\n font-size: 30px;\\n line-height: 50px;\\n}\\n.icon-dialog[data-v-9733a8b8] .el-dialog {\\n border-radius: 8px;\\n margin-bottom: 0;\\n margin-top: 4vh !important;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n -webkit-box-orient: vertical;\\n -webkit-box-direction: normal;\\n -ms-flex-direction: column;\\n flex-direction: column;\\n max-height: 92vh;\\n overflow: hidden;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.icon-dialog[data-v-9733a8b8] .el-dialog .el-dialog__header {\\n padding-top: 14px;\\n}\\n.icon-dialog[data-v-9733a8b8] .el-dialog .el-dialog__body {\\n margin: 0 20px 20px 20px;\\n padding: 0;\\n overflow: auto;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \"[data-v-17550072] .el-drawer__header {\\n display: none;\\n}\\n.action-bar[data-v-17550072] {\\n height: 33px;\\n background: #f2fafb;\\n padding: 0 15px;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.action-bar .bar-btn[data-v-17550072] {\\n display: inline-block;\\n padding: 0 6px;\\n line-height: 32px;\\n color: #8285f5;\\n cursor: pointer;\\n font-size: 14px;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none;\\n}\\n.action-bar .bar-btn i[data-v-17550072] {\\n font-size: 20px;\\n}\\n.action-bar .bar-btn[data-v-17550072]:hover {\\n color: #4348d4;\\n}\\n.action-bar .bar-btn + .bar-btn[data-v-17550072] {\\n margin-left: 8px;\\n}\\n.action-bar .delete-btn[data-v-17550072] {\\n color: #f56c6c;\\n}\\n.action-bar .delete-btn[data-v-17550072]:hover {\\n color: #ea0b30;\\n}\\n.json-editor[data-v-17550072] {\\n height: calc(100vh - 33px);\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true&": +/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true& ***! + \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".add-item[data-v-1b905544] {\\n margin-top: 8px;\\n}\\n.url-item[data-v-1b905544] {\\n margin-bottom: 12px;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".right-board[data-v-377e0596] {\\n width: 350px;\\n position: absolute;\\n right: 0;\\n top: 0;\\n padding-top: 3px;\\n}\\n.right-board .field-box[data-v-377e0596] {\\n position: relative;\\n height: calc(100vh - 42px);\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n overflow: hidden;\\n}\\n.right-board .el-scrollbar[data-v-377e0596] {\\n height: 100%;\\n}\\n.select-item[data-v-377e0596] {\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n border: 1px dashed #fff;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n}\\n.select-item .close-btn[data-v-377e0596] {\\n cursor: pointer;\\n color: #f56c6c;\\n}\\n.select-item .el-input + .el-input[data-v-377e0596] {\\n margin-left: 4px;\\n}\\n.select-item + .select-item[data-v-377e0596] {\\n margin-top: 4px;\\n}\\n.select-item.sortable-chosen[data-v-377e0596] {\\n border: 1px dashed #409eff;\\n}\\n.select-line-icon[data-v-377e0596] {\\n line-height: 32px;\\n font-size: 22px;\\n padding: 0 4px;\\n color: #777;\\n}\\n.option-drag[data-v-377e0596] {\\n cursor: move;\\n}\\n.time-range .el-date-editor[data-v-377e0596] {\\n width: 227px;\\n}\\n.time-range[data-v-377e0596] .el-icon-time {\\n display: none;\\n}\\n.document-link[data-v-377e0596] {\\n position: absolute;\\n display: block;\\n width: 26px;\\n height: 26px;\\n top: 0;\\n left: 0;\\n cursor: pointer;\\n background: #409eff;\\n z-index: 1;\\n border-radius: 0 0 6px 0;\\n text-align: center;\\n line-height: 26px;\\n color: #fff;\\n font-size: 18px;\\n}\\n.node-label[data-v-377e0596] {\\n font-size: 14px;\\n}\\n.node-icon[data-v-377e0596] {\\n color: #bebfc3;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/file-saver/dist/FileSaver.min.js": +/*!*******************************************************!*\ + !*** ./node_modules/file-saver/dist/FileSaver.min.js ***! + \*******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(a,b){if(true)!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (b),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else {}})(this,function(){\"use strict\";function b(a,b){return\"undefined\"==typeof b?b={autoBom:!1}:\"object\"!=typeof b&&(console.warn(\"Deprecated: Expected third argument to be a object\"),b={autoBom:!b}),b.autoBom&&/^\\s*(?:text\\/\\S*|application\\/xml|\\S*\\/\\S*\\+xml)\\s*;.*charset\\s*=\\s*utf-8/i.test(a.type)?new Blob([\"\\uFEFF\",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open(\"GET\",a),d.responseType=\"blob\",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error(\"could not download file\")},d.send()}function d(a){var b=new XMLHttpRequest;b.open(\"HEAD\",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent(\"click\"))}catch(c){var b=document.createEvent(\"MouseEvents\");b.initMouseEvent(\"click\",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f=\"object\"==typeof window&&window.window===window?window:\"object\"==typeof self&&self.self===self?self:\"object\"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||(\"object\"!=typeof window||window!==f?function(){}:\"download\"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement(\"a\");g=g||b.name||\"download\",j.download=g,j.rel=\"noopener\",\"string\"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target=\"_blank\")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:\"msSaveOrOpenBlob\"in navigator?function(f,g,h){if(g=g||f.name||\"download\",\"string\"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement(\"a\");i.href=f,i.target=\"_blank\",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open(\"\",\"_blank\"),g&&(g.document.title=g.document.body.innerText=\"downloading...\"),\"string\"==typeof b)return c(b,d,e);var h=\"application/octet-stream\"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\\/[\\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&\"undefined\"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,\"data:attachment/file;\"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g, true&&(module.exports=g)});\n\n//# sourceMappingURL=FileSaver.min.js.map\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))\n\n//# sourceURL=webpack:///./node_modules/file-saver/dist/FileSaver.min.js?"); + +/***/ }), + +/***/ "./node_modules/util/node_modules/inherits/inherits_browser.js": +/*!*********************************************************************!*\ + !*** ./node_modules/util/node_modules/inherits/inherits_browser.js ***! + \*********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("if (typeof Object.create === 'function') {\n // implementation from standard node.js 'util' module\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n };\n} else {\n // old school shim for old browsers\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n var TempCtor = function () {}\n TempCtor.prototype = superCtor.prototype\n ctor.prototype = new TempCtor()\n ctor.prototype.constructor = ctor\n }\n}\n\n\n//# sourceURL=webpack:///./node_modules/util/node_modules/inherits/inherits_browser.js?"); + +/***/ }), + +/***/ "./node_modules/util/support/isBufferBrowser.js": +/*!******************************************************!*\ + !*** ./node_modules/util/support/isBufferBrowser.js ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("module.exports = function isBuffer(arg) {\n return arg && typeof arg === 'object'\n && typeof arg.copy === 'function'\n && typeof arg.fill === 'function'\n && typeof arg.readUInt8 === 'function';\n}\n\n//# sourceURL=webpack:///./node_modules/util/support/isBufferBrowser.js?"); + +/***/ }), + +/***/ "./node_modules/util/util.js": +/*!***********************************!*\ + !*** ./node_modules/util/util.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||\n function getOwnPropertyDescriptors(obj) {\n var keys = Object.keys(obj);\n var descriptors = {};\n for (var i = 0; i < keys.length; i++) {\n descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);\n }\n return descriptors;\n };\n\nvar formatRegExp = /%[sdj%]/g;\nexports.format = function(f) {\n if (!isString(f)) {\n var objects = [];\n for (var i = 0; i < arguments.length; i++) {\n objects.push(inspect(arguments[i]));\n }\n return objects.join(' ');\n }\n\n var i = 1;\n var args = arguments;\n var len = args.length;\n var str = String(f).replace(formatRegExp, function(x) {\n if (x === '%%') return '%';\n if (i >= len) return x;\n switch (x) {\n case '%s': return String(args[i++]);\n case '%d': return Number(args[i++]);\n case '%j':\n try {\n return JSON.stringify(args[i++]);\n } catch (_) {\n return '[Circular]';\n }\n default:\n return x;\n }\n });\n for (var x = args[i]; i < len; x = args[++i]) {\n if (isNull(x) || !isObject(x)) {\n str += ' ' + x;\n } else {\n str += ' ' + inspect(x);\n }\n }\n return str;\n};\n\n\n// Mark that a method should not be used.\n// Returns a modified function which warns once by default.\n// If --no-deprecation is set, then it is a no-op.\nexports.deprecate = function(fn, msg) {\n if (typeof process !== 'undefined' && process.noDeprecation === true) {\n return fn;\n }\n\n // Allow for deprecating things in the process of starting up.\n if (typeof process === 'undefined') {\n return function() {\n return exports.deprecate(fn, msg).apply(this, arguments);\n };\n }\n\n var warned = false;\n function deprecated() {\n if (!warned) {\n if (process.throwDeprecation) {\n throw new Error(msg);\n } else if (process.traceDeprecation) {\n console.trace(msg);\n } else {\n console.error(msg);\n }\n warned = true;\n }\n return fn.apply(this, arguments);\n }\n\n return deprecated;\n};\n\n\nvar debugs = {};\nvar debugEnviron;\nexports.debuglog = function(set) {\n if (isUndefined(debugEnviron))\n debugEnviron = Object({\"NODE_ENV\":\"development\",\"VUE_APP_BASE_API\":\"http://127.0.0.1:48080\",\"VUE_APP_APP_NAME\":\"/admin-ui/\",\"BASE_URL\":\"/admin-ui/\"}).NODE_DEBUG || '';\n set = set.toUpperCase();\n if (!debugs[set]) {\n if (new RegExp('\\\\b' + set + '\\\\b', 'i').test(debugEnviron)) {\n var pid = process.pid;\n debugs[set] = function() {\n var msg = exports.format.apply(exports, arguments);\n console.error('%s %d: %s', set, pid, msg);\n };\n } else {\n debugs[set] = function() {};\n }\n }\n return debugs[set];\n};\n\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Object} opts Optional options object that alters the output.\n */\n/* legacy: obj, showHidden, depth, colors*/\nfunction inspect(obj, opts) {\n // default options\n var ctx = {\n seen: [],\n stylize: stylizeNoColor\n };\n // legacy...\n if (arguments.length >= 3) ctx.depth = arguments[2];\n if (arguments.length >= 4) ctx.colors = arguments[3];\n if (isBoolean(opts)) {\n // legacy...\n ctx.showHidden = opts;\n } else if (opts) {\n // got an \"options\" object\n exports._extend(ctx, opts);\n }\n // set default options\n if (isUndefined(ctx.showHidden)) ctx.showHidden = false;\n if (isUndefined(ctx.depth)) ctx.depth = 2;\n if (isUndefined(ctx.colors)) ctx.colors = false;\n if (isUndefined(ctx.customInspect)) ctx.customInspect = true;\n if (ctx.colors) ctx.stylize = stylizeWithColor;\n return formatValue(ctx, obj, ctx.depth);\n}\nexports.inspect = inspect;\n\n\n// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics\ninspect.colors = {\n 'bold' : [1, 22],\n 'italic' : [3, 23],\n 'underline' : [4, 24],\n 'inverse' : [7, 27],\n 'white' : [37, 39],\n 'grey' : [90, 39],\n 'black' : [30, 39],\n 'blue' : [34, 39],\n 'cyan' : [36, 39],\n 'green' : [32, 39],\n 'magenta' : [35, 39],\n 'red' : [31, 39],\n 'yellow' : [33, 39]\n};\n\n// Don't use 'blue' not visible on cmd.exe\ninspect.styles = {\n 'special': 'cyan',\n 'number': 'yellow',\n 'boolean': 'yellow',\n 'undefined': 'grey',\n 'null': 'bold',\n 'string': 'green',\n 'date': 'magenta',\n // \"name\": intentionally not styling\n 'regexp': 'red'\n};\n\n\nfunction stylizeWithColor(str, styleType) {\n var style = inspect.styles[styleType];\n\n if (style) {\n return '\\u001b[' + inspect.colors[style][0] + 'm' + str +\n '\\u001b[' + inspect.colors[style][1] + 'm';\n } else {\n return str;\n }\n}\n\n\nfunction stylizeNoColor(str, styleType) {\n return str;\n}\n\n\nfunction arrayToHash(array) {\n var hash = {};\n\n array.forEach(function(val, idx) {\n hash[val] = true;\n });\n\n return hash;\n}\n\n\nfunction formatValue(ctx, value, recurseTimes) {\n // Provide a hook for user-specified inspect functions.\n // Check that value is an object with an inspect function on it\n if (ctx.customInspect &&\n value &&\n isFunction(value.inspect) &&\n // Filter out the util module, it's inspect function is special\n value.inspect !== exports.inspect &&\n // Also filter out any prototype objects using the circular check.\n !(value.constructor && value.constructor.prototype === value)) {\n var ret = value.inspect(recurseTimes, ctx);\n if (!isString(ret)) {\n ret = formatValue(ctx, ret, recurseTimes);\n }\n return ret;\n }\n\n // Primitive types cannot have properties\n var primitive = formatPrimitive(ctx, value);\n if (primitive) {\n return primitive;\n }\n\n // Look up the keys of the object.\n var keys = Object.keys(value);\n var visibleKeys = arrayToHash(keys);\n\n if (ctx.showHidden) {\n keys = Object.getOwnPropertyNames(value);\n }\n\n // IE doesn't make error fields non-enumerable\n // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx\n if (isError(value)\n && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {\n return formatError(value);\n }\n\n // Some type of object without properties can be shortcutted.\n if (keys.length === 0) {\n if (isFunction(value)) {\n var name = value.name ? ': ' + value.name : '';\n return ctx.stylize('[Function' + name + ']', 'special');\n }\n if (isRegExp(value)) {\n return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n }\n if (isDate(value)) {\n return ctx.stylize(Date.prototype.toString.call(value), 'date');\n }\n if (isError(value)) {\n return formatError(value);\n }\n }\n\n var base = '', array = false, braces = ['{', '}'];\n\n // Make Array say that they are Array\n if (isArray(value)) {\n array = true;\n braces = ['[', ']'];\n }\n\n // Make functions say that they are functions\n if (isFunction(value)) {\n var n = value.name ? ': ' + value.name : '';\n base = ' [Function' + n + ']';\n }\n\n // Make RegExps say that they are RegExps\n if (isRegExp(value)) {\n base = ' ' + RegExp.prototype.toString.call(value);\n }\n\n // Make dates with properties first say the date\n if (isDate(value)) {\n base = ' ' + Date.prototype.toUTCString.call(value);\n }\n\n // Make error with message first say the error\n if (isError(value)) {\n base = ' ' + formatError(value);\n }\n\n if (keys.length === 0 && (!array || value.length == 0)) {\n return braces[0] + base + braces[1];\n }\n\n if (recurseTimes < 0) {\n if (isRegExp(value)) {\n return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n } else {\n return ctx.stylize('[Object]', 'special');\n }\n }\n\n ctx.seen.push(value);\n\n var output;\n if (array) {\n output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n } else {\n output = keys.map(function(key) {\n return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n });\n }\n\n ctx.seen.pop();\n\n return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n if (isUndefined(value))\n return ctx.stylize('undefined', 'undefined');\n if (isString(value)) {\n var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\\\\"/g, '\"') + '\\'';\n return ctx.stylize(simple, 'string');\n }\n if (isNumber(value))\n return ctx.stylize('' + value, 'number');\n if (isBoolean(value))\n return ctx.stylize('' + value, 'boolean');\n // For some reason typeof null is \"object\", so special case here.\n if (isNull(value))\n return ctx.stylize('null', 'null');\n}\n\n\nfunction formatError(value) {\n return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n var output = [];\n for (var i = 0, l = value.length; i < l; ++i) {\n if (hasOwnProperty(value, String(i))) {\n output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n String(i), true));\n } else {\n output.push('');\n }\n }\n keys.forEach(function(key) {\n if (!key.match(/^\\d+$/)) {\n output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n key, true));\n }\n });\n return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n var name, str, desc;\n desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };\n if (desc.get) {\n if (desc.set) {\n str = ctx.stylize('[Getter/Setter]', 'special');\n } else {\n str = ctx.stylize('[Getter]', 'special');\n }\n } else {\n if (desc.set) {\n str = ctx.stylize('[Setter]', 'special');\n }\n }\n if (!hasOwnProperty(visibleKeys, key)) {\n name = '[' + key + ']';\n }\n if (!str) {\n if (ctx.seen.indexOf(desc.value) < 0) {\n if (isNull(recurseTimes)) {\n str = formatValue(ctx, desc.value, null);\n } else {\n str = formatValue(ctx, desc.value, recurseTimes - 1);\n }\n if (str.indexOf('\\n') > -1) {\n if (array) {\n str = str.split('\\n').map(function(line) {\n return ' ' + line;\n }).join('\\n').substr(2);\n } else {\n str = '\\n' + str.split('\\n').map(function(line) {\n return ' ' + line;\n }).join('\\n');\n }\n }\n } else {\n str = ctx.stylize('[Circular]', 'special');\n }\n }\n if (isUndefined(name)) {\n if (array && key.match(/^\\d+$/)) {\n return str;\n }\n name = JSON.stringify('' + key);\n if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n name = name.substr(1, name.length - 2);\n name = ctx.stylize(name, 'name');\n } else {\n name = name.replace(/'/g, \"\\\\'\")\n .replace(/\\\\\"/g, '\"')\n .replace(/(^\"|\"$)/g, \"'\");\n name = ctx.stylize(name, 'string');\n }\n }\n\n return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n var numLinesEst = 0;\n var length = output.reduce(function(prev, cur) {\n numLinesEst++;\n if (cur.indexOf('\\n') >= 0) numLinesEst++;\n return prev + cur.replace(/\\u001b\\[\\d\\d?m/g, '').length + 1;\n }, 0);\n\n if (length > 60) {\n return braces[0] +\n (base === '' ? '' : base + '\\n ') +\n ' ' +\n output.join(',\\n ') +\n ' ' +\n braces[1];\n }\n\n return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\n\n// NOTE: These type checking functions intentionally don't use `instanceof`\n// because it is fragile and can be easily faked with `Object.create()`.\nfunction isArray(ar) {\n return Array.isArray(ar);\n}\nexports.isArray = isArray;\n\nfunction isBoolean(arg) {\n return typeof arg === 'boolean';\n}\nexports.isBoolean = isBoolean;\n\nfunction isNull(arg) {\n return arg === null;\n}\nexports.isNull = isNull;\n\nfunction isNullOrUndefined(arg) {\n return arg == null;\n}\nexports.isNullOrUndefined = isNullOrUndefined;\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\nexports.isNumber = isNumber;\n\nfunction isString(arg) {\n return typeof arg === 'string';\n}\nexports.isString = isString;\n\nfunction isSymbol(arg) {\n return typeof arg === 'symbol';\n}\nexports.isSymbol = isSymbol;\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\nexports.isUndefined = isUndefined;\n\nfunction isRegExp(re) {\n return isObject(re) && objectToString(re) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\nexports.isObject = isObject;\n\nfunction isDate(d) {\n return isObject(d) && objectToString(d) === '[object Date]';\n}\nexports.isDate = isDate;\n\nfunction isError(e) {\n return isObject(e) &&\n (objectToString(e) === '[object Error]' || e instanceof Error);\n}\nexports.isError = isError;\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\nexports.isFunction = isFunction;\n\nfunction isPrimitive(arg) {\n return arg === null ||\n typeof arg === 'boolean' ||\n typeof arg === 'number' ||\n typeof arg === 'string' ||\n typeof arg === 'symbol' || // ES6 symbol\n typeof arg === 'undefined';\n}\nexports.isPrimitive = isPrimitive;\n\nexports.isBuffer = __webpack_require__(/*! ./support/isBuffer */ \"./node_modules/util/support/isBufferBrowser.js\");\n\nfunction objectToString(o) {\n return Object.prototype.toString.call(o);\n}\n\n\nfunction pad(n) {\n return n < 10 ? '0' + n.toString(10) : n.toString(10);\n}\n\n\nvar months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',\n 'Oct', 'Nov', 'Dec'];\n\n// 26 Feb 16:19:34\nfunction timestamp() {\n var d = new Date();\n var time = [pad(d.getHours()),\n pad(d.getMinutes()),\n pad(d.getSeconds())].join(':');\n return [d.getDate(), months[d.getMonth()], time].join(' ');\n}\n\n\n// log is just a thin wrapper to console.log that prepends a timestamp\nexports.log = function() {\n console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));\n};\n\n\n/**\n * Inherit the prototype methods from one constructor into another.\n *\n * The Function.prototype.inherits from lang.js rewritten as a standalone\n * function (not on Function.prototype). NOTE: If this file is to be loaded\n * during bootstrapping this function needs to be rewritten using some native\n * functions as prototype setup using normal JavaScript does not work as\n * expected during bootstrapping (see mirror.js in r114903).\n *\n * @param {function} ctor Constructor function which needs to inherit the\n * prototype.\n * @param {function} superCtor Constructor function to inherit prototype from.\n */\nexports.inherits = __webpack_require__(/*! inherits */ \"./node_modules/util/node_modules/inherits/inherits_browser.js\");\n\nexports._extend = function(origin, add) {\n // Don't do anything if add isn't an object\n if (!add || !isObject(add)) return origin;\n\n var keys = Object.keys(add);\n var i = keys.length;\n while (i--) {\n origin[keys[i]] = add[keys[i]];\n }\n return origin;\n};\n\nfunction hasOwnProperty(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nvar kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;\n\nexports.promisify = function promisify(original) {\n if (typeof original !== 'function')\n throw new TypeError('The \"original\" argument must be of type Function');\n\n if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {\n var fn = original[kCustomPromisifiedSymbol];\n if (typeof fn !== 'function') {\n throw new TypeError('The \"util.promisify.custom\" argument must be of type Function');\n }\n Object.defineProperty(fn, kCustomPromisifiedSymbol, {\n value: fn, enumerable: false, writable: false, configurable: true\n });\n return fn;\n }\n\n function fn() {\n var promiseResolve, promiseReject;\n var promise = new Promise(function (resolve, reject) {\n promiseResolve = resolve;\n promiseReject = reject;\n });\n\n var args = [];\n for (var i = 0; i < arguments.length; i++) {\n args.push(arguments[i]);\n }\n args.push(function (err, value) {\n if (err) {\n promiseReject(err);\n } else {\n promiseResolve(value);\n }\n });\n\n try {\n original.apply(this, args);\n } catch (err) {\n promiseReject(err);\n }\n\n return promise;\n }\n\n Object.setPrototypeOf(fn, Object.getPrototypeOf(original));\n\n if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {\n value: fn, enumerable: false, writable: false, configurable: true\n });\n return Object.defineProperties(\n fn,\n getOwnPropertyDescriptors(original)\n );\n}\n\nexports.promisify.custom = kCustomPromisifiedSymbol\n\nfunction callbackifyOnRejected(reason, cb) {\n // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).\n // Because `null` is a special error value in callbacks which means \"no error\n // occurred\", we error-wrap so the callback consumer can distinguish between\n // \"the promise rejected with null\" or \"the promise fulfilled with undefined\".\n if (!reason) {\n var newReason = new Error('Promise was rejected with a falsy value');\n newReason.reason = reason;\n reason = newReason;\n }\n return cb(reason);\n}\n\nfunction callbackify(original) {\n if (typeof original !== 'function') {\n throw new TypeError('The \"original\" argument must be of type Function');\n }\n\n // We DO NOT return the promise as it gives the user a false sense that\n // the promise is actually somehow related to the callback's execution\n // and that the callback throwing will reject the promise.\n function callbackified() {\n var args = [];\n for (var i = 0; i < arguments.length; i++) {\n args.push(arguments[i]);\n }\n\n var maybeCb = args.pop();\n if (typeof maybeCb !== 'function') {\n throw new TypeError('The last argument must be of type Function');\n }\n var self = this;\n var cb = function() {\n return maybeCb.apply(self, arguments);\n };\n // In true node style we process the callback on `nextTick` with all the\n // implications (stack, `uncaughtException`, `async_hooks`)\n original.apply(this, args)\n .then(function(ret) { process.nextTick(cb, null, ret) },\n function(rej) { process.nextTick(callbackifyOnRejected, rej, cb) });\n }\n\n Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));\n Object.defineProperties(callbackified,\n getOwnPropertyDescriptors(original));\n return callbackified;\n}\nexports.callbackify = callbackify;\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../node-libs-browser/mock/process.js */ \"./node_modules/node-libs-browser/mock/process.js\")))\n\n//# sourceURL=webpack:///./node_modules/util/util.js?"); + +/***/ }), + +/***/ "./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/vue-style-loader??ref--8-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// style-loader: Adds some css to the DOM by adding a \");\n}\n\nfunction buildFormTemplate(scheme, child, type) {\n var labelPosition = '';\n\n if (scheme.labelPosition !== 'right') {\n labelPosition = \"label-position=\\\"\".concat(scheme.labelPosition, \"\\\"\");\n }\n\n var disabled = scheme.disabled ? \":disabled=\\\"\".concat(scheme.disabled, \"\\\"\") : '';\n var str = \"\\n \").concat(child, \"\\n \").concat(buildFromBtns(scheme, type), \"\\n \");\n\n if (someSpanIsNot24) {\n str = \"\\n \").concat(str, \"\\n \");\n }\n\n return str;\n}\n\nfunction buildFromBtns(scheme, type) {\n var str = '';\n\n if (scheme.formBtns && type === 'file') {\n str = \"\\n \\u63D0\\u4EA4\\n \\u91CD\\u7F6E\\n \";\n\n if (someSpanIsNot24) {\n str = \"\\n \".concat(str, \"\\n \");\n }\n }\n\n return str;\n} // span不为24的用el-col包裹\n\n\nfunction colWrapper(scheme, str) {\n if (someSpanIsNot24 || scheme.__config__.span !== 24) {\n return \"\\n \").concat(str, \"\\n \");\n }\n\n return str;\n}\n\nvar layouts = {\n colFormItem: function colFormItem(scheme) {\n var config = scheme.__config__;\n var labelWidth = '';\n var label = \"label=\\\"\".concat(config.label, \"\\\"\");\n\n if (config.labelWidth && config.labelWidth !== confGlobal.labelWidth) {\n labelWidth = \"label-width=\\\"\".concat(config.labelWidth, \"px\\\"\");\n }\n\n if (config.showLabel === false) {\n labelWidth = 'label-width=\"0\"';\n label = '';\n }\n\n var required = !_ruleTrigger.default[config.tag] && config.required ? 'required' : '';\n var tagDom = tags[config.tag] ? tags[config.tag](scheme) : null;\n var str = \"\\n \").concat(tagDom, \"\\n \");\n str = colWrapper(scheme, str);\n return str;\n },\n rowFormItem: function rowFormItem(scheme) {\n var config = scheme.__config__;\n var type = scheme.type === 'default' ? '' : \"type=\\\"\".concat(scheme.type, \"\\\"\");\n var justify = scheme.type === 'default' ? '' : \"justify=\\\"\".concat(scheme.justify, \"\\\"\");\n var align = scheme.type === 'default' ? '' : \"align=\\\"\".concat(scheme.align, \"\\\"\");\n var gutter = scheme.gutter ? \":gutter=\\\"\".concat(scheme.gutter, \"\\\"\") : '';\n var children = config.children.map(function (el) {\n return layouts[el.__config__.layout](el);\n });\n var str = \"\\n \").concat(children.join('\\n'), \"\\n \");\n str = colWrapper(scheme, str);\n return str;\n }\n};\nvar tags = {\n 'el-button': function elButton(el) {\n var _attrBuilder = attrBuilder(el),\n tag = _attrBuilder.tag,\n disabled = _attrBuilder.disabled;\n\n var type = el.type ? \"type=\\\"\".concat(el.type, \"\\\"\") : '';\n var icon = el.icon ? \"icon=\\\"\".concat(el.icon, \"\\\"\") : '';\n var round = el.round ? 'round' : '';\n var size = el.size ? \"size=\\\"\".concat(el.size, \"\\\"\") : '';\n var plain = el.plain ? 'plain' : '';\n var circle = el.circle ? 'circle' : '';\n var child = buildElButtonChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(type, \" \").concat(icon, \" \").concat(round, \" \").concat(size, \" \").concat(plain, \" \").concat(disabled, \" \").concat(circle, \">\").concat(child, \"\");\n },\n 'el-input': function elInput(el) {\n var _attrBuilder2 = attrBuilder(el),\n tag = _attrBuilder2.tag,\n disabled = _attrBuilder2.disabled,\n vModel = _attrBuilder2.vModel,\n clearable = _attrBuilder2.clearable,\n placeholder = _attrBuilder2.placeholder,\n width = _attrBuilder2.width;\n\n var maxlength = el.maxlength ? \":maxlength=\\\"\".concat(el.maxlength, \"\\\"\") : '';\n var showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '';\n var readonly = el.readonly ? 'readonly' : '';\n var prefixIcon = el['prefix-icon'] ? \"prefix-icon='\".concat(el['prefix-icon'], \"'\") : '';\n var suffixIcon = el['suffix-icon'] ? \"suffix-icon='\".concat(el['suffix-icon'], \"'\") : '';\n var showPassword = el['show-password'] ? 'show-password' : '';\n var type = el.type ? \"type=\\\"\".concat(el.type, \"\\\"\") : '';\n var autosize = el.autosize && el.autosize.minRows ? \":autosize=\\\"{minRows: \".concat(el.autosize.minRows, \", maxRows: \").concat(el.autosize.maxRows, \"}\\\"\") : '';\n var child = buildElInputChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(type, \" \").concat(placeholder, \" \").concat(maxlength, \" \").concat(showWordLimit, \" \").concat(readonly, \" \").concat(disabled, \" \").concat(clearable, \" \").concat(prefixIcon, \" \").concat(suffixIcon, \" \").concat(showPassword, \" \").concat(autosize, \" \").concat(width, \">\").concat(child, \"\");\n },\n 'el-input-number': function elInputNumber(el) {\n var _attrBuilder3 = attrBuilder(el),\n tag = _attrBuilder3.tag,\n disabled = _attrBuilder3.disabled,\n vModel = _attrBuilder3.vModel,\n placeholder = _attrBuilder3.placeholder;\n\n var controlsPosition = el['controls-position'] ? \"controls-position=\".concat(el['controls-position']) : '';\n var min = el.min ? \":min='\".concat(el.min, \"'\") : '';\n var max = el.max ? \":max='\".concat(el.max, \"'\") : '';\n var step = el.step ? \":step='\".concat(el.step, \"'\") : '';\n var stepStrictly = el['step-strictly'] ? 'step-strictly' : '';\n var precision = el.precision ? \":precision='\".concat(el.precision, \"'\") : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(placeholder, \" \").concat(step, \" \").concat(stepStrictly, \" \").concat(precision, \" \").concat(controlsPosition, \" \").concat(min, \" \").concat(max, \" \").concat(disabled, \">\");\n },\n 'el-select': function elSelect(el) {\n var _attrBuilder4 = attrBuilder(el),\n tag = _attrBuilder4.tag,\n disabled = _attrBuilder4.disabled,\n vModel = _attrBuilder4.vModel,\n clearable = _attrBuilder4.clearable,\n placeholder = _attrBuilder4.placeholder,\n width = _attrBuilder4.width;\n\n var filterable = el.filterable ? 'filterable' : '';\n var multiple = el.multiple ? 'multiple' : '';\n var child = buildElSelectChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(placeholder, \" \").concat(disabled, \" \").concat(multiple, \" \").concat(filterable, \" \").concat(clearable, \" \").concat(width, \">\").concat(child, \"\");\n },\n 'el-radio-group': function elRadioGroup(el) {\n var _attrBuilder5 = attrBuilder(el),\n tag = _attrBuilder5.tag,\n disabled = _attrBuilder5.disabled,\n vModel = _attrBuilder5.vModel;\n\n var size = \"size=\\\"\".concat(el.size, \"\\\"\");\n var child = buildElRadioGroupChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(size, \" \").concat(disabled, \">\").concat(child, \"\");\n },\n 'el-checkbox-group': function elCheckboxGroup(el) {\n var _attrBuilder6 = attrBuilder(el),\n tag = _attrBuilder6.tag,\n disabled = _attrBuilder6.disabled,\n vModel = _attrBuilder6.vModel;\n\n var size = \"size=\\\"\".concat(el.size, \"\\\"\");\n var min = el.min ? \":min=\\\"\".concat(el.min, \"\\\"\") : '';\n var max = el.max ? \":max=\\\"\".concat(el.max, \"\\\"\") : '';\n var child = buildElCheckboxGroupChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(min, \" \").concat(max, \" \").concat(size, \" \").concat(disabled, \">\").concat(child, \"\");\n },\n 'el-switch': function elSwitch(el) {\n var _attrBuilder7 = attrBuilder(el),\n tag = _attrBuilder7.tag,\n disabled = _attrBuilder7.disabled,\n vModel = _attrBuilder7.vModel;\n\n var activeText = el['active-text'] ? \"active-text=\\\"\".concat(el['active-text'], \"\\\"\") : '';\n var inactiveText = el['inactive-text'] ? \"inactive-text=\\\"\".concat(el['inactive-text'], \"\\\"\") : '';\n var activeColor = el['active-color'] ? \"active-color=\\\"\".concat(el['active-color'], \"\\\"\") : '';\n var inactiveColor = el['inactive-color'] ? \"inactive-color=\\\"\".concat(el['inactive-color'], \"\\\"\") : '';\n var activeValue = el['active-value'] !== true ? \":active-value='\".concat(JSON.stringify(el['active-value']), \"'\") : '';\n var inactiveValue = el['inactive-value'] !== false ? \":inactive-value='\".concat(JSON.stringify(el['inactive-value']), \"'\") : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(activeText, \" \").concat(inactiveText, \" \").concat(activeColor, \" \").concat(inactiveColor, \" \").concat(activeValue, \" \").concat(inactiveValue, \" \").concat(disabled, \">\");\n },\n 'el-cascader': function elCascader(el) {\n var _attrBuilder8 = attrBuilder(el),\n tag = _attrBuilder8.tag,\n disabled = _attrBuilder8.disabled,\n vModel = _attrBuilder8.vModel,\n clearable = _attrBuilder8.clearable,\n placeholder = _attrBuilder8.placeholder,\n width = _attrBuilder8.width;\n\n var options = el.options ? \":options=\\\"\".concat(el.__vModel__, \"Options\\\"\") : '';\n var props = el.props ? \":props=\\\"\".concat(el.__vModel__, \"Props\\\"\") : '';\n var showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels=\"false\"';\n var filterable = el.filterable ? 'filterable' : '';\n var separator = el.separator === '/' ? '' : \"separator=\\\"\".concat(el.separator, \"\\\"\");\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(options, \" \").concat(props, \" \").concat(width, \" \").concat(showAllLevels, \" \").concat(placeholder, \" \").concat(separator, \" \").concat(filterable, \" \").concat(clearable, \" \").concat(disabled, \">\");\n },\n 'el-slider': function elSlider(el) {\n var _attrBuilder9 = attrBuilder(el),\n tag = _attrBuilder9.tag,\n disabled = _attrBuilder9.disabled,\n vModel = _attrBuilder9.vModel;\n\n var min = el.min ? \":min='\".concat(el.min, \"'\") : '';\n var max = el.max ? \":max='\".concat(el.max, \"'\") : '';\n var step = el.step ? \":step='\".concat(el.step, \"'\") : '';\n var range = el.range ? 'range' : '';\n var showStops = el['show-stops'] ? \":show-stops=\\\"\".concat(el['show-stops'], \"\\\"\") : '';\n return \"<\".concat(tag, \" \").concat(min, \" \").concat(max, \" \").concat(step, \" \").concat(vModel, \" \").concat(range, \" \").concat(showStops, \" \").concat(disabled, \">\");\n },\n 'el-time-picker': function elTimePicker(el) {\n var _attrBuilder10 = attrBuilder(el),\n tag = _attrBuilder10.tag,\n disabled = _attrBuilder10.disabled,\n vModel = _attrBuilder10.vModel,\n clearable = _attrBuilder10.clearable,\n placeholder = _attrBuilder10.placeholder,\n width = _attrBuilder10.width;\n\n var startPlaceholder = el['start-placeholder'] ? \"start-placeholder=\\\"\".concat(el['start-placeholder'], \"\\\"\") : '';\n var endPlaceholder = el['end-placeholder'] ? \"end-placeholder=\\\"\".concat(el['end-placeholder'], \"\\\"\") : '';\n var rangeSeparator = el['range-separator'] ? \"range-separator=\\\"\".concat(el['range-separator'], \"\\\"\") : '';\n var isRange = el['is-range'] ? 'is-range' : '';\n var format = el.format ? \"format=\\\"\".concat(el.format, \"\\\"\") : '';\n var valueFormat = el['value-format'] ? \"value-format=\\\"\".concat(el['value-format'], \"\\\"\") : '';\n var pickerOptions = el['picker-options'] ? \":picker-options='\".concat(JSON.stringify(el['picker-options']), \"'\") : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(isRange, \" \").concat(format, \" \").concat(valueFormat, \" \").concat(pickerOptions, \" \").concat(width, \" \").concat(placeholder, \" \").concat(startPlaceholder, \" \").concat(endPlaceholder, \" \").concat(rangeSeparator, \" \").concat(clearable, \" \").concat(disabled, \">\");\n },\n 'el-date-picker': function elDatePicker(el) {\n var _attrBuilder11 = attrBuilder(el),\n tag = _attrBuilder11.tag,\n disabled = _attrBuilder11.disabled,\n vModel = _attrBuilder11.vModel,\n clearable = _attrBuilder11.clearable,\n placeholder = _attrBuilder11.placeholder,\n width = _attrBuilder11.width;\n\n var startPlaceholder = el['start-placeholder'] ? \"start-placeholder=\\\"\".concat(el['start-placeholder'], \"\\\"\") : '';\n var endPlaceholder = el['end-placeholder'] ? \"end-placeholder=\\\"\".concat(el['end-placeholder'], \"\\\"\") : '';\n var rangeSeparator = el['range-separator'] ? \"range-separator=\\\"\".concat(el['range-separator'], \"\\\"\") : '';\n var format = el.format ? \"format=\\\"\".concat(el.format, \"\\\"\") : '';\n var valueFormat = el['value-format'] ? \"value-format=\\\"\".concat(el['value-format'], \"\\\"\") : '';\n var type = el.type === 'date' ? '' : \"type=\\\"\".concat(el.type, \"\\\"\");\n var readonly = el.readonly ? 'readonly' : '';\n return \"<\".concat(tag, \" \").concat(type, \" \").concat(vModel, \" \").concat(format, \" \").concat(valueFormat, \" \").concat(width, \" \").concat(placeholder, \" \").concat(startPlaceholder, \" \").concat(endPlaceholder, \" \").concat(rangeSeparator, \" \").concat(clearable, \" \").concat(readonly, \" \").concat(disabled, \">\");\n },\n 'el-rate': function elRate(el) {\n var _attrBuilder12 = attrBuilder(el),\n tag = _attrBuilder12.tag,\n disabled = _attrBuilder12.disabled,\n vModel = _attrBuilder12.vModel;\n\n var max = el.max ? \":max='\".concat(el.max, \"'\") : '';\n var allowHalf = el['allow-half'] ? 'allow-half' : '';\n var showText = el['show-text'] ? 'show-text' : '';\n var showScore = el['show-score'] ? 'show-score' : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(max, \" \").concat(allowHalf, \" \").concat(showText, \" \").concat(showScore, \" \").concat(disabled, \">\");\n },\n 'el-color-picker': function elColorPicker(el) {\n var _attrBuilder13 = attrBuilder(el),\n tag = _attrBuilder13.tag,\n disabled = _attrBuilder13.disabled,\n vModel = _attrBuilder13.vModel;\n\n var size = \"size=\\\"\".concat(el.size, \"\\\"\");\n var showAlpha = el['show-alpha'] ? 'show-alpha' : '';\n var colorFormat = el['color-format'] ? \"color-format=\\\"\".concat(el['color-format'], \"\\\"\") : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(size, \" \").concat(showAlpha, \" \").concat(colorFormat, \" \").concat(disabled, \">\");\n },\n 'el-upload': function elUpload(el) {\n var tag = el.__config__.tag;\n var disabled = el.disabled ? ':disabled=\\'true\\'' : '';\n var action = el.action ? \":action=\\\"\".concat(el.__vModel__, \"Action\\\"\") : '';\n var multiple = el.multiple ? 'multiple' : '';\n var listType = el['list-type'] !== 'text' ? \"list-type=\\\"\".concat(el['list-type'], \"\\\"\") : '';\n var accept = el.accept ? \"accept=\\\"\".concat(el.accept, \"\\\"\") : '';\n var name = el.name !== 'file' ? \"name=\\\"\".concat(el.name, \"\\\"\") : '';\n var autoUpload = el['auto-upload'] === false ? ':auto-upload=\"false\"' : '';\n var beforeUpload = \":before-upload=\\\"\".concat(el.__vModel__, \"BeforeUpload\\\"\");\n var fileList = \":file-list=\\\"\".concat(el.__vModel__, \"fileList\\\"\");\n var ref = \"ref=\\\"\".concat(el.__vModel__, \"\\\"\");\n var child = buildElUploadChild(el);\n if (child) child = \"\\n\".concat(child, \"\\n\"); // 换行\n\n return \"<\".concat(tag, \" \").concat(ref, \" \").concat(fileList, \" \").concat(action, \" \").concat(autoUpload, \" \").concat(multiple, \" \").concat(beforeUpload, \" \").concat(listType, \" \").concat(accept, \" \").concat(name, \" \").concat(disabled, \">\").concat(child, \"\");\n },\n tinymce: function tinymce(el) {\n var _attrBuilder14 = attrBuilder(el),\n tag = _attrBuilder14.tag,\n vModel = _attrBuilder14.vModel,\n placeholder = _attrBuilder14.placeholder;\n\n var height = el.height ? \":height=\\\"\".concat(el.height, \"\\\"\") : '';\n var branding = el.branding ? \":branding=\\\"\".concat(el.branding, \"\\\"\") : '';\n return \"<\".concat(tag, \" \").concat(vModel, \" \").concat(placeholder, \" \").concat(height, \" \").concat(branding, \">\");\n }\n};\n\nfunction attrBuilder(el) {\n return {\n tag: el.__config__.tag,\n vModel: \"v-model=\\\"\".concat(confGlobal.formModel, \".\").concat(el.__vModel__, \"\\\"\"),\n clearable: el.clearable ? 'clearable' : '',\n placeholder: el.placeholder ? \"placeholder=\\\"\".concat(el.placeholder, \"\\\"\") : '',\n width: el.style && el.style.width ? ':style=\"{width: \\'100%\\'}\"' : '',\n disabled: el.disabled ? ':disabled=\\'true\\'' : ''\n };\n} // el-buttin 子级\n\n\nfunction buildElButtonChild(scheme) {\n var children = [];\n var slot = scheme.__slot__ || {};\n\n if (slot.default) {\n children.push(slot.default);\n }\n\n return children.join('\\n');\n} // el-input 子级\n\n\nfunction buildElInputChild(scheme) {\n var children = [];\n var slot = scheme.__slot__;\n\n if (slot && slot.prepend) {\n children.push(\"\"));\n }\n\n if (slot && slot.append) {\n children.push(\"\"));\n }\n\n return children.join('\\n');\n} // el-select 子级\n\n\nfunction buildElSelectChild(scheme) {\n var children = [];\n var slot = scheme.__slot__;\n\n if (slot && slot.options && slot.options.length) {\n children.push(\"\"));\n }\n\n return children.join('\\n');\n} // el-radio-group 子级\n\n\nfunction buildElRadioGroupChild(scheme) {\n var children = [];\n var slot = scheme.__slot__;\n var config = scheme.__config__;\n\n if (slot && slot.options && slot.options.length) {\n var tag = config.optionType === 'button' ? 'el-radio-button' : 'el-radio';\n var border = config.border ? 'border' : '';\n children.push(\"<\".concat(tag, \" v-for=\\\"(item, index) in \").concat(scheme.__vModel__, \"Options\\\" :key=\\\"index\\\" :label=\\\"item.value\\\" :disabled=\\\"item.disabled\\\" \").concat(border, \">{{item.label}}\"));\n }\n\n return children.join('\\n');\n} // el-checkbox-group 子级\n\n\nfunction buildElCheckboxGroupChild(scheme) {\n var children = [];\n var slot = scheme.__slot__;\n var config = scheme.__config__;\n\n if (slot && slot.options && slot.options.length) {\n var tag = config.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox';\n var border = config.border ? 'border' : '';\n children.push(\"<\".concat(tag, \" v-for=\\\"(item, index) in \").concat(scheme.__vModel__, \"Options\\\" :key=\\\"index\\\" :label=\\\"item.value\\\" :disabled=\\\"item.disabled\\\" \").concat(border, \">{{item.label}}\"));\n }\n\n return children.join('\\n');\n} // el-upload 子级\n\n\nfunction buildElUploadChild(scheme) {\n var list = [];\n var config = scheme.__config__;\n if (scheme['list-type'] === 'picture-card') list.push('');else list.push(\"\".concat(config.buttonText, \"\"));\n if (config.showTip) list.push(\"
\\u53EA\\u80FD\\u4E0A\\u4F20\\u4E0D\\u8D85\\u8FC7 \".concat(config.fileSize).concat(config.sizeUnit, \" \\u7684\").concat(scheme.accept, \"\\u6587\\u4EF6
\"));\n return list.join('\\n');\n}\n/**\n * 组装html代码。【入口函数】\n * @param {Object} formConfig 整个表单配置\n * @param {String} type 生成类型,文件或弹窗等\n */\n\n\nfunction makeUpHtml(formConfig, type) {\n var htmlList = [];\n confGlobal = formConfig; // 判断布局是否都沾满了24个栅格,以备后续简化代码结构\n\n someSpanIsNot24 = formConfig.fields.some(function (item) {\n return item.__config__.span !== 24;\n }); // 遍历渲染每个组件成html\n\n formConfig.fields.forEach(function (el) {\n htmlList.push(layouts[el.__config__.layout](el));\n });\n var htmlStr = htmlList.join('\\n'); // 将组件代码放进form标签\n\n var temp = buildFormTemplate(formConfig, htmlStr, type); // dialog标签包裹代码\n\n if (type === 'dialog') {\n temp = dialogWrapper(temp);\n }\n\n confGlobal = null;\n return temp;\n}\n\n//# sourceURL=webpack:///./src/components/generator/html.js?"); + +/***/ }), + +/***/ "./src/components/generator/js.js": +/*!****************************************!*\ + !*** ./src/components/generator/js.js ***! + \****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.makeUpJs = makeUpJs;\n\n__webpack_require__(/*! core-js/modules/es.object.to-string.js */ \"./node_modules/core-js/modules/es.object.to-string.js\");\n\n__webpack_require__(/*! core-js/modules/web.dom-collections.for-each.js */ \"./node_modules/core-js/modules/web.dom-collections.for-each.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.join.js */ \"./node_modules/core-js/modules/es.array.join.js\");\n\n__webpack_require__(/*! core-js/modules/es.array.concat.js */ \"./node_modules/core-js/modules/es.array.concat.js\");\n\n__webpack_require__(/*! core-js/modules/es.object.keys.js */ \"./node_modules/core-js/modules/es.object.keys.js\");\n\n__webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n\nvar _util = __webpack_require__(/*! util */ \"./node_modules/util/util.js\");\n\nvar _index = __webpack_require__(/*! @/utils/index */ \"./src/utils/index.js\");\n\nvar _ruleTrigger = _interopRequireDefault(__webpack_require__(/*! ./ruleTrigger */ \"./src/components/generator/ruleTrigger.js\"));\n\nvar units = {\n KB: '1024',\n MB: '1024 / 1024',\n GB: '1024 / 1024 / 1024'\n};\nvar confGlobal;\nvar inheritAttrs = {\n file: '',\n dialog: 'inheritAttrs: false,'\n};\n/**\n * 组装js 【入口函数】\n * @param {Object} formConfig 整个表单配置\n * @param {String} type 生成类型,文件或弹窗等\n */\n\nfunction makeUpJs(formConfig, type) {\n confGlobal = formConfig = (0, _index.deepClone)(formConfig);\n var dataList = [];\n var ruleList = [];\n var optionsList = [];\n var propsList = [];\n var methodList = mixinMethod(type);\n var uploadVarList = [];\n var created = [];\n formConfig.fields.forEach(function (el) {\n buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created);\n });\n var script = buildexport(formConfig, type, dataList.join('\\n'), ruleList.join('\\n'), optionsList.join('\\n'), uploadVarList.join('\\n'), propsList.join('\\n'), methodList.join('\\n'), created.join('\\n'));\n confGlobal = null;\n return script;\n} // 构建组件属性\n\n\nfunction buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {\n var config = scheme.__config__;\n var slot = scheme.__slot__;\n buildData(scheme, dataList);\n buildRules(scheme, ruleList); // 特殊处理options属性\n\n if (scheme.options || slot && slot.options && slot.options.length) {\n buildOptions(scheme, optionsList);\n\n if (config.dataType === 'dynamic') {\n var model = \"\".concat(scheme.__vModel__, \"Options\");\n var options = (0, _index.titleCase)(model);\n var methodName = \"get\".concat(options);\n buildOptionMethod(methodName, model, methodList, scheme);\n callInCreated(methodName, created);\n }\n } // 处理props\n\n\n if (scheme.props && scheme.props.props) {\n buildProps(scheme, propsList);\n } // 处理el-upload的action\n\n\n if (scheme.action && config.tag === 'el-upload') {\n uploadVarList.push(\"\".concat(scheme.__vModel__, \"Action: '\").concat(scheme.action, \"',\\n \").concat(scheme.__vModel__, \"fileList: [],\"));\n methodList.push(buildBeforeUpload(scheme)); // 非自动上传时,生成手动上传的函数\n\n if (!scheme['auto-upload']) {\n methodList.push(buildSubmitUpload(scheme));\n }\n } // 构建子级组件属性\n\n\n if (config.children) {\n config.children.forEach(function (item) {\n buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created);\n });\n }\n} // 在Created调用函数\n\n\nfunction callInCreated(methodName, created) {\n created.push(\"this.\".concat(methodName, \"()\"));\n} // 混入处理函数\n\n\nfunction mixinMethod(type) {\n var list = [];\n var minxins = {\n file: confGlobal.formBtns ? {\n submitForm: \"submitForm() {\\n this.$refs['\".concat(confGlobal.formRef, \"'].validate(valid => {\\n if(!valid) return\\n // TODO \\u63D0\\u4EA4\\u8868\\u5355\\n })\\n },\"),\n resetForm: \"resetForm() {\\n this.$refs['\".concat(confGlobal.formRef, \"'].resetFields()\\n },\")\n } : null,\n dialog: {\n onOpen: 'onOpen() {},',\n onClose: \"onClose() {\\n this.$refs['\".concat(confGlobal.formRef, \"'].resetFields()\\n },\"),\n close: \"close() {\\n this.$emit('update:visible', false)\\n },\",\n handelConfirm: \"handelConfirm() {\\n this.$refs['\".concat(confGlobal.formRef, \"'].validate(valid => {\\n if(!valid) return\\n this.close()\\n })\\n },\")\n }\n };\n var methods = minxins[type];\n\n if (methods) {\n Object.keys(methods).forEach(function (key) {\n list.push(methods[key]);\n });\n }\n\n return list;\n} // 构建data\n\n\nfunction buildData(scheme, dataList) {\n var config = scheme.__config__;\n if (scheme.__vModel__ === undefined) return;\n var defaultValue = JSON.stringify(config.defaultValue);\n dataList.push(\"\".concat(scheme.__vModel__, \": \").concat(defaultValue, \",\"));\n} // 构建校验规则\n\n\nfunction buildRules(scheme, ruleList) {\n var config = scheme.__config__;\n if (scheme.__vModel__ === undefined) return;\n var rules = [];\n\n if (_ruleTrigger.default[config.tag]) {\n if (config.required) {\n var type = (0, _util.isArray)(config.defaultValue) ? 'type: \\'array\\',' : '';\n var message = (0, _util.isArray)(config.defaultValue) ? \"\\u8BF7\\u81F3\\u5C11\\u9009\\u62E9\\u4E00\\u4E2A\".concat(config.label) : scheme.placeholder;\n if (message === undefined) message = \"\".concat(config.label, \"\\u4E0D\\u80FD\\u4E3A\\u7A7A\");\n rules.push(\"{ required: true, \".concat(type, \" message: '\").concat(message, \"', trigger: '\").concat(_ruleTrigger.default[config.tag], \"' }\"));\n }\n\n if (config.regList && (0, _util.isArray)(config.regList)) {\n config.regList.forEach(function (item) {\n if (item.pattern) {\n rules.push(\"{ pattern: \".concat(eval(item.pattern), \", message: '\").concat(item.message, \"', trigger: '\").concat(_ruleTrigger.default[config.tag], \"' }\"));\n }\n });\n }\n\n ruleList.push(\"\".concat(scheme.__vModel__, \": [\").concat(rules.join(','), \"],\"));\n }\n} // 构建options\n\n\nfunction buildOptions(scheme, optionsList) {\n if (scheme.__vModel__ === undefined) return; // el-cascader直接有options属性,其他组件都是定义在slot中,所以有两处判断\n\n var options = scheme.options;\n if (!options) options = scheme.__slot__.options;\n\n if (scheme.__config__.dataType === 'dynamic') {\n options = [];\n }\n\n var str = \"\".concat(scheme.__vModel__, \"Options: \").concat(JSON.stringify(options), \",\");\n optionsList.push(str);\n}\n\nfunction buildProps(scheme, propsList) {\n var str = \"\".concat(scheme.__vModel__, \"Props: \").concat(JSON.stringify(scheme.props.props), \",\");\n propsList.push(str);\n} // el-upload的BeforeUpload\n\n\nfunction buildBeforeUpload(scheme) {\n var config = scheme.__config__;\n var unitNum = units[config.sizeUnit];\n var rightSizeCode = '';\n var acceptCode = '';\n var returnList = [];\n\n if (config.fileSize) {\n rightSizeCode = \"let isRightSize = file.size / \".concat(unitNum, \" < \").concat(config.fileSize, \"\\n if(!isRightSize){\\n this.$message.error('\\u6587\\u4EF6\\u5927\\u5C0F\\u8D85\\u8FC7 \").concat(config.fileSize).concat(config.sizeUnit, \"')\\n }\");\n returnList.push('isRightSize');\n }\n\n if (scheme.accept) {\n acceptCode = \"let isAccept = new RegExp('\".concat(scheme.accept, \"').test(file.type)\\n if(!isAccept){\\n this.$message.error('\\u5E94\\u8BE5\\u9009\\u62E9\").concat(scheme.accept, \"\\u7C7B\\u578B\\u7684\\u6587\\u4EF6')\\n }\");\n returnList.push('isAccept');\n }\n\n var str = \"\".concat(scheme.__vModel__, \"BeforeUpload(file) {\\n \").concat(rightSizeCode, \"\\n \").concat(acceptCode, \"\\n return \").concat(returnList.join('&&'), \"\\n },\");\n return returnList.length ? str : '';\n} // el-upload的submit\n\n\nfunction buildSubmitUpload(scheme) {\n var str = \"submitUpload() {\\n this.$refs['\".concat(scheme.__vModel__, \"'].submit()\\n },\");\n return str;\n}\n\nfunction buildOptionMethod(methodName, model, methodList, scheme) {\n var config = scheme.__config__;\n var str = \"\".concat(methodName, \"() {\\n // \\u6CE8\\u610F\\uFF1Athis.$axios\\u662F\\u901A\\u8FC7Vue.prototype.$axios = axios\\u6302\\u8F7D\\u4EA7\\u751F\\u7684\\n this.$axios({\\n method: '\").concat(config.method, \"',\\n url: '\").concat(config.url, \"'\\n }).then(resp => {\\n var { data } = resp\\n this.\").concat(model, \" = data.\").concat(config.dataPath, \"\\n })\\n },\");\n methodList.push(str);\n} // js整体拼接\n\n\nfunction buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {\n var str = \"\".concat(_index.exportDefault, \"{\\n \").concat(inheritAttrs[type], \"\\n components: {},\\n props: [],\\n data () {\\n return {\\n \").concat(conf.formModel, \": {\\n \").concat(data, \"\\n },\\n \").concat(conf.formRules, \": {\\n \").concat(rules, \"\\n },\\n \").concat(uploadVar, \"\\n \").concat(selectOptions, \"\\n \").concat(props, \"\\n }\\n },\\n computed: {},\\n watch: {},\\n created () {\\n \").concat(created, \"\\n },\\n mounted () {},\\n methods: {\\n \").concat(methods, \"\\n }\\n}\");\n return str;\n}\n\n//# sourceURL=webpack:///./src/components/generator/js.js?"); + +/***/ }), + +/***/ "./src/components/generator/ruleTrigger.js": +/*!*************************************************!*\ + !*** ./src/components/generator/ruleTrigger.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n/**\n * 用于生成表单校验,指定正则规则的触发方式。\n * 未在此处声明无触发方式的组件将不生成rule!!\n */\nvar _default = {\n 'el-input': 'blur',\n 'el-input-number': 'blur',\n 'el-select': 'change',\n 'el-radio-group': 'change',\n 'el-checkbox-group': 'change',\n 'el-cascader': 'change',\n 'el-time-picker': 'change',\n 'el-date-picker': 'change',\n 'el-rate': 'change',\n tinymce: 'blur'\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/components/generator/ruleTrigger.js?"); + +/***/ }), + +/***/ "./src/utils/constants.js": +/*!********************************!*\ + !*** ./src/utils/constants.js ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.ToolCodegenTemplateTypeEnum = exports.SystemUserSocialTypeEnum = exports.SystemRoleTypeEnum = exports.SystemMenuTypeEnum = exports.SystemDataScopeEnum = exports.PayType = exports.PayRefundStatusEnum = exports.PayOrderStatusEnum = exports.PayOrderRefundStatusEnum = exports.PayOrderNotifyStatusEnum = exports.PayChannelEnum = exports.InfraJobStatusEnum = exports.InfraApiErrorLogProcessStatusEnum = exports.CommonStatusEnum = void 0;\n\n/**\n * Created by 芋道源码\n *\n * 枚举类\n */\n\n/**\n * 全局通用状态枚举\n */\nvar CommonStatusEnum = {\n ENABLE: 0,\n // 开启\n DISABLE: 1 // 禁用\n\n};\n/**\n * 菜单的类型枚举\n */\n\nexports.CommonStatusEnum = CommonStatusEnum;\nvar SystemMenuTypeEnum = {\n DIR: 1,\n // 目录\n MENU: 2,\n // 菜单\n BUTTON: 3 // 按钮\n\n};\n/**\n * 角色的类型枚举\n */\n\nexports.SystemMenuTypeEnum = SystemMenuTypeEnum;\nvar SystemRoleTypeEnum = {\n SYSTEM: 1,\n // 内置角色\n CUSTOM: 2 // 自定义角色\n\n};\n/**\n * 数据权限的范围枚举\n */\n\nexports.SystemRoleTypeEnum = SystemRoleTypeEnum;\nvar SystemDataScopeEnum = {\n ALL: 1,\n // 全部数据权限\n DEPT_CUSTOM: 2,\n // 指定部门数据权限\n DEPT_ONLY: 3,\n // 部门数据权限\n DEPT_AND_CHILD: 4,\n // 部门及以下数据权限\n DEPT_SELF: 5 // 仅本人数据权限\n\n};\n/**\n * 代码生成模板类型\n */\n\nexports.SystemDataScopeEnum = SystemDataScopeEnum;\nvar ToolCodegenTemplateTypeEnum = {\n CRUD: 1,\n // 基础 CRUD\n TREE: 2,\n // 树形 CRUD\n SUB: 3 // 主子表 CRUD\n\n};\n/**\n * 任务状态的枚举\n */\n\nexports.ToolCodegenTemplateTypeEnum = ToolCodegenTemplateTypeEnum;\nvar InfraJobStatusEnum = {\n INIT: 0,\n // 初始化中\n NORMAL: 1,\n // 运行中\n STOP: 2 // 暂停运行\n\n};\n/**\n * API 异常数据的处理状态\n */\n\nexports.InfraJobStatusEnum = InfraJobStatusEnum;\nvar InfraApiErrorLogProcessStatusEnum = {\n INIT: 0,\n // 未处理\n DONE: 1,\n // 已处理\n IGNORE: 2 // 已忽略\n\n};\n/**\n * 用户的社交平台的类型枚举\n */\n\nexports.InfraApiErrorLogProcessStatusEnum = InfraApiErrorLogProcessStatusEnum;\nvar SystemUserSocialTypeEnum = {\n // GITEE: {\n // title: \"码云\",\n // type: 10,\n // source: \"gitee\",\n // img: \"https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/gitee.png\",\n // },\n DINGTALK: {\n title: \"钉钉\",\n type: 20,\n source: \"dingtalk\",\n img: \"https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/dingtalk.png\"\n },\n WECHAT_ENTERPRISE: {\n title: \"企业微信\",\n type: 30,\n source: \"wechat_enterprise\",\n img: \"https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.11/wechat_enterprise.png\"\n }\n};\n/**\n * 支付渠道枚举\n */\n\nexports.SystemUserSocialTypeEnum = SystemUserSocialTypeEnum;\nvar PayChannelEnum = {\n WX_PUB: {\n \"code\": \"wx_pub\",\n \"name\": \"微信 JSAPI 支付\"\n },\n WX_LITE: {\n \"code\": \"wx_lite\",\n \"name\": \"微信小程序支付\"\n },\n WX_APP: {\n \"code\": \"wx_app\",\n \"name\": \"微信 APP 支付\"\n },\n ALIPAY_PC: {\n \"code\": \"alipay_pc\",\n \"name\": \"支付宝 PC 网站支付\"\n },\n ALIPAY_WAP: {\n \"code\": \"alipay_wap\",\n \"name\": \"支付宝 WAP 网站支付\"\n },\n ALIPAY_APP: {\n \"code\": \"alipay_app\",\n \"name\": \"支付宝 APP 支付\"\n },\n ALIPAY_QR: {\n \"code\": \"alipay_qr\",\n \"name\": \"支付宝扫码支付\"\n }\n};\n/**\n * 支付类型枚举\n */\n\nexports.PayChannelEnum = PayChannelEnum;\nvar PayType = {\n WECHAT: \"WECHAT\",\n ALIPAY: \"ALIPAY\"\n};\n/**\n * 支付订单状态枚举\n */\n\nexports.PayType = PayType;\nvar PayOrderStatusEnum = {\n WAITING: {\n status: 0,\n name: '未支付'\n },\n SUCCESS: {\n status: 10,\n name: '已支付'\n },\n CLOSED: {\n status: 20,\n name: '未支付'\n }\n};\n/**\n * 支付订单回调状态枚举\n */\n\nexports.PayOrderStatusEnum = PayOrderStatusEnum;\nvar PayOrderNotifyStatusEnum = {\n NO: {\n status: 0,\n name: '未通知'\n },\n SUCCESS: {\n status: 10,\n name: '通知成功'\n },\n FAILURE: {\n status: 20,\n name: '通知失败'\n }\n};\n/**\n * 支付订单退款状态枚举\n */\n\nexports.PayOrderNotifyStatusEnum = PayOrderNotifyStatusEnum;\nvar PayOrderRefundStatusEnum = {\n NO: {\n status: 0,\n name: '未退款'\n },\n SOME: {\n status: 10,\n name: '部分退款'\n },\n ALL: {\n status: 20,\n name: '全部退款'\n }\n};\n/**\n * 支付退款订单状态枚举\n */\n\nexports.PayOrderRefundStatusEnum = PayOrderRefundStatusEnum;\nvar PayRefundStatusEnum = {\n CREATE: {\n status: 0,\n name: '退款订单生成'\n },\n SUCCESS: {\n status: 1,\n name: '退款成功'\n },\n FAILURE: {\n status: 2,\n name: '退款失败'\n },\n PROCESSING_NOTIFY: {\n status: 3,\n name: '退款中,渠道通知结果'\n },\n PROCESSING_QUERY: {\n status: 4,\n name: '退款中,系统查询结果'\n },\n UNKNOWN_RETRY: {\n status: 5,\n name: '状态未知,请重试'\n },\n UNKNOWN_QUERY: {\n status: 6,\n name: '状态未知,系统查询结果'\n },\n CLOSE: {\n status: 99,\n name: '退款关闭'\n }\n};\nexports.PayRefundStatusEnum = PayRefundStatusEnum;\n\n//# sourceURL=webpack:///./src/utils/constants.js?"); + +/***/ }), + +/***/ "./src/utils/db.js": +/*!*************************!*\ + !*** ./src/utils/db.js ***! + \*************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.getDrawingList = getDrawingList;\nexports.getFormConf = getFormConf;\nexports.getIdGlobal = getIdGlobal;\nexports.getTreeNodeId = getTreeNodeId;\nexports.saveDrawingList = saveDrawingList;\nexports.saveFormConf = saveFormConf;\nexports.saveIdGlobal = saveIdGlobal;\nexports.saveTreeNodeId = saveTreeNodeId;\n\n__webpack_require__(/*! core-js/modules/es.json.stringify.js */ \"./node_modules/core-js/modules/es.json.stringify.js\");\n\nvar DRAWING_ITEMS = 'drawingItems';\nvar DRAWING_ITEMS_VERSION = '1.2';\nvar DRAWING_ITEMS_VERSION_KEY = 'DRAWING_ITEMS_VERSION';\nvar DRAWING_ID = 'idGlobal';\nvar TREE_NODE_ID = 'treeNodeId';\nvar FORM_CONF = 'formConf';\n\nfunction getDrawingList() {\n // 加入缓存版本的概念,保证缓存数据与程序匹配\n var version = localStorage.getItem(DRAWING_ITEMS_VERSION_KEY);\n\n if (version !== DRAWING_ITEMS_VERSION) {\n localStorage.setItem(DRAWING_ITEMS_VERSION_KEY, DRAWING_ITEMS_VERSION);\n saveDrawingList([]);\n return null;\n }\n\n var str = localStorage.getItem(DRAWING_ITEMS);\n if (str) return JSON.parse(str);\n return null;\n}\n\nfunction saveDrawingList(list) {\n localStorage.setItem(DRAWING_ITEMS, JSON.stringify(list));\n}\n\nfunction getIdGlobal() {\n var str = localStorage.getItem(DRAWING_ID);\n if (str) return parseInt(str, 10);\n return 100;\n}\n\nfunction saveIdGlobal(id) {\n localStorage.setItem(DRAWING_ID, \"\".concat(id));\n}\n\nfunction getTreeNodeId() {\n var str = localStorage.getItem(TREE_NODE_ID);\n if (str) return parseInt(str, 10);\n return 100;\n}\n\nfunction saveTreeNodeId(id) {\n localStorage.setItem(TREE_NODE_ID, \"\".concat(id));\n}\n\nfunction getFormConf() {\n var str = localStorage.getItem(FORM_CONF);\n if (str) return JSON.parse(str);\n return null;\n}\n\nfunction saveFormConf(obj) {\n localStorage.setItem(FORM_CONF, JSON.stringify(obj));\n}\n\n//# sourceURL=webpack:///./src/utils/db.js?"); + +/***/ }), + +/***/ "./src/utils/icon.json": +/*!*****************************!*\ + !*** ./src/utils/icon.json ***! + \*****************************/ +/*! exports provided: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, default */ +/***/ (function(module) { + +eval("module.exports = JSON.parse(\"[\\\"platform-eleme\\\",\\\"eleme\\\",\\\"delete-solid\\\",\\\"delete\\\",\\\"s-tools\\\",\\\"setting\\\",\\\"user-solid\\\",\\\"user\\\",\\\"phone\\\",\\\"phone-outline\\\",\\\"more\\\",\\\"more-outline\\\",\\\"star-on\\\",\\\"star-off\\\",\\\"s-goods\\\",\\\"goods\\\",\\\"warning\\\",\\\"warning-outline\\\",\\\"question\\\",\\\"info\\\",\\\"remove\\\",\\\"circle-plus\\\",\\\"success\\\",\\\"error\\\",\\\"zoom-in\\\",\\\"zoom-out\\\",\\\"remove-outline\\\",\\\"circle-plus-outline\\\",\\\"circle-check\\\",\\\"circle-close\\\",\\\"s-help\\\",\\\"help\\\",\\\"minus\\\",\\\"plus\\\",\\\"check\\\",\\\"close\\\",\\\"picture\\\",\\\"picture-outline\\\",\\\"picture-outline-round\\\",\\\"upload\\\",\\\"upload2\\\",\\\"download\\\",\\\"camera-solid\\\",\\\"camera\\\",\\\"video-camera-solid\\\",\\\"video-camera\\\",\\\"message-solid\\\",\\\"bell\\\",\\\"s-cooperation\\\",\\\"s-order\\\",\\\"s-platform\\\",\\\"s-fold\\\",\\\"s-unfold\\\",\\\"s-operation\\\",\\\"s-promotion\\\",\\\"s-home\\\",\\\"s-release\\\",\\\"s-ticket\\\",\\\"s-management\\\",\\\"s-open\\\",\\\"s-shop\\\",\\\"s-marketing\\\",\\\"s-flag\\\",\\\"s-comment\\\",\\\"s-finance\\\",\\\"s-claim\\\",\\\"s-custom\\\",\\\"s-opportunity\\\",\\\"s-data\\\",\\\"s-check\\\",\\\"s-grid\\\",\\\"menu\\\",\\\"share\\\",\\\"d-caret\\\",\\\"caret-left\\\",\\\"caret-right\\\",\\\"caret-bottom\\\",\\\"caret-top\\\",\\\"bottom-left\\\",\\\"bottom-right\\\",\\\"back\\\",\\\"right\\\",\\\"bottom\\\",\\\"top\\\",\\\"top-left\\\",\\\"top-right\\\",\\\"arrow-left\\\",\\\"arrow-right\\\",\\\"arrow-down\\\",\\\"arrow-up\\\",\\\"d-arrow-left\\\",\\\"d-arrow-right\\\",\\\"video-pause\\\",\\\"video-play\\\",\\\"refresh\\\",\\\"refresh-right\\\",\\\"refresh-left\\\",\\\"finished\\\",\\\"sort\\\",\\\"sort-up\\\",\\\"sort-down\\\",\\\"rank\\\",\\\"loading\\\",\\\"view\\\",\\\"c-scale-to-original\\\",\\\"date\\\",\\\"edit\\\",\\\"edit-outline\\\",\\\"folder\\\",\\\"folder-opened\\\",\\\"folder-add\\\",\\\"folder-remove\\\",\\\"folder-delete\\\",\\\"folder-checked\\\",\\\"tickets\\\",\\\"document-remove\\\",\\\"document-delete\\\",\\\"document-copy\\\",\\\"document-checked\\\",\\\"document\\\",\\\"document-add\\\",\\\"printer\\\",\\\"paperclip\\\",\\\"takeaway-box\\\",\\\"search\\\",\\\"monitor\\\",\\\"attract\\\",\\\"mobile\\\",\\\"scissors\\\",\\\"umbrella\\\",\\\"headset\\\",\\\"brush\\\",\\\"mouse\\\",\\\"coordinate\\\",\\\"magic-stick\\\",\\\"reading\\\",\\\"data-line\\\",\\\"data-board\\\",\\\"pie-chart\\\",\\\"data-analysis\\\",\\\"collection-tag\\\",\\\"film\\\",\\\"suitcase\\\",\\\"suitcase-1\\\",\\\"receiving\\\",\\\"collection\\\",\\\"files\\\",\\\"notebook-1\\\",\\\"notebook-2\\\",\\\"toilet-paper\\\",\\\"office-building\\\",\\\"school\\\",\\\"table-lamp\\\",\\\"house\\\",\\\"no-smoking\\\",\\\"smoking\\\",\\\"shopping-cart-full\\\",\\\"shopping-cart-1\\\",\\\"shopping-cart-2\\\",\\\"shopping-bag-1\\\",\\\"shopping-bag-2\\\",\\\"sold-out\\\",\\\"sell\\\",\\\"present\\\",\\\"box\\\",\\\"bank-card\\\",\\\"money\\\",\\\"coin\\\",\\\"wallet\\\",\\\"discount\\\",\\\"price-tag\\\",\\\"news\\\",\\\"guide\\\",\\\"male\\\",\\\"female\\\",\\\"thumb\\\",\\\"cpu\\\",\\\"link\\\",\\\"connection\\\",\\\"open\\\",\\\"turn-off\\\",\\\"set-up\\\",\\\"chat-round\\\",\\\"chat-line-round\\\",\\\"chat-square\\\",\\\"chat-dot-round\\\",\\\"chat-dot-square\\\",\\\"chat-line-square\\\",\\\"message\\\",\\\"postcard\\\",\\\"position\\\",\\\"turn-off-microphone\\\",\\\"microphone\\\",\\\"close-notification\\\",\\\"bangzhu\\\",\\\"time\\\",\\\"odometer\\\",\\\"crop\\\",\\\"aim\\\",\\\"switch-button\\\",\\\"full-screen\\\",\\\"copy-document\\\",\\\"mic\\\",\\\"stopwatch\\\",\\\"medal-1\\\",\\\"medal\\\",\\\"trophy\\\",\\\"trophy-1\\\",\\\"first-aid-kit\\\",\\\"discover\\\",\\\"place\\\",\\\"location\\\",\\\"location-outline\\\",\\\"location-information\\\",\\\"add-location\\\",\\\"delete-location\\\",\\\"map-location\\\",\\\"alarm-clock\\\",\\\"timer\\\",\\\"watch-1\\\",\\\"watch\\\",\\\"lock\\\",\\\"unlock\\\",\\\"key\\\",\\\"service\\\",\\\"mobile-phone\\\",\\\"bicycle\\\",\\\"truck\\\",\\\"ship\\\",\\\"basketball\\\",\\\"football\\\",\\\"soccer\\\",\\\"baseball\\\",\\\"wind-power\\\",\\\"light-rain\\\",\\\"lightning\\\",\\\"heavy-rain\\\",\\\"sunrise\\\",\\\"sunrise-1\\\",\\\"sunset\\\",\\\"sunny\\\",\\\"cloudy\\\",\\\"partly-cloudy\\\",\\\"cloudy-and-sunny\\\",\\\"moon\\\",\\\"moon-night\\\",\\\"dish\\\",\\\"dish-1\\\",\\\"food\\\",\\\"chicken\\\",\\\"fork-spoon\\\",\\\"knife-fork\\\",\\\"burger\\\",\\\"tableware\\\",\\\"sugar\\\",\\\"dessert\\\",\\\"ice-cream\\\",\\\"hot-water\\\",\\\"water-cup\\\",\\\"coffee-cup\\\",\\\"cold-drink\\\",\\\"goblet\\\",\\\"goblet-full\\\",\\\"goblet-square\\\",\\\"goblet-square-full\\\",\\\"refrigerator\\\",\\\"grape\\\",\\\"watermelon\\\",\\\"cherry\\\",\\\"apple\\\",\\\"pear\\\",\\\"orange\\\",\\\"coffee\\\",\\\"ice-tea\\\",\\\"ice-drink\\\",\\\"milk-tea\\\",\\\"potato-strips\\\",\\\"lollipop\\\",\\\"ice-cream-square\\\",\\\"ice-cream-round\\\"]\");\n\n//# sourceURL=webpack:///./src/utils/icon.json?"); + +/***/ }), + +/***/ "./src/utils/loadBeautifier.js": +/*!*************************************!*\ + !*** ./src/utils/loadBeautifier.js ***! + \*************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = loadBeautifier;\n\nvar _loadScript = _interopRequireDefault(__webpack_require__(/*! ./loadScript */ \"./src/utils/loadScript.js\"));\n\nvar _elementUi = _interopRequireDefault(__webpack_require__(/*! element-ui */ \"./node_modules/element-ui/lib/element-ui.common.js\"));\n\nvar _pluginsConfig = _interopRequireDefault(__webpack_require__(/*! ./pluginsConfig */ \"./src/utils/pluginsConfig.js\"));\n\nvar beautifierObj;\n\nfunction loadBeautifier(cb) {\n var beautifierUrl = _pluginsConfig.default.beautifierUrl;\n\n if (beautifierObj) {\n cb(beautifierObj);\n return;\n }\n\n var loading = _elementUi.default.Loading.service({\n fullscreen: true,\n lock: true,\n text: '格式化资源加载中...',\n spinner: 'el-icon-loading',\n background: 'rgba(255, 255, 255, 0.5)'\n });\n\n (0, _loadScript.default)(beautifierUrl, function () {\n loading.close(); // eslint-disable-next-line no-undef\n\n beautifierObj = beautifier;\n cb(beautifierObj);\n });\n}\n\n//# sourceURL=webpack:///./src/utils/loadBeautifier.js?"); + +/***/ }), + +/***/ "./src/utils/loadMonaco.js": +/*!*********************************!*\ + !*** ./src/utils/loadMonaco.js ***! + \*********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = loadMonaco;\n\nvar _loadScript = _interopRequireDefault(__webpack_require__(/*! ./loadScript */ \"./src/utils/loadScript.js\"));\n\nvar _elementUi = _interopRequireDefault(__webpack_require__(/*! element-ui */ \"./node_modules/element-ui/lib/element-ui.common.js\"));\n\nvar _pluginsConfig = _interopRequireDefault(__webpack_require__(/*! ./pluginsConfig */ \"./src/utils/pluginsConfig.js\"));\n\n// monaco-editor单例\nvar monacoEidtor;\n/**\n * 动态加载monaco-editor cdn资源\n * @param {Function} cb 回调,必填\n */\n\nfunction loadMonaco(cb) {\n if (monacoEidtor) {\n cb(monacoEidtor);\n return;\n }\n\n var vs = _pluginsConfig.default.monacoEditorUrl; // 使用element ui实现加载提示\n\n var loading = _elementUi.default.Loading.service({\n fullscreen: true,\n lock: true,\n text: '编辑器资源初始化中...',\n spinner: 'el-icon-loading',\n background: 'rgba(255, 255, 255, 0.5)'\n });\n\n !window.require && (window.require = {});\n !window.require.paths && (window.require.paths = {});\n window.require.paths.vs = vs;\n (0, _loadScript.default)(\"\".concat(vs, \"/loader.js\"), function () {\n window.require(['vs/editor/editor.main'], function () {\n loading.close();\n monacoEidtor = window.monaco;\n cb(monacoEidtor);\n });\n });\n}\n\n//# sourceURL=webpack:///./src/utils/loadMonaco.js?"); + +/***/ }), + +/***/ "./src/views/bpm/form/formEditor.vue": +/*!*******************************************!*\ + !*** ./src/views/bpm/form/formEditor.vue ***! + \*******************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./formEditor.vue?vue&type=template&id=3df0b122& */ \"./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122&\");\n/* harmony import */ var _formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./formEditor.vue?vue&type=script&lang=js& */ \"./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./formEditor.vue?vue&type=style&index=0&lang=scss& */ \"./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/bpm/form/formEditor.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?"); + +/***/ }), + +/***/ "./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js&": +/*!********************************************************************!*\ + !*** ./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js& ***! + \********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./formEditor.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?"); + +/***/ }), + +/***/ "./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss&": +/*!*****************************************************************************!*\ + !*** ./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss& ***! + \*****************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./formEditor.vue?vue&type=style&index=0&lang=scss& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=style&index=0&lang=scss&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_style_index_0_lang_scss___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?"); + +/***/ }), + +/***/ "./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122&": +/*!**************************************************************************!*\ + !*** ./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122& ***! + \**************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./formEditor.vue?vue&type=template&id=3df0b122& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/form/formEditor.vue?vue&type=template&id=3df0b122&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_formEditor_vue_vue_type_template_id_3df0b122___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/bpm/form/formEditor.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/CodeTypeDialog.vue": +/*!*************************************************!*\ + !*** ./src/views/tool/build/CodeTypeDialog.vue ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true& */ \"./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true&\");\n/* harmony import */ var _CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CodeTypeDialog.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"60e79e86\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/CodeTypeDialog.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/CodeTypeDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js&": +/*!**************************************************************************!*\ + !*** ./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js& ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./CodeTypeDialog.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/CodeTypeDialog.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/CodeTypeDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true&": +/*!********************************************************************************************!*\ + !*** ./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true& ***! + \********************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/CodeTypeDialog.vue?vue&type=template&id=60e79e86&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_CodeTypeDialog_vue_vue_type_template_id_60e79e86_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/CodeTypeDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/DraggableItem.vue": +/*!************************************************!*\ + !*** ./src/views/tool/build/DraggableItem.vue ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableItem.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\nvar render, staticRenderFns\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\n _DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/DraggableItem.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/DraggableItem.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js&": +/*!*************************************************************************!*\ + !*** ./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js& ***! + \*************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./DraggableItem.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/DraggableItem.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_DraggableItem_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/DraggableItem.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/FormDrawer.vue": +/*!*********************************************!*\ + !*** ./src/views/tool/build/FormDrawer.vue ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true& */ \"./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true&\");\n/* harmony import */ var _FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./FormDrawer.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true& */ \"./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"35027ca3\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/FormDrawer.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js&": +/*!**********************************************************************!*\ + !*** ./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js& ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./FormDrawer.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true&": +/*!*******************************************************************************************************!*\ + !*** ./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true& ***! + \*******************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=style&index=0&id=35027ca3&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_style_index_0_id_35027ca3_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true&": +/*!****************************************************************************************!*\ + !*** ./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true& ***! + \****************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/FormDrawer.vue?vue&type=template&id=35027ca3&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_FormDrawer_vue_vue_type_template_id_35027ca3_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/FormDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/IconsDialog.vue": +/*!**********************************************!*\ + !*** ./src/views/tool/build/IconsDialog.vue ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true& */ \"./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true&\");\n/* harmony import */ var _IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./IconsDialog.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true& */ \"./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"9733a8b8\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/IconsDialog.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js&": +/*!***********************************************************************!*\ + !*** ./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js& ***! + \***********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./IconsDialog.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true&": +/*!********************************************************************************************************!*\ + !*** ./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true& ***! + \********************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=style&index=0&id=9733a8b8&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_style_index_0_id_9733a8b8_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true&": +/*!*****************************************************************************************!*\ + !*** ./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true& ***! + \*****************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/IconsDialog.vue?vue&type=template&id=9733a8b8&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_IconsDialog_vue_vue_type_template_id_9733a8b8_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/IconsDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/JsonDrawer.vue": +/*!*********************************************!*\ + !*** ./src/views/tool/build/JsonDrawer.vue ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./JsonDrawer.vue?vue&type=template&id=17550072&scoped=true& */ \"./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true&\");\n/* harmony import */ var _JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./JsonDrawer.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true& */ \"./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"17550072\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/JsonDrawer.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js&": +/*!**********************************************************************!*\ + !*** ./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js& ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./JsonDrawer.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true&": +/*!*******************************************************************************************************!*\ + !*** ./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true& ***! + \*******************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=style&index=0&id=17550072&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_style_index_0_id_17550072_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true&": +/*!****************************************************************************************!*\ + !*** ./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true& ***! + \****************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./JsonDrawer.vue?vue&type=template&id=17550072&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/JsonDrawer.vue?vue&type=template&id=17550072&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_JsonDrawer_vue_vue_type_template_id_17550072_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/JsonDrawer.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/ResourceDialog.vue": +/*!*************************************************!*\ + !*** ./src/views/tool/build/ResourceDialog.vue ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true& */ \"./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true&\");\n/* harmony import */ var _ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ResourceDialog.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true& */ \"./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"1b905544\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/ResourceDialog.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js&": +/*!**************************************************************************!*\ + !*** ./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js& ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./ResourceDialog.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true&": +/*!***********************************************************************************************************!*\ + !*** ./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true& ***! + \***********************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=style&index=0&id=1b905544&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_style_index_0_id_1b905544_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true&": +/*!********************************************************************************************!*\ + !*** ./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true& ***! + \********************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/ResourceDialog.vue?vue&type=template&id=1b905544&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_ResourceDialog_vue_vue_type_template_id_1b905544_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/ResourceDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/RightPanel.vue": +/*!*********************************************!*\ + !*** ./src/views/tool/build/RightPanel.vue ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./RightPanel.vue?vue&type=template&id=377e0596&scoped=true& */ \"./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true&\");\n/* harmony import */ var _RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RightPanel.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true& */ \"./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"377e0596\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/RightPanel.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js&": +/*!**********************************************************************!*\ + !*** ./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js& ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./RightPanel.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true&": +/*!*******************************************************************************************************!*\ + !*** ./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true& ***! + \*******************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=style&index=0&id=377e0596&lang=scss&scoped=true&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_style_index_0_id_377e0596_lang_scss_scoped_true___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true&": +/*!****************************************************************************************!*\ + !*** ./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true& ***! + \****************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./RightPanel.vue?vue&type=template&id=377e0596&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/RightPanel.vue?vue&type=template&id=377e0596&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_RightPanel_vue_vue_type_template_id_377e0596_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/RightPanel.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/TreeNodeDialog.vue": +/*!*************************************************!*\ + !*** ./src/views/tool/build/TreeNodeDialog.vue ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true& */ \"./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true&\");\n/* harmony import */ var _TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TreeNodeDialog.vue?vue&type=script&lang=js& */ \"./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"8fb21d14\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/tool/build/TreeNodeDialog.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/tool/build/TreeNodeDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js&": +/*!**************************************************************************!*\ + !*** ./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js& ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/babel-loader/lib!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./TreeNodeDialog.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/TreeNodeDialog.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/tool/build/TreeNodeDialog.vue?"); + +/***/ }), + +/***/ "./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true&": +/*!********************************************************************************************!*\ + !*** ./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true& ***! + \********************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/tool/build/TreeNodeDialog.vue?vue&type=template&id=8fb21d14&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeNodeDialog_vue_vue_type_template_id_8fb21d14_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/tool/build/TreeNodeDialog.vue?"); + +/***/ }) + +}]); \ No newline at end of file diff --git a/yudao-server/src/main/resources/admin-ui/static/js/6.js b/yudao-server/src/main/resources/admin-ui/static/js/6.js new file mode 100644 index 0000000000..e57bdb753f --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/js/6.js @@ -0,0 +1,360 @@ +(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[6],{ + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/index.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/index.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _userAvatar = _interopRequireDefault(__webpack_require__(/*! ./userAvatar */ \"./src/views/system/user/profile/userAvatar.vue\"));\n\nvar _userInfo = _interopRequireDefault(__webpack_require__(/*! ./userInfo */ \"./src/views/system/user/profile/userInfo.vue\"));\n\nvar _resetPwd = _interopRequireDefault(__webpack_require__(/*! ./resetPwd */ \"./src/views/system/user/profile/resetPwd.vue\"));\n\nvar _userSocial = _interopRequireDefault(__webpack_require__(/*! ./userSocial */ \"./src/views/system/user/profile/userSocial.vue\"));\n\nvar _user = __webpack_require__(/*! @/api/system/user */ \"./src/api/system/user.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n name: \"Profile\",\n components: {\n userAvatar: _userAvatar.default,\n userInfo: _userInfo.default,\n resetPwd: _resetPwd.default,\n userSocial: _userSocial.default\n },\n data: function data() {\n return {\n user: {},\n roleGroup: {},\n postGroup: {},\n activeTab: \"userinfo\"\n };\n },\n created: function created() {\n this.getUser();\n },\n methods: {\n getUser: function getUser() {\n var _this = this;\n\n (0, _user.getUserProfile)().then(function (response) {\n _this.user = response.data;\n });\n },\n setActiveTab: function setActiveTab(activeTab) {\n this.activeTab = activeTab;\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/system/user/profile/index.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js&": +/*!********************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js& ***! + \********************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _user = __webpack_require__(/*! @/api/system/user */ \"./src/api/system/user.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n data: function data() {\n var _this = this;\n\n var equalToPassword = function equalToPassword(rule, value, callback) {\n if (_this.user.newPassword !== value) {\n callback(new Error(\"两次输入的密码不一致\"));\n } else {\n callback();\n }\n };\n\n return {\n test: \"1test\",\n user: {\n oldPassword: undefined,\n newPassword: undefined,\n confirmPassword: undefined\n },\n // 表单校验\n rules: {\n oldPassword: [{\n required: true,\n message: \"旧密码不能为空\",\n trigger: \"blur\"\n }],\n newPassword: [{\n required: true,\n message: \"新密码不能为空\",\n trigger: \"blur\"\n }, {\n min: 6,\n max: 20,\n message: \"长度在 6 到 20 个字符\",\n trigger: \"blur\"\n }],\n confirmPassword: [{\n required: true,\n message: \"确认密码不能为空\",\n trigger: \"blur\"\n }, {\n required: true,\n validator: equalToPassword,\n trigger: \"blur\"\n }]\n }\n };\n },\n methods: {\n submit: function submit() {\n var _this2 = this;\n\n this.$refs[\"form\"].validate(function (valid) {\n if (valid) {\n (0, _user.updateUserPwd)(_this2.user.oldPassword, _this2.user.newPassword).then(function (response) {\n _this2.msgSuccess(\"修改成功\");\n });\n }\n });\n },\n close: function close() {\n this.$store.dispatch(\"tagsView/delView\", this.$route);\n this.$router.push({\n path: \"/index\"\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/system/user/profile/resetPwd.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js&": +/*!**********************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js& ***! + \**********************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _store = _interopRequireDefault(__webpack_require__(/*! @/store */ \"./src/store/index.js\"));\n\nvar _vueCropper = __webpack_require__(/*! vue-cropper */ \"./node_modules/vue-cropper/dist/index.js\");\n\nvar _user = __webpack_require__(/*! @/api/system/user */ \"./src/api/system/user.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n components: {\n VueCropper: _vueCropper.VueCropper\n },\n props: {\n user: {\n type: Object\n }\n },\n data: function data() {\n return {\n // 是否显示弹出层\n open: false,\n // 是否显示cropper\n visible: false,\n // 弹出层标题\n title: \"修改头像\",\n options: {\n img: _store.default.getters.avatar,\n //裁剪图片的地址\n autoCrop: true,\n // 是否默认生成截图框\n autoCropWidth: 200,\n // 默认生成截图框宽度\n autoCropHeight: 200,\n // 默认生成截图框高度\n fixedBox: true // 固定截图框大小 不允许改变\n\n },\n previews: {}\n };\n },\n methods: {\n // 编辑头像\n editCropper: function editCropper() {\n this.open = true;\n },\n // 打开弹出层结束时的回调\n modalOpened: function modalOpened() {\n this.visible = true;\n },\n // 覆盖默认的上传行为\n requestUpload: function requestUpload() {},\n // 向左旋转\n rotateLeft: function rotateLeft() {\n this.$refs.cropper.rotateLeft();\n },\n // 向右旋转\n rotateRight: function rotateRight() {\n this.$refs.cropper.rotateRight();\n },\n // 图片缩放\n changeScale: function changeScale(num) {\n num = num || 1;\n this.$refs.cropper.changeScale(num);\n },\n // 上传预处理\n beforeUpload: function beforeUpload(file) {\n var _this = this;\n\n if (file.type.indexOf(\"image/\") == -1) {\n this.msgError(\"文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。\");\n } else {\n var reader = new FileReader();\n reader.readAsDataURL(file);\n\n reader.onload = function () {\n _this.options.img = reader.result;\n };\n }\n },\n // 上传图片\n uploadImg: function uploadImg() {\n var _this2 = this;\n\n this.$refs.cropper.getCropBlob(function (data) {\n var formData = new FormData();\n formData.append(\"avatarFile\", data);\n (0, _user.uploadAvatar)(formData).then(function (resp) {\n _this2.open = false; // this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;\n\n _store.default.commit('SET_AVATAR', resp.data);\n\n _this2.msgSuccess(\"修改成功\");\n\n _this2.visible = false;\n });\n });\n },\n // 实时预览\n realTime: function realTime(data) {\n this.previews = data;\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js&": +/*!********************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js& ***! + \********************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _user = __webpack_require__(/*! @/api/system/user */ \"./src/api/system/user.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n props: {\n user: {\n type: Object\n }\n },\n data: function data() {\n return {\n // 表单校验\n rules: {\n nickname: [{\n required: true,\n message: \"用户昵称不能为空\",\n trigger: \"blur\"\n }],\n email: [{\n required: true,\n message: \"邮箱地址不能为空\",\n trigger: \"blur\"\n }, {\n type: \"email\",\n message: \"'请输入正确的邮箱地址\",\n trigger: [\"blur\", \"change\"]\n }],\n mobile: [{\n required: true,\n message: \"手机号码不能为空\",\n trigger: \"blur\"\n }, {\n pattern: /^1[3|4|5|6|7|8|9][0-9]\\d{8}$/,\n message: \"请输入正确的手机号码\",\n trigger: \"blur\"\n }]\n }\n };\n },\n methods: {\n submit: function submit() {\n var _this = this;\n\n this.$refs[\"form\"].validate(function (valid) {\n if (valid) {\n (0, _user.updateUserProfile)(_this.user).then(function (response) {\n _this.msgSuccess(\"修改成功\");\n });\n }\n });\n },\n close: function close() {\n this.$store.dispatch(\"tagsView/delView\", this.$route);\n this.$router.push({\n path: \"/index\"\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userInfo.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js&": +/*!**********************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js& ***! + \**********************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n__webpack_require__(/*! core-js/modules/es.regexp.exec.js */ \"./node_modules/core-js/modules/es.regexp.exec.js\");\n\n__webpack_require__(/*! core-js/modules/es.string.replace.js */ \"./node_modules/core-js/modules/es.string.replace.js\");\n\nvar _objectSpread2 = _interopRequireDefault(__webpack_require__(/*! ./node_modules/@babel/runtime/helpers/objectSpread2.js */ \"./node_modules/@babel/runtime/helpers/objectSpread2.js\"));\n\nvar _constants = __webpack_require__(/*! @/utils/constants */ \"./src/utils/constants.js\");\n\nvar _login = __webpack_require__(/*! @/api/login */ \"./src/api/login.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n props: {\n user: {\n type: Object\n },\n getUser: {\n // 刷新用户\n type: Function\n },\n setActiveTab: {\n // 设置激活的\n type: Function\n }\n },\n data: function data() {\n return {};\n },\n computed: {\n socialUsers: function socialUsers() {\n var socialUsers = [];\n\n for (var i in _constants.SystemUserSocialTypeEnum) {\n var socialUser = (0, _objectSpread2.default)({}, _constants.SystemUserSocialTypeEnum[i]);\n socialUsers.push(socialUser);\n\n if (this.user.socialUsers) {\n for (var j in this.user.socialUsers) {\n if (socialUser.type === this.user.socialUsers[j].type) {\n socialUser.unionId = this.user.socialUsers[j].unionId;\n break;\n }\n }\n }\n }\n\n return socialUsers;\n }\n },\n created: function created() {\n var _this = this;\n\n // 社交绑定\n var type = this.$route.query.type;\n var code = this.$route.query.code;\n var state = this.$route.query.state;\n\n if (!code) {\n return;\n }\n\n (0, _login.socialBind)(type, code, state).then(function (resp) {\n _this.msgSuccess(\"绑定成功\");\n\n _this.$router.replace('/user/profile'); // 调用父组件, 刷新\n\n\n _this.getUser();\n\n _this.setActiveTab('userSocial');\n });\n },\n methods: {\n bind: function bind(socialUser) {\n // 计算 redirectUri\n var redirectUri = location.origin + '/user/profile?type=' + socialUser.type; // 进行跳转\n\n (0, _login.socialAuthRedirect)(socialUser.type, encodeURIComponent(redirectUri)).then(function (res) {\n // console.log(res.url);\n window.location.href = res.data;\n });\n },\n unbind: function unbind(socialUser) {\n var _this2 = this;\n\n (0, _login.socialUnbind)(socialUser.type, socialUser.unionId).then(function (resp) {\n _this2.msgSuccess(\"解绑成功\");\n\n socialUser.unionId = undefined;\n });\n },\n close: function close() {\n this.$store.dispatch(\"tagsView/delView\", this.$route);\n this.$router.push({\n path: \"/index\"\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userSocial.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44&": +/*!*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44& ***! + \*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"app-container\" },\n [\n _c(\n \"el-row\",\n { attrs: { gutter: 20 } },\n [\n _c(\n \"el-col\",\n { attrs: { span: 6, xs: 24 } },\n [\n _c(\"el-card\", { staticClass: \"box-card\" }, [\n _c(\n \"div\",\n {\n staticClass: \"clearfix\",\n attrs: { slot: \"header\" },\n slot: \"header\",\n },\n [_c(\"span\", [_vm._v(\"个人信息\")])]\n ),\n _c(\"div\", [\n _c(\n \"div\",\n { staticClass: \"text-center\" },\n [_c(\"userAvatar\", { attrs: { user: _vm.user } })],\n 1\n ),\n _c(\"ul\", { staticClass: \"list-group list-group-striped\" }, [\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"user\" } }),\n _vm._v(\"用户名称 \"),\n _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(_vm._s(_vm.user.username)),\n ]),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"phone\" } }),\n _vm._v(\"手机号码 \"),\n _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(_vm._s(_vm.user.mobile)),\n ]),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"email\" } }),\n _vm._v(\"用户邮箱 \"),\n _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(_vm._s(_vm.user.email)),\n ]),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"tree\" } }),\n _vm._v(\"所属部门 \"),\n _vm.user.dept\n ? _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(_vm._s(_vm.user.dept.name)),\n ])\n : _vm._e(),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"tree\" } }),\n _vm._v(\"所属岗位 \"),\n _vm.user.posts\n ? _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(\n _vm._s(\n _vm.user.posts\n .map(function (post) {\n return post.name\n })\n .join(\",\")\n )\n ),\n ])\n : _vm._e(),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"peoples\" } }),\n _vm._v(\"所属角色 \"),\n _vm.user.roles\n ? _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(\n _vm._s(\n _vm.user.roles\n .map(function (role) {\n return role.name\n })\n .join(\",\")\n )\n ),\n ])\n : _vm._e(),\n ],\n 1\n ),\n _c(\n \"li\",\n { staticClass: \"list-group-item\" },\n [\n _c(\"svg-icon\", { attrs: { \"icon-class\": \"date\" } }),\n _vm._v(\"创建日期 \"),\n _c(\"div\", { staticClass: \"pull-right\" }, [\n _vm._v(_vm._s(_vm.parseTime(_vm.user.createTime))),\n ]),\n ],\n 1\n ),\n ]),\n ]),\n ]),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { span: 18, xs: 24 } },\n [\n _c(\n \"el-card\",\n [\n _c(\n \"div\",\n {\n staticClass: \"clearfix\",\n attrs: { slot: \"header\" },\n slot: \"header\",\n },\n [_c(\"span\", [_vm._v(\"基本资料\")])]\n ),\n _c(\n \"el-tabs\",\n {\n model: {\n value: _vm.activeTab,\n callback: function ($$v) {\n _vm.activeTab = $$v\n },\n expression: \"activeTab\",\n },\n },\n [\n _c(\n \"el-tab-pane\",\n { attrs: { label: \"基本资料\", name: \"userinfo\" } },\n [_c(\"userInfo\", { attrs: { user: _vm.user } })],\n 1\n ),\n _c(\n \"el-tab-pane\",\n { attrs: { label: \"修改密码\", name: \"resetPwd\" } },\n [_c(\"resetPwd\", { attrs: { user: _vm.user } })],\n 1\n ),\n _c(\n \"el-tab-pane\",\n { attrs: { label: \"社交信息\", name: \"userSocial\" } },\n [\n _c(\"userSocial\", {\n attrs: {\n user: _vm.user,\n getUser: _vm.getUser,\n setActiveTab: _vm.setActiveTab,\n },\n }),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/index.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc&": +/*!****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc& ***! + \****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"el-form\",\n {\n ref: \"form\",\n attrs: { model: _vm.user, rules: _vm.rules, \"label-width\": \"80px\" },\n },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"旧密码\", prop: \"oldPassword\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入旧密码\", type: \"password\" },\n model: {\n value: _vm.user.oldPassword,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"oldPassword\", $$v)\n },\n expression: \"user.oldPassword\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"新密码\", prop: \"newPassword\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请输入新密码\", type: \"password\" },\n model: {\n value: _vm.user.newPassword,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"newPassword\", $$v)\n },\n expression: \"user.newPassword\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"确认密码\", prop: \"confirmPassword\" } },\n [\n _c(\"el-input\", {\n attrs: { placeholder: \"请确认密码\", type: \"password\" },\n model: {\n value: _vm.user.confirmPassword,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"confirmPassword\", $$v)\n },\n expression: \"user.confirmPassword\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n [\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\", size: \"mini\" },\n on: { click: _vm.submit },\n },\n [_vm._v(\"保存\")]\n ),\n _c(\n \"el-button\",\n {\n attrs: { type: \"danger\", size: \"mini\" },\n on: { click: _vm.close },\n },\n [_vm._v(\"关闭\")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/resetPwd.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true&": +/*!******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true& ***! + \******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n [\n _c(\n \"div\",\n {\n staticClass: \"user-info-head\",\n on: {\n click: function ($event) {\n return _vm.editCropper()\n },\n },\n },\n [\n _c(\"img\", {\n staticClass: \"img-circle img-lg\",\n attrs: { src: _vm.options.img, title: \"点击上传头像\" },\n }),\n ]\n ),\n _c(\n \"el-dialog\",\n {\n attrs: {\n title: _vm.title,\n visible: _vm.open,\n width: \"800px\",\n \"append-to-body\": \"\",\n },\n on: {\n \"update:visible\": function ($event) {\n _vm.open = $event\n },\n opened: _vm.modalOpened,\n },\n },\n [\n _c(\n \"el-row\",\n [\n _c(\n \"el-col\",\n { style: { height: \"350px\" }, attrs: { xs: 24, md: 12 } },\n [\n _vm.visible\n ? _c(\"vue-cropper\", {\n ref: \"cropper\",\n attrs: {\n img: _vm.options.img,\n info: true,\n autoCrop: _vm.options.autoCrop,\n autoCropWidth: _vm.options.autoCropWidth,\n autoCropHeight: _vm.options.autoCropHeight,\n fixedBox: _vm.options.fixedBox,\n },\n on: { realTime: _vm.realTime },\n })\n : _vm._e(),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { style: { height: \"350px\" }, attrs: { xs: 24, md: 12 } },\n [\n _c(\"div\", { staticClass: \"avatar-upload-preview\" }, [\n _c(\"img\", {\n style: _vm.previews.img,\n attrs: { src: _vm.previews.url },\n }),\n ]),\n ]\n ),\n ],\n 1\n ),\n _c(\"br\"),\n _c(\n \"el-row\",\n [\n _c(\n \"el-col\",\n { attrs: { lg: 2, md: 2 } },\n [\n _c(\n \"el-upload\",\n {\n attrs: {\n action: \"#\",\n \"http-request\": _vm.requestUpload,\n \"show-file-list\": false,\n \"before-upload\": _vm.beforeUpload,\n },\n },\n [\n _c(\"el-button\", { attrs: { size: \"small\" } }, [\n _vm._v(\" 选择 \"),\n _c(\"i\", {\n staticClass: \"el-icon-upload el-icon--right\",\n }),\n ]),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { lg: { span: 1, offset: 2 }, md: 2 } },\n [\n _c(\"el-button\", {\n attrs: { icon: \"el-icon-plus\", size: \"small\" },\n on: {\n click: function ($event) {\n return _vm.changeScale(1)\n },\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { lg: { span: 1, offset: 1 }, md: 2 } },\n [\n _c(\"el-button\", {\n attrs: { icon: \"el-icon-minus\", size: \"small\" },\n on: {\n click: function ($event) {\n return _vm.changeScale(-1)\n },\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { lg: { span: 1, offset: 1 }, md: 2 } },\n [\n _c(\"el-button\", {\n attrs: { icon: \"el-icon-refresh-left\", size: \"small\" },\n on: {\n click: function ($event) {\n return _vm.rotateLeft()\n },\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { lg: { span: 1, offset: 1 }, md: 2 } },\n [\n _c(\"el-button\", {\n attrs: { icon: \"el-icon-refresh-right\", size: \"small\" },\n on: {\n click: function ($event) {\n return _vm.rotateRight()\n },\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-col\",\n { attrs: { lg: { span: 2, offset: 6 }, md: 2 } },\n [\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\", size: \"small\" },\n on: {\n click: function ($event) {\n return _vm.uploadImg()\n },\n },\n },\n [_vm._v(\"提 交\")]\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86&": +/*!****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86& ***! + \****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"el-form\",\n {\n ref: \"form\",\n attrs: { model: _vm.user, rules: _vm.rules, \"label-width\": \"80px\" },\n },\n [\n _c(\n \"el-form-item\",\n { attrs: { label: \"用户昵称\", prop: \"nickName\" } },\n [\n _c(\"el-input\", {\n model: {\n value: _vm.user.nickname,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"nickname\", $$v)\n },\n expression: \"user.nickname\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"手机号码\", prop: \"mobile\" } },\n [\n _c(\"el-input\", {\n attrs: { maxlength: \"11\" },\n model: {\n value: _vm.user.mobile,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"mobile\", $$v)\n },\n expression: \"user.mobile\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"邮箱\", prop: \"email\" } },\n [\n _c(\"el-input\", {\n attrs: { maxlength: \"50\" },\n model: {\n value: _vm.user.email,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"email\", $$v)\n },\n expression: \"user.email\",\n },\n }),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n { attrs: { label: \"性别\" } },\n [\n _c(\n \"el-radio-group\",\n {\n model: {\n value: _vm.user.sex,\n callback: function ($$v) {\n _vm.$set(_vm.user, \"sex\", $$v)\n },\n expression: \"user.sex\",\n },\n },\n [\n _c(\"el-radio\", { attrs: { label: 1 } }, [_vm._v(\"男\")]),\n _c(\"el-radio\", { attrs: { label: 2 } }, [_vm._v(\"女\")]),\n ],\n 1\n ),\n ],\n 1\n ),\n _c(\n \"el-form-item\",\n [\n _c(\n \"el-button\",\n {\n attrs: { type: \"primary\", size: \"mini\" },\n on: { click: _vm.submit },\n },\n [_vm._v(\"保存\")]\n ),\n _c(\n \"el-button\",\n {\n attrs: { type: \"danger\", size: \"mini\" },\n on: { click: _vm.close },\n },\n [_vm._v(\"关闭\")]\n ),\n ],\n 1\n ),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userInfo.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc&": +/*!******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc& ***! + \******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"el-table\",\n { attrs: { data: _vm.socialUsers, \"show-header\": false } },\n [\n _c(\"el-table-column\", {\n attrs: { label: \"社交平台\", align: \"left\", width: \"120\" },\n scopedSlots: _vm._u([\n {\n key: \"default\",\n fn: function (scope) {\n return [\n _c(\"img\", {\n staticStyle: { height: \"20px\", \"vertical-align\": \"middle\" },\n attrs: { src: scope.row.img },\n }),\n _vm._v(\" \" + _vm._s(scope.row.title) + \" \"),\n ]\n },\n },\n ]),\n }),\n _c(\"el-table-column\", {\n attrs: { label: \"操作\", align: \"left\" },\n scopedSlots: _vm._u([\n {\n key: \"default\",\n fn: function (scope) {\n return [\n scope.row.unionId\n ? _c(\n \"div\",\n [\n _vm._v(\" 已绑定 \"),\n _c(\n \"el-button\",\n {\n attrs: { size: \"large\", type: \"text\" },\n on: {\n click: function ($event) {\n return _vm.unbind(scope.row)\n },\n },\n },\n [_vm._v(\"(解绑)\")]\n ),\n ],\n 1\n )\n : _c(\n \"div\",\n [\n _vm._v(\" 未绑定 \"),\n _c(\n \"el-button\",\n {\n attrs: { size: \"large\", type: \"text\" },\n on: {\n click: function ($event) {\n return _vm.bind(scope.row)\n },\n },\n },\n [_vm._v(\"(绑定)\")]\n ),\n ],\n 1\n ),\n ]\n },\n },\n ]),\n }),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userSocial.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss&": +/*!**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss& ***! + \**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".user-info-head[data-v-e81d90b0] {\\n position: relative;\\n display: inline-block;\\n height: 120px;\\n}\\n.user-info-head[data-v-e81d90b0]:hover:after {\\n content: \\\"+\\\";\\n position: absolute;\\n left: 0;\\n right: 0;\\n top: 0;\\n bottom: 0;\\n color: #eee;\\n background: rgba(0, 0, 0, 0.5);\\n font-size: 24px;\\n font-style: normal;\\n -webkit-font-smoothing: antialiased;\\n -moz-osx-font-smoothing: grayscale;\\n cursor: pointer;\\n line-height: 110px;\\n border-radius: 50%;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/vue-cropper/dist/index.js": +/*!************************************************!*\ + !*** ./node_modules/vue-cropper/dist/index.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("!function(t,e){ true?module.exports=e():undefined}(window,function(){return function(t){var e={};function o(n){if(e[n])return e[n].exports;var r=e[n]={i:n,l:!1,exports:{}};return t[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(t,\"__esModule\",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&\"object\"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,\"default\",{enumerable:!0,value:t}),2&e&&\"string\"!=typeof t)for(var r in t)o.d(n,r,function(e){return t[e]}.bind(null,r));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,\"a\",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p=\"\",o(o.s=6)}([function(t,e,o){var n=o(2);\"string\"==typeof n&&(n=[[t.i,n,\"\"]]);var r={hmr:!0,transform:void 0,insertInto:void 0};o(4)(n,r);n.locals&&(t.exports=n.locals)},function(t,e,o){\"use strict\";var n=o(0);o.n(n).a},function(t,e,o){(t.exports=o(3)(!1)).push([t.i,'\\n.vue-cropper[data-v-6dae58fd] {\\n position: relative;\\n width: 100%;\\n height: 100%;\\n box-sizing: border-box;\\n user-select: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n direction: ltr;\\n touch-action: none;\\n text-align: left;\\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC\");\\n}\\n.cropper-box[data-v-6dae58fd],\\n.cropper-box-canvas[data-v-6dae58fd],\\n.cropper-drag-box[data-v-6dae58fd],\\n.cropper-crop-box[data-v-6dae58fd],\\n.cropper-face[data-v-6dae58fd] {\\n position: absolute;\\n top: 0;\\n right: 0;\\n bottom: 0;\\n left: 0;\\n user-select: none;\\n}\\n.cropper-box-canvas img[data-v-6dae58fd] {\\n position: relative;\\n text-align: left;\\n user-select: none;\\n transform: none;\\n max-width: none;\\n max-height: none;\\n}\\n.cropper-box[data-v-6dae58fd] {\\n overflow: hidden;\\n}\\n.cropper-move[data-v-6dae58fd] {\\n cursor: move;\\n}\\n.cropper-crop[data-v-6dae58fd] {\\n cursor: crosshair;\\n}\\n.cropper-modal[data-v-6dae58fd] {\\n background: rgba(0, 0, 0, 0.5);\\n}\\n.cropper-crop-box[data-v-6dae58fd] {\\n /*border: 2px solid #39f;*/\\n}\\n.cropper-view-box[data-v-6dae58fd] {\\n display: block;\\n overflow: hidden;\\n width: 100%;\\n height: 100%;\\n outline: 1px solid #39f;\\n outline-color: rgba(51, 153, 255, 0.75);\\n user-select: none;\\n}\\n.cropper-view-box img[data-v-6dae58fd] {\\n user-select: none;\\n text-align: left;\\n max-width: none;\\n max-height: none;\\n}\\n.cropper-face[data-v-6dae58fd] {\\n top: 0;\\n left: 0;\\n background-color: #fff;\\n opacity: 0.1;\\n}\\n.crop-info[data-v-6dae58fd] {\\n position: absolute;\\n left: 0px;\\n min-width: 65px;\\n text-align: center;\\n color: white;\\n line-height: 20px;\\n background-color: rgba(0, 0, 0, 0.8);\\n font-size: 12px;\\n}\\n.crop-line[data-v-6dae58fd] {\\n position: absolute;\\n display: block;\\n width: 100%;\\n height: 100%;\\n opacity: 0.1;\\n}\\n.line-w[data-v-6dae58fd] {\\n top: -3px;\\n left: 0;\\n height: 5px;\\n cursor: n-resize;\\n}\\n.line-a[data-v-6dae58fd] {\\n top: 0;\\n left: -3px;\\n width: 5px;\\n cursor: w-resize;\\n}\\n.line-s[data-v-6dae58fd] {\\n bottom: -3px;\\n left: 0;\\n height: 5px;\\n cursor: s-resize;\\n}\\n.line-d[data-v-6dae58fd] {\\n top: 0;\\n right: -3px;\\n width: 5px;\\n cursor: e-resize;\\n}\\n.crop-point[data-v-6dae58fd] {\\n position: absolute;\\n width: 8px;\\n height: 8px;\\n opacity: 0.75;\\n background-color: #39f;\\n border-radius: 100%;\\n}\\n.point1[data-v-6dae58fd] {\\n top: -4px;\\n left: -4px;\\n cursor: nw-resize;\\n}\\n.point2[data-v-6dae58fd] {\\n top: -5px;\\n left: 50%;\\n margin-left: -3px;\\n cursor: n-resize;\\n}\\n.point3[data-v-6dae58fd] {\\n top: -4px;\\n right: -4px;\\n cursor: ne-resize;\\n}\\n.point4[data-v-6dae58fd] {\\n top: 50%;\\n left: -4px;\\n margin-top: -3px;\\n cursor: w-resize;\\n}\\n.point5[data-v-6dae58fd] {\\n top: 50%;\\n right: -4px;\\n margin-top: -3px;\\n cursor: e-resize;\\n}\\n.point6[data-v-6dae58fd] {\\n bottom: -5px;\\n left: -4px;\\n cursor: sw-resize;\\n}\\n.point7[data-v-6dae58fd] {\\n bottom: -5px;\\n left: 50%;\\n margin-left: -3px;\\n cursor: s-resize;\\n}\\n.point8[data-v-6dae58fd] {\\n bottom: -5px;\\n right: -4px;\\n cursor: se-resize;\\n}\\n@media screen and (max-width: 500px) {\\n.crop-point[data-v-6dae58fd] {\\n position: absolute;\\n width: 20px;\\n height: 20px;\\n opacity: 0.45;\\n background-color: #39f;\\n border-radius: 100%;\\n}\\n.point1[data-v-6dae58fd] {\\n top: -10px;\\n left: -10px;\\n}\\n.point2[data-v-6dae58fd],\\n .point4[data-v-6dae58fd],\\n .point5[data-v-6dae58fd],\\n .point7[data-v-6dae58fd] {\\n display: none;\\n}\\n.point3[data-v-6dae58fd] {\\n top: -10px;\\n right: -10px;\\n}\\n.point4[data-v-6dae58fd] {\\n top: 0;\\n left: 0;\\n}\\n.point6[data-v-6dae58fd] {\\n bottom: -10px;\\n left: -10px;\\n}\\n.point8[data-v-6dae58fd] {\\n bottom: -10px;\\n right: -10px;\\n}\\n}\\n',\"\"])},function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var o=function(t,e){var o=t[1]||\"\",n=t[3];if(!n)return o;if(e&&\"function\"==typeof btoa){var r=function(t){return\"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,\"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+\" */\"}(n),i=n.sources.map(function(t){return\"/*# sourceURL=\"+n.sourceRoot+t+\" */\"});return[o].concat(i).concat([r]).join(\"\\n\")}return[o].join(\"\\n\")}(e,t);return e[2]?\"@media \"+e[2]+\"{\"+o+\"}\":o}).join(\"\")},e.i=function(t,o){\"string\"==typeof t&&(t=[[null,t,\"\"]]);for(var n={},r=0;r=0&&c.splice(e,1)}function f(t){var e=document.createElement(\"style\");if(void 0===t.attrs.type&&(t.attrs.type=\"text/css\"),void 0===t.attrs.nonce){var n=function(){0;return o.nc}();n&&(t.attrs.nonce=n)}return g(e,t.attrs),d(t,e),e}function g(t,e){Object.keys(e).forEach(function(o){t.setAttribute(o,e[o])})}function v(t,e){var o,n,r,i;if(e.transform&&t.css){if(!(i=\"function\"==typeof e.transform?e.transform(t.css):e.transform.default(t.css)))return function(){};t.css=i}if(e.singleton){var c=a++;o=s||(s=f(e)),n=w.bind(null,o,c,!1),r=w.bind(null,o,c,!0)}else t.sourceMap&&\"function\"==typeof URL&&\"function\"==typeof URL.createObjectURL&&\"function\"==typeof URL.revokeObjectURL&&\"function\"==typeof Blob&&\"function\"==typeof btoa?(o=function(t){var e=document.createElement(\"link\");return void 0===t.attrs.type&&(t.attrs.type=\"text/css\"),t.attrs.rel=\"stylesheet\",g(e,t.attrs),d(t,e),e}(e),n=function(t,e,o){var n=o.css,r=o.sourceMap,i=void 0===e.convertToAbsoluteUrls&&r;(e.convertToAbsoluteUrls||i)&&(n=h(n));r&&(n+=\"\\n/*# sourceMappingURL=data:application/json;base64,\"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+\" */\");var s=new Blob([n],{type:\"text/css\"}),a=t.href;t.href=URL.createObjectURL(s),a&&URL.revokeObjectURL(a)}.bind(null,o,e),r=function(){l(o),o.href&&URL.revokeObjectURL(o.href)}):(o=f(e),n=function(t,e){var o=e.css,n=e.media;n&&t.setAttribute(\"media\",n);if(t.styleSheet)t.styleSheet.cssText=o;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(o))}}.bind(null,o),r=function(){l(o)});return n(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;n(t=e)}else r()}}t.exports=function(t,e){if(\"undefined\"!=typeof DEBUG&&DEBUG&&\"object\"!=typeof document)throw new Error(\"The style-loader cannot be used in a non-browser environment\");(e=e||{}).attrs=\"object\"==typeof e.attrs?e.attrs:{},e.singleton||\"boolean\"==typeof e.singleton||(e.singleton=r()),e.insertInto||(e.insertInto=\"head\"),e.insertAt||(e.insertAt=\"bottom\");var o=u(t,e);return p(o,e),function(t){for(var r=[],i=0;i=8&&(a=o+n)));if(a)for(u=p.getUint16(a,r),h=0;h21?\"-21px\":\"0px\",t.width=this.cropW>0?this.cropW:0,t.height=this.cropH>0?this.cropH:0,this.infoTrue){var e=1;this.high&&!this.full&&(e=window.devicePixelRatio),1!==this.enlarge&!this.full&&(e=Math.abs(Number(this.enlarge))),t.width=t.width*e,t.height=t.height*e,this.full&&(t.width=t.width/this.scale,t.height=t.height/this.scale)}return t.width=t.width.toFixed(0),t.height=t.height.toFixed(0),t},isIE:function(){navigator.userAgent;var t=!!window.ActiveXObject||\"ActiveXObject\"in window;return t},passive:function(){return this.isIE?null:{passive:!1}}},watch:{img:function(){this.checkedImg()},imgs:function(t){\"\"!==t&&this.reload()},cropW:function(){this.showPreview()},cropH:function(){this.showPreview()},cropOffsertX:function(){this.showPreview()},cropOffsertY:function(){this.showPreview()},scale:function(t,e){this.showPreview()},x:function(){this.showPreview()},y:function(){this.showPreview()},autoCrop:function(t){t&&this.goAutoCrop()},autoCropWidth:function(){this.autoCrop&&this.goAutoCrop()},autoCropHeight:function(){this.autoCrop&&this.goAutoCrop()},mode:function(){this.checkedImg()},rotate:function(){this.showPreview(),this.autoCrop?this.goAutoCrop(this.cropW,this.cropH):(this.cropW>0||this.cropH>0)&&this.goAutoCrop(this.cropW,this.cropH)}},methods:{getVersion:function(t){for(var e=navigator.userAgent.split(\" \"),o=\"\",n=new RegExp(t,\"i\"),r=0;r=81)e=-1;else if(this.getVersion(\"safari\")[0]>=605){var i=this.getVersion(\"version\");i[0]>13&&i[1]>1&&(e=-1)}else{var s=navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?) like mac os/);if(s){var a=s[1];((a=a.split(\"_\"))[0]>13||a[0]>=13&&a[1]>=4)&&(e=-1)}}var c=document.createElement(\"canvas\"),h=c.getContext(\"2d\");switch(h.save(),e){case 2:c.width=o,c.height=n,h.translate(o,0),h.scale(-1,1);break;case 3:c.width=o,c.height=n,h.translate(o/2,n/2),h.rotate(180*Math.PI/180),h.translate(-o/2,-n/2);break;case 4:c.width=o,c.height=n,h.translate(0,n),h.scale(1,-1);break;case 5:c.height=o,c.width=n,h.rotate(.5*Math.PI),h.scale(1,-1);break;case 6:c.width=n,c.height=o,h.translate(n/2,o/2),h.rotate(90*Math.PI/180),h.translate(-o/2,-n/2);break;case 7:c.height=o,c.width=n,h.rotate(.5*Math.PI),h.translate(o,-n),h.scale(-1,1);break;case 8:c.height=o,c.width=n,h.translate(n/2,o/2),h.rotate(-90*Math.PI/180),h.translate(-o/2,-n/2);break;default:c.width=o,c.height=n}h.drawImage(t,0,0,o,n),h.restore(),c.toBlob(function(t){var e=URL.createObjectURL(t);URL.revokeObjectURL(r.imgs),r.imgs=e},\"image/\"+this.outputType,1)},checkedImg:function(){var t=this;if(null===this.img||\"\"===this.img)return this.imgs=\"\",void this.clearCrop();this.loading=!0,this.scale=1,this.rotate=0,this.clearCrop();var e=new Image;if(e.onload=function(){if(\"\"===t.img)return t.$emit(\"imgLoad\",\"error\"),t.$emit(\"img-load\",\"error\"),!1;var o=e.width,n=e.height;i.getData(e).then(function(r){t.orientation=r.orientation||1;var i=t.maxImgSize;!t.orientation&&oi&&(n=n/o*i,o=i),n>i&&(o=o/n*i,n=i),t.checkOrientationImage(e,t.orientation,o,n))})},e.onerror=function(){t.$emit(\"imgLoad\",\"error\"),t.$emit(\"img-load\",\"error\")},\"data\"!==this.img.substr(0,4)&&(e.crossOrigin=\"\"),this.isIE){var o=new XMLHttpRequest;o.onload=function(){var t=URL.createObjectURL(this.response);e.src=t},o.open(\"GET\",this.img,!0),o.responseType=\"blob\",o.send()}else e.src=this.img},startMove:function(t){if(t.preventDefault(),this.move&&!this.crop){if(!this.canMove)return!1;this.moveX=(t.clientX?t.clientX:t.touches[0].clientX)-this.x,this.moveY=(t.clientY?t.clientY:t.touches[0].clientY)-this.y,t.touches?(window.addEventListener(\"touchmove\",this.moveImg),window.addEventListener(\"touchend\",this.leaveImg),2==t.touches.length&&(this.touches=t.touches,window.addEventListener(\"touchmove\",this.touchScale),window.addEventListener(\"touchend\",this.cancelTouchScale))):(window.addEventListener(\"mousemove\",this.moveImg),window.addEventListener(\"mouseup\",this.leaveImg)),this.$emit(\"imgMoving\",{moving:!0,axis:this.getImgAxis()}),this.$emit(\"img-moving\",{moving:!0,axis:this.getImgAxis()})}else this.cropping=!0,window.addEventListener(\"mousemove\",this.createCrop),window.addEventListener(\"mouseup\",this.endCrop),window.addEventListener(\"touchmove\",this.createCrop),window.addEventListener(\"touchend\",this.endCrop),this.cropOffsertX=t.offsetX?t.offsetX:t.touches[0].pageX-this.$refs.cropper.offsetLeft,this.cropOffsertY=t.offsetY?t.offsetY:t.touches[0].pageY-this.$refs.cropper.offsetTop,this.cropX=t.clientX?t.clientX:t.touches[0].clientX,this.cropY=t.clientY?t.clientY:t.touches[0].clientY,this.cropChangeX=this.cropOffsertX,this.cropChangeY=this.cropOffsertY,this.cropW=0,this.cropH=0},touchScale:function(t){var e=this;t.preventDefault();var o=this.scale,n=this.touches[0].clientX,r=this.touches[0].clientY,i=t.touches[0].clientX,s=t.touches[0].clientY,a=this.touches[1].clientX,c=this.touches[1].clientY,h=t.touches[1].clientX,p=t.touches[1].clientY,u=Math.sqrt(Math.pow(n-a,2)+Math.pow(r-c,2)),d=Math.sqrt(Math.pow(i-h,2)+Math.pow(s-p,2))-u,l=1,f=(l=(l=l/this.trueWidth>l/this.trueHeight?l/this.trueHeight:l/this.trueWidth)>.1?.1:l)*d;if(!this.touchNow){if(this.touchNow=!0,d>0?o+=Math.abs(f):d<0&&o>Math.abs(f)&&(o-=Math.abs(f)),this.touches=t.touches,setTimeout(function(){e.touchNow=!1},8),!this.checkoutImgAxis(this.x,this.y,o))return!1;this.scale=o}},cancelTouchScale:function(t){window.removeEventListener(\"touchmove\",this.touchScale)},moveImg:function(t){var e=this;if(t.preventDefault(),t.touches&&2===t.touches.length)return this.touches=t.touches,window.addEventListener(\"touchmove\",this.touchScale),window.addEventListener(\"touchend\",this.cancelTouchScale),window.removeEventListener(\"touchmove\",this.moveImg),!1;var o,n,r=t.clientX?t.clientX:t.touches[0].clientX,i=t.clientY?t.clientY:t.touches[0].clientY;o=r-this.moveX,n=i-this.moveY,this.$nextTick(function(){if(e.centerBox){var t,r,i,s,a=e.getImgAxis(o,n,e.scale),c=e.getCropAxis(),h=e.trueHeight*e.scale,p=e.trueWidth*e.scale;switch(e.rotate){case 1:case-1:case 3:case-3:t=e.cropOffsertX-e.trueWidth*(1-e.scale)/2+(h-p)/2,r=e.cropOffsertY-e.trueHeight*(1-e.scale)/2+(p-h)/2,i=t-h+e.cropW,s=r-p+e.cropH;break;default:t=e.cropOffsertX-e.trueWidth*(1-e.scale)/2,r=e.cropOffsertY-e.trueHeight*(1-e.scale)/2,i=t-p+e.cropW,s=r-h+e.cropH}a.x1>=c.x1&&(o=t),a.y1>=c.y1&&(n=r),a.x2<=c.x2&&(o=i),a.y2<=c.y2&&(n=s)}e.x=o,e.y=n,e.$emit(\"imgMoving\",{moving:!0,axis:e.getImgAxis()}),e.$emit(\"img-moving\",{moving:!0,axis:e.getImgAxis()})})},leaveImg:function(t){window.removeEventListener(\"mousemove\",this.moveImg),window.removeEventListener(\"touchmove\",this.moveImg),window.removeEventListener(\"mouseup\",this.leaveImg),window.removeEventListener(\"touchend\",this.leaveImg),this.$emit(\"imgMoving\",{moving:!1,axis:this.getImgAxis()}),this.$emit(\"img-moving\",{moving:!1,axis:this.getImgAxis()})},scaleImg:function(){this.canScale&&window.addEventListener(this.support,this.changeSize,this.passive)},cancelScale:function(){this.canScale&&window.removeEventListener(this.support,this.changeSize)},changeSize:function(t){var e=this;t.preventDefault();var o=this.scale,n=t.deltaY||t.wheelDelta;n=navigator.userAgent.indexOf(\"Firefox\")>0?30*n:n,this.isIE&&(n=-n);var r=this.coe,i=(r=r/this.trueWidth>r/this.trueHeight?r/this.trueHeight:r/this.trueWidth)*n;i<0?o+=Math.abs(i):o>Math.abs(i)&&(o-=Math.abs(i));var s=i<0?\"add\":\"reduce\";if(s!==this.coeStatus&&(this.coeStatus=s,this.coe=.2),this.scaling||(this.scalingSet=setTimeout(function(){e.scaling=!1,e.coe=e.coe+=.01},50)),this.scaling=!0,!this.checkoutImgAxis(this.x,this.y,o))return!1;this.scale=o},changeScale:function(t){var e=this.scale;t=t||1;var o=20;if((t*=o=o/this.trueWidth>o/this.trueHeight?o/this.trueHeight:o/this.trueWidth)>0?e+=Math.abs(t):e>Math.abs(t)&&(e-=Math.abs(t)),!this.checkoutImgAxis(this.x,this.y,e))return!1;this.scale=e},createCrop:function(t){var e=this;t.preventDefault();var o=t.clientX?t.clientX:t.touches?t.touches[0].clientX:0,n=t.clientY?t.clientY:t.touches?t.touches[0].clientY:0;this.$nextTick(function(){var t=o-e.cropX,r=n-e.cropY;if(t>0?(e.cropW=t+e.cropChangeX>e.w?e.w-e.cropChangeX:t,e.cropOffsertX=e.cropChangeX):(e.cropW=e.w-e.cropChangeX+Math.abs(t)>e.w?e.cropChangeX:Math.abs(t),e.cropOffsertX=e.cropChangeX+t>0?e.cropChangeX+t:0),e.fixed){var i=e.cropW/e.fixedNumber[0]*e.fixedNumber[1];i+e.cropOffsertY>e.h?(e.cropH=e.h-e.cropOffsertY,e.cropW=e.cropH/e.fixedNumber[1]*e.fixedNumber[0],e.cropOffsertX=t>0?e.cropChangeX:e.cropChangeX-e.cropW):e.cropH=i,e.cropOffsertY=e.cropOffsertY}else r>0?(e.cropH=r+e.cropChangeY>e.h?e.h-e.cropChangeY:r,e.cropOffsertY=e.cropChangeY):(e.cropH=e.h-e.cropChangeY+Math.abs(r)>e.h?e.cropChangeY:Math.abs(r),e.cropOffsertY=e.cropChangeY+r>0?e.cropChangeY+r:0)})},changeCropSize:function(t,e,o,n,r){t.preventDefault(),window.addEventListener(\"mousemove\",this.changeCropNow),window.addEventListener(\"mouseup\",this.changeCropEnd),window.addEventListener(\"touchmove\",this.changeCropNow),window.addEventListener(\"touchend\",this.changeCropEnd),this.canChangeX=e,this.canChangeY=o,this.changeCropTypeX=n,this.changeCropTypeY=r,this.cropX=t.clientX?t.clientX:t.touches[0].clientX,this.cropY=t.clientY?t.clientY:t.touches[0].clientY,this.cropOldW=this.cropW,this.cropOldH=this.cropH,this.cropChangeX=this.cropOffsertX,this.cropChangeY=this.cropOffsertY,this.fixed&&this.canChangeX&&this.canChangeY&&(this.canChangeY=0),this.$emit(\"change-crop-size\",{width:this.cropW,height:this.cropH})},changeCropNow:function(t){var e=this;t.preventDefault();var o=t.clientX?t.clientX:t.touches?t.touches[0].clientX:0,n=t.clientY?t.clientY:t.touches?t.touches[0].clientY:0,r=this.w,i=this.h,s=0,a=0;if(this.centerBox){var c=this.getImgAxis(),h=c.x2,p=c.y2;s=c.x1>0?c.x1:0,a=c.y1>0?c.y1:0,r>h&&(r=h),i>p&&(i=p)}this.$nextTick(function(){var t=o-e.cropX,c=n-e.cropY;if(e.canChangeX&&(1===e.changeCropTypeX?e.cropOldW-t>0?(e.cropW=r-e.cropChangeX-t<=r-s?e.cropOldW-t:e.cropOldW+e.cropChangeX-s,e.cropOffsertX=r-e.cropChangeX-t<=r-s?e.cropChangeX+t:s):(e.cropW=Math.abs(t)+e.cropChangeX<=r?Math.abs(t)-e.cropOldW:r-e.cropOldW-e.cropChangeX,e.cropOffsertX=e.cropChangeX+e.cropOldW):2===e.changeCropTypeX&&(e.cropOldW+t>0?(e.cropW=e.cropOldW+t+e.cropOffsertX<=r?e.cropOldW+t:r-e.cropOffsertX,e.cropOffsertX=e.cropChangeX):(e.cropW=r-e.cropChangeX+Math.abs(t+e.cropOldW)<=r-s?Math.abs(t+e.cropOldW):e.cropChangeX-s,e.cropOffsertX=r-e.cropChangeX+Math.abs(t+e.cropOldW)<=r-s?e.cropChangeX-Math.abs(t+e.cropOldW):s))),e.canChangeY&&(1===e.changeCropTypeY?e.cropOldH-c>0?(e.cropH=i-e.cropChangeY-c<=i-a?e.cropOldH-c:e.cropOldH+e.cropChangeY-a,e.cropOffsertY=i-e.cropChangeY-c<=i-a?e.cropChangeY+c:a):(e.cropH=Math.abs(c)+e.cropChangeY<=i?Math.abs(c)-e.cropOldH:i-e.cropOldH-e.cropChangeY,e.cropOffsertY=e.cropChangeY+e.cropOldH):2===e.changeCropTypeY&&(e.cropOldH+c>0?(e.cropH=e.cropOldH+c+e.cropOffsertY<=i?e.cropOldH+c:i-e.cropOffsertY,e.cropOffsertY=e.cropChangeY):(e.cropH=i-e.cropChangeY+Math.abs(c+e.cropOldH)<=i-a?Math.abs(c+e.cropOldH):e.cropChangeY-a,e.cropOffsertY=i-e.cropChangeY+Math.abs(c+e.cropOldH)<=i-a?e.cropChangeY-Math.abs(c+e.cropOldH):a))),e.canChangeX&&e.fixed){var h=e.cropW/e.fixedNumber[0]*e.fixedNumber[1];h+e.cropOffsertY>i?(e.cropH=i-e.cropOffsertY,e.cropW=e.cropH/e.fixedNumber[1]*e.fixedNumber[0]):e.cropH=h}if(e.canChangeY&&e.fixed){var p=e.cropH/e.fixedNumber[1]*e.fixedNumber[0];p+e.cropOffsertX>r?(e.cropW=r-e.cropOffsertX,e.cropH=e.cropW/e.fixedNumber[0]*e.fixedNumber[1]):e.cropW=p}})},checkCropLimitSize:function(){this.cropW,this.cropH;var t=this.limitMinSize,e=new Array;return e=Array.isArray[t]?t:[t,t],[parseFloat(e[0]),parseFloat(e[1])]},changeCropEnd:function(t){window.removeEventListener(\"mousemove\",this.changeCropNow),window.removeEventListener(\"mouseup\",this.changeCropEnd),window.removeEventListener(\"touchmove\",this.changeCropNow),window.removeEventListener(\"touchend\",this.changeCropEnd)},endCrop:function(){0===this.cropW&&0===this.cropH&&(this.cropping=!1),window.removeEventListener(\"mousemove\",this.createCrop),window.removeEventListener(\"mouseup\",this.endCrop),window.removeEventListener(\"touchmove\",this.createCrop),window.removeEventListener(\"touchend\",this.endCrop)},startCrop:function(){this.crop=!0},stopCrop:function(){this.crop=!1},clearCrop:function(){this.cropping=!1,this.cropW=0,this.cropH=0},cropMove:function(t){if(t.preventDefault(),!this.canMoveBox)return this.crop=!1,this.startMove(t),!1;if(t.touches&&2===t.touches.length)return this.crop=!1,this.startMove(t),this.leaveCrop(),!1;window.addEventListener(\"mousemove\",this.moveCrop),window.addEventListener(\"mouseup\",this.leaveCrop),window.addEventListener(\"touchmove\",this.moveCrop),window.addEventListener(\"touchend\",this.leaveCrop);var e,o,n=t.clientX?t.clientX:t.touches[0].clientX,r=t.clientY?t.clientY:t.touches[0].clientY;e=n-this.cropOffsertX,o=r-this.cropOffsertY,this.cropX=e,this.cropY=o,this.$emit(\"cropMoving\",{moving:!0,axis:this.getCropAxis()}),this.$emit(\"crop-moving\",{moving:!0,axis:this.getCropAxis()})},moveCrop:function(t,e){var o=this,n=0,r=0;t&&(t.preventDefault(),n=t.clientX?t.clientX:t.touches[0].clientX,r=t.clientY?t.clientY:t.touches[0].clientY),this.$nextTick(function(){var t,i,s=n-o.cropX,a=r-o.cropY;if(e&&(s=o.cropOffsertX,a=o.cropOffsertY),t=s<=0?0:s+o.cropW>o.w?o.w-o.cropW:s,i=a<=0?0:a+o.cropH>o.h?o.h-o.cropH:a,o.centerBox){var c=o.getImgAxis();t<=c.x1&&(t=c.x1),t+o.cropW>c.x2&&(t=c.x2-o.cropW),i<=c.y1&&(i=c.y1),i+o.cropH>c.y2&&(i=c.y2-o.cropH)}o.cropOffsertX=t,o.cropOffsertY=i,o.$emit(\"cropMoving\",{moving:!0,axis:o.getCropAxis()}),o.$emit(\"crop-moving\",{moving:!0,axis:o.getCropAxis()})})},getImgAxis:function(t,e,o){t=t||this.x,e=e||this.y,o=o||this.scale;var n={x1:0,x2:0,y1:0,y2:0},r=this.trueWidth*o,i=this.trueHeight*o;switch(this.rotate){case 0:n.x1=t+this.trueWidth*(1-o)/2,n.x2=n.x1+this.trueWidth*o,n.y1=e+this.trueHeight*(1-o)/2,n.y2=n.y1+this.trueHeight*o;break;case 1:case-1:case 3:case-3:n.x1=t+this.trueWidth*(1-o)/2+(r-i)/2,n.x2=n.x1+this.trueHeight*o,n.y1=e+this.trueHeight*(1-o)/2+(i-r)/2,n.y2=n.y1+this.trueWidth*o;break;default:n.x1=t+this.trueWidth*(1-o)/2,n.x2=n.x1+this.trueWidth*o,n.y1=e+this.trueHeight*(1-o)/2,n.y2=n.y1+this.trueHeight*o}return n},getCropAxis:function(){var t={x1:0,x2:0,y1:0,y2:0};return t.x1=this.cropOffsertX,t.x2=t.x1+this.cropW,t.y1=this.cropOffsertY,t.y2=t.y1+this.cropH,t},leaveCrop:function(t){window.removeEventListener(\"mousemove\",this.moveCrop),window.removeEventListener(\"mouseup\",this.leaveCrop),window.removeEventListener(\"touchmove\",this.moveCrop),window.removeEventListener(\"touchend\",this.leaveCrop),this.$emit(\"cropMoving\",{moving:!1,axis:this.getCropAxis()}),this.$emit(\"crop-moving\",{moving:!1,axis:this.getCropAxis()})},getCropChecked:function(t){var e=this,o=document.createElement(\"canvas\"),n=new Image,r=this.rotate,i=this.trueWidth,s=this.trueHeight,a=this.cropOffsertX,c=this.cropOffsertY;function h(t,e){o.width=Math.round(t),o.height=Math.round(e)}n.onload=function(){if(0!==e.cropW){var p=o.getContext(\"2d\"),u=1;e.high&!e.full&&(u=window.devicePixelRatio),1!==e.enlarge&!e.full&&(u=Math.abs(Number(e.enlarge)));var d=e.cropW*u,l=e.cropH*u,f=i*e.scale*u,g=s*e.scale*u,v=(e.x-a+e.trueWidth*(1-e.scale)/2)*u,m=(e.y-c+e.trueHeight*(1-e.scale)/2)*u;switch(h(d,l),p.save(),r){case 0:e.full?(h(d/e.scale,l/e.scale),p.drawImage(n,v/e.scale,m/e.scale,f/e.scale,g/e.scale)):p.drawImage(n,v,m,f,g);break;case 1:case-3:e.full?(h(d/e.scale,l/e.scale),v=v/e.scale+(f/e.scale-g/e.scale)/2,m=m/e.scale+(g/e.scale-f/e.scale)/2,p.rotate(90*r*Math.PI/180),p.drawImage(n,m,-v-g/e.scale,f/e.scale,g/e.scale)):(v+=(f-g)/2,m+=(g-f)/2,p.rotate(90*r*Math.PI/180),p.drawImage(n,m,-v-g,f,g));break;case 2:case-2:e.full?(h(d/e.scale,l/e.scale),p.rotate(90*r*Math.PI/180),v/=e.scale,m/=e.scale,p.drawImage(n,-v-f/e.scale,-m-g/e.scale,f/e.scale,g/e.scale)):(p.rotate(90*r*Math.PI/180),p.drawImage(n,-v-f,-m-g,f,g));break;case 3:case-1:e.full?(h(d/e.scale,l/e.scale),v=v/e.scale+(f/e.scale-g/e.scale)/2,m=m/e.scale+(g/e.scale-f/e.scale)/2,p.rotate(90*r*Math.PI/180),p.drawImage(n,-m-f/e.scale,v,f/e.scale,g/e.scale)):(v+=(f-g)/2,m+=(g-f)/2,p.rotate(90*r*Math.PI/180),p.drawImage(n,-m-f,v,f,g));break;default:e.full?(h(d/e.scale,l/e.scale),p.drawImage(n,v/e.scale,m/e.scale,f/e.scale,g/e.scale)):p.drawImage(n,v,m,f,g)}p.restore()}else{var w=i*e.scale,x=s*e.scale,C=o.getContext(\"2d\");switch(C.save(),r){case 0:h(w,x),C.drawImage(n,0,0,w,x);break;case 1:case-3:h(x,w),C.rotate(90*r*Math.PI/180),C.drawImage(n,0,-x,w,x);break;case 2:case-2:h(w,x),C.rotate(90*r*Math.PI/180),C.drawImage(n,-w,-x,w,x);break;case 3:case-1:h(x,w),C.rotate(90*r*Math.PI/180),C.drawImage(n,-w,0,w,x);break;default:h(w,x),C.drawImage(n,0,0,w,x)}C.restore()}t(o)},\"data\"!==this.img.substr(0,4)&&(n.crossOrigin=\"Anonymous\"),n.src=this.imgs},getCropData:function(t){var e=this;this.getCropChecked(function(o){t(o.toDataURL(\"image/\"+e.outputType,e.outputSize))})},getCropBlob:function(t){var e=this;this.getCropChecked(function(o){o.toBlob(function(e){return t(e)},\"image/\"+e.outputType,e.outputSize)})},showPreview:function(){var t=this;if(!this.isCanShow)return!1;this.isCanShow=!1,setTimeout(function(){t.isCanShow=!0},16);var e=this.cropW,o=this.cropH,n=this.scale,r={};r.div={width:\"\".concat(e,\"px\"),height:\"\".concat(o,\"px\")};var i=(this.x-this.cropOffsertX)/n,s=(this.y-this.cropOffsertY)/n;r.w=e,r.h=o,r.url=this.imgs,r.img={width:\"\".concat(this.trueWidth,\"px\"),height:\"\".concat(this.trueHeight,\"px\"),transform:\"scale(\".concat(n,\")translate3d(\").concat(i,\"px, \").concat(s,\"px, \").concat(0,\"px)rotateZ(\").concat(90*this.rotate,\"deg)\")},r.html='\\n
\\n
\\n \\n
\\n
'),this.$emit(\"realTime\",r),this.$emit(\"real-time\",r)},reload:function(){var t=this,e=new Image;e.onload=function(){t.w=parseFloat(window.getComputedStyle(t.$refs.cropper).width),t.h=parseFloat(window.getComputedStyle(t.$refs.cropper).height),t.trueWidth=e.width,t.trueHeight=e.height,t.original?t.scale=1:t.scale=t.checkedMode(),t.$nextTick(function(){t.x=-(t.trueWidth-t.trueWidth*t.scale)/2+(t.w-t.trueWidth*t.scale)/2,t.y=-(t.trueHeight-t.trueHeight*t.scale)/2+(t.h-t.trueHeight*t.scale)/2,t.loading=!1,t.autoCrop&&t.goAutoCrop(),t.$emit(\"img-load\",\"success\"),t.$emit(\"imgLoad\",\"success\"),setTimeout(function(){t.showPreview()},20)})},e.onerror=function(){t.$emit(\"imgLoad\",\"error\"),t.$emit(\"img-load\",\"error\")},e.src=this.imgs},checkedMode:function(){var t=1,e=(this.trueWidth,this.trueHeight),o=this.mode.split(\" \");switch(o[0]){case\"contain\":this.trueWidth>this.w&&(t=this.w/this.trueWidth),this.trueHeight*t>this.h&&(t=this.h/this.trueHeight);break;case\"cover\":(e*=t=this.w/this.trueWidth)o?o:s,a=a>n?n:a,this.fixed&&(a=s/this.fixedNumber[0]*this.fixedNumber[1]),a>this.h&&(s=(a=this.h)/this.fixedNumber[1]*this.fixedNumber[0]),this.changeCrop(s,a)}},changeCrop:function(t,e){var o=this;if(this.centerBox){var n=this.getImgAxis();t>n.x2-n.x1&&(e=(t=n.x2-n.x1)/this.fixedNumber[0]*this.fixedNumber[1]),e>n.y2-n.y1&&(t=(e=n.y2-n.y1)/this.fixedNumber[1]*this.fixedNumber[0])}this.cropW=t,this.cropH=e,this.checkCropLimitSize(),this.$nextTick(function(){o.cropOffsertX=(o.w-o.cropW)/2,o.cropOffsertY=(o.h-o.cropH)/2,o.centerBox&&o.moveCrop(null,!0)})},refresh:function(){var t=this;this.img;this.imgs=\"\",this.scale=1,this.crop=!1,this.rotate=0,this.w=0,this.h=0,this.trueWidth=0,this.trueHeight=0,this.clearCrop(),this.$nextTick(function(){t.checkedImg()})},rotateLeft:function(){this.rotate=this.rotate<=-3?0:this.rotate-1},rotateRight:function(){this.rotate=this.rotate>=3?0:this.rotate+1},rotateClear:function(){this.rotate=0},checkoutImgAxis:function(t,e,o){t=t||this.x,e=e||this.y,o=o||this.scale;var n=!0;if(this.centerBox){var r=this.getImgAxis(t,e,o),i=this.getCropAxis();r.x1>=i.x1&&(n=!1),r.x2<=i.x2&&(n=!1),r.y1>=i.y1&&(n=!1),r.y2<=i.y2&&(n=!1)}return n}},mounted:function(){this.support=\"onwheel\"in document.createElement(\"div\")?\"wheel\":void 0!==document.onmousewheel?\"mousewheel\":\"DOMMouseScroll\";var t=this,e=navigator.userAgent;this.isIOS=!!e.match(/\\(i[^;]+;( U;)? CPU.+Mac OS X/),HTMLCanvasElement.prototype.toBlob||Object.defineProperty(HTMLCanvasElement.prototype,\"toBlob\",{value:function(e,o,n){for(var r=atob(this.toDataURL(o,n).split(\",\")[1]),i=r.length,s=new Uint8Array(i),a=0;a tag\n\n// load the styles\nvar content = __webpack_require__(/*! !../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss& */ \"./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss&\");\nif(content.__esModule) content = content.default;\nif(typeof content === 'string') content = [[module.i, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar add = __webpack_require__(/*! ../../../../../node_modules/vue-style-loader/lib/addStylesClient.js */ \"./node_modules/vue-style-loader/lib/addStylesClient.js\").default\nvar update = add(\"ba16fb20\", content, false, {\"sourceMap\":false,\"shadowMode\":false});\n// Hot Module Replacement\nif(false) {}\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?./node_modules/vue-style-loader??ref--8-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./src/api/system/user.js": +/*!********************************!*\ + !*** ./src/api/system/user.js ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.addUser = addUser;\nexports.changeUserStatus = changeUserStatus;\nexports.delUser = delUser;\nexports.exportUser = exportUser;\nexports.getUser = getUser;\nexports.getUserProfile = getUserProfile;\nexports.importTemplate = importTemplate;\nexports.listSimpleUsers = listSimpleUsers;\nexports.listUser = listUser;\nexports.resetUserPwd = resetUserPwd;\nexports.updateUser = updateUser;\nexports.updateUserProfile = updateUserProfile;\nexports.updateUserPwd = updateUserPwd;\nexports.uploadAvatar = uploadAvatar;\n\nvar _request = _interopRequireDefault(__webpack_require__(/*! @/utils/request */ \"./src/utils/request.js\"));\n\nvar _ruoyi = __webpack_require__(/*! @/utils/ruoyi */ \"./src/utils/ruoyi.js\");\n\n// 查询用户列表\nfunction listUser(query) {\n return (0, _request.default)({\n url: '/system/user/page',\n method: 'get',\n params: query\n });\n} // 获取用户精简信息列表\n\n\nfunction listSimpleUsers() {\n return (0, _request.default)({\n url: '/system/user/list-all-simple',\n method: 'get'\n });\n} // 查询用户详细\n\n\nfunction getUser(userId) {\n return (0, _request.default)({\n url: '/system/user/get?id=' + (0, _ruoyi.praseStrEmpty)(userId),\n method: 'get'\n });\n} // 新增用户\n\n\nfunction addUser(data) {\n return (0, _request.default)({\n url: '/system/user/create',\n method: 'post',\n data: data\n });\n} // 修改用户\n\n\nfunction updateUser(data) {\n return (0, _request.default)({\n url: '/system/user/update',\n method: 'put',\n data: data\n });\n} // 删除用户\n\n\nfunction delUser(userId) {\n return (0, _request.default)({\n url: '/system/user/delete?id=' + userId,\n method: 'delete'\n });\n} // 导出用户\n\n\nfunction exportUser(query) {\n return (0, _request.default)({\n url: '/system/user/export',\n method: 'get',\n params: query,\n responseType: 'blob'\n });\n} // 用户密码重置\n\n\nfunction resetUserPwd(id, password) {\n var data = {\n id: id,\n password: password\n };\n return (0, _request.default)({\n url: '/system/user/update-password',\n method: 'put',\n data: data\n });\n} // 用户状态修改\n\n\nfunction changeUserStatus(id, status) {\n var data = {\n id: id,\n status: status\n };\n return (0, _request.default)({\n url: '/system/user/update-status',\n method: 'put',\n data: data\n });\n} // 查询用户个人信息\n\n\nfunction getUserProfile() {\n return (0, _request.default)({\n url: '/system/user/profile/get',\n method: 'get'\n });\n} // 修改用户个人信息\n\n\nfunction updateUserProfile(data) {\n return (0, _request.default)({\n url: '/system/user/profile/update',\n method: 'put',\n data: data\n });\n} // 用户密码重置\n\n\nfunction updateUserPwd(oldPassword, newPassword) {\n var data = {\n oldPassword: oldPassword,\n newPassword: newPassword\n };\n return (0, _request.default)({\n url: '/system/user/profile/update-password',\n method: 'put',\n data: data\n });\n} // 用户头像上传\n\n\nfunction uploadAvatar(data) {\n return (0, _request.default)({\n url: '/system/user/profile/update-avatar',\n method: 'put',\n data: data\n });\n} // 下载用户导入模板\n\n\nfunction importTemplate() {\n return (0, _request.default)({\n url: '/system/user/get-import-template',\n method: 'get',\n responseType: 'blob'\n });\n}\n\n//# sourceURL=webpack:///./src/api/system/user.js?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/index.vue": +/*!*************************************************!*\ + !*** ./src/views/system/user/profile/index.vue ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./index.vue?vue&type=template&id=03488e44& */ \"./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44&\");\n/* harmony import */ var _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./index.vue?vue&type=script&lang=js& */ \"./src/views/system/user/profile/index.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/system/user/profile/index.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/system/user/profile/index.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/index.vue?vue&type=script&lang=js&": +/*!**************************************************************************!*\ + !*** ./src/views/system/user/profile/index.vue?vue&type=script&lang=js& ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../../node_modules/babel-loader/lib!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./index.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/index.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/system/user/profile/index.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44&": +/*!********************************************************************************!*\ + !*** ./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44& ***! + \********************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./index.vue?vue&type=template&id=03488e44& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/index.vue?vue&type=template&id=03488e44&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_index_vue_vue_type_template_id_03488e44___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/index.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/resetPwd.vue": +/*!****************************************************!*\ + !*** ./src/views/system/user/profile/resetPwd.vue ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./resetPwd.vue?vue&type=template&id=95e4cfdc& */ \"./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc&\");\n/* harmony import */ var _resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./resetPwd.vue?vue&type=script&lang=js& */ \"./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/system/user/profile/resetPwd.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/system/user/profile/resetPwd.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js&": +/*!*****************************************************************************!*\ + !*** ./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js& ***! + \*****************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../../node_modules/babel-loader/lib!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./resetPwd.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/resetPwd.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/system/user/profile/resetPwd.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc&": +/*!***********************************************************************************!*\ + !*** ./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc& ***! + \***********************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./resetPwd.vue?vue&type=template&id=95e4cfdc& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/resetPwd.vue?vue&type=template&id=95e4cfdc&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_resetPwd_vue_vue_type_template_id_95e4cfdc___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/resetPwd.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userAvatar.vue": +/*!******************************************************!*\ + !*** ./src/views/system/user/profile/userAvatar.vue ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true& */ \"./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true&\");\n/* harmony import */ var _userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./userAvatar.vue?vue&type=script&lang=js& */ \"./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss& */ \"./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss&\");\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(\n _userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n \"e81d90b0\",\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/system/user/profile/userAvatar.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js&": +/*!*******************************************************************************!*\ + !*** ./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js& ***! + \*******************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../../node_modules/babel-loader/lib!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userAvatar.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss&": +/*!****************************************************************************************************************!*\ + !*** ./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss& ***! + \****************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/vue-style-loader??ref--8-oneOf-1-0!../../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src??ref--8-oneOf-1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss& */ \"./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=style&index=0&id=e81d90b0&scoped=true&lang=scss&\");\n/* harmony import */ var _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_vue_style_loader_index_js_ref_8_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_8_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_8_oneOf_1_2_node_modules_sass_loader_dist_cjs_js_ref_8_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_style_index_0_id_e81d90b0_scoped_true_lang_scss___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true&": +/*!*************************************************************************************************!*\ + !*** ./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true& ***! + \*************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userAvatar.vue?vue&type=template&id=e81d90b0&scoped=true&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userAvatar_vue_vue_type_template_id_e81d90b0_scoped_true___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userAvatar.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userInfo.vue": +/*!****************************************************!*\ + !*** ./src/views/system/user/profile/userInfo.vue ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userInfo.vue?vue&type=template&id=804a6b86& */ \"./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86&\");\n/* harmony import */ var _userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./userInfo.vue?vue&type=script&lang=js& */ \"./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/system/user/profile/userInfo.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userInfo.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js&": +/*!*****************************************************************************!*\ + !*** ./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js& ***! + \*****************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../../node_modules/babel-loader/lib!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userInfo.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userInfo.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/system/user/profile/userInfo.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86&": +/*!***********************************************************************************!*\ + !*** ./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86& ***! + \***********************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userInfo.vue?vue&type=template&id=804a6b86& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userInfo.vue?vue&type=template&id=804a6b86&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userInfo_vue_vue_type_template_id_804a6b86___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userInfo.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userSocial.vue": +/*!******************************************************!*\ + !*** ./src/views/system/user/profile/userSocial.vue ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./userSocial.vue?vue&type=template&id=34c563bc& */ \"./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc&\");\n/* harmony import */ var _userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./userSocial.vue?vue&type=script&lang=js& */ \"./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"src/views/system/user/profile/userSocial.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userSocial.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js&": +/*!*******************************************************************************!*\ + !*** ./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js& ***! + \*******************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../../node_modules/babel-loader/lib!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userSocial.vue?vue&type=script&lang=js& */ \"./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userSocial.vue?vue&type=script&lang=js&\");\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__);\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_cache_loader_dist_cjs_js_ref_12_0_node_modules_babel_loader_lib_index_js_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0___default.a); \n\n//# sourceURL=webpack:///./src/views/system/user/profile/userSocial.vue?"); + +/***/ }), + +/***/ "./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc&": +/*!*************************************************************************************!*\ + !*** ./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc& ***! + \*************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../../node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!../../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../../node_modules/vue-loader/lib??vue-loader-options!./userSocial.vue?vue&type=template&id=34c563bc& */ \"./node_modules/cache-loader/dist/cjs.js?{\\\"cacheDirectory\\\":\\\"node_modules/.cache/vue-loader\\\",\\\"cacheIdentifier\\\":\\\"a42e0954-vue-loader-template\\\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/system/user/profile/userSocial.vue?vue&type=template&id=34c563bc&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_cache_loader_dist_cjs_js_cacheDirectory_node_modules_cache_vue_loader_cacheIdentifier_a42e0954_vue_loader_template_node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_userSocial_vue_vue_type_template_id_34c563bc___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./src/views/system/user/profile/userSocial.vue?"); + +/***/ }) + +}]); \ No newline at end of file diff --git a/yudao-server/src/main/resources/admin-ui/static/js/7.js b/yudao-server/src/main/resources/admin-ui/static/js/7.js new file mode 100644 index 0000000000..1e0e23e0b2 --- /dev/null +++ b/yudao-server/src/main/resources/admin-ui/static/js/7.js @@ -0,0 +1,263 @@ +(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[7],{ + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=script&lang=js&": +/*!***********************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=script&lang=js& ***! + \***********************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _minDash = __webpack_require__(/*! min-dash */ \"./node_modules/min-dash/dist/index.esm.js\");\n\n//\n//\n//\n//\n//\n//\n//\nvar _default = {\n name: \"MyProcessPalette\",\n data: function data() {\n return {};\n },\n mounted: function mounted() {},\n methods: {\n addTask: function addTask(event) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var ElementFactory = window.bpmnInstances.elementFactory;\n var create = window.bpmnInstances.modeler.get(\"create\");\n console.log(ElementFactory, create);\n var shape = ElementFactory.createShape((0, _minDash.assign)({\n type: \"bpmn:UserTask\"\n }, options));\n\n if (options) {\n shape.businessObject.di.isExpanded = options.isExpanded;\n }\n\n create.start(event, shape);\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/model/modelEditor.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/model/modelEditor.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +eval("\n\nvar _interopRequireDefault = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/interopRequireDefault.js */ \"./node_modules/@babel/runtime/helpers/interopRequireDefault.js\").default;\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _objectSpread2 = _interopRequireDefault(__webpack_require__(/*! ./node_modules/@babel/runtime/helpers/objectSpread2.js */ \"./node_modules/@babel/runtime/helpers/objectSpread2.js\"));\n\nvar _translations = _interopRequireDefault(__webpack_require__(/*! @/components/bpmnProcessDesigner/src/translations */ \"./src/components/bpmnProcessDesigner/src/translations.js\"));\n\nvar _contentPad = _interopRequireDefault(__webpack_require__(/*! @/components/bpmnProcessDesigner/package/designer/plugins/content-pad */ \"./src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js\"));\n\nvar _palette = _interopRequireDefault(__webpack_require__(/*! @/components/bpmnProcessDesigner/package/designer/plugins/palette */ \"./src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js\"));\n\nvar _ProcessPalette = _interopRequireDefault(__webpack_require__(/*! @/components/bpmnProcessDesigner/package/palette/ProcessPalette */ \"./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue\"));\n\nvar _model = __webpack_require__(/*! @/api/bpm/model */ \"./src/api/bpm/model.js\");\n\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n// 自定义元素选中时的弹出菜单(修改 默认任务 为 用户任务)\n// 自定义左侧菜单(修改 默认任务 为 用户任务)\n// import xmlObj2json from \"./utils/xml2json\";\n// 自定义侧边栏\n// import MyProcessPanel from \"../package/process-panel/ProcessPanel\";\nvar _default = {\n name: \"App\",\n components: {\n MyProcessPalette: _ProcessPalette.default\n },\n data: function data() {\n return {\n xmlString: \"\",\n // BPMN XML\n modeler: null,\n reloadIndex: 0,\n controlDrawerVisible: false,\n translationsSelf: _translations.default,\n controlForm: {\n simulation: true,\n labelEditing: false,\n labelVisible: false,\n prefix: \"activiti\",\n headerButtonSize: \"mini\",\n additionalModel: [_contentPad.default, _palette.default]\n },\n addis: {\n CustomContentPadProvider: _contentPad.default,\n CustomPaletteProvider: _palette.default\n },\n // 流程模型的信息\n model: {}\n };\n },\n created: function created() {\n var _this = this;\n\n // 如果 modelId 非空,说明是修改流程模型\n var modelId = this.$route.query && this.$route.query.modelId;\n\n if (modelId) {\n (0, _model.getModel)(modelId).then(function (response) {\n _this.xmlString = response.data.bpmnXml;\n _this.model = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, response.data), {}, {\n bpmnXml: undefined // 清空 bpmnXml 属性\n\n }); // this.controlForm.processId = response.data.key\n });\n }\n },\n methods: {\n initModeler: function initModeler(modeler) {\n var _this2 = this;\n\n setTimeout(function () {\n _this2.modeler = modeler;\n console.log(modeler);\n }, 10);\n },\n reloadProcessDesigner: function reloadProcessDesigner(deep) {\n this.controlForm.additionalModel = [];\n\n for (var key in this.addis) {\n if (this.addis[key]) {\n this.controlForm.additionalModel.push(this.addis[key]);\n }\n }\n\n deep && (this.xmlString = undefined);\n this.reloadIndex += 1;\n this.modeler = null; // 避免 panel 异常\n // if (deep) {\n // this.xmlString = undefined;\n // this.$refs.processDesigner.processRestart();\n // }\n },\n save: function save(bpmnXml) {\n var _this3 = this;\n\n var data = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, this.model), {}, {\n bpmnXml: bpmnXml // this.bpmnXml 只是初始化流程图,后续修改无法通过它获得\n\n }); // 修改的提交\n\n if (data.id) {\n (0, _model.updateModel)(data).then(function (response) {\n _this3.msgSuccess(\"修改成功\"); // 跳转回去\n\n\n _this3.close();\n });\n return;\n } // 添加的提交\n\n\n (0, _model.createModel)(data).then(function (response) {\n _this3.msgSuccess(\"保存成功\"); // 跳转回去\n\n\n _this3.close();\n });\n },\n\n /** 关闭按钮 */\n close: function close() {\n this.$store.dispatch(\"tagsView/delView\", this.$route);\n this.$router.push({\n path: \"/bpm/manager/model\",\n query: {\n t: Date.now()\n }\n });\n }\n }\n};\nexports.default = _default;\n\n//# sourceURL=webpack:///./src/views/bpm/model/modelEditor.vue?./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=template&id=ad2b6d86&scoped=true&": +/*!*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=template&id=ad2b6d86&scoped=true& ***! + \*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"my-process-palette\" }, [\n _c(\n \"div\",\n {\n staticClass: \"test-button\",\n on: { click: _vm.addTask, mousedown: _vm.addTask },\n },\n [_vm._v(\"测试任务\")]\n ),\n _c(\n \"div\",\n { staticClass: \"test-container\", attrs: { id: \"palette-container\" } },\n [_vm._v(\"1\")]\n ),\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"a42e0954-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/model/modelEditor.vue?vue&type=template&id=3232eb94&": +/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a42e0954-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/model/modelEditor.vue?vue&type=template&id=3232eb94& ***! + \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function () {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"app-container\" },\n [\n _c(\n \"my-process-designer\",\n _vm._b(\n {\n key: \"designer-\" + _vm.reloadIndex,\n ref: \"processDesigner\",\n attrs: { keyboard: \"\" },\n on: { \"init-finished\": _vm.initModeler, save: _vm.save },\n model: {\n value: _vm.xmlString,\n callback: function ($$v) {\n _vm.xmlString = $$v\n },\n expression: \"xmlString\",\n },\n },\n \"my-process-designer\",\n _vm.controlForm,\n false\n )\n ),\n _c(\"my-properties-panel\", {\n key: \"penal-\" + _vm.reloadIndex,\n staticClass: \"process-panel\",\n attrs: {\n \"bpmn-modeler\": _vm.modeler,\n prefix: _vm.controlForm.prefix,\n model: _vm.model,\n },\n }),\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./src/views/bpm/model/modelEditor.vue?./node_modules/cache-loader/dist/cjs.js?%7B%22cacheDirectory%22:%22node_modules/.cache/vue-loader%22,%22cacheIdentifier%22:%22a42e0954-vue-loader-template%22%7D!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=style&index=0&id=ad2b6d86&scoped=true&lang=scss&": +/*!***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=style&index=0&id=ad2b6d86&scoped=true&lang=scss& ***! + \***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".my-process-palette[data-v-ad2b6d86] {\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n padding: 80px 20px 20px 20px;\\n}\\n.my-process-palette .test-button[data-v-ad2b6d86] {\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n padding: 8px 16px;\\n border-radius: 4px;\\n border: 1px solid rgba(24, 144, 255, 0.8);\\n cursor: pointer;\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/views/bpm/model/modelEditor.vue?vue&type=style&index=0&lang=scss&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/bpm/model/modelEditor.vue?vue&type=style&index=0&lang=scss& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// Imports\nvar ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\nexports = ___CSS_LOADER_API_IMPORT___(false);\n// Module\nexports.push([module.i, \".demo-control-bar {\\n position: fixed;\\n right: 8px;\\n bottom: 8px;\\n z-index: 1;\\n}\\n.demo-control-bar .open-control-dialog {\\n width: 48px;\\n height: 48px;\\n display: -webkit-box;\\n display: -ms-flexbox;\\n display: flex;\\n -webkit-box-align: center;\\n -ms-flex-align: center;\\n align-items: center;\\n -webkit-box-pack: center;\\n -ms-flex-pack: center;\\n justify-content: center;\\n border-radius: 4px;\\n font-size: 32px;\\n background: #409eff;\\n color: #ffffff;\\n cursor: pointer;\\n}\\n.control-form .el-radio {\\n width: 100%;\\n line-height: 32px;\\n}\\n.element-overlays {\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n padding: 8px;\\n background: rgba(0, 0, 0, 0.6);\\n border-radius: 4px;\\n color: #fafafa;\\n}\\n.my-process-designer {\\n height: calc(100vh - 84px);\\n}\\n.process-panel__container {\\n position: absolute;\\n right: 0;\\n top: 55px;\\n height: calc(100vh - 84px);\\n}\", \"\"]);\n// Exports\nmodule.exports = exports;\n\n\n//# sourceURL=webpack:///./src/views/bpm/model/modelEditor.vue?./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/vue-style-loader/index.js?!./node_modules/css-loader/dist/cjs.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=style&index=0&id=ad2b6d86&scoped=true&lang=scss&": +/*!*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/vue-style-loader??ref--8-oneOf-1-0!./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue?vue&type=style&index=0&id=ad2b6d86&scoped=true&lang=scss& ***! + \*****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// style-loader: Adds some css to the DOM by adding a \"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/build.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/button.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/button.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-button\",\n \"use\": \"icon-button-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/button.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/cascader.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/cascader.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-cascader\",\n \"use\": \"icon-cascader-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/cascader.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/chart.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/chart.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-chart\",\n \"use\": \"icon-chart-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/chart.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/checkbox.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/checkbox.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-checkbox\",\n \"use\": \"icon-checkbox-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/checkbox.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/clipboard.svg": +/*!********************************************!*\ + !*** ./src/assets/icons/svg/clipboard.svg ***! + \********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-clipboard\",\n \"use\": \"icon-clipboard-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/clipboard.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/code.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/code.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-code\",\n \"use\": \"icon-code-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/code.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/color.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/color.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-color\",\n \"use\": \"icon-color-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/color.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/component.svg": +/*!********************************************!*\ + !*** ./src/assets/icons/svg/component.svg ***! + \********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-component\",\n \"use\": \"icon-component-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/component.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/config.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/config.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-config\",\n \"use\": \"icon-config-usage\",\n \"viewBox\": \"0 0 1070 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/config.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/dashboard.svg": +/*!********************************************!*\ + !*** ./src/assets/icons/svg/dashboard.svg ***! + \********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-dashboard\",\n \"use\": \"icon-dashboard-usage\",\n \"viewBox\": \"0 0 128 100\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/dashboard.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/date-range.svg": +/*!*********************************************!*\ + !*** ./src/assets/icons/svg/date-range.svg ***! + \*********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-date-range\",\n \"use\": \"icon-date-range-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/date-range.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/date.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/date.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-date\",\n \"use\": \"icon-date-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/date.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/dict.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/dict.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-dict\",\n \"use\": \"icon-dict-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/dict.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/documentation.svg": +/*!************************************************!*\ + !*** ./src/assets/icons/svg/documentation.svg ***! + \************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-documentation\",\n \"use\": \"icon-documentation-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/documentation.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/download.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/download.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-download\",\n \"use\": \"icon-download-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/download.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/drag.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/drag.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-drag\",\n \"use\": \"icon-drag-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/drag.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/druid.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/druid.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-druid\",\n \"use\": \"icon-druid-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/druid.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/edit.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/edit.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-edit\",\n \"use\": \"icon-edit-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/edit.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/education.svg": +/*!********************************************!*\ + !*** ./src/assets/icons/svg/education.svg ***! + \********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-education\",\n \"use\": \"icon-education-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/education.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/email.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/email.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-email\",\n \"use\": \"icon-email-usage\",\n \"viewBox\": \"0 0 128 96\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/email.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/example.svg": +/*!******************************************!*\ + !*** ./src/assets/icons/svg/example.svg ***! + \******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-example\",\n \"use\": \"icon-example-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/example.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/excel.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/excel.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-excel\",\n \"use\": \"icon-excel-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/excel.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/exit-fullscreen.svg": +/*!**************************************************!*\ + !*** ./src/assets/icons/svg/exit-fullscreen.svg ***! + \**************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-exit-fullscreen\",\n \"use\": \"icon-exit-fullscreen-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/exit-fullscreen.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/eye-open.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/eye-open.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-eye-open\",\n \"use\": \"icon-eye-open-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/eye-open.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/eye.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/eye.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-eye\",\n \"use\": \"icon-eye-usage\",\n \"viewBox\": \"0 0 128 64\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/eye.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/form.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/form.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-form\",\n \"use\": \"icon-form-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/form.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/fullscreen.svg": +/*!*********************************************!*\ + !*** ./src/assets/icons/svg/fullscreen.svg ***! + \*********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-fullscreen\",\n \"use\": \"icon-fullscreen-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/fullscreen.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/github.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/github.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-github\",\n \"use\": \"icon-github-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/github.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/guide.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/guide.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-guide\",\n \"use\": \"icon-guide-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/guide.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/icon.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/icon.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-icon\",\n \"use\": \"icon-icon-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/icon.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/input.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/input.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-input\",\n \"use\": \"icon-input-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/input.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/international.svg": +/*!************************************************!*\ + !*** ./src/assets/icons/svg/international.svg ***! + \************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-international\",\n \"use\": \"icon-international-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/international.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/job.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/job.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-job\",\n \"use\": \"icon-job-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/job.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/language.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/language.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-language\",\n \"use\": \"icon-language-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/language.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/link.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/link.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-link\",\n \"use\": \"icon-link-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/link.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/list.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/list.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-list\",\n \"use\": \"icon-list-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/list.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/lock.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/lock.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-lock\",\n \"use\": \"icon-lock-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/lock.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/log.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/log.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-log\",\n \"use\": \"icon-log-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/log.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/logininfor.svg": +/*!*********************************************!*\ + !*** ./src/assets/icons/svg/logininfor.svg ***! + \*********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-logininfor\",\n \"use\": \"icon-logininfor-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/logininfor.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/merchant.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/merchant.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-merchant\",\n \"use\": \"icon-merchant-usage\",\n \"viewBox\": \"0 0 1184 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/merchant.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/message.svg": +/*!******************************************!*\ + !*** ./src/assets/icons/svg/message.svg ***! + \******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-message\",\n \"use\": \"icon-message-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/message.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/money.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/money.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-money\",\n \"use\": \"icon-money-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/money.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/monitor.svg": +/*!******************************************!*\ + !*** ./src/assets/icons/svg/monitor.svg ***! + \******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-monitor\",\n \"use\": \"icon-monitor-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/monitor.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/nested.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/nested.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-nested\",\n \"use\": \"icon-nested-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/nested.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/number.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/number.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-number\",\n \"use\": \"icon-number-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/number.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/online.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/online.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-online\",\n \"use\": \"icon-online-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/online.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/order.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/order.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-order\",\n \"use\": \"icon-order-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/order.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/password.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/password.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-password\",\n \"use\": \"icon-password-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/password.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/pay.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/pay.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-pay\",\n \"use\": \"icon-pay-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/pay.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/pdf.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/pdf.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-pdf\",\n \"use\": \"icon-pdf-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/pdf.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/people.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/people.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-people\",\n \"use\": \"icon-people-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/people.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/peoples.svg": +/*!******************************************!*\ + !*** ./src/assets/icons/svg/peoples.svg ***! + \******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-peoples\",\n \"use\": \"icon-peoples-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/peoples.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/percentSign.svg": +/*!**********************************************!*\ + !*** ./src/assets/icons/svg/percentSign.svg ***! + \**********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-percentSign\",\n \"use\": \"icon-percentSign-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/percentSign.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/phone.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/phone.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-phone\",\n \"use\": \"icon-phone-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/phone.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/post.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/post.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-post\",\n \"use\": \"icon-post-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/post.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/qq.svg": +/*!*************************************!*\ + !*** ./src/assets/icons/svg/qq.svg ***! + \*************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-qq\",\n \"use\": \"icon-qq-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/qq.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/question.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/question.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-question\",\n \"use\": \"icon-question-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/question.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/radio.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/radio.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-radio\",\n \"use\": \"icon-radio-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/radio.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/rate.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/rate.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-rate\",\n \"use\": \"icon-rate-usage\",\n \"viewBox\": \"0 0 1069 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/rate.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/redis.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/redis.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-redis\",\n \"use\": \"icon-redis-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/redis.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/row.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/row.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-row\",\n \"use\": \"icon-row-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/row.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/search.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/search.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-search\",\n \"use\": \"icon-search-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/search.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/select.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/select.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-select\",\n \"use\": \"icon-select-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/select.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/server.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/server.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-server\",\n \"use\": \"icon-server-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/server.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/shopping.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/shopping.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-shopping\",\n \"use\": \"icon-shopping-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/shopping.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/size.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/size.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-size\",\n \"use\": \"icon-size-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/size.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/skill.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/skill.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-skill\",\n \"use\": \"icon-skill-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/skill.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/slider.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/slider.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-slider\",\n \"use\": \"icon-slider-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/slider.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/star.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/star.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-star\",\n \"use\": \"icon-star-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/star.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/swagger.svg": +/*!******************************************!*\ + !*** ./src/assets/icons/svg/swagger.svg ***! + \******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-swagger\",\n \"use\": \"icon-swagger-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/swagger.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/switch.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/switch.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-switch\",\n \"use\": \"icon-switch-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/switch.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/system.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/system.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-system\",\n \"use\": \"icon-system-usage\",\n \"viewBox\": \"0 0 1084 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/system.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/tab.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/tab.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-tab\",\n \"use\": \"icon-tab-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/tab.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/table.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/table.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-table\",\n \"use\": \"icon-table-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/table.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/textarea.svg": +/*!*******************************************!*\ + !*** ./src/assets/icons/svg/textarea.svg ***! + \*******************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-textarea\",\n \"use\": \"icon-textarea-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/textarea.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/theme.svg": +/*!****************************************!*\ + !*** ./src/assets/icons/svg/theme.svg ***! + \****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-theme\",\n \"use\": \"icon-theme-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/theme.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/time-range.svg": +/*!*********************************************!*\ + !*** ./src/assets/icons/svg/time-range.svg ***! + \*********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-time-range\",\n \"use\": \"icon-time-range-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/time-range.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/time.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/time.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-time\",\n \"use\": \"icon-time-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/time.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/tool.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/tool.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-tool\",\n \"use\": \"icon-tool-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/tool.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/tree-table.svg": +/*!*********************************************!*\ + !*** ./src/assets/icons/svg/tree-table.svg ***! + \*********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-tree-table\",\n \"use\": \"icon-tree-table-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/tree-table.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/tree.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/tree.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-tree\",\n \"use\": \"icon-tree-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/tree.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/upload.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/upload.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-upload\",\n \"use\": \"icon-upload-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/upload.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/user.svg": +/*!***************************************!*\ + !*** ./src/assets/icons/svg/user.svg ***! + \***************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-user\",\n \"use\": \"icon-user-usage\",\n \"viewBox\": \"0 0 130 130\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/user.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/validCode.svg": +/*!********************************************!*\ + !*** ./src/assets/icons/svg/validCode.svg ***! + \********************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-validCode\",\n \"use\": \"icon-validCode-usage\",\n \"viewBox\": \"0 0 1024 1024\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/validCode.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/wechat.svg": +/*!*****************************************!*\ + !*** ./src/assets/icons/svg/wechat.svg ***! + \*****************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-wechat\",\n \"use\": \"icon-wechat-usage\",\n \"viewBox\": \"0 0 128 110\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/wechat.svg?"); + +/***/ }), + +/***/ "./src/assets/icons/svg/zip.svg": +/*!**************************************!*\ + !*** ./src/assets/icons/svg/zip.svg ***! + \**************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/svg-baker-runtime/browser-symbol.js */ \"./node_modules/svg-baker-runtime/browser-symbol.js\");\n/* harmony import */ var _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/svg-sprite-loader/runtime/browser-sprite.build.js */ \"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js\");\n/* harmony import */ var _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\nvar symbol = new _node_modules_svg_baker_runtime_browser_symbol_js__WEBPACK_IMPORTED_MODULE_0___default.a({\n \"id\": \"icon-zip\",\n \"use\": \"icon-zip-usage\",\n \"viewBox\": \"0 0 128 128\",\n \"content\": \"\"\n});\nvar result = _node_modules_svg_sprite_loader_runtime_browser_sprite_build_js__WEBPACK_IMPORTED_MODULE_1___default.a.add(symbol);\n/* harmony default export */ __webpack_exports__[\"default\"] = (symbol);\n\n//# sourceURL=webpack:///./src/assets/icons/svg/zip.svg?"); + +/***/ }), + +/***/ "./src/assets/images/dark.svg": +/*!************************************!*\ + !*** ./src/assets/images/dark.svg ***! + \************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("module.exports = __webpack_require__.p + \"static/img/dark.d0efa020.svg\";\n\n//# sourceURL=webpack:///./src/assets/images/dark.svg?"); + +/***/ }), + +/***/ "./src/assets/images/light.svg": +/*!*************************************!*\ + !*** ./src/assets/images/light.svg ***! + \*************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("module.exports = __webpack_require__.p + \"static/img/light.ccbb6cbd.svg\";\n\n//# sourceURL=webpack:///./src/assets/images/light.svg?"); + +/***/ }), + +/***/ "./src/assets/images/profile.jpg": +/*!***************************************!*\ + !*** ./src/assets/images/profile.jpg ***! + \***************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("module.exports = __webpack_require__.p + \"static/img/profile.473f5971.jpg\";\n\n//# sourceURL=webpack:///./src/assets/images/profile.jpg?"); + +/***/ }), + +/***/ "./src/assets/logo/logo.png": +/*!**********************************!*\ + !*** ./src/assets/logo/logo.png ***! + \**********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("module.exports = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAACdlBMVEUgFBUlFxnh3eMsHR6abFYgFhmhcl3i3+eeb1mTZE+WaFTc19wbDxATEBMeGx/Y09u6q7B6VEQ1IB3c2uLAt8EsGhjSy9S9sLRKLirAsrkaFRkpGBXo4OM0KS0bGybf2N3Z0NS9rLCWipPKwcexoqatnaM+JyWpnqhQPUHIw81QNC3Gu8K4qKy2pKgnHR2nmZ5gS09DLSY7JCCjj4+/lHuld2BVQ0ctICSbkZy5j3aNYE7U0NjBs7q4sbmupa+flqGXjZqWgoG1iXGIXUuEW0caHi4lHyQ9LSIxHRzj2t3Etr20pq6tm5yaiI6ah4mGcHJWOTTw6evNytHMx85uWVtpSDxbPTlAMjM8LC42Kh7p5evt4+bZyMzGwMm9sbeQiI7CeYiDcHKwg2uofGZlWFplUVRQSExGNjokIS9PPS4vJimplZebjZKUhIqPgoizdIWJfYRjX2hbRElMNzw3MTZLJSA8KhbRxsnMv8PFtLaimqSFd3t9dXl+aG5vXmNxTj9CPT1hQzhEOClSOSMNAwXm4+nJt7uyqrWzoaq0mqeylaKjkpamgI2JhIuqboLBmYCmf294X2aUbV5YUldzWEtGLh/08vO+ydjh09O7tL2SpLvBqKW4paKilZqzi5iXlJbRhpKfioi9cYJ9amg3MUJZSTdNNjZZPyhLNCNYSBswJRq5oKukpaSxj4VybHhoZml8YFWFYFFlVkgnMUdlVzFdMiY1JCXAwsHfqrnEq7J5jaeskaGvkZa1hJDMfYunhXZDPVJZSE5eTC/Bj52ebYJGWXSXeXOoXXJKSFiJZ05DNkm2vs+hss9hfZ1Vb4k3UGxtOitKPxK3/ZdxAAAINklEQVRIx0WVBVsbWRSG70SIjYQ48RBvCBEkSAMsBIK2uLtbcbfi0FJoC9R161vX3W23vu67/2jPhPbZd5JJMjnv/XLunZkgJlMzd0l+pV1LKrMUtoqm1aONV78/Z0+2DpXPGan1xqtv38iFGoLNxmiY8ETRzGg00k4SSrLbUnjLffCA43Lj1XsSmfFk+UmZ7Ejj1cbLkjSEEDtk0NAKwSYIpZIcqbxlm5v9MJD7pvF7v0M2MPJLcjFEXjvq2ERsAEMIY4qyRbSCwyBKNtnZOdIWb+sY7nvZ35gnkW3euFEnO3rt7bUjjoc4CGzm05sVdA5i+qLBZrOzRD6NrS1+eKhtTni5/965kob2DxL9kf63/U7JIGRER1c9f/5cKlKBAr1ArtJnuUUO0cbJUvO9rSP+uoSmk47k9f7GfqF/Bwdn7Cvg3zEmrWCIRqToGByxDZW62+IPvdw66q+zTs9GUOv91/rlayM4jKr6KvDr8zHp/wrmtXVUzw+fLG1ti5+Vb132103NztZTeVvXjkms82xMJZLePXVKpJJmqxCmDSk+i1vjL8ba3MNuW6nw2DF/Xer1WT8l3Pr5tST1Bo7BXH0tArIhBWYbMvBlS2nlzOb9ivYdm9t96btj54ypB2dTdBFbP69LHnYidsixWIJBiwWxQWPjWQ3zle1+4tH9+4M299DAke8kdmi/T+D44Qf/2iAobIT2PK8XsbN8bEK5fKXIb2yv/Nrn07htw9MSh4yqqxfmUSUgT/3SiSEALBoMabWdnSSGRq5Ea3yVHfFu2OKtAs7Kykp1dTVDIJNIpt7f0NCzDM4emZnPMjFieWCGOWTr0Gg03ZqdVF01sMJZ4XA44mRZys5vNxCO459CmEhbMZ+J5jfvs30VwzabrSO+z85Rc8QcDoMTgiFO7vvtPYbT0HOlkiLl4nwn0XCaJLRklqZiuOmcjsEQiwWMEKCAWvLwfRaOZYtEKgSKChFKbRZzeUdCaLNIMmtAptfpBDqxGLy9GNorfqhRjS3dPnUnKFXRKUrM5+tefnSF6CazZvR6XY5At5fwOYgh5sgGPXduL42NLd1RqbJDipJQ4N/MV2haBQIdZdRTFFSKS+yyEkongDyBgLP29PappaWlO10WTIpIklQS0SrfN5oO94Rap59gnD4N4zLsVFFRTgklFoihM0rcu3vzY/jS7ZtdUimsC1yTeMU3O8whV02OYKLo9JlX58WcYhnn/Ksz4mLIAIcS268//fhxbKyrSwRKJkEQy4/alyuu62vURv3pMz8Sj6rFdYzzz8gfz+iTBQIqGTax9eZisCvoWQwpSiUB086s/CJHzTDmFP3x7GvjCkfGeKXF/z6jL0mmKCpZJqMktrtVnjtdwWxa0SoJNlwFHYYiNUMvYySfz/32WwGD+v3Pv85TRhkFMbISe7F9ropAwcXFKmg/M5Mk2CoMuWuL1GoGLEqR+tvaHHhTbJcV6wU6+GGg2IsbNET0YjDoyQ4pShyU0pyimpoasNSwGlSxTg1vAVDAAKa6ieDNrqpgFVJCMyRcCeh6TVGNmpEjEKj140aH3CjIgfNAoJfpZXaj0Vhn38wiqroW70YzQdHCiYJheKu6Jkcn0Bsdtav7c4WmvNwJR25urgPKJRKJw1GXplHdrbpL4gh1agmViImx8fjampyz+gl5lPC1233MbM4TRsjl8gjQ9tOOZKBbWgW9ewvRMy2hCC/LZuOVBvVZfe2qwWk6qhgFZd0QEbF/f8TeTiJJKfXAHUbqWShEWrJy9/GuAuHY9Fn9+MSkIcrpvPwm3+yMMsihmq6nlbWm8lGvFMveJ8URqby1Ww4qjleYaicmI+SGqCinybweJRTKIaI+or5eXl8f0RsvlWZjuEjqHUUkspTvK1RgCOGaacOkQSiMMhjuRQFC+Wci6nvbmdIX/4yqvJ7RUbjzM0VBuDlrNGxUOW1wms0mwAxY8yAJyDNFztg0mOrFixej2d5REbJYLF6vyGvxWJqM4+PjQrPr0iWX2eVypV5yWVNSUvJcrR2VTPiTkEIR1HoUaN8nFIoL6tqzeqHJvLFhyhU6Icq6h00KA3oUCgVdBJVIAa8hPLde1jomJw1O14awdhXmLSrPmpCQmppyMPwzh+FRVoYKacrLyxcWyq9f+Onxlxed+S7TpMEETVinEiLTElJiAoEnSRlAeHgGLaLDu4+fPOHzt7f52ywen3/iois/3+Xa2DDnuRIS0tLSEqbWfgokJSXxkgKBjCQgA7G4YWFxcWGwD4M9/4G5x+Q0uXoPFPQeioyMBCU1xcnn8Vjw5EMtl8VDXC5tfILbcsGcbzBE5fcWFBw6BA5IqdZzr7nwFRAGG5eF4AMcYLG4NKx3k/n5hihTT08PKAUFtJNq9ctZIegqCEMsyOPTD/oA78Rqfo/T2bPR0xNz4EBBQW9vJDSTsv8ECHxeUkYSj8dtQXwWlPNCCo/LPbF6MSY/P4amABw6Bpqp387gsbis5vTmxMTYWPhhfFZYHGSFBuJeMNDlXwIHaA410NNsaGmG8vTY44mJ6YmxKNRFGFSDFfbuxIOLMV/8T19fHzhrFxJjjx+PPR4LEYnpsYhHwwL4/Adn1YJxQ8zBTzQ1Nc3MTA9spl48DoMnJoITC1mJaG/OAwFYRRAc8ryZdlv8h7bW1tLW1tbBwemGyCvbvDB6JZrT09ObmyElI8DjQ/+wNi0P3m0/3i3r8jKjMay7u9tHkiODA30NDaW3F8oOhx8+HB54Qs8ZgtKWlri4OHpVeHAgIzwQHl62UF64T+HxeOLbSufmni6UAXBOBn7lQ/V/V089QlcnVhMAAAAASUVORK5CYII=\"\n\n//# sourceURL=webpack:///./src/assets/logo/logo.png?"); + +/***/ }), + +/***/ "./src/assets/styles/element-variables.scss": +/*!**************************************************!*\ + !*** ./src/assets/styles/element-variables.scss ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// style-loader: Adds some css to the DOM by adding a ', returnEnd: true,\n subLanguage: ['css', 'xml']\n }\n },\n {\n className: 'tag',\n // See the comment in the \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/cascader.svg b/yudao-ui-admin/src/icons/svg/cascader.svg new file mode 100644 index 0000000000..e256024f9d --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/cascader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/checkbox.svg b/yudao-ui-admin/src/icons/svg/checkbox.svg new file mode 100644 index 0000000000..013fd3a273 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/checkbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/color.svg b/yudao-ui-admin/src/icons/svg/color.svg new file mode 100644 index 0000000000..44a81aab1b --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/component.svg b/yudao-ui-admin/src/icons/svg/component.svg new file mode 100644 index 0000000000..29c3458099 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/date-range.svg b/yudao-ui-admin/src/icons/svg/date-range.svg new file mode 100644 index 0000000000..fda571e700 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/date-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/date.svg b/yudao-ui-admin/src/icons/svg/date.svg new file mode 100644 index 0000000000..52dc73eecf --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/date.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/input.svg b/yudao-ui-admin/src/icons/svg/input.svg new file mode 100644 index 0000000000..ab91381e6d --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/input.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/number.svg b/yudao-ui-admin/src/icons/svg/number.svg new file mode 100644 index 0000000000..ad5ce9af2a --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/number.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/password.svg b/yudao-ui-admin/src/icons/svg/password.svg new file mode 100644 index 0000000000..6c64defe39 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/radio.svg b/yudao-ui-admin/src/icons/svg/radio.svg new file mode 100644 index 0000000000..0cde34521a --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/rate.svg b/yudao-ui-admin/src/icons/svg/rate.svg new file mode 100644 index 0000000000..aa3b14d7de --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/rate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/rich-text.svg b/yudao-ui-admin/src/icons/svg/rich-text.svg new file mode 100644 index 0000000000..76c45bfe35 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/rich-text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/row.svg b/yudao-ui-admin/src/icons/svg/row.svg new file mode 100644 index 0000000000..0780992226 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/row.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/select.svg b/yudao-ui-admin/src/icons/svg/select.svg new file mode 100644 index 0000000000..d6283828ba --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/select.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/slider.svg b/yudao-ui-admin/src/icons/svg/slider.svg new file mode 100644 index 0000000000..fbe4f39f00 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/slider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/switch.svg b/yudao-ui-admin/src/icons/svg/switch.svg new file mode 100644 index 0000000000..0ba61e38d7 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/switch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/table.svg b/yudao-ui-admin/src/icons/svg/table.svg new file mode 100644 index 0000000000..e8068454f9 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/textarea.svg b/yudao-ui-admin/src/icons/svg/textarea.svg new file mode 100644 index 0000000000..2709f292ea --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/textarea.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/time-range.svg b/yudao-ui-admin/src/icons/svg/time-range.svg new file mode 100644 index 0000000000..13c1202bda --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/time-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/time.svg b/yudao-ui-admin/src/icons/svg/time.svg new file mode 100644 index 0000000000..b376e32a60 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-ui-admin/src/icons/svg/upload.svg b/yudao-ui-admin/src/icons/svg/upload.svg new file mode 100644 index 0000000000..bae49c0a50 --- /dev/null +++ b/yudao-ui-admin/src/icons/svg/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yudao-admin-ui/src/layout/components/AppMain.vue b/yudao-ui-admin/src/layout/components/AppMain.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/AppMain.vue rename to yudao-ui-admin/src/layout/components/AppMain.vue diff --git a/yudao-admin-ui/src/layout/components/Navbar.vue b/yudao-ui-admin/src/layout/components/Navbar.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Navbar.vue rename to yudao-ui-admin/src/layout/components/Navbar.vue diff --git a/yudao-admin-ui/src/layout/components/Settings/index.vue b/yudao-ui-admin/src/layout/components/Settings/index.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Settings/index.vue rename to yudao-ui-admin/src/layout/components/Settings/index.vue diff --git a/yudao-admin-ui/src/layout/components/Sidebar/FixiOSBug.js b/yudao-ui-admin/src/layout/components/Sidebar/FixiOSBug.js similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/FixiOSBug.js rename to yudao-ui-admin/src/layout/components/Sidebar/FixiOSBug.js diff --git a/yudao-admin-ui/src/layout/components/Sidebar/Item.vue b/yudao-ui-admin/src/layout/components/Sidebar/Item.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/Item.vue rename to yudao-ui-admin/src/layout/components/Sidebar/Item.vue diff --git a/yudao-admin-ui/src/layout/components/Sidebar/Link.vue b/yudao-ui-admin/src/layout/components/Sidebar/Link.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/Link.vue rename to yudao-ui-admin/src/layout/components/Sidebar/Link.vue diff --git a/yudao-admin-ui/src/layout/components/Sidebar/Logo.vue b/yudao-ui-admin/src/layout/components/Sidebar/Logo.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/Logo.vue rename to yudao-ui-admin/src/layout/components/Sidebar/Logo.vue diff --git a/yudao-admin-ui/src/layout/components/Sidebar/SidebarItem.vue b/yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/SidebarItem.vue rename to yudao-ui-admin/src/layout/components/Sidebar/SidebarItem.vue diff --git a/yudao-admin-ui/src/layout/components/Sidebar/index.vue b/yudao-ui-admin/src/layout/components/Sidebar/index.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/Sidebar/index.vue rename to yudao-ui-admin/src/layout/components/Sidebar/index.vue diff --git a/yudao-admin-ui/src/layout/components/TagsView/ScrollPane.vue b/yudao-ui-admin/src/layout/components/TagsView/ScrollPane.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/TagsView/ScrollPane.vue rename to yudao-ui-admin/src/layout/components/TagsView/ScrollPane.vue diff --git a/yudao-admin-ui/src/layout/components/TagsView/index.vue b/yudao-ui-admin/src/layout/components/TagsView/index.vue similarity index 100% rename from yudao-admin-ui/src/layout/components/TagsView/index.vue rename to yudao-ui-admin/src/layout/components/TagsView/index.vue diff --git a/yudao-admin-ui/src/layout/components/global.js b/yudao-ui-admin/src/layout/components/global.js similarity index 100% rename from yudao-admin-ui/src/layout/components/global.js rename to yudao-ui-admin/src/layout/components/global.js diff --git a/yudao-admin-ui/src/layout/components/index.js b/yudao-ui-admin/src/layout/components/index.js similarity index 100% rename from yudao-admin-ui/src/layout/components/index.js rename to yudao-ui-admin/src/layout/components/index.js diff --git a/yudao-admin-ui/src/layout/index.vue b/yudao-ui-admin/src/layout/index.vue similarity index 100% rename from yudao-admin-ui/src/layout/index.vue rename to yudao-ui-admin/src/layout/index.vue diff --git a/yudao-admin-ui/src/layout/mixin/ResizeHandler.js b/yudao-ui-admin/src/layout/mixin/ResizeHandler.js similarity index 100% rename from yudao-admin-ui/src/layout/mixin/ResizeHandler.js rename to yudao-ui-admin/src/layout/mixin/ResizeHandler.js diff --git a/yudao-admin-ui/src/main.js b/yudao-ui-admin/src/main.js similarity index 100% rename from yudao-admin-ui/src/main.js rename to yudao-ui-admin/src/main.js diff --git a/yudao-admin-ui/src/permission.js b/yudao-ui-admin/src/permission.js similarity index 100% rename from yudao-admin-ui/src/permission.js rename to yudao-ui-admin/src/permission.js diff --git a/yudao-admin-ui/src/router/index.js b/yudao-ui-admin/src/router/index.js similarity index 100% rename from yudao-admin-ui/src/router/index.js rename to yudao-ui-admin/src/router/index.js diff --git a/yudao-admin-ui/src/settings.js b/yudao-ui-admin/src/settings.js similarity index 100% rename from yudao-admin-ui/src/settings.js rename to yudao-ui-admin/src/settings.js diff --git a/yudao-admin-ui/src/store/getters.js b/yudao-ui-admin/src/store/getters.js similarity index 100% rename from yudao-admin-ui/src/store/getters.js rename to yudao-ui-admin/src/store/getters.js diff --git a/yudao-admin-ui/src/store/index.js b/yudao-ui-admin/src/store/index.js similarity index 100% rename from yudao-admin-ui/src/store/index.js rename to yudao-ui-admin/src/store/index.js diff --git a/yudao-admin-ui/src/store/modules/app.js b/yudao-ui-admin/src/store/modules/app.js similarity index 100% rename from yudao-admin-ui/src/store/modules/app.js rename to yudao-ui-admin/src/store/modules/app.js diff --git a/yudao-admin-ui/src/store/modules/dict.js b/yudao-ui-admin/src/store/modules/dict.js similarity index 89% rename from yudao-admin-ui/src/store/modules/dict.js rename to yudao-ui-admin/src/store/modules/dict.js index 64c05a1941..62d84ec8ab 100644 --- a/yudao-admin-ui/src/store/modules/dict.js +++ b/yudao-ui-admin/src/store/modules/dict.js @@ -18,6 +18,10 @@ const mutations = { const actions = { loadDictDatas({ commit }) { listSimpleDictDatas().then(response => { + // 如果未加载到数据,则直接返回 + if (!response || !response.data) { + return; + } // 设置数据 const dictDataMap = {} response.data.forEach(dictData => { diff --git a/yudao-admin-ui/src/store/modules/permission.js b/yudao-ui-admin/src/store/modules/permission.js similarity index 100% rename from yudao-admin-ui/src/store/modules/permission.js rename to yudao-ui-admin/src/store/modules/permission.js diff --git a/yudao-admin-ui/src/store/modules/settings.js b/yudao-ui-admin/src/store/modules/settings.js similarity index 100% rename from yudao-admin-ui/src/store/modules/settings.js rename to yudao-ui-admin/src/store/modules/settings.js diff --git a/yudao-admin-ui/src/store/modules/tagsView.js b/yudao-ui-admin/src/store/modules/tagsView.js similarity index 100% rename from yudao-admin-ui/src/store/modules/tagsView.js rename to yudao-ui-admin/src/store/modules/tagsView.js diff --git a/yudao-admin-ui/src/store/modules/user.js b/yudao-ui-admin/src/store/modules/user.js similarity index 92% rename from yudao-admin-ui/src/store/modules/user.js rename to yudao-ui-admin/src/store/modules/user.js index 57472374ef..1f868ff1e0 100644 --- a/yudao-admin-ui/src/store/modules/user.js +++ b/yudao-ui-admin/src/store/modules/user.js @@ -91,6 +91,20 @@ const user = { GetInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(res => { + // 没有 data 数据,赋予个默认值 + if (!res) { + res = { + data: { + roles: [], + user: { + id: '', + avatar: '', + userName: '' + } + } + } + } + res = res.data; // 读取 data 数据 const user = res.user const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : user.avatar; diff --git a/yudao-admin-ui/src/styles/home.scss b/yudao-ui-admin/src/styles/home.scss similarity index 100% rename from yudao-admin-ui/src/styles/home.scss rename to yudao-ui-admin/src/styles/home.scss diff --git a/yudao-admin-ui/src/styles/index.scss b/yudao-ui-admin/src/styles/index.scss similarity index 100% rename from yudao-admin-ui/src/styles/index.scss rename to yudao-ui-admin/src/styles/index.scss diff --git a/yudao-admin-ui/src/styles/mixin.scss b/yudao-ui-admin/src/styles/mixin.scss similarity index 100% rename from yudao-admin-ui/src/styles/mixin.scss rename to yudao-ui-admin/src/styles/mixin.scss diff --git a/yudao-admin-ui/src/utils/auth.js b/yudao-ui-admin/src/utils/auth.js similarity index 100% rename from yudao-admin-ui/src/utils/auth.js rename to yudao-ui-admin/src/utils/auth.js diff --git a/yudao-admin-ui/src/utils/constants.js b/yudao-ui-admin/src/utils/constants.js similarity index 89% rename from yudao-admin-ui/src/utils/constants.js rename to yudao-ui-admin/src/utils/constants.js index 87ca6e8ccc..912f90f2ad 100644 --- a/yudao-admin-ui/src/utils/constants.js +++ b/yudao-ui-admin/src/utils/constants.js @@ -7,7 +7,7 @@ /** * 全局通用状态枚举 */ -export const SysCommonStatusEnum = { +export const CommonStatusEnum = { ENABLE: 0, // 开启 DISABLE: 1 // 禁用 } @@ -15,7 +15,7 @@ export const SysCommonStatusEnum = { /** * 菜单的类型枚举 */ -export const SysMenuTypeEnum = { +export const SystemMenuTypeEnum = { DIR: 1, // 目录 MENU: 2, // 菜单 BUTTON: 3 // 按钮 @@ -24,7 +24,7 @@ export const SysMenuTypeEnum = { /** * 角色的类型枚举 */ -export const SysRoleTypeEnum = { +export const SystemRoleTypeEnum = { SYSTEM: 1, // 内置角色 CUSTOM: 2 // 自定义角色 } @@ -32,7 +32,7 @@ export const SysRoleTypeEnum = { /** * 数据权限的范围枚举 */ -export const SysDataScopeEnum = { +export const SystemDataScopeEnum = { ALL: 1, // 全部数据权限 DEPT_CUSTOM: 2, // 指定部门数据权限 DEPT_ONLY: 3, // 部门数据权限 @@ -52,7 +52,7 @@ export const ToolCodegenTemplateTypeEnum = { /** * 任务状态的枚举 */ -export const InfJobStatusEnum = { +export const InfraJobStatusEnum = { INIT: 0, // 初始化中 NORMAL: 1, // 运行中 STOP: 2, // 暂停运行 @@ -61,7 +61,7 @@ export const InfJobStatusEnum = { /** * API 异常数据的处理状态 */ -export const InfApiErrorLogProcessStatusEnum = { +export const InfraApiErrorLogProcessStatusEnum = { INIT: 0, // 未处理 DONE: 1, // 已处理 IGNORE: 2, // 已忽略 @@ -70,7 +70,7 @@ export const InfApiErrorLogProcessStatusEnum = { /** * 用户的社交平台的类型枚举 */ -export const SysUserSocialTypeEnum = { +export const SystemUserSocialTypeEnum = { // GITEE: { // title: "码云", // type: 10, @@ -136,7 +136,7 @@ export const PayType = { /** * 支付订单状态枚举 */ -export const payOrderStatusEnum = { +export const PayOrderStatusEnum = { WAITING: { status: 0, name: '未支付' @@ -154,7 +154,7 @@ export const payOrderStatusEnum = { /** * 支付订单回调状态枚举 */ -export const payOrderNotifyStatusEnum = { +export const PayOrderNotifyStatusEnum = { NO: { status: 0, name: '未通知' @@ -172,7 +172,7 @@ export const payOrderNotifyStatusEnum = { /** * 支付订单退款状态枚举 */ -export const payOrderRefundStatusEnum = { +export const PayOrderRefundStatusEnum = { NO: { status: 0, name: '未退款' @@ -190,7 +190,7 @@ export const payOrderRefundStatusEnum = { /** * 支付退款订单状态枚举 */ -export const payRefundStatusEnum = { +export const PayRefundStatusEnum = { CREATE:{ status:0, name: '退款订单生成' diff --git a/yudao-admin-ui/src/utils/dateUtils.js b/yudao-ui-admin/src/utils/dateUtils.js similarity index 100% rename from yudao-admin-ui/src/utils/dateUtils.js rename to yudao-ui-admin/src/utils/dateUtils.js diff --git a/yudao-admin-ui/src/utils/db.js b/yudao-ui-admin/src/utils/db.js similarity index 100% rename from yudao-admin-ui/src/utils/db.js rename to yudao-ui-admin/src/utils/db.js diff --git a/yudao-ui-admin/src/utils/dict.js b/yudao-ui-admin/src/utils/dict.js new file mode 100644 index 0000000000..1c46aebe0a --- /dev/null +++ b/yudao-ui-admin/src/utils/dict.js @@ -0,0 +1,88 @@ +/** + * Created by 芋道源码 + * + * 数据字典工具类 + */ +import store from '@/store' + +export const DICT_TYPE = { + USER_TYPE: 'user_type', + COMMON_STATUS: 'common_status', + + // ========== SYSTEM 模块 ========== + SYSTEM_USER_SEX: 'system_user_sex', + SYSTEM_MENU_TYPE: 'system_menu_type', + SYSTEM_ROLE_TYPE: 'system_role_type', + SYSTEM_DATA_SCOPE: 'system_data_scope', + SYSTEM_NOTICE_TYPE: 'system_notice_type', + SYSTEM_OPERATE_TYPE: 'system_operate_type', + SYSTEM_LOGIN_TYPE: 'system_login_type', + SYSTEM_LOGIN_RESULT: 'system_login_result', + SYSTEM_SMS_CHANNEL_CODE: 'system_sms_channel_code', + SYSTEM_SMS_TEMPLATE_TYPE: 'system_sms_template_type', + SYSTEM_SMS_SEND_STATUS: 'system_sms_send_status', + SYSTEM_SMS_RECEIVE_STATUS: 'system_sms_receive_status', + SYSTEM_ERROR_CODE_TYPE: 'system_error_code_type', + + // ========== INFRA 模块 ========== + INFRA_REDIS_TIMEOUT_TYPE: 'infra_redis_timeout_type', + INFRA_JOB_STATUS: 'infra_job_status', + INFRA_JOB_LOG_STATUS: 'infra_job_log_status', + INFRA_API_ERROR_LOG_PROCESS_STATUS: 'infra_api_error_log_process_status', + INFRA_CONFIG_TYPE: 'infra_config_type', + + // ========== TOOL 模块 ========== + TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', + TOOL_CODEGEN_SCENE: 'tool_codegen_scene', + + // ========== BPM 模块 ========== + BPM_MODEL_CATEGORY: 'bpm_model_category', + BPM_MODEL_FORM_TYPE: 'bpm_model_form_type', + BPM_TASK_ASSIGN_RULE_TYPE: 'bpm_task_assign_rule_type', + BPM_PROCESS_INSTANCE_STATUS: 'bpm_process_instance_status', + BPM_PROCESS_INSTANCE_RESULT: 'bpm_process_instance_result', + BPM_TASK_ASSIGN_SCRIPT: 'bpm_task_assign_script', + BPM_OA_LEAVE_TYPE: 'bpm_oa_leave_type', + + // ========== PAY 模块 ========== + PAY_CHANNEL_WECHAT_VERSION: 'pay_channel_wechat_version', // 微信渠道版本 + PAY_CHANNEL_ALIPAY_SIGN_TYPE: 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型 + PAY_CHANNEL_ALIPAY_MODE: 'pay_channel_alipay_mode', // 支付宝公钥类型 + PAY_CHANNEL_ALIPAY_SERVER_TYPE: 'pay_channel_alipay_server_type', // 支付宝网关地址 + PAY_CHANNEL_CODE_TYPE: 'pay_channel_code_type', // 支付渠道编码类型 + PAY_ORDER_NOTIFY_STATUS: 'pay_order_notify_status', // 商户支付订单回调状态 + PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态 + PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', // 商户支付订单退款状态 + PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态 + PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别 +} + +/** + * 获取 dictType 对应的数据字典数组 + * + * @param dictType 数据类型 + * @returns {*|Array} 数据字典数组 + */ +export function getDictDatas(dictType) { + // if (dictType === 'bpm_task_assign_script') { + // console.log(store.getters.dict_datas[dictType]); + // debugger + // } + return store.getters.dict_datas[dictType] || [] +} + +export function getDictDataLabel(dictType, value) { + // 获取 dictType 对应的数据字典数组 + const dictDatas = getDictDatas(dictType) + if (!dictDatas || dictDatas.length === 0) { + return '' + } + // 获取 value 对应的展示名 + value = value + '' // 强制转换成字符串,因为 DictData 小类数值,是字符串 + for (const dictData of dictDatas) { + if (dictData.value === value) { + return dictData.label + } + } + return '' +} diff --git a/yudao-admin-ui/src/utils/errorCode.js b/yudao-ui-admin/src/utils/errorCode.js similarity index 100% rename from yudao-admin-ui/src/utils/errorCode.js rename to yudao-ui-admin/src/utils/errorCode.js diff --git a/yudao-admin-ui/src/utils/formGenerator.js b/yudao-ui-admin/src/utils/formGenerator.js similarity index 100% rename from yudao-admin-ui/src/utils/formGenerator.js rename to yudao-ui-admin/src/utils/formGenerator.js diff --git a/yudao-admin-ui/src/utils/icon.json b/yudao-ui-admin/src/utils/icon.json similarity index 100% rename from yudao-admin-ui/src/utils/icon.json rename to yudao-ui-admin/src/utils/icon.json diff --git a/yudao-admin-ui/src/utils/index.js b/yudao-ui-admin/src/utils/index.js similarity index 98% rename from yudao-admin-ui/src/utils/index.js rename to yudao-ui-admin/src/utils/index.js index 4d29dd0ece..5729937509 100644 --- a/yudao-admin-ui/src/utils/index.js +++ b/yudao-ui-admin/src/utils/index.js @@ -273,7 +273,7 @@ export function debounce(func, wait, immediate) { // } // 深拷贝对象 -// 【add by 芋道源码】https://github.com/JakHuang/form-generator/blob/dev/src/utils/index.js#L107 +// add by 芋道源码 https://github.com/JakHuang/form-generator/blob/dev/src/utils/index.js#L107 export function deepClone(obj) { const _toString = Object.prototype.toString diff --git a/yudao-admin-ui/src/utils/jsencrypt.js b/yudao-ui-admin/src/utils/jsencrypt.js similarity index 100% rename from yudao-admin-ui/src/utils/jsencrypt.js rename to yudao-ui-admin/src/utils/jsencrypt.js diff --git a/yudao-admin-ui/src/utils/loadBeautifier.js b/yudao-ui-admin/src/utils/loadBeautifier.js similarity index 100% rename from yudao-admin-ui/src/utils/loadBeautifier.js rename to yudao-ui-admin/src/utils/loadBeautifier.js diff --git a/yudao-admin-ui/src/utils/loadMonaco.js b/yudao-ui-admin/src/utils/loadMonaco.js similarity index 100% rename from yudao-admin-ui/src/utils/loadMonaco.js rename to yudao-ui-admin/src/utils/loadMonaco.js diff --git a/yudao-admin-ui/src/utils/loadScript.js b/yudao-ui-admin/src/utils/loadScript.js similarity index 100% rename from yudao-admin-ui/src/utils/loadScript.js rename to yudao-ui-admin/src/utils/loadScript.js diff --git a/yudao-admin-ui/src/utils/loadTinymce.js b/yudao-ui-admin/src/utils/loadTinymce.js similarity index 100% rename from yudao-admin-ui/src/utils/loadTinymce.js rename to yudao-ui-admin/src/utils/loadTinymce.js diff --git a/yudao-admin-ui/src/utils/permission.js b/yudao-ui-admin/src/utils/permission.js similarity index 100% rename from yudao-admin-ui/src/utils/permission.js rename to yudao-ui-admin/src/utils/permission.js diff --git a/yudao-admin-ui/src/utils/pluginsConfig.js b/yudao-ui-admin/src/utils/pluginsConfig.js similarity index 100% rename from yudao-admin-ui/src/utils/pluginsConfig.js rename to yudao-ui-admin/src/utils/pluginsConfig.js diff --git a/yudao-admin-ui/src/utils/request.js b/yudao-ui-admin/src/utils/request.js similarity index 96% rename from yudao-admin-ui/src/utils/request.js rename to yudao-ui-admin/src/utils/request.js index 7b8c2901f6..ee2fee18a0 100644 --- a/yudao-admin-ui/src/utils/request.js +++ b/yudao-ui-admin/src/utils/request.js @@ -9,7 +9,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' // 创建axios实例 const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 - baseURL: process.env.VUE_APP_BASE_API + '/api/', // 此处的 /api/ 地址,原因是后端的基础路径为 /api/ + baseURL: process.env.VUE_APP_BASE_API + '/admin-api/', // 此处的 /admin-api/ 地址,原因是后端的基础路径为 /admin-api/ // 超时 timeout: 10000 }) diff --git a/yudao-admin-ui/src/utils/ruoyi.js b/yudao-ui-admin/src/utils/ruoyi.js similarity index 100% rename from yudao-admin-ui/src/utils/ruoyi.js rename to yudao-ui-admin/src/utils/ruoyi.js diff --git a/yudao-admin-ui/src/utils/scroll-to.js b/yudao-ui-admin/src/utils/scroll-to.js similarity index 100% rename from yudao-admin-ui/src/utils/scroll-to.js rename to yudao-ui-admin/src/utils/scroll-to.js diff --git a/yudao-admin-ui/src/utils/validate.js b/yudao-ui-admin/src/utils/validate.js similarity index 100% rename from yudao-admin-ui/src/utils/validate.js rename to yudao-ui-admin/src/utils/validate.js diff --git a/yudao-admin-ui/src/views/bpm/definition/index.vue b/yudao-ui-admin/src/views/bpm/definition/index.vue similarity index 100% rename from yudao-admin-ui/src/views/bpm/definition/index.vue rename to yudao-ui-admin/src/views/bpm/definition/index.vue diff --git a/yudao-admin-ui/src/views/bpm/form/formEditor.vue b/yudao-ui-admin/src/views/bpm/form/formEditor.vue similarity index 99% rename from yudao-admin-ui/src/views/bpm/form/formEditor.vue rename to yudao-ui-admin/src/views/bpm/form/formEditor.vue index b04ef694e4..c2ec15e32c 100644 --- a/yudao-admin-ui/src/views/bpm/form/formEditor.vue +++ b/yudao-ui-admin/src/views/bpm/form/formEditor.vue @@ -42,7 +42,7 @@ - {{dict.label}} @@ -167,7 +167,7 @@ import { getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf } from '@/utils/db' import loadBeautifier from '@/utils/loadBeautifier' -import {SysCommonStatusEnum} from "@/utils/constants"; +import {CommonStatusEnum} from "@/utils/constants"; import {createForm, getForm, updateForm} from "@/api/bpm/form"; import {decodeFields} from "@/utils/formGenerator"; @@ -232,7 +232,7 @@ export default { // 表单参数 form: { - status: SysCommonStatusEnum.ENABLE, + status: CommonStatusEnum.ENABLE, }, // 表单校验 rules: { diff --git a/yudao-admin-ui/src/views/bpm/form/index.vue b/yudao-ui-admin/src/views/bpm/form/index.vue similarity index 98% rename from yudao-admin-ui/src/views/bpm/form/index.vue rename to yudao-ui-admin/src/views/bpm/form/index.vue index 15943b7cef..41be534d3d 100644 --- a/yudao-admin-ui/src/views/bpm/form/index.vue +++ b/yudao-ui-admin/src/views/bpm/form/index.vue @@ -27,7 +27,7 @@ diff --git a/yudao-admin-ui/src/views/bpm/group/index.vue b/yudao-ui-admin/src/views/bpm/group/index.vue similarity index 97% rename from yudao-admin-ui/src/views/bpm/group/index.vue rename to yudao-ui-admin/src/views/bpm/group/index.vue index f0407270c0..9b2372c999 100644 --- a/yudao-admin-ui/src/views/bpm/group/index.vue +++ b/yudao-ui-admin/src/views/bpm/group/index.vue @@ -8,7 +8,7 @@ - @@ -45,7 +45,7 @@ @@ -82,7 +82,7 @@ - {{dict.label}} @@ -97,7 +97,7 @@