diff --git a/.github/workflows/english-bolt.yml b/.github/workflows/english-bolt.yml new file mode 100644 index 0000000..ab963c6 --- /dev/null +++ b/.github/workflows/english-bolt.yml @@ -0,0 +1,15 @@ +name: 'issues-translator' +on: + issue_comment: + types: [created] + issues: + types: [opened] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: usthe/issues-translate-action@v2.7 + with: + IS_MODIFY_TITLE: true + # BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }} diff --git a/README-CN.md b/README-CN.md index 3b480a8..3ae4c65 100644 --- a/README-CN.md +++ b/README-CN.md @@ -11,18 +11,33 @@ [![CN doc](https://img.shields.io/badge/文档-中文版-blue.svg)](README-CN.md) #### 介绍 -dataCompare 是一个数据库比对工具:支持hive表数据比对,mysql、Doris 数据比对,实现自动化配置进行数据比对,避免频繁写sql 进行处理,后续考虑支持ck等等 +dataCompare 是一个大数据数据比对和数据探测平台 + +(1)支持hive表数据比对,mysql、Doris 数据比对,实现自动化配置进行数据比对,避免频繁写sql 进行处理 + +(2)支持少量配置即可实现数据探测 ![image](https://user-images.githubusercontent.com/28300167/207563954-6e3dba02-84de-4881-9a23-371b88ed5b1e.png) +![image](https://user-images.githubusercontent.com/28300167/226346775-f1c1ed2d-8370-45db-878c-8ab81d9e402e.png) + #### 功能介绍 -(1)低代码配置,即可实现数据表的对比,不需要繁琐的sql开发 -(2)目前已经支持如下功能: 量级对比、一致性对比、差异case 发现,已经支持MySQL、Hive、Doris +数据对比: + +(1)界面级交互数据对比任务配置,低代码少量配置快速生成对比任务 -(3)后续计划支持:陌生表指针探测,包括:枚举值探测、范围值探测、主键id hash 探测 +(2)量级对比、一致性对比、自动化差异case发现 +(3)目前已经支持MySQL、Apache Hive、Apache Doris 等JDBC 数据库 +(4)已经支持对比结果自动发送邮件告警报告 + +数据探针: + +(1)低代码、少量配置即可完成数据探测 + +(2)主键、枚举值、空值探测 #### 软件架构 ![输入图片说明](image77.png) @@ -54,6 +69,8 @@ dataCompare 是一个数据库比对工具:支持hive表数据比对,mysql 系统主页 ![image](https://user-images.githubusercontent.com/28300167/207257662-273fc531-c21e-437a-9d20-f15a533b58bd.png) +(1)数据对比功能展示 + 数据库配置 mysql配置 @@ -75,6 +92,20 @@ job配置 ![3fd83de9c582347f7f88cc82f438db4](https://user-images.githubusercontent.com/28300167/208607767-94cffce0-30f3-45ec-a280-978964e153bb.png) +(2)数据探针 + +job配置 + +![img_2.png](img_2.png) + +探针结果 + +![img_3.png](img_3.png) + +![img_4.png](img_4.png) + +![image](https://user-images.githubusercontent.com/28300167/229501053-4e33b6fb-851a-4fb2-9b19-16308359f57e.png) + #### 系统运行 系统运行环境要求: @@ -86,9 +117,10 @@ mysql 5.7.36 (1)将sql目录中的sql文件进行运行在数据库,创建库和表 -(2)下载发布好的jar(https://github.com/zhugezifang/dataCompare/releases) 或者自己构建jar +(2)在根目录下面进行mvn clean package,使用target 目录下的dataCompare.jar -(3)修改数据库配置信息 application.yml +(3)修改数据库配置信息 application.yml,将数据库连接信息改为步骤(1)的数据库连接信息 +![47d1145d147214348d6d0f2fc599ea7](https://user-images.githubusercontent.com/28300167/219598181-5731e845-a49e-43af-a96c-db6d6148b11a.png) (4)运行 java -jar -Dspring.config.location=application.yml dataCompare.jar (application.yml和jar在同一目录下) diff --git a/README.md b/README.md index 5e1c0e6..1c44ce0 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,34 @@ #### Introduction -dataCompare is a database comparison platform: support Hive table data comparison, MySQL、Doris data comparison, realize automatic configuration for data comparison, avoid frequent SQL writing for processing, and consider supporting CK and so on +dataCompare is a database comparison and profiling platform + +(1)support Hive table data comparison, MySQL、Doris data comparison, realize automatic configuration for data comparison, avoid frequent SQL writing for processing + +(2)support easy configuration for data profiling ![image](https://user-images.githubusercontent.com/28300167/207563534-e4df0c95-846b-4cf3-be68-37b91bd05f0b.png) +![image](https://user-images.githubusercontent.com/28300167/226346775-f1c1ed2d-8370-45db-878c-8ab81d9e402e.png) + + #### Features -(1)Low-code configuration can realize the comparison of data tables without cumbersome sql development -(2)The following functions are currently supported: magnitude comparison, consistency comparison, difference case discovery, MySQL、Hive and Doris haved already supported +data-compare + +(1)Interface-level interactive data comparison task configuration, low code and small amount of configuration to quickly generate comparison tasks -(3)Subsequent plan support: unfamiliar table pointer detection, including: enumeration value detection, range value detection, primary key id hash detection +(2)Magnitude comparison, consistency comparison, automatic difference case discovery +(3)JDBC databases such as MySQL, Apache Hive, and Apache Doris are currently supported + +(4)Already supports the comparison results to automatically send email alarm reports + +data-profiling + +(1)Data detection can be completed with low code and a small amount of configuration + +(2)Primary key, enumeration value, null value detection #### Software Architecture @@ -57,6 +74,8 @@ Big Data:Hive、Spark Home ![image](https://user-images.githubusercontent.com/28300167/207257662-273fc531-c21e-437a-9d20-f15a533b58bd.png) +data-compare: + DbConfig mysql config @@ -78,6 +97,19 @@ Comparison results are displayed ![3fd83de9c582347f7f88cc82f438db4](https://user-images.githubusercontent.com/28300167/208607767-94cffce0-30f3-45ec-a280-978964e153bb.png) +data-profiling: + +job config + +![img_2.png](img_2.png) + +profiling result + +![img_3.png](img_3.png) + +![img_4.png](img_4.png) + +![image](https://user-images.githubusercontent.com/28300167/229501053-4e33b6fb-851a-4fb2-9b19-16308359f57e.png) #### The system running environment @@ -89,7 +121,7 @@ Runing config (1)Run the SQL files in the SQL directory in the database, create database and tables -(2)download the release jar(https://github.com/zhugezifang/dataCompare/releases) or build jar using the source code of the project +(2)build jar using the source code of the project: mvn clean package (3)edit database config information of application.yml @@ -103,10 +135,8 @@ Environment installation configuration (2)After installation, when creating a new data source connection, select Hive at the address jdbc:hive2://ip:10000 - -#### Technological Communication -![image](https://user-images.githubusercontent.com/28300167/207255900-152d6834-9602-4ada-91ca-ad9906d89bf8.png) - +#### Star History +[![Star History Chart](https://api.star-history.com/svg?repos=zhugezifang/dataCompare&type=Date)](https://star-history.com/#zhugezifang/dataCompare&Date) #### Thanks Thanks ruoyi Provides front-end services diff --git a/img_2.png b/img_2.png new file mode 100644 index 0000000..205b52a Binary files /dev/null and b/img_2.png differ diff --git a/img_3.png b/img_3.png new file mode 100644 index 0000000..9a51791 Binary files /dev/null and b/img_3.png differ diff --git a/img_4.png b/img_4.png new file mode 100644 index 0000000..f3d7bb2 Binary files /dev/null and b/img_4.png differ diff --git a/pom.xml b/pom.xml index cc42d73..9650392 100644 --- a/pom.xml +++ b/pom.xml @@ -257,6 +257,10 @@ jetty-all org.eclipse.jetty.aggregate + + jdk.tools + jdk.tools + @@ -266,6 +270,11 @@ ${antlr4.version} + + org.springframework.boot + spring-boot-starter-mail + + diff --git a/sql/dataCompare.sql b/sql/dataCompare.sql index 907ebd8..0623475 100644 --- a/sql/dataCompare.sql +++ b/sql/dataCompare.sql @@ -1,3 +1,4 @@ + SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- @@ -14,7 +15,7 @@ CREATE TABLE `db_config` ( `create_time` datetime DEFAULT NULL COMMENT 'create_time', `create_by` varchar(255) DEFAULT NULL COMMENT 'create_by', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='db config'; +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='db config'; -- ---------------------------- -- Table structure for gen_table @@ -104,7 +105,7 @@ CREATE TABLE `job_config` ( `origin_table_group` text, `to_table_group` text, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='job_config'; +) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8 COMMENT='job_config'; -- ---------------------------- -- Table structure for job_instance @@ -127,7 +128,44 @@ CREATE TABLE `job_instance` ( `dt` varchar(255) DEFAULT NULL COMMENT 'dt', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COMMENT='job_instance'; +) ENGINE=InnoDB AUTO_INCREMENT=7259 DEFAULT CHARSET=utf8 COMMENT='job_instance'; + +-- ---------------------------- +-- Records of job_instance +-- ---------------------------- + +-- ---------------------------- +-- Table structure for probe_job_config +-- ---------------------------- +DROP TABLE IF EXISTS `probe_job_config`; +CREATE TABLE `probe_job_config` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `table_name` varchar(255) NOT NULL, + `table_primary` varchar(255) DEFAULT NULL, + `table_enum_fields` varchar(255) DEFAULT NULL COMMENT 'table_enum_fields', + `table_null_fields` varchar(255) DEFAULT NULL COMMENT 'table_null_fields', + `table_length_fields` varchar(255) DEFAULT NULL COMMENT 'table_length_fields', + `filter` varchar(255) DEFAULT NULL COMMENT 'filter', + `db_config_id` int(11) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `create_by` varchar(255) DEFAULT NULL COMMENT 'create_by', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='probe_job_config'; + +-- ---------------------------- +-- Table structure for probe_job_instance +-- ---------------------------- +DROP TABLE IF EXISTS `probe_job_instance`; +CREATE TABLE `probe_job_instance` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_config_id` int(11) NOT NULL, + `primary_result` text COMMENT 'primary_result', + `enum_result` text COMMENT 'enum_result', + `null_result` text COMMENT 'null_result', + `len_result` text COMMENT 'len_result', + `create_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 COMMENT='probe_job_instance'; -- ---------------------------- -- Table structure for QRTZ_BLOB_TRIGGERS @@ -525,7 +563,7 @@ CREATE TABLE `sys_job` ( -- ---------------------------- -- Records of sys_job -- ---------------------------- -INSERT INTO `sys_job` VALUES ('1', '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2022-11-25 05:04:10', '', null, ''); +INSERT INTO `sys_job` VALUES ('1', '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2022-11-25 05:04:10', '', '2022-12-21 07:34:33', ''); INSERT INTO `sys_job` VALUES ('2', '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', '2022-11-25 05:04:10', '', null, ''); INSERT INTO `sys_job` VALUES ('3', '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', '2022-11-25 05:04:10', '', null, ''); @@ -543,12 +581,7 @@ CREATE TABLE `sys_job_log` ( `exception_info` varchar(2000) DEFAULT '' COMMENT '异常信息', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`job_log_id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='定时任务调度日志表'; - --- ---------------------------- --- Records of sys_job_log --- ---------------------------- -INSERT INTO `sys_job_log` VALUES ('1', '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '系统默认(无参) 总共耗时:2毫秒', '0', '', '2022-11-25 05:08:23'); +) ENGINE=InnoDB AUTO_INCREMENT=209 DEFAULT CHARSET=utf8 COMMENT='定时任务调度日志表'; -- ---------------------------- -- Table structure for sys_logininfor @@ -565,234 +598,7 @@ CREATE TABLE `sys_logininfor` ( `msg` varchar(255) DEFAULT '' COMMENT '提示消息', `login_time` datetime DEFAULT NULL COMMENT '访问时间', PRIMARY KEY (`info_id`) -) ENGINE=InnoDB AUTO_INCREMENT=323 DEFAULT CHARSET=utf8 COMMENT='系统访问记录'; - --- ---------------------------- --- Records of sys_logininfor --- ---------------------------- -INSERT INTO `sys_logininfor` VALUES ('100', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '1', '验证码错误', '2022-11-25 05:07:29'); -INSERT INTO `sys_logininfor` VALUES ('101', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 05:07:53'); -INSERT INTO `sys_logininfor` VALUES ('102', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '退出成功', '2022-11-25 05:09:43'); -INSERT INTO `sys_logininfor` VALUES ('103', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 05:21:10'); -INSERT INTO `sys_logininfor` VALUES ('104', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '退出成功', '2022-11-25 05:23:15'); -INSERT INTO `sys_logininfor` VALUES ('105', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '1', '验证码错误', '2022-11-25 06:16:31'); -INSERT INTO `sys_logininfor` VALUES ('106', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 06:16:40'); -INSERT INTO `sys_logininfor` VALUES ('107', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 06:39:08'); -INSERT INTO `sys_logininfor` VALUES ('108', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 06:44:23'); -INSERT INTO `sys_logininfor` VALUES ('109', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 06:51:09'); -INSERT INTO `sys_logininfor` VALUES ('110', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-25 10:12:07'); -INSERT INTO `sys_logininfor` VALUES ('111', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 04:53:02'); -INSERT INTO `sys_logininfor` VALUES ('112', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 05:00:47'); -INSERT INTO `sys_logininfor` VALUES ('113', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 05:06:27'); -INSERT INTO `sys_logininfor` VALUES ('114', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 05:16:46'); -INSERT INTO `sys_logininfor` VALUES ('115', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 06:17:17'); -INSERT INTO `sys_logininfor` VALUES ('116', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 06:27:33'); -INSERT INTO `sys_logininfor` VALUES ('117', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 06:34:26'); -INSERT INTO `sys_logininfor` VALUES ('118', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 09:53:04'); -INSERT INTO `sys_logininfor` VALUES ('119', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 10:02:49'); -INSERT INTO `sys_logininfor` VALUES ('120', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 10:04:39'); -INSERT INTO `sys_logininfor` VALUES ('121', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 10:11:37'); -INSERT INTO `sys_logininfor` VALUES ('122', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 12:40:46'); -INSERT INTO `sys_logininfor` VALUES ('123', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-29 13:22:58'); -INSERT INTO `sys_logininfor` VALUES ('124', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:01:21'); -INSERT INTO `sys_logininfor` VALUES ('125', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:09:58'); -INSERT INTO `sys_logininfor` VALUES ('126', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:11:41'); -INSERT INTO `sys_logininfor` VALUES ('127', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:24:33'); -INSERT INTO `sys_logininfor` VALUES ('128', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:31:40'); -INSERT INTO `sys_logininfor` VALUES ('129', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:33:32'); -INSERT INTO `sys_logininfor` VALUES ('130', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:36:10'); -INSERT INTO `sys_logininfor` VALUES ('131', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 02:45:14'); -INSERT INTO `sys_logininfor` VALUES ('132', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 03:11:08'); -INSERT INTO `sys_logininfor` VALUES ('133', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 03:14:02'); -INSERT INTO `sys_logininfor` VALUES ('134', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 03:15:53'); -INSERT INTO `sys_logininfor` VALUES ('135', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 03:18:22'); -INSERT INTO `sys_logininfor` VALUES ('136', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 04:51:34'); -INSERT INTO `sys_logininfor` VALUES ('137', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 04:54:36'); -INSERT INTO `sys_logininfor` VALUES ('138', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 04:56:21'); -INSERT INTO `sys_logininfor` VALUES ('139', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 06:05:30'); -INSERT INTO `sys_logininfor` VALUES ('140', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 06:19:22'); -INSERT INTO `sys_logininfor` VALUES ('141', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 06:28:48'); -INSERT INTO `sys_logininfor` VALUES ('142', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 06:32:54'); -INSERT INTO `sys_logininfor` VALUES ('143', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 06:47:23'); -INSERT INTO `sys_logininfor` VALUES ('144', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 07:06:37'); -INSERT INTO `sys_logininfor` VALUES ('145', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 07:12:55'); -INSERT INTO `sys_logininfor` VALUES ('146', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:35:33'); -INSERT INTO `sys_logininfor` VALUES ('147', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:37:34'); -INSERT INTO `sys_logininfor` VALUES ('148', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:40:20'); -INSERT INTO `sys_logininfor` VALUES ('149', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:46:36'); -INSERT INTO `sys_logininfor` VALUES ('150', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:49:03'); -INSERT INTO `sys_logininfor` VALUES ('151', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:50:17'); -INSERT INTO `sys_logininfor` VALUES ('152', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:51:39'); -INSERT INTO `sys_logininfor` VALUES ('153', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-11-30 09:53:03'); -INSERT INTO `sys_logininfor` VALUES ('154', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 03:23:46'); -INSERT INTO `sys_logininfor` VALUES ('155', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 03:26:48'); -INSERT INTO `sys_logininfor` VALUES ('156', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 03:31:48'); -INSERT INTO `sys_logininfor` VALUES ('157', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 03:36:19'); -INSERT INTO `sys_logininfor` VALUES ('158', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 03:58:22'); -INSERT INTO `sys_logininfor` VALUES ('159', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 04:04:17'); -INSERT INTO `sys_logininfor` VALUES ('160', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 04:10:04'); -INSERT INTO `sys_logininfor` VALUES ('161', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 05:19:26'); -INSERT INTO `sys_logininfor` VALUES ('162', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 05:59:14'); -INSERT INTO `sys_logininfor` VALUES ('163', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 06:11:17'); -INSERT INTO `sys_logininfor` VALUES ('164', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 06:19:43'); -INSERT INTO `sys_logininfor` VALUES ('165', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-01 06:54:55'); -INSERT INTO `sys_logininfor` VALUES ('166', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:24:29'); -INSERT INTO `sys_logininfor` VALUES ('167', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:30:22'); -INSERT INTO `sys_logininfor` VALUES ('168', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:33:52'); -INSERT INTO `sys_logininfor` VALUES ('169', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:35:17'); -INSERT INTO `sys_logininfor` VALUES ('170', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:37:30'); -INSERT INTO `sys_logininfor` VALUES ('171', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:42:16'); -INSERT INTO `sys_logininfor` VALUES ('172', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:45:08'); -INSERT INTO `sys_logininfor` VALUES ('173', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:48:42'); -INSERT INTO `sys_logininfor` VALUES ('174', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:53:27'); -INSERT INTO `sys_logininfor` VALUES ('175', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:56:07'); -INSERT INTO `sys_logininfor` VALUES ('176', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 11:58:48'); -INSERT INTO `sys_logininfor` VALUES ('177', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 12:03:20'); -INSERT INTO `sys_logininfor` VALUES ('178', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 12:09:24'); -INSERT INTO `sys_logininfor` VALUES ('179', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 12:14:59'); -INSERT INTO `sys_logininfor` VALUES ('180', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 12:16:20'); -INSERT INTO `sys_logininfor` VALUES ('181', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-04 12:17:33'); -INSERT INTO `sys_logininfor` VALUES ('182', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-05 08:53:20'); -INSERT INTO `sys_logininfor` VALUES ('183', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-05 09:17:13'); -INSERT INTO `sys_logininfor` VALUES ('184', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-05 10:07:45'); -INSERT INTO `sys_logininfor` VALUES ('185', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-05 10:11:09'); -INSERT INTO `sys_logininfor` VALUES ('186', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-05 10:12:48'); -INSERT INTO `sys_logininfor` VALUES ('187', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:43:51'); -INSERT INTO `sys_logininfor` VALUES ('188', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:45:54'); -INSERT INTO `sys_logininfor` VALUES ('189', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:49:33'); -INSERT INTO `sys_logininfor` VALUES ('190', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:50:55'); -INSERT INTO `sys_logininfor` VALUES ('191', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:52:21'); -INSERT INTO `sys_logininfor` VALUES ('192', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:53:36'); -INSERT INTO `sys_logininfor` VALUES ('193', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-06 12:56:03'); -INSERT INTO `sys_logininfor` VALUES ('194', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-08 06:56:20'); -INSERT INTO `sys_logininfor` VALUES ('195', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-08 06:58:10'); -INSERT INTO `sys_logininfor` VALUES ('196', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 02:59:48'); -INSERT INTO `sys_logininfor` VALUES ('197', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 03:40:39'); -INSERT INTO `sys_logininfor` VALUES ('198', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 03:46:00'); -INSERT INTO `sys_logininfor` VALUES ('199', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 03:47:24'); -INSERT INTO `sys_logininfor` VALUES ('200', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 03:49:38'); -INSERT INTO `sys_logininfor` VALUES ('201', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:19:20'); -INSERT INTO `sys_logininfor` VALUES ('202', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:25:09'); -INSERT INTO `sys_logininfor` VALUES ('203', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:28:03'); -INSERT INTO `sys_logininfor` VALUES ('204', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:33:10'); -INSERT INTO `sys_logininfor` VALUES ('205', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:37:05'); -INSERT INTO `sys_logininfor` VALUES ('206', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:46:47'); -INSERT INTO `sys_logininfor` VALUES ('207', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 08:58:01'); -INSERT INTO `sys_logininfor` VALUES ('208', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:00:10'); -INSERT INTO `sys_logininfor` VALUES ('209', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:02:04'); -INSERT INTO `sys_logininfor` VALUES ('210', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:04:06'); -INSERT INTO `sys_logininfor` VALUES ('211', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:06:50'); -INSERT INTO `sys_logininfor` VALUES ('212', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:10:20'); -INSERT INTO `sys_logininfor` VALUES ('213', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:14:51'); -INSERT INTO `sys_logininfor` VALUES ('214', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:17:37'); -INSERT INTO `sys_logininfor` VALUES ('215', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:21:24'); -INSERT INTO `sys_logininfor` VALUES ('216', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:24:15'); -INSERT INTO `sys_logininfor` VALUES ('217', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 09:52:10'); -INSERT INTO `sys_logininfor` VALUES ('218', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 10:01:08'); -INSERT INTO `sys_logininfor` VALUES ('219', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 10:04:19'); -INSERT INTO `sys_logininfor` VALUES ('220', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-12 10:06:12'); -INSERT INTO `sys_logininfor` VALUES ('221', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 01:58:49'); -INSERT INTO `sys_logininfor` VALUES ('222', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:17:34'); -INSERT INTO `sys_logininfor` VALUES ('223', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:35:23'); -INSERT INTO `sys_logininfor` VALUES ('224', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:40:58'); -INSERT INTO `sys_logininfor` VALUES ('225', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:43:12'); -INSERT INTO `sys_logininfor` VALUES ('226', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:46:46'); -INSERT INTO `sys_logininfor` VALUES ('227', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:53:09'); -INSERT INTO `sys_logininfor` VALUES ('228', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 03:55:33'); -INSERT INTO `sys_logininfor` VALUES ('229', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 04:01:44'); -INSERT INTO `sys_logininfor` VALUES ('230', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 04:56:07'); -INSERT INTO `sys_logininfor` VALUES ('231', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:09:20'); -INSERT INTO `sys_logininfor` VALUES ('232', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:11:51'); -INSERT INTO `sys_logininfor` VALUES ('233', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:13:11'); -INSERT INTO `sys_logininfor` VALUES ('234', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:18:22'); -INSERT INTO `sys_logininfor` VALUES ('235', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:20:54'); -INSERT INTO `sys_logininfor` VALUES ('236', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:23:54'); -INSERT INTO `sys_logininfor` VALUES ('237', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 05:29:19'); -INSERT INTO `sys_logininfor` VALUES ('238', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:00:57'); -INSERT INTO `sys_logininfor` VALUES ('239', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:04:07'); -INSERT INTO `sys_logininfor` VALUES ('240', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:06:25'); -INSERT INTO `sys_logininfor` VALUES ('241', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:08:09'); -INSERT INTO `sys_logininfor` VALUES ('242', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:13:22'); -INSERT INTO `sys_logininfor` VALUES ('243', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:14:52'); -INSERT INTO `sys_logininfor` VALUES ('244', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:20:01'); -INSERT INTO `sys_logininfor` VALUES ('245', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:21:42'); -INSERT INTO `sys_logininfor` VALUES ('246', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:24:11'); -INSERT INTO `sys_logininfor` VALUES ('247', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:39:42'); -INSERT INTO `sys_logininfor` VALUES ('248', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:48:33'); -INSERT INTO `sys_logininfor` VALUES ('249', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 06:52:56'); -INSERT INTO `sys_logininfor` VALUES ('250', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 07:49:11'); -INSERT INTO `sys_logininfor` VALUES ('251', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 08:26:58'); -INSERT INTO `sys_logininfor` VALUES ('252', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 08:40:24'); -INSERT INTO `sys_logininfor` VALUES ('253', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 08:58:14'); -INSERT INTO `sys_logininfor` VALUES ('254', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-13 10:34:33'); -INSERT INTO `sys_logininfor` VALUES ('255', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-14 03:21:06'); -INSERT INTO `sys_logininfor` VALUES ('256', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 01:58:35'); -INSERT INTO `sys_logininfor` VALUES ('257', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 02:16:00'); -INSERT INTO `sys_logininfor` VALUES ('258', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 05:42:22'); -INSERT INTO `sys_logininfor` VALUES ('259', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:16:03'); -INSERT INTO `sys_logininfor` VALUES ('260', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:19:09'); -INSERT INTO `sys_logininfor` VALUES ('261', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:23:42'); -INSERT INTO `sys_logininfor` VALUES ('262', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:26:32'); -INSERT INTO `sys_logininfor` VALUES ('263', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:33:36'); -INSERT INTO `sys_logininfor` VALUES ('264', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:48:16'); -INSERT INTO `sys_logininfor` VALUES ('265', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:51:39'); -INSERT INTO `sys_logininfor` VALUES ('266', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:53:38'); -INSERT INTO `sys_logininfor` VALUES ('267', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 08:58:36'); -INSERT INTO `sys_logininfor` VALUES ('268', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:07:09'); -INSERT INTO `sys_logininfor` VALUES ('269', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:09:53'); -INSERT INTO `sys_logininfor` VALUES ('270', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:28:21'); -INSERT INTO `sys_logininfor` VALUES ('271', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:30:25'); -INSERT INTO `sys_logininfor` VALUES ('272', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:34:11'); -INSERT INTO `sys_logininfor` VALUES ('273', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:36:12'); -INSERT INTO `sys_logininfor` VALUES ('274', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:46:02'); -INSERT INTO `sys_logininfor` VALUES ('275', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:48:14'); -INSERT INTO `sys_logininfor` VALUES ('276', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:52:46'); -INSERT INTO `sys_logininfor` VALUES ('277', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:55:32'); -INSERT INTO `sys_logininfor` VALUES ('278', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:56:58'); -INSERT INTO `sys_logininfor` VALUES ('279', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 09:59:22'); -INSERT INTO `sys_logininfor` VALUES ('280', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:01:07'); -INSERT INTO `sys_logininfor` VALUES ('281', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:03:49'); -INSERT INTO `sys_logininfor` VALUES ('282', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:07:10'); -INSERT INTO `sys_logininfor` VALUES ('283', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:09:49'); -INSERT INTO `sys_logininfor` VALUES ('284', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:11:01'); -INSERT INTO `sys_logininfor` VALUES ('285', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:12:35'); -INSERT INTO `sys_logininfor` VALUES ('286', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:17:08'); -INSERT INTO `sys_logininfor` VALUES ('287', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:19:21'); -INSERT INTO `sys_logininfor` VALUES ('288', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 10:21:35'); -INSERT INTO `sys_logininfor` VALUES ('289', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 11:05:23'); -INSERT INTO `sys_logininfor` VALUES ('290', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-15 11:09:24'); -INSERT INTO `sys_logininfor` VALUES ('291', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 02:13:20'); -INSERT INTO `sys_logininfor` VALUES ('292', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 12:47:13'); -INSERT INTO `sys_logininfor` VALUES ('293', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 12:52:26'); -INSERT INTO `sys_logininfor` VALUES ('294', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 12:54:25'); -INSERT INTO `sys_logininfor` VALUES ('295', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 13:01:36'); -INSERT INTO `sys_logininfor` VALUES ('296', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 13:05:10'); -INSERT INTO `sys_logininfor` VALUES ('297', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 13:08:56'); -INSERT INTO `sys_logininfor` VALUES ('298', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 13:10:32'); -INSERT INTO `sys_logininfor` VALUES ('299', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-19 13:11:35'); -INSERT INTO `sys_logininfor` VALUES ('300', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 01:59:13'); -INSERT INTO `sys_logininfor` VALUES ('301', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:01:20'); -INSERT INTO `sys_logininfor` VALUES ('302', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:29:56'); -INSERT INTO `sys_logininfor` VALUES ('303', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:36:21'); -INSERT INTO `sys_logininfor` VALUES ('304', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:40:10'); -INSERT INTO `sys_logininfor` VALUES ('305', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:41:37'); -INSERT INTO `sys_logininfor` VALUES ('306', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 02:44:07'); -INSERT INTO `sys_logininfor` VALUES ('307', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 03:19:55'); -INSERT INTO `sys_logininfor` VALUES ('308', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 03:32:26'); -INSERT INTO `sys_logininfor` VALUES ('309', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:21:25'); -INSERT INTO `sys_logininfor` VALUES ('310', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:24:01'); -INSERT INTO `sys_logininfor` VALUES ('311', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:26:26'); -INSERT INTO `sys_logininfor` VALUES ('312', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:27:33'); -INSERT INTO `sys_logininfor` VALUES ('313', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:30:28'); -INSERT INTO `sys_logininfor` VALUES ('314', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:35:25'); -INSERT INTO `sys_logininfor` VALUES ('315', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:38:28'); -INSERT INTO `sys_logininfor` VALUES ('316', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:46:18'); -INSERT INTO `sys_logininfor` VALUES ('317', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:47:46'); -INSERT INTO `sys_logininfor` VALUES ('318', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 06:55:47'); -INSERT INTO `sys_logininfor` VALUES ('319', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 07:00:05'); -INSERT INTO `sys_logininfor` VALUES ('320', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 07:01:52'); -INSERT INTO `sys_logininfor` VALUES ('321', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 07:20:05'); -INSERT INTO `sys_logininfor` VALUES ('322', 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '登录成功', '2022-12-20 07:24:09'); +) ENGINE=InnoDB AUTO_INCREMENT=409 DEFAULT CHARSET=utf8 COMMENT='系统访问记录'; -- ---------------------------- -- Table structure for sys_menu @@ -816,16 +622,16 @@ CREATE TABLE `sys_menu` ( `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar(500) DEFAULT '' COMMENT '备注', PRIMARY KEY (`menu_id`) -) ENGINE=InnoDB AUTO_INCREMENT=2008 DEFAULT CHARSET=utf8 COMMENT='菜单权限表'; +) ENGINE=InnoDB AUTO_INCREMENT=2013 DEFAULT CHARSET=utf8 COMMENT='菜单权限表'; -- ---------------------------- -- Records of sys_menu -- ---------------------------- -INSERT INTO `sys_menu` VALUES ('1', '系统管理', '0', '1', '#', 'menuItem', 'M', '1', '1', '', 'fa fa-gear', 'admin', '2022-11-29 10:10:28', 'admin', '2022-12-12 09:52:29', '系统管理目录'); +INSERT INTO `sys_menu` VALUES ('1', '系统管理', '0', '1', '#', 'menuItem', 'M', '1', '1', '', 'fa fa-gear', 'admin', '2022-11-29 10:10:28', 'admin', '2023-03-17 10:13:17', '系统管理目录'); INSERT INTO `sys_menu` VALUES ('2', '系统监控', '0', '2', '#', 'menuItem', 'M', '1', '1', '', 'fa fa-video-camera', 'admin', '2022-11-29 10:10:29', 'admin', '2022-12-12 09:24:32', '系统监控目录'); INSERT INTO `sys_menu` VALUES ('3', '系统工具', '0', '3', '#', 'menuItem', 'M', '1', '1', '', 'fa fa-bars', 'admin', '2022-11-29 10:10:29', 'admin', '2022-12-12 09:24:39', '系统工具目录'); INSERT INTO `sys_menu` VALUES ('4', '若依官网', '0', '4', 'http://ruoyi.vip', 'menuBlank', 'C', '1', '1', '', 'fa fa-location-arrow', 'admin', '2022-11-29 10:10:29', 'admin', '2022-12-12 09:24:48', '若依官网地址'); -INSERT INTO `sys_menu` VALUES ('5', '数据配置管理', '0', '5', '#', '', 'M', '0', '1', '', 'fa fa-gear', 'admin', '2022-11-29 12:15:43', '', null, '数据配置管理'); +INSERT INTO `sys_menu` VALUES ('5', '数据源配置', '0', '5', '#', 'menuItem', 'M', '0', '1', '', 'fa fa-bars', 'admin', '2022-11-29 12:15:43', 'admin', '2023-03-05 13:35:43', '数据配置管理'); INSERT INTO `sys_menu` VALUES ('100', '用户管理', '1', '1', '/system/user', '', 'C', '0', '1', 'system:user:view', 'fa fa-user-o', 'admin', '2022-11-29 10:10:29', '', null, '用户管理菜单'); INSERT INTO `sys_menu` VALUES ('101', '角色管理', '1', '2', '/system/role', '', 'C', '0', '1', 'system:role:view', 'fa fa-user-secret', 'admin', '2022-11-29 10:10:29', '', null, '角色管理菜单'); INSERT INTO `sys_menu` VALUES ('102', '菜单管理', '1', '3', '/system/menu', '', 'C', '0', '1', 'system:menu:view', 'fa fa-th-list', 'admin', '2022-11-29 10:10:29', '', null, '菜单管理菜单'); @@ -843,7 +649,7 @@ INSERT INTO `sys_menu` VALUES ('113', '缓存监控', '2', '5', '/monitor/cache' INSERT INTO `sys_menu` VALUES ('114', '表单构建', '3', '1', '/tool/build', '', 'C', '0', '1', 'tool:build:view', 'fa fa-wpforms', 'admin', '2022-11-29 10:10:30', '', null, '表单构建菜单'); INSERT INTO `sys_menu` VALUES ('115', '代码生成', '3', '2', '/tool/gen', '', 'C', '0', '1', 'tool:gen:view', 'fa fa-code', 'admin', '2022-11-29 10:10:30', '', null, '代码生成菜单'); INSERT INTO `sys_menu` VALUES ('116', '系统接口', '3', '3', '/tool/swagger', '', 'C', '0', '1', 'tool:swagger:view', 'fa fa-gg', 'admin', '2022-11-29 10:10:30', '', null, '系统接口菜单'); -INSERT INTO `sys_menu` VALUES ('117', '数据配置', '5', '1', '/system/dbconfig', 'menuItem', 'C', '0', '1', 'system:dbconfig:view', 'fa fa-gg', 'admin', '2022-11-29 12:15:53', 'admin', '2022-11-30 07:17:43', '数据配置'); +INSERT INTO `sys_menu` VALUES ('117', '数据源配置', '5', '1', '/system/dbconfig', 'menuItem', 'C', '0', '1', 'system:dbconfig:view', 'fa fa-gg', 'admin', '2022-11-29 12:15:53', 'admin', '2023-03-05 13:15:05', '数据配置'); INSERT INTO `sys_menu` VALUES ('500', '操作日志', '108', '1', '/monitor/operlog', '', 'C', '0', '1', 'monitor:operlog:view', 'fa fa-address-book', 'admin', '2022-11-29 10:10:30', '', null, '操作日志菜单'); INSERT INTO `sys_menu` VALUES ('501', '登录日志', '108', '2', '/monitor/logininfor', '', 'C', '0', '1', 'monitor:logininfor:view', 'fa fa-file-image-o', 'admin', '2022-11-29 10:10:30', '', null, '登录日志菜单'); INSERT INTO `sys_menu` VALUES ('1000', '用户查询', '100', '1', '#', '', 'F', '0', '1', 'system:user:list', '#', 'admin', '2022-11-29 10:10:30', '', null, ''); @@ -913,14 +719,18 @@ INSERT INTO `sys_menu` VALUES ('1063', '配置新增', '117', '2', '#', 'menuIte INSERT INTO `sys_menu` VALUES ('1064', '修改', '117', '3', '#', '', 'F', '0', '1', 'system:dbconfig:edit', '#', 'admin', '2022-11-29 13:04:30', '', null, ''); INSERT INTO `sys_menu` VALUES ('1065', '删除', '117', '4', '#', '', 'F', '0', '1', 'system:dbconfig:remove', '#', 'admin', '2022-11-29 13:04:30', '', null, ''); INSERT INTO `sys_menu` VALUES ('1066', '导出', '117', '5', '#', '', 'F', '0', '1', 'system:dbconfig:export', '#', 'admin', '2022-11-29 13:04:30', '', null, ''); -INSERT INTO `sys_menu` VALUES ('2000', '任务配置', '5', '2', '/system/jobconfig', 'menuItem', 'C', '0', '1', 'system:jobconfig:view', 'fa fa-archive', 'admin', '2022-11-30 07:16:51', 'admin', '2022-11-30 07:19:45', ''); +INSERT INTO `sys_menu` VALUES ('2000', '任务配置', '2008', '2', '/system/jobconfig', 'menuItem', 'C', '0', '1', 'system:jobconfig:view', 'fa fa-archive', 'admin', '2022-11-30 07:16:51', 'admin', '2023-03-05 13:14:17', ''); INSERT INTO `sys_menu` VALUES ('2001', '查询', '2000', '1', 'system:dbconfig:list', 'menuItem', 'F', '0', '1', 'system:jobconfig:list', '#', 'admin', '2022-11-30 07:18:54', 'admin', '2022-11-30 07:23:02', ''); INSERT INTO `sys_menu` VALUES ('2002', '新增', '2000', '2', '#', 'menuItem', 'F', '0', '1', 'system:dbconfig:add', '#', 'admin', '2022-11-30 07:22:19', '', null, ''); INSERT INTO `sys_menu` VALUES ('2003', '修改', '2000', '3', '#', 'menuItem', 'F', '0', '1', 'system:dbconfig:edit', '#', 'admin', '2022-11-30 07:22:51', '', null, ''); INSERT INTO `sys_menu` VALUES ('2004', '删除', '2000', '4', '#', 'menuItem', 'F', '0', '1', 'system:dbconfig:remove', '#', 'admin', '2022-11-30 07:23:53', '', null, ''); -INSERT INTO `sys_menu` VALUES ('2005', '运行实例', '5', '3', '/system/jobInstance', 'menuItem', 'C', '0', '1', '/system/jobInstance', 'fa fa-asterisk', 'admin', '2022-12-12 03:41:51', 'admin', '2022-12-12 03:50:16', ''); +INSERT INTO `sys_menu` VALUES ('2005', '运行实例', '2008', '3', '/system/jobInstance', 'menuItem', 'C', '0', '1', '/system/jobInstance', 'fa fa-asterisk', 'admin', '2022-12-12 03:41:51', 'admin', '2023-03-05 13:14:29', ''); INSERT INTO `sys_menu` VALUES ('2006', '查看详情', '2005', '1', '#', 'menuItem', 'F', '0', '1', 'system:jobInstance:detail', '#', 'admin', '2022-12-12 03:42:42', 'admin', '2022-12-19 12:50:41', ''); INSERT INTO `sys_menu` VALUES ('2007', '查看差异', '2005', '2', '#', 'menuItem', 'F', '0', '1', 'system:jobInstance:diffDetail', '#', 'admin', '2022-12-19 12:50:09', 'admin', '2022-12-19 12:51:15', ''); +INSERT INTO `sys_menu` VALUES ('2008', '数据对比', '0', '6', '#', 'menuItem', 'M', '0', '1', '', 'fa fa-bars', 'admin', '2023-03-05 13:12:55', 'admin', '2023-03-05 13:13:41', ''); +INSERT INTO `sys_menu` VALUES ('2009', '数据探测', '0', '7', '#', 'menuItem', 'M', '0', '1', null, 'fa fa-bars', 'admin', '2023-03-05 13:15:40', '', null, ''); +INSERT INTO `sys_menu` VALUES ('2010', '任务配置', '2009', '0', '/system/probeJobConfig', 'menuItem', 'C', '0', '1', 'system:probeJobConfig:view', '#', 'admin', '2023-03-13 11:53:09', 'admin', '2023-03-13 11:53:52', ''); +INSERT INTO `sys_menu` VALUES ('2012', '探测结果', '2009', '1', '/system/probeJobInstance', 'menuItem', 'C', '0', '1', 'system:probeJobInstance:view', '#', 'admin', '2023-03-14 12:20:21', 'admin', '2023-03-14 12:20:56', ''); -- ---------------------------- -- Table structure for sys_notice @@ -968,7 +778,7 @@ CREATE TABLE `sys_oper_log` ( `error_msg` varchar(2000) DEFAULT '' COMMENT '错误消息', `oper_time` datetime DEFAULT NULL COMMENT '操作时间', PRIMARY KEY (`oper_id`) -) ENGINE=InnoDB AUTO_INCREMENT=197 DEFAULT CHARSET=utf8 COMMENT='操作日志记录'; +) ENGINE=InnoDB AUTO_INCREMENT=251 DEFAULT CHARSET=utf8 COMMENT='操作日志记录'; -- ---------------------------- -- Table structure for sys_post @@ -1176,7 +986,7 @@ CREATE TABLE `sys_user` ( -- ---------------------------- -- Records of sys_user -- ---------------------------- -INSERT INTO `sys_user` VALUES ('1', '103', 'admin', 'admin', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2022-12-20 15:24:08', '2022-11-25 05:03:52', 'admin', '2022-11-25 05:03:52', '', '2022-12-20 07:24:09', '管理员'); +INSERT INTO `sys_user` VALUES ('1', '103', 'admin', 'admin', '00', 'xiaoqiu2017wy@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2023-03-17 18:10:20', '2022-11-25 05:03:52', 'admin', '2022-11-25 05:03:52', '', '2023-03-17 10:10:23', '管理员'); INSERT INTO `sys_user` VALUES ('2', '105', 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', '2022-11-25 05:03:52', '2022-11-25 05:03:52', 'admin', '2022-11-25 05:03:52', '', null, '测试员'); -- ---------------------------- @@ -1201,7 +1011,7 @@ CREATE TABLE `sys_user_online` ( -- ---------------------------- -- Records of sys_user_online -- ---------------------------- -INSERT INTO `sys_user_online` VALUES ('a7346ff6-e689-4450-9b41-676bc0eedc98', 'admin', '研发部门', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', 'on_line', '2022-12-20 15:24:06', '2022-12-20 15:24:08', '1800000'); +INSERT INTO `sys_user_online` VALUES ('0052b779-31d7-4748-961e-af078289225d', 'admin', '研发部门', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', 'on_line', '2023-03-17 18:10:18', '2023-03-17 18:12:25', '1800000'); -- ---------------------------- -- Table structure for sys_user_post diff --git a/src/main/java/com/vince/xq/common/constant/Constants.java b/src/main/java/com/vince/xq/common/constant/Constants.java index ee1f43f..d8b6409 100644 --- a/src/main/java/com/vince/xq/common/constant/Constants.java +++ b/src/main/java/com/vince/xq/common/constant/Constants.java @@ -116,4 +116,6 @@ public class Constants { public static final String TEST_CONNECT_SQL = "show databases"; public static final String CHECK_TABLE_SQL ="select %s from %s limit 1"; + + public static final String EMAIL_TITLE ="dataCompare check result"; } diff --git a/src/main/java/com/vince/xq/project/common/RunUtil.java b/src/main/java/com/vince/xq/project/common/RunUtil.java index 45b65b7..ae8df2d 100644 --- a/src/main/java/com/vince/xq/project/common/RunUtil.java +++ b/src/main/java/com/vince/xq/project/common/RunUtil.java @@ -1,9 +1,13 @@ package com.vince.xq.project.common; +import com.alibaba.fastjson.JSONObject; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstance; import com.vince.xq.project.system.instance.controller.InstanceController; import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import com.vince.xq.project.system.dbconfig.domain.Dbconfig; import com.vince.xq.project.system.instance.domain.Instance; +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -140,9 +144,9 @@ public static Instance run(Dbconfig dbconfig, Jobconfig jobconfig) throws Except String compareNumSql = String.format(PV_UV_SQL, jobconfig.getOriginTablePrimary(), jobconfig.getOriginTableName(), Optional.ofNullable(jobconfig.getOriginTableFilter()).orElse("") , jobconfig.getToTablePrimary(), jobconfig.getToTableName(), Optional.ofNullable(jobconfig.getToTableFilter()).orElse("")); - log.info("====compareNumSql===="); + /*log.info("====compareNumSql===="); log.info(compareNumSql); - log.info("====compareNumSql===="); + log.info("====compareNumSql====");*/ String[] fileds = jobconfig.getOriginTableFields().split(","); List originColumns = new ArrayList<>(); @@ -172,9 +176,9 @@ public static Instance run(Dbconfig dbconfig, Jobconfig jobconfig) throws Except jobconfig.getToTableName(), Optional.ofNullable(jobconfig.getToTableFilter()).orElse("")); - log.info("====consistencyNumSql===="); + /*log.info("====consistencyNumSql===="); log.info(consistencyNumSql); - log.info("====consistencyNumSql===="); + log.info("====consistencyNumSql====");*/ Instance instance = runNum(dbconfig, dbTypeEnum.getConnectDriver(), compareNumSql, consistencyNumSql); instance.setMagnitudeSql(compareNumSql); @@ -199,9 +203,9 @@ public static List> runDiffDetail(Dbconfig dbconfi .replaceAll("fields_list_check_filter", String.join(" or ", fields_list_filter)) .replaceAll("fields_list_check", String.join(",", fields_list)); - log.info("====check_sql===="); + /*log.info("====check_sql===="); log.info(check_sql); - log.info("====check_sql===="); + log.info("====check_sql====");*/ DbTypeEnum dbTypeEnum = DbTypeEnum.findEnumByType(dbconfig.getType()); try { @@ -274,4 +278,143 @@ public static Instance runNum(Dbconfig dbconfig, String connectDriver, String co } return instance; } + + public static final String mainTemplateSql = "select count(distinct column) as distinct_cnt," + + "count(*) as cnt" + + " from tableName filter"; + + public static final String emptyTemplateSql = "select count(*) as cnt,column_dict as dict from (\n" + + "select *,\n" + + "case when column is null then 0\n" + + "else 1\n" + + "end as column_dict\n" + + "from tableName\n" + + "filter\n" + + ")t group by column_dict;"; + + public static final String enumTemplateSql = "select cnt,dict from (\n" + + "select count(*) as cnt,column as dict\n" + + "from tableName\n" + + "filter\n" + + "group by column\n" + + ")t order by cnt desc limit 20;"; + + public static final String lengthTemplateSql = "select len,count(*) as cnt from (\n" + + "select *,length(column) as len from tableName filter\n" + + ")t group by len;"; + + public static ProbeJobInstance runProbeJob(Dbconfig dbconfig, Probejobconfig probejobconfig) throws Exception { + DbTypeEnum dbTypeEnum = DbTypeEnum.findEnumByType(dbconfig.getType()); + String filter = probejobconfig.getFilter(); + String mainSql = ""; + ProbeJobInstance instance = new ProbeJobInstance(); + if (StringUtils.isNotBlank(probejobconfig.getTablePrimary())) { + String primaryField = probejobconfig.getTablePrimary(); + mainSql = mainTemplateSql.replaceAll("column", primaryField).replace("tableName", probejobconfig.getTableName()).replace("filter", Optional.ofNullable(filter).orElse("")); + Map primaryResult = runProbJobPrimaryKey(dbconfig, dbTypeEnum.getConnectDriver(), mainSql); + if (primaryResult != null) { + Map> mainResult = new HashMap<>(); + mainResult.put(probejobconfig.getTablePrimary(), primaryResult); + instance.setPrimaryResult(JSONObject.toJSONString(mainResult)); + } + } + if (StringUtils.isNotBlank(probejobconfig.getTableNullFields())) { + String[] emptyFieldArr = probejobconfig.getTableNullFields().split(","); + Map>> emptyResult = new HashMap<>(); + for (String emptyField : emptyFieldArr) { + String sql = emptyTemplateSql.replaceAll("column", emptyField).replace("tableName", probejobconfig.getTableName()).replace("filter", Optional.ofNullable(filter).orElse("")); + List> emptyList = runProbJobField(dbconfig, dbTypeEnum.getConnectDriver(), sql); + emptyResult.put(emptyField, emptyList); + } + instance.setNullResult(JSONObject.toJSONString(emptyResult)); + } + if (StringUtils.isNotBlank(probejobconfig.getTableEnumFields())) { + String[] enumFieldArr = probejobconfig.getTableEnumFields().split(","); + Map>> enumResult = new HashMap<>(); + for (String enumField : enumFieldArr) { + String sql = enumTemplateSql.replaceAll("column", enumField).replace("tableName", probejobconfig.getTableName()).replace("filter", Optional.ofNullable(filter).orElse("")); + List> enumList = runProbJobField(dbconfig, dbTypeEnum.getConnectDriver(), sql); + enumResult.put(enumField, enumList); + } + instance.setEnumResult(JSONObject.toJSONString(enumResult)); + } + if (StringUtils.isNotBlank(probejobconfig.getTableLengthFields())) { + String[] lenFieldArr = probejobconfig.getTableLengthFields().split(","); + Map>> lengthResult = new HashMap<>(); + for (String lenField : lenFieldArr) { + String sql = lengthTemplateSql.replaceAll("column", lenField).replace("tableName", probejobconfig.getTableName()).replace("filter", Optional.ofNullable(filter).orElse("")); + List> lenList = runProbJobField(dbconfig, dbTypeEnum.getConnectDriver(), sql); + lengthResult.put(lenField, lenList); + } + instance.setLenResult(JSONObject.toJSONString(lengthResult)); + } + return instance; + } + + private static Map runProbJobPrimaryKey(Dbconfig dbconfig, String connectDriver, String sql) throws Exception { + try { + Class.forName(connectDriver); + } catch (ClassNotFoundException e) { + throw new Exception("注册驱动失败"); + } + Connection conn = null; + try { + conn = DriverManager.getConnection(dbconfig.getUrl(), dbconfig.getUserName(), dbconfig.getPwd()); + Statement stat = conn.createStatement(); + if (StringUtils.isNotBlank(sql)) { + log.info("=====sql:{}=======", sql); + ResultSet re = stat.executeQuery(sql); + Map hashMap = new HashMap<>(); + while (re.next()) { + hashMap.put("distinct_cnt", re.getString(1)); + hashMap.put("cnt", re.getString(2)); + } + re.close(); + return hashMap; + } + stat.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + throw new Exception("连接数据库失败"); + } + return null; + } + + private static List> runProbJobField(Dbconfig dbconfig, String connectDriver, String sql) throws Exception { + try { + Class.forName(connectDriver); + } catch (ClassNotFoundException e) { + throw new Exception("注册驱动失败"); + } + Connection conn = null; + try { + conn = DriverManager.getConnection(dbconfig.getUrl(), dbconfig.getUserName(), dbconfig.getPwd()); + Statement stat = conn.createStatement(); + if (StringUtils.isNotBlank(sql)) { + log.info("=====sql:{}=======", sql); + ResultSet re = stat.executeQuery(sql); + ResultSetMetaData metaData = re.getMetaData(); //获取列集 + int columnCount = metaData.getColumnCount(); //获取列的数量 + List> list = new ArrayList<>(); + while (re.next()) { + LinkedHashMap hashMap = new LinkedHashMap(); + for (int i = 0; i < columnCount; i++) { //循环列 + String columnName = metaData.getColumnName(i + 1); //通过序号获取列名,起始值为1 + String columnValue = re.getString(columnName); //通过列名获取值.如果列值为空,columnValue为null,不是字符型 + hashMap.put(columnName, columnValue); + } + list.add(hashMap); + } + re.close(); + return list; + } + stat.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + throw new Exception("连接数据库失败"); + } + return null; + } } diff --git a/src/main/java/com/vince/xq/project/monitor/job/service/JobServiceImpl.java b/src/main/java/com/vince/xq/project/monitor/job/service/JobServiceImpl.java index 427ef4c..8517d94 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/service/JobServiceImpl.java +++ b/src/main/java/com/vince/xq/project/monitor/job/service/JobServiceImpl.java @@ -39,12 +39,12 @@ public class JobServiceImpl implements IJobService @PostConstruct public void init() throws SchedulerException, TaskException { - scheduler.clear(); + /*scheduler.clear(); List jobList = jobMapper.selectJobAll(); for (Job job : jobList) { ScheduleUtils.createScheduleJob(scheduler, job); - } + }*/ } /** diff --git a/src/main/java/com/vince/xq/project/monitor/job/task/RyTask.java b/src/main/java/com/vince/xq/project/monitor/job/task/RyTask.java index 5e17ede..bdb6705 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/task/RyTask.java +++ b/src/main/java/com/vince/xq/project/monitor/job/task/RyTask.java @@ -1,28 +1,31 @@ package com.vince.xq.project.monitor.job.task; import com.vince.xq.common.utils.StringUtils; +import com.vince.xq.project.system.instance.service.IInstanceService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 定时任务调度测试 - * + * * @author ruoyi */ @Component("ryTask") -public class RyTask -{ - public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) - { +public class RyTask { + + @Autowired + private IInstanceService instanceService; + + public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) { System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); } - public void ryParams(String params) - { - System.out.println("执行有参方法:" + params); + public void ryParams(String params) throws Exception { + //System.out.println("执行有参方法:" + params); + instanceService.runJob(params); } - public void ryNoParams() - { + public void ryNoParams() { System.out.println("执行无参方法"); } } diff --git a/src/main/java/com/vince/xq/project/monitor/job/util/AbstractQuartzJob.java b/src/main/java/com/vince/xq/project/monitor/job/util/AbstractQuartzJob.java index d5f7bf5..0c95605 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/util/AbstractQuartzJob.java +++ b/src/main/java/com/vince/xq/project/monitor/job/util/AbstractQuartzJob.java @@ -7,6 +7,7 @@ import com.vince.xq.common.utils.StringUtils; import com.vince.xq.common.utils.bean.BeanUtils; import com.vince.xq.common.utils.spring.SpringUtils; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; @@ -33,7 +34,7 @@ public abstract class AbstractQuartzJob implements org.quartz.Job @Override public void execute(JobExecutionContext context) throws JobExecutionException { - Job job = new Job(); + Jobconfig job = new Jobconfig(); BeanUtils.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); try { @@ -55,9 +56,8 @@ public void execute(JobExecutionContext context) throws JobExecutionException * 执行前 * * @param context 工作执行上下文对象 - * @param sysJob 系统计划任务 */ - protected void before(JobExecutionContext context, Job job) + protected void before(JobExecutionContext context, Jobconfig job) { threadLocal.set(new Date()); } @@ -66,17 +66,16 @@ protected void before(JobExecutionContext context, Job job) * 执行后 * * @param context 工作执行上下文对象 - * @param sysScheduleJob 系统计划任务 */ - protected void after(JobExecutionContext context, Job job, Exception e) + protected void after(JobExecutionContext context, Jobconfig job, Exception e) { Date startTime = threadLocal.get(); threadLocal.remove(); final JobLog jobLog = new JobLog(); - jobLog.setJobName(job.getJobName()); - jobLog.setJobGroup(job.getJobGroup()); - jobLog.setInvokeTarget(job.getInvokeTarget()); + jobLog.setJobName(job.getId().toString()); + jobLog.setJobGroup("test-job"); + //jobLog.setInvokeTarget(job.getInvokeTarget()); jobLog.setStartTime(startTime); jobLog.setEndTime(new Date()); long runMs = jobLog.getEndTime().getTime() - jobLog.getStartTime().getTime(); @@ -93,7 +92,7 @@ protected void after(JobExecutionContext context, Job job, Exception e) } // 写入数据库当中 - SpringUtils.getBean(IJobLogService.class).addJobLog(jobLog); + //SpringUtils.getBean(IJobLogService.class).addJobLog(jobLog); } /** @@ -103,5 +102,5 @@ protected void after(JobExecutionContext context, Job job, Exception e) * @param job 系统计划任务 * @throws Exception 执行过程中的异常 */ - protected abstract void doExecute(JobExecutionContext context, Job job) throws Exception; + protected abstract void doExecute(JobExecutionContext context, Jobconfig job) throws Exception; } \ No newline at end of file diff --git a/src/main/java/com/vince/xq/project/monitor/job/util/JobInvokeUtil.java b/src/main/java/com/vince/xq/project/monitor/job/util/JobInvokeUtil.java index 9318a6b..ffc9d60 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/util/JobInvokeUtil.java +++ b/src/main/java/com/vince/xq/project/monitor/job/util/JobInvokeUtil.java @@ -8,33 +8,27 @@ import com.vince.xq.common.utils.StringUtils; import com.vince.xq.common.utils.spring.SpringUtils; import com.vince.xq.project.monitor.job.domain.Job; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; /** * 任务执行工具 * * @author ruoyi */ -public class JobInvokeUtil -{ +public class JobInvokeUtil { /** * 执行方法 - * - * @param sysJob 系统任务 */ - public static void invokeMethod(Job job) throws Exception - { - String invokeTarget = job.getInvokeTarget(); + public static void invokeMethod(Jobconfig job) throws Exception { + String invokeTarget = "ryTask.ryParams('" + job.getId() + "')"; String beanName = getBeanName(invokeTarget); String methodName = getMethodName(invokeTarget); List methodParams = getMethodParams(invokeTarget); - if (!isValidClassName(beanName)) - { + if (!isValidClassName(beanName)) { Object bean = SpringUtils.getBean(beanName); invokeMethod(bean, methodName, methodParams); - } - else - { + } else { Object bean = Class.forName(beanName).newInstance(); invokeMethod(bean, methodName, methodParams); } @@ -43,21 +37,17 @@ public static void invokeMethod(Job job) throws Exception /** * 调用任务方法 * - * @param bean 目标对象 - * @param methodName 方法名称 + * @param bean 目标对象 + * @param methodName 方法名称 * @param methodParams 方法参数 */ private static void invokeMethod(Object bean, String methodName, List methodParams) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException - { - if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) - { + InvocationTargetException { + if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) { Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams)); method.invoke(bean, getMethodParamsValue(methodParams)); - } - else - { + } else { Method method = bean.getClass().getMethod(methodName); method.invoke(bean); } @@ -65,81 +55,70 @@ private static void invokeMethod(Object bean, String methodName, List /** * 校验是否为为class包名 - * + * * @param invokeTarget 名称 * @return true是 false否 */ - public static boolean isValidClassName(String invokeTarget) - { + public static boolean isValidClassName(String invokeTarget) { return StringUtils.countMatches(invokeTarget, ".") > 1; } /** * 获取bean名称 - * + * * @param invokeTarget 目标字符串 * @return bean名称 */ - public static String getBeanName(String invokeTarget) - { + public static String getBeanName(String invokeTarget) { String beanName = StringUtils.substringBefore(invokeTarget, "("); return StringUtils.substringBeforeLast(beanName, "."); } /** * 获取bean方法 - * + * * @param invokeTarget 目标字符串 * @return method方法 */ - public static String getMethodName(String invokeTarget) - { + public static String getMethodName(String invokeTarget) { String methodName = StringUtils.substringBefore(invokeTarget, "("); return StringUtils.substringAfterLast(methodName, "."); } /** * 获取method方法参数相关列表 - * + * * @param invokeTarget 目标字符串 * @return method方法相关参数列表 */ - public static List getMethodParams(String invokeTarget) - { + public static List getMethodParams(String invokeTarget) { String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); - if (StringUtils.isEmpty(methodStr)) - { + if (StringUtils.isEmpty(methodStr)) { return null; } String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); List classs = new LinkedList<>(); - for (int i = 0; i < methodParams.length; i++) - { + for (int i = 0; i < methodParams.length; i++) { String str = StringUtils.trimToEmpty(methodParams[i]); // String字符串类型,以'或"开头 - if (StringUtils.startsWithAny(str, "'", "\"")) - { - classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class }); + if (StringUtils.startsWithAny(str, "'", "\"")) { + classs.add(new Object[]{StringUtils.substring(str, 1, str.length() - 1), String.class}); } // boolean布尔类型,等于true或者false - else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) - { - classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) { + classs.add(new Object[]{Boolean.valueOf(str), Boolean.class}); } // long长整形,以L结尾 - else if (StringUtils.endsWith(str, "L")) - { - classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class }); + else if (StringUtils.endsWith(str, "L")) { + classs.add(new Object[]{Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class}); } // double浮点类型,以D结尾 - else if (StringUtils.endsWith(str, "D")) - { - classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class }); + else if (StringUtils.endsWith(str, "D")) { + classs.add(new Object[]{Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class}); } // 其他类型归类为整形 - else - { - classs.add(new Object[] { Integer.valueOf(str), Integer.class }); + else { + classs.add(new Object[]{Integer.valueOf(str), Integer.class}); } } return classs; @@ -147,16 +126,14 @@ else if (StringUtils.endsWith(str, "D")) /** * 获取参数类型 - * + * * @param methodParams 参数相关列表 * @return 参数类型列表 */ - public static Class[] getMethodParamsType(List methodParams) - { + public static Class[] getMethodParamsType(List methodParams) { Class[] classs = new Class[methodParams.size()]; int index = 0; - for (Object[] os : methodParams) - { + for (Object[] os : methodParams) { classs[index] = (Class) os[1]; index++; } @@ -165,16 +142,14 @@ public static Class[] getMethodParamsType(List methodParams) /** * 获取参数值 - * + * * @param methodParams 参数相关列表 * @return 参数值列表 */ - public static Object[] getMethodParamsValue(List methodParams) - { + public static Object[] getMethodParamsValue(List methodParams) { Object[] classs = new Object[methodParams.size()]; int index = 0; - for (Object[] os : methodParams) - { + for (Object[] os : methodParams) { classs[index] = (Object) os[0]; index++; } diff --git a/src/main/java/com/vince/xq/project/monitor/job/util/QuartzDisallowConcurrentExecution.java b/src/main/java/com/vince/xq/project/monitor/job/util/QuartzDisallowConcurrentExecution.java index c926163..999bdb6 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/util/QuartzDisallowConcurrentExecution.java +++ b/src/main/java/com/vince/xq/project/monitor/job/util/QuartzDisallowConcurrentExecution.java @@ -1,5 +1,6 @@ package com.vince.xq.project.monitor.job.util; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import com.vince.xq.project.monitor.job.domain.Job; @@ -14,7 +15,7 @@ public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob { @Override - protected void doExecute(JobExecutionContext context, Job job) throws Exception + protected void doExecute(JobExecutionContext context, Jobconfig job) throws Exception { JobInvokeUtil.invokeMethod(job); } diff --git a/src/main/java/com/vince/xq/project/monitor/job/util/QuartzJobExecution.java b/src/main/java/com/vince/xq/project/monitor/job/util/QuartzJobExecution.java index f120202..a3d5dde 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/util/QuartzJobExecution.java +++ b/src/main/java/com/vince/xq/project/monitor/job/util/QuartzJobExecution.java @@ -1,5 +1,6 @@ package com.vince.xq.project.monitor.job.util; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import org.quartz.JobExecutionContext; import com.vince.xq.project.monitor.job.domain.Job; @@ -12,7 +13,7 @@ public class QuartzJobExecution extends AbstractQuartzJob { @Override - protected void doExecute(JobExecutionContext context, Job job) throws Exception + protected void doExecute(JobExecutionContext context, Jobconfig job) throws Exception { JobInvokeUtil.invokeMethod(job); } diff --git a/src/main/java/com/vince/xq/project/monitor/job/util/ScheduleUtils.java b/src/main/java/com/vince/xq/project/monitor/job/util/ScheduleUtils.java index e1561bb..1fc3424 100644 --- a/src/main/java/com/vince/xq/project/monitor/job/util/ScheduleUtils.java +++ b/src/main/java/com/vince/xq/project/monitor/job/util/ScheduleUtils.java @@ -3,6 +3,7 @@ import com.vince.xq.common.constant.Constants; import com.vince.xq.common.utils.StringUtils; import com.vince.xq.common.utils.spring.SpringUtils; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; @@ -19,45 +20,80 @@ /** * 定时任务工具类 - * - * @author ruoyi * + * @author ruoyi */ -public class ScheduleUtils -{ +public class ScheduleUtils { /** * 得到quartz任务类 * - * @param sysJob 执行计划 * @return 具体执行任务类 */ - private static Class getQuartzJobClass(Job job) - { + private static Class getQuartzJobClass(Job job) { boolean isConcurrent = "0".equals(job.getConcurrent()); return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; } + private static Class getQuartzJobClass(Jobconfig job) { + boolean isConcurrent = "0".equals("1"); + return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; + } + /** * 构建任务触发对象 */ - public static TriggerKey getTriggerKey(Long jobId, String jobGroup) - { + public static TriggerKey getTriggerKey(Long jobId, String jobGroup) { return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); } /** * 构建任务键对象 */ - public static JobKey getJobKey(Long jobId, String jobGroup) - { + public static JobKey getJobKey(Long jobId, String jobGroup) { return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); } + public static void createScheduleJob(Scheduler scheduler, Jobconfig job) throws SchedulerException, TaskException { + Class jobClass = getQuartzJobClass(job); + // 构建job信息 + Long jobId = job.getId(); + String jobGroup = "test-job"; + JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); + + // 表达式调度构建器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getSchduleTime()); + cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); + + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) + .withSchedule(cronScheduleBuilder).build(); + + // 放入参数,运行时的方法可以获取 + jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); + + // 判断是否存在 + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(getJobKey(jobId, jobGroup)); + } + + // 判断任务是否过期 + if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getSchduleTime()))) { + // 执行调度任务 + scheduler.scheduleJob(jobDetail, trigger); + } + + // 暂停任务 + if (job.getSchduleStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + } + + /** * 创建定时任务 */ - public static void createScheduleJob(Scheduler scheduler, Job job) throws SchedulerException, TaskException - { + public static void createScheduleJob(Scheduler scheduler, Job job) throws SchedulerException, TaskException { Class jobClass = getQuartzJobClass(job); // 构建job信息 Long jobId = job.getJobId(); @@ -76,33 +112,31 @@ public static void createScheduleJob(Scheduler scheduler, Job job) throws Schedu jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); // 判断是否存在 - if (scheduler.checkExists(getJobKey(jobId, jobGroup))) - { + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) { // 防止创建时存在数据问题 先移除,然后在执行创建操作 scheduler.deleteJob(getJobKey(jobId, jobGroup)); } // 判断任务是否过期 - if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) - { + if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) { // 执行调度任务 scheduler.scheduleJob(jobDetail, trigger); } // 暂停任务 - if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) - { + if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) { scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); } } + /** * 设置定时任务策略 */ - public static CronScheduleBuilder handleCronScheduleMisfirePolicy(Job job, CronScheduleBuilder cb) - throws TaskException - { - switch (job.getMisfirePolicy()) + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(Jobconfig job, CronScheduleBuilder cb) + throws TaskException { + return cb; + /*switch (job.getMisfirePolicy()) { case ScheduleConstants.MISFIRE_DEFAULT: return cb; @@ -115,21 +149,39 @@ public static CronScheduleBuilder handleCronScheduleMisfirePolicy(Job job, CronS default: throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + }*/ + } + + /** + * 设置定时任务策略 + */ + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(Job job, CronScheduleBuilder cb) + throws TaskException { + switch (job.getMisfirePolicy()) { + case ScheduleConstants.MISFIRE_DEFAULT: + return cb; + case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: + return cb.withMisfireHandlingInstructionIgnoreMisfires(); + case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: + return cb.withMisfireHandlingInstructionFireAndProceed(); + case ScheduleConstants.MISFIRE_DO_NOTHING: + return cb.withMisfireHandlingInstructionDoNothing(); + default: + throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); } } /** * 检查包名是否为白名单配置 - * + * * @param invokeTarget 目标字符串 * @return 结果 */ - public static boolean whiteList(String invokeTarget) - { + public static boolean whiteList(String invokeTarget) { String packageName = StringUtils.substringBefore(invokeTarget, "("); int count = StringUtils.countMatches(packageName, "."); - if (count > 1) - { + if (count > 1) { return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); } Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/controller/ProbeJobInstanceController.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/controller/ProbeJobInstanceController.java new file mode 100644 index 0000000..f85b5ed --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/controller/ProbeJobInstanceController.java @@ -0,0 +1,96 @@ +package com.vince.xq.project.system.ProbeJobInstance.controller; + +import com.alibaba.fastjson.JSONObject; +import com.vince.xq.framework.aspectj.lang.annotation.Log; +import com.vince.xq.framework.aspectj.lang.enums.BusinessType; +import com.vince.xq.framework.web.controller.BaseController; +import com.vince.xq.framework.web.domain.AjaxResult; +import com.vince.xq.framework.web.page.TableDataInfo; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstance; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstanceResult; +import com.vince.xq.project.system.ProbeJobInstance.service.IProbeJobInstanceService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * 岗位信息操作处理 + * + * @author ruoyi + */ +@Controller +@RequestMapping("/system/probeJobInstance") +public class ProbeJobInstanceController extends BaseController { + private static final Logger log = LoggerFactory.getLogger(ProbeJobInstanceController.class); + + private String prefix = "system/probeJobInstance"; + + @Autowired + private IProbeJobInstanceService instanceService; + + @RequiresPermissions("system:probeJobInstance:view") + @GetMapping() + public String operlog() { + return prefix + "/probeJobInstance"; + } + + @RequiresPermissions("system:probeJobInstance:list") + @PostMapping("/list") + @ResponseBody + public TableDataInfo list(ProbeJobInstance Instance) { + startPage(); + List list = instanceService.selectInstanceList(Instance); + return getDataTable(list); + } + + @RequiresPermissions("system:probeJobInstance:insert") + @Log(title = "instance管理", businessType = BusinessType.INSERT) + @PostMapping("/insert") + @ResponseBody + public AjaxResult insert(ProbeJobInstance instance) { + try { + return toAjax(instanceService.insertInstance(instance)); + } catch (Exception e) { + return error(e.getMessage()); + } + } + + /** + * 新增保存 + */ + @RequiresPermissions("system:probeJobInstance:add") + @Log(title = "add", businessType = BusinessType.INSERT) + @PostMapping("/add") + @ResponseBody + public AjaxResult addSave(@Validated ProbeJobInstance Instance) { + try { + return toAjax(instanceService.insertInstance(Instance)); + } catch (Exception e) { + e.printStackTrace(); + return error(e.getMessage()); + } + } + + @RequiresPermissions("system:probeJobInstance:detail") + @GetMapping("/detail/{id}") + public String edit(@PathVariable("id") Long id, ModelMap mmap) { + ProbeJobInstanceResult instance = instanceService.selectInstanceById(id); + mmap.put("Instance", instance); + /*boolean numFlag = instance.getPvDiff().equals("0") && instance.getUvDiff().equals("0") ? true : false; + boolean consistencyFlag = instance.getCountDiff().equals(instance.getOriginTableCount()) && instance.getCountDiff().equals(instance.getToTableCount()) ? true : false; + mmap.put("Instance", instance); + mmap.put("numFlag", numFlag); + mmap.put("consistencyFlag", consistencyFlag);*/ + return prefix + "/detail"; + } + +} diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstance.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstance.java new file mode 100644 index 0000000..0c94086 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstance.java @@ -0,0 +1,118 @@ +package com.vince.xq.project.system.ProbeJobInstance.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.vince.xq.framework.aspectj.lang.annotation.Excel; + +import java.io.Serializable; +import java.util.Date; + +/** + * 岗位表 sys_post + * + * @author ruoyi + */ +public class ProbeJobInstance implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** id */ + @Excel(name = "id", cellType = Excel.ColumnType.NUMERIC) + private Long id; + + @Excel(name = "jobconfigId") + private Long jobconfigId; + + @Excel(name = "tableName") + private String tableName; + + @Excel(name = "primaryResult") + private String primaryResult; + + @Excel(name = "enumResult") + private String enumResult; + + @Excel(name = "nullResult") + private String nullResult; + + @Excel(name = "lenResult") + private String lenResult; + + @Excel(name = "filter") + private String filter; + + public String getFilter() { + return filter; + } + + public void setFilter(String filter) { + this.filter = filter; + } + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + public String getLenResult() { + return lenResult; + } + + public void setLenResult(String lenResult) { + this.lenResult = lenResult; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public Long getJobconfigId() { + return jobconfigId; + } + + public void setJobconfigId(Long jobconfigId) { + this.jobconfigId = jobconfigId; + } + + public String getPrimaryResult() { + return primaryResult; + } + + public void setPrimaryResult(String primaryResult) { + this.primaryResult = primaryResult; + } + + public String getEnumResult() { + return enumResult; + } + + public void setEnumResult(String enumResult) { + this.enumResult = enumResult; + } + + public String getNullResult() { + return nullResult; + } + + public void setNullResult(String nullResult) { + this.nullResult = nullResult; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } +} diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstanceResult.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstanceResult.java new file mode 100644 index 0000000..2ef1670 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/domain/ProbeJobInstanceResult.java @@ -0,0 +1,189 @@ +package com.vince.xq.project.system.ProbeJobInstance.domain; + +import com.vince.xq.framework.aspectj.lang.annotation.Excel; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public class ProbeJobInstanceResult implements Serializable +{ + private static final long serialVersionUID = 1L; + + @Excel(name = "id", cellType = Excel.ColumnType.NUMERIC) + private Long id; + + @Excel(name = "jobconfigId") + private Long jobconfigId; + + @Excel(name = "tableName") + private String tableName; + + @Excel(name = "primaryResult") + private PrimaryResult primaryResult; + + @Excel(name = "enumResultMap") + private Map> enumResultMap; + + @Excel(name = "lenResultMap") + private Map> lenResultMap; + + @Excel(name = "nullResultList") + private List nullResultList; + + @Excel(name = "filter") + private String filter; + + public Map> getLenResultMap() { + return lenResultMap; + } + + public void setLenResultMap(Map> lenResultMap) { + this.lenResultMap = lenResultMap; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getJobconfigId() { + return jobconfigId; + } + + public void setJobconfigId(Long jobconfigId) { + this.jobconfigId = jobconfigId; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public PrimaryResult getPrimaryResult() { + return primaryResult; + } + + public void setPrimaryResult(PrimaryResult primaryResult) { + this.primaryResult = primaryResult; + } + + public Map> getEnumResultMap() { + return enumResultMap; + } + + public void setEnumResultMap(Map> enumResultMap) { + this.enumResultMap = enumResultMap; + } + + public List getNullResultList() { + return nullResultList; + } + + public void setNullResultList(List nullResultList) { + this.nullResultList = nullResultList; + } + + public String getFilter() { + return filter; + } + + public void setFilter(String filter) { + this.filter = filter; + } + + public static class NullResult{ + private String nullField; + + private Long totalCnt; + + private Long nullCnt; + + public String getNullField() { + return nullField; + } + + public void setNullField(String nullField) { + this.nullField = nullField; + } + + public Long getTotalCnt() { + return totalCnt; + } + + public void setTotalCnt(Long totalCnt) { + this.totalCnt = totalCnt; + } + + public Long getNullCnt() { + return nullCnt; + } + + public void setNullCnt(Long nullCnt) { + this.nullCnt = nullCnt; + } + } + + public static class EnumResult{ + private String enumValue; + + private Long cnt; + + public String getEnumValue() { + return enumValue; + } + + public void setEnumValue(String enumValue) { + this.enumValue = enumValue; + } + + public Long getCnt() { + return cnt; + } + + public void setCnt(Long cnt) { + this.cnt = cnt; + } + } + + public static class PrimaryResult{ + + private String primaryField; + + private Long cnt; + + private Long distinctCnt; + + public String getPrimaryField() { + return primaryField; + } + + public void setPrimaryField(String primaryField) { + this.primaryField = primaryField; + } + + public Long getCnt() { + return cnt; + } + + public void setCnt(Long cnt) { + this.cnt = cnt; + } + + public Long getDistinctCnt() { + return distinctCnt; + } + + public void setDistinctCnt(Long distinctCnt) { + this.distinctCnt = distinctCnt; + } + } + + +} diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/mapper/ProbeJobInstanceMapper.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/mapper/ProbeJobInstanceMapper.java new file mode 100644 index 0000000..7c1adf0 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/mapper/ProbeJobInstanceMapper.java @@ -0,0 +1,19 @@ +package com.vince.xq.project.system.ProbeJobInstance.mapper; + +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstance; + +import java.util.List; + + +public interface ProbeJobInstanceMapper { + + public List selectInstanceList(ProbeJobInstance Instance); + + public List selectInstanceAll(); + + public ProbeJobInstance selectInstanceById(Long id); + + public int insertInstance(ProbeJobInstance Instance); + + public List selectInstancesByUser(String createBy); +} diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/IProbeJobInstanceService.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/IProbeJobInstanceService.java new file mode 100644 index 0000000..c5d7486 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/IProbeJobInstanceService.java @@ -0,0 +1,32 @@ +package com.vince.xq.project.system.ProbeJobInstance.service; + +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstance; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstanceResult; + +import java.util.LinkedHashMap; +import java.util.List; + +/** + * 岗位信息 服务层 + * + * @author ruoyi + */ +public interface IProbeJobInstanceService { + + public List selectInstanceList(ProbeJobInstance instance); + + public List selectInstanceAll(); + + public ProbeJobInstanceResult selectInstanceById(Long id); + + public List selectDbTypesAll(); + + public int insertInstance(ProbeJobInstance instance); + + public int countUserPostById(Long postId); + + public void runJob(String ids) throws Exception; + + //public List> getDiffDetail(Long id) throws Exception; + +} diff --git a/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/ProbeJobInstanceServiceImpl.java b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/ProbeJobInstanceServiceImpl.java new file mode 100644 index 0000000..af48169 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/ProbeJobInstance/service/ProbeJobInstanceServiceImpl.java @@ -0,0 +1,185 @@ +package com.vince.xq.project.system.ProbeJobInstance.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.vince.xq.common.utils.text.Convert; +import com.vince.xq.project.common.DbTypeEnum; +import com.vince.xq.project.common.RunUtil; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstance; +import com.vince.xq.project.system.ProbeJobInstance.domain.ProbeJobInstanceResult; +import com.vince.xq.project.system.ProbeJobInstance.mapper.ProbeJobInstanceMapper; +import com.vince.xq.project.system.dbconfig.domain.Dbconfig; +import com.vince.xq.project.system.dbconfig.mapper.DbconfigMapper; +import com.vince.xq.project.system.email.service.IEmailService; +import com.vince.xq.project.system.jobconfig.domain.Jobconfig; +import com.vince.xq.project.system.jobconfig.mapper.JobconfigMapper; +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; +import com.vince.xq.project.system.probeJobConfig.mapper.ProbeJobconfigMapper; +import com.vince.xq.project.system.user.domain.User; +import com.vince.xq.project.system.user.mapper.UserMapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 岗位信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class ProbeJobInstanceServiceImpl implements IProbeJobInstanceService { + + @Autowired + private ProbeJobInstanceMapper instanceMapper; + + @Autowired + private DbconfigMapper dbconfigMapper; + + @Autowired + private ProbeJobconfigMapper jobconfigMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private IEmailService emailService; + + @Override + public List selectInstanceList(ProbeJobInstance instance) { + return instanceMapper.selectInstanceList(instance); + } + + @Override + public List selectInstanceAll() { + return instanceMapper.selectInstanceAll(); + } + + @Override + public ProbeJobInstanceResult selectInstanceById(Long id) { + ProbeJobInstance probeJobInstance = instanceMapper.selectInstanceById(id); + return extract(probeJobInstance); + } + + private ProbeJobInstanceResult extract(ProbeJobInstance instance) { + ProbeJobInstanceResult probeJobInstanceResult = new ProbeJobInstanceResult(); + probeJobInstanceResult.setId(instance.getId()); + probeJobInstanceResult.setTableName(instance.getTableName()); + probeJobInstanceResult.setFilter(instance.getFilter()); + + if (StringUtils.isNotEmpty(instance.getPrimaryResult())){ + JSONObject primaryResultObj = JSONObject.parseObject(instance.getPrimaryResult()); + for (String key : primaryResultObj.keySet()) { + ProbeJobInstanceResult.PrimaryResult primaryResult = new ProbeJobInstanceResult.PrimaryResult(); + primaryResult.setPrimaryField(key); + JSONObject jsonObject = JSONObject.parseObject(primaryResultObj.getString(key)); + primaryResult.setCnt(jsonObject.getLong("cnt")); + primaryResult.setDistinctCnt(jsonObject.getLong("distinct_cnt")); + probeJobInstanceResult.setPrimaryResult(primaryResult); + } + } + + if (StringUtils.isNotEmpty(instance.getNullResult())){ + JSONObject nullResultObj = JSONObject.parseObject(instance.getNullResult()); + List nullResultList = new ArrayList<>(); + for (String key : nullResultObj.keySet()) { + ProbeJobInstanceResult.NullResult nullResult = new ProbeJobInstanceResult.NullResult(); + nullResult.setNullField(key); + JSONArray jsonArray = JSONObject.parseArray(nullResultObj.getString(key)); + long totalCnt = 0; + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString()); + if (jsonObject.getString("dict").equals("0")) { + nullResult.setNullCnt(jsonObject.getLong("cnt")); + } + totalCnt += jsonObject.getLong("cnt"); + } + nullResult.setTotalCnt(totalCnt); + nullResultList.add(nullResult); + } + probeJobInstanceResult.setNullResultList(nullResultList); + } + + + if (StringUtils.isNotEmpty(instance.getEnumResult())){ + JSONObject enumObj = JSONObject.parseObject(instance.getEnumResult()); + Map> enumResultMap = new HashMap<>(); + for (String key : enumObj.keySet()) { + JSONArray jsonArray = JSONObject.parseArray(enumObj.getString(key)); + List list = new ArrayList<>(); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString()); + ProbeJobInstanceResult.EnumResult enumResult = new ProbeJobInstanceResult.EnumResult(); + enumResult.setEnumValue(jsonObject.getString("dict")); + enumResult.setCnt(jsonObject.getLong("cnt")); + list.add(enumResult); + } + enumResultMap.put(key, list); + } + probeJobInstanceResult.setEnumResultMap(enumResultMap); + } + + if (StringUtils.isNotEmpty(instance.getLenResult())) { + JSONObject lenObj = JSONObject.parseObject(instance.getLenResult()); + Map> lenResultMap = new HashMap<>(); + for (String key : lenObj.keySet()) { + JSONArray jsonArray = JSONObject.parseArray(lenObj.getString(key)); + List list = new ArrayList<>(); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject = JSONObject.parseObject(jsonArray.get(i).toString()); + ProbeJobInstanceResult.EnumResult enumResult = new ProbeJobInstanceResult.EnumResult(); + enumResult.setEnumValue(jsonObject.getString("len")); + enumResult.setCnt(jsonObject.getLong("cnt")); + list.add(enumResult); + } + lenResultMap.put(key, list); + } + probeJobInstanceResult.setLenResultMap(lenResultMap); + } + + return probeJobInstanceResult; + } + + @Override + public List selectDbTypesAll() { + List list = new ArrayList<>(); + for (DbTypeEnum dbTypeEnum : DbTypeEnum.values()) { + list.add(dbTypeEnum.getType()); + } + return list; + } + + + @Override + public int insertInstance(ProbeJobInstance instance) { + return instanceMapper.insertInstance(instance); + } + + + @Override + public int countUserPostById(Long postId) { + return 0; + } + + @Override + public void runJob(String ids) throws Exception { + Long[] idsArray = Convert.toLongArray(ids); + for (Long id : idsArray) { + Probejobconfig jobconfig = jobconfigMapper.selectJobconfigById(id); + Dbconfig dbconfig = dbconfigMapper.selectDbconfigById(jobconfig.getDbConfigId()); + ProbeJobInstance instance = RunUtil.runProbeJob(dbconfig, jobconfig); + instance.setJobconfigId(id); + instanceMapper.insertInstance(instance); + } + } + + /*@Override + public List> getDiffDetail(Long id) throws Exception { + ProbeJobInstance instance = instanceMapper.selectInstanceById(id); + Probejobconfig jobconfig = jobconfigMapper.selectJobconfigById(instance.getJobconfigId()); + Dbconfig dbconfig = dbconfigMapper.selectDbconfigById(jobconfig.getDbConfigId()); + List> list = RunUtil.runDiffDetail(dbconfig, jobconfig); + return list; + }*/ +} diff --git a/src/main/java/com/vince/xq/project/system/email/service/EmailServiceImpl.java b/src/main/java/com/vince/xq/project/system/email/service/EmailServiceImpl.java new file mode 100644 index 0000000..b0defff --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/email/service/EmailServiceImpl.java @@ -0,0 +1,96 @@ +package com.vince.xq.project.system.email.service; + +import com.vince.xq.common.constant.Constants; +import com.vince.xq.project.system.instance.controller.InstanceController; +import com.vince.xq.project.system.instance.domain.Instance; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.MessageFormat; + +@Service +public class EmailServiceImpl implements IEmailService { + private static final Logger log = LoggerFactory.getLogger(EmailServiceImpl.class); + + @Autowired + private JavaMailSender javaMailSender; + + @Value("${spring.mail.enabled}") + private boolean mailEnabled; + + @Value("${spring.mail.username}") + private String fromEmail; + + @Override + public void sendEmail(Instance instance, String email) throws MessagingException { + if (mailEnabled && StringUtils.isNotBlank(email)) { + boolean numFlag = instance.getPvDiff().equals("0") && instance.getUvDiff().equals("0") ? true : false; + boolean consistencyFlag = instance.getCountDiff().equals(instance.getOriginTableCount()) && instance.getCountDiff().equals(instance.getToTableCount()) ? true : false; + String content = buildTemplate(numFlag, consistencyFlag); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(fromEmail); + helper.setTo("xiaoqiu2017wy@163.com"); + helper.setSubject(Constants.EMAIL_TITLE); + // 设置邮件内容,第二个参数设置是否支持 text/html 类型 + helper.setText(content, true); + javaMailSender.send(mimeMessage); + } catch (MessagingException e) { + e.printStackTrace(); + } + } else { + //do nothing + } + } + + private String buildTemplate(boolean numFlag, boolean consistencyFlag) { + //加载邮件html模板 + Resource resource = new ClassPathResource("EmailTemplate.txt"); + InputStream inputStream = null; + BufferedReader fileReader = null; + StringBuffer buffer = new StringBuffer(); + String line = ""; + try { + inputStream = resource.getInputStream(); + fileReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((line = fileReader.readLine()) != null) { + buffer.append(line); + } + } catch (Exception e) { + log.info("发送邮件读取模板失败{}", e); + } finally { + if (fileReader != null) { + try { + fileReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + //替换html模板中的参数 + return MessageFormat.format(buffer.toString(), numFlag, consistencyFlag); + } +} diff --git a/src/main/java/com/vince/xq/project/system/email/service/IEmailService.java b/src/main/java/com/vince/xq/project/system/email/service/IEmailService.java new file mode 100644 index 0000000..f74005c --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/email/service/IEmailService.java @@ -0,0 +1,9 @@ +package com.vince.xq.project.system.email.service; + +import com.vince.xq.project.system.instance.domain.Instance; + +import javax.mail.MessagingException; + +public interface IEmailService { + public void sendEmail(Instance instance, String email) throws MessagingException; +} diff --git a/src/main/java/com/vince/xq/project/system/instance/service/InstanceServiceImpl.java b/src/main/java/com/vince/xq/project/system/instance/service/InstanceServiceImpl.java index 0bc0dc4..f27f3b2 100644 --- a/src/main/java/com/vince/xq/project/system/instance/service/InstanceServiceImpl.java +++ b/src/main/java/com/vince/xq/project/system/instance/service/InstanceServiceImpl.java @@ -5,10 +5,13 @@ import com.vince.xq.project.common.RunUtil; import com.vince.xq.project.system.dbconfig.domain.Dbconfig; import com.vince.xq.project.system.dbconfig.mapper.DbconfigMapper; +import com.vince.xq.project.system.email.service.IEmailService; import com.vince.xq.project.system.instance.domain.Instance; import com.vince.xq.project.system.instance.mapper.InstanceMapper; import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import com.vince.xq.project.system.jobconfig.mapper.JobconfigMapper; +import com.vince.xq.project.system.user.domain.User; +import com.vince.xq.project.system.user.mapper.UserMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,6 +37,12 @@ public class InstanceServiceImpl implements IInstanceService { @Autowired private JobconfigMapper jobconfigMapper; + @Autowired + private UserMapper userMapper; + + @Autowired + private IEmailService emailService; + @Override public List selectInstanceList(Instance instance) { return instanceMapper.selectInstanceList(instance); @@ -79,6 +88,8 @@ public void runJob(String ids) throws Exception { Instance instance = RunUtil.run(dbconfig, jobconfig); instance.setJobconfigId(id); instanceMapper.insertInstance(instance); + User user= userMapper.selectUserByLoginName(jobconfig.getCreateBy()); + emailService.sendEmail(instance,user.getEmail()); } } diff --git a/src/main/java/com/vince/xq/project/system/jobconfig/controller/JobConfigController.java b/src/main/java/com/vince/xq/project/system/jobconfig/controller/JobConfigController.java index a515e78..36d58a4 100644 --- a/src/main/java/com/vince/xq/project/system/jobconfig/controller/JobConfigController.java +++ b/src/main/java/com/vince/xq/project/system/jobconfig/controller/JobConfigController.java @@ -1,7 +1,11 @@ package com.vince.xq.project.system.jobconfig.controller; +import com.vince.xq.common.constant.ScheduleConstants; import com.vince.xq.framework.aspectj.lang.annotation.Log; import com.vince.xq.framework.aspectj.lang.enums.BusinessType; +import com.vince.xq.project.monitor.job.domain.Job; +import com.vince.xq.project.monitor.job.util.CronUtils; +import com.vince.xq.project.monitor.job.util.ScheduleUtils; import com.vince.xq.project.system.jobconfig.service.IJobconfigService; import com.vince.xq.framework.web.controller.BaseController; import com.vince.xq.framework.web.domain.AjaxResult; @@ -10,6 +14,7 @@ import com.vince.xq.project.system.instance.service.IInstanceService; import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.quartz.Scheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -99,7 +104,13 @@ public String add(ModelMap mmap) { @ResponseBody public AjaxResult addSave(@Validated Jobconfig jobconfig) { try { - return toAjax(jobconfigService.insertJobconfig(jobconfig)); + if (jobconfig.getSchduleStatus().equals("0")) {//定时调度 + if (!CronUtils.isValid(jobconfig.getSchduleTime())) { + return error("新增任务失败,Cron表达式不正确"); + } + } + jobconfigService.insertJobconfig(jobconfig); + return success(); } catch (Exception e) { e.printStackTrace(); return error(e.getMessage()); diff --git a/src/main/java/com/vince/xq/project/system/jobconfig/service/IJobconfigService.java b/src/main/java/com/vince/xq/project/system/jobconfig/service/IJobconfigService.java index 04095cc..5be86fe 100644 --- a/src/main/java/com/vince/xq/project/system/jobconfig/service/IJobconfigService.java +++ b/src/main/java/com/vince/xq/project/system/jobconfig/service/IJobconfigService.java @@ -1,6 +1,8 @@ package com.vince.xq.project.system.jobconfig.service; +import com.vince.xq.common.exception.job.TaskException; import com.vince.xq.project.system.jobconfig.domain.Jobconfig; +import org.quartz.SchedulerException; import java.util.List; @@ -23,7 +25,7 @@ public interface IJobconfigService public int deleteJobconfigByIds(String ids); - public int insertJobconfig(Jobconfig dbconfig); + public void insertJobconfig(Jobconfig dbconfig) throws TaskException, SchedulerException; public int updateJobconfig(Jobconfig dbconfig); diff --git a/src/main/java/com/vince/xq/project/system/jobconfig/service/JobconfigServiceImpl.java b/src/main/java/com/vince/xq/project/system/jobconfig/service/JobconfigServiceImpl.java index 5d1628b..8c30bd2 100644 --- a/src/main/java/com/vince/xq/project/system/jobconfig/service/JobconfigServiceImpl.java +++ b/src/main/java/com/vince/xq/project/system/jobconfig/service/JobconfigServiceImpl.java @@ -1,16 +1,24 @@ package com.vince.xq.project.system.jobconfig.service; import com.vince.xq.common.constant.Constants; +import com.vince.xq.common.constant.ScheduleConstants; +import com.vince.xq.common.exception.job.TaskException; import com.vince.xq.common.utils.security.ShiroUtils; import com.vince.xq.common.utils.text.Convert; +import com.vince.xq.project.monitor.job.domain.Job; +import com.vince.xq.project.monitor.job.mapper.JobMapper; +import com.vince.xq.project.monitor.job.util.ScheduleUtils; import com.vince.xq.project.system.jobconfig.domain.Jobconfig; import com.vince.xq.project.system.jobconfig.mapper.JobconfigMapper; import com.vince.xq.project.common.DbTypeEnum; import com.vince.xq.project.system.dbconfig.domain.Dbconfig; import com.vince.xq.project.system.dbconfig.mapper.DbconfigMapper; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.sql.*; import java.util.ArrayList; import java.util.List; @@ -29,6 +37,23 @@ public class JobconfigServiceImpl implements IJobconfigService { @Autowired private DbconfigMapper dbconfigMapper; + @Autowired + private JobMapper jobMapper; + + @Autowired + private Scheduler scheduler; + + @PostConstruct + public void init() throws SchedulerException, TaskException { + scheduler.clear(); + List jobList = jobconfigMapper.selectJobconfigAll(); + for (Jobconfig job : jobList) { + if (job.getSchduleStatus().equals("0")) { + ScheduleUtils.createScheduleJob(scheduler, job); + } + } + } + @Override public List selectJobconfigList(Jobconfig dbconfig) { return jobconfigMapper.selectJobconfigList(dbconfig); @@ -89,12 +114,14 @@ public int deleteJobconfigByIds(String ids) { @Override - public int insertJobconfig(Jobconfig dbconfig) { - dbconfig.setCreateBy(ShiroUtils.getLoginName()); - return jobconfigMapper.insertJobconfig(dbconfig); + public void insertJobconfig(Jobconfig jobconfig) throws TaskException, SchedulerException { + jobconfig.setCreateBy(ShiroUtils.getLoginName()); + int rows = jobconfigMapper.insertJobconfig(jobconfig); + if (rows > 0 && jobconfig.getSchduleStatus().equals("0")) { + ScheduleUtils.createScheduleJob(scheduler, jobconfig); + } } - @Override public int updateJobconfig(Jobconfig dbconfig) { dbconfig.setCreateBy(ShiroUtils.getLoginName()); diff --git a/src/main/java/com/vince/xq/project/system/probeJobConfig/controller/ProbeJobConfigController.java b/src/main/java/com/vince/xq/project/system/probeJobConfig/controller/ProbeJobConfigController.java new file mode 100644 index 0000000..78e0ad6 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/probeJobConfig/controller/ProbeJobConfigController.java @@ -0,0 +1,147 @@ +package com.vince.xq.project.system.probeJobConfig.controller; + +import com.vince.xq.framework.aspectj.lang.annotation.Log; +import com.vince.xq.framework.aspectj.lang.enums.BusinessType; +import com.vince.xq.framework.web.controller.BaseController; +import com.vince.xq.framework.web.domain.AjaxResult; +import com.vince.xq.framework.web.page.TableDataInfo; +import com.vince.xq.project.monitor.job.util.CronUtils; +import com.vince.xq.project.system.ProbeJobInstance.service.IProbeJobInstanceService; +import com.vince.xq.project.system.dbconfig.service.IDbconfigService; +import com.vince.xq.project.system.instance.service.IInstanceService; +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; +import com.vince.xq.project.system.probeJobConfig.service.IProbeJobconfigService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 岗位信息操作处理 + * + * @author ruoyi + */ +@Controller +@RequestMapping("/system/probeJobConfig") +public class ProbeJobConfigController extends BaseController { + private static final Logger log = LoggerFactory.getLogger(ProbeJobConfigController.class); + + private String prefix = "system/probeJobConfig"; + + @Autowired + private IProbeJobconfigService probeJobconfigService; + + @Autowired + private IDbconfigService dbconfigService; + + @Autowired + private IProbeJobInstanceService instanceService; + + @RequiresPermissions("system:probeJobConfig:view") + @GetMapping() + public String operlog() { + return prefix + "/probeJobConfig"; + } + + @RequiresPermissions("system:probeJobConfig:list") + @PostMapping("/list") + @ResponseBody + public TableDataInfo list(Probejobconfig jobconfig) { + startPage(); + List list = probeJobconfigService.selectJobconfigList(jobconfig); + return getDataTable(list); + } + + @RequiresPermissions("system:probeJobConfig:remove") + @Log(title = "job管理", businessType = BusinessType.DELETE) + @PostMapping("/remove") + @ResponseBody + public AjaxResult remove(String ids) { + try { + return toAjax(probeJobconfigService.deleteJobconfigByIds(ids)); + } catch (Exception e) { + return error(e.getMessage()); + } + } + + @RequiresPermissions("system:probeJobConfig:run") + @Log(title = "job管理", businessType = BusinessType.RUN) + @PostMapping("/run") + @ResponseBody + public AjaxResult run(String ids) { + try { + instanceService.runJob(ids); + return success(); + } catch (Exception e) { + return error(e.getMessage()); + } + } + + /** + * 新增 + */ + @GetMapping("/add") + public String add(ModelMap mmap) { + mmap.put("dbConfigList", dbconfigService.selectDbconfigAll()); + return prefix + "/add"; + } + + /** + * 新增保存 + */ + @RequiresPermissions("system:probeJobConfig:add") + @Log(title = "add", businessType = BusinessType.INSERT) + @PostMapping("/add") + @ResponseBody + public AjaxResult addSave(@Validated Probejobconfig jobconfig) { + try { + /*if (jobconfig.getSchduleStatus().equals("0")) {//定时调度 + if (!CronUtils.isValid(jobconfig.getSchduleTime())) { + return error("新增任务失败,Cron表达式不正确"); + } + }*/ + probeJobconfigService.insertJobconfig(jobconfig); + return success(); + } catch (Exception e) { + e.printStackTrace(); + return error(e.getMessage()); + } + } + + /*@RequiresPermissions("system:probeJobConfig:edit") + @GetMapping("/edit/{id}") + public String edit(@PathVariable("id") Long id, ModelMap mmap) { + Probejobconfig jobconfig = probeJobconfigService.selectJobconfigById(id); + mmap.put("jobconfig", jobconfig); + return prefix + "/edit"; + }*/ + + + /*@RequiresPermissions("system:probeJobConfig:edit") + @Log(title = "job管理", businessType = BusinessType.UPDATE) + @PostMapping("/edit") + @ResponseBody + public AjaxResult editSave(@Validated Probejobconfig jobconfig) { + return toAjax(probeJobconfigService.updateJobconfig(jobconfig)); + }*/ + + /*@RequestMapping(value = "/checkTableName", method = RequestMethod.POST) + @ResponseBody + public AjaxResult checkTableName(Probejobconfig jobconfig) { + try { + log.info("========checkTableName=========="); + jobconfigService.checkTableName(jobconfig); + } catch (Exception e) { + e.printStackTrace(); + return error("错误信息:" + e.getMessage()); + } + return success("表和字段校验成功"); + }*/ + +} diff --git a/src/main/java/com/vince/xq/project/system/probeJobConfig/domain/Probejobconfig.java b/src/main/java/com/vince/xq/project/system/probeJobConfig/domain/Probejobconfig.java new file mode 100644 index 0000000..60a4c32 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/probeJobConfig/domain/Probejobconfig.java @@ -0,0 +1,130 @@ +package com.vince.xq.project.system.probeJobConfig.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.vince.xq.framework.aspectj.lang.annotation.Excel; + +import java.io.Serializable; +import java.util.Date; + +/** + * 岗位表 sys_post + * + * @author ruoyi + */ +public class Probejobconfig implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** id */ + @Excel(name = "id", cellType = Excel.ColumnType.NUMERIC) + private Long id; + + @Excel(name = "tableName") + private String tableName; + + @Excel(name = "tablePrimary") + private String tablePrimary; + + @Excel(name = "tableEnumFields") + private String tableEnumFields; + + @Excel(name = "tableNullFields") + private String tableNullFields; + + @Excel(name = "tableLengthFields") + private String tableLengthFields; + + /** createBy */ + @Excel(name = "createBy") + private String createBy; + + @Excel(name = "filter") + private String filter; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @Excel(name = "dbConfigId") + private Long dbConfigId; + + public String getTableLengthFields() { + return tableLengthFields; + } + + public void setTableLengthFields(String tableLengthFields) { + this.tableLengthFields = tableLengthFields; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFilter() { + return filter; + } + + public void setFilter(String filter) { + this.filter = filter; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public String getTablePrimary() { + return tablePrimary; + } + + public void setTablePrimary(String tablePrimary) { + this.tablePrimary = tablePrimary; + } + + public String getTableEnumFields() { + return tableEnumFields; + } + + public void setTableEnumFields(String tableEnumFields) { + this.tableEnumFields = tableEnumFields; + } + + public String getTableNullFields() { + return tableNullFields; + } + + public void setTableNullFields(String tableNullFields) { + this.tableNullFields = tableNullFields; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Long getDbConfigId() { + return dbConfigId; + } + + public void setDbConfigId(Long dbConfigId) { + this.dbConfigId = dbConfigId; + } +} diff --git a/src/main/java/com/vince/xq/project/system/probeJobConfig/mapper/ProbeJobconfigMapper.java b/src/main/java/com/vince/xq/project/system/probeJobConfig/mapper/ProbeJobconfigMapper.java new file mode 100644 index 0000000..b856245 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/probeJobConfig/mapper/ProbeJobconfigMapper.java @@ -0,0 +1,25 @@ +package com.vince.xq.project.system.probeJobConfig.mapper; + +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; + +import java.util.List; + + +public interface ProbeJobconfigMapper +{ + + public List selectJobconfigList(Probejobconfig dbconfig); + + public List selectJobconfigAll(); + + public Probejobconfig selectJobconfigById(Long id); + + public int deleteJobconfigByIds(Long[] ids); + + //public int updateJobconfig(Probejobconfig dbconfig); + + public int insertJobconfig(Probejobconfig dbconfig); + + + public List selectJobconfigsByUser(String createBy); +} diff --git a/src/main/java/com/vince/xq/project/system/probeJobConfig/service/IProbeJobconfigService.java b/src/main/java/com/vince/xq/project/system/probeJobConfig/service/IProbeJobconfigService.java new file mode 100644 index 0000000..f903b9e --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/probeJobConfig/service/IProbeJobconfigService.java @@ -0,0 +1,36 @@ +package com.vince.xq.project.system.probeJobConfig.service; + +import com.vince.xq.common.exception.job.TaskException; +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; +import org.quartz.SchedulerException; + +import java.util.List; + +/** + * 岗位信息 服务层 + * + * @author ruoyi + */ +public interface IProbeJobconfigService +{ + public List selectJobconfigList(Probejobconfig dbconfig); + + public List selectJobconfigAll(); + + /*public List selectJobconfigsByUserId(Long userId);*/ + + public Probejobconfig selectJobconfigById(Long id); + + public List selectDbTypesAll(); + + public int deleteJobconfigByIds(String ids); + + public void insertJobconfig(Probejobconfig dbconfig) throws TaskException, SchedulerException; + + public int updateJobconfig(Probejobconfig dbconfig); + + public int countUserPostById(Long postId); + + public void checkTableName(Probejobconfig jobconfig) throws Exception; + +} diff --git a/src/main/java/com/vince/xq/project/system/probeJobConfig/service/ProbeJobconfigServiceImpl.java b/src/main/java/com/vince/xq/project/system/probeJobConfig/service/ProbeJobconfigServiceImpl.java new file mode 100644 index 0000000..43b8472 --- /dev/null +++ b/src/main/java/com/vince/xq/project/system/probeJobConfig/service/ProbeJobconfigServiceImpl.java @@ -0,0 +1,141 @@ +package com.vince.xq.project.system.probeJobConfig.service; + +import com.vince.xq.common.constant.Constants; +import com.vince.xq.common.exception.job.TaskException; +import com.vince.xq.common.utils.security.ShiroUtils; +import com.vince.xq.common.utils.text.Convert; +import com.vince.xq.project.common.DbTypeEnum; +import com.vince.xq.project.monitor.job.mapper.JobMapper; +import com.vince.xq.project.monitor.job.util.ScheduleUtils; +import com.vince.xq.project.system.dbconfig.domain.Dbconfig; +import com.vince.xq.project.system.dbconfig.mapper.DbconfigMapper; +import com.vince.xq.project.system.probeJobConfig.domain.Probejobconfig; +import com.vince.xq.project.system.probeJobConfig.mapper.ProbeJobconfigMapper; +import com.vince.xq.project.system.probeJobConfig.mapper.ProbeJobconfigMapper; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 岗位信息 服务层处理 + * + * @author ruoyi + */ +@Service +public class ProbeJobconfigServiceImpl implements IProbeJobconfigService { + + @Autowired + private ProbeJobconfigMapper probeJobconfigMapper; + + @Autowired + private DbconfigMapper dbconfigMapper; + + @Autowired + private JobMapper jobMapper; + + @Autowired + private Scheduler scheduler; + + @PostConstruct + public void init() throws SchedulerException, TaskException { + /*scheduler.clear(); + List jobList = probeJobconfigMapper.selectJobconfigAll(); + for (Probejobconfig job : jobList) { + if (job.getSchduleStatus().equals("0")) { + ScheduleUtils.createScheduleJob(scheduler, job); + } + }*/ + } + + @Override + public List selectJobconfigList(Probejobconfig dbconfig) { + return probeJobconfigMapper.selectJobconfigList(dbconfig); + } + + @Override + public List selectJobconfigAll() { + return probeJobconfigMapper.selectJobconfigAll(); + } + + /*@Override + public List selectJobconfigsByUserId(Long userId) + { + List userJobconfigs = probeJobconfigMapper.selectJobconfigsByUserId(userId); + List dbconfigs = probeJobconfigMapper.selectJobconfigAll(); + for (Jobconfig dbconfig : dbconfigs) + { + for (Jobconfig userJobconfig : userJobconfigs) + { + if (dbconfig.getId().longValue() == userJobconfig.getId().longValue()) + { + dbconfig.setFlag(true); + break; + } + } + } + return dbconfigs; + }*/ + + + @Override + public Probejobconfig selectJobconfigById(Long id) { + return probeJobconfigMapper.selectJobconfigById(id); + } + + @Override + public List selectDbTypesAll() { + List list = new ArrayList<>(); + for (DbTypeEnum dbTypeEnum : DbTypeEnum.values()) { + list.add(dbTypeEnum.getType()); + } + return list; + } + + @Override + public int deleteJobconfigByIds(String ids) { + Long[] idsArray = Convert.toLongArray(ids); + /*for (Long id : idsArray) + { + Jobconfig dbconfig = selectJobconfigById(id); + if (countUserPostById(dbconfig) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName())); + } + }*/ + return probeJobconfigMapper.deleteJobconfigByIds(idsArray); + } + + + @Override + public void insertJobconfig(Probejobconfig jobconfig) throws TaskException, SchedulerException { + jobconfig.setCreateBy(ShiroUtils.getLoginName()); + int rows = probeJobconfigMapper.insertJobconfig(jobconfig); + /*if (rows > 0 && jobconfig.getSchduleStatus().equals("0")) { + ScheduleUtils.createScheduleJob(scheduler, jobconfig); + }*/ + } + + @Override + public int updateJobconfig(Probejobconfig dbconfig) { + /*dbconfig.setCreateBy(ShiroUtils.getLoginName()); + return probeJobconfigMapper.updateJobconfig(dbconfig);*/ + return 0; + } + + @Override + public int countUserPostById(Long postId) { + return 0; + } + + @Override + public void checkTableName(Probejobconfig jobconfig) throws Exception { + Dbconfig dbconfig = dbconfigMapper.selectDbconfigById(jobconfig.getDbConfigId()); + //checkTableNameSql(dbconfig, DbTypeEnum.findEnumByType(dbconfig.getType()).getConnectDriver(), jobconfig); + } +} diff --git a/src/main/resources/EmailTemplate.txt b/src/main/resources/EmailTemplate.txt new file mode 100644 index 0000000..9d6ebf7 --- /dev/null +++ b/src/main/resources/EmailTemplate.txt @@ -0,0 +1,50 @@ + + + + + + + + + + +
+ + + + + + + + + +
+ dataCompare平台邮件 +
+
+ +

+ + + 对比结果: + +

+ +

量级对比校验通过:{0}


+

一致性对比校验通过:{1}


+

详细对比信息去dataCompare平台进行查看


+
+
+

dataCompare平台发送,请勿回复
+ Please do not reply to this system email +

+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0b690be..b34f7ae 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,7 +1,7 @@ # 项目相关配置 ruoyi: # 名称 - name: RuoYi + name: dataComapre # 版本 version: 4.7.5 # 版权年份 @@ -45,6 +45,18 @@ user: # Spring配置 spring: + mail: + enabled: false + host: smtp.qq.com + username: xxx@qq.com + password: xxx + properties: + mail: + smtp: + auth: true + starttls: + enable: true + required: true # 模板引擎 thymeleaf: mode: HTML @@ -64,7 +76,7 @@ spring: druid: # 主库数据源 master: - url: jdbc:mysql://127.0.0.1:3306/dataCompare?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://ip:3306/dataCompare?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: 123456 # 从库数据源 diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index c0bbd6b..eecd837 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,7 +1,7 @@ - + diff --git a/src/main/resources/mybatis/system/ProbeJobInstanceMapper.xml b/src/main/resources/mybatis/system/ProbeJobInstanceMapper.xml new file mode 100644 index 0000000..1d6a1e3 --- /dev/null +++ b/src/main/resources/mybatis/system/ProbeJobInstanceMapper.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + select a.id, + a.job_config_id, + a.primary_result, + a.enum_result, + a.null_result, + a.len_result, + a.create_time, + b.`table_name`, + b.filter + from probe_job_instance a + join probe_job_config b on a.job_config_id = b.id + + + + + + + + + + delete from probe_job_instance where id in + + #{id} + + + + + insert into probe_job_instance( + job_config_id, + primary_result, + enum_result, + null_result, + len_result, + create_time + )values( + #{jobconfigId}, + #{primaryResult}, + #{enumResult}, + #{nullResult}, + #{lenResult}, + sysdate() + ) + + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/system/ProbeJobconfigMapper.xml b/src/main/resources/mybatis/system/ProbeJobconfigMapper.xml new file mode 100644 index 0000000..30d1764 --- /dev/null +++ b/src/main/resources/mybatis/system/ProbeJobconfigMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + select id, `table_name`,table_primary, table_enum_fields, table_null_fields,table_length_fields,db_config_id,filter, + create_by, create_time + from probe_job_config + + + + + + + + + + delete from probe_job_config where id in + + #{id} + + + + + insert into probe_job_config( + `table_name`, + table_primary, + table_enum_fields, + table_null_fields, + table_length_fields, + + db_config_id, + filter, + create_by, + create_time + )values( + #{tableName}, + #{tablePrimary}, + #{tableEnumFields}, + #{tableNullFields}, + #{tableNullFields}, + + #{dbConfigId}, + #{filter}, + #{createBy}, + sysdate() + ) + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/system/jobconfig/add.html b/src/main/resources/templates/system/jobconfig/add.html index d97f105..b469c7c 100644 --- a/src/main/resources/templates/system/jobconfig/add.html +++ b/src/main/resources/templates/system/jobconfig/add.html @@ -23,10 +23,8 @@
-
- -
+
@@ -50,7 +48,7 @@
+ >
@@ -59,9 +57,21 @@
+ > +
+ + +
+ +
+
+
@@ -78,27 +88,38 @@
- +
- +
- +
- + +
+
+ +
@@ -111,6 +132,15 @@ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ + + + + + diff --git a/src/main/resources/templates/system/probeJobConfig/edit.html b/src/main/resources/templates/system/probeJobConfig/edit.html new file mode 100644 index 0000000..1050abc --- /dev/null +++ b/src/main/resources/templates/system/probeJobConfig/edit.html @@ -0,0 +1,86 @@ + + + + + + +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+
+ + + + diff --git a/src/main/resources/templates/system/probeJobConfig/probeJobConfig.html b/src/main/resources/templates/system/probeJobConfig/probeJobConfig.html new file mode 100644 index 0000000..6451aeb --- /dev/null +++ b/src/main/resources/templates/system/probeJobConfig/probeJobConfig.html @@ -0,0 +1,115 @@ + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/resources/templates/system/probeJobInstance/add.html b/src/main/resources/templates/system/probeJobInstance/add.html new file mode 100644 index 0000000..4aaadc0 --- /dev/null +++ b/src/main/resources/templates/system/probeJobInstance/add.html @@ -0,0 +1,108 @@ + + + + + + + +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ + + + + + diff --git a/src/main/resources/templates/system/probeJobInstance/detail.html b/src/main/resources/templates/system/probeJobInstance/detail.html new file mode 100644 index 0000000..197b5fd --- /dev/null +++ b/src/main/resources/templates/system/probeJobInstance/detail.html @@ -0,0 +1,169 @@ + + + + + + +
+ +
+ + +
+ +
+
+ +
+ + + + + + + + + + + + + + +
表名
过滤条件
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + +
主键
总行数
主键去重总行数
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
字段名
空值行数
总行数
空值占比
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + +
enum_value
num
+ +
+ + +
+ +
+ +
+ +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + +
lenth_value
num
+ +
+ +
+ +
+
+ + + + diff --git a/src/main/resources/templates/system/probeJobInstance/edit.html b/src/main/resources/templates/system/probeJobInstance/edit.html new file mode 100644 index 0000000..1050abc --- /dev/null +++ b/src/main/resources/templates/system/probeJobInstance/edit.html @@ -0,0 +1,86 @@ + + + + + + +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+
+ + + + diff --git a/src/main/resources/templates/system/probeJobInstance/probeJobInstance.html b/src/main/resources/templates/system/probeJobInstance/probeJobInstance.html new file mode 100644 index 0000000..5841267 --- /dev/null +++ b/src/main/resources/templates/system/probeJobInstance/probeJobInstance.html @@ -0,0 +1,96 @@ + + + + + + +
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/test/java/SpringBootApplicationTest.java b/src/test/java/SpringBootApplicationTest.java new file mode 100644 index 0000000..0875476 --- /dev/null +++ b/src/test/java/SpringBootApplicationTest.java @@ -0,0 +1,94 @@ +import com.vince.xq.DataCompareApplication; +import com.vince.xq.common.constant.Constants; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.MessageFormat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = DataCompareApplication.class) +public class SpringBootApplicationTest { + + @Autowired + private JavaMailSender javaMailSender; + + @Value("${spring.mail.username}") + private String fromEmail; + + @Test + public void sendHtmlMail() throws MessagingException { + String content = buildTemplate(true, true); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(fromEmail); + helper.setTo("xiaoqiu2017wy@163.com"); + helper.setSubject(Constants.EMAIL_TITLE); + // 设置邮件内容,第二个参数设置是否支持 text/html 类型 + helper.setText(content, true); + javaMailSender.send(mimeMessage); + } catch (MessagingException e) { + e.printStackTrace(); + } + } + + @Test + public void sendMail() { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(fromEmail); + message.setTo("xiaoqiu2017wy@163.com"); + message.setSubject("主题:简单邮件"); + message.setText("测试邮件内容"); + javaMailSender.send(message); + } + + private String buildTemplate(boolean numFlag, boolean consistencyFlag) { + //加载邮件html模板 + Resource resource = new ClassPathResource("EmailTemplate.txt"); + InputStream inputStream = null; + BufferedReader fileReader = null; + StringBuffer buffer = new StringBuffer(); + String line = ""; + try { + inputStream = resource.getInputStream(); + fileReader = new BufferedReader(new InputStreamReader(inputStream)); + while ((line = fileReader.readLine()) != null) { + buffer.append(line); + } + } catch (Exception e) { + } finally { + if (fileReader != null) { + try { + fileReader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + //替换html模板中的参数 + return MessageFormat.format(buffer.toString(), numFlag, consistencyFlag); + } + +} \ No newline at end of file diff --git a/src/test/java/XqTest.java b/src/test/java/XqTest.java index 0a45db7..60577b7 100644 --- a/src/test/java/XqTest.java +++ b/src/test/java/XqTest.java @@ -7,7 +7,10 @@ import java.sql.*; + public class XqTest { + + /** @Test public void testSql() throws Exception { Dbconfig dbconfig = new Dbconfig(); @@ -62,4 +65,5 @@ public void testHive() throws Exception { throw new Exception("连接数据库失败"); } } + /** }