| @ -0,0 +1,15 @@ | |||||
| ## ide | |||||
| **/.idea | |||||
| *.iml | |||||
| rebel.xml | |||||
| ## backend | |||||
| **/target | |||||
| **/logs | |||||
| ## front | |||||
| **/*.lock | |||||
| os_del.cmd | |||||
| os_del_doc.cmd | |||||
| .svn | |||||
| derby.log | |||||
| @ -0,0 +1,213 @@ | |||||
| Apache License | |||||
| Version 2.0, January 2004 | |||||
| http://www.apache.org/licenses/ | |||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||||
| 1. Definitions. | |||||
| "License" shall mean the terms and conditions for use, reproduction, | |||||
| and distribution as defined by Sections 1 through 9 of this document. | |||||
| "Licensor" shall mean the copyright owner or entity authorized by | |||||
| the copyright owner that is granting the License. | |||||
| "Legal Entity" shall mean the union of the acting entity and all | |||||
| other entities that control, are controlled by, or are under common | |||||
| control with that entity. For the purposes of this definition, | |||||
| "control" means (i) the power, direct or indirect, to cause the | |||||
| direction or management of such entity, whether by contract or | |||||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||||
| outstanding shares, or (iii) beneficial ownership of such entity. | |||||
| "You" (or "Your") shall mean an individual or Legal Entity | |||||
| exercising permissions granted by this License. | |||||
| "Source" form shall mean the preferred form for making modifications, | |||||
| including but not limited to software source code, documentation | |||||
| source, and configuration files. | |||||
| "Object" form shall mean any form resulting from mechanical | |||||
| transformation or translation of a Source form, including but | |||||
| not limited to compiled object code, generated documentation, | |||||
| and conversions to other media types. | |||||
| "Work" shall mean the work of authorship, whether in Source or | |||||
| Object form, made available under the License, as indicated by a | |||||
| copyright notice that is included in or attached to the work | |||||
| (an example is provided in the Appendix below). | |||||
| "Derivative Works" shall mean any work, whether in Source or Object | |||||
| form, that is based on (or derived from) the Work and for which the | |||||
| editorial revisions, annotations, elaborations, or other modifications | |||||
| represent, as a whole, an original work of authorship. For the purposes | |||||
| of this License, Derivative Works shall not include works that remain | |||||
| separable from, or merely link (or bind by name) to the interfaces of, | |||||
| the Work and Derivative Works thereof. | |||||
| "Contribution" shall mean any work of authorship, including | |||||
| the original version of the Work and any modifications or additions | |||||
| to that Work or Derivative Works thereof, that is intentionally | |||||
| submitted to Licensor for inclusion in the Work by the copyright owner | |||||
| or by an individual or Legal Entity authorized to submit on behalf of | |||||
| the copyright owner. For the purposes of this definition, "submitted" | |||||
| means any form of electronic, verbal, or written communication sent | |||||
| to the Licensor or its representatives, including but not limited to | |||||
| communication on electronic mailing lists, source code control systems, | |||||
| and issue tracking systems that are managed by, or on behalf of, the | |||||
| Licensor for the purpose of discussing and improving the Work, but | |||||
| excluding communication that is conspicuously marked or otherwise | |||||
| designated in writing by the copyright owner as "Not a Contribution." | |||||
| "Contributor" shall mean Licensor and any individual or Legal Entity | |||||
| on behalf of whom a Contribution has been received by Licensor and | |||||
| subsequently incorporated within the Work. | |||||
| 2. Grant of Copyright License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| copyright license to reproduce, prepare Derivative Works of, | |||||
| publicly display, publicly perform, sublicense, and distribute the | |||||
| Work and such Derivative Works in Source or Object form. | |||||
| 3. Grant of Patent License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| (except as stated in this section) patent license to make, have made, | |||||
| use, offer to sell, sell, import, and otherwise transfer the Work, | |||||
| where such license applies only to those patent claims licensable | |||||
| by such Contributor that are necessarily infringed by their | |||||
| Contribution(s) alone or by combination of their Contribution(s) | |||||
| with the Work to which such Contribution(s) was submitted. If You | |||||
| institute patent litigation against any entity (including a | |||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | |||||
| or a Contribution incorporated within the Work constitutes direct | |||||
| or contributory patent infringement, then any patent licenses | |||||
| granted to You under this License for that Work shall terminate | |||||
| as of the date such litigation is filed. | |||||
| 4. Redistribution. You may reproduce and distribute copies of the | |||||
| Work or Derivative Works thereof in any medium, with or without | |||||
| modifications, and in Source or Object form, provided that You | |||||
| meet the following conditions: | |||||
| (a) You must give any other recipients of the Work or | |||||
| Derivative Works a copy of this License; and | |||||
| (b) You must cause any modified files to carry prominent notices | |||||
| stating that You changed the files; and | |||||
| (c) You must retain, in the Source form of any Derivative Works | |||||
| that You distribute, all copyright, patent, trademark, and | |||||
| attribution notices from the Source form of the Work, | |||||
| excluding those notices that do not pertain to any part of | |||||
| the Derivative Works; and | |||||
| (d) If the Work includes a "NOTICE" text file as part of its | |||||
| distribution, then any Derivative Works that You distribute must | |||||
| include a readable copy of the attribution notices contained | |||||
| within such NOTICE file, excluding those notices that do not | |||||
| pertain to any part of the Derivative Works, in at least one | |||||
| of the following places: within a NOTICE text file distributed | |||||
| as part of the Derivative Works; within the Source form or | |||||
| documentation, if provided along with the Derivative Works; or, | |||||
| within a display generated by the Derivative Works, if and | |||||
| wherever such third-party notices normally appear. The contents | |||||
| of the NOTICE file are for informational purposes only and | |||||
| do not modify the License. You may add Your own attribution | |||||
| notices within Derivative Works that You distribute, alongside | |||||
| or as an addendum to the NOTICE text from the Work, provided | |||||
| that such additional attribution notices cannot be construed | |||||
| as modifying the License. | |||||
| You may add Your own copyright statement to Your modifications and | |||||
| may provide additional or different license terms and conditions | |||||
| for use, reproduction, or distribution of Your modifications, or | |||||
| for any such Derivative Works as a whole, provided Your use, | |||||
| reproduction, and distribution of the Work otherwise complies with | |||||
| the conditions stated in this License. | |||||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | |||||
| any Contribution intentionally submitted for inclusion in the Work | |||||
| by You to the Licensor shall be under the terms and conditions of | |||||
| this License, without any additional terms or conditions. | |||||
| Notwithstanding the above, nothing herein shall supersede or modify | |||||
| the terms of any separate license agreement you may have executed | |||||
| with Licensor regarding such Contributions. | |||||
| 6. Trademarks. This License does not grant permission to use the trade | |||||
| names, trademarks, service marks, or product names of the Licensor, | |||||
| except as required for reasonable and customary use in describing the | |||||
| origin of the Work and reproducing the content of the NOTICE file. | |||||
| 7. Disclaimer of Warranty. Unless required by applicable law or | |||||
| agreed to in writing, Licensor provides the Work (and each | |||||
| Contributor provides its Contributions) on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||||
| implied, including, without limitation, any warranties or conditions | |||||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||||
| PARTICULAR PURPOSE. You are solely responsible for determining the | |||||
| appropriateness of using or redistributing the Work and assume any | |||||
| risks associated with Your exercise of permissions under this License. | |||||
| 8. Limitation of Liability. In no event and under no legal theory, | |||||
| whether in tort (including negligence), contract, or otherwise, | |||||
| unless required by applicable law (such as deliberate and grossly | |||||
| negligent acts) or agreed to in writing, shall any Contributor be | |||||
| liable to You for damages, including any direct, indirect, special, | |||||
| incidental, or consequential damages of any character arising as a | |||||
| result of this License or out of the use or inability to use the | |||||
| Work (including but not limited to damages for loss of goodwill, | |||||
| work stoppage, computer failure or malfunction, or any and all | |||||
| other commercial damages or losses), even if such Contributor | |||||
| has been advised of the possibility of such damages. | |||||
| 9. Accepting Warranty or Additional Liability. While redistributing | |||||
| the Work or Derivative Works thereof, You may choose to offer, | |||||
| and charge a fee for, acceptance of support, warranty, indemnity, | |||||
| or other liability obligations and/or rights consistent with this | |||||
| License. However, in accepting such obligations, You may act only | |||||
| on Your own behalf and on Your sole responsibility, not on behalf | |||||
| of any other Contributor, and only if You agree to indemnify, | |||||
| defend, and hold each Contributor harmless for any liability | |||||
| incurred by, or claims asserted against, such Contributor by reason | |||||
| of your accepting any such warranty or additional liability. | |||||
| END OF TERMS AND CONDITIONS | |||||
| APPENDIX: How to apply the Apache License to your work. | |||||
| To apply the Apache License to your work, attach the following | |||||
| boilerplate notice, with the fields enclosed by brackets "[]" | |||||
| replaced with your own identifying information. (Don't include | |||||
| the brackets!) The text should be enclosed in the appropriate | |||||
| comment syntax for the file format. We also recommend that a | |||||
| file or class name and description of purpose be included on the | |||||
| same "printed page" as the copyright notice for easier | |||||
| identification within third-party archives. | |||||
| Copyright (c) 2019 <a href="http://www.jeecg.com">Jeecg Boot</a> All rights reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | |||||
| In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software. | |||||
| JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com | |||||
| 本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。 | |||||
| 开源协议中文释意如下: | |||||
| 1.JeecgBoot开源版本无任何限制,在遵循本开源协议条款下,允许商用使用,不会造成侵权行为。 | |||||
| 2.允许基于本平台软件开展业务系统开发。 | |||||
| 3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件。 | |||||
| 最终解释权归:http://www.jeecg.com | |||||
| @ -0,0 +1,190 @@ | |||||
| JeecgBoot 低代码开发平台 | |||||
| =============== | |||||
| 当前最新版本: 3.8.0(发布日期:2025-04-21) | |||||
| [](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE) | |||||
| [](http://jeecg.com/aboutusIndex) | |||||
| [](https://github.com/zhangdaiscott/jeecg-boot) | |||||
| [](https://github.com/zhangdaiscott/jeecg-boot) | |||||
| [](https://github.com/zhangdaiscott/jeecg-boot) | |||||
| 项目介绍 | |||||
| ----------------------------------- | |||||
| <h3 align="center">Java Low Code Platform for Enterprise web applications</h3> | |||||
| JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x和3.x,SpringCloud,Ant Design Vue3,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性! | |||||
| #### 项目说明 | |||||
| | 项目名 | 说明 | | |||||
| |--------------------|------------------------| | |||||
| | `jeecg-boot` | 后端源码JAVA(SpringBoot微服务架构) | | |||||
| | `jeecgboot-vue3` | 前端源码VUE3(vue3+vite5+ts最新技术栈) | | |||||
| 技术文档 | |||||
| ----------------------------------- | |||||
| - 官方网站: [http://www.jeecg.com](http://www.jeecg.com) | |||||
| - 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | |||||
| - QQ交流群 : ⑩716488839、⑨808791225、其他(满) | |||||
| - 在线演示 : [在线演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) | |||||
| >## 1. 导入 SQL 文件 | |||||
| - 导入 `n10086.sql` 及 `jeecg-boot.sql` 文件后 | |||||
| --- | |||||
| ## 2. 平台管理登录信息 | |||||
| - **公司名**:`10086` | |||||
| - **帐号**:`admin` | |||||
| - **密码**:`1` | |||||
| --- | |||||
| ## 3. 创建新公司 | |||||
| 在 **租户管理 → 公司管理** 中随意创建一个公司,例如 `10090` | |||||
| --- | |||||
| ## 4. 租户登录信息 | |||||
| - **公司名**:`10090` | |||||
| - **帐号**:`admin` | |||||
| - **密码**:`123456` | |||||
| 启动项目 | |||||
| ----------------------------------- | |||||
| - [IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup) | |||||
| - [Docker一键启动前后端](https://help.jeecg.com/java/docker/quick) | |||||
| 微服务启动 | |||||
| ----------------------------------- | |||||
| - [单体快速切换微服务](https://help.jeecg.com/java/springcloud/switchcloud/monomer) | |||||
| - [Docker启动微服务后台](https://help.jeecg.com/java/docker/springcloud) | |||||
| 技术架构: | |||||
| ----------------------------------- | |||||
| #### 后端 | |||||
| - IDE建议: IDEA (必须安装lombok插件 ) | |||||
| - 语言:Java 8+ (支持17) | |||||
| - 依赖管理:Maven | |||||
| - 基础框架:Spring Boot 2.7.18 | |||||
| - 微服务框架: Spring Cloud Alibaba 2021.0.1.0 | |||||
| - 持久层框架:MybatisPlus 3.5.3.2 | |||||
| - 报表工具: JimuReport 1.9.4 | |||||
| - 安全框架:Apache Shiro 1.12.0,Jwt 3.11.0 | |||||
| - 微服务技术栈:Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking | |||||
| - 数据库连接池:阿里巴巴Druid 1.1.24 | |||||
| - 日志打印:logback | |||||
| - 缓存:Redis | |||||
| - 其他:autopoi, fastjson,poi,Swagger-ui,quartz, lombok(简化代码)等。 | |||||
| - 默认数据库脚本:MySQL5.7+ | |||||
| - [其他数据库,需要自己转](https://my.oschina.net/jeecg/blog/4905722) | |||||
| #### 前端 | |||||
| - 前端IDE建议:WebStorm、Vscode | |||||
| - 采用 Vue3.0+TypeScript+Vite+Ant-Design-Vue等新技术方案,包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能 | |||||
| - 最新技术栈:Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6 | |||||
| - 依赖管理:node、npm、pnpm | |||||
| #### 支持库 | |||||
| | 数据库 | 支持 | | |||||
| | --- | --- | | |||||
| | MySQL | √ | | |||||
| | Oracle11g | √ | | |||||
| | Sqlserver2017 | √ | | |||||
| | PostgreSQL | √ | | |||||
| | MariaDB | √ | | |||||
| | 达梦 | √ | | |||||
| | 人大金仓 | √ | | |||||
| | TiDB | √ | | |||||
| ## 微服务解决方案 | |||||
| - 1、服务注册和发现 Nacos √ | |||||
| - 2、统一配置中心 Nacos √ | |||||
| - 3、路由网关 gateway(三种加载方式) √ | |||||
| - 4、分布式 http feign √ | |||||
| - 5、熔断降级限流 Sentinel √ | |||||
| - 6、分布式文件 Minio、阿里OSS √ | |||||
| - 7、统一权限控制 JWT + Shiro √ | |||||
| - 8、服务监控 SpringBootAdmin√ | |||||
| - 9、链路跟踪 Skywalking [参考文档](https://help.jeecg.com/java/springcloud/super/skywarking) | |||||
| - 10、消息中间件 RabbitMQ √ | |||||
| - 11、分布式任务 xxl-job √ | |||||
| - 12、分布式事务 Seata | |||||
| - 13、轻量分布式日志 Loki+grafana套件 | |||||
| - 14、支持 docker-compose、k8s、jenkins | |||||
| - 15、CAS 单点登录 √ | |||||
| - 16、路由限流 √ | |||||
| 后台目录结构 | |||||
| ----------------------------------- | |||||
| ``` | |||||
| 项目结构 | |||||
| ├─jeecg-boot-parent(父POM: 项目依赖、modules组织) | |||||
| │ ├─jeecg-boot-base-core(共通模块: 工具类、config、权限、查询过滤器、注解等) | |||||
| │ ├─jeecg-module-demo 示例代码 | |||||
| │ ├─jeecg-module-system System系统管理目录 | |||||
| │ │ ├─jeecg-system-biz System系统管理权限等功能 | |||||
| │ │ ├─jeecg-system-start System单体启动项目(8080) | |||||
| │ │ ├─jeecg-system-api System系统管理模块对外api | |||||
| │ │ │ ├─jeecg-system-cloud-api System模块对外提供的微服务接口 | |||||
| │ │ │ ├─jeecg-system-local-api System模块对外提供的单体接口 | |||||
| │ ├─jeecg-server-cloud --微服务模块 | |||||
| ├─jeecg-cloud-gateway --微服务网关模块(9999) | |||||
| ├─jeecg-cloud-nacos --Nacos服务模块(8848) | |||||
| ├─jeecg-system-cloud-start --System微服务启动项目(7001) | |||||
| ├─jeecg-demo-cloud-start --Demo微服务启动项目(7002) | |||||
| ├─jeecg-visual | |||||
| ├─jeecg-cloud-monitor --微服务监控模块 (9111) | |||||
| ├─jeecg-cloud-xxljob --微服务xxljob定时任务服务端 (9080) | |||||
| ├─jeecg-cloud-sentinel --sentinel服务端 (9000) | |||||
| ├─jeecg-cloud-test -- 微服务测试示例(各种例子) | |||||
| ├─jeecg-cloud-test-more -- 微服务测试示例(feign、熔断降级、xxljob、分布式锁) | |||||
| ├─jeecg-cloud-test-rabbitmq -- 微服务测试示例(rabbitmq) | |||||
| ├─jeecg-cloud-test-seata -- 微服务测试示例(seata分布式事务) | |||||
| ├─jeecg-cloud-test-shardingsphere -- 微服务测试示例(分库分表) | |||||
| ``` | |||||
| #### 微服务架构图 | |||||
|  | |||||
| @ -0,0 +1,13 @@ | |||||
| FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/mysql:8.0.19 | |||||
| MAINTAINER jeecgos@163.com | |||||
| ENV TZ=Asia/Shanghai | |||||
| RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone | |||||
| COPY ./tables_nacos.sql /docker-entrypoint-initdb.d | |||||
| COPY ./jeecgboot-mysql-5.7.sql /docker-entrypoint-initdb.d | |||||
| COPY ./tables_xxl_job.sql /docker-entrypoint-initdb.d | |||||
| @ -0,0 +1,360 @@ | |||||
| # | |||||
| # XXL-JOB v2.2.0 | |||||
| # Copyright (c) 2015-present, xuxueli. | |||||
| CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_general_ci; | |||||
| use `xxl_job`; | |||||
| /* | |||||
| Navicat Premium Data Transfer | |||||
| Source Server : mysql5.7 | |||||
| Source Server Type : MySQL | |||||
| Source Server Version : 50738 (5.7.38) | |||||
| Source Host : 127.0.0.1:3306 | |||||
| Source Schema : xxl_job | |||||
| Target Server Type : MySQL | |||||
| Target Server Version : 50738 (5.7.38) | |||||
| File Encoding : 65001 | |||||
| Date: 10/02/2025 13:49:31 | |||||
| */ | |||||
| SET NAMES utf8mb4; | |||||
| SET FOREIGN_KEY_CHECKS = 0; | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_group | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_group`; | |||||
| CREATE TABLE `xxl_job_group` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `app_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器AppName', | |||||
| `title` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器名称', | |||||
| `address_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '执行器地址类型:0=自动注册、1=手动录入', | |||||
| `address_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行器地址列表,多地址逗号分隔', | |||||
| `update_time` datetime NULL DEFAULT NULL, | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_group | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_group` VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2025-02-10 13:49:04'); | |||||
| INSERT INTO `xxl_job_group` VALUES (2, 'jeecg-demo', '测试Demo模块', 0, NULL, '2025-02-10 13:49:04'); | |||||
| INSERT INTO `xxl_job_group` VALUES (3, 'jeecg-system', '系统System模块', 0, NULL, '2025-02-10 13:49:04'); | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_info | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_info`; | |||||
| CREATE TABLE `xxl_job_info` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `job_group` int(11) NOT NULL COMMENT '执行器主键ID', | |||||
| `job_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | |||||
| `add_time` datetime NULL DEFAULT NULL, | |||||
| `update_time` datetime NULL DEFAULT NULL, | |||||
| `author` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者', | |||||
| `alarm_email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '报警邮件', | |||||
| `schedule_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NONE' COMMENT '调度类型', | |||||
| `schedule_conf` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型', | |||||
| `misfire_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略', | |||||
| `executor_route_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器路由策略', | |||||
| `executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler', | |||||
| `executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数', | |||||
| `executor_block_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '阻塞处理策略', | |||||
| `executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒', | |||||
| `executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数', | |||||
| `glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE类型', | |||||
| `glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码', | |||||
| `glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE备注', | |||||
| `glue_updatetime` datetime NULL DEFAULT NULL COMMENT 'GLUE更新时间', | |||||
| `child_jobid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '子任务ID,多个逗号分隔', | |||||
| `trigger_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '调度状态:0-停止,1-运行', | |||||
| `trigger_last_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '上次调度时间', | |||||
| `trigger_next_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '下次调度时间', | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_info | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_info` VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2024-08-21 22:30:30', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '', 1, 1729353600000, 1739203200000); | |||||
| INSERT INTO `xxl_job_info` VALUES (2, 3, '测试jeecg xxljob', '2024-08-21 22:41:10', '2024-08-21 22:41:30', 'JEECG', '', 'CRON', '* * * * * ?', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2024-08-21 22:41:10', '', 1, 1739166572000, 1739166573000); | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_lock | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_lock`; | |||||
| CREATE TABLE `xxl_job_lock` ( | |||||
| `lock_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '锁名称', | |||||
| PRIMARY KEY (`lock_name`) USING BTREE | |||||
| ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_lock | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_lock` VALUES ('schedule_lock'); | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_log | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_log`; | |||||
| CREATE TABLE `xxl_job_log` ( | |||||
| `id` bigint(20) NOT NULL AUTO_INCREMENT, | |||||
| `job_group` int(11) NOT NULL COMMENT '执行器主键ID', | |||||
| `job_id` int(11) NOT NULL COMMENT '任务,主键ID', | |||||
| `executor_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器地址,本次执行的地址', | |||||
| `executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler', | |||||
| `executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数', | |||||
| `executor_sharding_param` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2', | |||||
| `executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数', | |||||
| `trigger_time` datetime NULL DEFAULT NULL COMMENT '调度-时间', | |||||
| `trigger_code` int(11) NOT NULL COMMENT '调度-结果', | |||||
| `trigger_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '调度-日志', | |||||
| `handle_time` datetime NULL DEFAULT NULL COMMENT '执行-时间', | |||||
| `handle_code` int(11) NOT NULL COMMENT '执行-状态', | |||||
| `handle_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行-日志', | |||||
| `alarm_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败', | |||||
| PRIMARY KEY (`id`) USING BTREE, | |||||
| INDEX `I_trigger_time`(`trigger_time`) USING BTREE, | |||||
| INDEX `I_handle_code`(`handle_code`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 6761 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_log | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_log` VALUES (6618, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6619, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6620, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6621, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6622, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6623, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6624, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6625, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6626, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6627, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6628, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6629, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6630, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6631, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6632, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6633, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6634, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6635, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6636, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6637, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6638, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6639, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6640, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6641, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:32', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6642, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:33', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6643, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:34', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6644, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:35', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6645, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:36', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6646, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:37', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6647, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:38', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6648, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:39', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6649, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:40', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6650, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:41', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6651, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:42', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6652, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:43', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6653, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:44', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6654, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:45', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6655, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:46', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6656, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:47', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6657, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:48', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6658, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:49', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6659, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:50', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6660, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:51', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6661, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:52', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6662, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:53', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6663, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:54', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6664, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:55', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6665, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:56', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6666, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:57', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6667, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:58', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6668, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:59', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6669, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:00', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6670, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:01', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6671, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:02', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6672, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:03', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6673, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:04', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6674, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:05', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6675, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:06', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6676, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:07', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6677, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:08', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6678, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6679, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6680, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6681, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6682, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6683, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6684, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6685, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6686, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6687, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6688, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6689, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6690, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6691, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6692, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6693, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6694, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6695, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6696, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6697, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6698, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6699, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6700, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6701, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:32', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6702, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:33', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6703, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:34', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6704, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:35', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6705, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:36', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6706, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:37', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6707, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:38', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6708, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:39', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6709, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:40', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6710, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:41', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6711, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:42', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6712, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:43', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6713, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:44', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6714, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:45', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6715, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:46', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6716, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:47', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6717, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:48', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6718, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:49', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6719, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:50', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6720, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:51', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6721, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:52', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6722, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:53', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6723, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:54', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6724, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:55', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6725, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:56', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6726, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:57', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6727, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:58', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6728, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:59', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6729, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:00', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6730, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:01', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6731, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:02', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6732, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:03', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6733, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:04', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6734, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:05', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6735, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:06', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6736, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:07', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6737, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:08', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6738, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:09', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6739, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:10', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6740, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:11', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6741, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:12', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6742, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:13', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6743, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:14', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6744, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:15', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6745, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:16', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6746, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:17', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6747, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:18', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6748, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:19', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6749, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:20', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6750, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:21', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6751, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:22', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6752, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:23', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6753, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:24', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2); | |||||
| INSERT INTO `xxl_job_log` VALUES (6754, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:25', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6755, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:26', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6756, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:27', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6757, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:28', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6758, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:29', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6759, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:30', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| INSERT INTO `xxl_job_log` VALUES (6760, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:31', 500, '任务触发类型:Cron触发<br>调度机器:192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0); | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_log_report | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_log_report`; | |||||
| CREATE TABLE `xxl_job_log_report` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `trigger_day` datetime NULL DEFAULT NULL COMMENT '调度-时间', | |||||
| `running_count` int(11) NOT NULL DEFAULT 0 COMMENT '运行中-日志数量', | |||||
| `suc_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行成功-日志数量', | |||||
| `fail_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量', | |||||
| `update_time` datetime NULL DEFAULT NULL, | |||||
| PRIMARY KEY (`id`) USING BTREE, | |||||
| UNIQUE INDEX `i_trigger_day`(`trigger_day`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_log_report | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_log_report` VALUES (1, '2024-08-21 00:00:00', 70, 0, 5, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (2, '2024-08-20 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (3, '2024-08-19 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (4, '2024-09-10 00:00:00', 0, 0, 56, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (5, '2024-09-09 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (6, '2024-09-08 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (7, '2024-10-19 00:00:00', 0, 0, 6391, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (8, '2024-10-18 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (9, '2024-10-17 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (10, '2025-02-10 00:00:00', 0, 0, 116, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (11, '2025-02-09 00:00:00', 0, 0, 0, NULL); | |||||
| INSERT INTO `xxl_job_log_report` VALUES (12, '2025-02-08 00:00:00', 0, 0, 0, NULL); | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_logglue | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_logglue`; | |||||
| CREATE TABLE `xxl_job_logglue` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `job_id` int(11) NOT NULL COMMENT '任务,主键ID', | |||||
| `glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE类型', | |||||
| `glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码', | |||||
| `glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE备注', | |||||
| `add_time` datetime NULL DEFAULT NULL, | |||||
| `update_time` datetime NULL DEFAULT NULL, | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_logglue | |||||
| -- ---------------------------- | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_registry | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_registry`; | |||||
| CREATE TABLE `xxl_job_registry` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `registry_group` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | |||||
| `registry_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | |||||
| `registry_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | |||||
| `update_time` datetime NULL DEFAULT NULL, | |||||
| PRIMARY KEY (`id`) USING BTREE, | |||||
| INDEX `i_g_k_v`(`registry_group`, `registry_key`, `registry_value`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_registry | |||||
| -- ---------------------------- | |||||
| -- ---------------------------- | |||||
| -- Table structure for xxl_job_user | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `xxl_job_user`; | |||||
| CREATE TABLE `xxl_job_user` ( | |||||
| `id` int(11) NOT NULL AUTO_INCREMENT, | |||||
| `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号', | |||||
| `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', | |||||
| `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员', | |||||
| `permission` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割', | |||||
| PRIMARY KEY (`id`) USING BTREE, | |||||
| UNIQUE INDEX `i_username`(`username`) USING BTREE | |||||
| ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | |||||
| -- ---------------------------- | |||||
| -- Records of xxl_job_user | |||||
| -- ---------------------------- | |||||
| INSERT INTO `xxl_job_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL); | |||||
| SET FOREIGN_KEY_CHECKS = 1; | |||||
| @ -0,0 +1,170 @@ | |||||
| /* | |||||
| Navicat Premium Data Transfer | |||||
| Source Server : mysql5.7 | |||||
| Source Server Type : MySQL | |||||
| Source Server Version : 50738 (5.7.38) | |||||
| Source Host : 127.0.0.1:3306 | |||||
| Source Schema : jeecg-boot | |||||
| Target Server Type : MySQL | |||||
| Target Server Version : 50738 (5.7.38) | |||||
| File Encoding : 65001 | |||||
| Date: 15/05/2025 10:18:36 | |||||
| */ | |||||
| SET NAMES utf8mb4; | |||||
| SET FOREIGN_KEY_CHECKS = 0; | |||||
| -- ---------------------------- | |||||
| -- Table structure for open_api | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `open_api`; | |||||
| CREATE TABLE `open_api` ( | |||||
| `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, | |||||
| `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '接口名称', | |||||
| `request_method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '请求方法', | |||||
| `request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '接口地址', | |||||
| `black_list` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'IP 黑名单', | |||||
| `body` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '请求体内容', | |||||
| `origin_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '原始地址', | |||||
| `status` int(10) NULL DEFAULT NULL COMMENT '状态', | |||||
| `del_flag` int(10) NULL DEFAULT NULL COMMENT '删除标识', | |||||
| `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', | |||||
| `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', | |||||
| `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '修改人', | |||||
| `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间', | |||||
| `headers_json` json NULL COMMENT '请求头json', | |||||
| `params_json` json NULL COMMENT '请求参数json', | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '接口表' ROW_FORMAT = DYNAMIC; | |||||
| -- ---------------------------- | |||||
| -- Records of open_api | |||||
| -- ---------------------------- | |||||
| INSERT INTO `open_api` VALUES ('1922132683346649090', '根据部门查询用户', 'GET', 'TEwcXBlr', NULL, NULL, '/sys/user/queryUserByDepId', 1, 0, 'admin', '2025-05-13 11:31:58', 'admin', '2025-05-15 10:10:01', '[]', '[{\"id\": \"row_24\", \"note\": \"\", \"paramKey\": \"id\", \"required\": \"1\", \"defaultValue\": \"\"}]'); | |||||
| -- ---------------------------- | |||||
| -- Table structure for open_api_auth | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `open_api_auth`; | |||||
| CREATE TABLE `open_api_auth` ( | |||||
| `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, | |||||
| `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '授权名称', | |||||
| `ak` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'AK', | |||||
| `sk` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'SK', | |||||
| `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', | |||||
| `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', | |||||
| `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '修改人', | |||||
| `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间', | |||||
| `system_user_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '关联系统用户名', | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '权限表' ROW_FORMAT = DYNAMIC; | |||||
| -- ---------------------------- | |||||
| -- Records of open_api_auth | |||||
| -- ---------------------------- | |||||
| INSERT INTO `open_api_auth` VALUES ('1922164194775056386', 'scott', 'ak-pFjyNHWRsJEFWlu6', '4hV5dBrZtmGAtPdbA5yseaeKRYNpzGsS', 'admin', '2025-05-13 13:37:11', NULL, NULL, 'e9ca23d68d884d4ebb19d07889727dae'); | |||||
| -- ---------------------------- | |||||
| -- Table structure for open_api_log | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `open_api_log`; | |||||
| CREATE TABLE `open_api_log` ( | |||||
| `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, | |||||
| `api_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '接口ID', | |||||
| `call_auth_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '调用ID', | |||||
| `call_time` datetime NULL DEFAULT NULL COMMENT '调用时间', | |||||
| `used_time` bigint(20) NULL DEFAULT NULL COMMENT '耗时', | |||||
| `response_time` datetime NULL DEFAULT NULL COMMENT '响应时间', | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '调用记录表' ROW_FORMAT = DYNAMIC; | |||||
| -- ---------------------------- | |||||
| -- Records of open_api_log | |||||
| -- ---------------------------- | |||||
| INSERT INTO `open_api_log` VALUES ('1922175238557913090', '1922132683346649090', '1922164194775056386', '2025-05-13 14:21:04', 94, '2025-05-13 14:21:04'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922175436256432130', '1922132683346649090', '1922164194775056386', '2025-05-13 14:21:51', 38, '2025-05-13 14:21:51'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922175487921868802', '1922132683346649090', '1922164194775056386', '2025-05-13 14:22:03', 31, '2025-05-13 14:22:03'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922176033789562883', '1922132683346649090', '1922164194775056386', '2025-05-13 14:24:13', 27, '2025-05-13 14:24:13'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922176583943835650', '1922132683346649090', '1922164194775056386', '2025-05-13 14:26:25', 39, '2025-05-13 14:26:25'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922177249969934337', '1922132683346649090', '1922164194775056386', '2025-05-13 14:28:08', 55250, '2025-05-13 14:29:03'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922180212645941249', '1922132683346649090', '1922164194775056386', '2025-05-13 14:40:46', 4162, '2025-05-13 14:40:50'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922180441692688385', '1922132683346649090', '1922164194775056386', '2025-05-13 14:41:11', 33346, '2025-05-13 14:41:44'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922180521686454273', '1922132683346649090', '1922164194775056386', '2025-05-13 14:42:00', 3570, '2025-05-13 14:42:03'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922180965825499138', '1922132683346649090', '1922164194775056386', '2025-05-13 14:42:10', 99211, '2025-05-13 14:43:49'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922181034515615746', '1922132683346649090', '1922164194775056386', '2025-05-13 14:43:52', 14005, '2025-05-13 14:44:06'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922183171307982850', '1922132683346649090', '1922164194775056386', '2025-05-13 14:52:15', 19834, '2025-05-13 14:52:35'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922184177068523521', '1922132683346649090', '1922164194775056386', '2025-05-13 14:56:34', 748, '2025-05-13 14:56:35'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922184729043107841', '1922132683346649090', '1922164194775056386', '2025-05-13 14:58:46', 1031, '2025-05-13 14:58:47'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922184806453182465', '1922132683346649090', '1922164194775056386', '2025-05-13 14:59:05', 68, '2025-05-13 14:59:05'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922184918382379009', '1922132683346649090', '1922164194775056386', '2025-05-13 14:59:10', 22155, '2025-05-13 14:59:32'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922185292635844610', '1922132683346649090', '1922164194775056386', '2025-05-13 15:00:55', 6267, '2025-05-13 15:01:01'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922186002672791554', '1922132683346649090', '1922164194775056386', '2025-05-13 15:03:23', 27554, '2025-05-13 15:03:50'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922187506582425601', '1922132683346649090', '1922164194775056386', '2025-05-13 15:09:45', 3464, '2025-05-13 15:09:49'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922187586597163011', '1922132683346649090', '1922164194775056386', '2025-05-13 15:10:08', 82, '2025-05-13 15:10:08'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922187924741951490', '1922132683346649090', '1922164194775056386', '2025-05-13 15:10:49', 39590, '2025-05-13 15:11:28'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922188138710261761', '1922132683346649090', '1922164194775056386', '2025-05-13 15:12:19', 758, '2025-05-13 15:12:19'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922188290661507073', '1922132683346649090', '1922164194775056386', '2025-05-13 15:12:29', 26527, '2025-05-13 15:12:56'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922189701755424769', '1922132683346649090', '1922164194775056386', '2025-05-13 15:18:28', 3619, '2025-05-13 15:18:32'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922190076784803841', '1922132683346649090', '1922164194775056386', '2025-05-13 15:20:01', 741, '2025-05-13 15:20:02'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922836671113101313', '1922132683346649090', '1922164194775056386', '2025-05-15 10:09:21', 186, '2025-05-15 10:09:22'); | |||||
| INSERT INTO `open_api_log` VALUES ('1922836856287428610', '1922132683346649090', '1922164194775056386', '2025-05-15 10:10:06', 145, '2025-05-15 10:10:06'); | |||||
| -- ---------------------------- | |||||
| -- Table structure for open_api_permission | |||||
| -- ---------------------------- | |||||
| DROP TABLE IF EXISTS `open_api_permission`; | |||||
| CREATE TABLE `open_api_permission` ( | |||||
| `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, | |||||
| `api_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '接口ID', | |||||
| `api_auth_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '认证ID', | |||||
| `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人', | |||||
| `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', | |||||
| `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人', | |||||
| `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', | |||||
| PRIMARY KEY (`id`) USING BTREE | |||||
| ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'openapi授权' ROW_FORMAT = DYNAMIC; | |||||
| -- ---------------------------- | |||||
| -- Records of open_api_permission | |||||
| -- ---------------------------- | |||||
| INSERT INTO `open_api_permission` VALUES ('1922164225875820545', '1922132683346649090', '1922164194775056386', 'admin', '2025-05-13 13:37:18', NULL, NULL); | |||||
| SET FOREIGN_KEY_CHECKS = 1; | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1917957565728198657', '1922109301837606914', '接口文档', '/openapi/SwaggerUI', 'openapi/SwaggerUI', 1, '', null, 1, null, '0', 1, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 23:01:32', 'admin', '2025-05-13 09:59:46', 0, 0, null, 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1922109301837606914', '', 'OpenApi管理', '/openapi', 'layouts/RouteView', 1, '', null, 0, null, '0', 12.1, 0, 'ant-design:swap-outlined', 0, 0, 0, 0, null, 'admin', '2025-05-13 09:59:03', 'admin', '2025-05-13 10:02:43', 0, 0, null, 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193340030', '1922109301837606914', '接口管理', '/openapi/openApiList', 'openapi/OpenApiList', 1, null, null, 1, null, '1', 0, 0, null, 0, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', 'admin', '2025-05-13 09:59:24', 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350031', '2025050104193340030', '添加接口管理', null, null, 0, null, null, 2, 'openapi:open_api:add', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350032', '2025050104193340030', '编辑接口管理', null, null, 0, null, null, 2, 'openapi:open_api:edit', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350033', '2025050104193340030', '删除接口管理', null, null, 0, null, null, 2, 'openapi:open_api:delete', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350034', '2025050104193340030', '批量删除接口管理', null, null, 0, null, null, 2, 'openapi:open_api:deleteBatch', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350035', '2025050104193340030', '导出excel_接口管理', null, null, 0, null, null, 2, 'openapi:open_api:exportXls', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050104193350036', '2025050104193340030', '导入excel_接口管理', null, null, 0, null, null, 2, 'openapi:open_api:importExcel', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 16:19:03', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940200', '1922109301837606914', '授权管理', '/openapi/openApiAuthList', 'openapi/OpenApiAuthList', 1, null, null, 1, null, '1', 0, 0, null, 0, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', 'admin', '2025-05-13 09:59:35', 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940201', '2025050105554940200', '添加授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:add', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940202', '2025050105554940200', '编辑授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:edit', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940203', '2025050105554940200', '删除授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:delete', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940204', '2025050105554940200', '批量删除授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:deleteBatch', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940205', '2025050105554940200', '导出excel_授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:exportXls', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('2025050105554940206', '2025050105554940200', '导入excel_授权管理', null, null, 0, null, null, 2, 'openapi:open_api_auth:importExcel', '1', null, 0, null, 1, 0, 0, 0, null, 'admin', '2025-05-01 17:55:20', null, null, 0, 0, '1', 0); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917957659860963330', 'f6817f48af4fb3af11b9e8bf182f618b', '1917957565728198657', null, '2025-05-01 23:01:55', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1922109760551858178', 'f6817f48af4fb3af11b9e8bf182f618b', '1922109301837606914', null, '2025-05-13 10:00:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071739539457', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193340030', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648321', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350031', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648322', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350032', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648323', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350033', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648324', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350034', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648325', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350035', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917857071806648326', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050104193350036', null, '2025-05-01 16:22:13', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917881149426864129', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050105554940200', null, '2025-05-01 17:57:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917881149431058436', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050105554940203', null, '2025-05-01 17:57:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917881149431058437', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050105554940204', null, '2025-05-01 17:57:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917881149431058438', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050105554940205', null, '2025-05-01 17:57:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917881149431058439', 'f6817f48af4fb3af11b9e8bf182f618b', '2025050105554940206', null, '2025-05-01 17:57:53', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1917957659860963330', 'f6817f48af4fb3af11b9e8bf182f618b', '1917957565728198657', null, '2025-05-01 23:01:55', '0:0:0:0:0:0:0:1'); | |||||
| INSERT INTO sys_role_permission (id, role_id, permission_id, data_rule_ids, operate_date, operate_ip) VALUES ('1922109760551858178', 'f6817f48af4fb3af11b9e8bf182f618b', '1922109301837606914', null, '2025-05-13 10:00:53', '0:0:0:0:0:0:0:1'); | |||||
| @ -0,0 +1,15 @@ | |||||
| # 版本升级方法 | |||||
| > JeecgBoot属于平台级产品,每次升级改动较大,目前做不到平滑升级。 | |||||
| ### 增量升级方案 | |||||
| #### 1.代码合并 | |||||
| 本地通过svn或git做好主干,在分支上做业务开发,jeecg每次版本发布,可以手工覆盖主干的代码,对比合并代码; | |||||
| #### 2.数据库升级 | |||||
| - 从3.6.2+版本增加flyway自动升级数据库机制,支持 mysql5.7、mysql8; | |||||
| - 其他库请手工执行SQL, 目录: `jeecg-module-system\jeecg-system-start\src\main\resources\flyway\sql\mysql` | |||||
| > 注意: 升级sql只提供mysql版本;如果有权限升级, 还需要手工角色授权,退出重新登录才好使。 | |||||
| #### 3.兼容问题 | |||||
| 每次发版,会针对不兼容地方重点说明。 | |||||
| @ -0,0 +1,52 @@ | |||||
| version: '2' | |||||
| services: | |||||
| jeecg-boot-mysql: | |||||
| build: | |||||
| context: ./db | |||||
| environment: | |||||
| MYSQL_ROOT_PASSWORD: root | |||||
| MYSQL_ROOT_HOST: '%' | |||||
| TZ: Asia/Shanghai | |||||
| restart: always | |||||
| container_name: jeecg-boot-mysql | |||||
| image: jeecg-boot-mysql | |||||
| command: | |||||
| --character-set-server=utf8mb4 | |||||
| --collation-server=utf8mb4_general_ci | |||||
| --explicit_defaults_for_timestamp=true | |||||
| --lower_case_table_names=1 | |||||
| --max_allowed_packet=128M | |||||
| --default-authentication-plugin=caching_sha2_password | |||||
| ports: | |||||
| - 3306:3306 | |||||
| networks: | |||||
| - jeecg-boot | |||||
| jeecg-boot-redis: | |||||
| image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0 | |||||
| ports: | |||||
| - 6379:6379 | |||||
| restart: always | |||||
| hostname: jeecg-boot-redis | |||||
| container_name: jeecg-boot-redis | |||||
| networks: | |||||
| - jeecg-boot | |||||
| jeecg-boot-system: | |||||
| build: | |||||
| context: ./jeecg-module-system/jeecg-system-start | |||||
| restart: on-failure | |||||
| depends_on: | |||||
| - jeecg-boot-mysql | |||||
| - jeecg-boot-redis | |||||
| container_name: jeecg-boot-system | |||||
| image: jeecg-boot-system | |||||
| hostname: jeecg-boot-system | |||||
| ports: | |||||
| - 8080:8080 | |||||
| networks: | |||||
| - jeecg-boot | |||||
| networks: | |||||
| jeecg-boot: | |||||
| name: jeecg_boot | |||||
| @ -0,0 +1,323 @@ | |||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
| <parent> | |||||
| <groupId>org.jeecgframework.boot</groupId> | |||||
| <artifactId>jeecg-boot-parent</artifactId> | |||||
| <version>3.8.0</version> | |||||
| </parent> | |||||
| <modelVersion>4.0.0</modelVersion> | |||||
| <artifactId>jeecg-boot-base-core</artifactId> | |||||
| <repositories> | |||||
| <repository> | |||||
| <id>aliyun</id> | |||||
| <name>aliyun Repository</name> | |||||
| <url>https://maven.aliyun.com/repository/public</url> | |||||
| <snapshots> | |||||
| <enabled>false</enabled> | |||||
| </snapshots> | |||||
| </repository> | |||||
| <repository> | |||||
| <id>jeecg</id> | |||||
| <name>jeecg Repository</name> | |||||
| <url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url> | |||||
| <snapshots> | |||||
| <enabled>false</enabled> | |||||
| </snapshots> | |||||
| </repository> | |||||
| <repository> | |||||
| <id>jeecg-snapshots</id> | |||||
| <name>jeecg-snapshots Repository</name> | |||||
| <url>https://oss.sonatype.org/content/repositories/snapshots</url> | |||||
| <releases> | |||||
| <enabled>false</enabled> | |||||
| </releases> | |||||
| <snapshots> | |||||
| <enabled>true</enabled> | |||||
| </snapshots> | |||||
| </repository> | |||||
| </repositories> | |||||
| <dependencies> | |||||
| <!--jeecg-tools--> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework.boot</groupId> | |||||
| <artifactId>jeecg-boot-common</artifactId> | |||||
| </dependency> | |||||
| <!--集成springmvc框架并实现自动配置 --> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-web</artifactId> | |||||
| <exclusions> | |||||
| <exclusion> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-tomcat</artifactId> | |||||
| </exclusion> | |||||
| </exclusions> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-undertow</artifactId> | |||||
| </dependency> | |||||
| <!-- websocket --> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-websocket</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-mail</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-aop</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-actuator</artifactId> | |||||
| </dependency> | |||||
| <!--springboot2.3+ 需引入validation对应的包--> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-validation</artifactId> | |||||
| </dependency> | |||||
| <!--springboot2.6+解决metrics端点不显示jvm信息的问题--> | |||||
| <dependency> | |||||
| <groupId>io.micrometer</groupId> | |||||
| <artifactId>micrometer-registry-prometheus</artifactId> | |||||
| </dependency> | |||||
| <!-- commons --> | |||||
| <dependency> | |||||
| <groupId>commons-io</groupId> | |||||
| <artifactId>commons-io</artifactId> | |||||
| <version>${commons-io.version}</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>commons-lang</groupId> | |||||
| <artifactId>commons-lang</artifactId> | |||||
| <version>${commons.version}</version> | |||||
| </dependency> | |||||
| <!-- freemarker --> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-freemarker</artifactId> | |||||
| </dependency> | |||||
| <!-- mybatis-plus --> | |||||
| <dependency> | |||||
| <groupId>com.baomidou</groupId> | |||||
| <artifactId>mybatis-plus-boot-starter</artifactId> | |||||
| <version>${mybatis-plus.version}</version> | |||||
| </dependency> | |||||
| <!-- druid --> | |||||
| <dependency> | |||||
| <groupId>com.alibaba</groupId> | |||||
| <artifactId>druid-spring-boot-starter</artifactId> | |||||
| <version>${druid.version}</version> | |||||
| </dependency> | |||||
| <!-- 动态数据源 --> | |||||
| <dependency> | |||||
| <groupId>com.baomidou</groupId> | |||||
| <artifactId>dynamic-datasource-spring-boot-starter</artifactId> | |||||
| <version>${dynamic-datasource-spring-boot-starter.version}</version> | |||||
| </dependency> | |||||
| <!-- 数据库驱动 --> | |||||
| <!--mysql--> | |||||
| <dependency> | |||||
| <groupId>mysql</groupId> | |||||
| <artifactId>mysql-connector-java</artifactId> | |||||
| <version>${mysql-connector-java.version}</version> | |||||
| <scope>runtime</scope> | |||||
| </dependency> | |||||
| <!-- sqlserver--> | |||||
| <dependency> | |||||
| <groupId>com.microsoft.sqlserver</groupId> | |||||
| <artifactId>sqljdbc4</artifactId> | |||||
| <version>${sqljdbc4.version}</version> | |||||
| <scope>runtime</scope> | |||||
| </dependency> | |||||
| <!-- oracle驱动 --> | |||||
| <dependency> | |||||
| <groupId>com.oracle</groupId> | |||||
| <artifactId>ojdbc6</artifactId> | |||||
| <version>${ojdbc6.version}</version> | |||||
| <scope>runtime</scope> | |||||
| </dependency> | |||||
| <!-- postgresql驱动 --> | |||||
| <dependency> | |||||
| <groupId>org.postgresql</groupId> | |||||
| <artifactId>postgresql</artifactId> | |||||
| <version>${postgresql.version}</version> | |||||
| <scope>runtime</scope> | |||||
| </dependency> | |||||
| <!--人大金仓驱动 版本号V008R006C005B0013 --> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework</groupId> | |||||
| <artifactId>kingbase8</artifactId> | |||||
| <version>9.0.0</version> | |||||
| <scope>runtime</scope> | |||||
| </dependency> | |||||
| <!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT --> | |||||
| <dependency> | |||||
| <groupId>com.dameng</groupId> | |||||
| <artifactId>Dm8JdbcDriver18</artifactId> | |||||
| <version>${dm8.version}</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>com.dameng</groupId> | |||||
| <artifactId>DmDialect-for-hibernate5.0</artifactId> | |||||
| <version>${dm8.version}</version> | |||||
| </dependency> | |||||
| <!-- Quartz定时任务 --> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-quartz</artifactId> | |||||
| </dependency> | |||||
| <!--JWT--> | |||||
| <dependency> | |||||
| <groupId>com.auth0</groupId> | |||||
| <artifactId>java-jwt</artifactId> | |||||
| <version>${java-jwt.version}</version> | |||||
| </dependency> | |||||
| <!--shiro--> | |||||
| <dependency> | |||||
| <groupId>org.apache.shiro</groupId> | |||||
| <artifactId>shiro-spring-boot-starter</artifactId> | |||||
| <version>${shiro.version}</version> | |||||
| </dependency> | |||||
| <!-- shiro-redis --> | |||||
| <dependency> | |||||
| <groupId>org.crazycake</groupId> | |||||
| <artifactId>shiro-redis</artifactId> | |||||
| <version>${shiro-redis.version}</version> | |||||
| <exclusions> | |||||
| <exclusion> | |||||
| <groupId>org.apache.shiro</groupId> | |||||
| <artifactId>shiro-core</artifactId> | |||||
| </exclusion> | |||||
| <exclusion> | |||||
| <artifactId>checkstyle</artifactId> | |||||
| <groupId>com.puppycrawl.tools</groupId> | |||||
| </exclusion> | |||||
| </exclusions> | |||||
| </dependency> | |||||
| <!-- knife4j --> | |||||
| <dependency> | |||||
| <groupId>com.github.xiaoymin</groupId> | |||||
| <artifactId>knife4j-openapi3-spring-boot-starter</artifactId> | |||||
| <version>${knife4j-spring-boot-starter.version}</version> | |||||
| </dependency> | |||||
| <!-- 代码生成器 --> | |||||
| <!-- 如下载失败,请参考此文档 https://help.jeecg.com/java/setup/maven.html --> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework.boot</groupId> | |||||
| <artifactId>codegenerate</artifactId> | |||||
| <version>${codegenerate.version}</version> | |||||
| <exclusions> | |||||
| <exclusion> | |||||
| <artifactId>commons-io</artifactId> | |||||
| <groupId>commons-io</groupId> | |||||
| </exclusion> | |||||
| <exclusion> | |||||
| <artifactId>mysql-connector-java</artifactId> | |||||
| <groupId>mysql</groupId> | |||||
| </exclusion> | |||||
| </exclusions> | |||||
| </dependency> | |||||
| <!-- AutoPoi Excel工具类--> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework</groupId> | |||||
| <artifactId>autopoi-web</artifactId> | |||||
| <version>${autopoi-web.version}</version> | |||||
| <exclusions> | |||||
| <exclusion> | |||||
| <groupId>commons-codec</groupId> | |||||
| <artifactId>commons-codec</artifactId> | |||||
| </exclusion> | |||||
| <exclusion> | |||||
| <artifactId>xercesImpl</artifactId> | |||||
| <groupId>xerces</groupId> | |||||
| </exclusion> | |||||
| </exclusions> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>xerces</groupId> | |||||
| <artifactId>xercesImpl</artifactId> | |||||
| <version>2.12.2</version> | |||||
| <optional>true</optional> | |||||
| </dependency> | |||||
| <!-- mini文件存储服务 --> | |||||
| <dependency> | |||||
| <groupId>io.minio</groupId> | |||||
| <artifactId>minio</artifactId> | |||||
| <exclusions> | |||||
| <exclusion> | |||||
| <artifactId>checker-qual</artifactId> | |||||
| <groupId>org.checkerframework</groupId> | |||||
| </exclusion> | |||||
| </exclusions> | |||||
| </dependency> | |||||
| <!-- 阿里云短信 --> | |||||
| <dependency> | |||||
| <groupId>com.aliyun</groupId> | |||||
| <artifactId>aliyun-java-sdk-dysmsapi</artifactId> | |||||
| <version>${aliyun-java-sdk-dysmsapi.version}</version> | |||||
| </dependency> | |||||
| <!-- aliyun oss --> | |||||
| <dependency> | |||||
| <groupId>com.aliyun.oss</groupId> | |||||
| <artifactId>aliyun-sdk-oss</artifactId> | |||||
| <version>${aliyun.oss.version}</version> | |||||
| </dependency> | |||||
| <!-- 第三方登录 --> | |||||
| <dependency> | |||||
| <groupId>com.xkcoding.justauth</groupId> | |||||
| <artifactId>justauth-spring-boot-starter</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>com.squareup.okhttp3</groupId> | |||||
| <artifactId>okhttp</artifactId> | |||||
| </dependency> | |||||
| <!-- 解决okhttp引用了kotlin,应用启动有警告日志问题 --> | |||||
| <dependency> | |||||
| <groupId>com.fasterxml.jackson.module</groupId> | |||||
| <artifactId>jackson-module-kotlin</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>commons-fileupload</groupId> | |||||
| <artifactId>commons-fileupload</artifactId> | |||||
| </dependency> | |||||
| <!--加载hutool--> | |||||
| <dependency> | |||||
| <groupId>cn.hutool</groupId> | |||||
| <artifactId>hutool-core</artifactId> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>cn.hutool</groupId> | |||||
| <artifactId>hutool-crypto</artifactId> | |||||
| </dependency> | |||||
| <!-- chatgpt --> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework.boot</groupId> | |||||
| <artifactId>jeecg-boot-starter-chatgpt</artifactId> | |||||
| </dependency> | |||||
| <!-- minidao --> | |||||
| <dependency> | |||||
| <groupId>org.jeecgframework</groupId> | |||||
| <artifactId>minidao-spring-boot-starter</artifactId> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| </project> | |||||
| @ -0,0 +1,147 @@ | |||||
| package org.jeecg.common.api; | |||||
| import org.jeecg.common.system.vo.*; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| /** | |||||
| * 通用api | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public interface CommonAPI { | |||||
| /** | |||||
| * 1查询用户角色信息 | |||||
| * @param username | |||||
| * @return | |||||
| */ | |||||
| Set<String> queryUserRoles(String username); | |||||
| /** | |||||
| * 1查询用户角色信息 | |||||
| * @param userId | |||||
| * @return | |||||
| */ | |||||
| Set<String> queryUserRolesById(String userId); | |||||
| /** | |||||
| * 2查询用户权限信息 | |||||
| * @param userId | |||||
| * @return | |||||
| */ | |||||
| Set<String> queryUserAuths(String userId); | |||||
| /** | |||||
| * 3根据 id 查询数据库中存储的 DynamicDataSourceModel | |||||
| * | |||||
| * @param dbSourceId | |||||
| * @return | |||||
| */ | |||||
| DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId); | |||||
| /** | |||||
| * 4根据 code 查询数据库中存储的 DynamicDataSourceModel | |||||
| * | |||||
| * @param dbSourceCode | |||||
| * @return | |||||
| */ | |||||
| DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode); | |||||
| /** | |||||
| * 5根据用户账号查询用户信息 | |||||
| * @param username | |||||
| * @return | |||||
| */ | |||||
| public LoginUser getUserByName(String username); | |||||
| /** | |||||
| * 5根据用户账号查询用户Id | |||||
| * @param username | |||||
| * @return | |||||
| */ | |||||
| public String getUserIdByName(String username); | |||||
| /** | |||||
| * 6字典表的 翻译 | |||||
| * @param table | |||||
| * @param text | |||||
| * @param code | |||||
| * @param key | |||||
| * @return | |||||
| */ | |||||
| String translateDictFromTable(String table, String text, String code, String key); | |||||
| /** | |||||
| * 7普通字典的翻译 | |||||
| * @param code | |||||
| * @param key | |||||
| * @return | |||||
| */ | |||||
| String translateDict(String code, String key); | |||||
| /** | |||||
| * 8查询数据权限 | |||||
| * @param component 组件 | |||||
| * @param username 用户名 | |||||
| * @param requestPath 前段请求地址 | |||||
| * @return | |||||
| */ | |||||
| List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username); | |||||
| /** | |||||
| * 9查询用户信息 | |||||
| * @param username | |||||
| * @return | |||||
| */ | |||||
| SysUserCacheInfo getCacheUser(String username); | |||||
| /** | |||||
| * 10获取数据字典 | |||||
| * @param code | |||||
| * @return | |||||
| */ | |||||
| public List<DictModel> queryDictItemsByCode(String code); | |||||
| /** | |||||
| * 获取有效的数据字典项 | |||||
| * @param code | |||||
| * @return | |||||
| */ | |||||
| public List<DictModel> queryEnableDictItemsByCode(String code); | |||||
| /** | |||||
| * 13获取表数据字典 | |||||
| * @param tableFilterSql | |||||
| * @param text | |||||
| * @param code | |||||
| * @return | |||||
| */ | |||||
| List<DictModel> queryTableDictItemsByCode(String tableFilterSql, String text, String code); | |||||
| /** | |||||
| * 14 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割 | |||||
| * @param dictCodes 例如:user_status,sex | |||||
| * @param keys 例如:1,2,0 | |||||
| * @return | |||||
| */ | |||||
| Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys); | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| /** | |||||
| * 15 字典表的 翻译,可批量 | |||||
| * @param table | |||||
| * @param text | |||||
| * @param code | |||||
| * @param keys 多个用逗号分割 | |||||
| * @param dataSource 数据源 | |||||
| * @return | |||||
| */ | |||||
| List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| } | |||||
| @ -0,0 +1,38 @@ | |||||
| package org.jeecg.common.api.dto; | |||||
| import lombok.Data; | |||||
| /** | |||||
| * @Author taoYan | |||||
| * @Date 2022/7/26 14:44 | |||||
| **/ | |||||
| @Data | |||||
| public class DataLogDTO { | |||||
| private String tableName; | |||||
| private String dataId; | |||||
| private String content; | |||||
| private String type; | |||||
| private String createName; | |||||
| public DataLogDTO(){ | |||||
| } | |||||
| public DataLogDTO(String tableName, String dataId, String content, String type) { | |||||
| this.tableName = tableName; | |||||
| this.dataId = dataId; | |||||
| this.content = content; | |||||
| this.type = type; | |||||
| } | |||||
| public DataLogDTO(String tableName, String dataId, String type) { | |||||
| this.tableName = tableName; | |||||
| this.dataId = dataId; | |||||
| this.type = type; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,31 @@ | |||||
| package org.jeecg.common.api.dto; | |||||
| import lombok.Data; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 文件下载 | |||||
| * cloud api 用到的接口传输对象 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class FileDownDTO implements Serializable { | |||||
| private static final long serialVersionUID = 6749126258686446019L; | |||||
| private String filePath; | |||||
| private String uploadpath; | |||||
| private String uploadType; | |||||
| private HttpServletResponse response; | |||||
| public FileDownDTO(){} | |||||
| public FileDownDTO(String filePath, String uploadpath, String uploadType,HttpServletResponse response){ | |||||
| this.filePath = filePath; | |||||
| this.uploadpath = uploadpath; | |||||
| this.uploadType = uploadType; | |||||
| this.response = response; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,56 @@ | |||||
| package org.jeecg.common.api.dto; | |||||
| import lombok.Data; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 文件上传 | |||||
| * cloud api 用到的接口传输对象 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class FileUploadDTO implements Serializable { | |||||
| private static final long serialVersionUID = -4111953058578954386L; | |||||
| private MultipartFile file; | |||||
| private String bizPath; | |||||
| private String uploadType; | |||||
| private String customBucket; | |||||
| public FileUploadDTO(){ | |||||
| } | |||||
| /** | |||||
| * 简单上传 构造器1 | |||||
| * @param file | |||||
| * @param bizPath | |||||
| * @param uploadType | |||||
| */ | |||||
| public FileUploadDTO(MultipartFile file,String bizPath,String uploadType){ | |||||
| this.file = file; | |||||
| this.bizPath = bizPath; | |||||
| this.uploadType = uploadType; | |||||
| } | |||||
| /** | |||||
| * 申明桶 文件上传 构造器2 | |||||
| * @param file | |||||
| * @param bizPath | |||||
| * @param uploadType | |||||
| * @param customBucket | |||||
| */ | |||||
| public FileUploadDTO(MultipartFile file,String bizPath,String uploadType,String customBucket){ | |||||
| this.file = file; | |||||
| this.bizPath = bizPath; | |||||
| this.uploadType = uploadType; | |||||
| this.customBucket = customBucket; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,80 @@ | |||||
| package org.jeecg.common.api.dto; | |||||
| import lombok.Data; | |||||
| import org.jeecg.common.aspect.annotation.Dict; | |||||
| import org.jeecg.common.system.vo.LoginUser; | |||||
| import java.io.Serializable; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * 日志对象 | |||||
| * cloud api 用到的接口传输对象 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class LogDTO implements Serializable { | |||||
| private static final long serialVersionUID = 8482720462943906924L; | |||||
| /**内容*/ | |||||
| private String logContent; | |||||
| /**日志类型(0:操作日志;1:登录日志;2:定时任务) */ | |||||
| private Integer logType; | |||||
| /**操作类型(1:添加;2:修改;3:删除;) */ | |||||
| private Integer operateType; | |||||
| /**登录用户 */ | |||||
| private LoginUser loginUser; | |||||
| private String id; | |||||
| private String createBy; | |||||
| private Date createTime; | |||||
| private Long costTime; | |||||
| private String ip; | |||||
| /**请求参数 */ | |||||
| private String requestParam; | |||||
| /**请求类型*/ | |||||
| private String requestType; | |||||
| /**请求路径*/ | |||||
| private String requestUrl; | |||||
| /**请求方法 */ | |||||
| private String method; | |||||
| /**操作人用户名称*/ | |||||
| private String username; | |||||
| /**操作人用户账户*/ | |||||
| private String userid; | |||||
| /** | |||||
| * 租户ID | |||||
| */ | |||||
| private Integer tenantId; | |||||
| /** | |||||
| * 客户终端类型 pc:电脑端 app:手机端 h5:移动网页端 | |||||
| */ | |||||
| private String clientType; | |||||
| public LogDTO(){ | |||||
| } | |||||
| public LogDTO(String logContent, Integer logType, Integer operatetype){ | |||||
| this.logContent = logContent; | |||||
| this.logType = logType; | |||||
| this.operateType = operatetype; | |||||
| } | |||||
| public LogDTO(String logContent, Integer logType, Integer operatetype, LoginUser loginUser){ | |||||
| this.logContent = logContent; | |||||
| this.logType = logType; | |||||
| this.operateType = operatetype; | |||||
| this.loginUser = loginUser; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,49 @@ | |||||
| package org.jeecg.common.api.dto; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * online 拦截器权限判断 | |||||
| * cloud api 用到的接口传输对象 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class OnlineAuthDTO implements Serializable { | |||||
| private static final long serialVersionUID = 1771827545416418203L; | |||||
| /** | |||||
| * 用户名 | |||||
| */ | |||||
| private String username; | |||||
| /** | |||||
| * 可能的请求地址 | |||||
| */ | |||||
| private List<String> possibleUrl; | |||||
| /** | |||||
| * online开发的菜单地址 | |||||
| */ | |||||
| private String onlineFormUrl; | |||||
| //update-begin---author:chenrui ---date:20240123 for:[QQYUN-7992]【online】工单申请下的online表单,未配置online表单开发菜单,操作报错无权限------------ | |||||
| /** | |||||
| * online工单的地址 | |||||
| */ | |||||
| private String onlineWorkOrderUrl; | |||||
| //update-end---author:chenrui ---date:20240123 for:[QQYUN-7992]【online】工单申请下的online表单,未配置online表单开发菜单,操作报错无权限------------ | |||||
| public OnlineAuthDTO(){ | |||||
| } | |||||
| public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl){ | |||||
| this.username = username; | |||||
| this.possibleUrl = possibleUrl; | |||||
| this.onlineFormUrl = onlineFormUrl; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,46 @@ | |||||
| package org.jeecg.common.api.dto.message; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 带业务参数的消息 | |||||
| * | |||||
| * @author: taoyan | |||||
| * @date: 2022/8/17 | |||||
| */ | |||||
| @Data | |||||
| public class BusMessageDTO extends MessageDTO implements Serializable { | |||||
| private static final long serialVersionUID = 9104793287983367669L; | |||||
| /** | |||||
| * 业务类型 | |||||
| */ | |||||
| private String busType; | |||||
| /** | |||||
| * 业务id | |||||
| */ | |||||
| private String busId; | |||||
| public BusMessageDTO(){ | |||||
| } | |||||
| /** | |||||
| * 构造 带业务参数的消息 | |||||
| * @param fromUser | |||||
| * @param toUser | |||||
| * @param title | |||||
| * @param msgContent | |||||
| * @param msgCategory | |||||
| * @param busType | |||||
| * @param busId | |||||
| */ | |||||
| public BusMessageDTO(String fromUser, String toUser, String title, String msgContent, String msgCategory, String busType, String busId){ | |||||
| super(fromUser, toUser, title, msgContent, msgCategory); | |||||
| this.busId = busId; | |||||
| this.busType = busType; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,46 @@ | |||||
| package org.jeecg.common.api.dto.message; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 带业务参数的模板消息 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class BusTemplateMessageDTO extends TemplateMessageDTO implements Serializable { | |||||
| private static final long serialVersionUID = -4277810906346929459L; | |||||
| /** | |||||
| * 业务类型 | |||||
| */ | |||||
| private String busType; | |||||
| /** | |||||
| * 业务id | |||||
| */ | |||||
| private String busId; | |||||
| public BusTemplateMessageDTO(){ | |||||
| } | |||||
| /** | |||||
| * 构造 带业务参数的模板消息 | |||||
| * @param fromUser | |||||
| * @param toUser | |||||
| * @param title | |||||
| * @param templateParam | |||||
| * @param templateCode | |||||
| * @param busType | |||||
| * @param busId | |||||
| */ | |||||
| public BusTemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode, String busType, String busId){ | |||||
| super(fromUser, toUser, title, templateParam, templateCode); | |||||
| this.busId = busId; | |||||
| this.busType = busType; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,128 @@ | |||||
| package org.jeecg.common.api.dto.message; | |||||
| import lombok.Data; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import java.io.Serializable; | |||||
| import java.util.*; | |||||
| /** | |||||
| * 普通消息 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class MessageDTO implements Serializable { | |||||
| private static final long serialVersionUID = -5690444483968058442L; | |||||
| /** | |||||
| * 发送人(用户登录账户) | |||||
| */ | |||||
| protected String fromUser; | |||||
| /** | |||||
| * 发送给(用户登录账户) | |||||
| */ | |||||
| protected String toUser; | |||||
| /** | |||||
| * 发送给所有人 | |||||
| */ | |||||
| protected Boolean toAll; | |||||
| /** | |||||
| * 消息主题 | |||||
| */ | |||||
| protected String title; | |||||
| /** | |||||
| * 消息内容 | |||||
| */ | |||||
| protected String content; | |||||
| /** | |||||
| * 消息类型 1:消息 2:系统消息 | |||||
| */ | |||||
| protected String category; | |||||
| /** | |||||
| * 消息类型:org.jeecg.common.constant.enums.MessageTypeEnum | |||||
| * XT("system", "系统消息") | |||||
| * YJ("email", "邮件消息") | |||||
| * DD("dingtalk", "钉钉消息") | |||||
| * QYWX("wechat_enterprise", "企业微信") | |||||
| */ | |||||
| protected String type; | |||||
| //---【推送模板相关参数】------------------------------------------------------------- | |||||
| /** | |||||
| * 是否发送Markdown格式的消息 | |||||
| */ | |||||
| protected boolean isMarkdown; | |||||
| /** | |||||
| * 模板消息对应的模板编码 | |||||
| */ | |||||
| protected String templateCode; | |||||
| /** | |||||
| * 解析模板内容 对应的数据 | |||||
| */ | |||||
| protected Map<String, Object> data; | |||||
| //---【推送模板相关参数】------------------------------------------------------------- | |||||
| //---【邮件相关参数】------------------------------------------------------------- | |||||
| /** | |||||
| * 邮件抄送人 | |||||
| */ | |||||
| private String copyToUser; | |||||
| /** | |||||
| * 邮件推送地址 | |||||
| */ | |||||
| protected Set<String> toEmailList; | |||||
| /** | |||||
| * 邮件抄送地址 | |||||
| */ | |||||
| protected Set<String> ccEmailList; | |||||
| /** | |||||
| * 是否为定时任务推送email | |||||
| */ | |||||
| private Boolean isTimeJob = false; | |||||
| //---【邮件相关参数】------------------------------------------------------------- | |||||
| public MessageDTO(){ | |||||
| } | |||||
| /** | |||||
| * 构造器1 系统消息 | |||||
| */ | |||||
| public MessageDTO(String fromUser,String toUser,String title, String content){ | |||||
| this.fromUser = fromUser; | |||||
| this.toUser = toUser; | |||||
| this.title = title; | |||||
| this.content = content; | |||||
| //默认 都是2系统消息 | |||||
| this.category = CommonConstant.MSG_CATEGORY_2; | |||||
| } | |||||
| /** | |||||
| * 构造器2 支持设置category 1:消息 2:系统消息 | |||||
| */ | |||||
| public MessageDTO(String fromUser,String toUser,String title, String content, String category){ | |||||
| this.fromUser = fromUser; | |||||
| this.toUser = toUser; | |||||
| this.title = title; | |||||
| this.content = content; | |||||
| this.category = category; | |||||
| } | |||||
| public boolean isMarkdown() { | |||||
| return this.isMarkdown; | |||||
| } | |||||
| public void setIsMarkdown(boolean isMarkdown) { | |||||
| this.isMarkdown = isMarkdown; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,38 @@ | |||||
| package org.jeecg.common.api.dto.message; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 消息模板dto | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class TemplateDTO implements Serializable { | |||||
| private static final long serialVersionUID = 5848247133907528650L; | |||||
| /** | |||||
| * 模板编码 | |||||
| */ | |||||
| protected String templateCode; | |||||
| /** | |||||
| * 模板参数 | |||||
| */ | |||||
| protected Map<String, String> templateParam; | |||||
| /** | |||||
| * 构造器 通过设置模板参数和模板编码 作为参数获取消息内容 | |||||
| */ | |||||
| public TemplateDTO(String templateCode, Map<String, String> templateParam){ | |||||
| this.templateCode = templateCode; | |||||
| this.templateParam = templateParam; | |||||
| } | |||||
| public TemplateDTO(){ | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,49 @@ | |||||
| package org.jeecg.common.api.dto.message; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 模板消息 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class TemplateMessageDTO extends TemplateDTO implements Serializable { | |||||
| private static final long serialVersionUID = 411137565170647585L; | |||||
| /** | |||||
| * 发送人(用户登录账户) | |||||
| */ | |||||
| protected String fromUser; | |||||
| /** | |||||
| * 发送给(用户登录账户) | |||||
| */ | |||||
| protected String toUser; | |||||
| /** | |||||
| * 消息主题 | |||||
| */ | |||||
| protected String title; | |||||
| public TemplateMessageDTO(){ | |||||
| } | |||||
| /** | |||||
| * 构造器1 发模板消息用 | |||||
| */ | |||||
| public TemplateMessageDTO(String fromUser, String toUser,String title, Map<String, String> templateParam, String templateCode){ | |||||
| super(templateCode, templateParam); | |||||
| this.fromUser = fromUser; | |||||
| this.toUser = toUser; | |||||
| this.title = title; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,176 @@ | |||||
| package org.jeecg.common.api.vo; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | |||||
| import io.swagger.v3.oas.annotations.media.Schema; | |||||
| import lombok.Data; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * 接口返回数据格式 | |||||
| * @author scott | |||||
| * @email jeecgos@163.com | |||||
| * @date 2019年1月19日 | |||||
| */ | |||||
| @Data | |||||
| @Schema(description="接口返回对象") | |||||
| public class Result<T> implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 成功标志 | |||||
| */ | |||||
| @Schema(description = "成功标志") | |||||
| private boolean success = true; | |||||
| /** | |||||
| * 返回处理消息 | |||||
| */ | |||||
| @Schema(description = "返回处理消息") | |||||
| private String message = ""; | |||||
| /** | |||||
| * 返回代码 | |||||
| */ | |||||
| @Schema(description = "返回代码") | |||||
| private Integer code = 0; | |||||
| /** | |||||
| * 返回数据对象 data | |||||
| */ | |||||
| @Schema(description = "返回数据对象") | |||||
| private T result; | |||||
| /** | |||||
| * 时间戳 | |||||
| */ | |||||
| @Schema(description = "时间戳") | |||||
| private long timestamp = System.currentTimeMillis(); | |||||
| public Result() { | |||||
| } | |||||
| /** | |||||
| * 兼容VUE3版token失效不跳转登录页面 | |||||
| * @param code | |||||
| * @param message | |||||
| */ | |||||
| public Result(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Result<T> success(String message) { | |||||
| this.message = message; | |||||
| this.code = CommonConstant.SC_OK_200; | |||||
| this.success = true; | |||||
| return this; | |||||
| } | |||||
| public static<T> Result<T> ok() { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> ok(String msg) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| //Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D | |||||
| r.setResult((T) msg); | |||||
| r.setMessage(msg); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> ok(T data) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| r.setResult(data); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> OK() { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| return r; | |||||
| } | |||||
| /** | |||||
| * 此方法是为了兼容升级所创建 | |||||
| * | |||||
| * @param msg | |||||
| * @param <T> | |||||
| * @return | |||||
| */ | |||||
| public static<T> Result<T> OK(String msg) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| r.setMessage(msg); | |||||
| //Result OK(String msg)方法会造成兼容性问题 issues/I4IP3D | |||||
| r.setResult((T) msg); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> OK(T data) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| r.setResult(data); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> OK(String msg, T data) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(true); | |||||
| r.setCode(CommonConstant.SC_OK_200); | |||||
| r.setMessage(msg); | |||||
| r.setResult(data); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> error(String msg, T data) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setSuccess(false); | |||||
| r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500); | |||||
| r.setMessage(msg); | |||||
| r.setResult(data); | |||||
| return r; | |||||
| } | |||||
| public static<T> Result<T> error(String msg) { | |||||
| return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg); | |||||
| } | |||||
| public static<T> Result<T> error(int code, String msg) { | |||||
| Result<T> r = new Result<T>(); | |||||
| r.setCode(code); | |||||
| r.setMessage(msg); | |||||
| r.setSuccess(false); | |||||
| return r; | |||||
| } | |||||
| public Result<T> error500(String message) { | |||||
| this.message = message; | |||||
| this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500; | |||||
| this.success = false; | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * 无权限访问返回结果 | |||||
| */ | |||||
| public static<T> Result<T> noauth(String msg) { | |||||
| return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg); | |||||
| } | |||||
| @JsonIgnore | |||||
| private String onlTable; | |||||
| } | |||||
| @ -0,0 +1,259 @@ | |||||
| package org.jeecg.common.aspect; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.alibaba.fastjson.serializer.PropertyFilter; | |||||
| import org.apache.shiro.SecurityUtils; | |||||
| import org.aspectj.lang.JoinPoint; | |||||
| import org.aspectj.lang.ProceedingJoinPoint; | |||||
| import org.aspectj.lang.annotation.Around; | |||||
| import org.aspectj.lang.annotation.Aspect; | |||||
| import org.aspectj.lang.annotation.Pointcut; | |||||
| import org.aspectj.lang.reflect.MethodSignature; | |||||
| import org.jeecg.common.api.dto.LogDTO; | |||||
| import org.jeecg.common.api.vo.Result; | |||||
| import org.jeecg.common.aspect.annotation.AutoLog; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.constant.enums.ModuleType; | |||||
| import org.jeecg.common.constant.enums.OperateTypeEnum; | |||||
| import org.jeecg.modules.base.service.BaseCommonService; | |||||
| import org.jeecg.common.system.vo.LoginUser; | |||||
| import org.jeecg.common.util.IpUtils; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.core.LocalVariableTableParameterNameDiscoverer; | |||||
| import org.springframework.stereotype.Component; | |||||
| import org.springframework.validation.BindingResult; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.annotation.Resource; | |||||
| import javax.servlet.ServletRequest; | |||||
| import javax.servlet.ServletResponse; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * 系统日志,切面处理类 | |||||
| * | |||||
| * @Author scott | |||||
| * @email jeecgos@163.com | |||||
| * @Date 2018年1月14日 | |||||
| */ | |||||
| @Aspect | |||||
| @Component | |||||
| public class AutoLogAspect { | |||||
| @Resource | |||||
| private BaseCommonService baseCommonService; | |||||
| @Pointcut("@annotation(org.jeecg.common.aspect.annotation.AutoLog)") | |||||
| public void logPointCut() { | |||||
| } | |||||
| @Around("logPointCut()") | |||||
| public Object around(ProceedingJoinPoint point) throws Throwable { | |||||
| long beginTime = System.currentTimeMillis(); | |||||
| //执行方法 | |||||
| Object result = point.proceed(); | |||||
| //执行时长(毫秒) | |||||
| long time = System.currentTimeMillis() - beginTime; | |||||
| //保存日志 | |||||
| saveSysLog(point, time, result); | |||||
| return result; | |||||
| } | |||||
| private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) { | |||||
| MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | |||||
| Method method = signature.getMethod(); | |||||
| LogDTO dto = new LogDTO(); | |||||
| AutoLog syslog = method.getAnnotation(AutoLog.class); | |||||
| if(syslog != null){ | |||||
| //update-begin-author:taoyan date: | |||||
| String content = syslog.value(); | |||||
| if(syslog.module()== ModuleType.ONLINE){ | |||||
| content = getOnlineLogContent(obj, content); | |||||
| } | |||||
| //注解上的描述,操作日志内容 | |||||
| dto.setLogType(syslog.logType()); | |||||
| dto.setLogContent(content); | |||||
| } | |||||
| //请求的方法名 | |||||
| String className = joinPoint.getTarget().getClass().getName(); | |||||
| String methodName = signature.getName(); | |||||
| dto.setMethod(className + "." + methodName + "()"); | |||||
| //设置操作类型 | |||||
| if (CommonConstant.LOG_TYPE_2 == dto.getLogType()) { | |||||
| dto.setOperateType(getOperateType(methodName, syslog.operateType())); | |||||
| } | |||||
| //获取request | |||||
| HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); | |||||
| //请求的参数 | |||||
| dto.setRequestParam(getReqestParams(request,joinPoint)); | |||||
| //设置IP地址 | |||||
| dto.setIp(IpUtils.getIpAddr(request)); | |||||
| //获取登录用户信息 | |||||
| LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | |||||
| if(sysUser!=null){ | |||||
| dto.setUserid(sysUser.getUsername()); | |||||
| dto.setUsername(sysUser.getRealname()); | |||||
| } | |||||
| //耗时 | |||||
| dto.setCostTime(time); | |||||
| dto.setCreateTime(new Date()); | |||||
| //保存系统日志 | |||||
| baseCommonService.addLog(dto); | |||||
| } | |||||
| /** | |||||
| * 获取操作类型 | |||||
| */ | |||||
| private int getOperateType(String methodName,int operateType) { | |||||
| if (operateType > 0) { | |||||
| return operateType; | |||||
| } | |||||
| //update-begin---author:wangshuai ---date:20220331 for:阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------ | |||||
| return OperateTypeEnum.getTypeByMethodName(methodName); | |||||
| //update-end---author:wangshuai ---date:20220331 for:阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------ | |||||
| } | |||||
| /** | |||||
| * @Description: 获取请求参数 | |||||
| * @author: scott | |||||
| * @date: 2020/4/16 0:10 | |||||
| * @param request: request | |||||
| * @param joinPoint: joinPoint | |||||
| * @Return: java.lang.String | |||||
| */ | |||||
| private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) { | |||||
| String httpMethod = request.getMethod(); | |||||
| String params = ""; | |||||
| if (CommonConstant.HTTP_POST.equals(httpMethod) || CommonConstant.HTTP_PUT.equals(httpMethod) || CommonConstant.HTTP_PATCH.equals(httpMethod)) { | |||||
| Object[] paramsArray = joinPoint.getArgs(); | |||||
| // java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) | |||||
| // https://my.oschina.net/mengzhang6/blog/2395893 | |||||
| Object[] arguments = new Object[paramsArray.length]; | |||||
| for (int i = 0; i < paramsArray.length; i++) { | |||||
| if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile) { | |||||
| //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) | |||||
| //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response | |||||
| continue; | |||||
| } | |||||
| arguments[i] = paramsArray[i]; | |||||
| } | |||||
| //update-begin-author:taoyan date:20200724 for:日志数据太长的直接过滤掉 | |||||
| PropertyFilter profilter = new PropertyFilter() { | |||||
| @Override | |||||
| public boolean apply(Object o, String name, Object value) { | |||||
| int length = 500; | |||||
| if(value!=null && value.toString().length()>length){ | |||||
| return false; | |||||
| } | |||||
| if(value instanceof MultipartFile){ | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| }; | |||||
| params = JSONObject.toJSONString(arguments, profilter); | |||||
| //update-end-author:taoyan date:20200724 for:日志数据太长的直接过滤掉 | |||||
| } else { | |||||
| MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | |||||
| Method method = signature.getMethod(); | |||||
| // 请求的方法参数值 | |||||
| Object[] args = joinPoint.getArgs(); | |||||
| // 请求的方法参数名称 | |||||
| LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); | |||||
| String[] paramNames = u.getParameterNames(method); | |||||
| if (args != null && paramNames != null) { | |||||
| for (int i = 0; i < args.length; i++) { | |||||
| params += " " + paramNames[i] + ": " + args[i]; | |||||
| } | |||||
| } | |||||
| } | |||||
| return params; | |||||
| } | |||||
| /** | |||||
| * online日志内容拼接 | |||||
| * @param obj | |||||
| * @param content | |||||
| * @return | |||||
| */ | |||||
| private String getOnlineLogContent(Object obj, String content){ | |||||
| if (Result.class.isInstance(obj)){ | |||||
| Result res = (Result)obj; | |||||
| String msg = res.getMessage(); | |||||
| String tableName = res.getOnlTable(); | |||||
| if(oConvertUtils.isNotEmpty(tableName)){ | |||||
| content+=",表名:"+tableName; | |||||
| } | |||||
| if(res.isSuccess()){ | |||||
| content+= ","+(oConvertUtils.isEmpty(msg)?"操作成功":msg); | |||||
| }else{ | |||||
| content+= ","+(oConvertUtils.isEmpty(msg)?"操作失败":msg); | |||||
| } | |||||
| } | |||||
| return content; | |||||
| } | |||||
| /* private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) { | |||||
| MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | |||||
| Method method = signature.getMethod(); | |||||
| SysLog sysLog = new SysLog(); | |||||
| AutoLog syslog = method.getAnnotation(AutoLog.class); | |||||
| if(syslog != null){ | |||||
| //update-begin-author:taoyan date: | |||||
| String content = syslog.value(); | |||||
| if(syslog.module()== ModuleType.ONLINE){ | |||||
| content = getOnlineLogContent(obj, content); | |||||
| } | |||||
| //注解上的描述,操作日志内容 | |||||
| sysLog.setLogContent(content); | |||||
| sysLog.setLogType(syslog.logType()); | |||||
| } | |||||
| //请求的方法名 | |||||
| String className = joinPoint.getTarget().getClass().getName(); | |||||
| String methodName = signature.getName(); | |||||
| sysLog.setMethod(className + "." + methodName + "()"); | |||||
| //设置操作类型 | |||||
| if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) { | |||||
| sysLog.setOperateType(getOperateType(methodName, syslog.operateType())); | |||||
| } | |||||
| //获取request | |||||
| HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); | |||||
| //请求的参数 | |||||
| sysLog.setRequestParam(getReqestParams(request,joinPoint)); | |||||
| //设置IP地址 | |||||
| sysLog.setIp(IPUtils.getIpAddr(request)); | |||||
| //获取登录用户信息 | |||||
| LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal(); | |||||
| if(sysUser!=null){ | |||||
| sysLog.setUserid(sysUser.getUsername()); | |||||
| sysLog.setUsername(sysUser.getRealname()); | |||||
| } | |||||
| //耗时 | |||||
| sysLog.setCostTime(time); | |||||
| sysLog.setCreateTime(new Date()); | |||||
| //保存系统日志 | |||||
| sysLogService.save(sysLog); | |||||
| }*/ | |||||
| } | |||||
| @ -0,0 +1,457 @@ | |||||
| package org.jeecg.common.aspect; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.alibaba.fastjson.parser.Feature; | |||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | |||||
| import com.fasterxml.jackson.core.JsonProcessingException; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.aspectj.lang.ProceedingJoinPoint; | |||||
| import org.aspectj.lang.annotation.Around; | |||||
| import org.aspectj.lang.annotation.Aspect; | |||||
| import org.aspectj.lang.annotation.Pointcut; | |||||
| import org.jeecg.common.api.CommonAPI; | |||||
| import org.jeecg.common.api.vo.Result; | |||||
| import org.jeecg.common.aspect.annotation.Dict; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.system.vo.DictModel; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Lazy; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | |||||
| import org.springframework.stereotype.Component; | |||||
| import org.springframework.util.StringUtils; | |||||
| import java.lang.reflect.Field; | |||||
| import java.util.*; | |||||
| import java.util.concurrent.TimeUnit; | |||||
| import java.util.stream.Collectors; | |||||
| /** | |||||
| * @Description: 字典aop类 | |||||
| * @Author: dangzhenghui | |||||
| * @Date: 2019-3-17 21:50 | |||||
| * @Version: 1.0 | |||||
| */ | |||||
| @Aspect | |||||
| @Component | |||||
| @Slf4j | |||||
| public class DictAspect { | |||||
| @Lazy | |||||
| @Autowired | |||||
| private CommonAPI commonApi; | |||||
| @Autowired | |||||
| public RedisTemplate redisTemplate; | |||||
| @Autowired | |||||
| private ObjectMapper objectMapper; | |||||
| private static final String JAVA_UTIL_DATE = "java.util.Date"; | |||||
| /** | |||||
| * 定义切点Pointcut | |||||
| */ | |||||
| @Pointcut("(@within(org.springframework.web.bind.annotation.RestController) || " + | |||||
| "@within(org.springframework.stereotype.Controller) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)) " + | |||||
| "&& execution(public org.jeecg.common.api.vo.Result org.jeecg..*.*(..))") | |||||
| public void excudeService() { | |||||
| } | |||||
| @Around("excudeService()") | |||||
| public Object doAround(ProceedingJoinPoint pjp) throws Throwable { | |||||
| long time1=System.currentTimeMillis(); | |||||
| Object result = pjp.proceed(); | |||||
| long time2=System.currentTimeMillis(); | |||||
| log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms"); | |||||
| long start=System.currentTimeMillis(); | |||||
| result=this.parseDictText(result); | |||||
| long end=System.currentTimeMillis(); | |||||
| log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms"); | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入 | |||||
| * 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ,table字典 code table text配合使用与原来jeecg的用法相同 | |||||
| * 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端 | |||||
| * 例输入当前返回值的就会多出一个sex_dictText字段 | |||||
| * { | |||||
| * sex:1, | |||||
| * sex_dictText:"男" | |||||
| * } | |||||
| * 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了 | |||||
| * customRender:function (text) { | |||||
| * if(text==1){ | |||||
| * return "男"; | |||||
| * }else if(text==2){ | |||||
| * return "女"; | |||||
| * }else{ | |||||
| * return text; | |||||
| * } | |||||
| * } | |||||
| * 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用 | |||||
| * @param result | |||||
| */ | |||||
| private Object parseDictText(Object result) { | |||||
| //if (result instanceof Result) { | |||||
| if (true) { | |||||
| if (((Result) result).getResult() instanceof IPage) { | |||||
| List<JSONObject> items = new ArrayList<>(); | |||||
| //step.1 筛选出加了 Dict 注解的字段列表 | |||||
| List<Field> dictFieldList = new ArrayList<>(); | |||||
| // 字典数据列表, key = 字典code,value=数据列表 | |||||
| Map<String, List<String>> dataListMap = new HashMap<>(5); | |||||
| //取出结果集 | |||||
| List<Object> records=((IPage) ((Result) result).getResult()).getRecords(); | |||||
| //update-begin--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回----- | |||||
| Boolean hasDict= checkHasDict(records); | |||||
| if(!hasDict){ | |||||
| return result; | |||||
| } | |||||
| log.debug(" __ 进入字典翻译切面 DictAspect —— " ); | |||||
| //update-end--Author:zyf -- Date:20220606 ----for:【VUEN-1230】 判断是否含有字典注解,没有注解返回----- | |||||
| for (Object record : records) { | |||||
| String json="{}"; | |||||
| try { | |||||
| //update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错----- | |||||
| //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat | |||||
| json = objectMapper.writeValueAsString(record); | |||||
| //update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错----- | |||||
| } catch (JsonProcessingException e) { | |||||
| log.error("json解析失败"+e.getMessage(),e); | |||||
| } | |||||
| //update-begin--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 ----- | |||||
| JSONObject item = JSONObject.parseObject(json, Feature.OrderedField); | |||||
| //update-end--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 ----- | |||||
| //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ | |||||
| //for (Field field : record.getClass().getDeclaredFields()) { | |||||
| // 遍历所有字段,把字典Code取出来,放到 map 里 | |||||
| for (Field field : oConvertUtils.getAllFields(record)) { | |||||
| String value = item.getString(field.getName()); | |||||
| if (oConvertUtils.isEmpty(value)) { | |||||
| continue; | |||||
| } | |||||
| //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ | |||||
| if (field.getAnnotation(Dict.class) != null) { | |||||
| if (!dictFieldList.contains(field)) { | |||||
| dictFieldList.add(field); | |||||
| } | |||||
| String code = field.getAnnotation(Dict.class).dicCode(); | |||||
| String text = field.getAnnotation(Dict.class).dicText(); | |||||
| String table = field.getAnnotation(Dict.class).dictTable(); | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| String dataSource = field.getAnnotation(Dict.class).ds(); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| List<String> dataList; | |||||
| String dictCode = code; | |||||
| if (!StringUtils.isEmpty(table)) { | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| } | |||||
| dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>()); | |||||
| this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(","))); | |||||
| } | |||||
| //date类型默认转换string格式化日期 | |||||
| //update-begin--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错----- | |||||
| //if (JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){ | |||||
| //SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |||||
| // item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName())))); | |||||
| //} | |||||
| //update-end--Author:zyf -- Date:20220531 ----for:【issues/#3629】 DictAspect Jackson序列化报错----- | |||||
| } | |||||
| items.add(item); | |||||
| } | |||||
| //step.2 调用翻译方法,一次性翻译 | |||||
| Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap); | |||||
| //step.3 将翻译结果填充到返回结果里 | |||||
| for (JSONObject record : items) { | |||||
| for (Field field : dictFieldList) { | |||||
| String code = field.getAnnotation(Dict.class).dicCode(); | |||||
| String text = field.getAnnotation(Dict.class).dicText(); | |||||
| String table = field.getAnnotation(Dict.class).dictTable(); | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| // 自定义的字典表数据源 | |||||
| String dataSource = field.getAnnotation(Dict.class).ds(); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| String fieldDictCode = code; | |||||
| if (!StringUtils.isEmpty(table)) { | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| } | |||||
| String value = record.getString(field.getName()); | |||||
| if (oConvertUtils.isNotEmpty(value)) { | |||||
| List<DictModel> dictModels = translText.get(fieldDictCode); | |||||
| if(dictModels==null || dictModels.size()==0){ | |||||
| continue; | |||||
| } | |||||
| String textValue = this.translDictText(dictModels, value); | |||||
| log.debug(" 字典Val : " + textValue); | |||||
| log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue); | |||||
| // TODO-sun 测试输出,待删 | |||||
| log.debug(" ---- dictCode: " + fieldDictCode); | |||||
| log.debug(" ---- value: " + value); | |||||
| log.debug(" ----- text: " + textValue); | |||||
| log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels)); | |||||
| record.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); | |||||
| } | |||||
| } | |||||
| } | |||||
| ((IPage) ((Result) result).getResult()).setRecords(items); | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * list 去重添加 | |||||
| */ | |||||
| private void listAddAllDeduplicate(List<String> dataList, List<String> addList) { | |||||
| // 筛选出dataList中没有的数据 | |||||
| List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList()); | |||||
| dataList.addAll(filterList); | |||||
| } | |||||
| /** | |||||
| * 一次性把所有的字典都翻译了 | |||||
| * 1. 所有的普通数据字典的所有数据只执行一次SQL | |||||
| * 2. 表字典相同的所有数据只执行一次SQL | |||||
| * @param dataListMap | |||||
| * @return | |||||
| */ | |||||
| private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) { | |||||
| // 翻译后的字典文本,key=dictCode | |||||
| Map<String, List<DictModel>> translText = new HashMap<>(5); | |||||
| // 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询) | |||||
| List<String> needTranslData = new ArrayList<>(); | |||||
| //step.1 先通过redis中获取缓存字典数据 | |||||
| for (String dictCode : dataListMap.keySet()) { | |||||
| List<String> dataList = dataListMap.get(dictCode); | |||||
| if (dataList.size() == 0) { | |||||
| continue; | |||||
| } | |||||
| // 表字典需要翻译的数据 | |||||
| List<String> needTranslDataTable = new ArrayList<>(); | |||||
| for (String s : dataList) { | |||||
| String data = s.trim(); | |||||
| if (data.length() == 0) { | |||||
| continue; //跳过循环 | |||||
| } | |||||
| if (dictCode.contains(",")) { | |||||
| String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data); | |||||
| if (redisTemplate.hasKey(keyString)) { | |||||
| try { | |||||
| String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); | |||||
| List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); | |||||
| list.add(new DictModel(data, text)); | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage()); | |||||
| } | |||||
| } else if (!needTranslDataTable.contains(data)) { | |||||
| // 去重添加 | |||||
| needTranslDataTable.add(data); | |||||
| } | |||||
| } else { | |||||
| String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data); | |||||
| if (redisTemplate.hasKey(keyString)) { | |||||
| try { | |||||
| String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); | |||||
| List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); | |||||
| list.add(new DictModel(data, text)); | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage()); | |||||
| } | |||||
| } else if (!needTranslData.contains(data)) { | |||||
| // 去重添加 | |||||
| needTranslData.add(data); | |||||
| } | |||||
| } | |||||
| } | |||||
| //step.2 调用数据库翻译表字典 | |||||
| if (needTranslDataTable.size() > 0) { | |||||
| String[] arr = dictCode.split(","); | |||||
| String table = arr[0], text = arr[1], code = arr[2]; | |||||
| String values = String.join(",", needTranslDataTable); | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| // 自定义的数据源 | |||||
| String dataSource = null; | |||||
| if (arr.length > 3) { | |||||
| dataSource = arr[3]; | |||||
| } | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| log.debug("translateDictFromTableByKeys.dictCode:" + dictCode); | |||||
| log.debug("translateDictFromTableByKeys.values:" + values); | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| //update-begin---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串--- | |||||
| if(null == dataSource){ | |||||
| dataSource = ""; | |||||
| } | |||||
| //update-end---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串--- | |||||
| List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource); | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| log.debug("translateDictFromTableByKeys.result:" + texts); | |||||
| List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); | |||||
| list.addAll(texts); | |||||
| // 做 redis 缓存 | |||||
| for (DictModel dict : texts) { | |||||
| String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue()); | |||||
| try { | |||||
| // update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061 | |||||
| // 保留5分钟 | |||||
| redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS); | |||||
| // update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061 | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage(), e); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| //step.3 调用数据库进行翻译普通字典 | |||||
| if (needTranslData.size() > 0) { | |||||
| List<String> dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{})); | |||||
| // 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典 | |||||
| List<String> filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList()); | |||||
| String dictCodes = String.join(",", filterDictCodes); | |||||
| String values = String.join(",", needTranslData); | |||||
| log.debug("translateManyDict.dictCodes:" + dictCodes); | |||||
| log.debug("translateManyDict.values:" + values); | |||||
| Map<String, List<DictModel>> manyDict = commonApi.translateManyDict(dictCodes, values); | |||||
| log.debug("translateManyDict.result:" + manyDict); | |||||
| for (String dictCode : manyDict.keySet()) { | |||||
| List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); | |||||
| List<DictModel> newList = manyDict.get(dictCode); | |||||
| list.addAll(newList); | |||||
| // 做 redis 缓存 | |||||
| for (DictModel dict : newList) { | |||||
| String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue()); | |||||
| try { | |||||
| redisTemplate.opsForValue().set(redisKey, dict.getText()); | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage(), e); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return translText; | |||||
| } | |||||
| /** | |||||
| * 字典值替换文本 | |||||
| * | |||||
| * @param dictModels | |||||
| * @param values | |||||
| * @return | |||||
| */ | |||||
| private String translDictText(List<DictModel> dictModels, String values) { | |||||
| List<String> result = new ArrayList<>(); | |||||
| // 允许多个逗号分隔,允许传数组对象 | |||||
| String[] splitVal = values.split(","); | |||||
| for (String val : splitVal) { | |||||
| String dictText = val; | |||||
| for (DictModel dict : dictModels) { | |||||
| if (val.equals(dict.getValue())) { | |||||
| dictText = dict.getText(); | |||||
| break; | |||||
| } | |||||
| } | |||||
| result.add(dictText); | |||||
| } | |||||
| return String.join(",", result); | |||||
| } | |||||
| /** | |||||
| * 翻译字典文本 | |||||
| * @param code | |||||
| * @param text | |||||
| * @param table | |||||
| * @param key | |||||
| * @return | |||||
| */ | |||||
| @Deprecated | |||||
| private String translateDictValue(String code, String text, String table, String key) { | |||||
| if(oConvertUtils.isEmpty(key)) { | |||||
| return null; | |||||
| } | |||||
| StringBuffer textValue=new StringBuffer(); | |||||
| String[] keys = key.split(","); | |||||
| for (String k : keys) { | |||||
| String tmpValue = null; | |||||
| log.debug(" 字典 key : "+ k); | |||||
| if (k.trim().length() == 0) { | |||||
| continue; //跳过循环 | |||||
| } | |||||
| //update-begin--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题----- | |||||
| if (!StringUtils.isEmpty(table)){ | |||||
| log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code); | |||||
| String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim()); | |||||
| if (redisTemplate.hasKey(keyString)){ | |||||
| try { | |||||
| tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage()); | |||||
| } | |||||
| }else { | |||||
| tmpValue= commonApi.translateDictFromTable(table,text,code,k.trim()); | |||||
| } | |||||
| }else { | |||||
| String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim()); | |||||
| if (redisTemplate.hasKey(keyString)){ | |||||
| try { | |||||
| tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); | |||||
| } catch (Exception e) { | |||||
| log.warn(e.getMessage()); | |||||
| } | |||||
| }else { | |||||
| tmpValue = commonApi.translateDict(code, k.trim()); | |||||
| } | |||||
| } | |||||
| //update-end--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题----- | |||||
| if (tmpValue != null) { | |||||
| if (!"".equals(textValue.toString())) { | |||||
| textValue.append(","); | |||||
| } | |||||
| textValue.append(tmpValue); | |||||
| } | |||||
| } | |||||
| return textValue.toString(); | |||||
| } | |||||
| /** | |||||
| * 检测返回结果集中是否包含Dict注解 | |||||
| * @param records | |||||
| * @return | |||||
| */ | |||||
| private Boolean checkHasDict(List<Object> records){ | |||||
| if(oConvertUtils.isNotEmpty(records) && records.size()>0){ | |||||
| for (Field field : oConvertUtils.getAllFields(records.get(0))) { | |||||
| if (oConvertUtils.isNotEmpty(field.getAnnotation(Dict.class))) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,139 @@ | |||||
| package org.jeecg.common.aspect; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.aspectj.lang.ProceedingJoinPoint; | |||||
| import org.aspectj.lang.annotation.Around; | |||||
| import org.aspectj.lang.annotation.Aspect; | |||||
| import org.aspectj.lang.annotation.Pointcut; | |||||
| import org.aspectj.lang.reflect.MethodSignature; | |||||
| import org.jeecg.common.api.CommonAPI; | |||||
| import org.jeecg.common.aspect.annotation.PermissionData; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.constant.SymbolConstant; | |||||
| import org.jeecg.common.system.query.QueryRuleEnum; | |||||
| import org.jeecg.common.system.util.JeecgDataAutorUtils; | |||||
| import org.jeecg.common.system.util.JwtUtil; | |||||
| import org.jeecg.common.system.vo.SysPermissionDataRuleModel; | |||||
| import org.jeecg.common.system.vo.SysUserCacheInfo; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Lazy; | |||||
| import org.springframework.stereotype.Component; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 数据权限切面处理类 | |||||
| * 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息 | |||||
| * @Date 2019年4月10日 | |||||
| * @Version: 1.0 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Aspect | |||||
| @Component | |||||
| @Slf4j | |||||
| public class PermissionDataAspect { | |||||
| @Lazy | |||||
| @Autowired | |||||
| private CommonAPI commonApi; | |||||
| private static final String SPOT_DO = ".do"; | |||||
| @Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)") | |||||
| public void pointCut() { | |||||
| } | |||||
| @Around("pointCut()") | |||||
| public Object arround(ProceedingJoinPoint point) throws Throwable{ | |||||
| HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); | |||||
| MethodSignature signature = (MethodSignature) point.getSignature(); | |||||
| Method method = signature.getMethod(); | |||||
| PermissionData pd = method.getAnnotation(PermissionData.class); | |||||
| String component = pd.pageComponent(); | |||||
| String requestMethod = request.getMethod(); | |||||
| String requestPath = request.getRequestURI().substring(request.getContextPath().length()); | |||||
| requestPath = filterUrl(requestPath); | |||||
| //update-begin-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效 | |||||
| //先判断是否online报表请求 | |||||
| if(requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl())>=0 || requestPath.indexOf(UrlMatchEnum.CGREPORT_ONLY_DATA.getMatchUrl())>=0){ | |||||
| // 获取地址栏参数 | |||||
| String urlParamString = request.getParameter(CommonConstant.ONL_REP_URL_PARAM_STR); | |||||
| if(oConvertUtils.isNotEmpty(urlParamString)){ | |||||
| requestPath+="?"+urlParamString; | |||||
| } | |||||
| } | |||||
| //update-end-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效 | |||||
| log.debug("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod); | |||||
| String username = JwtUtil.getUserNameByToken(request); | |||||
| //查询数据权限信息 | |||||
| //TODO 微服务情况下也得支持缓存机制 | |||||
| List<SysPermissionDataRuleModel> dataRules = commonApi.queryPermissionDataRule(component, requestPath, username); | |||||
| if(dataRules!=null && dataRules.size()>0) { | |||||
| //临时存储 | |||||
| JeecgDataAutorUtils.installDataSearchConditon(request, dataRules); | |||||
| //TODO 微服务情况下也得支持缓存机制 | |||||
| SysUserCacheInfo userinfo = commonApi.getCacheUser(username); | |||||
| JeecgDataAutorUtils.installUserInfo(request, userinfo); | |||||
| } | |||||
| return point.proceed(); | |||||
| } | |||||
| private String filterUrl(String requestPath){ | |||||
| String url = ""; | |||||
| if(oConvertUtils.isNotEmpty(requestPath)){ | |||||
| url = requestPath.replace("\\", "/"); | |||||
| url = url.replace("//", "/"); | |||||
| if(url.indexOf(SymbolConstant.DOUBLE_SLASH)>=0){ | |||||
| url = filterUrl(url); | |||||
| } | |||||
| /*if(url.startsWith("/")){ | |||||
| url=url.substring(1); | |||||
| }*/ | |||||
| } | |||||
| return url; | |||||
| } | |||||
| /** | |||||
| * 获取请求地址 | |||||
| * @param request | |||||
| * @return | |||||
| */ | |||||
| @Deprecated | |||||
| private String getJgAuthRequsetPath(HttpServletRequest request) { | |||||
| String queryString = request.getQueryString(); | |||||
| String requestPath = request.getRequestURI(); | |||||
| if(oConvertUtils.isNotEmpty(queryString)){ | |||||
| requestPath += "?" + queryString; | |||||
| } | |||||
| // 去掉其他参数(保留一个参数) 例如:loginController.do?login | |||||
| if (requestPath.indexOf(SymbolConstant.AND) > -1) { | |||||
| requestPath = requestPath.substring(0, requestPath.indexOf("&")); | |||||
| } | |||||
| if(requestPath.indexOf(QueryRuleEnum.EQ.getValue())!=-1){ | |||||
| if(requestPath.indexOf(SPOT_DO)!=-1){ | |||||
| requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3); | |||||
| }else{ | |||||
| requestPath = requestPath.substring(0,requestPath.indexOf("?")); | |||||
| } | |||||
| } | |||||
| // 去掉项目路径 | |||||
| requestPath = requestPath.substring(request.getContextPath().length() + 1); | |||||
| return filterUrl(requestPath); | |||||
| } | |||||
| @Deprecated | |||||
| private boolean moHuContain(List<String> list,String key){ | |||||
| for(String str : list){ | |||||
| if(key.contains(str)){ | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,68 @@ | |||||
| package org.jeecg.common.aspect; | |||||
| /** | |||||
| * @Author scott | |||||
| * @Date 2020/1/14 13:36 | |||||
| * @Description: 请求URL与菜单路由URL转换规则(方便于采用菜单路由URL来配置数据权限规则) | |||||
| */ | |||||
| public enum UrlMatchEnum { | |||||
| /**求URL与菜单路由URL转换规则 /online/cgform/api/getData/ */ | |||||
| CGFORM_DATA("/online/cgform/api/getData/", "/online/cgformList/"), | |||||
| /**求URL与菜单路由URL转换规则 /online/cgform/api/exportXls/ */ | |||||
| CGFORM_EXCEL_DATA("/online/cgform/api/exportXls/", "/online/cgformList/"), | |||||
| /**求URL与菜单路由URL转换规则 /online/cgform/api/getTreeData/ */ | |||||
| CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"), | |||||
| /**求URL与菜单路由URL转换规则 /online/cgreport/api/getColumnsAndData/ */ | |||||
| CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"), | |||||
| /** 求URL与菜单路由URL转换规则/online/cgreport/api/getData/ 【vue3报表数据请求地址】 */ | |||||
| CGREPORT_ONLY_DATA("/online/cgreport/api/getData/", "/online/cgreport/"), | |||||
| /**求URL与菜单路由URL转换规则 /online/cgreport/api/exportXls/ */ | |||||
| CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/"), | |||||
| /**求URL与菜单路由URL转换规则 /online/cgreport/api/exportManySheetXls/ */ | |||||
| CGREPORT_EXCEL_DATA2("/online/cgreport/api/exportManySheetXls/", "/online/cgreport/"); | |||||
| UrlMatchEnum(String url, String matchUrl) { | |||||
| this.url = url; | |||||
| this.matchUrl = matchUrl; | |||||
| } | |||||
| /** | |||||
| * Request 请求 URL前缀 | |||||
| */ | |||||
| private String url; | |||||
| /** | |||||
| * 菜单路由 URL前缀 (对应菜单路径) | |||||
| */ | |||||
| private String matchUrl; | |||||
| /** | |||||
| * 根据req url 获取到菜单配置路径(前端页面路由URL) | |||||
| * | |||||
| * @param url | |||||
| * @return | |||||
| */ | |||||
| public static String getMatchResultByUrl(String url) { | |||||
| //获取到枚举 | |||||
| UrlMatchEnum[] values = UrlMatchEnum.values(); | |||||
| //加强for循环进行遍历操作 | |||||
| for (UrlMatchEnum lr : values) { | |||||
| //如果遍历获取的type和参数type一致 | |||||
| if (url.indexOf(lr.url) != -1) { | |||||
| //返回type对象的desc | |||||
| return url.replace(lr.url, lr.matchUrl); | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public String getMatchUrl() { | |||||
| return matchUrl; | |||||
| } | |||||
| // public static void main(String[] args) { | |||||
| // /** | |||||
| // * 比如request真实请求URL: /online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a | |||||
| // * 转换匹配路由URL后(对应配置的菜单路径):/online/cgformList/81fcf7d8922d45069b0d5ba983612d3a | |||||
| // */ | |||||
| // System.out.println(UrlMatchEnum.getMatchResultByUrl("/online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a")); | |||||
| // } | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 通过此注解声明的接口,自动实现字典翻译 | |||||
| * | |||||
| * @Author scott | |||||
| * @email jeecgos@163.com | |||||
| * @Date 2022年01月05日 | |||||
| */ | |||||
| @Target(ElementType.METHOD) | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Documented | |||||
| public @interface AutoDict { | |||||
| /** | |||||
| * 暂时无用 | |||||
| * @return | |||||
| */ | |||||
| String value() default ""; | |||||
| } | |||||
| @ -0,0 +1,46 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.constant.enums.ModuleType; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 系统日志注解 | |||||
| * | |||||
| * @Author scott | |||||
| * @email jeecgos@163.com | |||||
| * @Date 2019年1月14日 | |||||
| */ | |||||
| @Target(ElementType.METHOD) | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Documented | |||||
| public @interface AutoLog { | |||||
| /** | |||||
| * 日志内容 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| String value() default ""; | |||||
| /** | |||||
| * 日志类型 | |||||
| * | |||||
| * @return 0:操作日志;1:登录日志;2:定时任务; | |||||
| */ | |||||
| int logType() default CommonConstant.LOG_TYPE_2; | |||||
| /** | |||||
| * 操作日志类型 | |||||
| * | |||||
| * @return (1查询,2添加,3修改,4删除) | |||||
| */ | |||||
| int operateType() default 0; | |||||
| /** | |||||
| * 模块类型 默认为common | |||||
| * @return | |||||
| */ | |||||
| ModuleType module() default ModuleType.COMMON; | |||||
| } | |||||
| @ -0,0 +1,54 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import java.lang.annotation.ElementType; | |||||
| import java.lang.annotation.Retention; | |||||
| import java.lang.annotation.RetentionPolicy; | |||||
| import java.lang.annotation.Target; | |||||
| /** | |||||
| * 字典注解 | |||||
| * @author: dangzhenghui | |||||
| * @date: 2019年03月17日-下午9:37:16 | |||||
| */ | |||||
| @Target(ElementType.FIELD) | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| public @interface Dict { | |||||
| /** | |||||
| * 方法描述: 数据code | |||||
| * 作 者: dangzhenghui | |||||
| * 日 期: 2019年03月17日-下午9:37:16 | |||||
| * | |||||
| * @return 返回类型: String | |||||
| */ | |||||
| String dicCode(); | |||||
| /** | |||||
| * 方法描述: 数据Text | |||||
| * 作 者: dangzhenghui | |||||
| * 日 期: 2019年03月17日-下午9:37:16 | |||||
| * | |||||
| * @return 返回类型: String | |||||
| */ | |||||
| String dicText() default ""; | |||||
| /** | |||||
| * 方法描述: 数据字典表 | |||||
| * 作 者: dangzhenghui | |||||
| * 日 期: 2019年03月17日-下午9:37:16 | |||||
| * | |||||
| * @return 返回类型: String | |||||
| */ | |||||
| String dictTable() default ""; | |||||
| //update-begin---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| /** | |||||
| * 方法描述: 数据字典表所在数据源名称 | |||||
| * 作 者: chenrui | |||||
| * 日 期: 2023年12月20日-下午4:58 | |||||
| * | |||||
| * @return 返回类型: String | |||||
| */ | |||||
| String ds() default ""; | |||||
| //update-end---author:chenrui ---date:20231221 for:[issues/#5643]解决分布式下表字典跨库无法查询问题------------ | |||||
| } | |||||
| @ -0,0 +1,20 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 动态table切换 | |||||
| * | |||||
| * @author :zyf | |||||
| * @date:2020-04-25 | |||||
| */ | |||||
| @Target(ElementType.METHOD) | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Documented | |||||
| public @interface DynamicTable { | |||||
| /** | |||||
| * 需要动态解析的表名 | |||||
| * @return | |||||
| */ | |||||
| String value(); | |||||
| } | |||||
| @ -0,0 +1,19 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * online请求拦截专用注解 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target({ElementType.TYPE,ElementType.METHOD}) | |||||
| @Documented | |||||
| public @interface OnlineAuth { | |||||
| /** | |||||
| * 请求关键字,在xxx/code之前的字符串 | |||||
| * @return | |||||
| */ | |||||
| String value(); | |||||
| } | |||||
| @ -0,0 +1,29 @@ | |||||
| package org.jeecg.common.aspect.annotation; | |||||
| import java.lang.annotation.Documented; | |||||
| import java.lang.annotation.ElementType; | |||||
| import java.lang.annotation.Retention; | |||||
| import java.lang.annotation.RetentionPolicy; | |||||
| import java.lang.annotation.Target; | |||||
| /** | |||||
| * 数据权限注解 | |||||
| * @Author taoyan | |||||
| * @Date 2019年4月11日 | |||||
| */ | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target({ElementType.TYPE,ElementType.METHOD}) | |||||
| @Documented | |||||
| public @interface PermissionData { | |||||
| /** | |||||
| * 暂时没用 | |||||
| * @return | |||||
| */ | |||||
| String value() default ""; | |||||
| /** | |||||
| * 配置菜单的组件路径,用于数据权限 | |||||
| */ | |||||
| String pageComponent() default ""; | |||||
| } | |||||
| @ -0,0 +1,632 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * @Description: 通用常量 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public interface CommonConstant { | |||||
| /** | |||||
| * 正常状态 | |||||
| */ | |||||
| Integer STATUS_NORMAL = 0; | |||||
| /** | |||||
| * 禁用状态 | |||||
| */ | |||||
| Integer STATUS_DISABLE = -1; | |||||
| /** | |||||
| * 删除标志 | |||||
| */ | |||||
| Integer DEL_FLAG_1 = 1; | |||||
| /** | |||||
| * 未删除 | |||||
| */ | |||||
| Integer DEL_FLAG_0 = 0; | |||||
| /** | |||||
| * 系统日志类型: 登录 | |||||
| */ | |||||
| int LOG_TYPE_1 = 1; | |||||
| /** | |||||
| * 系统日志类型: 操作 | |||||
| */ | |||||
| int LOG_TYPE_2 = 2; | |||||
| /** | |||||
| * 系统日志类型: 租户操作日志 | |||||
| */ | |||||
| int LOG_TYPE_3 = 3; | |||||
| /** | |||||
| * 系统日志类型: 异常 | |||||
| */ | |||||
| int LOG_TYPE_4 = 4; | |||||
| /** | |||||
| * 操作日志类型: 查询 | |||||
| */ | |||||
| int OPERATE_TYPE_1 = 1; | |||||
| /** | |||||
| * 操作日志类型: 添加 | |||||
| */ | |||||
| int OPERATE_TYPE_2 = 2; | |||||
| /** | |||||
| * 操作日志类型: 更新 | |||||
| */ | |||||
| int OPERATE_TYPE_3 = 3; | |||||
| /** | |||||
| * 操作日志类型: 删除 | |||||
| */ | |||||
| int OPERATE_TYPE_4 = 4; | |||||
| /** | |||||
| * 操作日志类型: 倒入 | |||||
| */ | |||||
| int OPERATE_TYPE_5 = 5; | |||||
| /** | |||||
| * 操作日志类型: 导出 | |||||
| */ | |||||
| int OPERATE_TYPE_6 = 6; | |||||
| /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */ | |||||
| Integer SC_INTERNAL_SERVER_ERROR_500 = 500; | |||||
| /** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */ | |||||
| Integer SC_INTERNAL_NOT_FOUND_404 = 404; | |||||
| /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */ | |||||
| Integer SC_OK_200 = 200; | |||||
| /**访问权限认证未通过 510*/ | |||||
| Integer SC_JEECG_NO_AUTHZ=510; | |||||
| /** 登录用户Shiro权限缓存KEY前缀 */ | |||||
| public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:"; | |||||
| /** 登录用户Token令牌缓存KEY前缀 */ | |||||
| String PREFIX_USER_TOKEN = "prefix_user_token:"; | |||||
| // /** Token缓存时间:3600秒即一小时 */ | |||||
| // int TOKEN_EXPIRE_TIME = 3600; | |||||
| /** 登录二维码 */ | |||||
| String LOGIN_QRCODE_PRE = "QRCODELOGIN:"; | |||||
| String LOGIN_QRCODE = "LQ:"; | |||||
| /** 登录二维码token */ | |||||
| String LOGIN_QRCODE_TOKEN = "LQT:"; | |||||
| /** | |||||
| * 0:一级菜单 | |||||
| */ | |||||
| Integer MENU_TYPE_0 = 0; | |||||
| /** | |||||
| * 1:子菜单 | |||||
| */ | |||||
| Integer MENU_TYPE_1 = 1; | |||||
| /** | |||||
| * 2:按钮权限 | |||||
| */ | |||||
| Integer MENU_TYPE_2 = 2; | |||||
| /**通告对象类型(USER:指定用户,ALL:全体用户)*/ | |||||
| String MSG_TYPE_UESR = "USER"; | |||||
| String MSG_TYPE_ALL = "ALL"; | |||||
| /**发布状态(0未发布,1已发布,2已撤销)*/ | |||||
| String NO_SEND = "0"; | |||||
| String HAS_SEND = "1"; | |||||
| String HAS_CANCLE = "2"; | |||||
| /**阅读状态(0未读,1已读)*/ | |||||
| Integer HAS_READ_FLAG = 1; | |||||
| Integer NO_READ_FLAG = 0; | |||||
| /**优先级(L低,M中,H高)*/ | |||||
| String PRIORITY_L = "L"; | |||||
| String PRIORITY_M = "M"; | |||||
| String PRIORITY_H = "H"; | |||||
| /** | |||||
| * 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板 | |||||
| */ | |||||
| String SMS_TPL_TYPE_0 = "0"; | |||||
| String SMS_TPL_TYPE_1 = "1"; | |||||
| String SMS_TPL_TYPE_2 = "2"; | |||||
| /** | |||||
| * 状态(0无效1有效) | |||||
| */ | |||||
| String STATUS_0 = "0"; | |||||
| String STATUS_1 = "1"; | |||||
| Integer STATUS_0_INT = 0; | |||||
| Integer STATUS_1_INT = 1; | |||||
| /** | |||||
| * 同步工作流引擎1同步0不同步 | |||||
| */ | |||||
| Integer ACT_SYNC_1 = 1; | |||||
| Integer ACT_SYNC_0 = 0; | |||||
| /** | |||||
| * 消息类型1:通知公告2:系统消息 | |||||
| */ | |||||
| String MSG_CATEGORY_1 = "1"; | |||||
| String MSG_CATEGORY_2 = "2"; | |||||
| /** | |||||
| * 是否配置菜单的数据权限 1是0否 | |||||
| */ | |||||
| Integer RULE_FLAG_0 = 0; | |||||
| Integer RULE_FLAG_1 = 1; | |||||
| /** | |||||
| * 是否用户已被冻结 1正常(解冻) 2冻结 3离职 | |||||
| */ | |||||
| Integer USER_UNFREEZE = 1; | |||||
| Integer USER_FREEZE = 2; | |||||
| Integer USER_QUIT = 3; | |||||
| /**字典翻译文本后缀*/ | |||||
| String DICT_TEXT_SUFFIX = "_dictText"; | |||||
| /**字典翻译颜色后缀*/ | |||||
| String DICT_COLOR_SUFFIX = "_dictColor"; | |||||
| /** | |||||
| * 表单设计器主表类型 | |||||
| */ | |||||
| Integer DESIGN_FORM_TYPE_MAIN = 1; | |||||
| /** | |||||
| * 表单设计器子表表类型 | |||||
| */ | |||||
| Integer DESIGN_FORM_TYPE_SUB = 2; | |||||
| /** | |||||
| * 表单设计器URL授权通过 | |||||
| */ | |||||
| Integer DESIGN_FORM_URL_STATUS_PASSED = 1; | |||||
| /** | |||||
| * 表单设计器URL授权未通过 | |||||
| */ | |||||
| Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2; | |||||
| /** | |||||
| * 表单设计器新增 Flag | |||||
| */ | |||||
| String DESIGN_FORM_URL_TYPE_ADD = "add"; | |||||
| /** | |||||
| * 表单设计器修改 Flag | |||||
| */ | |||||
| String DESIGN_FORM_URL_TYPE_EDIT = "edit"; | |||||
| /** | |||||
| * 表单设计器详情 Flag | |||||
| */ | |||||
| String DESIGN_FORM_URL_TYPE_DETAIL = "detail"; | |||||
| /** | |||||
| * 表单设计器复用数据 Flag | |||||
| */ | |||||
| String DESIGN_FORM_URL_TYPE_REUSE = "reuse"; | |||||
| /** | |||||
| * 表单设计器编辑 Flag (已弃用) | |||||
| */ | |||||
| String DESIGN_FORM_URL_TYPE_VIEW = "view"; | |||||
| /** | |||||
| * online参数值设置(是:Y, 否:N) | |||||
| */ | |||||
| String ONLINE_PARAM_VAL_IS_TURE = "Y"; | |||||
| String ONLINE_PARAM_VAL_IS_FALSE = "N"; | |||||
| /** | |||||
| * 文件上传类型(本地:local,Minio:minio,阿里云:alioss) | |||||
| */ | |||||
| String UPLOAD_TYPE_LOCAL = "local"; | |||||
| String UPLOAD_TYPE_MINIO = "minio"; | |||||
| String UPLOAD_TYPE_OSS = "alioss"; | |||||
| /** | |||||
| * 文档上传自定义桶名称 | |||||
| */ | |||||
| String UPLOAD_CUSTOM_BUCKET = "eoafile"; | |||||
| /** | |||||
| * 文档上传自定义路径 | |||||
| */ | |||||
| String UPLOAD_CUSTOM_PATH = "eoafile"; | |||||
| /** | |||||
| * 文件外链接有效天数 | |||||
| */ | |||||
| Integer UPLOAD_EFFECTIVE_DAYS = 1; | |||||
| /** | |||||
| * 员工身份 (1:普通员工 2:上级) | |||||
| */ | |||||
| Integer USER_IDENTITY_1 = 1; | |||||
| Integer USER_IDENTITY_2 = 2; | |||||
| /** sys_user 表 username 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username"; | |||||
| /** sys_user 表 work_no 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no"; | |||||
| /** sys_user 表 phone 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone"; | |||||
| /** 达梦数据库升提示。违反表[SYS_USER]唯一性约束 */ | |||||
| String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束"; | |||||
| /** sys_user 表 email 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email"; | |||||
| /** sys_quartz_job 表 job_class_name 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name"; | |||||
| /** sys_position 表 code 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_CODE = "uniq_code"; | |||||
| /** sys_role 表 code 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code"; | |||||
| /** sys_depart 表 code 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code"; | |||||
| /** sys_category 表 code 唯一键索引 */ | |||||
| String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code"; | |||||
| /** | |||||
| * 在线聊天 是否为默认分组 | |||||
| */ | |||||
| String IM_DEFAULT_GROUP = "1"; | |||||
| /** | |||||
| * 在线聊天 图片文件保存路径 | |||||
| */ | |||||
| String IM_UPLOAD_CUSTOM_PATH = "biz/user_imgs"; | |||||
| /** | |||||
| * 在线聊天 用户状态 | |||||
| */ | |||||
| String IM_STATUS_ONLINE = "online"; | |||||
| /** | |||||
| * 在线聊天 SOCKET消息类型 | |||||
| */ | |||||
| String IM_SOCKET_TYPE = "chatMessage"; | |||||
| /** | |||||
| * 在线聊天 是否开启默认添加好友 1是 0否 | |||||
| */ | |||||
| String IM_DEFAULT_ADD_FRIEND = "1"; | |||||
| /** | |||||
| * 在线聊天 用户好友缓存前缀 | |||||
| */ | |||||
| String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_"; | |||||
| /** | |||||
| * 缓存用户id与用户名关系 | |||||
| */ | |||||
| String SYS_USER_ID_MAPPING_CACHE = "sys:cache:user:id_mapping"; | |||||
| /** | |||||
| * 考勤补卡业务状态 (1:同意 2:不同意) | |||||
| */ | |||||
| String SIGN_PATCH_BIZ_STATUS_1 = "1"; | |||||
| String SIGN_PATCH_BIZ_STATUS_2 = "2"; | |||||
| /** | |||||
| * 公文文档上传自定义路径 | |||||
| */ | |||||
| String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc"; | |||||
| /** | |||||
| * 公文文档下载自定义路径 | |||||
| */ | |||||
| String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown"; | |||||
| /** | |||||
| * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板)) | |||||
| */ | |||||
| String WPS_TYPE_1="1"; | |||||
| String WPS_TYPE_2="2"; | |||||
| /**===============================================================================================*/ | |||||
| /** | |||||
| * ::非常重要:: | |||||
| * 注意:这四个常量值如果修改,需要与 jeecg-boot-starter/jeecg-boot-common/org.jeecg.config.FeignConfig 类中的值保持一致。 | |||||
| */ | |||||
| String X_ACCESS_TOKEN = "X-Access-Token"; | |||||
| String X_SIGN = "X-Sign"; | |||||
| String X_TIMESTAMP = "X-TIMESTAMP"; | |||||
| /** 租户请求头 更名为:X-Tenant-Id */ | |||||
| String TENANT_ID = "X-Tenant-Id"; | |||||
| /** 简流接口请求头,用于排除不支持的控件字段 */ | |||||
| String X_MiniFlowExclusionFieldMode = "X-Miniflowexclusionfieldmode"; | |||||
| /**===============================================================================================*/ | |||||
| String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!"; | |||||
| String X_FORWARDED_SCHEME = "X-Forwarded-Scheme"; | |||||
| /** | |||||
| * 微服务读取配置文件属性 服务地址 | |||||
| */ | |||||
| String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr"; | |||||
| /** | |||||
| * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用 | |||||
| */ | |||||
| String THIRD_LOGIN_CODE = "third_login_code"; | |||||
| /** | |||||
| * 第三方APP同步方向:本地 --> 第三方APP | |||||
| */ | |||||
| String THIRD_SYNC_TO_APP = "SYNC_TO_APP"; | |||||
| /** | |||||
| * 第三方APP同步方向:第三方APP --> 本地 | |||||
| */ | |||||
| String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL"; | |||||
| /** 系统通告消息状态:0=未发布 */ | |||||
| String ANNOUNCEMENT_SEND_STATUS_0 = "0"; | |||||
| /** 系统通告消息状态:1=已发布 */ | |||||
| String ANNOUNCEMENT_SEND_STATUS_1 = "1"; | |||||
| /** 系统通告消息状态:2=已撤销 */ | |||||
| String ANNOUNCEMENT_SEND_STATUS_2 = "2"; | |||||
| /**ONLINE 报表权限用 从request中获取地址栏后的参数*/ | |||||
| String ONL_REP_URL_PARAM_STR="onlRepUrlParamStr"; | |||||
| /**POST请求*/ | |||||
| String HTTP_POST = "POST"; | |||||
| /**PUT请求*/ | |||||
| String HTTP_PUT = "PUT"; | |||||
| /**PATCH请求*/ | |||||
| String HTTP_PATCH = "PATCH"; | |||||
| /**未知的*/ | |||||
| String UNKNOWN = "unknown"; | |||||
| /**字符串http*/ | |||||
| String STR_HTTP = "http"; | |||||
| /**String 类型的空值*/ | |||||
| String STRING_NULL = "null"; | |||||
| /**前端vue3版本Header参数名*/ | |||||
| String VERSION="X-Version"; | |||||
| String VERSION_V3 = "v3"; | |||||
| /**存储在线程变量里的动态表名*/ | |||||
| String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME"; | |||||
| /** | |||||
| * http:// http协议 | |||||
| */ | |||||
| String HTTP_PROTOCOL = "http://"; | |||||
| /** | |||||
| * https:// https协议 | |||||
| */ | |||||
| String HTTPS_PROTOCOL = "https://"; | |||||
| /** 部门表唯一key,id */ | |||||
| String DEPART_KEY_ID = "id"; | |||||
| /** 部门表唯一key,orgCode */ | |||||
| String DEPART_KEY_ORG_CODE = "orgCode"; | |||||
| /**======【消息推送相关】==============================================================================*/ | |||||
| /** | |||||
| * 发消息 会传递一些信息到map | |||||
| */ | |||||
| String NOTICE_MSG_SUMMARY = "NOTICE_MSG_SUMMARY"; | |||||
| /** | |||||
| * 发消息 会传递一个业务ID到map | |||||
| */ | |||||
| String NOTICE_MSG_BUS_ID = "NOTICE_MSG_BUS_ID"; | |||||
| /** | |||||
| * 发消息 消息业务类型 | |||||
| */ | |||||
| String NOTICE_MSG_BUS_TYPE = "NOTICE_MSG_BUS_TYPE"; | |||||
| /** | |||||
| * 邮箱消息中地址登录时地址后携带的token,需要替换成真实的token值 | |||||
| */ | |||||
| String LOGIN_TOKEN = "{LOGIN_TOKEN}"; | |||||
| /** | |||||
| * 模板消息中 跳转地址的对应的key | |||||
| */ | |||||
| String MSG_HREF_URL = "url"; | |||||
| /** | |||||
| * sys_data_log表的类型 用于区别评论区域的日志数据 | |||||
| */ | |||||
| String DATA_LOG_TYPE_COMMENT = "comment"; | |||||
| /** | |||||
| * sys_data_log表的类型 老的数据比较 类型都设置为json | |||||
| */ | |||||
| String DATA_LOG_TYPE_JSON = "json"; | |||||
| /** 消息模板:markdown */ | |||||
| String MSG_TEMPLATE_TYPE_MD = "5"; | |||||
| /**========【消息推送相关】==========================================================================*/ | |||||
| /** | |||||
| * 短信验证码redis-key的前缀 | |||||
| */ | |||||
| String PHONE_REDIS_KEY_PRE = "phone_msg"; | |||||
| /** | |||||
| * 是文件夹 | |||||
| */ | |||||
| String IT_IS_FOLDER = "1"; | |||||
| /** | |||||
| * 文件拥有者 | |||||
| */ | |||||
| String FILE_OWNER = "owner"; | |||||
| /** | |||||
| * 文件管理员 | |||||
| */ | |||||
| String FILE_ADMIN = "admin"; | |||||
| /** | |||||
| * 只允许编辑 | |||||
| */ | |||||
| String FILE_EDITABLE = "editable"; | |||||
| /** | |||||
| * 文件 只读 | |||||
| */ | |||||
| String FILE_READONLY = "readonly"; | |||||
| /** | |||||
| * 登录失败,用于记录失败次数的key | |||||
| */ | |||||
| String LOGIN_FAIL = "LOGIN_FAIL_"; | |||||
| /** | |||||
| * 入职事件 | |||||
| */ | |||||
| Integer BPM_USER_EVENT_ADD = 1; | |||||
| /** | |||||
| * 离职事件 | |||||
| */ | |||||
| Integer BPM_USER_EVENT_LEVEL = 2; | |||||
| /** | |||||
| * 用户租户状态(正常/已通过审核的) | |||||
| */ | |||||
| String USER_TENANT_NORMAL = "1"; | |||||
| /** | |||||
| * 用户租户状态(离职) | |||||
| */ | |||||
| String USER_TENANT_QUIT = "2"; | |||||
| /** | |||||
| * 用户租户状态(审核中) | |||||
| */ | |||||
| String USER_TENANT_UNDER_REVIEW = "3"; | |||||
| /** | |||||
| * 用户租户状态(拒绝) | |||||
| */ | |||||
| String USER_TENANT_REFUSE = "4"; | |||||
| /** | |||||
| * 用户租户状态(邀请) | |||||
| */ | |||||
| String USER_TENANT_INVITE = "5"; | |||||
| /** | |||||
| * 不是叶子节点 | |||||
| */ | |||||
| Integer NOT_LEAF = 0; | |||||
| /** | |||||
| * 是叶子节点 | |||||
| */ | |||||
| Integer IS_LEAF = 1; | |||||
| /** | |||||
| * 钉钉 | |||||
| */ | |||||
| String DINGTALK = "DINGTALK"; | |||||
| /** | |||||
| * 企业微信 | |||||
| */ | |||||
| String WECHAT_ENTERPRISE = "WECHAT_ENTERPRISE"; | |||||
| /** | |||||
| * 系统默认租户id 0 | |||||
| */ | |||||
| Integer TENANT_ID_DEFAULT_VALUE = 0; | |||||
| /** | |||||
| * 【low-app用】 应用级别的复制 | |||||
| */ | |||||
| String COPY_LEVEL_APP = "app"; | |||||
| /** | |||||
| * 【low-app用】 菜单级别的复制 | |||||
| */ | |||||
| String COPY_LEVEL_MENU = "menu"; | |||||
| /** | |||||
| * 【low-app用】 应用备份 | |||||
| */ | |||||
| String COPY_LEVEL_BAK = "backup"; | |||||
| /** | |||||
| * 【low-app用】 从备份还原 | |||||
| */ | |||||
| String COPY_LEVEL_COVER = "cover"; | |||||
| /** 【QQYUN-6034】关联字段变更历史值,缓存半个小时 */ | |||||
| String CACHE_REL_FIELD_OLD_VAL = "sys:cache:desform:relFieldOldVal:"; | |||||
| /** | |||||
| * 排序类型:升序 | |||||
| */ | |||||
| String ORDER_TYPE_ASC = "ASC"; | |||||
| /** | |||||
| * 排序类型:降序 | |||||
| */ | |||||
| String ORDER_TYPE_DESC = "DESC"; | |||||
| //update-begin---author:scott ---date:2023-09-10 for:积木报表常量---- | |||||
| /** | |||||
| * 报表允许设计开发的角色 | |||||
| */ | |||||
| public static String[] allowDevRoles = new String[]{"lowdeveloper", "admin"}; | |||||
| /** | |||||
| * 【对应积木报表的常量】 | |||||
| * 数据隔离模式: 按照创建人隔离 | |||||
| */ | |||||
| public static final String SAAS_MODE_CREATED = "created"; | |||||
| /** | |||||
| * 【对应积木报表的常量】 | |||||
| * 数据隔离模式: 按照租户隔离 | |||||
| */ | |||||
| public static final String SAAS_MODE_TENANT = "tenant"; | |||||
| //update-end---author:scott ---date::2023-09-10 for:积木报表常量---- | |||||
| //update-begin---author:wangshuai---date:2024-04-07---for:修改手机号常量--- | |||||
| /** | |||||
| * 修改手机号短信验证码redis-key的前缀 | |||||
| */ | |||||
| String CHANGE_PHONE_REDIS_KEY_PRE = "sys:cache:phone:change_phone_msg:"; | |||||
| /** | |||||
| * 手机号短信验证码redis-key的前缀 | |||||
| */ | |||||
| String LOG_OFF_PHONE_REDIS_KEY_PRE = "sys:cache:phone:qqy_log_off_user_msg:"; | |||||
| /** | |||||
| * 缓存用户最后一次收到消息通知的时间 KEY | |||||
| */ | |||||
| String CACHE_KEY_USER_LAST_ANNOUNT_TIME_1HOUR = "sys:cache:userinfo:user_last_annount_time::%s"; | |||||
| /** | |||||
| * 验证原手机号 | |||||
| */ | |||||
| String VERIFY_ORIGINAL_PHONE = "verifyOriginalPhone"; | |||||
| /** | |||||
| * 修改手机号 | |||||
| */ | |||||
| String UPDATE_PHONE = "updatePhone"; | |||||
| //update-end---author:wangshuai---date:2024-04-07---for:修改手机号常量--- | |||||
| /** | |||||
| * 修改手机号验证码请求次数超出 | |||||
| */ | |||||
| Integer PHONE_SMS_FAIL_CODE = 40002; | |||||
| } | |||||
| @ -0,0 +1,48 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * 系统通告 - 发布状态 | |||||
| * @Author LeeShaoQing | |||||
| * | |||||
| */ | |||||
| public interface CommonSendStatus { | |||||
| /** | |||||
| * 未发布 | |||||
| */ | |||||
| public static final String UNPUBLISHED_STATUS_0 = "0"; | |||||
| /** | |||||
| * 已发布 | |||||
| */ | |||||
| public static final String PUBLISHED_STATUS_1 = "1"; | |||||
| /** | |||||
| * 撤销 | |||||
| */ | |||||
| public static final String REVOKE_STATUS_2 = "2"; | |||||
| /** | |||||
| * app端推送会话标识后缀 | |||||
| */ | |||||
| public static final String APP_SESSION_SUFFIX = "_app"; | |||||
| /**-----【流程相关通知模板code】------------------------------------------------------------*/ | |||||
| /**流程催办——系统通知消息模板*/ | |||||
| public static final String TZMB_BPM_CUIBAN = "bpm_cuiban"; | |||||
| /**流程抄送——系统通知消息模板*/ | |||||
| public static final String TZMB_BPM_CC = "bpm_cc"; | |||||
| /**流程催办——邮件通知消息模板*/ | |||||
| public static final String TZMB_BPM_CUIBAN_EMAIL = "bpm_cuiban_email"; | |||||
| /**标准模板—系统消息通知*/ | |||||
| public static final String TZMB_SYS_TS_NOTE = "sys_ts_note"; | |||||
| /**流程超时提醒——系统通知消息模板*/ | |||||
| public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip"; | |||||
| /**-----【流程相关通知模板code】-----------------------------------------------------------*/ | |||||
| /** | |||||
| * 系统通知拓展参数(比如:用于流程抄送和催办通知,这里额外传递流程跳转页面所需要的路由参数) | |||||
| */ | |||||
| public static final String MSG_ABSTRACT_JSON = "msg_abstract"; | |||||
| } | |||||
| @ -0,0 +1,182 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * 数据库上下文常量 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public interface DataBaseConstant { | |||||
| //*********数据库类型**************************************** | |||||
| /**MYSQL数据库*/ | |||||
| public static final String DB_TYPE_MYSQL = "MYSQL"; | |||||
| /** ORACLE*/ | |||||
| public static final String DB_TYPE_ORACLE = "ORACLE"; | |||||
| /**达梦数据库*/ | |||||
| public static final String DB_TYPE_DM = "DM"; | |||||
| /**postgreSQL达梦数据库*/ | |||||
| public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL"; | |||||
| /**人大金仓数据库*/ | |||||
| public static final String DB_TYPE_KINGBASEES = "KINGBASEES"; | |||||
| /**sqlserver数据库*/ | |||||
| public static final String DB_TYPE_SQLSERVER = "SQLSERVER"; | |||||
| /**mariadb 数据库*/ | |||||
| public static final String DB_TYPE_MARIADB = "MARIADB"; | |||||
| /**DB2 数据库*/ | |||||
| public static final String DB_TYPE_DB2 = "DB2"; | |||||
| /**HSQL 数据库*/ | |||||
| public static final String DB_TYPE_HSQL = "HSQL"; | |||||
| // // 数据库类型,对应 database_type 字典 | |||||
| // public static final String DB_TYPE_MYSQL_NUM = "1"; | |||||
| // public static final String DB_TYPE_MYSQL7_NUM = "6"; | |||||
| // public static final String DB_TYPE_ORACLE_NUM = "2"; | |||||
| // public static final String DB_TYPE_SQLSERVER_NUM = "3"; | |||||
| // public static final String DB_TYPE_POSTGRESQL_NUM = "4"; | |||||
| // public static final String DB_TYPE_MARIADB_NUM = "5"; | |||||
| //*********系统上下文变量**************************************** | |||||
| /** | |||||
| * 数据-所属机构编码 | |||||
| */ | |||||
| public static final String SYS_ORG_CODE = "sysOrgCode"; | |||||
| /** | |||||
| * 数据-所属机构编码 | |||||
| */ | |||||
| public static final String SYS_ORG_CODE_TABLE = "sys_org_code"; | |||||
| /** | |||||
| * 数据-所属机构编码 | |||||
| */ | |||||
| public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode"; | |||||
| /** | |||||
| * 数据-所属机构编码 | |||||
| */ | |||||
| public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code"; | |||||
| /** | |||||
| * 数据-所属机构ID | |||||
| */ | |||||
| public static final String SYS_ORG_ID = "sysOrgId"; | |||||
| /** | |||||
| * 数据-所属机构ID | |||||
| */ | |||||
| public static final String SYS_ORG_ID_TABLE = "sys_org_id"; | |||||
| /** | |||||
| * 数据-所属角色code(多个逗号分割) | |||||
| */ | |||||
| public static final String SYS_ROLE_CODE = "sysRoleCode"; | |||||
| /** | |||||
| * 数据-所属角色code(多个逗号分割) | |||||
| */ | |||||
| public static final String SYS_ROLE_CODE_TABLE = "sys_role_code"; | |||||
| /** | |||||
| * 数据-系统用户编码(对应登录用户账号) | |||||
| */ | |||||
| public static final String SYS_USER_CODE = "sysUserCode"; | |||||
| /** | |||||
| * 数据-系统用户编码(对应登录用户账号) | |||||
| */ | |||||
| public static final String SYS_USER_CODE_TABLE = "sys_user_code"; | |||||
| /** | |||||
| * 登录用户ID | |||||
| */ | |||||
| public static final String SYS_USER_ID = "sysUserId"; | |||||
| /** | |||||
| * 登录用户ID | |||||
| */ | |||||
| public static final String SYS_USER_ID_TABLE = "sys_user_id"; | |||||
| /** | |||||
| * 登录用户真实姓名 | |||||
| */ | |||||
| public static final String SYS_USER_NAME = "sysUserName"; | |||||
| /** | |||||
| * 登录用户真实姓名 | |||||
| */ | |||||
| public static final String SYS_USER_NAME_TABLE = "sys_user_name"; | |||||
| /** | |||||
| * 系统日期"yyyy-MM-dd" | |||||
| */ | |||||
| public static final String SYS_DATE = "sysDate"; | |||||
| /** | |||||
| * 系统日期"yyyy-MM-dd" | |||||
| */ | |||||
| public static final String SYS_DATE_TABLE = "sys_date"; | |||||
| /** | |||||
| * 系统时间"yyyy-MM-dd HH:mm" | |||||
| */ | |||||
| public static final String SYS_TIME = "sysTime"; | |||||
| /** | |||||
| * 系统时间"yyyy-MM-dd HH:mm" | |||||
| */ | |||||
| public static final String SYS_TIME_TABLE = "sys_time"; | |||||
| /** | |||||
| * 数据-所属机构编码 | |||||
| */ | |||||
| public static final String SYS_BASE_PATH = "sys_base_path"; | |||||
| //*********系统上下文变量**************************************** | |||||
| //*********系统建表标准字段**************************************** | |||||
| /** | |||||
| * 创建者登录名称 | |||||
| */ | |||||
| public static final String CREATE_BY_TABLE = "create_by"; | |||||
| /** | |||||
| * 创建者登录名称 | |||||
| */ | |||||
| public static final String CREATE_BY = "createBy"; | |||||
| /** | |||||
| * 创建日期时间 | |||||
| */ | |||||
| public static final String CREATE_TIME_TABLE = "create_time"; | |||||
| /** | |||||
| * 创建日期时间 | |||||
| */ | |||||
| public static final String CREATE_TIME = "createTime"; | |||||
| /** | |||||
| * 更新用户登录名称 | |||||
| */ | |||||
| public static final String UPDATE_BY_TABLE = "update_by"; | |||||
| /** | |||||
| * 更新用户登录名称 | |||||
| */ | |||||
| public static final String UPDATE_BY = "updateBy"; | |||||
| /** | |||||
| * 更新日期时间 | |||||
| */ | |||||
| public static final String UPDATE_TIME = "updateTime"; | |||||
| /** | |||||
| * 更新日期时间 | |||||
| */ | |||||
| public static final String UPDATE_TIME_TABLE = "update_time"; | |||||
| /** | |||||
| * 业务流程状态 | |||||
| */ | |||||
| public static final String BPM_STATUS = "bpmStatus"; | |||||
| /** | |||||
| * 业务流程状态 | |||||
| */ | |||||
| public static final String BPM_STATUS_TABLE = "bpm_status"; | |||||
| //*********系统建表标准字段**************************************** | |||||
| /** | |||||
| * sql语句 where | |||||
| */ | |||||
| String SQL_WHERE = "where"; | |||||
| /** | |||||
| * sql语句 asc | |||||
| */ | |||||
| String SQL_ASC = "asc"; | |||||
| /** | |||||
| * sqlserver数据库,中间有空格 | |||||
| */ | |||||
| String DB_TYPE_SQL_SERVER_BLANK = "sql server"; | |||||
| } | |||||
| @ -0,0 +1,16 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * 动态切换表配置常量 | |||||
| * | |||||
| * @author: scott | |||||
| * @date: 2022年04月25日 22:30 | |||||
| */ | |||||
| public class DynamicTableConstant { | |||||
| /** | |||||
| * 角色首页配置表 | |||||
| * vue2表名: sys_role_index | |||||
| * vue3表名: sys_role_index_vue3 | |||||
| */ | |||||
| public static final String SYS_ROLE_INDEX = "sys_role_index"; | |||||
| } | |||||
| @ -0,0 +1,25 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * 规则值生成 编码常量类 | |||||
| * @author: taoyan | |||||
| * @date: 2020年04月02日 | |||||
| */ | |||||
| public class FillRuleConstant { | |||||
| /** | |||||
| * 公文发文编码 | |||||
| */ | |||||
| public static final String DOC_SEND = "doc_send_code"; | |||||
| /** | |||||
| * 部门编码 | |||||
| */ | |||||
| public static final String DEPART = "org_num_role"; | |||||
| /** | |||||
| * 分类字典编码 | |||||
| */ | |||||
| public static final String CATEGORY = "category_code_rule"; | |||||
| } | |||||
| @ -0,0 +1,223 @@ | |||||
| package org.jeecg.common.constant; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.core.io.Resource; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Scanner; | |||||
| import java.util.Set; | |||||
| import java.util.List; | |||||
| /** | |||||
| * @Description: 省市区 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Component("pca") | |||||
| public class ProvinceCityArea { | |||||
| List<Area> areaList; | |||||
| public String getText(String code){ | |||||
| if(StringUtils.isNotBlank(code)){ | |||||
| this.initAreaList(); | |||||
| if(this.areaList!=null || this.areaList.size()>0){ | |||||
| List<String> ls = new ArrayList<String>(); | |||||
| getAreaByCode(code,ls); | |||||
| return String.join("/",ls); | |||||
| } | |||||
| } | |||||
| return ""; | |||||
| } | |||||
| public String getCode(String text){ | |||||
| if(StringUtils.isNotBlank(text)){ | |||||
| this.initAreaList(); | |||||
| if(areaList!=null && areaList.size()>0){ | |||||
| for(int i=areaList.size()-1;i>=0;i--){ | |||||
| //update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | |||||
| String areaText = areaList.get(i).getText(); | |||||
| String cityText = areaList.get(i).getAheadText(); | |||||
| if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){ | |||||
| return areaList.get(i).getId(); | |||||
| } | |||||
| //update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | |||||
| } | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| // update-begin-author:sunjianlei date:20220121 for:【JTC-704】数据导入错误 省市区组件,文件中为北京市,导入后,导为了山西省 | |||||
| /** | |||||
| * 获取省市区code,精准匹配 | |||||
| * @param texts 文本数组,省,市,区 | |||||
| * @return 返回 省市区的code | |||||
| */ | |||||
| public String[] getCode(String[] texts) { | |||||
| if (texts == null || texts.length == 0) { | |||||
| return null; | |||||
| } | |||||
| this.initAreaList(); | |||||
| if (areaList == null || areaList.size() == 0) { | |||||
| return null; | |||||
| } | |||||
| String[] codes = new String[texts.length]; | |||||
| String code = null; | |||||
| for (int i = 0; i < texts.length; i++) { | |||||
| String text = texts[i]; | |||||
| Area area; | |||||
| if (code == null) { | |||||
| area = getAreaByText(text); | |||||
| } else { | |||||
| area = getAreaByPidAndText(code, text); | |||||
| } | |||||
| if (area != null) { | |||||
| code = area.id; | |||||
| codes[i] = code; | |||||
| } else { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| return codes; | |||||
| } | |||||
| /** | |||||
| * 根据text获取area | |||||
| * @param text | |||||
| * @return | |||||
| */ | |||||
| public Area getAreaByText(String text) { | |||||
| for (Area area : areaList) { | |||||
| if (text.equals(area.getText())) { | |||||
| return area; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * 通过pid获取 area 对象 | |||||
| * @param pCode 父级编码 | |||||
| * @param text | |||||
| * @return | |||||
| */ | |||||
| public Area getAreaByPidAndText(String pCode, String text) { | |||||
| this.initAreaList(); | |||||
| if (this.areaList != null && this.areaList.size() > 0) { | |||||
| for (Area area : this.areaList) { | |||||
| if (area.getPid().equals(pCode) && area.getText().equals(text)) { | |||||
| return area; | |||||
| } | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| // update-end-author:sunjianlei date:20220121 for:【JTC-704】数据导入错误 省市区组件,文件中为北京市,导入后,导为了山西省 | |||||
| public void getAreaByCode(String code,List<String> ls){ | |||||
| for(Area area: areaList){ | |||||
| if(area.getId().equals(code)){ | |||||
| String pid = area.getPid(); | |||||
| ls.add(0,area.getText()); | |||||
| getAreaByCode(pid,ls); | |||||
| } | |||||
| } | |||||
| } | |||||
| private void initAreaList(){ | |||||
| //System.out.println("====================="); | |||||
| if(this.areaList==null || this.areaList.size()==0){ | |||||
| this.areaList = new ArrayList<Area>(); | |||||
| try { | |||||
| String jsonData = oConvertUtils.readStatic("classpath:static/pca.json"); | |||||
| JSONObject baseJson = JSONObject.parseObject(jsonData); | |||||
| //第一层 省 | |||||
| JSONObject provinceJson = baseJson.getJSONObject("86"); | |||||
| for(String provinceKey: provinceJson.keySet()){ | |||||
| //System.out.println("===="+provinceKey); | |||||
| Area province = new Area(provinceKey,provinceJson.getString(provinceKey),"86"); | |||||
| this.areaList.add(province); | |||||
| //第二层 市 | |||||
| JSONObject cityJson = baseJson.getJSONObject(provinceKey); | |||||
| for(String cityKey:cityJson.keySet()){ | |||||
| //System.out.println("-----"+cityKey); | |||||
| Area city = new Area(cityKey,cityJson.getString(cityKey),provinceKey); | |||||
| this.areaList.add(city); | |||||
| //第三层 区 | |||||
| JSONObject areaJson = baseJson.getJSONObject(cityKey); | |||||
| if(areaJson!=null){ | |||||
| for(String areaKey:areaJson.keySet()){ | |||||
| //System.out.println("········"+areaKey); | |||||
| Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey); | |||||
| //update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | |||||
| area.setAheadText(cityJson.getString(cityKey)); | |||||
| //update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | |||||
| this.areaList.add(area); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| private String jsonRead(File file){ | |||||
| Scanner scanner = null; | |||||
| StringBuilder buffer = new StringBuilder(); | |||||
| try { | |||||
| scanner = new Scanner(file, "utf-8"); | |||||
| while (scanner.hasNextLine()) { | |||||
| buffer.append(scanner.nextLine()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| } finally { | |||||
| if (scanner != null) { | |||||
| scanner.close(); | |||||
| } | |||||
| } | |||||
| return buffer.toString(); | |||||
| } | |||||
| class Area{ | |||||
| String id; | |||||
| String text; | |||||
| String pid; | |||||
| // 用于存储上级文本数据,区的上级文本 是市的数据 | |||||
| String aheadText; | |||||
| public Area(String id,String text,String pid){ | |||||
| this.id = id; | |||||
| this.text = text; | |||||
| this.pid = pid; | |||||
| } | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public String getText() { | |||||
| return text; | |||||
| } | |||||
| public String getPid() { | |||||
| return pid; | |||||
| } | |||||
| public String getAheadText() { | |||||
| return aheadText; | |||||
| } | |||||
| public void setAheadText(String aheadText) { | |||||
| this.aheadText = aheadText; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,59 @@ | |||||
| /* | |||||
| * | |||||
| * * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com). | |||||
| * * <p> | |||||
| * * Licensed under the GNU Lesser General Public License 3.0 (the "License"); | |||||
| * * you may not use this file except in compliance with the License. | |||||
| * * You may obtain a copy of the License at | |||||
| * * <p> | |||||
| * * https://www.gnu.org/licenses/lgpl.html | |||||
| * * <p> | |||||
| * * Unless required by applicable law or agreed to in writing, software | |||||
| * * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * * See the License for the specific language governing permissions and | |||||
| * * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * @author scott | |||||
| * @date 2019年05月18日 | |||||
| * 服务名称 | |||||
| */ | |||||
| public interface ServiceNameConstants { | |||||
| /** | |||||
| * 微服务名:系统管理模块 | |||||
| */ | |||||
| String SERVICE_SYSTEM = "jeecg-system"; | |||||
| /** | |||||
| * 微服务名: demo模块 | |||||
| */ | |||||
| String SERVICE_DEMO = "jeecg-demo"; | |||||
| /** | |||||
| * 微服务名:joa模块 | |||||
| */ | |||||
| String SERVICE_JOA = "jeecg-joa"; | |||||
| // /** | |||||
| // * 微服务名:online在线模块 | |||||
| // */ | |||||
| // String SERVICE_ONLINE = "jeecg-online"; | |||||
| // /** | |||||
| // * 微服务名:OA模块 | |||||
| // */ | |||||
| // String SERVICE_EOA = "jeecg-eoa"; | |||||
| // /** | |||||
| // * 微服务名:表单设计模块 | |||||
| // */ | |||||
| // String SERVICE_FORM = "jeecg-desform"; | |||||
| /** | |||||
| * gateway通过header传递根路径 basePath | |||||
| */ | |||||
| String X_GATEWAY_BASE_PATH = "X_GATEWAY_BASE_PATH"; | |||||
| } | |||||
| @ -0,0 +1,123 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * @Description: 符号和特殊符号常用类 | |||||
| * @author: wangshuai | |||||
| * @date: 2022年03月30日 17:44 | |||||
| */ | |||||
| public class SymbolConstant { | |||||
| /** | |||||
| * 符号:点 | |||||
| */ | |||||
| public static final String SPOT = "."; | |||||
| /** | |||||
| * 符号:双斜杠 | |||||
| */ | |||||
| public static final String DOUBLE_BACKSLASH = "\\"; | |||||
| /** | |||||
| * 符号:冒号 | |||||
| */ | |||||
| public static final String COLON = ":"; | |||||
| /** | |||||
| * 符号:逗号 | |||||
| */ | |||||
| public static final String COMMA = ","; | |||||
| /** | |||||
| * 符号:左花括号 } | |||||
| */ | |||||
| public static final String LEFT_CURLY_BRACKET = "{"; | |||||
| /** | |||||
| * 符号:右花括号 } | |||||
| */ | |||||
| public static final String RIGHT_CURLY_BRACKET = "}"; | |||||
| /** | |||||
| * 符号:井号 # | |||||
| */ | |||||
| public static final String WELL_NUMBER = "#"; | |||||
| /** | |||||
| * 符号:单斜杠 | |||||
| */ | |||||
| public static final String SINGLE_SLASH = "/"; | |||||
| /** | |||||
| * 符号:双斜杠 | |||||
| */ | |||||
| public static final String DOUBLE_SLASH = "//"; | |||||
| /** | |||||
| * 符号:感叹号 | |||||
| */ | |||||
| public static final String EXCLAMATORY_MARK = "!"; | |||||
| /** | |||||
| * 符号:下划线 | |||||
| */ | |||||
| public static final String UNDERLINE = "_"; | |||||
| /** | |||||
| * 符号:单引号 | |||||
| */ | |||||
| public static final String SINGLE_QUOTATION_MARK = "'"; | |||||
| /** | |||||
| * 符号:星号 | |||||
| */ | |||||
| public static final String ASTERISK = "*"; | |||||
| /** | |||||
| * 符号:百分号 | |||||
| */ | |||||
| public static final String PERCENT_SIGN = "%"; | |||||
| /** | |||||
| * 符号:美元 $ | |||||
| */ | |||||
| public static final String DOLLAR = "$"; | |||||
| /** | |||||
| * 符号:和 & | |||||
| */ | |||||
| public static final String AND = "&"; | |||||
| /** | |||||
| * 符号:../ | |||||
| */ | |||||
| public static final String SPOT_SINGLE_SLASH = "../"; | |||||
| /** | |||||
| * 符号:..\\ | |||||
| */ | |||||
| public static final String SPOT_DOUBLE_BACKSLASH = "..\\"; | |||||
| /** | |||||
| * 系统变量前缀 #{ | |||||
| */ | |||||
| public static final String SYS_VAR_PREFIX = "#{"; | |||||
| /** | |||||
| * 符号 {{ | |||||
| */ | |||||
| public static final String DOUBLE_LEFT_CURLY_BRACKET = "{{"; | |||||
| /** | |||||
| * 符号:[ | |||||
| */ | |||||
| public static final String SQUARE_BRACKETS_LEFT = "["; | |||||
| /** | |||||
| * 符号:] | |||||
| */ | |||||
| public static final String SQUARE_BRACKETS_RIGHT = "]"; | |||||
| /** | |||||
| * 拼接字符串符号 分号 ; | |||||
| */ | |||||
| public static final String SEMICOLON = ";"; | |||||
| } | |||||
| @ -0,0 +1,50 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * @Description: TenantConstant | |||||
| * @author: scott | |||||
| * @date: 2022年08月29日 15:29 | |||||
| */ | |||||
| public interface TenantConstant { | |||||
| /*------【低代码应用参数】----------------------------------------------*/ | |||||
| /** | |||||
| * header的lowAppId标识 | |||||
| */ | |||||
| String X_LOW_APP_ID = "X-Low-App-ID"; | |||||
| /** | |||||
| * 应用ID——实体字段 | |||||
| */ | |||||
| String FIELD_LOW_APP_ID = "lowAppId"; | |||||
| /** | |||||
| * 应用ID——表字段 | |||||
| */ | |||||
| String DB_FIELD_LOW_APP_ID = "low_app_id"; | |||||
| /*------【低代码应用参数】---------------------------------------------*/ | |||||
| /*--------【租户参数】-----------------------------------------------*/ | |||||
| /** | |||||
| * 租户ID(实体字段名 和 url参数名) | |||||
| */ | |||||
| String TENANT_ID = "tenantId"; | |||||
| /** | |||||
| * 租户ID 数据库字段名 | |||||
| */ | |||||
| String TENANT_ID_TABLE = "tenant_id"; | |||||
| /*-------【租户参数】-----------------------------------------------*/ | |||||
| /** | |||||
| * 超级管理员 | |||||
| */ | |||||
| String SUPER_ADMIN = "superAdmin"; | |||||
| /** | |||||
| * 组织账户管理员 | |||||
| */ | |||||
| String ACCOUNT_ADMIN = "accountAdmin"; | |||||
| /** | |||||
| * 组织应用管理员 | |||||
| */ | |||||
| String APP_ADMIN = "appAdmin"; | |||||
| } | |||||
| @ -0,0 +1,31 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * VXESocket 常量 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class VxeSocketConst { | |||||
| /** | |||||
| * 消息类型 | |||||
| */ | |||||
| public static final String TYPE = "type"; | |||||
| /** | |||||
| * 消息数据 | |||||
| */ | |||||
| public static final String DATA = "data"; | |||||
| /** | |||||
| * 消息类型:心跳检测 | |||||
| */ | |||||
| public static final String TYPE_HB = "heart_beat"; | |||||
| /** | |||||
| * 消息类型:通用数据传递 | |||||
| */ | |||||
| public static final String TYPE_CSD = "common_send_date"; | |||||
| /** | |||||
| * 消息类型:更新vxe table数据 | |||||
| */ | |||||
| public static final String TYPE_UVT = "update_vxe_table"; | |||||
| } | |||||
| @ -0,0 +1,66 @@ | |||||
| package org.jeecg.common.constant; | |||||
| /** | |||||
| * @Description: Websocket常量类 | |||||
| * @author: taoyan | |||||
| * @date: 2020年03月23日 | |||||
| */ | |||||
| public class WebsocketConst { | |||||
| /** | |||||
| * 消息json key:cmd | |||||
| */ | |||||
| public static final String MSG_CMD = "cmd"; | |||||
| /** | |||||
| * 消息json key:msgId | |||||
| */ | |||||
| public static final String MSG_ID = "msgId"; | |||||
| /** | |||||
| * 消息json key:msgTxt | |||||
| */ | |||||
| public static final String MSG_TXT = "msgTxt"; | |||||
| /** | |||||
| * 消息json key:userId | |||||
| */ | |||||
| public static final String MSG_USER_ID = "userId"; | |||||
| /** | |||||
| * 消息json key:chat | |||||
| */ | |||||
| public static final String MSG_CHAT = "chat"; | |||||
| /** | |||||
| * 消息类型 heartcheck | |||||
| */ | |||||
| public static final String CMD_CHECK = "heartcheck"; | |||||
| /** | |||||
| * 消息类型 user 用户消息 | |||||
| */ | |||||
| public static final String CMD_USER = "user"; | |||||
| /** | |||||
| * 消息类型 topic 系统通知 | |||||
| */ | |||||
| public static final String CMD_TOPIC = "topic"; | |||||
| /** | |||||
| * 消息类型 email | |||||
| */ | |||||
| public static final String CMD_EMAIL = "email"; | |||||
| /** | |||||
| * 消息类型 meetingsign 会议签到 | |||||
| */ | |||||
| public static final String CMD_SIGN = "sign"; | |||||
| /** | |||||
| * 消息类型 新闻发布/取消 | |||||
| */ | |||||
| public static final String NEWS_PUBLISH = "publish"; | |||||
| } | |||||
| @ -0,0 +1,167 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import java.util.ArrayList; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * online表单枚举 代码生成器用到 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public enum CgformEnum { | |||||
| /** | |||||
| * 单表 | |||||
| */ | |||||
| ONE(1, "one", "/jeecg/code-template-online", "default.one", "经典风格", new String[]{"vue3","vue","vue3Native"}), | |||||
| /** | |||||
| * 多表 | |||||
| */ | |||||
| MANY(2, "many", "/jeecg/code-template-online", "default.onetomany", "经典风格" ,new String[]{"vue"}), | |||||
| /** | |||||
| * 多表(jvxe风格) | |||||
| * */ | |||||
| JVXE_TABLE(2, "jvxe", "/jeecg/code-template-online", "jvxe.onetomany", "默认风格" ,new String[]{"vue3","vue","vue3Native"}), | |||||
| /** | |||||
| * 多表 (erp风格) | |||||
| */ | |||||
| ERP(2, "erp", "/jeecg/code-template-online", "erp.onetomany", "ERP风格" ,new String[]{"vue3","vue","vue3Native"}), | |||||
| /** | |||||
| * 多表(内嵌子表风格) | |||||
| */ | |||||
| INNER_TABLE(2, "innerTable", "/jeecg/code-template-online", "inner-table.onetomany", "内嵌子表风格" ,new String[]{"vue3","vue"}), | |||||
| /** | |||||
| * 多表(tab风格) | |||||
| * */ | |||||
| TAB(2, "tab", "/jeecg/code-template-online", "tab.onetomany", "Tab风格" ,new String[]{"vue3","vue"}), | |||||
| /** | |||||
| * 树形列表 | |||||
| */ | |||||
| TREE(3, "tree", "/jeecg/code-template-online", "default.tree", "树形列表" ,new String[]{"vue3","vue","vue3Native"}); | |||||
| /** | |||||
| * 类型 1/单表 2/一对多 3/树 | |||||
| */ | |||||
| int type; | |||||
| /** | |||||
| * 编码标识 | |||||
| */ | |||||
| String code; | |||||
| /** | |||||
| * 代码生成器模板路径 | |||||
| */ | |||||
| String templatePath; | |||||
| /** | |||||
| * 代码生成器模板路径 | |||||
| */ | |||||
| String stylePath; | |||||
| /** | |||||
| * 模板风格名称 | |||||
| */ | |||||
| String note; | |||||
| /** | |||||
| * 支持代码风格 vue3:vue3包装代码 vue3Native:vue3原生代码 vue:vue2代码 | |||||
| */ | |||||
| String[] vueStyle; | |||||
| /** | |||||
| * 构造器 | |||||
| * | |||||
| * @param type 类型 1/单表 2/一对多 3/树 | |||||
| * @param code 模板编码 | |||||
| * @param templatePath 模板路径 | |||||
| * @param stylePath 模板子路径 | |||||
| * @param note | |||||
| * @param vueStyle 支持代码风格 | |||||
| */ | |||||
| CgformEnum(int type, String code, String templatePath, String stylePath, String note, String[] vueStyle) { | |||||
| this.type = type; | |||||
| this.code = code; | |||||
| this.templatePath = templatePath; | |||||
| this.stylePath = stylePath; | |||||
| this.note = note; | |||||
| this.vueStyle = vueStyle; | |||||
| } | |||||
| /** | |||||
| * 根据code获取模板路径 | |||||
| * | |||||
| * @param code | |||||
| * @return | |||||
| */ | |||||
| public static String getTemplatePathByConfig(String code) { | |||||
| return getCgformEnumByConfig(code).templatePath; | |||||
| } | |||||
| public int getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(int type) { | |||||
| this.type = type; | |||||
| } | |||||
| public String getTemplatePath() { | |||||
| return templatePath; | |||||
| } | |||||
| public void setTemplatePath(String templatePath) { | |||||
| this.templatePath = templatePath; | |||||
| } | |||||
| public String getStylePath() { | |||||
| return stylePath; | |||||
| } | |||||
| public void setStylePath(String stylePath) { | |||||
| this.stylePath = stylePath; | |||||
| } | |||||
| public String[] getVueStyle() { | |||||
| return vueStyle; | |||||
| } | |||||
| public void setVueStyle(String[] vueStyle) { | |||||
| this.vueStyle = vueStyle; | |||||
| } | |||||
| /** | |||||
| * 根据code找枚举 | |||||
| * | |||||
| * @param code | |||||
| * @return | |||||
| */ | |||||
| public static CgformEnum getCgformEnumByConfig(String code) { | |||||
| for (CgformEnum e : CgformEnum.values()) { | |||||
| if (e.code.equals(code)) { | |||||
| return e; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * 根据类型找所有 | |||||
| * | |||||
| * @param type | |||||
| * @return | |||||
| */ | |||||
| public static List<Map<String, Object>> getJspModelList(int type) { | |||||
| List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>(); | |||||
| for (CgformEnum e : CgformEnum.values()) { | |||||
| if (e.type == type) { | |||||
| Map<String, Object> map = new HashMap<String, Object>(); | |||||
| map.put("code", e.code); | |||||
| map.put("note", e.note); | |||||
| ls.add(map); | |||||
| } | |||||
| } | |||||
| return ls; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| /** | |||||
| * 客户终端类型 | |||||
| */ | |||||
| public enum ClientTerminalTypeEnum { | |||||
| PC("pc", "电脑终端"), | |||||
| H5("h5", "移动网页端"), | |||||
| APP("app", "手机app端"); | |||||
| private String key; | |||||
| private String text; | |||||
| ClientTerminalTypeEnum(String value, String text) { | |||||
| this.key = value; | |||||
| this.text = text; | |||||
| } | |||||
| public String getKey() { | |||||
| return this.key; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,27 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| /** | |||||
| * 日期预设范围枚举 | |||||
| */ | |||||
| public enum DateRangeEnum { | |||||
| // 今天 | |||||
| TODAY, | |||||
| // 昨天 | |||||
| YESTERDAY, | |||||
| // 明天 | |||||
| TOMORROW, | |||||
| // 本周 | |||||
| THIS_WEEK, | |||||
| // 上周 | |||||
| LAST_WEEK, | |||||
| // 下周 | |||||
| NEXT_WEEK, | |||||
| // 过去七天 | |||||
| LAST_7_DAYS, | |||||
| // 本月 | |||||
| THIS_MONTH, | |||||
| // 上月 | |||||
| LAST_MONTH, | |||||
| // 下月 | |||||
| NEXT_MONTH, | |||||
| } | |||||
| @ -0,0 +1,75 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| /** | |||||
| * @Description: 短信枚举类 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public enum DySmsEnum { | |||||
| /**登录短信模板编码*/ | |||||
| LOGIN_TEMPLATE_CODE("SMS_175435174","敲敲云","code"), | |||||
| /**忘记密码短信模板编码*/ | |||||
| FORGET_PASSWORD_TEMPLATE_CODE("SMS_175435174","敲敲云","code"), | |||||
| /**修改密码短信模板编码*/ | |||||
| CHANGE_PASSWORD_TEMPLATE_CODE("SMS_465391221","敲敲云","code"), | |||||
| /**注册账号短信模板编码*/ | |||||
| REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code"); | |||||
| /** | |||||
| * 短信模板编码 | |||||
| */ | |||||
| private String templateCode; | |||||
| /** | |||||
| * 签名 | |||||
| */ | |||||
| private String signName; | |||||
| /** | |||||
| * 短信模板必需的数据名称,多个key以逗号分隔,此处配置作为校验 | |||||
| */ | |||||
| private String keys; | |||||
| private DySmsEnum(String templateCode,String signName,String keys) { | |||||
| this.templateCode = templateCode; | |||||
| this.signName = signName; | |||||
| this.keys = keys; | |||||
| } | |||||
| public String getTemplateCode() { | |||||
| return templateCode; | |||||
| } | |||||
| public void setTemplateCode(String templateCode) { | |||||
| this.templateCode = templateCode; | |||||
| } | |||||
| public String getSignName() { | |||||
| return signName; | |||||
| } | |||||
| public void setSignName(String signName) { | |||||
| this.signName = signName; | |||||
| } | |||||
| public String getKeys() { | |||||
| return keys; | |||||
| } | |||||
| public void setKeys(String keys) { | |||||
| this.keys = keys; | |||||
| } | |||||
| public static DySmsEnum toEnum(String templateCode) { | |||||
| if(StringUtils.isEmpty(templateCode)){ | |||||
| return null; | |||||
| } | |||||
| for(DySmsEnum item : DySmsEnum.values()) { | |||||
| if(item.getTemplateCode().equals(templateCode)) { | |||||
| return item; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,66 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * 邮件html模板配置地址美剧 | |||||
| * | |||||
| * @author: liusq | |||||
| * @Date: 2023-10-13 | |||||
| */ | |||||
| public enum EmailTemplateEnum { | |||||
| /** | |||||
| * 流程催办 | |||||
| */ | |||||
| BPM_CUIBAN_EMAIL("bpm_cuiban_email", "/templates/email/bpm_cuiban_email.ftl"), | |||||
| /** | |||||
| * 流程新任务 | |||||
| */ | |||||
| BPM_NEW_TASK_EMAIL("bpm_new_task_email", "/templates/email/bpm_new_task_email.ftl"), | |||||
| /** | |||||
| * 表单新增记录 | |||||
| */ | |||||
| DESFORM_NEW_DATA_EMAIL("desform_new_data_email", "/templates/email/desform_new_data_email.ftl"); | |||||
| /** | |||||
| * 模板名称 | |||||
| */ | |||||
| private String name; | |||||
| /** | |||||
| * 模板地址 | |||||
| */ | |||||
| private String url; | |||||
| EmailTemplateEnum(String name, String url) { | |||||
| this.name = name; | |||||
| this.url = url; | |||||
| } | |||||
| public String getName() { | |||||
| return name; | |||||
| } | |||||
| public void setName(String name) { | |||||
| this.name = name; | |||||
| } | |||||
| public String getUrl() { | |||||
| return url; | |||||
| } | |||||
| public void setUrl(String url) { | |||||
| this.url = url; | |||||
| } | |||||
| public static EmailTemplateEnum getByName(String name) { | |||||
| if (oConvertUtils.isEmpty(name)) { | |||||
| return null; | |||||
| } | |||||
| for (EmailTemplateEnum val : values()) { | |||||
| if (val.getName().equals(name)) { | |||||
| return val; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,76 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * 文件类型 | |||||
| */ | |||||
| public enum FileTypeEnum { | |||||
| // 文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频 voice:语音) | |||||
| // FOLDER | |||||
| xls(".xls","excel","excel"), | |||||
| xlsx(".xlsx","excel","excel"), | |||||
| doc(".doc","doc","word"), | |||||
| docx(".docx","doc","word"), | |||||
| ppt(".ppt","pp","ppt"), | |||||
| pptx(".pptx","pp","ppt"), | |||||
| gif(".gif","image","图片"), | |||||
| jpg(".jpg","image","图片"), | |||||
| jpeg(".jpeg","image","图片"), | |||||
| png(".png","image","图片"), | |||||
| txt(".txt","text","文本"), | |||||
| avi(".avi","video","视频"), | |||||
| mov(".mov","video","视频"), | |||||
| rmvb(".rmvb","video","视频"), | |||||
| rm(".rm","video","视频"), | |||||
| flv(".flv","video","视频"), | |||||
| mp4(".mp4","video","视频"), | |||||
| zip(".zip","zip","压缩包"), | |||||
| pdf(".pdf","pdf","pdf"), | |||||
| mp3(".mp3","mp3","语音"); | |||||
| private String type; | |||||
| private String value; | |||||
| private String text; | |||||
| private FileTypeEnum(String type,String value,String text){ | |||||
| this.type = type; | |||||
| this.value = value; | |||||
| this.text = text; | |||||
| } | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(String type) { | |||||
| this.type = type; | |||||
| } | |||||
| public String getValue() { | |||||
| return value; | |||||
| } | |||||
| public void setValue(String value) { | |||||
| this.value = value; | |||||
| } | |||||
| public String getText() { | |||||
| return text; | |||||
| } | |||||
| public void setText(String text) { | |||||
| this.text = text; | |||||
| } | |||||
| public static FileTypeEnum getByType(String type){ | |||||
| if (oConvertUtils.isEmpty(type)) { | |||||
| return null; | |||||
| } | |||||
| for (FileTypeEnum val : values()) { | |||||
| if (val.getType().equals(type)) { | |||||
| return val; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,88 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.system.annotation.EnumDict; | |||||
| import org.jeecg.common.system.vo.DictModel; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 消息类型 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @EnumDict("messageType") | |||||
| public enum MessageTypeEnum { | |||||
| /** 系统消息 */ | |||||
| XT("system", "系统消息"), | |||||
| /** 邮件消息 */ | |||||
| YJ("email", "邮件消息"), | |||||
| /** 钉钉消息 */ | |||||
| DD("dingtalk", "钉钉消息"), | |||||
| /** 企业微信 */ | |||||
| QYWX("wechat_enterprise", "企业微信"); | |||||
| MessageTypeEnum(String type, String note){ | |||||
| this.type = type; | |||||
| this.note = note; | |||||
| } | |||||
| /** | |||||
| * 消息类型 | |||||
| */ | |||||
| String type; | |||||
| /** | |||||
| * 类型说明 | |||||
| */ | |||||
| String note; | |||||
| public String getNote() { | |||||
| return note; | |||||
| } | |||||
| public void setNote(String note) { | |||||
| this.note = note; | |||||
| } | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(String type) { | |||||
| this.type = type; | |||||
| } | |||||
| /** | |||||
| * 获取字典数据 | |||||
| * @return | |||||
| */ | |||||
| public static List<DictModel> getDictList(){ | |||||
| List<DictModel> list = new ArrayList<>(); | |||||
| DictModel dictModel = null; | |||||
| for(MessageTypeEnum e: MessageTypeEnum.values()){ | |||||
| dictModel = new DictModel(); | |||||
| dictModel.setValue(e.getType()); | |||||
| dictModel.setText(e.getNote()); | |||||
| list.add(dictModel); | |||||
| } | |||||
| return list; | |||||
| } | |||||
| /** | |||||
| * 根据type获取枚举 | |||||
| * | |||||
| * @param type | |||||
| * @return | |||||
| */ | |||||
| public static MessageTypeEnum valueOfType(String type) { | |||||
| for (MessageTypeEnum e : MessageTypeEnum.values()) { | |||||
| if (e.getType().equals(type)) { | |||||
| return e; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,18 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| /** | |||||
| * 日志按模块分类 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public enum ModuleType { | |||||
| /** | |||||
| * 普通 | |||||
| */ | |||||
| COMMON, | |||||
| /** | |||||
| * online | |||||
| */ | |||||
| ONLINE; | |||||
| } | |||||
| @ -0,0 +1,95 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| /** | |||||
| * @Description: 操作类型 | |||||
| * @author: jeecg-boot | |||||
| * @date: 2022/3/31 10:05 | |||||
| */ | |||||
| public enum OperateTypeEnum { | |||||
| /** | |||||
| * 列表 | |||||
| */ | |||||
| LIST(CommonConstant.OPERATE_TYPE_1, "list"), | |||||
| /** | |||||
| * 新增 | |||||
| */ | |||||
| ADD(CommonConstant.OPERATE_TYPE_2, "add"), | |||||
| /** | |||||
| * 编辑 | |||||
| */ | |||||
| EDIT(CommonConstant.OPERATE_TYPE_3, "edit"), | |||||
| /** | |||||
| * 删除 | |||||
| */ | |||||
| DELETE(CommonConstant.OPERATE_TYPE_4, "delete"), | |||||
| /** | |||||
| * 导入 | |||||
| */ | |||||
| IMPORT(CommonConstant.OPERATE_TYPE_5, "import"), | |||||
| /** | |||||
| * 导出 | |||||
| */ | |||||
| EXPORT(CommonConstant.OPERATE_TYPE_6, "export"); | |||||
| /** | |||||
| * 类型 1列表,2新增,3编辑,4删除,5导入,6导出 | |||||
| */ | |||||
| int type; | |||||
| /** | |||||
| * 编码(请求方式) | |||||
| */ | |||||
| String code; | |||||
| public int getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(int type) { | |||||
| this.type = type; | |||||
| } | |||||
| public String getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(String code) { | |||||
| this.code = code; | |||||
| } | |||||
| /** | |||||
| * 构造器 | |||||
| * | |||||
| * @param type 类型 | |||||
| * @param code 编码(请求方式) | |||||
| */ | |||||
| OperateTypeEnum(int type, String code) { | |||||
| this.type = type; | |||||
| this.code = code; | |||||
| } | |||||
| /** | |||||
| * 根据请求名称匹配 | |||||
| * | |||||
| * @param methodName 请求名称 | |||||
| * @return Integer 类型 | |||||
| */ | |||||
| public static Integer getTypeByMethodName(String methodName) { | |||||
| for (OperateTypeEnum e : OperateTypeEnum.values()) { | |||||
| if (methodName.startsWith(e.getCode())) { | |||||
| return e.getType(); | |||||
| } | |||||
| } | |||||
| return CommonConstant.OPERATE_TYPE_1; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,97 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 首页自定义 | |||||
| * 通过角色编码与首页组件路径配置 | |||||
| * 枚举的顺序有权限高低权重作用(也就是配置多个角色,在前面的角色首页,会优先生效) | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public enum RoleIndexConfigEnum { | |||||
| /**首页自定义 admin*/ | |||||
| // ADMIN("admin", "dashboard/Analysis"), | |||||
| //TEST("test", "dashboard/IndexChart"), | |||||
| /**首页自定义 hr*/ | |||||
| // HR("hr", "dashboard/IndexBdc"); | |||||
| //DM("dm", "dashboard/IndexTask"), | |||||
| // 注:此值仅为防止报错,无任何实际意义 | |||||
| ROLE_INDEX_CONFIG_ENUM("RoleIndexConfigEnumDefault", "dashboard/Analysis"); | |||||
| /** | |||||
| * 角色编码 | |||||
| */ | |||||
| String roleCode; | |||||
| /** | |||||
| * 路由index | |||||
| */ | |||||
| String componentUrl; | |||||
| /** | |||||
| * 构造器 | |||||
| * | |||||
| * @param roleCode 角色编码 | |||||
| * @param componentUrl 首页组件路径(规则跟菜单配置一样) | |||||
| */ | |||||
| RoleIndexConfigEnum(String roleCode, String componentUrl) { | |||||
| this.roleCode = roleCode; | |||||
| this.componentUrl = componentUrl; | |||||
| } | |||||
| /** | |||||
| * 根据code找枚举 | |||||
| * @param roleCode 角色编码 | |||||
| * @return | |||||
| */ | |||||
| private static RoleIndexConfigEnum getEnumByCode(String roleCode) { | |||||
| for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) { | |||||
| if (e.roleCode.equals(roleCode)) { | |||||
| return e; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * 根据code找index | |||||
| * @param roleCode 角色编码 | |||||
| * @return | |||||
| */ | |||||
| private static String getIndexByCode(String roleCode) { | |||||
| for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) { | |||||
| if (e.roleCode.equals(roleCode)) { | |||||
| return e.componentUrl; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public static String getIndexByRoles(List<String> roles) { | |||||
| String[] rolesArray = roles.toArray(new String[roles.size()]); | |||||
| for (RoleIndexConfigEnum e : RoleIndexConfigEnum.values()) { | |||||
| if (oConvertUtils.isIn(e.roleCode,rolesArray)){ | |||||
| return e.componentUrl; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public String getRoleCode() { | |||||
| return roleCode; | |||||
| } | |||||
| public void setRoleCode(String roleCode) { | |||||
| this.roleCode = roleCode; | |||||
| } | |||||
| public String getComponentUrl() { | |||||
| return componentUrl; | |||||
| } | |||||
| public void setComponentUrl(String componentUrl) { | |||||
| this.componentUrl = componentUrl; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,82 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * 系统公告自定义跳转方式 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public enum SysAnnmentTypeEnum { | |||||
| /** | |||||
| * 邮件跳转组件 | |||||
| */ | |||||
| EMAIL("email", "component", "modules/eoa/email/modals/EoaEmailInForm"), | |||||
| /** | |||||
| * 流程跳转到我的任务 | |||||
| */ | |||||
| BPM("bpm", "url", "/bpm/task/MyTaskList"), | |||||
| /** | |||||
| * 流程抄送任务 | |||||
| */ | |||||
| BPM_VIEW("bpm_cc", "url", "/bpm/task/MyTaskList"), | |||||
| /** | |||||
| * 邀请用户跳转到个人设置 | |||||
| */ | |||||
| TENANT_INVITE("tenant_invite", "url", "/system/usersetting"); | |||||
| /** | |||||
| * 业务类型(email:邮件 bpm:流程) | |||||
| */ | |||||
| private String type; | |||||
| /** | |||||
| * 打开方式 组件:component 路由:url | |||||
| */ | |||||
| private String openType; | |||||
| /** | |||||
| * 组件/路由 地址 | |||||
| */ | |||||
| private String openPage; | |||||
| SysAnnmentTypeEnum(String type, String openType, String openPage) { | |||||
| this.type = type; | |||||
| this.openType = openType; | |||||
| this.openPage = openPage; | |||||
| } | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(String type) { | |||||
| this.type = type; | |||||
| } | |||||
| public String getOpenType() { | |||||
| return openType; | |||||
| } | |||||
| public void setOpenType(String openType) { | |||||
| this.openType = openType; | |||||
| } | |||||
| public String getOpenPage() { | |||||
| return openPage; | |||||
| } | |||||
| public void setOpenPage(String openPage) { | |||||
| this.openPage = openPage; | |||||
| } | |||||
| public static SysAnnmentTypeEnum getByType(String type) { | |||||
| if (oConvertUtils.isEmpty(type)) { | |||||
| return null; | |||||
| } | |||||
| for (SysAnnmentTypeEnum val : values()) { | |||||
| if (val.getType().equals(type)) { | |||||
| return val; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,75 @@ | |||||
| package org.jeecg.common.constant.enums; | |||||
| import org.jeecg.common.system.annotation.EnumDict; | |||||
| import org.jeecg.common.system.vo.DictModel; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 消息跳转【vue3】 | |||||
| * @Author taoYan | |||||
| * @Date 2022/8/19 20:41 | |||||
| **/ | |||||
| @EnumDict("messageHref") | |||||
| public enum Vue3MessageHrefEnum { | |||||
| /** | |||||
| * 流程催办 | |||||
| */ | |||||
| BPM("bpm", "/task/myHandleTaskInfo"), | |||||
| /** | |||||
| * 系统消息通知 | |||||
| */ | |||||
| BPM_SYSTEM_MSG("bpm_msg_node", ""), | |||||
| /** | |||||
| * 流程抄送任务 | |||||
| */ | |||||
| BPM_VIEW("bpm_cc", "/task/myHandleTaskInfo"), | |||||
| /** | |||||
| * 节点通知 | |||||
| */ | |||||
| BPM_TASK("bpm_task", "/task/myHandleTaskInfo"), | |||||
| /** | |||||
| * 邮件消息 | |||||
| */ | |||||
| EMAIL("email", "/eoa/email"); | |||||
| String busType; | |||||
| String path; | |||||
| Vue3MessageHrefEnum(String busType, String path) { | |||||
| this.busType = busType; | |||||
| this.path = path; | |||||
| } | |||||
| public String getBusType() { | |||||
| return busType; | |||||
| } | |||||
| public String getPath() { | |||||
| return path; | |||||
| } | |||||
| /** | |||||
| * 获取字典数据 | |||||
| * @return | |||||
| */ | |||||
| public static List<DictModel> getDictList(){ | |||||
| List<DictModel> list = new ArrayList<>(); | |||||
| DictModel dictModel = null; | |||||
| for(Vue3MessageHrefEnum e: Vue3MessageHrefEnum.values()){ | |||||
| dictModel = new DictModel(); | |||||
| dictModel.setValue(e.getBusType()); | |||||
| dictModel.setText(e.getPath()); | |||||
| list.add(dictModel); | |||||
| } | |||||
| return list; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,87 @@ | |||||
| package org.jeecg.common.desensitization; | |||||
| import com.fasterxml.jackson.core.JsonGenerator; | |||||
| import com.fasterxml.jackson.databind.BeanProperty; | |||||
| import com.fasterxml.jackson.databind.JsonMappingException; | |||||
| import com.fasterxml.jackson.databind.JsonSerializer; | |||||
| import com.fasterxml.jackson.databind.SerializerProvider; | |||||
| import com.fasterxml.jackson.databind.ser.ContextualSerializer; | |||||
| import lombok.AllArgsConstructor; | |||||
| import lombok.NoArgsConstructor; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.jeecg.common.desensitization.annotation.Sensitive; | |||||
| import org.jeecg.common.desensitization.enums.SensitiveEnum; | |||||
| import org.jeecg.common.desensitization.util.SensitiveInfoUtil; | |||||
| import org.jeecg.common.util.encryption.AesEncryptUtil; | |||||
| import java.io.IOException; | |||||
| import java.util.Objects; | |||||
| /** | |||||
| * @author eightmonth@qq.com | |||||
| * @date 2024/6/19 10:43 | |||||
| */ | |||||
| @NoArgsConstructor | |||||
| @AllArgsConstructor | |||||
| @Slf4j | |||||
| public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer { | |||||
| private SensitiveEnum type; | |||||
| @Override | |||||
| public void serialize(String data, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { | |||||
| switch (type){ | |||||
| case ENCODE: | |||||
| try { | |||||
| jsonGenerator.writeString(AesEncryptUtil.encrypt(data)); | |||||
| } catch (Exception exception) { | |||||
| log.error("数据加密错误", exception.getMessage()); | |||||
| jsonGenerator.writeString(data); | |||||
| } | |||||
| break; | |||||
| case CHINESE_NAME: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.chineseName(data)); | |||||
| break; | |||||
| case ID_CARD: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.idCardNum(data)); | |||||
| break; | |||||
| case FIXED_PHONE: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.fixedPhone(data)); | |||||
| break; | |||||
| case MOBILE_PHONE: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.mobilePhone(data)); | |||||
| break; | |||||
| case ADDRESS: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.address(data, 3)); | |||||
| break; | |||||
| case EMAIL: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.email(data)); | |||||
| break; | |||||
| case BANK_CARD: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.bankCard(data)); | |||||
| break; | |||||
| case CNAPS_CODE: | |||||
| jsonGenerator.writeString(SensitiveInfoUtil.cnapsCode(data)); | |||||
| break; | |||||
| default: | |||||
| jsonGenerator.writeString(data); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException { | |||||
| if (beanProperty != null) { | |||||
| if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { | |||||
| Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class); | |||||
| if (sensitive == null) { | |||||
| sensitive = beanProperty.getContextAnnotation(Sensitive.class); | |||||
| } | |||||
| if (sensitive != null) { | |||||
| return new SensitiveSerialize(sensitive.type()); | |||||
| } | |||||
| } | |||||
| return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); | |||||
| } | |||||
| return serializerProvider.findNullValueSerializer(null); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,26 @@ | |||||
| package org.jeecg.common.desensitization.annotation; | |||||
| import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonSerialize; | |||||
| import org.jeecg.common.desensitization.SensitiveSerialize; | |||||
| import org.jeecg.common.desensitization.enums.SensitiveEnum; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 在字段上定义 标识字段存储的信息是敏感的 | |||||
| */ | |||||
| @Documented | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target(ElementType.FIELD) | |||||
| @JacksonAnnotationsInside | |||||
| @JsonSerialize(using = SensitiveSerialize.class) | |||||
| public @interface Sensitive { | |||||
| /** | |||||
| * 不同类型处理不同 | |||||
| * @return | |||||
| */ | |||||
| SensitiveEnum type() default SensitiveEnum.ENCODE; | |||||
| } | |||||
| @ -0,0 +1,20 @@ | |||||
| package org.jeecg.common.desensitization.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 解密注解 | |||||
| * | |||||
| * 在方法上定义 将方法返回对象中的敏感字段 解密,需要注意的是,如果没有加密过,解密会出问题,返回原字符串 | |||||
| */ | |||||
| @Documented | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target({ElementType.METHOD}) | |||||
| public @interface SensitiveDecode { | |||||
| /** | |||||
| * 指明需要脱敏的实体类class | |||||
| * @return | |||||
| */ | |||||
| Class entity() default Object.class; | |||||
| } | |||||
| @ -0,0 +1,20 @@ | |||||
| package org.jeecg.common.desensitization.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 加密注解 | |||||
| * | |||||
| * 在方法上声明 将方法返回对象中的敏感字段 加密/格式化 | |||||
| */ | |||||
| @Documented | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target({ElementType.METHOD}) | |||||
| public @interface SensitiveEncode { | |||||
| /** | |||||
| * 指明需要脱敏的实体类class | |||||
| * @return | |||||
| */ | |||||
| Class entity() default Object.class; | |||||
| } | |||||
| @ -0,0 +1,21 @@ | |||||
| package org.jeecg.common.desensitization.annotation; | |||||
| import org.jeecg.common.desensitization.enums.SensitiveEnum; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 在字段上定义 标识字段存储的信息是敏感的 | |||||
| */ | |||||
| @Documented | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Target(ElementType.FIELD) | |||||
| public @interface SensitiveField { | |||||
| /** | |||||
| * 不同类型处理不同 | |||||
| * @return | |||||
| */ | |||||
| SensitiveEnum type() default SensitiveEnum.ENCODE; | |||||
| } | |||||
| @ -0,0 +1,81 @@ | |||||
| package org.jeecg.common.desensitization.aspect; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.aspectj.lang.ProceedingJoinPoint; | |||||
| import org.aspectj.lang.annotation.Around; | |||||
| import org.aspectj.lang.annotation.Aspect; | |||||
| import org.aspectj.lang.annotation.Pointcut; | |||||
| import org.aspectj.lang.reflect.MethodSignature; | |||||
| import org.jeecg.common.desensitization.annotation.SensitiveDecode; | |||||
| import org.jeecg.common.desensitization.annotation.SensitiveEncode; | |||||
| import org.jeecg.common.desensitization.util.SensitiveInfoUtil; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.lang.reflect.Method; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 敏感数据切面处理类 | |||||
| * @Author taoYan | |||||
| * @Date 2022/4/20 17:45 | |||||
| **/ | |||||
| @Slf4j | |||||
| @Aspect | |||||
| @Component | |||||
| public class SensitiveDataAspect { | |||||
| /** | |||||
| * 定义切点Pointcut | |||||
| */ | |||||
| @Pointcut("@annotation(org.jeecg.common.desensitization.annotation.SensitiveEncode) || @annotation(org.jeecg.common.desensitization.annotation.SensitiveDecode)") | |||||
| public void sensitivePointCut() { | |||||
| } | |||||
| @Around("sensitivePointCut()") | |||||
| public Object around(ProceedingJoinPoint point) throws Throwable { | |||||
| // 处理结果 | |||||
| Object result = point.proceed(); | |||||
| if(result == null){ | |||||
| return result; | |||||
| } | |||||
| Class resultClass = result.getClass(); | |||||
| log.debug(" resultClass = {}" , resultClass); | |||||
| if(resultClass.isPrimitive()){ | |||||
| //是基本类型 直接返回 不需要处理 | |||||
| return result; | |||||
| } | |||||
| // 获取方法注解信息:是哪个实体、是加密还是解密 | |||||
| boolean isEncode = true; | |||||
| Class entity = null; | |||||
| MethodSignature methodSignature = (MethodSignature) point.getSignature(); | |||||
| Method method = methodSignature.getMethod(); | |||||
| SensitiveEncode encode = method.getAnnotation(SensitiveEncode.class); | |||||
| if(encode==null){ | |||||
| SensitiveDecode decode = method.getAnnotation(SensitiveDecode.class); | |||||
| if(decode!=null){ | |||||
| entity = decode.entity(); | |||||
| isEncode = false; | |||||
| } | |||||
| }else{ | |||||
| entity = encode.entity(); | |||||
| } | |||||
| long startTime=System.currentTimeMillis(); | |||||
| if(resultClass.equals(entity) || entity.equals(Object.class)){ | |||||
| // 方法返回实体和注解的entity一样,如果注解没有申明entity属性则认为是(方法返回实体和注解的entity一样) | |||||
| SensitiveInfoUtil.handlerObject(result, isEncode); | |||||
| } else if(result instanceof List){ | |||||
| // 方法返回List<实体> | |||||
| SensitiveInfoUtil.handleList(result, entity, isEncode); | |||||
| }else{ | |||||
| // 方法返回一个对象 | |||||
| SensitiveInfoUtil.handleNestedObject(result, entity, isEncode); | |||||
| } | |||||
| long endTime=System.currentTimeMillis(); | |||||
| log.info((isEncode ? "加密操作," : "解密操作,") + "Aspect程序耗时:" + (endTime - startTime) + "ms"); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,55 @@ | |||||
| package org.jeecg.common.desensitization.enums; | |||||
| /** | |||||
| * 敏感字段信息类型 | |||||
| */ | |||||
| public enum SensitiveEnum { | |||||
| /** | |||||
| * 加密 | |||||
| */ | |||||
| ENCODE, | |||||
| /** | |||||
| * 中文名 | |||||
| */ | |||||
| CHINESE_NAME, | |||||
| /** | |||||
| * 身份证号 | |||||
| */ | |||||
| ID_CARD, | |||||
| /** | |||||
| * 座机号 | |||||
| */ | |||||
| FIXED_PHONE, | |||||
| /** | |||||
| * 手机号 | |||||
| */ | |||||
| MOBILE_PHONE, | |||||
| /** | |||||
| * 地址 | |||||
| */ | |||||
| ADDRESS, | |||||
| /** | |||||
| * 电子邮件 | |||||
| */ | |||||
| EMAIL, | |||||
| /** | |||||
| * 银行卡 | |||||
| */ | |||||
| BANK_CARD, | |||||
| /** | |||||
| * 公司开户银行联号 | |||||
| */ | |||||
| CNAPS_CODE; | |||||
| } | |||||
| @ -0,0 +1,363 @@ | |||||
| package org.jeecg.common.desensitization.util; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.jeecg.common.desensitization.annotation.SensitiveField; | |||||
| import org.jeecg.common.desensitization.enums.SensitiveEnum; | |||||
| import org.jeecg.common.util.encryption.AesEncryptUtil; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import java.lang.reflect.Field; | |||||
| import java.lang.reflect.ParameterizedType; | |||||
| import java.util.Collections; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 敏感信息处理工具类 | |||||
| * @author taoYan | |||||
| * @date 2022/4/20 18:01 | |||||
| **/ | |||||
| @Slf4j | |||||
| public class SensitiveInfoUtil { | |||||
| /** | |||||
| * 处理嵌套对象 | |||||
| * @param obj 方法返回值 | |||||
| * @param entity 实体class | |||||
| * @param isEncode 是否加密(true: 加密操作 / false:解密操作) | |||||
| * @throws IllegalAccessException | |||||
| */ | |||||
| public static void handleNestedObject(Object obj, Class entity, boolean isEncode) throws IllegalAccessException { | |||||
| Field[] fields = obj.getClass().getDeclaredFields(); | |||||
| for (Field field : fields) { | |||||
| if(field.getType().isPrimitive()){ | |||||
| continue; | |||||
| } | |||||
| if(field.getType().equals(entity)){ | |||||
| // 对象里面是实体 | |||||
| field.setAccessible(true); | |||||
| Object nestedObject = field.get(obj); | |||||
| handlerObject(nestedObject, isEncode); | |||||
| break; | |||||
| }else{ | |||||
| // 对象里面是List<实体> | |||||
| if(field.getGenericType() instanceof ParameterizedType){ | |||||
| ParameterizedType pt = (ParameterizedType)field.getGenericType(); | |||||
| if(pt.getRawType().equals(List.class)){ | |||||
| if(pt.getActualTypeArguments()[0].equals(entity)){ | |||||
| field.setAccessible(true); | |||||
| Object nestedObject = field.get(obj); | |||||
| handleList(nestedObject, entity, isEncode); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 处理Object | |||||
| * @param obj 方法返回值 | |||||
| * @param isEncode 是否加密(true: 加密操作 / false:解密操作) | |||||
| * @return | |||||
| * @throws IllegalAccessException | |||||
| */ | |||||
| public static Object handlerObject(Object obj, boolean isEncode) throws IllegalAccessException { | |||||
| if (oConvertUtils.isEmpty(obj)) { | |||||
| return obj; | |||||
| } | |||||
| long startTime=System.currentTimeMillis(); | |||||
| log.debug(" obj --> "+ obj.toString()); | |||||
| // 判断是不是一个对象 | |||||
| Field[] fields = obj.getClass().getDeclaredFields(); | |||||
| for (Field field : fields) { | |||||
| boolean isSensitiveField = field.isAnnotationPresent(SensitiveField.class); | |||||
| if(isSensitiveField){ | |||||
| // 必须有SensitiveField注解 才作处理 | |||||
| if(field.getType().isAssignableFrom(String.class)){ | |||||
| //必须是字符串类型 才作处理 | |||||
| field.setAccessible(true); | |||||
| String realValue = (String) field.get(obj); | |||||
| if(realValue==null || "".equals(realValue)){ | |||||
| continue; | |||||
| } | |||||
| SensitiveField sf = field.getAnnotation(SensitiveField.class); | |||||
| if(isEncode==true){ | |||||
| //加密 | |||||
| String value = SensitiveInfoUtil.getEncodeData(realValue, sf.type()); | |||||
| field.set(obj, value); | |||||
| }else{ | |||||
| //解密只处理 encode类型的 | |||||
| if(sf.type().equals(SensitiveEnum.ENCODE)){ | |||||
| String value = SensitiveInfoUtil.getDecodeData(realValue); | |||||
| field.set(obj, value); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| //long endTime=System.currentTimeMillis(); | |||||
| //log.info((isEncode ? "加密操作," : "解密操作,") + "当前程序耗时:" + (endTime - startTime) + "ms"); | |||||
| return obj; | |||||
| } | |||||
| /** | |||||
| * 处理 List<实体> | |||||
| * @param obj | |||||
| * @param entity | |||||
| * @param isEncode(true: 加密操作 / false:解密操作) | |||||
| */ | |||||
| public static void handleList(Object obj, Class entity, boolean isEncode){ | |||||
| List list = (List)obj; | |||||
| if(list.size()>0){ | |||||
| Object first = list.get(0); | |||||
| if(first.getClass().equals(entity)){ | |||||
| for(int i=0; i<list.size(); i++){ | |||||
| Object temp = list.get(i); | |||||
| try { | |||||
| handlerObject(temp, isEncode); | |||||
| } catch (IllegalAccessException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 处理数据 获取解密后的数据 | |||||
| * @param data | |||||
| * @return | |||||
| */ | |||||
| public static String getDecodeData(String data){ | |||||
| String result = null; | |||||
| try { | |||||
| result = AesEncryptUtil.desEncrypt(data); | |||||
| } catch (Exception exception) { | |||||
| log.debug("数据解密错误,原数据:"+data); | |||||
| } | |||||
| //解决debug模式下,加解密失效导致中文被解密变成空的问题 | |||||
| if(oConvertUtils.isEmpty(result) && oConvertUtils.isNotEmpty(data)){ | |||||
| result = data; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 处理数据 获取加密后的数据 或是格式化后的数据 | |||||
| * @param data 字符串 | |||||
| * @param sensitiveEnum 类型 | |||||
| * @return 处理后的字符串 | |||||
| */ | |||||
| public static String getEncodeData(String data, SensitiveEnum sensitiveEnum){ | |||||
| String result; | |||||
| switch (sensitiveEnum){ | |||||
| case ENCODE: | |||||
| try { | |||||
| result = AesEncryptUtil.encrypt(data); | |||||
| } catch (Exception exception) { | |||||
| log.error("数据加密错误", exception.getMessage()); | |||||
| result = data; | |||||
| } | |||||
| break; | |||||
| case CHINESE_NAME: | |||||
| result = chineseName(data); | |||||
| break; | |||||
| case ID_CARD: | |||||
| result = idCardNum(data); | |||||
| break; | |||||
| case FIXED_PHONE: | |||||
| result = fixedPhone(data); | |||||
| break; | |||||
| case MOBILE_PHONE: | |||||
| result = mobilePhone(data); | |||||
| break; | |||||
| case ADDRESS: | |||||
| result = address(data, 3); | |||||
| break; | |||||
| case EMAIL: | |||||
| result = email(data); | |||||
| break; | |||||
| case BANK_CARD: | |||||
| result = bankCard(data); | |||||
| break; | |||||
| case CNAPS_CODE: | |||||
| result = cnapsCode(data); | |||||
| break; | |||||
| default: | |||||
| result = data; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号 | |||||
| * @param fullName 全名 | |||||
| * @return <例子:李**> | |||||
| */ | |||||
| public static String chineseName(String fullName) { | |||||
| if (oConvertUtils.isEmpty(fullName)) { | |||||
| return ""; | |||||
| } | |||||
| return formatRight(fullName, 1); | |||||
| } | |||||
| /** | |||||
| * [中文姓名] 只显示第一个汉字,其他隐藏为2个星号 | |||||
| * @param familyName 姓 | |||||
| * @param firstName 名 | |||||
| * @return <例子:李**> | |||||
| */ | |||||
| public static String chineseName(String familyName, String firstName) { | |||||
| if (oConvertUtils.isEmpty(familyName) || oConvertUtils.isEmpty(firstName)) { | |||||
| return ""; | |||||
| } | |||||
| return chineseName(familyName + firstName); | |||||
| } | |||||
| /** | |||||
| * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。 | |||||
| * @param id 身份证号 | |||||
| * @return <例子:*************5762> | |||||
| */ | |||||
| public static String idCardNum(String id) { | |||||
| if (oConvertUtils.isEmpty(id)) { | |||||
| return ""; | |||||
| } | |||||
| return formatLeft(id, 4); | |||||
| } | |||||
| /** | |||||
| * [固定电话] 后四位,其他隐藏 | |||||
| * @param num 固定电话 | |||||
| * @return <例子:****1234> | |||||
| */ | |||||
| public static String fixedPhone(String num) { | |||||
| if (oConvertUtils.isEmpty(num)) { | |||||
| return ""; | |||||
| } | |||||
| return formatLeft(num, 4); | |||||
| } | |||||
| /** | |||||
| * [手机号码] 前三位,后四位,其他隐藏 | |||||
| * @param num 手机号码 | |||||
| * @return <例子:138******1234> | |||||
| */ | |||||
| public static String mobilePhone(String num) { | |||||
| if (oConvertUtils.isEmpty(num)) { | |||||
| return ""; | |||||
| } | |||||
| int len = num.length(); | |||||
| if(len<11){ | |||||
| return num; | |||||
| } | |||||
| return formatBetween(num, 3, 4); | |||||
| } | |||||
| /** | |||||
| * [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护 | |||||
| * @param address 地址 | |||||
| * @param sensitiveSize 敏感信息长度 | |||||
| * @return <例子:北京市海淀区****> | |||||
| */ | |||||
| public static String address(String address, int sensitiveSize) { | |||||
| if (oConvertUtils.isEmpty(address)) { | |||||
| return ""; | |||||
| } | |||||
| int len = address.length(); | |||||
| if(len<sensitiveSize){ | |||||
| return address; | |||||
| } | |||||
| return formatRight(address, sensitiveSize); | |||||
| } | |||||
| /** | |||||
| * [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示 | |||||
| * @param email 电子邮箱 | |||||
| * @return <例子:g**@163.com> | |||||
| */ | |||||
| public static String email(String email) { | |||||
| if (oConvertUtils.isEmpty(email)) { | |||||
| return ""; | |||||
| } | |||||
| int index = email.indexOf("@"); | |||||
| if (index <= 1){ | |||||
| return email; | |||||
| } | |||||
| String begin = email.substring(0, 1); | |||||
| String end = email.substring(index); | |||||
| String stars = "**"; | |||||
| return begin + stars + end; | |||||
| } | |||||
| /** | |||||
| * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号 | |||||
| * @param cardNum 银行卡号 | |||||
| * @return <例子:6222600**********1234> | |||||
| */ | |||||
| public static String bankCard(String cardNum) { | |||||
| if (oConvertUtils.isEmpty(cardNum)) { | |||||
| return ""; | |||||
| } | |||||
| return formatBetween(cardNum, 6, 4); | |||||
| } | |||||
| /** | |||||
| * [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号 | |||||
| * @param code 公司开户银行联号 | |||||
| * @return <例子:12********> | |||||
| */ | |||||
| public static String cnapsCode(String code) { | |||||
| if (oConvertUtils.isEmpty(code)) { | |||||
| return ""; | |||||
| } | |||||
| return formatRight(code, 2); | |||||
| } | |||||
| /** | |||||
| * 将右边的格式化成* | |||||
| * @param str 字符串 | |||||
| * @param reservedLength 保留长度 | |||||
| * @return 格式化后的字符串 | |||||
| */ | |||||
| public static String formatRight(String str, int reservedLength){ | |||||
| String name = str.substring(0, reservedLength); | |||||
| String stars = String.join("", Collections.nCopies(str.length()-reservedLength, "*")); | |||||
| return name + stars; | |||||
| } | |||||
| /** | |||||
| * 将左边的格式化成* | |||||
| * @param str 字符串 | |||||
| * @param reservedLength 保留长度 | |||||
| * @return 格式化后的字符串 | |||||
| */ | |||||
| public static String formatLeft(String str, int reservedLength){ | |||||
| int len = str.length(); | |||||
| String show = str.substring(len-reservedLength); | |||||
| String stars = String.join("", Collections.nCopies(len-reservedLength, "*")); | |||||
| return stars + show; | |||||
| } | |||||
| /** | |||||
| * 将中间的格式化成* | |||||
| * @param str 字符串 | |||||
| * @param beginLen 开始保留长度 | |||||
| * @param endLen 结尾保留长度 | |||||
| * @return 格式化后的字符串 | |||||
| */ | |||||
| public static String formatBetween(String str, int beginLen, int endLen){ | |||||
| int len = str.length(); | |||||
| String begin = str.substring(0, beginLen); | |||||
| String end = str.substring(len-endLen); | |||||
| String stars = String.join("", Collections.nCopies(len-beginLen-endLen, "*")); | |||||
| return begin + stars + end; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,546 @@ | |||||
| package org.jeecg.common.es; | |||||
| import com.alibaba.fastjson.JSONArray; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.jeecg.common.util.RestUtil; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |||||
| import org.springframework.http.HttpHeaders; | |||||
| import org.springframework.http.HttpMethod; | |||||
| import org.springframework.http.HttpStatus; | |||||
| import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.util.*; | |||||
| /** | |||||
| * 关于 ElasticSearch 的一些方法(创建索引、添加数据、查询等) | |||||
| * | |||||
| * @author sunjianlei | |||||
| */ | |||||
| @Slf4j | |||||
| @Component | |||||
| @ConditionalOnProperty(prefix = "jeecg.elasticsearch", name = "cluster-nodes") | |||||
| public class JeecgElasticsearchTemplate { | |||||
| /** es服务地址 */ | |||||
| private String baseUrl; | |||||
| private final String FORMAT_JSON = "format=json"; | |||||
| /** Elasticsearch 的版本号 */ | |||||
| private String version = null; | |||||
| /**ElasticSearch 最大可返回条目数*/ | |||||
| public static final int ES_MAX_SIZE = 10000; | |||||
| /**es7*/ | |||||
| public static final String IE_SEVEN = "7"; | |||||
| /**url not found 404*/ | |||||
| public static final String URL_NOT_FOUND = "404 Not Found"; | |||||
| public JeecgElasticsearchTemplate(@Value("${jeecg.elasticsearch.cluster-nodes}") String baseUrl, @Value("${jeecg.elasticsearch.check-enabled}") boolean checkEnabled) { | |||||
| log.debug("JeecgElasticsearchTemplate BaseURL:" + baseUrl); | |||||
| if (StringUtils.isNotEmpty(baseUrl)) { | |||||
| this.baseUrl = baseUrl; | |||||
| // 验证配置的ES地址是否有效 | |||||
| if (checkEnabled) { | |||||
| try { | |||||
| this.getElasticsearchVersion(); | |||||
| log.info("ElasticSearch 服务连接成功"); | |||||
| log.info("ElasticSearch version: " + this.version); | |||||
| } catch (Exception e) { | |||||
| this.version = ""; | |||||
| log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取 Elasticsearch 的版本号信息,失败返回null | |||||
| */ | |||||
| private void getElasticsearchVersion() { | |||||
| if (this.version == null) { | |||||
| String url = this.getBaseUrl().toString(); | |||||
| JSONObject result = RestUtil.get(url); | |||||
| if (result != null) { | |||||
| JSONObject v = result.getJSONObject("version"); | |||||
| this.version = v.getString("number"); | |||||
| } | |||||
| } | |||||
| } | |||||
| public StringBuilder getBaseUrl(String indexName, String typeName) { | |||||
| typeName = typeName.trim().toLowerCase(); | |||||
| return this.getBaseUrl(indexName).append("/").append(typeName); | |||||
| } | |||||
| public StringBuilder getBaseUrl(String indexName) { | |||||
| indexName = indexName.trim().toLowerCase(); | |||||
| return this.getBaseUrl().append("/").append(indexName); | |||||
| } | |||||
| public StringBuilder getBaseUrl() { | |||||
| return new StringBuilder("http://").append(this.baseUrl); | |||||
| } | |||||
| /** | |||||
| * cat 查询ElasticSearch系统数据,返回json | |||||
| */ | |||||
| private <T> ResponseEntity<T> cat(String urlAfter, Class<T> responseType) { | |||||
| String url = this.getBaseUrl().append("/_cat").append(urlAfter).append("?").append(FORMAT_JSON).toString(); | |||||
| return RestUtil.request(url, HttpMethod.GET, null, null, null, responseType); | |||||
| } | |||||
| /** | |||||
| * 查询所有索引 | |||||
| * <p> | |||||
| * 查询地址:GET http://{baseUrl}/_cat/indices | |||||
| */ | |||||
| public JSONArray getIndices() { | |||||
| return getIndices(null); | |||||
| } | |||||
| /** | |||||
| * 查询单个索引 | |||||
| * <p> | |||||
| * 查询地址:GET http://{baseUrl}/_cat/indices/{indexName} | |||||
| */ | |||||
| public JSONArray getIndices(String indexName) { | |||||
| StringBuilder urlAfter = new StringBuilder("/indices"); | |||||
| if (!StringUtils.isEmpty(indexName)) { | |||||
| urlAfter.append("/").append(indexName.trim().toLowerCase()); | |||||
| } | |||||
| return cat(urlAfter.toString(), JSONArray.class).getBody(); | |||||
| } | |||||
| /** | |||||
| * 索引是否存在 | |||||
| */ | |||||
| public boolean indexExists(String indexName) { | |||||
| try { | |||||
| JSONArray array = getIndices(indexName); | |||||
| return array != null; | |||||
| } catch (org.springframework.web.client.HttpClientErrorException ex) { | |||||
| if (HttpStatus.NOT_FOUND == ex.getStatusCode()) { | |||||
| return false; | |||||
| } else { | |||||
| throw ex; | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 根据ID获取索引数据,未查询到返回null | |||||
| * <p> | |||||
| * 查询地址:GET http://{baseUrl}/{indexName}/{typeName}/{dataId} | |||||
| * | |||||
| * @param indexName 索引名称 | |||||
| * @param typeName type,一个任意字符串,用于分类 | |||||
| * @param dataId 数据id | |||||
| * @return | |||||
| */ | |||||
| public JSONObject getDataById(String indexName, String typeName, String dataId) { | |||||
| String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString(); | |||||
| log.info("url:" + url); | |||||
| JSONObject result = RestUtil.get(url); | |||||
| boolean found = result.getBoolean("found"); | |||||
| if (found) { | |||||
| return result.getJSONObject("_source"); | |||||
| } else { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 创建索引 | |||||
| * <p> | |||||
| * 查询地址:PUT http://{baseUrl}/{indexName} | |||||
| */ | |||||
| public boolean createIndex(String indexName) { | |||||
| String url = this.getBaseUrl(indexName).toString(); | |||||
| /* 返回结果 (仅供参考) | |||||
| "createIndex": { | |||||
| "shards_acknowledged": true, | |||||
| "acknowledged": true, | |||||
| "index": "hello_world" | |||||
| } | |||||
| */ | |||||
| try { | |||||
| return RestUtil.put(url).getBoolean("acknowledged"); | |||||
| } catch (org.springframework.web.client.HttpClientErrorException ex) { | |||||
| if (HttpStatus.BAD_REQUEST == ex.getStatusCode()) { | |||||
| log.warn("索引创建失败:" + indexName + " 已存在,无需再创建"); | |||||
| } else { | |||||
| ex.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * 删除索引 | |||||
| * <p> | |||||
| * 查询地址:DELETE http://{baseUrl}/{indexName} | |||||
| */ | |||||
| public boolean removeIndex(String indexName) { | |||||
| String url = this.getBaseUrl(indexName).toString(); | |||||
| try { | |||||
| return RestUtil.delete(url).getBoolean("acknowledged"); | |||||
| } catch (org.springframework.web.client.HttpClientErrorException ex) { | |||||
| if (HttpStatus.NOT_FOUND == ex.getStatusCode()) { | |||||
| log.warn("索引删除失败:" + indexName + " 不存在,无需删除"); | |||||
| } else { | |||||
| ex.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * 获取索引字段映射(可获取字段类型) | |||||
| * <p> | |||||
| * | |||||
| * @param indexName 索引名称 | |||||
| * @param typeName 分类名称 | |||||
| * @return | |||||
| */ | |||||
| public JSONObject getIndexMapping(String indexName, String typeName) { | |||||
| String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString(); | |||||
| // 针对 es 7.x 版本做兼容 | |||||
| this.getElasticsearchVersion(); | |||||
| if (oConvertUtils.isNotEmpty(this.version) && this.version.startsWith(IE_SEVEN)) { | |||||
| url += "&include_type_name=true"; | |||||
| } | |||||
| log.info("getIndexMapping-url:" + url); | |||||
| /* | |||||
| * 参考返回JSON结构: | |||||
| * | |||||
| *{ | |||||
| * // 索引名称 | |||||
| * "[indexName]": { | |||||
| * "mappings": { | |||||
| * // 分类名称 | |||||
| * "[typeName]": { | |||||
| * "properties": { | |||||
| * // 字段名 | |||||
| * "input_number": { | |||||
| * // 字段类型 | |||||
| * "type": "long" | |||||
| * }, | |||||
| * "input_string": { | |||||
| * "type": "text", | |||||
| * "fields": { | |||||
| * "keyword": { | |||||
| * "type": "keyword", | |||||
| * "ignore_above": 256 | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| * } | |||||
| */ | |||||
| try { | |||||
| return RestUtil.get(url); | |||||
| } catch (org.springframework.web.client.HttpClientErrorException e) { | |||||
| String message = e.getMessage(); | |||||
| if (message != null && message.contains(URL_NOT_FOUND)) { | |||||
| return null; | |||||
| } | |||||
| throw e; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取索引字段映射,返回Java实体类 | |||||
| * | |||||
| * @param indexName | |||||
| * @param typeName | |||||
| * @return | |||||
| */ | |||||
| public <T> Map<String, T> getIndexMappingFormat(String indexName, String typeName, Class<T> clazz) { | |||||
| JSONObject mapping = this.getIndexMapping(indexName, typeName); | |||||
| Map<String, T> map = new HashMap<>(5); | |||||
| if (mapping == null) { | |||||
| return map; | |||||
| } | |||||
| // 获取字段属性 | |||||
| JSONObject properties = mapping.getJSONObject(indexName) | |||||
| .getJSONObject("mappings") | |||||
| .getJSONObject(typeName) | |||||
| .getJSONObject("properties"); | |||||
| // 封装成 java类型 | |||||
| for (String key : properties.keySet()) { | |||||
| T entity = properties.getJSONObject(key).toJavaObject(clazz); | |||||
| map.put(key, entity); | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 保存数据,详见:saveOrUpdate | |||||
| */ | |||||
| public boolean save(String indexName, String typeName, String dataId, JSONObject data) { | |||||
| return this.saveOrUpdate(indexName, typeName, dataId, data); | |||||
| } | |||||
| /** | |||||
| * 更新数据,详见:saveOrUpdate | |||||
| */ | |||||
| public boolean update(String indexName, String typeName, String dataId, JSONObject data) { | |||||
| return this.saveOrUpdate(indexName, typeName, dataId, data); | |||||
| } | |||||
| /** | |||||
| * 保存或修改索引数据 | |||||
| * <p> | |||||
| * 查询地址:PUT http://{baseUrl}/{indexName}/{typeName}/{dataId} | |||||
| * | |||||
| * @param indexName 索引名称 | |||||
| * @param typeName type,一个任意字符串,用于分类 | |||||
| * @param dataId 数据id | |||||
| * @param data 要存储的数据 | |||||
| * @return | |||||
| */ | |||||
| public boolean saveOrUpdate(String indexName, String typeName, String dataId, JSONObject data) { | |||||
| String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).append("?refresh=wait_for").toString(); | |||||
| /* 返回结果(仅供参考) | |||||
| "createIndexA2": { | |||||
| "result": "created", | |||||
| "_shards": { | |||||
| "total": 2, | |||||
| "successful": 1, | |||||
| "failed": 0 | |||||
| }, | |||||
| "_seq_no": 0, | |||||
| "_index": "test_index_1", | |||||
| "_type": "test_type_1", | |||||
| "_id": "a2", | |||||
| "_version": 1, | |||||
| "_primary_term": 1 | |||||
| } | |||||
| */ | |||||
| try { | |||||
| // 去掉 data 中为空的值 | |||||
| Set<String> keys = data.keySet(); | |||||
| List<String> emptyKeys = new ArrayList<>(keys.size()); | |||||
| for (String key : keys) { | |||||
| String value = data.getString(key); | |||||
| //1、剔除空值 | |||||
| if (oConvertUtils.isEmpty(value) || "[]".equals(value)) { | |||||
| emptyKeys.add(key); | |||||
| } | |||||
| //2、剔除上传控件值(会导致ES同步失败,报异常failed to parse field [ge_pic] of type [text] ) | |||||
| if (oConvertUtils.isNotEmpty(value) && value.indexOf("[{")!=-1) { | |||||
| emptyKeys.add(key); | |||||
| log.info("-------剔除上传控件字段------------key: "+ key); | |||||
| } | |||||
| } | |||||
| for (String key : emptyKeys) { | |||||
| data.remove(key); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| try { | |||||
| String result = RestUtil.put(url, data).getString("result"); | |||||
| return "created".equals(result) || "updated".equals(result); | |||||
| } catch (Exception e) { | |||||
| log.error(e.getMessage() + "\n-- url: " + url + "\n-- data: " + data.toJSONString()); | |||||
| //TODO 打印接口返回异常json | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 批量保存数据 | |||||
| * | |||||
| * @param indexName 索引名称 | |||||
| * @param typeName type,一个任意字符串,用于分类 | |||||
| * @param dataList 要存储的数据数组,每行数据必须包含id | |||||
| * @return | |||||
| */ | |||||
| public boolean saveBatch(String indexName, String typeName, JSONArray dataList) { | |||||
| String url = this.getBaseUrl().append("/_bulk").append("?refresh=wait_for").toString(); | |||||
| StringBuilder bodySb = new StringBuilder(); | |||||
| for (int i = 0; i < dataList.size(); i++) { | |||||
| JSONObject data = dataList.getJSONObject(i); | |||||
| String id = data.getString("id"); | |||||
| // 该行的操作 | |||||
| // {"create": {"_id":"${id}", "_index": "${indexName}", "_type": "${typeName}"}} | |||||
| JSONObject action = new JSONObject(); | |||||
| JSONObject actionInfo = new JSONObject(); | |||||
| actionInfo.put("_id", id); | |||||
| actionInfo.put("_index", indexName); | |||||
| actionInfo.put("_type", typeName); | |||||
| action.put("create", actionInfo); | |||||
| bodySb.append(action.toJSONString()).append("\n"); | |||||
| // 该行的数据 | |||||
| data.remove("id"); | |||||
| bodySb.append(data.toJSONString()).append("\n"); | |||||
| } | |||||
| System.out.println("+-+-+-: bodySb.toString(): " + bodySb.toString()); | |||||
| HttpHeaders headers = RestUtil.getHeaderApplicationJson(); | |||||
| RestUtil.request(url, HttpMethod.PUT, headers, null, bodySb, JSONObject.class); | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * 删除索引数据 | |||||
| * <p> | |||||
| * 请求地址:DELETE http://{baseUrl}/{indexName}/{typeName}/{dataId} | |||||
| */ | |||||
| public boolean delete(String indexName, String typeName, String dataId) { | |||||
| String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString(); | |||||
| /* 返回结果(仅供参考) | |||||
| { | |||||
| "_index": "es_demo", | |||||
| "_type": "docs", | |||||
| "_id": "001", | |||||
| "_version": 3, | |||||
| "result": "deleted", | |||||
| "_shards": { | |||||
| "total": 1, | |||||
| "successful": 1, | |||||
| "failed": 0 | |||||
| }, | |||||
| "_seq_no": 28, | |||||
| "_primary_term": 18 | |||||
| } | |||||
| */ | |||||
| try { | |||||
| return "deleted".equals(RestUtil.delete(url).getString("result")); | |||||
| } catch (org.springframework.web.client.HttpClientErrorException ex) { | |||||
| if (HttpStatus.NOT_FOUND == ex.getStatusCode()) { | |||||
| return false; | |||||
| } else { | |||||
| throw ex; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* = = = 以下关于查询和查询条件的方法 = = =*/ | |||||
| /** | |||||
| * 查询数据 | |||||
| * <p> | |||||
| * 请求地址:POST http://{baseUrl}/{indexName}/{typeName}/_search | |||||
| */ | |||||
| public JSONObject search(String indexName, String typeName, JSONObject queryObject) { | |||||
| String url = this.getBaseUrl(indexName, typeName).append("/_search").toString(); | |||||
| log.info("url:" + url + " ,search: " + queryObject.toJSONString()); | |||||
| JSONObject res = RestUtil.post(url, queryObject); | |||||
| log.info("url:" + url + " ,return res: \n" + res.toJSONString()); | |||||
| return res; | |||||
| } | |||||
| /** | |||||
| * @param source (源滤波器)指定返回的字段,传null返回所有字段 | |||||
| * @param query | |||||
| * @param from 从第几条数据开始 | |||||
| * @param size 返回条目数 | |||||
| * @return { "query": query } | |||||
| */ | |||||
| public JSONObject buildQuery(List<String> source, JSONObject query, int from, int size) { | |||||
| JSONObject json = new JSONObject(); | |||||
| if (source != null) { | |||||
| json.put("_source", source); | |||||
| } | |||||
| json.put("query", query); | |||||
| json.put("from", from); | |||||
| json.put("size", size); | |||||
| return json; | |||||
| } | |||||
| /** | |||||
| * @return { "bool" : { "must": must, "must_not": mustNot, "should": should } } | |||||
| */ | |||||
| public JSONObject buildBoolQuery(JSONArray must, JSONArray mustNot, JSONArray should) { | |||||
| JSONObject bool = new JSONObject(); | |||||
| if (must != null) { | |||||
| bool.put("must", must); | |||||
| } | |||||
| if (mustNot != null) { | |||||
| bool.put("must_not", mustNot); | |||||
| } | |||||
| if (should != null) { | |||||
| bool.put("should", should); | |||||
| } | |||||
| JSONObject json = new JSONObject(); | |||||
| json.put("bool", bool); | |||||
| return json; | |||||
| } | |||||
| /** | |||||
| * @param field 要查询的字段 | |||||
| * @param args 查询参数,参考: *哈哈* OR *哒* NOT *呵* OR *啊* | |||||
| * @return | |||||
| */ | |||||
| public JSONObject buildQueryString(String field, String... args) { | |||||
| if (field == null) { | |||||
| return null; | |||||
| } | |||||
| StringBuilder sb = new StringBuilder(field).append(":("); | |||||
| if (args != null) { | |||||
| for (String arg : args) { | |||||
| sb.append(arg).append(" "); | |||||
| } | |||||
| } | |||||
| sb.append(")"); | |||||
| return this.buildQueryString(sb.toString()); | |||||
| } | |||||
| /** | |||||
| * @return { "query_string": { "query": query } } | |||||
| */ | |||||
| public JSONObject buildQueryString(String query) { | |||||
| JSONObject queryString = new JSONObject(); | |||||
| queryString.put("query", query); | |||||
| JSONObject json = new JSONObject(); | |||||
| json.put("query_string", queryString); | |||||
| return json; | |||||
| } | |||||
| /** | |||||
| * @param field 查询字段 | |||||
| * @param min 最小值 | |||||
| * @param max 最大值 | |||||
| * @param containMin 范围内是否包含最小值 | |||||
| * @param containMax 范围内是否包含最大值 | |||||
| * @return { "range" : { field : { 『 "gt『e』?containMin" : min 』?min!=null , 『 "lt『e』?containMax" : max 』}} } | |||||
| */ | |||||
| public JSONObject buildRangeQuery(String field, Object min, Object max, boolean containMin, boolean containMax) { | |||||
| JSONObject inner = new JSONObject(); | |||||
| if (min != null) { | |||||
| if (containMin) { | |||||
| inner.put("gte", min); | |||||
| } else { | |||||
| inner.put("gt", min); | |||||
| } | |||||
| } | |||||
| if (max != null) { | |||||
| if (containMax) { | |||||
| inner.put("lte", max); | |||||
| } else { | |||||
| inner.put("lt", max); | |||||
| } | |||||
| } | |||||
| JSONObject range = new JSONObject(); | |||||
| range.put(field, inner); | |||||
| JSONObject json = new JSONObject(); | |||||
| json.put("range", range); | |||||
| return json; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,98 @@ | |||||
| package org.jeecg.common.es; | |||||
| /** | |||||
| * 用于创建 ElasticSearch 的 queryString | |||||
| * | |||||
| * @author sunjianlei | |||||
| */ | |||||
| public class QueryStringBuilder { | |||||
| StringBuilder builder; | |||||
| public QueryStringBuilder(String field, String str, boolean not, boolean addQuot) { | |||||
| builder = this.createBuilder(field, str, not, addQuot); | |||||
| } | |||||
| public QueryStringBuilder(String field, String str, boolean not) { | |||||
| builder = this.createBuilder(field, str, not, true); | |||||
| } | |||||
| /** | |||||
| * 创建 StringBuilder | |||||
| * | |||||
| * @param field | |||||
| * @param str | |||||
| * @param not 是否是不匹配 | |||||
| * @param addQuot 是否添加双引号 | |||||
| * @return | |||||
| */ | |||||
| public StringBuilder createBuilder(String field, String str, boolean not, boolean addQuot) { | |||||
| StringBuilder sb = new StringBuilder(field).append(":("); | |||||
| if (not) { | |||||
| sb.append(" NOT "); | |||||
| } | |||||
| this.addQuotEffect(sb, str, addQuot); | |||||
| return sb; | |||||
| } | |||||
| public QueryStringBuilder and(String str) { | |||||
| return this.and(str, true); | |||||
| } | |||||
| public QueryStringBuilder and(String str, boolean addQuot) { | |||||
| builder.append(" AND "); | |||||
| this.addQuot(str, addQuot); | |||||
| return this; | |||||
| } | |||||
| public QueryStringBuilder or(String str) { | |||||
| return this.or(str, true); | |||||
| } | |||||
| public QueryStringBuilder or(String str, boolean addQuot) { | |||||
| builder.append(" OR "); | |||||
| this.addQuot(str, addQuot); | |||||
| return this; | |||||
| } | |||||
| public QueryStringBuilder not(String str) { | |||||
| return this.not(str, true); | |||||
| } | |||||
| public QueryStringBuilder not(String str, boolean addQuot) { | |||||
| builder.append(" NOT "); | |||||
| this.addQuot(str, addQuot); | |||||
| return this; | |||||
| } | |||||
| /** | |||||
| * 添加双引号(模糊查询,不能加双引号) | |||||
| */ | |||||
| private QueryStringBuilder addQuot(String str, boolean addQuot) { | |||||
| return this.addQuotEffect(this.builder, str, addQuot); | |||||
| } | |||||
| /** | |||||
| * 是否在两边加上双引号 | |||||
| * @param builder | |||||
| * @param str | |||||
| * @param addQuot | |||||
| * @return | |||||
| */ | |||||
| private QueryStringBuilder addQuotEffect(StringBuilder builder, String str, boolean addQuot) { | |||||
| if (addQuot) { | |||||
| builder.append('"'); | |||||
| } | |||||
| builder.append(str); | |||||
| if (addQuot) { | |||||
| builder.append('"'); | |||||
| } | |||||
| return this; | |||||
| } | |||||
| @Override | |||||
| public String toString() { | |||||
| return builder.append(")").toString(); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| package org.jeecg.common.exception; | |||||
| /** | |||||
| * @Description: jeecg-boot自定义401异常 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class JeecgBoot401Exception extends RuntimeException { | |||||
| private static final long serialVersionUID = 1L; | |||||
| public JeecgBoot401Exception(String message){ | |||||
| super(message); | |||||
| } | |||||
| public JeecgBoot401Exception(Throwable cause) | |||||
| { | |||||
| super(cause); | |||||
| } | |||||
| public JeecgBoot401Exception(String message, Throwable cause) | |||||
| { | |||||
| super(message,cause); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,21 @@ | |||||
| package org.jeecg.common.exception; | |||||
| /** | |||||
| * jeecgboot断言异常 | |||||
| * for [QQYUN-10990]AIRAG | |||||
| * @author chenrui | |||||
| * @date 2025/2/14 14:31 | |||||
| */ | |||||
| public class JeecgBootAssertException extends JeecgBootException { | |||||
| private static final long serialVersionUID = 1L; | |||||
| public JeecgBootAssertException(String message) { | |||||
| super(message); | |||||
| } | |||||
| public JeecgBootAssertException(String message, int errCode) { | |||||
| super(message, errCode); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,40 @@ | |||||
| package org.jeecg.common.exception; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| /** | |||||
| * @Description: 业务提醒异常(用于操作业务提醒) | |||||
| * @date: 2024-04-26 | |||||
| * @author: scott | |||||
| */ | |||||
| public class JeecgBootBizTipException extends RuntimeException { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 返回给前端的错误code | |||||
| */ | |||||
| private int errCode = CommonConstant.SC_INTERNAL_SERVER_ERROR_500; | |||||
| public JeecgBootBizTipException(String message){ | |||||
| super(message); | |||||
| } | |||||
| public JeecgBootBizTipException(String message, int errCode){ | |||||
| super(message); | |||||
| this.errCode = errCode; | |||||
| } | |||||
| public int getErrCode() { | |||||
| return errCode; | |||||
| } | |||||
| public JeecgBootBizTipException(Throwable cause) | |||||
| { | |||||
| super(cause); | |||||
| } | |||||
| public JeecgBootBizTipException(String message, Throwable cause) | |||||
| { | |||||
| super(message,cause); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,39 @@ | |||||
| package org.jeecg.common.exception; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| /** | |||||
| * @Description: jeecg-boot自定义异常 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class JeecgBootException extends RuntimeException { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * 返回给前端的错误code | |||||
| */ | |||||
| private int errCode = CommonConstant.SC_INTERNAL_SERVER_ERROR_500; | |||||
| public JeecgBootException(String message){ | |||||
| super(message); | |||||
| } | |||||
| public JeecgBootException(String message, int errCode){ | |||||
| super(message); | |||||
| this.errCode = errCode; | |||||
| } | |||||
| public int getErrCode() { | |||||
| return errCode; | |||||
| } | |||||
| public JeecgBootException(Throwable cause) | |||||
| { | |||||
| super(cause); | |||||
| } | |||||
| public JeecgBootException(String message,Throwable cause) | |||||
| { | |||||
| super(message,cause); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,254 @@ | |||||
| package org.jeecg.common.exception; | |||||
| import cn.hutool.core.util.ObjectUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.commons.lang3.exception.ExceptionUtils; | |||||
| import org.apache.shiro.SecurityUtils; | |||||
| import org.apache.shiro.authz.AuthorizationException; | |||||
| import org.apache.shiro.authz.UnauthorizedException; | |||||
| import org.jeecg.common.api.dto.LogDTO; | |||||
| import org.jeecg.common.api.vo.Result; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.constant.enums.ClientTerminalTypeEnum; | |||||
| import org.jeecg.common.enums.SentinelErrorInfoEnum; | |||||
| import org.jeecg.common.system.vo.LoginUser; | |||||
| import org.jeecg.common.util.BrowserUtils; | |||||
| import org.jeecg.common.util.IpUtils; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.jeecg.modules.base.service.BaseCommonService; | |||||
| import org.springframework.beans.BeansException; | |||||
| import org.springframework.dao.DataIntegrityViolationException; | |||||
| import org.springframework.dao.DuplicateKeyException; | |||||
| import org.springframework.data.redis.connection.PoolException; | |||||
| import org.springframework.http.HttpStatus; | |||||
| import org.springframework.util.CollectionUtils; | |||||
| import org.springframework.validation.ObjectError; | |||||
| import org.springframework.web.HttpRequestMethodNotSupportedException; | |||||
| import org.springframework.web.bind.MethodArgumentNotValidException; | |||||
| import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
| import org.springframework.web.bind.annotation.ResponseStatus; | |||||
| import org.springframework.web.bind.annotation.RestControllerAdvice; | |||||
| import org.springframework.web.multipart.MaxUploadSizeExceededException; | |||||
| import org.springframework.web.servlet.NoHandlerFoundException; | |||||
| import javax.annotation.Resource; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.util.Map; | |||||
| import java.util.stream.Collectors; | |||||
| /** | |||||
| * 异常处理器 | |||||
| * | |||||
| * @Author scott | |||||
| * @Date 2019 | |||||
| */ | |||||
| @RestControllerAdvice | |||||
| @Slf4j | |||||
| public class JeecgBootExceptionHandler { | |||||
| @Resource | |||||
| BaseCommonService baseCommonService; | |||||
| @ExceptionHandler(MethodArgumentNotValidException.class) | |||||
| public Result<?> handleValidationExceptions(MethodArgumentNotValidException e) { | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error("校验失败!" + e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","))); | |||||
| } | |||||
| /** | |||||
| * 处理自定义异常 | |||||
| */ | |||||
| @ExceptionHandler(JeecgBootException.class) | |||||
| public Result<?> handleJeecgBootException(JeecgBootException e){ | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error(e.getErrCode(), e.getMessage()); | |||||
| } | |||||
| /** | |||||
| * 处理自定义异常 | |||||
| */ | |||||
| @ExceptionHandler(JeecgBootBizTipException.class) | |||||
| public Result<?> handleJeecgBootBizTipException(JeecgBootBizTipException e){ | |||||
| log.error(e.getMessage()); | |||||
| return Result.error(e.getErrCode(), e.getMessage()); | |||||
| } | |||||
| /** | |||||
| * 处理自定义微服务异常 | |||||
| */ | |||||
| @ExceptionHandler(JeecgCloudException.class) | |||||
| public Result<?> handleJeecgCloudException(JeecgCloudException e){ | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error(e.getMessage()); | |||||
| } | |||||
| /** | |||||
| * 处理自定义异常 | |||||
| */ | |||||
| @ExceptionHandler(JeecgBoot401Exception.class) | |||||
| @ResponseStatus(HttpStatus.UNAUTHORIZED) | |||||
| public Result<?> handleJeecgBoot401Exception(JeecgBoot401Exception e){ | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return new Result(401,e.getMessage()); | |||||
| } | |||||
| @ExceptionHandler(NoHandlerFoundException.class) | |||||
| public Result<?> handlerNoFoundException(Exception e) { | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error(404, "路径不存在,请检查路径是否正确"); | |||||
| } | |||||
| @ExceptionHandler(DuplicateKeyException.class) | |||||
| public Result<?> handleDuplicateKeyException(DuplicateKeyException e){ | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error("数据库中已存在该记录"); | |||||
| } | |||||
| @ExceptionHandler({UnauthorizedException.class, AuthorizationException.class}) | |||||
| public Result<?> handleAuthorizationException(AuthorizationException e){ | |||||
| log.error(e.getMessage(), e); | |||||
| return Result.noauth("没有权限,请联系管理员分配权限!"); | |||||
| } | |||||
| @ExceptionHandler(Exception.class) | |||||
| public Result<?> handleException(Exception e){ | |||||
| log.error(e.getMessage(), e); | |||||
| //update-begin---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常 | |||||
| Throwable throwable = e.getCause(); | |||||
| SentinelErrorInfoEnum errorInfoEnum = SentinelErrorInfoEnum.getErrorByException(throwable); | |||||
| if (ObjectUtil.isNotEmpty(errorInfoEnum)) { | |||||
| return Result.error(errorInfoEnum.getError()); | |||||
| } | |||||
| //update-end---author:zyf ---date:20220411 for:处理Sentinel限流自定义异常 | |||||
| addSysLog(e); | |||||
| return Result.error("操作失败,"+e.getMessage()); | |||||
| } | |||||
| /** | |||||
| * @Author 政辉 | |||||
| * @param e | |||||
| * @return | |||||
| */ | |||||
| @ExceptionHandler(HttpRequestMethodNotSupportedException.class) | |||||
| public Result<?> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){ | |||||
| StringBuffer sb = new StringBuffer(); | |||||
| sb.append("不支持"); | |||||
| sb.append(e.getMethod()); | |||||
| sb.append("请求方法,"); | |||||
| sb.append("支持以下"); | |||||
| String [] methods = e.getSupportedMethods(); | |||||
| if(methods!=null){ | |||||
| for(String str:methods){ | |||||
| sb.append(str); | |||||
| sb.append("、"); | |||||
| } | |||||
| } | |||||
| log.error(sb.toString(), e); | |||||
| //return Result.error("没有权限,请联系管理员授权"); | |||||
| addSysLog(e); | |||||
| return Result.error(405,sb.toString()); | |||||
| } | |||||
| /** | |||||
| * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException | |||||
| */ | |||||
| @ExceptionHandler(MaxUploadSizeExceededException.class) | |||||
| public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) { | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! "); | |||||
| } | |||||
| @ExceptionHandler(DataIntegrityViolationException.class) | |||||
| public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) { | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| //【issues/3624】数据库执行异常handleDataIntegrityViolationException提示有误 #3624 | |||||
| return Result.error("执行数据库异常,违反了完整性例如:违反惟一约束、违反非空限制、字段内容超出长度等"); | |||||
| } | |||||
| @ExceptionHandler(PoolException.class) | |||||
| public Result<?> handlePoolException(PoolException e) { | |||||
| log.error(e.getMessage(), e); | |||||
| addSysLog(e); | |||||
| return Result.error("Redis 连接异常!"); | |||||
| } | |||||
| /** | |||||
| * SQL注入风险,全局异常处理 | |||||
| * | |||||
| * @param exception | |||||
| * @return | |||||
| */ | |||||
| @ExceptionHandler(JeecgSqlInjectionException.class) | |||||
| public Result<?> handleSQLException(Exception exception) { | |||||
| String msg = exception.getMessage().toLowerCase(); | |||||
| final String extractvalue = "extractvalue"; | |||||
| final String updatexml = "updatexml"; | |||||
| boolean hasSensitiveInformation = msg.indexOf(extractvalue) >= 0 || msg.indexOf(updatexml) >= 0; | |||||
| if (msg != null && hasSensitiveInformation) { | |||||
| log.error("校验失败,存在SQL注入风险!{}", msg); | |||||
| return Result.error("校验失败,存在SQL注入风险!"); | |||||
| } | |||||
| addSysLog(exception); | |||||
| return Result.error("校验失败,存在SQL注入风险!" + msg); | |||||
| } | |||||
| //update-begin---author:chenrui ---date:20240423 for:[QQYUN-8732]把错误的日志都抓取了 方便后续处理,单独弄个日志类型------------ | |||||
| /** | |||||
| * 添加异常新系统日志 | |||||
| * @param e 异常 | |||||
| * @author chenrui | |||||
| * @date 2024/4/22 17:16 | |||||
| */ | |||||
| private void addSysLog(Throwable e) { | |||||
| LogDTO log = new LogDTO(); | |||||
| log.setLogType(CommonConstant.LOG_TYPE_4); | |||||
| log.setLogContent(e.getClass().getName()+":"+e.getMessage()); | |||||
| log.setRequestParam(ExceptionUtils.getStackTrace(e)); | |||||
| //获取request | |||||
| HttpServletRequest request = null; | |||||
| try { | |||||
| request = SpringContextUtils.getHttpServletRequest(); | |||||
| } catch (NullPointerException | BeansException ignored) { | |||||
| } | |||||
| if (null != request) { | |||||
| //请求的参数 | |||||
| Map<String, String[]> parameterMap = request.getParameterMap(); | |||||
| if(!CollectionUtils.isEmpty(parameterMap)){ | |||||
| log.setMethod(oConvertUtils.mapToString(request.getParameterMap())); | |||||
| } | |||||
| // 请求地址 | |||||
| log.setRequestUrl(request.getRequestURI()); | |||||
| //设置IP地址 | |||||
| log.setIp(IpUtils.getIpAddr(request)); | |||||
| //设置客户端 | |||||
| if(BrowserUtils.isDesktop(request)){ | |||||
| log.setClientType(ClientTerminalTypeEnum.PC.getKey()); | |||||
| }else{ | |||||
| log.setClientType(ClientTerminalTypeEnum.APP.getKey()); | |||||
| } | |||||
| } | |||||
| //获取登录用户信息 | |||||
| LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | |||||
| if(sysUser!=null){ | |||||
| log.setUserid(sysUser.getUsername()); | |||||
| log.setUsername(sysUser.getRealname()); | |||||
| } | |||||
| baseCommonService.addLog(log); | |||||
| } | |||||
| //update-end---author:chenrui ---date:20240423 for:[QQYUN-8732]把错误的日志都抓取了 方便后续处理,单独弄个日志类型------------ | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| package org.jeecg.common.exception; | |||||
| /** | |||||
| * @Description: jeecg-boot自定义SQL注入异常 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class JeecgSqlInjectionException extends RuntimeException { | |||||
| private static final long serialVersionUID = 1L; | |||||
| public JeecgSqlInjectionException(String message){ | |||||
| super(message); | |||||
| } | |||||
| public JeecgSqlInjectionException(Throwable cause) | |||||
| { | |||||
| super(cause); | |||||
| } | |||||
| public JeecgSqlInjectionException(String message, Throwable cause) | |||||
| { | |||||
| super(message,cause); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,22 @@ | |||||
| package org.jeecg.common.handler; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| /** | |||||
| * 填值规则接口 | |||||
| * | |||||
| * @author Yan_东 | |||||
| * 如需使用填值规则功能,规则实现类必须实现此接口 | |||||
| */ | |||||
| public interface IFillRuleHandler { | |||||
| /** | |||||
| * 填值规则 | |||||
| * @param params 页面配置固定参数 | |||||
| * @param formData 动态表单参数 | |||||
| * @return | |||||
| */ | |||||
| public Object execute(JSONObject params, JSONObject formData); | |||||
| } | |||||
| @ -0,0 +1,19 @@ | |||||
| package org.jeecg.common.system.annotation; | |||||
| import java.lang.annotation.*; | |||||
| /** | |||||
| * 将枚举类转化成字典数据 | |||||
| * @Author taoYan | |||||
| * @Date 2022/7/8 10:34 | |||||
| **/ | |||||
| @Target(ElementType.TYPE) | |||||
| @Retention(RetentionPolicy.RUNTIME) | |||||
| @Documented | |||||
| public @interface EnumDict { | |||||
| /** | |||||
| * 作为字典数据的唯一编码 | |||||
| */ | |||||
| String value() default ""; | |||||
| } | |||||
| @ -0,0 +1,203 @@ | |||||
| package org.jeecg.common.system.base.controller; | |||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | |||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||
| import com.baomidou.mybatisplus.extension.service.IService; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.commons.beanutils.PropertyUtils; | |||||
| import org.apache.shiro.SecurityUtils; | |||||
| import org.jeecg.common.api.vo.Result; | |||||
| import org.jeecg.common.system.query.QueryGenerator; | |||||
| import org.jeecg.common.system.vo.LoginUser; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.jeecg.config.JeecgBaseConfig; | |||||
| import org.jeecgframework.poi.excel.ExcelImportUtil; | |||||
| import org.jeecgframework.poi.excel.def.NormalExcelConstants; | |||||
| import org.jeecgframework.poi.excel.entity.ExportParams; | |||||
| import org.jeecgframework.poi.excel.entity.ImportParams; | |||||
| import org.jeecgframework.poi.excel.entity.enmus.ExcelType; | |||||
| import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import org.springframework.web.multipart.MultipartHttpServletRequest; | |||||
| import org.springframework.web.servlet.ModelAndView; | |||||
| import javax.annotation.Resource; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| import java.util.*; | |||||
| /** | |||||
| * @Description: Controller基类 | |||||
| * @Author: dangzhenghui@163.com | |||||
| * @Date: 2019-4-21 8:13 | |||||
| * @Version: 1.0 | |||||
| */ | |||||
| @Slf4j | |||||
| public class JeecgController<T, S extends IService<T>> { | |||||
| /**issues/2933 JeecgController注入service时改用protected修饰,能避免重复引用service*/ | |||||
| @Autowired | |||||
| protected S service; | |||||
| @Resource | |||||
| private JeecgBaseConfig jeecgBaseConfig; | |||||
| /** | |||||
| * 导出excel | |||||
| * | |||||
| * @param request | |||||
| */ | |||||
| protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title) { | |||||
| // Step.1 组装查询条件 | |||||
| QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap()); | |||||
| LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | |||||
| // 过滤选中数据 | |||||
| String selections = request.getParameter("selections"); | |||||
| if (oConvertUtils.isNotEmpty(selections)) { | |||||
| List<String> selectionList = Arrays.asList(selections.split(",")); | |||||
| queryWrapper.in("id",selectionList); | |||||
| } | |||||
| // Step.2 获取导出数据 | |||||
| List<T> exportList = service.list(queryWrapper); | |||||
| // Step.3 AutoPoi 导出Excel | |||||
| ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); | |||||
| //此处设置的filename无效 ,前端会重更新设置一下 | |||||
| mv.addObject(NormalExcelConstants.FILE_NAME, title); | |||||
| mv.addObject(NormalExcelConstants.CLASS, clazz); | |||||
| //update-begin--Author:liusq Date:20210126 for:图片导出报错,ImageBasePath未设置-------------------- | |||||
| ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title); | |||||
| exportParams.setImageBasePath(jeecgBaseConfig.getPath().getUpload()); | |||||
| //update-end--Author:liusq Date:20210126 for:图片导出报错,ImageBasePath未设置---------------------- | |||||
| mv.addObject(NormalExcelConstants.PARAMS,exportParams); | |||||
| mv.addObject(NormalExcelConstants.DATA_LIST, exportList); | |||||
| return mv; | |||||
| } | |||||
| /** | |||||
| * 根据每页sheet数量导出多sheet | |||||
| * | |||||
| * @param request | |||||
| * @param object 实体类 | |||||
| * @param clazz 实体类class | |||||
| * @param title 标题 | |||||
| * @param exportFields 导出字段自定义 | |||||
| * @param pageNum 每个sheet的数据条数 | |||||
| * @param request | |||||
| */ | |||||
| protected ModelAndView exportXlsSheet(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields,Integer pageNum) { | |||||
| // Step.1 组装查询条件 | |||||
| QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap()); | |||||
| LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | |||||
| // Step.2 计算分页sheet数据 | |||||
| double total = service.count(); | |||||
| int count = (int)Math.ceil(total/pageNum); | |||||
| //update-begin-author:liusq---date:20220629--for: 多sheet导出根据选择导出写法调整 --- | |||||
| // Step.3 过滤选中数据 | |||||
| String selections = request.getParameter("selections"); | |||||
| if (oConvertUtils.isNotEmpty(selections)) { | |||||
| List<String> selectionList = Arrays.asList(selections.split(",")); | |||||
| queryWrapper.in("id",selectionList); | |||||
| } | |||||
| //update-end-author:liusq---date:20220629--for: 多sheet导出根据选择导出写法调整 --- | |||||
| // Step.4 多sheet处理 | |||||
| List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>(); | |||||
| for (int i = 1; i <=count ; i++) { | |||||
| Page<T> page = new Page<T>(i, pageNum); | |||||
| IPage<T> pageList = service.page(page, queryWrapper); | |||||
| List<T> exportList = pageList.getRecords(); | |||||
| Map<String, Object> map = new HashMap<>(5); | |||||
| ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title+i,jeecgBaseConfig.getPath().getUpload()); | |||||
| exportParams.setType(ExcelType.XSSF); | |||||
| //map.put("title",exportParams); | |||||
| //表格Title | |||||
| map.put(NormalExcelConstants.PARAMS,exportParams); | |||||
| //表格对应实体 | |||||
| map.put(NormalExcelConstants.CLASS,clazz); | |||||
| //数据集合 | |||||
| map.put(NormalExcelConstants.DATA_LIST, exportList); | |||||
| listMap.add(map); | |||||
| } | |||||
| // Step.4 AutoPoi 导出Excel | |||||
| ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); | |||||
| //此处设置的filename无效 ,前端会重更新设置一下 | |||||
| mv.addObject(NormalExcelConstants.FILE_NAME, title); | |||||
| mv.addObject(NormalExcelConstants.MAP_LIST, listMap); | |||||
| return mv; | |||||
| } | |||||
| /** | |||||
| * 根据权限导出excel,传入导出字段参数 | |||||
| * | |||||
| * @param request | |||||
| */ | |||||
| protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields) { | |||||
| ModelAndView mv = this.exportXls(request,object,clazz,title); | |||||
| mv.addObject(NormalExcelConstants.EXPORT_FIELDS,exportFields); | |||||
| return mv; | |||||
| } | |||||
| /** | |||||
| * 获取对象ID | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| private String getId(T item) { | |||||
| try { | |||||
| return PropertyUtils.getProperty(item, "id").toString(); | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 通过excel导入数据 | |||||
| * | |||||
| * @param request | |||||
| * @param response | |||||
| * @return | |||||
| */ | |||||
| protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) { | |||||
| MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; | |||||
| Map<String, MultipartFile> fileMap = multipartRequest.getFileMap(); | |||||
| for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) { | |||||
| // 获取上传文件对象 | |||||
| MultipartFile file = entity.getValue(); | |||||
| ImportParams params = new ImportParams(); | |||||
| params.setTitleRows(2); | |||||
| params.setHeadRows(1); | |||||
| params.setNeedSave(true); | |||||
| try { | |||||
| List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params); | |||||
| //update-begin-author:taoyan date:20190528 for:批量插入数据 | |||||
| long start = System.currentTimeMillis(); | |||||
| service.saveBatch(list); | |||||
| //400条 saveBatch消耗时间1592毫秒 循环插入消耗时间1947毫秒 | |||||
| //1200条 saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒 | |||||
| log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒"); | |||||
| //update-end-author:taoyan date:20190528 for:批量插入数据 | |||||
| return Result.ok("文件导入成功!数据行数:" + list.size()); | |||||
| } catch (Exception e) { | |||||
| //update-begin-author:taoyan date:20211124 for: 导入数据重复增加提示 | |||||
| String msg = e.getMessage(); | |||||
| log.error(msg, e); | |||||
| if(msg!=null && msg.indexOf("Duplicate entry")>=0){ | |||||
| return Result.error("文件导入失败:有重复数据!"); | |||||
| }else{ | |||||
| return Result.error("文件导入失败:" + e.getMessage()); | |||||
| } | |||||
| //update-end-author:taoyan date:20211124 for: 导入数据重复增加提示 | |||||
| } finally { | |||||
| try { | |||||
| file.getInputStream().close(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return Result.error("文件导入失败!"); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,68 @@ | |||||
| package org.jeecg.common.system.base.entity; | |||||
| import java.io.Serializable; | |||||
| import io.swagger.v3.oas.annotations.media.Schema; | |||||
| import org.jeecgframework.poi.excel.annotation.Excel; | |||||
| import org.springframework.format.annotation.DateTimeFormat; | |||||
| import com.baomidou.mybatisplus.annotation.IdType; | |||||
| import com.baomidou.mybatisplus.annotation.TableId; | |||||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.experimental.Accessors; | |||||
| /** | |||||
| * @Description: Entity基类 | |||||
| * @Author: dangzhenghui@163.com | |||||
| * @Date: 2019-4-28 | |||||
| * @Version: 1.1 | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = false) | |||||
| @Accessors(chain = true) | |||||
| public class JeecgEntity implements Serializable { | |||||
| private static final long serialVersionUID = 1L; | |||||
| /** | |||||
| * ID | |||||
| */ | |||||
| @TableId(type = IdType.ASSIGN_ID) | |||||
| @Schema(description = "ID") | |||||
| private java.lang.String id; | |||||
| /** | |||||
| * 创建人 | |||||
| */ | |||||
| @Schema(description = "创建人") | |||||
| @Excel(name = "创建人", width = 15) | |||||
| private java.lang.String createBy; | |||||
| /** | |||||
| * 创建时间 | |||||
| */ | |||||
| @Schema(description = "创建时间") | |||||
| @Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss") | |||||
| @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | |||||
| @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
| private java.util.Date createTime; | |||||
| /** | |||||
| * 更新人 | |||||
| */ | |||||
| @Schema(description = "更新人") | |||||
| @Excel(name = "更新人", width = 15) | |||||
| private java.lang.String updateBy; | |||||
| /** | |||||
| * 更新时间 | |||||
| */ | |||||
| @Schema(description = "更新时间") | |||||
| @Excel(name = "更新时间", width = 20, format = "yyyy-MM-dd HH:mm:ss") | |||||
| @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | |||||
| @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||||
| private java.util.Date updateTime; | |||||
| } | |||||
| @ -0,0 +1,12 @@ | |||||
| package org.jeecg.common.system.base.service; | |||||
| import com.baomidou.mybatisplus.extension.service.IService; | |||||
| /** | |||||
| * @Description: Service基类 | |||||
| * @Author: dangzhenghui@163.com | |||||
| * @Date: 2019-4-21 8:13 | |||||
| * @Version: 1.0 | |||||
| */ | |||||
| public interface JeecgService<T> extends IService<T> { | |||||
| } | |||||
| @ -0,0 +1,19 @@ | |||||
| package org.jeecg.common.system.base.service.impl; | |||||
| import org.jeecg.common.system.base.entity.JeecgEntity; | |||||
| import org.jeecg.common.system.base.service.JeecgService; | |||||
| import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| /** | |||||
| * @Description: ServiceImpl基类 | |||||
| * @Author: dangzhenghui@163.com | |||||
| * @Date: 2019-4-21 8:13 | |||||
| * @Version: 1.0 | |||||
| */ | |||||
| @Slf4j | |||||
| public class JeecgServiceImpl<M extends BaseMapper<T>, T extends JeecgEntity> extends ServiceImpl<M, T> implements JeecgService<T> { | |||||
| } | |||||
| @ -0,0 +1,19 @@ | |||||
| package org.jeecg.common.system.enhance; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 用户增强 | |||||
| */ | |||||
| public interface UserFilterEnhance { | |||||
| /** | |||||
| * 获取用户id | |||||
| * @param loginUserId 当前登录的用户id | |||||
| * | |||||
| * @return List<String> 返回多个用户id | |||||
| */ | |||||
| default List<String> getUserIds(String loginUserId) { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,45 @@ | |||||
| package org.jeecg.common.system.query; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * 查询链接规则 | |||||
| * | |||||
| * @Author Sunjianlei | |||||
| */ | |||||
| public enum MatchTypeEnum { | |||||
| /**查询链接规则 AND*/ | |||||
| AND("AND"), | |||||
| /**查询链接规则 OR*/ | |||||
| OR("OR"); | |||||
| private String value; | |||||
| MatchTypeEnum(String value) { | |||||
| this.value = value; | |||||
| } | |||||
| public String getValue() { | |||||
| return value; | |||||
| } | |||||
| public static MatchTypeEnum getByValue(Object value) { | |||||
| if (oConvertUtils.isEmpty(value)) { | |||||
| return null; | |||||
| } | |||||
| return getByValue(value.toString()); | |||||
| } | |||||
| public static MatchTypeEnum getByValue(String value) { | |||||
| if (oConvertUtils.isEmpty(value)) { | |||||
| return null; | |||||
| } | |||||
| for (MatchTypeEnum val : values()) { | |||||
| if (val.getValue().toLowerCase().equals(value.toLowerCase())) { | |||||
| return val; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,81 @@ | |||||
| package org.jeecg.common.system.query; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @Description: QueryCondition | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class QueryCondition implements Serializable { | |||||
| private static final long serialVersionUID = 4740166316629191651L; | |||||
| private String field; | |||||
| /** 组件的类型(例如:input、select、radio) */ | |||||
| private String type; | |||||
| /** | |||||
| * 对应的数据库字段的类型 | |||||
| * 支持:int、bigDecimal、short、long、float、double、boolean | |||||
| */ | |||||
| private String dbType; | |||||
| private String rule; | |||||
| private String val; | |||||
| public QueryCondition(String field, String type, String dbType, String rule, String val) { | |||||
| this.field = field; | |||||
| this.type = type; | |||||
| this.dbType = dbType; | |||||
| this.rule = rule; | |||||
| this.val = val; | |||||
| } | |||||
| public String getField() { | |||||
| return field; | |||||
| } | |||||
| public void setField(String field) { | |||||
| this.field = field; | |||||
| } | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| public void setType(String type) { | |||||
| this.type = type; | |||||
| } | |||||
| public String getDbType() { | |||||
| return dbType; | |||||
| } | |||||
| public void setDbType(String dbType) { | |||||
| this.dbType = dbType; | |||||
| } | |||||
| public String getRule() { | |||||
| return rule; | |||||
| } | |||||
| public void setRule(String rule) { | |||||
| this.rule = rule; | |||||
| } | |||||
| public String getVal() { | |||||
| return val; | |||||
| } | |||||
| public void setVal(String val) { | |||||
| this.val = val; | |||||
| } | |||||
| @Override | |||||
| public String toString(){ | |||||
| StringBuffer sb =new StringBuffer(); | |||||
| if(field == null || "".equals(field)){ | |||||
| return ""; | |||||
| } | |||||
| sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.dbType).append(" ").append(this.val); | |||||
| return sb.toString(); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,116 @@ | |||||
| package org.jeecg.common.system.query; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * Query 规则 常量 | |||||
| * @Author Scott | |||||
| * @Date 2019年02月14日 | |||||
| */ | |||||
| public enum QueryRuleEnum { | |||||
| /**查询规则 大于*/ | |||||
| GT(">","gt","大于"), | |||||
| /**查询规则 大于等于*/ | |||||
| GE(">=","ge","大于等于"), | |||||
| /**查询规则 小于*/ | |||||
| LT("<","lt","小于"), | |||||
| /**查询规则 小于等于*/ | |||||
| LE("<=","le","小于等于"), | |||||
| /**查询规则 等于*/ | |||||
| EQ("=","eq","等于"), | |||||
| /**查询规则 不等于*/ | |||||
| NE("!=","ne","不等于"), | |||||
| /**查询规则 包含*/ | |||||
| IN("IN","in","包含"), | |||||
| /**查询规则 全模糊*/ | |||||
| LIKE("LIKE","like","全模糊"), | |||||
| /**查询规则 不模糊包含*/ | |||||
| NOT_LIKE("NOT_LIKE","not_like","不模糊包含"), | |||||
| /**查询规则 左模糊*/ | |||||
| LEFT_LIKE("LEFT_LIKE","left_like","左模糊"), | |||||
| /**查询规则 右模糊*/ | |||||
| RIGHT_LIKE("RIGHT_LIKE","right_like","右模糊"), | |||||
| /**查询规则 带加号等于*/ | |||||
| EQ_WITH_ADD("EQWITHADD","eq_with_add","带加号等于"), | |||||
| /**查询规则 多词模糊匹配(and)*/ | |||||
| LIKE_WITH_AND("LIKEWITHAND","like_with_and","多词模糊匹配————暂时未用上"), | |||||
| /**查询规则 多词模糊匹配(or)*/ | |||||
| LIKE_WITH_OR("LIKEWITHOR","like_with_or","多词模糊匹配(or)"), | |||||
| /**查询规则 自定义SQL片段*/ | |||||
| SQL_RULES("USE_SQL_RULES","ext","自定义SQL片段"), | |||||
| /** 查询工作表 */ | |||||
| LINKAGE("LINKAGE","linkage","查询工作表"), | |||||
| // ------- 当前表单设计器内专用 ------- | |||||
| /**查询规则 不以…结尾*/ | |||||
| NOT_LEFT_LIKE("NOT_LEFT_LIKE","not_left_like","不以…结尾"), | |||||
| /**查询规则 不以…开头*/ | |||||
| NOT_RIGHT_LIKE("NOT_RIGHT_LIKE","not_right_like","不以…开头"), | |||||
| /** 值为空 */ | |||||
| EMPTY("EMPTY","empty","值为空"), | |||||
| /** 值不为空 */ | |||||
| NOT_EMPTY("NOT_EMPTY","not_empty","值不为空"), | |||||
| /**查询规则 不包含*/ | |||||
| NOT_IN("NOT_IN","not_in","不包含"), | |||||
| /**查询规则 多词精确匹配*/ | |||||
| ELE_MATCH("ELE_MATCH","elemMatch","多词匹配"), | |||||
| /**查询规则 多词精确不匹配*/ | |||||
| ELE_NOT_MATCH("ELE_NOT_MATCH","elemNotMatch","多词精确不匹配"), | |||||
| /**查询规则 范围查询*/ | |||||
| RANGE("RANGE","range","范围查询"), | |||||
| /**查询规则 不在范围内查询*/ | |||||
| NOT_RANGE("NOT_RANGE","not_range","不在范围查询"), | |||||
| /** 自定义mongodb查询语句 */ | |||||
| CUSTOM_MONGODB("CUSTOM_MONGODB","custom_mongodb","自定义mongodb查询语句"); | |||||
| // ------- 当前表单设计器内专用 ------- | |||||
| private String value; | |||||
| private String condition; | |||||
| private String msg; | |||||
| QueryRuleEnum(String value, String condition, String msg){ | |||||
| this.value = value; | |||||
| this.condition = condition; | |||||
| this.msg = msg; | |||||
| } | |||||
| public String getValue() { | |||||
| return value; | |||||
| } | |||||
| public void setValue(String value) { | |||||
| this.value = value; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public String getCondition() { | |||||
| return condition; | |||||
| } | |||||
| public void setCondition(String condition) { | |||||
| this.condition = condition; | |||||
| } | |||||
| public static QueryRuleEnum getByValue(String value){ | |||||
| if(oConvertUtils.isEmpty(value)) { | |||||
| return null; | |||||
| } | |||||
| for(QueryRuleEnum val :values()){ | |||||
| if (val.getValue().equals(value) || val.getCondition().equalsIgnoreCase(value)){ | |||||
| return val; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,106 @@ | |||||
| package org.jeecg.common.system.util; | |||||
| import org.jeecg.common.system.vo.SysPermissionDataRuleModel; | |||||
| import org.jeecg.common.system.vo.SysUserCacheInfo; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.springframework.util.StringUtils; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * @ClassName: JeecgDataAutorUtils | |||||
| * @Description: 数据权限查询规则容器工具类 | |||||
| * @Author: 张代浩 | |||||
| * @Date: 2012-12-15 下午11:27:39 | |||||
| * | |||||
| */ | |||||
| public class JeecgDataAutorUtils { | |||||
| public static final String MENU_DATA_AUTHOR_RULES = "MENU_DATA_AUTHOR_RULES"; | |||||
| public static final String MENU_DATA_AUTHOR_RULE_SQL = "MENU_DATA_AUTHOR_RULE_SQL"; | |||||
| public static final String SYS_USER_INFO = "SYS_USER_INFO"; | |||||
| /** | |||||
| * 往链接请求里面,传入数据查询条件 | |||||
| * | |||||
| * @param request | |||||
| * @param dataRules | |||||
| */ | |||||
| public static synchronized void installDataSearchConditon(HttpServletRequest request, List<SysPermissionDataRuleModel> dataRules) { | |||||
| @SuppressWarnings("unchecked") | |||||
| // 1.先从request获取MENU_DATA_AUTHOR_RULES,如果存则获取到LIST | |||||
| List<SysPermissionDataRuleModel> list = (List<SysPermissionDataRuleModel>)loadDataSearchConditon(); | |||||
| if (list==null) { | |||||
| // 2.如果不存在,则new一个list | |||||
| list = new ArrayList<SysPermissionDataRuleModel>(); | |||||
| } | |||||
| for (SysPermissionDataRuleModel tsDataRule : dataRules) { | |||||
| list.add(tsDataRule); | |||||
| } | |||||
| // 3.往list里面增量存指 | |||||
| request.setAttribute(MENU_DATA_AUTHOR_RULES, list); | |||||
| } | |||||
| /** | |||||
| * 获取请求对应的数据权限规则 | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| @SuppressWarnings("unchecked") | |||||
| public static synchronized List<SysPermissionDataRuleModel> loadDataSearchConditon() { | |||||
| return (List<SysPermissionDataRuleModel>) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULES); | |||||
| } | |||||
| /** | |||||
| * 获取请求对应的数据权限SQL | |||||
| * | |||||
| * @return | |||||
| */ | |||||
| public static synchronized String loadDataSearchConditonSqlString() { | |||||
| return (String) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULE_SQL); | |||||
| } | |||||
| /** | |||||
| * 往链接请求里面,传入数据查询条件 | |||||
| * | |||||
| * @param request | |||||
| * @param sql | |||||
| */ | |||||
| public static synchronized void installDataSearchConditon(HttpServletRequest request, String sql) { | |||||
| String ruleSql = (String) loadDataSearchConditonSqlString(); | |||||
| if (!StringUtils.hasText(ruleSql)) { | |||||
| request.setAttribute(MENU_DATA_AUTHOR_RULE_SQL,sql); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 将用户信息存到request | |||||
| * @param request | |||||
| * @param userinfo | |||||
| */ | |||||
| public static synchronized void installUserInfo(HttpServletRequest request, SysUserCacheInfo userinfo) { | |||||
| request.setAttribute(SYS_USER_INFO, userinfo); | |||||
| } | |||||
| /** | |||||
| * 将用户信息存到request | |||||
| * @param userinfo | |||||
| */ | |||||
| public static synchronized void installUserInfo(SysUserCacheInfo userinfo) { | |||||
| SpringContextUtils.getHttpServletRequest().setAttribute(SYS_USER_INFO, userinfo); | |||||
| } | |||||
| /** | |||||
| * 从request获取用户信息 | |||||
| * @return | |||||
| */ | |||||
| public static synchronized SysUserCacheInfo loadUserInfo() { | |||||
| return (SysUserCacheInfo) SpringContextUtils.getHttpServletRequest().getAttribute(SYS_USER_INFO); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,333 @@ | |||||
| package org.jeecg.common.system.util; | |||||
| import com.auth0.jwt.JWT; | |||||
| import com.auth0.jwt.JWTVerifier; | |||||
| import com.auth0.jwt.algorithms.Algorithm; | |||||
| import com.auth0.jwt.exceptions.JWTDecodeException; | |||||
| import com.auth0.jwt.interfaces.DecodedJWT; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import java.io.IOException; | |||||
| import java.io.OutputStream; | |||||
| import java.util.Date; | |||||
| import java.util.Objects; | |||||
| import java.util.stream.Collectors; | |||||
| import javax.servlet.ServletResponse; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import javax.servlet.http.HttpSession; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.shiro.SecurityUtils; | |||||
| import org.jeecg.common.api.vo.Result; | |||||
| import org.jeecg.common.constant.CommonConstant; | |||||
| import org.jeecg.common.constant.DataBaseConstant; | |||||
| import org.jeecg.common.constant.SymbolConstant; | |||||
| import org.jeecg.common.constant.TenantConstant; | |||||
| import org.jeecg.common.exception.JeecgBootException; | |||||
| import org.jeecg.common.system.vo.LoginUser; | |||||
| import org.jeecg.common.system.vo.SysUserCacheInfo; | |||||
| import org.jeecg.common.util.DateUtils; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| /** | |||||
| * @Author Scott | |||||
| * @Date 2018-07-12 14:23 | |||||
| * @Desc JWT工具类 | |||||
| **/ | |||||
| @Slf4j | |||||
| public class JwtUtil { | |||||
| /**Token有效期为7天(Token在reids中缓存时间为两倍)*/ | |||||
| public static final long EXPIRE_TIME = (7 * 12) * 60 * 60 * 1000; | |||||
| static final String WELL_NUMBER = SymbolConstant.WELL_NUMBER + SymbolConstant.LEFT_CURLY_BRACKET; | |||||
| /** | |||||
| * | |||||
| * @param response | |||||
| * @param code | |||||
| * @param errorMsg | |||||
| */ | |||||
| public static void responseError(ServletResponse response, Integer code, String errorMsg) { | |||||
| HttpServletResponse httpServletResponse = (HttpServletResponse) response; | |||||
| // issues/I4YH95浏览器显示乱码问题 | |||||
| httpServletResponse.setHeader("Content-type", "text/html;charset=UTF-8"); | |||||
| Result jsonResult = new Result(code, errorMsg); | |||||
| jsonResult.setSuccess(false); | |||||
| OutputStream os = null; | |||||
| try { | |||||
| os = httpServletResponse.getOutputStream(); | |||||
| httpServletResponse.setCharacterEncoding("UTF-8"); | |||||
| httpServletResponse.setStatus(code); | |||||
| os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8")); | |||||
| os.flush(); | |||||
| os.close(); | |||||
| } catch (IOException e) { | |||||
| log.error(e.getMessage(), e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 校验token是否正确 | |||||
| * | |||||
| * @param token 密钥 | |||||
| * @param secret 用户的密码 | |||||
| * @return 是否正确 | |||||
| */ | |||||
| public static boolean verify(String token, String username, String secret) { | |||||
| try { | |||||
| // 根据密码生成JWT效验器 | |||||
| Algorithm algorithm = Algorithm.HMAC256(secret); | |||||
| JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build(); | |||||
| // 效验TOKEN | |||||
| DecodedJWT jwt = verifier.verify(token); | |||||
| return true; | |||||
| } catch (Exception e) { | |||||
| log.error(e.getMessage(), e); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获得token中的信息无需secret解密也能获得 | |||||
| * | |||||
| * @return token中包含的用户名 | |||||
| */ | |||||
| public static String getUsername(String token) { | |||||
| try { | |||||
| DecodedJWT jwt = JWT.decode(token); | |||||
| return jwt.getClaim("username").asString(); | |||||
| } catch (JWTDecodeException e) { | |||||
| log.warn(e.getMessage(), e); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 生成签名,5min后过期 | |||||
| * | |||||
| * @param username 用户名 | |||||
| * @param secret 用户的密码 | |||||
| * @return 加密的token | |||||
| */ | |||||
| public static String sign(String username, String secret) { | |||||
| Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); | |||||
| Algorithm algorithm = Algorithm.HMAC256(secret); | |||||
| // 附带username信息 | |||||
| return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm); | |||||
| } | |||||
| /** | |||||
| * 根据request中的token获取用户账号 | |||||
| * | |||||
| * @param request | |||||
| * @return | |||||
| * @throws JeecgBootException | |||||
| */ | |||||
| public static String getUserNameByToken(HttpServletRequest request) throws JeecgBootException { | |||||
| String accessToken = request.getHeader("X-Access-Token"); | |||||
| String username = getUsername(accessToken); | |||||
| if (oConvertUtils.isEmpty(username)) { | |||||
| throw new JeecgBootException("未获取到用户"); | |||||
| } | |||||
| return username; | |||||
| } | |||||
| /** | |||||
| * 从session中获取变量 | |||||
| * @param key | |||||
| * @return | |||||
| */ | |||||
| public static String getSessionData(String key) { | |||||
| //${myVar}% | |||||
| //得到${} 后面的值 | |||||
| String moshi = ""; | |||||
| String wellNumber = WELL_NUMBER; | |||||
| if(key.indexOf(SymbolConstant.RIGHT_CURLY_BRACKET)!=-1){ | |||||
| moshi = key.substring(key.indexOf("}")+1); | |||||
| } | |||||
| String returnValue = null; | |||||
| if (key.contains(wellNumber)) { | |||||
| key = key.substring(2,key.indexOf("}")); | |||||
| } | |||||
| if (oConvertUtils.isNotEmpty(key)) { | |||||
| HttpSession session = SpringContextUtils.getHttpServletRequest().getSession(); | |||||
| returnValue = (String) session.getAttribute(key); | |||||
| } | |||||
| //结果加上${} 后面的值 | |||||
| if(returnValue!=null){returnValue = returnValue + moshi;} | |||||
| return returnValue; | |||||
| } | |||||
| /** | |||||
| * 从当前用户中获取变量 | |||||
| * @param key | |||||
| * @param user | |||||
| * @return | |||||
| */ | |||||
| public static String getUserSystemData(String key, SysUserCacheInfo user) { | |||||
| //1.优先获取 SysUserCacheInfo | |||||
| if(user==null) { | |||||
| try { | |||||
| user = JeecgDataAutorUtils.loadUserInfo(); | |||||
| } catch (Exception e) { | |||||
| log.warn("获取用户信息异常:" + e.getMessage()); | |||||
| } | |||||
| } | |||||
| //2.通过shiro获取登录用户信息 | |||||
| LoginUser sysUser = null; | |||||
| try { | |||||
| sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | |||||
| } catch (Exception e) { | |||||
| log.warn("SecurityUtils.getSubject() 获取用户信息异常:" + e.getMessage()); | |||||
| } | |||||
| //#{sys_user_code}% | |||||
| String moshi = ""; | |||||
| String wellNumber = WELL_NUMBER; | |||||
| if(key.indexOf(SymbolConstant.RIGHT_CURLY_BRACKET)!=-1){ | |||||
| moshi = key.substring(key.indexOf("}")+1); | |||||
| } | |||||
| String returnValue = null; | |||||
| //针对特殊标示处理#{sysOrgCode},判断替换 | |||||
| if (key.contains(wellNumber)) { | |||||
| key = key.substring(2,key.indexOf("}")); | |||||
| } else { | |||||
| key = key; | |||||
| } | |||||
| //update-begin---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| // 是否存在字符串标志 | |||||
| boolean multiStr; | |||||
| if(oConvertUtils.isNotEmpty(key) && key.trim().matches("^\\[\\w+]$")){ | |||||
| key = key.substring(1,key.length()-1); | |||||
| multiStr = true; | |||||
| } else { | |||||
| multiStr = false; | |||||
| } | |||||
| //update-end---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| //替换为当前系统时间(年月日) | |||||
| if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) { | |||||
| returnValue = DateUtils.formatDate(); | |||||
| } | |||||
| //替换为当前系统时间(年月日时分秒) | |||||
| else if (key.equals(DataBaseConstant.SYS_TIME)|| key.toLowerCase().equals(DataBaseConstant.SYS_TIME_TABLE)) { | |||||
| returnValue = DateUtils.now(); | |||||
| } | |||||
| //流程状态默认值(默认未发起) | |||||
| else if (key.equals(DataBaseConstant.BPM_STATUS)|| key.toLowerCase().equals(DataBaseConstant.BPM_STATUS_TABLE)) { | |||||
| returnValue = "1"; | |||||
| } | |||||
| //后台任务获取用户信息异常,导致程序中断 | |||||
| if(sysUser==null && user==null){ | |||||
| return null; | |||||
| } | |||||
| //替换为系统登录用户帐号 | |||||
| if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) { | |||||
| if(user==null) { | |||||
| returnValue = sysUser.getUsername(); | |||||
| }else { | |||||
| returnValue = user.getSysUserCode(); | |||||
| } | |||||
| } | |||||
| // 替换为系统登录用户ID | |||||
| else if (key.equals(DataBaseConstant.SYS_USER_ID) || key.equalsIgnoreCase(DataBaseConstant.SYS_USER_ID_TABLE)) { | |||||
| if(user==null) { | |||||
| returnValue = sysUser.getId(); | |||||
| }else { | |||||
| returnValue = user.getSysUserId(); | |||||
| } | |||||
| } | |||||
| //替换为系统登录用户真实名字 | |||||
| else if (key.equals(DataBaseConstant.SYS_USER_NAME)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_NAME_TABLE)) { | |||||
| if(user==null) { | |||||
| returnValue = sysUser.getRealname(); | |||||
| }else { | |||||
| returnValue = user.getSysUserName(); | |||||
| } | |||||
| } | |||||
| //替换为系统用户登录所使用的机构编码 | |||||
| else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) { | |||||
| if(user==null) { | |||||
| returnValue = sysUser.getOrgCode(); | |||||
| }else { | |||||
| returnValue = user.getSysOrgCode(); | |||||
| } | |||||
| } | |||||
| // 替换为系统用户登录所使用的机构ID | |||||
| else if (key.equals(DataBaseConstant.SYS_ORG_ID) || key.equalsIgnoreCase(DataBaseConstant.SYS_ORG_ID_TABLE)) { | |||||
| if (user == null) { | |||||
| returnValue = sysUser.getOrgId(); | |||||
| } else { | |||||
| returnValue = user.getSysOrgId(); | |||||
| } | |||||
| } | |||||
| //替换为系统用户所拥有的所有机构编码 | |||||
| else if (key.equals(DataBaseConstant.SYS_MULTI_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE)) { | |||||
| if(user==null){ | |||||
| //TODO 暂时使用用户登录部门,存在逻辑缺陷,不是用户所拥有的部门 | |||||
| returnValue = sysUser.getOrgCode(); | |||||
| //update-begin---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| returnValue = multiStr ? "'" + returnValue + "'" : returnValue; | |||||
| //update-end---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| }else{ | |||||
| if(user.isOneDepart()) { | |||||
| returnValue = user.getSysMultiOrgCode().get(0); | |||||
| //update-begin---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| returnValue = multiStr ? "'" + returnValue + "'" : returnValue; | |||||
| //update-end---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| }else { | |||||
| //update-begin---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| returnValue = user.getSysMultiOrgCode().stream() | |||||
| .filter(Objects::nonNull) | |||||
| //update-begin---author:chenrui ---date:20250224 for:[issues/7288]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| .map(orgCode -> { | |||||
| if (multiStr) { | |||||
| return "'" + orgCode + "'"; | |||||
| } else { | |||||
| return orgCode; | |||||
| } | |||||
| }) | |||||
| //update-end---author:chenrui ---date:20250224 for:[issues/7288]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| .collect(Collectors.joining(", ")); | |||||
| //update-end---author:chenrui ---date:20250107 for:[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------ | |||||
| } | |||||
| } | |||||
| } | |||||
| // 替换为当前登录用户的角色code(多个逗号分割) | |||||
| else if (key.equals(DataBaseConstant.SYS_ROLE_CODE) || key.equalsIgnoreCase(DataBaseConstant.SYS_ROLE_CODE_TABLE)) { | |||||
| if (user == null) { | |||||
| returnValue = sysUser.getRoleCode(); | |||||
| } else { | |||||
| returnValue = user.getSysRoleCode(); | |||||
| } | |||||
| } | |||||
| //update-begin-author:taoyan date:20210330 for:多租户ID作为系统变量 | |||||
| else if (key.equals(TenantConstant.TENANT_ID) || key.toLowerCase().equals(TenantConstant.TENANT_ID_TABLE)){ | |||||
| try { | |||||
| returnValue = SpringContextUtils.getHttpServletRequest().getHeader(CommonConstant.TENANT_ID); | |||||
| } catch (Exception e) { | |||||
| log.warn("获取系统租户异常:" + e.getMessage()); | |||||
| } | |||||
| } | |||||
| //update-end-author:taoyan date:20210330 for:多租户ID作为系统变量 | |||||
| if(returnValue!=null){returnValue = returnValue + moshi;} | |||||
| return returnValue; | |||||
| } | |||||
| // public static void main(String[] args) { | |||||
| // String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0"; | |||||
| // System.out.println(JwtUtil.getUsername(token)); | |||||
| // } | |||||
| } | |||||
| @ -0,0 +1,136 @@ | |||||
| package org.jeecg.common.system.util; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.jeecg.common.system.annotation.EnumDict; | |||||
| import org.jeecg.common.system.vo.DictModel; | |||||
| import org.jeecg.common.util.SpringContextUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import org.springframework.beans.factory.NoSuchBeanDefinitionException; | |||||
| import org.springframework.core.io.Resource; | |||||
| import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | |||||
| import org.springframework.core.io.support.ResourcePatternResolver; | |||||
| import org.springframework.core.type.classreading.CachingMetadataReaderFactory; | |||||
| import org.springframework.core.type.classreading.MetadataReader; | |||||
| import org.springframework.core.type.classreading.MetadataReaderFactory; | |||||
| import org.springframework.util.ClassUtils; | |||||
| import java.util.ArrayList; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * 资源加载工具类 | |||||
| * @Author taoYan | |||||
| * @Date 2022/7/8 10:40 | |||||
| **/ | |||||
| @Slf4j | |||||
| public class ResourceUtil { | |||||
| /** | |||||
| * 枚举字典数据 | |||||
| */ | |||||
| private final static Map<String, List<DictModel>> enumDictData = new HashMap<>(5); | |||||
| /** | |||||
| * 所有java类 | |||||
| */ | |||||
| private final static String CLASS_PATTERN="/**/*.class"; | |||||
| /** | |||||
| * 所有枚举java类 | |||||
| */ | |||||
| private final static String CLASS_ENUM_PATTERN="/**/*Enum.class"; | |||||
| /** | |||||
| * 包路径 org.jeecg | |||||
| */ | |||||
| private final static String BASE_PACKAGE = "org.jeecg"; | |||||
| /** | |||||
| * 枚举类中获取字典数据的方法名 | |||||
| */ | |||||
| private final static String METHOD_NAME = "getDictList"; | |||||
| /** | |||||
| * 获取枚举类对应的字典数据 SysDictServiceImpl#queryAllDictItems() | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, List<DictModel>> getEnumDictData(){ | |||||
| if(enumDictData.keySet().size()>0){ | |||||
| return enumDictData; | |||||
| } | |||||
| ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); | |||||
| String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + CLASS_ENUM_PATTERN; | |||||
| try { | |||||
| Resource[] resources = resourcePatternResolver.getResources(pattern); | |||||
| MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); | |||||
| for (Resource resource : resources) { | |||||
| MetadataReader reader = readerFactory.getMetadataReader(resource); | |||||
| String classname = reader.getClassMetadata().getClassName(); | |||||
| Class<?> clazz = Class.forName(classname); | |||||
| EnumDict enumDict = clazz.getAnnotation(EnumDict.class); | |||||
| if (enumDict != null) { | |||||
| EnumDict annotation = clazz.getAnnotation(EnumDict.class); | |||||
| String key = annotation.value(); | |||||
| if(oConvertUtils.isNotEmpty(key)){ | |||||
| List<DictModel> list = (List<DictModel>) clazz.getDeclaredMethod(METHOD_NAME).invoke(null); | |||||
| enumDictData.put(key, list); | |||||
| } | |||||
| } | |||||
| } | |||||
| }catch (Exception e){ | |||||
| log.error("获取枚举类字典数据异常", e.getMessage()); | |||||
| // e.printStackTrace(); | |||||
| } | |||||
| return enumDictData; | |||||
| } | |||||
| /** | |||||
| * 用于后端字典翻译 SysDictServiceImpl#queryManyDictByKeys(java.util.List, java.util.List) | |||||
| * @param dictCodeList | |||||
| * @param keys | |||||
| * @return | |||||
| */ | |||||
| public static Map<String, List<DictModel>> queryManyDictByKeys(List<String> dictCodeList, List<String> keys){ | |||||
| if(enumDictData.keySet().size()==0){ | |||||
| getEnumDictData(); | |||||
| } | |||||
| Map<String, List<DictModel>> map = new HashMap<>(); | |||||
| for (String code : enumDictData.keySet()) { | |||||
| if(dictCodeList.indexOf(code)>=0){ | |||||
| List<DictModel> dictItemList = enumDictData.get(code); | |||||
| for(DictModel dm: dictItemList){ | |||||
| String value = dm.getValue(); | |||||
| if(keys.indexOf(value)>=0){ | |||||
| List<DictModel> list = new ArrayList<>(); | |||||
| list.add(new DictModel(value, dm.getText())); | |||||
| map.put(code,list); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return map; | |||||
| } | |||||
| /** | |||||
| * 获取实现类 | |||||
| * | |||||
| * @param classPath | |||||
| */ | |||||
| public static Object getImplementationClass(String classPath){ | |||||
| try { | |||||
| Class<?> aClass = Class.forName(classPath); | |||||
| return SpringContextUtils.getBean(aClass); | |||||
| } catch (ClassNotFoundException e) { | |||||
| log.error("类没有找到",e); | |||||
| return null; | |||||
| } catch (NoSuchBeanDefinitionException e){ | |||||
| log.error(classPath + "没有实现",e); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,243 @@ | |||||
| package org.jeecg.common.system.util; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.jeecg.common.constant.DataBaseConstant; | |||||
| import org.jeecg.common.constant.SymbolConstant; | |||||
| import org.jeecg.common.system.query.QueryGenerator; | |||||
| import org.jeecg.common.system.query.QueryRuleEnum; | |||||
| import org.jeecg.common.util.CommonUtils; | |||||
| import org.jeecg.common.util.oConvertUtils; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| /** | |||||
| * @Description: 查询过滤器,SQL拼接写法拆成独立工具类 | |||||
| * @author:qinfeng | |||||
| * @date 20230904 | |||||
| */ | |||||
| @Slf4j | |||||
| public class SqlConcatUtil { | |||||
| /** | |||||
| * 获取单个查询条件的值 | |||||
| * @param rule | |||||
| * @param field | |||||
| * @param value | |||||
| * @param isString | |||||
| * @return | |||||
| */ | |||||
| public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) { | |||||
| return getSingleSqlByRule(rule, field, value, isString, null); | |||||
| } | |||||
| /** | |||||
| * 报表获取查询条件 支持多数据源 | |||||
| * @param field | |||||
| * @param alias | |||||
| * @param value | |||||
| * @param isString | |||||
| * @param dataBaseType | |||||
| * @return | |||||
| */ | |||||
| public static String getSingleQueryConditionSql(String field,String alias,Object value,boolean isString, String dataBaseType) { | |||||
| if (value == null) { | |||||
| return ""; | |||||
| } | |||||
| field = alias+oConvertUtils.camelToUnderline(field); | |||||
| QueryRuleEnum rule = QueryGenerator.convert2Rule(value); | |||||
| return getSingleSqlByRule(rule, field, value, isString, dataBaseType); | |||||
| } | |||||
| /** | |||||
| * 获取单个查询条件的值 | |||||
| * @param rule | |||||
| * @param field | |||||
| * @param value | |||||
| * @param isString | |||||
| * @param dataBaseType | |||||
| * @return | |||||
| */ | |||||
| private static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) { | |||||
| String res = ""; | |||||
| switch (rule) { | |||||
| case GT: | |||||
| res =field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case GE: | |||||
| res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case LT: | |||||
| res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case LE: | |||||
| res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case EQ: | |||||
| res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case EQ_WITH_ADD: | |||||
| res = field+" = "+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case NE: | |||||
| res = field+" <> "+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| case IN: | |||||
| res = field + " in "+getInConditionValue(value, isString); | |||||
| break; | |||||
| case LIKE: | |||||
| res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.LIKE); | |||||
| break; | |||||
| case LEFT_LIKE: | |||||
| res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.LEFT_LIKE); | |||||
| break; | |||||
| case RIGHT_LIKE: | |||||
| res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.RIGHT_LIKE); | |||||
| break; | |||||
| default: | |||||
| res = field+" = "+getFieldConditionValue(value, isString, dataBaseType); | |||||
| break; | |||||
| } | |||||
| return res; | |||||
| } | |||||
| /** | |||||
| * 获取查询条件的值 | |||||
| * @param value | |||||
| * @param isString | |||||
| * @param dataBaseType | |||||
| * @return | |||||
| */ | |||||
| private static String getFieldConditionValue(Object value,boolean isString, String dataBaseType) { | |||||
| String str = value.toString().trim(); | |||||
| if(str.startsWith(SymbolConstant.EXCLAMATORY_MARK)) { | |||||
| str = str.substring(1); | |||||
| }else if(str.startsWith(QueryRuleEnum.GE.getValue())) { | |||||
| str = str.substring(2); | |||||
| }else if(str.startsWith(QueryRuleEnum.LE.getValue())) { | |||||
| str = str.substring(2); | |||||
| }else if(str.startsWith(QueryRuleEnum.GT.getValue())) { | |||||
| str = str.substring(1); | |||||
| }else if(str.startsWith(QueryRuleEnum.LT.getValue())) { | |||||
| str = str.substring(1); | |||||
| }else if(str.indexOf(QueryGenerator.QUERY_COMMA_ESCAPE)>0) { | |||||
| str = str.replaceAll("\\+\\+", SymbolConstant.COMMA); | |||||
| } | |||||
| if(dataBaseType==null){ | |||||
| dataBaseType = getDbType(); | |||||
| } | |||||
| if(isString) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType)){ | |||||
| return " N'"+str+"' "; | |||||
| }else{ | |||||
| return " '"+str+"' "; | |||||
| } | |||||
| }else { | |||||
| // 如果不是字符串 有一种特殊情况 popup调用都走这个逻辑 参数传递的可能是“‘admin’”这种格式的 | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK)){ | |||||
| return " N"+str; | |||||
| } | |||||
| return value.toString(); | |||||
| } | |||||
| } | |||||
| private static String getInConditionValue(Object value,boolean isString) { | |||||
| //update-begin-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错 | |||||
| String[] temp = value.toString().split(","); | |||||
| if(temp.length==0){ | |||||
| return "('')"; | |||||
| } | |||||
| if(isString) { | |||||
| List<String> res = new ArrayList<>(); | |||||
| for (String string : temp) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | |||||
| res.add("N'"+string+"'"); | |||||
| }else{ | |||||
| res.add("'"+string+"'"); | |||||
| } | |||||
| } | |||||
| return "("+String.join("," ,res)+")"; | |||||
| }else { | |||||
| return "("+value.toString()+")"; | |||||
| } | |||||
| //update-end-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错 | |||||
| } | |||||
| /** | |||||
| * 先根据值判断 走左模糊还是右模糊 | |||||
| * 最后如果值不带任何标识(*或者%),则再根据ruleEnum判断 | |||||
| * @param value | |||||
| * @param ruleEnum | |||||
| * @return | |||||
| */ | |||||
| private static String getLikeConditionValue(Object value, QueryRuleEnum ruleEnum) { | |||||
| String str = value.toString().trim(); | |||||
| if(str.startsWith(SymbolConstant.ASTERISK) && str.endsWith(SymbolConstant.ASTERISK)) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | |||||
| return "N'%"+str.substring(1,str.length()-1)+"%'"; | |||||
| }else{ | |||||
| return "'%"+str.substring(1,str.length()-1)+"%'"; | |||||
| } | |||||
| }else if(str.startsWith(SymbolConstant.ASTERISK)) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | |||||
| return "N'%"+str.substring(1)+"'"; | |||||
| }else{ | |||||
| return "'%"+str.substring(1)+"'"; | |||||
| } | |||||
| }else if(str.endsWith(SymbolConstant.ASTERISK)) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | |||||
| return "N'"+str.substring(0,str.length()-1)+"%'"; | |||||
| }else{ | |||||
| return "'"+str.substring(0,str.length()-1)+"%'"; | |||||
| } | |||||
| }else { | |||||
| if(str.indexOf(SymbolConstant.PERCENT_SIGN)>=0) { | |||||
| if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | |||||
| if(str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK)){ | |||||
| return "N"+str; | |||||
| }else{ | |||||
| return "N"+"'"+str+"'"; | |||||
| } | |||||
| }else{ | |||||
| if(str.startsWith(SymbolConstant.SINGLE_QUOTATION_MARK) && str.endsWith(SymbolConstant.SINGLE_QUOTATION_MARK)){ | |||||
| return str; | |||||
| }else{ | |||||
| return "'"+str+"'"; | |||||
| } | |||||
| } | |||||
| }else { | |||||
| //update-begin-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题 | |||||
| // 走到这里说明 value不带有任何模糊查询的标识(*或者%) | |||||
| if (ruleEnum == QueryRuleEnum.LEFT_LIKE) { | |||||
| if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | |||||
| return "N'%" + str + "'"; | |||||
| } else { | |||||
| return "'%" + str + "'"; | |||||
| } | |||||
| } else if (ruleEnum == QueryRuleEnum.RIGHT_LIKE) { | |||||
| if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | |||||
| return "N'" + str + "%'"; | |||||
| } else { | |||||
| return "'" + str + "%'"; | |||||
| } | |||||
| } else { | |||||
| if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | |||||
| return "N'%" + str + "%'"; | |||||
| } else { | |||||
| return "'%" + str + "%'"; | |||||
| } | |||||
| } | |||||
| //update-end-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题 | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取系统数据库类型 | |||||
| */ | |||||
| private static String getDbType() { | |||||
| return CommonUtils.getDatabaseType(); | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,40 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @Description: 文档管理 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = false) | |||||
| @Accessors(chain = true) | |||||
| @JsonIgnoreProperties(ignoreUnknown = true) | |||||
| public class ComboModel implements Serializable { | |||||
| private String id; | |||||
| private String title; | |||||
| /**文档管理 表单table默认选中*/ | |||||
| private boolean checked; | |||||
| /**文档管理 表单table 用户账号*/ | |||||
| private String username; | |||||
| /**文档管理 表单table 用户邮箱*/ | |||||
| private String email; | |||||
| /**文档管理 表单table 角色编码*/ | |||||
| private String roleCode; | |||||
| public ComboModel(){ | |||||
| }; | |||||
| public ComboModel(String id,String title,boolean checked,String username){ | |||||
| this.id = id; | |||||
| this.title = title; | |||||
| this.checked = false; | |||||
| this.username = username; | |||||
| }; | |||||
| } | |||||
| @ -0,0 +1,71 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import java.io.Serializable; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.experimental.Accessors; | |||||
| /** | |||||
| * @Description: 字典类 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = false) | |||||
| @Accessors(chain = true) | |||||
| @JsonIgnoreProperties(ignoreUnknown = true) | |||||
| public class DictModel implements Serializable{ | |||||
| private static final long serialVersionUID = 1L; | |||||
| public DictModel() { | |||||
| } | |||||
| public DictModel(String value, String text) { | |||||
| this.value = value; | |||||
| this.text = text; | |||||
| } | |||||
| public DictModel(String value, String text, String color) { | |||||
| this.value = value; | |||||
| this.text = text; | |||||
| this.color = color; | |||||
| } | |||||
| /** | |||||
| * 字典value | |||||
| */ | |||||
| private String value; | |||||
| /** | |||||
| * 字典文本 | |||||
| */ | |||||
| private String text; | |||||
| /** | |||||
| * 字典颜色 | |||||
| */ | |||||
| private String color; | |||||
| /** | |||||
| * 特殊用途: JgEditableTable | |||||
| * @return | |||||
| */ | |||||
| public String getTitle() { | |||||
| return this.text; | |||||
| } | |||||
| /** | |||||
| * 特殊用途: vue3 Select组件 | |||||
| */ | |||||
| public String getLabel() { | |||||
| return this.text; | |||||
| } | |||||
| /** | |||||
| * 用于表单设计器 关联记录表数据存储 | |||||
| * QQYUN-5595【表单设计器】他表字段 导入没有翻译 | |||||
| */ | |||||
| private JSONObject jsonObject; | |||||
| } | |||||
| @ -0,0 +1,19 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| /** | |||||
| * 查询多个字典时用到 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class DictModelMany extends DictModel { | |||||
| /** | |||||
| * 字典code,根据多个字段code查询时才用到,用于区分不同的字典选项 | |||||
| */ | |||||
| private String dictCode; | |||||
| } | |||||
| @ -0,0 +1,35 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import lombok.Data; | |||||
| /** | |||||
| * 字典查询参数实体 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class DictQuery { | |||||
| /** | |||||
| * 表名 | |||||
| */ | |||||
| private String table; | |||||
| /** | |||||
| * 存储列 | |||||
| */ | |||||
| private String code; | |||||
| /** | |||||
| * 显示列 | |||||
| */ | |||||
| private String text; | |||||
| /** | |||||
| * 关键字查询 | |||||
| */ | |||||
| private String keyword; | |||||
| /** | |||||
| * 存储列的值 用于回显查询 | |||||
| */ | |||||
| private String codeValue; | |||||
| } | |||||
| @ -0,0 +1,58 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import lombok.Data; | |||||
| import org.springframework.beans.BeanUtils; | |||||
| /** | |||||
| * @Description: 数据源 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class DynamicDataSourceModel { | |||||
| public DynamicDataSourceModel() { | |||||
| } | |||||
| public DynamicDataSourceModel(Object dbSource) { | |||||
| if (dbSource != null) { | |||||
| BeanUtils.copyProperties(dbSource, this); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * id | |||||
| */ | |||||
| private java.lang.String id; | |||||
| /** | |||||
| * 数据源编码 | |||||
| */ | |||||
| private java.lang.String code; | |||||
| /** | |||||
| * 数据库类型 | |||||
| */ | |||||
| private java.lang.String dbType; | |||||
| /** | |||||
| * 驱动类 | |||||
| */ | |||||
| private java.lang.String dbDriver; | |||||
| /** | |||||
| * 数据源地址 | |||||
| */ | |||||
| private java.lang.String dbUrl; | |||||
| // /** | |||||
| // * 数据库名称 | |||||
| // */ | |||||
| // private java.lang.String dbName; | |||||
| /** | |||||
| * 用户名 | |||||
| */ | |||||
| private java.lang.String dbUsername; | |||||
| /** | |||||
| * 密码 | |||||
| */ | |||||
| private java.lang.String dbPassword; | |||||
| } | |||||
| @ -0,0 +1,141 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.experimental.Accessors; | |||||
| import org.jeecg.common.desensitization.annotation.SensitiveField; | |||||
| import org.springframework.format.annotation.DateTimeFormat; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * <p> | |||||
| * 在线用户信息 | |||||
| * </p> | |||||
| * | |||||
| * @Author scott | |||||
| * @since 2018-12-20 | |||||
| */ | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = false) | |||||
| @Accessors(chain = true) | |||||
| public class LoginUser { | |||||
| /** | |||||
| * 登录人id | |||||
| */ | |||||
| @SensitiveField | |||||
| private String id; | |||||
| /** | |||||
| * 登录人账号 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String username; | |||||
| /** | |||||
| * 登录人名字 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String realname; | |||||
| /** | |||||
| * 登录人密码 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String password; | |||||
| /** | |||||
| * 当前登录部门code | |||||
| */ | |||||
| @SensitiveField | |||||
| private String orgCode; | |||||
| /** | |||||
| * 当前登录部门id | |||||
| */ | |||||
| @SensitiveField | |||||
| private String orgId; | |||||
| /** | |||||
| * 当前登录角色code(多个逗号分割) | |||||
| */ | |||||
| @SensitiveField | |||||
| private String roleCode; | |||||
| /** | |||||
| * 头像 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String avatar; | |||||
| /** | |||||
| * 生日 | |||||
| */ | |||||
| @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") | |||||
| @DateTimeFormat(pattern = "yyyy-MM-dd") | |||||
| private Date birthday; | |||||
| /** | |||||
| * 性别(1:男 2:女) | |||||
| */ | |||||
| private Integer sex; | |||||
| /** | |||||
| * 电子邮件 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String email; | |||||
| /** | |||||
| * 电话 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String phone; | |||||
| /** | |||||
| * 状态(1:正常 2:冻结 ) | |||||
| */ | |||||
| private Integer status; | |||||
| private Integer delFlag; | |||||
| /** | |||||
| * 同步工作流引擎1同步0不同步 | |||||
| */ | |||||
| private Integer activitiSync; | |||||
| /** | |||||
| * 创建时间 | |||||
| */ | |||||
| private Date createTime; | |||||
| /** | |||||
| * 身份(1 普通员工 2 上级) | |||||
| */ | |||||
| private Integer userIdentity; | |||||
| /** | |||||
| * 管理部门ids | |||||
| */ | |||||
| @SensitiveField | |||||
| private String departIds; | |||||
| /** | |||||
| * 职务,关联职务表 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String post; | |||||
| /** | |||||
| * 座机号 | |||||
| */ | |||||
| @SensitiveField | |||||
| private String telephone; | |||||
| /** 多租户ids临时用,不持久化数据库(数据库字段不存在) */ | |||||
| @SensitiveField | |||||
| private String relTenantIds; | |||||
| /**设备id uniapp推送用*/ | |||||
| private String clientId; | |||||
| } | |||||
| @ -0,0 +1,32 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 下拉树 model | |||||
| * | |||||
| * @author jeecg-boot | |||||
| */ | |||||
| @Data | |||||
| public class SelectTreeModel implements Serializable { | |||||
| private String key; | |||||
| private String title; | |||||
| private String value; | |||||
| /** | |||||
| * 父Id | |||||
| */ | |||||
| private String parentId; | |||||
| /** | |||||
| * 是否是叶节点 | |||||
| */ | |||||
| private boolean isLeaf; | |||||
| /** | |||||
| * 子节点 | |||||
| */ | |||||
| private List<SelectTreeModel> children; | |||||
| } | |||||
| @ -0,0 +1,52 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import org.jeecgframework.poi.excel.annotation.Excel; | |||||
| /** | |||||
| * @Author qinfeng | |||||
| * @Date 2020/2/19 12:01 | |||||
| * @Description: | |||||
| * @Version 1.0 | |||||
| */ | |||||
| public class SysCategoryModel { | |||||
| /**主键*/ | |||||
| private java.lang.String id; | |||||
| /**父级节点*/ | |||||
| private java.lang.String pid; | |||||
| /**类型名称*/ | |||||
| private java.lang.String name; | |||||
| /**类型编码*/ | |||||
| private java.lang.String code; | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(String id) { | |||||
| this.id = id; | |||||
| } | |||||
| public String getPid() { | |||||
| return pid; | |||||
| } | |||||
| public void setPid(String pid) { | |||||
| this.pid = pid; | |||||
| } | |||||
| public String getName() { | |||||
| return name; | |||||
| } | |||||
| public void setName(String name) { | |||||
| this.name = name; | |||||
| } | |||||
| public String getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(String code) { | |||||
| this.code = code; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,148 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| /** | |||||
| * 部门机构model | |||||
| * @author: lvdandan | |||||
| */ | |||||
| public class SysDepartModel { | |||||
| /**ID*/ | |||||
| private String id; | |||||
| /**父机构ID*/ | |||||
| private String parentId; | |||||
| /**机构/部门名称*/ | |||||
| private String departName; | |||||
| /**英文名*/ | |||||
| private String departNameEn; | |||||
| /**缩写*/ | |||||
| private String departNameAbbr; | |||||
| /**排序*/ | |||||
| private Integer departOrder; | |||||
| /**描述*/ | |||||
| private String description; | |||||
| /**机构类别 1组织机构,2岗位*/ | |||||
| private String orgCategory; | |||||
| /**机构类型*/ | |||||
| private String orgType; | |||||
| /**机构编码*/ | |||||
| private String orgCode; | |||||
| /**手机号*/ | |||||
| private String mobile; | |||||
| /**传真*/ | |||||
| private String fax; | |||||
| /**地址*/ | |||||
| private String address; | |||||
| /**备注*/ | |||||
| private String memo; | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(String id) { | |||||
| this.id = id; | |||||
| } | |||||
| public String getParentId() { | |||||
| return parentId; | |||||
| } | |||||
| public void setParentId(String parentId) { | |||||
| this.parentId = parentId; | |||||
| } | |||||
| public String getDepartName() { | |||||
| return departName; | |||||
| } | |||||
| public void setDepartName(String departName) { | |||||
| this.departName = departName; | |||||
| } | |||||
| public String getDepartNameEn() { | |||||
| return departNameEn; | |||||
| } | |||||
| public void setDepartNameEn(String departNameEn) { | |||||
| this.departNameEn = departNameEn; | |||||
| } | |||||
| public String getDepartNameAbbr() { | |||||
| return departNameAbbr; | |||||
| } | |||||
| public void setDepartNameAbbr(String departNameAbbr) { | |||||
| this.departNameAbbr = departNameAbbr; | |||||
| } | |||||
| public Integer getDepartOrder() { | |||||
| return departOrder; | |||||
| } | |||||
| public void setDepartOrder(Integer departOrder) { | |||||
| this.departOrder = departOrder; | |||||
| } | |||||
| public String getDescription() { | |||||
| return description; | |||||
| } | |||||
| public void setDescription(String description) { | |||||
| this.description = description; | |||||
| } | |||||
| public String getOrgCategory() { | |||||
| return orgCategory; | |||||
| } | |||||
| public void setOrgCategory(String orgCategory) { | |||||
| this.orgCategory = orgCategory; | |||||
| } | |||||
| public String getOrgType() { | |||||
| return orgType; | |||||
| } | |||||
| public void setOrgType(String orgType) { | |||||
| this.orgType = orgType; | |||||
| } | |||||
| public String getOrgCode() { | |||||
| return orgCode; | |||||
| } | |||||
| public void setOrgCode(String orgCode) { | |||||
| this.orgCode = orgCode; | |||||
| } | |||||
| public String getMobile() { | |||||
| return mobile; | |||||
| } | |||||
| public void setMobile(String mobile) { | |||||
| this.mobile = mobile; | |||||
| } | |||||
| public String getFax() { | |||||
| return fax; | |||||
| } | |||||
| public void setFax(String fax) { | |||||
| this.fax = fax; | |||||
| } | |||||
| public String getAddress() { | |||||
| return address; | |||||
| } | |||||
| public void setAddress(String address) { | |||||
| this.address = address; | |||||
| } | |||||
| public String getMemo() { | |||||
| return memo; | |||||
| } | |||||
| public void setMemo(String memo) { | |||||
| this.memo = memo; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,80 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| /** | |||||
| * @Description: 系统文件实体类 | |||||
| * @author: wangshuai | |||||
| * @date: 2022年08月11日 9:48 | |||||
| */ | |||||
| public class SysFilesModel { | |||||
| /**主键id*/ | |||||
| private String id; | |||||
| /**文件名称*/ | |||||
| private String fileName; | |||||
| /**文件地址*/ | |||||
| private String url; | |||||
| /**文档类型(folder:文件夹 excel:excel doc:word pp:ppt image:图片 archive:其他文档 video:视频)*/ | |||||
| private String fileType; | |||||
| /**文件上传类型(temp/本地上传(临时文件) manage/知识库)*/ | |||||
| private String storeType; | |||||
| /**文件大小(kb)*/ | |||||
| private Double fileSize; | |||||
| /**租户id*/ | |||||
| private String tenantId; | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(String id) { | |||||
| this.id = id; | |||||
| } | |||||
| public String getFileName() { | |||||
| return fileName; | |||||
| } | |||||
| public void setFileName(String fileName) { | |||||
| this.fileName = fileName; | |||||
| } | |||||
| public String getUrl() { | |||||
| return url; | |||||
| } | |||||
| public void setUrl(String url) { | |||||
| this.url = url; | |||||
| } | |||||
| public String getFileType() { | |||||
| return fileType; | |||||
| } | |||||
| public void setFileType(String fileType) { | |||||
| this.fileType = fileType; | |||||
| } | |||||
| public String getStoreType() { | |||||
| return storeType; | |||||
| } | |||||
| public void setStoreType(String storeType) { | |||||
| this.storeType = storeType; | |||||
| } | |||||
| public Double getFileSize() { | |||||
| return fileSize; | |||||
| } | |||||
| public void setFileSize(Double fileSize) { | |||||
| this.fileSize = fileSize; | |||||
| } | |||||
| public String getTenantId() { | |||||
| return tenantId; | |||||
| } | |||||
| public void setTenantId(String tenantId) { | |||||
| this.tenantId = tenantId; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,151 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import com.baomidou.mybatisplus.annotation.IdType; | |||||
| import com.baomidou.mybatisplus.annotation.TableId; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import lombok.experimental.Accessors; | |||||
| import java.io.Serializable; | |||||
| import java.util.Date; | |||||
| /** | |||||
| * <p> | |||||
| * 菜单权限规则表 | |||||
| * </p> | |||||
| * | |||||
| * @Author huangzhilin | |||||
| * @since 2019-03-29 | |||||
| */ | |||||
| public class SysPermissionDataRuleModel { | |||||
| /** | |||||
| * id | |||||
| */ | |||||
| private String id; | |||||
| /** | |||||
| * 对应的菜单id | |||||
| */ | |||||
| private String permissionId; | |||||
| /** | |||||
| * 规则名称 | |||||
| */ | |||||
| private String ruleName; | |||||
| /** | |||||
| * 字段 | |||||
| */ | |||||
| private String ruleColumn; | |||||
| /** | |||||
| * 条件 | |||||
| */ | |||||
| private String ruleConditions; | |||||
| /** | |||||
| * 规则值 | |||||
| */ | |||||
| private String ruleValue; | |||||
| /** | |||||
| * 创建时间 | |||||
| */ | |||||
| private Date createTime; | |||||
| /** | |||||
| * 创建人 | |||||
| */ | |||||
| private String createBy; | |||||
| /** | |||||
| * 修改时间 | |||||
| */ | |||||
| private Date updateTime; | |||||
| /** | |||||
| * 修改人 | |||||
| */ | |||||
| private String updateBy; | |||||
| public String getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(String id) { | |||||
| this.id = id; | |||||
| } | |||||
| public String getPermissionId() { | |||||
| return permissionId; | |||||
| } | |||||
| public void setPermissionId(String permissionId) { | |||||
| this.permissionId = permissionId; | |||||
| } | |||||
| public String getRuleName() { | |||||
| return ruleName; | |||||
| } | |||||
| public void setRuleName(String ruleName) { | |||||
| this.ruleName = ruleName; | |||||
| } | |||||
| public String getRuleColumn() { | |||||
| return ruleColumn; | |||||
| } | |||||
| public void setRuleColumn(String ruleColumn) { | |||||
| this.ruleColumn = ruleColumn; | |||||
| } | |||||
| public String getRuleConditions() { | |||||
| return ruleConditions; | |||||
| } | |||||
| public void setRuleConditions(String ruleConditions) { | |||||
| this.ruleConditions = ruleConditions; | |||||
| } | |||||
| public String getRuleValue() { | |||||
| return ruleValue; | |||||
| } | |||||
| public void setRuleValue(String ruleValue) { | |||||
| this.ruleValue = ruleValue; | |||||
| } | |||||
| public Date getCreateTime() { | |||||
| return createTime; | |||||
| } | |||||
| public void setCreateTime(Date createTime) { | |||||
| this.createTime = createTime; | |||||
| } | |||||
| public String getCreateBy() { | |||||
| return createBy; | |||||
| } | |||||
| public void setCreateBy(String createBy) { | |||||
| this.createBy = createBy; | |||||
| } | |||||
| public Date getUpdateTime() { | |||||
| return updateTime; | |||||
| } | |||||
| public void setUpdateTime(Date updateTime) { | |||||
| this.updateTime = updateTime; | |||||
| } | |||||
| public String getUpdateBy() { | |||||
| return updateBy; | |||||
| } | |||||
| public void setUpdateBy(String updateBy) { | |||||
| this.updateBy = updateBy; | |||||
| } | |||||
| } | |||||
| @ -0,0 +1,106 @@ | |||||
| package org.jeecg.common.system.vo; | |||||
| import java.util.List; | |||||
| import org.jeecg.common.util.DateUtils; | |||||
| /** | |||||
| * @Description: 用户缓存信息 | |||||
| * @author: jeecg-boot | |||||
| */ | |||||
| public class SysUserCacheInfo { | |||||
| private String sysUserId; | |||||
| private String sysUserCode; | |||||
| private String sysUserName; | |||||
| private String sysOrgCode; | |||||
| /** | |||||
| * 当前用户部门ID | |||||
| */ | |||||
| private String sysOrgId; | |||||
| private List<String> sysMultiOrgCode; | |||||
| private boolean oneDepart; | |||||
| /** | |||||
| * 当前用户角色code(多个逗号分割) | |||||
| */ | |||||
| private String sysRoleCode; | |||||
| public boolean isOneDepart() { | |||||
| return oneDepart; | |||||
| } | |||||
| public void setOneDepart(boolean oneDepart) { | |||||
| this.oneDepart = oneDepart; | |||||
| } | |||||
| public String getSysDate() { | |||||
| return DateUtils.formatDate(); | |||||
| } | |||||
| public String getSysTime() { | |||||
| return DateUtils.now(); | |||||
| } | |||||
| public String getSysUserCode() { | |||||
| return sysUserCode; | |||||
| } | |||||
| public void setSysUserCode(String sysUserCode) { | |||||
| this.sysUserCode = sysUserCode; | |||||
| } | |||||
| public String getSysUserName() { | |||||
| return sysUserName; | |||||
| } | |||||
| public void setSysUserName(String sysUserName) { | |||||
| this.sysUserName = sysUserName; | |||||
| } | |||||
| public String getSysOrgCode() { | |||||
| return sysOrgCode; | |||||
| } | |||||
| public void setSysOrgCode(String sysOrgCode) { | |||||
| this.sysOrgCode = sysOrgCode; | |||||
| } | |||||
| public List<String> getSysMultiOrgCode() { | |||||
| return sysMultiOrgCode; | |||||
| } | |||||
| public void setSysMultiOrgCode(List<String> sysMultiOrgCode) { | |||||
| this.sysMultiOrgCode = sysMultiOrgCode; | |||||
| } | |||||
| public String getSysUserId() { | |||||
| return sysUserId; | |||||
| } | |||||
| public void setSysUserId(String sysUserId) { | |||||
| this.sysUserId = sysUserId; | |||||
| } | |||||
| public String getSysOrgId() { | |||||
| return sysOrgId; | |||||
| } | |||||
| public void setSysOrgId(String sysOrgId) { | |||||
| this.sysOrgId = sysOrgId; | |||||
| } | |||||
| public String getSysRoleCode() { | |||||
| return sysRoleCode; | |||||
| } | |||||
| public void setSysRoleCode(String sysRoleCode) { | |||||
| this.sysRoleCode = sysRoleCode; | |||||
| } | |||||
| } | |||||