Compare commits

...

980 Commits

Author SHA1 Message Date
17d609cf34 只保留AI的相关介绍 2025-12-04 14:52:34 +08:00
bfcd2797f1 变更数据库名 jeecgai 2025-12-04 14:46:39 +08:00
e112f4eea3 【制作独立jeecg-ai】删除微服务模块,简化使用 2025-12-04 14:39:06 +08:00
3b36f1909a 【制作独立jeecg-ai】只保留mysql库 2025-12-04 14:39:01 +08:00
5e5e11f952 【制作独立jeecg-ai】变更数据库为jeecgai 2025-12-04 14:38:55 +08:00
d6051addeb 【制作独立jeecg-ai】删除示例代码 2025-12-04 14:38:45 +08:00
281c3ff3c8 措辞优化 2025-12-04 13:55:53 +08:00
38d44c2487 修改一个参数,就实现默认的四个系统主题快速切换 2025-12-03 19:55:13 +08:00
8c88f8adf5 【issues/9098】tabs标签页关闭异常 2025-12-03 19:06:21 +08:00
526734c5a5 v3.9.0 其他数据库脚本,增加aiflow调试接口权限 2025-12-02 12:19:35 +08:00
44b48ad916 AI流程调试接口加权限,存在命令执行漏洞 #9144 2025-12-01 15:18:34 +08:00
1a3ae4f61c 解决AI流程两个严重问题
1、AI流程调试接口,存在命令执行漏洞 #9144
2、AI流程导入后缀改成 *.jeecgai
2025-12-01 15:13:18 +08:00
859c509f08 解决AI流程两个严重问题
1、AI流程调试接口,存在命令执行漏洞 #9144
2、AI流程导入后缀改成 *.jeecgai
2025-12-01 15:13:11 +08:00
0704f187af 遗漏方法提交 2025-12-01 13:52:23 +08:00
199d2b439e GUI代码生成,更新文档地址 2025-11-28 15:59:10 +08:00
5f898ed034 V3.9.0 微服务启动失败 缺少配置application-liteflow.yml 2025-11-28 15:06:06 +08:00
5a9cb05c86 V3.9.0 打包太大,默认不集成积木报表的nosql支持包 2025-11-28 11:47:44 +08:00
98936680d5 V3.9.0 打包太大,删除demo模块无用代码 2025-11-28 11:42:58 +08:00
fc043fd5f3 V3.9.0 打包太大,删除非必须依赖 2025-11-28 11:35:15 +08:00
54531002a7 v3.9.0 oracle、SqlServer、postgresql初始化脚本 2025-11-28 11:04:50 +08:00
728a95c00d 描述 2025-11-28 10:09:04 +08:00
13c9951c1f 优化描述 2025-11-28 10:05:36 +08:00
8dfaa3c3e1 优化 2025-11-28 10:02:23 +08:00
050c478dce 产品描述优化 2025-11-28 10:00:44 +08:00
2688e8b6e2 解决yarn安装,启动报错问题 2025-11-27 22:32:09 +08:00
a9f30f0ca5 解决yarn安装,启动报错问题 2025-11-27 22:25:57 +08:00
1bf4a0595a V3.9.0 修复部门老数据,类型不对 2025-11-27 18:50:13 +08:00
74cd57fd99 V3.9.0 Oracle11g 数据库 登录提示 无效的列类型: 1111 #9145 2025-11-27 18:44:35 +08:00
c9ac4c9945 v3.9.0 修复历史机构的部门类型 2025-11-27 18:42:27 +08:00
3b3371ee1a v3.9.0 更新数据库 2025-11-27 18:21:31 +08:00
1d3bde9fe7 MCP示例 2025-11-27 15:46:51 +08:00
90b50a51a7 简化MCP示例 2025-11-27 15:46:40 +08:00
668ac59a5c AI聊天创建用户等功能,移除工号和邮箱的唯一性要求 2025-11-27 15:36:57 +08:00
5f01bdd29b v3.9.0 增加MCP插件示例数据 2025-11-27 13:23:56 +08:00
82bfcc7b14 启动脚本,host检查失败,不影响启动 2025-11-27 11:59:04 +08:00
ef210a2242 前端依赖包有问题,导致build报错 2025-11-27 11:53:01 +08:00
435445cb4e v3.9.0 APP推送方法优化 2025-11-26 22:22:25 +08:00
fdf7cd1f6b v3.9.0 数据库更新,解决多屏大屏示例不展示问题 2025-11-26 13:42:36 +08:00
92a38f41b0 v3.9.0 数据库升级 2025-11-26 12:11:25 +08:00
7ed3bcc912 分支名称调整 2025-11-26 11:41:35 +08:00
2706c0a519 v3.9.0 支持MCP和插件,实现聊天式业务操作(如 “一句话创建用户”)! 2025-11-26 11:38:16 +08:00
f4b80365a9 描述修改 2025-11-26 11:36:56 +08:00
1108aa5288 更新版本号至v3.9.0 2025-11-26 11:29:52 +08:00
9919ae2bc5 v3.9.0 里程碑版本发布 2025-11-26 11:25:35 +08:00
1f73837b7d uniapp推送设置为空 2025-11-26 11:25:30 +08:00
9571e0b169 v3.9.0 里程碑版本发布 2025-11-26 11:14:47 +08:00
1a923596db 显示说明增量sql位置 2025-11-25 17:11:47 +08:00
62549e0a1c 打开flyway 数据库自动升级 2025-11-25 17:11:28 +08:00
2740a2f419 升级积木报表和积木BI到v2.2.0、poi升级到5 2025-11-24 22:04:12 +08:00
899264250c 请求中附带非法或过期 Token 时,返回重复的 401 请求 #9107 2025-11-17 11:02:43 +08:00
0be7d00eb2 集成vite-plugin-pwa实现渐进式Web应用,首屏很快,同时异步加载了系统的资源,点击菜单更快 2025-11-17 10:24:38 +08:00
7152ae9e49 jeecg-boot-starter项目说明 2025-11-12 23:14:04 +08:00
58b41db786 Online报表(带参数)预览后台报错 #9000 2025-11-11 15:09:15 +08:00
d715c7a0ac rollup版本号固定4.52.5,rollup-plugin-visualizer固定5.14.0,导致打包失败 2025-11-10 15:54:36 +08:00
aca407e1ce AI实战编程教程:JEECG低代码与Cursor+GitHub Copilot实现AI高效编程实战 2025-10-31 11:31:10 +08:00
cfea79a187 修复功能菜单“系统管理”-“部门管理”,用户列表中,编辑用户界面-用户账号为空 #9032 2025-10-30 22:26:55 +08:00
7848d1fb33 lock版本更新 2025-10-28 22:59:47 +08:00
91fa645878 3.8.3-master分支:租户用户 菜单下 新增用户报错 #9039 2025-10-28 13:40:27 +08:00
c9fc948658 更新jimureport和jimubi的版本号至2.1.5 2025-10-21 17:44:28 +08:00
b97d041e7f 更新springboot3版本号 2025-10-17 19:31:53 +08:00
6492f2c99a 更新README.md,修正Sa-Token下载链接格式 2025-10-16 19:13:47 +08:00
bf32385a06 更新README.md,调整下载链接顺序 2025-10-16 19:12:11 +08:00
6ef637c46f 提供SpringBoot3.3 + Sa-Token版本 2025-10-16 19:05:59 +08:00
bc6f336745 issues/8972 通义千问的多模态模型保存激活报错 #55 2025-10-14 22:46:46 +08:00
0d86df8e9e 1 2025-10-14 18:03:51 +08:00
3db673b67d issue格式 2025-10-14 18:03:01 +08:00
3ba5395d33 优化gateway启动报警告 2025-10-14 16:48:17 +08:00
e7eed37470 升级shardingsphere-jdbc版本到5.5.0,需要手工配置ShardingSphere数据源到spring.datasource.dynamic.datasource中,用法更明确 2025-10-14 16:47:05 +08:00
30ac3f7c72 升级shardingsphere-jdbc版本到5.5.0,需要手工配置ShardingSphere数据源到spring.datasource.dynamic.datasource中,用法更明确 2025-10-14 16:02:15 +08:00
03e6c97d80 重构JeecgBizToolsProvider.java,使用JsonObjectSchema替代JsonSchemaProperty,优化参数定义 2025-10-13 14:10:52 +08:00
b9f6f6dc53 升级langchain4j到1.3.0,解决很多模型不支持问题和MCP支持 2025-10-13 11:27:09 +08:00
107e13c8af [issues/8859]online表单java增强失效-- 2025-10-11 11:35:36 +08:00
0512b41b2b 更新README.md,增加对Node.js版本要求的说明,强调不再支持EOL的Node.js 18 2025-10-10 17:34:00 +08:00
d6d880f887 更新说明 2025-10-10 10:20:09 +08:00
b0e974a418 更新README.md,优化平台介绍和技术架构信息,增强AI应用平台描述 2025-10-09 11:15:45 +08:00
388fa9b8c2 v3.8.3大版本发布,全面迈向 SpringBoot3 2025-10-09 11:06:32 +08:00
bc04bd1433 --author:scott--date:20250930--for:使用@PostConstruct注解初始化PrometheusMeterRegistry配置,避免启动后配置延迟 2025-09-30 15:43:24 +08:00
35aba0784d Path Traversal Vulnerability /sys/comment/addFile /sys/upload/uploadMinio endpoint (notice the uploadlocal function is different from the /sys/common/upload ) #8827 2025-09-29 18:24:33 +08:00
c3822ab702 3.8.3版本能正常连接sqlserver数据库,但是无法解析查询代码 #8900 2025-09-29 11:55:37 +08:00
d4487356f0 更新 JeecgSystemApplication.java,排除 MongoAutoConfiguration 以避免未集成 mongo 的报错 2025-09-28 22:34:10 +08:00
ae4363dc72 仪表盘大屏分享,提示需要token错误 2025-09-28 18:12:03 +08:00
3e6c7651ee 提供v3.8.3版本数据库脚本 2025-09-28 14:29:52 +08:00
c0ffd14b7a 更新 pom.xml,修改 jimureport 依赖的 artifactId 2025-09-26 16:26:35 +08:00
914875d6a1 更新 pom.xml,升级 jimubi-spring-boot-starter 和 jimureport-nosql-starter 版本 2025-09-26 15:26:30 +08:00
2298ee3eed 更新 docker-compose-cloud.yml,添加 jeecg-boot 网络配置到 sentinel 和 xxljob 服务 2025-09-25 13:47:33 +08:00
2a8853b353 docker微服务启动 docker-compose 增加xxljob和sentinel配置 2025-09-25 12:48:25 +08:00
b920c5b794 Oracle11g数据库 多租户管理>>添加租户 报错 #8897 2025-09-25 12:42:53 +08:00
d3fa38a9e6 更新 application-docker.yml,修改 Redis 和 XXL-JOB 配置为使用服务名称 2025-09-25 11:17:53 +08:00
b0df78b06c 配置文件升级到v3.8.3 切换tomcat 2025-09-25 10:23:51 +08:00
80749098bd 添加 JustAuth 自动配置支持,更新 pom.xml 以包含 jeecg-boot-starter-job 依赖,并修改 application.yml 中的 nacos 服务器地址配置 2025-09-24 16:06:54 +08:00
19b7f2cb29 springboot3 支持 jdk17、jdk21、jdk24 2025-09-24 15:18:32 +08:00
39f5c3a5be 支持jdk21 2025-09-24 13:18:52 +08:00
9ee3a36fbb 版本发布日期更新 2025-09-24 13:17:21 +08:00
8c5cf3a0d9 【v3.8.3开源版本发布】更改groupId从org.jeecgframework.boot为org.jeecgframework.boot3,与springboot2区分 2025-09-24 12:19:01 +08:00
053552c123 【v3.8.3开源版本发布】
Merge remote-tracking branch 'origin/master' into springboot3

# Conflicts:
#	README.md
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FileDownloadUtils.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserAgentController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysDepartService.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserService.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysAnnouncementServiceImpl.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-seata/pom.xml
#	jeecg-boot/pom.xml
2025-09-24 12:01:11 +08:00
fc44deca83 Merge remote-tracking branch 'origin/springboot3' into springboot3 2025-09-24 11:18:36 +08:00
5d5d9fc53d Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-09-24 11:16:50 +08:00
002bfe25f8 【v3.8.3】升级数据库,暂时先删除 2025-09-24 11:06:54 +08:00
7cb2dc4fde Update @vitejs/plugin-vue-jsx version
Updated version of @vitejs/plugin-vue-jsx to 4.1.1.
自动下载的依赖 @vitejs/plugin-vue-jsx@4.2.0 是 CJS 格式 , 1.0.0-beta.38 版本的 @rolldown/pluginutils 是 ESM 格式模块不兼容
2025-09-18 17:32:11 +08:00
9c244bd266 Update @vitejs/plugin-vue-jsx version
Updated version of @vitejs/plugin-vue-jsx to 4.1.1.

 自动下载的依赖 @vitejs/plugin-vue-jsx@4.2.0 是 CJS 格式 , 1.0.0-beta.38 版本的 @rolldown/pluginutils 是 ESM 格式
模块不兼容
2025-09-18 17:31:14 +08:00
ab151879b3 XXL-JOB版本号错误,修改至v2.4.0 2025-09-14 16:03:45 +08:00
000ae1db30 升级前端pnpm lock 2025-09-14 15:52:27 +08:00
63e066180d 【v3.8.3】更新pom.xml,升级Kotlin和Liteflow版本 2025-09-14 12:57:48 +08:00
44c1079f87 【v3.8.3】优化顶部导航风格菜单的样式,支持外部链接打开及菜单重定向 2025-09-14 11:59:09 +08:00
e825e0f912 【v3.8.3】升级数据库 2025-09-14 11:58:05 +08:00
132e89b0e1 【v3.8.3】底层core的一些功能修改 2025-09-14 11:57:47 +08:00
881a637285 【v3.8.3】AI助手调用系统业务扩展接口,支持添加用户、查询用户、查询角色及授予角色功能 2025-09-14 11:57:37 +08:00
02e9f8984f 【v3.8.3】更新EnumDict.java,添加使用说明和配置要求 2025-09-14 11:55:45 +08:00
a4343fc2cb 【v3.8.3】底层core的一些功能修改 2025-09-14 11:55:31 +08:00
152e8c7aaa 【v3.8.3】优化枚举字典数据加载,支持多包路径扫描,提升初始化性能 2025-09-14 11:54:01 +08:00
d7dc81455d 【v3.8.3】用户组织机构大改造(新增主岗位、主岗位、用户签名) 2025-09-14 11:53:36 +08:00
aefdcd6315 【v3.8.3】大数据导出共通类 2025-09-14 11:50:56 +08:00
1cf4054e76 【v3.8.3】租户大改造 2025-09-14 11:50:37 +08:00
7829cf18d7 解决升级mybatisPlus后SqlServer分页使用OFFSET 2025-09-14 11:49:55 +08:00
69c3a9da9a 【v3.8.3】升级版本号至3.8.3,更新依赖项和排除项 2025-09-14 11:49:42 +08:00
4d34150479 升级kingbase8驱动和切换回tomcat 2025-09-14 11:48:00 +08:00
29687c8908 【v3.8.3】升级版本号3.8.3和docker配置 2025-09-14 10:48:13 +08:00
2e93a92dde 【v3.8.3】修改配置文件,删除undertow 2025-09-14 10:45:32 +08:00
d383f7458d 【v3.8.3】企业微信通知采用卡片 2025-09-14 10:44:08 +08:00
700318e1c1 【v3.8.3】首页配置功能改造 2025-09-14 10:43:21 +08:00
d728d6b090 【v3.8.3】升级代码生成器模板 2025-09-14 10:43:00 +08:00
7abc2e4c9c 【v3.8.3】大数据导出示例 2025-09-14 10:42:45 +08:00
da2b0cc354 【v3.8.3】升级aiflow 2025-09-14 10:41:53 +08:00
a6751c22be 【v3.8.3】功能性能优化 2025-09-14 10:41:25 +08:00
f087525a75 【v3.8.3】undertow不稳定切换回tomcat 2025-09-14 10:40:21 +08:00
4f46213df6 【v3.8.3】前端小改动汇总集合 2025-09-14 10:39:48 +08:00
d76842ae07 【v3.8.3】airag优化体验升级 2025-09-14 10:38:41 +08:00
8c64db46e5 【v3.8.3】默认首页改造 2025-09-14 10:37:29 +08:00
81fb2ac3b2 【v3.8.3】切换回Tomcat信息 2025-09-14 10:37:14 +08:00
fa98817aeb 【v3.8.3】部门大改造关联修改 2025-09-14 10:37:05 +08:00
1158977826 更新版本号至3.8.3,修改README.md以反映最新框架和工具版本 2025-09-14 10:27:07 +08:00
8b6def0ee3 导出excel总提示格式不匹配和日志大数据导出示例 2025-09-14 10:26:52 +08:00
39c0d5b3f5 【v3.8.3】组织机构部门大改造(支持子公司、岗位与不能功能划分更清晰,岗位可以设置上下级,岗位可以设置职级,支持回报关系) 2025-09-14 10:26:24 +08:00
adeebee840 【v3.8.3】用户大改造,取消原职位换成职位字典、原职位改成岗位职级、新增主岗位和兼职岗位 2025-09-14 10:24:02 +08:00
862aaa8632 【v3.8.3】我的租户大改造 2025-09-14 10:22:26 +08:00
6a11ff8a64 【v3.8.3】升级版本号 2025-09-14 10:16:56 +08:00
73059b8a53 优化AIRG 2025-09-13 16:15:23 +08:00
e377bf6990 升级版本号 2025-09-05 18:49:20 +08:00
434b42e9ed 部分配置丢失,修复 2025-09-04 10:47:50 +08:00
f1ceb08e16 Merge remote-tracking branch 'origin/master' into springboot3
# Conflicts:
#	README.md
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-seata/pom.xml
#	jeecg-boot/pom.xml
#	jeecgboot-vue3/src/components/jeecg/JVxeTable/src/hooks/useFinallyProps.ts
2025-09-04 09:40:57 +08:00
d2eedacc85 优化项目介绍 2025-09-03 19:58:13 +08:00
8791384791 优化项目介绍 2025-09-03 19:21:56 +08:00
fd60e49f5b 升级积木报表和积木BI到2.1.3\升级minidao解决SqlServer兼容问题 2025-09-03 17:44:01 +08:00
5f1dc06067 升级积木报表和积木BI到2.1.3\升级minidao解决SqlServer兼容问题 2025-09-03 17:43:57 +08:00
b67770ff14 升级miniao到1.10.14,解决SqlServer分页兼容问题 2025-09-03 17:36:32 +08:00
1dae808cf1 升级积木报表和积木BI到最新版 v2.1.3 2025-09-03 16:34:26 +08:00
70d8353219 升级springBoot 3.5.5 2025-09-03 15:53:53 +08:00
208d9990ae 主干默认springboot3版本 2025-09-03 15:41:30 +08:00
3e208de18e 默认主干切换springboot3分支 2025-09-03 15:37:26 +08:00
4f3c71af5b 主干默认springboot3版本 2025-09-03 15:30:19 +08:00
70bd639206 【issues/8738】componentProps是函数时获取不到valueType 2025-08-26 13:29:16 +08:00
d245ef3037 【JVXETable】修复首屏加载速度 2025-08-26 13:29:05 +08:00
7af8346b79 【#8695】修复JVxeTable卡顿问题 2025-08-22 17:51:42 +08:00
1b8a31f0d3 代码生成器还原到 1.5.1 2025-08-22 14:44:57 +08:00
294ad5a6c9 代码生成,把角色授权sql菜单的,也生成出来 2025-08-20 19:34:01 +08:00
065b255d90 设置代码生成,FreeMarker空值处理不报错 2025-08-20 15:12:59 +08:00
56976e68b4 升级spring-boot到3.5.4、升级spring-cloud到2025.0.0、升级spring-cloud-alibaba到2023.0.3.3 2025-08-20 10:42:43 +08:00
db1ff0268b Squashed commit of the following:
commit b7519d7199
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 15:18:52 2025 +0800

    中文乱码

commit 81ba07c853
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 15:09:21 2025 +0800

    增加代码生成用法文档

commit 92ed296e63
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:04:22 2025 +0800

    【issues/8709】LayoutContent样式多出1px

commit c2aff84914
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:04:09 2025 +0800

    【issues/8683】DatePicker组件的componentProps使用函数形式时初始值获取不对

commit e002cd3bf3
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:03:51 2025 +0800

    【issues/8680】editComponentProps 可接受一个函数传入record

commit 1de07ff3ff
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:03:32 2025 +0800

    -- author:liaozhiyang---date:20250813--for:【issues/8690】BasicTable的rowSelection新增onSelect方法 ---

commit 35852d41f1
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:03:04 2025 +0800

    jvxeTable表格切换disabled属性时,相邻的两个枚举下拉,如果值是一样的,但是label不一样,会把第二个下拉的显示值渲染到第一个下拉中 #8593

commit a2cb1d9f25
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 14:00:01 2025 +0800

    【issues/8529】setColumns将原本隐藏的列展示后,列配置里却没有勾选该列

commit 2002af54d0
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 13:59:42 2025 +0800

    JVxeTypes.image组件action字段只能定义第1张图片的上传接口,后面图片的接口还是使用公共上传接口 #8628

commit 89747403a2
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 13:59:28 2025 +0800

    JVxeTable组件全选翻页后会被取消选中 #8630

commit 3db0995c3f
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 19 11:23:19 2025 +0800

    [代码生成]前端代码支持直接生成到前端项目、菜单sql会自动生成到start项目的flyway目录

commit 950621dd88
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 18 23:04:59 2025 +0800

    升级代码生成器,一键生成代码,vue3代码会生成到前端项目、菜单升级sql自动迁移到flyway目录重启自动执行(不需要手工迁移前端代码和手工执行升级sql)

commit 033cf51d69
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 18 23:04:52 2025 +0800

    升级代码生成器,一键生成代码,vue3代码会生成到前端项目、菜单升级sql自动迁移到flyway目录重启自动执行(不需要手工迁移前端代码和手工执行升级sql)

commit fb9f367517
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 18 23:02:53 2025 +0800

    代码生成,online自定义按钮无排序报错

commit b2da45d803
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 18 16:23:22 2025 +0800

    演示地址

commit 2840f0d325
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 18 15:37:10 2025 +0800

    默认账号密码

commit 6ace7eae8a
Author: JEECG <445654970@qq.com>
Date:   Sun Aug 17 15:11:45 2025 +0800

    开发环境关闭日志生成,项目启动快;生产环境请按需打开注释

commit 3d88147c59
Author: JEECG <445654970@qq.com>
Date:   Thu Aug 14 23:03:46 2025 +0800

    调整微服务启动文档

commit ba0052d452
Author: JEECG <445654970@qq.com>
Date:   Wed Aug 13 13:55:13 2025 +0800

    支持lazy-initialization启动,项目大了后启动会更快

commit 69fca254f0
Author: JEECG <445654970@qq.com>
Date:   Wed Aug 13 11:47:27 2025 +0800

    补充注释

commit b3de596199
Author: JEECG <445654970@qq.com>
Date:   Wed Aug 13 11:47:16 2025 +0800

    彻底关闭 prettier 校验规则

commit f46273d15e
Author: JEECG <445654970@qq.com>
Date:   Wed Aug 13 10:26:23 2025 +0800

    设置ESLint 的 vue/html-self-closing 自闭合标签警告配置

commit 0fe258dbc2
Author: JEECG <445654970@qq.com>
Date:   Wed Aug 13 09:26:16 2025 +0800

    修复 onExportXls defSort 不生效问题 #7570

commit de7f23c555
Merge: d97e56b2 444c7140
Author: JEECG <zhangdaiscott@163.com>
Date:   Wed Aug 13 09:20:31 2025 +0800

    Merge pull request #8496 from lileiAimee/developer

    解决TableAction中自定义图标颜色不起作用的问题

commit d97e56b2f0
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 19:08:43 2025 +0800

    多租户模式下系统系统会给租户默认增加上测试的角色菜单,但是后台获取菜单时异常,无法打开相关页面 #8667

commit c868496b78
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 19:02:49 2025 +0800

    映射警告

commit c5150baa69
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 18:18:34 2025 +0800

    支持通过用户账号邀请加入租户

commit 3d9f59c69b
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 18:17:55 2025 +0800

    邀请用户加入租户,支持通过用户账号

commit 420d6db3fb
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 18:06:20 2025 +0800

    登录用户没有部门,不提示警告

commit 473a626039
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 14:10:02 2025 +0800

    增加JPopup组件带参数示例

commit 0308b0597c
Author: JEECG <445654970@qq.com>
Date:   Tue Aug 12 14:08:18 2025 +0800

    【issues/8426】解决JPopup组件传参不能接收

commit 2191f5d48c
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 11 22:43:07 2025 +0800

    调整位置

commit 1158b0b6e7
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 11 22:30:39 2025 +0800

    升级seata到1.7.0;升级dynamic-datasource-spring-boot-starter到3.5.2

commit ead2cef1f4
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 11 18:47:48 2025 +0800

    支持多字段默认排序defSort数组、解决多列排序无效 #8659

commit 83bb0a0a6a
Author: JEECG <445654970@qq.com>
Date:   Mon Aug 11 18:47:43 2025 +0800

    支持多字段默认排序defSort数组

commit b474e9e5a5
Author: JEECG <445654970@qq.com>
Date:   Sun Aug 10 17:06:01 2025 +0800

    开发环境安装

commit 422373e300
Author: JEECG <445654970@qq.com>
Date:   Sun Aug 10 16:30:13 2025 +0800

    提供JeecgBoot 运行环境python检查脚本

commit 1cf11a4c2a
Author: JEECG <445654970@qq.com>
Date:   Sat Aug 9 09:41:57 2025 +0800

    提供jeecgboot-oracle11g.dmp

commit 925f163784
Author: JEECG <445654970@qq.com>
Date:   Fri Aug 8 22:07:24 2025 +0800

    引入jeecg-boot-starter-job依赖启动报错 #8694

commit d01c1d7d47
Author: JEECG <445654970@qq.com>
Date:   Thu Aug 7 15:41:21 2025 +0800

    支持lazy-initialization

commit 3576b54945
Author: JEECG <445654970@qq.com>
Date:   Thu Aug 7 15:36:51 2025 +0800

    升级积木报表和积木BI到最新版v2.1.2

commit 444c7140f6
Author: lileiAimee <345697385@qq.com>
Date:   Wed Jun 25 09:55:07 2025 +0800

    解决TableAction中自定义图标颜色不起作用的问题

# Conflicts:
#	README-EN.md
#	README.md
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-seata/pom.xml
#	jeecg-boot/pom.xml
2025-08-19 22:58:12 +08:00
b7519d7199 中文乱码 2025-08-19 15:18:52 +08:00
81ba07c853 增加代码生成用法文档 2025-08-19 15:09:21 +08:00
92ed296e63 【issues/8709】LayoutContent样式多出1px 2025-08-19 14:04:22 +08:00
c2aff84914 【issues/8683】DatePicker组件的componentProps使用函数形式时初始值获取不对 2025-08-19 14:04:09 +08:00
e002cd3bf3 【issues/8680】editComponentProps 可接受一个函数传入record 2025-08-19 14:03:51 +08:00
1de07ff3ff -- author:liaozhiyang---date:20250813--for:【issues/8690】BasicTable的rowSelection新增onSelect方法 --- 2025-08-19 14:03:32 +08:00
35852d41f1 jvxeTable表格切换disabled属性时,相邻的两个枚举下拉,如果值是一样的,但是label不一样,会把第二个下拉的显示值渲染到第一个下拉中 #8593 2025-08-19 14:03:04 +08:00
a2cb1d9f25 【issues/8529】setColumns将原本隐藏的列展示后,列配置里却没有勾选该列 2025-08-19 14:00:01 +08:00
2002af54d0 JVxeTypes.image组件action字段只能定义第1张图片的上传接口,后面图片的接口还是使用公共上传接口 #8628 2025-08-19 13:59:42 +08:00
89747403a2 JVxeTable组件全选翻页后会被取消选中 #8630 2025-08-19 13:59:28 +08:00
3db0995c3f [代码生成]前端代码支持直接生成到前端项目、菜单sql会自动生成到start项目的flyway目录 2025-08-19 11:23:19 +08:00
950621dd88 升级代码生成器,一键生成代码,vue3代码会生成到前端项目、菜单升级sql自动迁移到flyway目录重启自动执行(不需要手工迁移前端代码和手工执行升级sql) 2025-08-18 23:04:59 +08:00
033cf51d69 升级代码生成器,一键生成代码,vue3代码会生成到前端项目、菜单升级sql自动迁移到flyway目录重启自动执行(不需要手工迁移前端代码和手工执行升级sql) 2025-08-18 23:04:52 +08:00
fb9f367517 代码生成,online自定义按钮无排序报错 2025-08-18 23:02:53 +08:00
b2da45d803 演示地址 2025-08-18 16:23:22 +08:00
2840f0d325 默认账号密码 2025-08-18 15:37:10 +08:00
6ace7eae8a 开发环境关闭日志生成,项目启动快;生产环境请按需打开注释 2025-08-17 15:11:45 +08:00
3d88147c59 调整微服务启动文档 2025-08-14 23:03:46 +08:00
08f245bdf9 修改遗漏 swagger上选择的接口和实际接口不对应#8705 2025-08-13 18:15:19 +08:00
8cc033b86f swagger上选择的接口和实际接口不对应 #8705 2025-08-13 17:22:42 +08:00
6b7542620b swagger上选择的接口和实际接口不对应 #8705 2025-08-13 16:44:16 +08:00
ba0052d452 支持lazy-initialization启动,项目大了后启动会更快 2025-08-13 13:55:13 +08:00
69fca254f0 补充注释 2025-08-13 11:47:27 +08:00
b3de596199 彻底关闭 prettier 校验规则 2025-08-13 11:47:16 +08:00
f46273d15e 设置ESLint 的 vue/html-self-closing 自闭合标签警告配置 2025-08-13 10:26:23 +08:00
0fe258dbc2 修复 onExportXls defSort 不生效问题 #7570 2025-08-13 09:26:16 +08:00
de7f23c555 Merge pull request #8496 from lileiAimee/developer
解决TableAction中自定义图标颜色不起作用的问题
2025-08-13 09:20:31 +08:00
67d9865861 Merge pull request #8550 from TsuGit/fix/xxljob-startup-error
fix(xxljob): 修复因 factoryBeanObjectType 导致的启动失败
2025-08-13 00:02:30 +08:00
d97e56b2f0 多租户模式下系统系统会给租户默认增加上测试的角色菜单,但是后台获取菜单时异常,无法打开相关页面 #8667 2025-08-12 19:08:43 +08:00
c868496b78 映射警告 2025-08-12 19:02:49 +08:00
c5150baa69 支持通过用户账号邀请加入租户 2025-08-12 18:18:34 +08:00
3d9f59c69b 邀请用户加入租户,支持通过用户账号 2025-08-12 18:17:55 +08:00
420d6db3fb 登录用户没有部门,不提示警告 2025-08-12 18:06:20 +08:00
473a626039 增加JPopup组件带参数示例 2025-08-12 14:10:02 +08:00
0308b0597c 【issues/8426】解决JPopup组件传参不能接收 2025-08-12 14:08:18 +08:00
cd809a6573 Squashed commit of the following:
升级seata到1.7.0;升级dynamic-datasource-spring-boot-starter到3.5.2
    支持多字段默认排序defSort数组、解决多列排序无效 #8659
    支持多字段默认排序defSort数组
    提供JeecgBoot 运行环境python检查脚本
    提供jeecgboot-oracle11g.dmp
2025-08-12 09:25:01 +08:00
2191f5d48c 调整位置 2025-08-11 22:43:07 +08:00
1158b0b6e7 升级seata到1.7.0;升级dynamic-datasource-spring-boot-starter到3.5.2 2025-08-11 22:30:39 +08:00
ead2cef1f4 支持多字段默认排序defSort数组、解决多列排序无效 #8659 2025-08-11 18:47:48 +08:00
83bb0a0a6a 支持多字段默认排序defSort数组 2025-08-11 18:47:43 +08:00
b474e9e5a5 开发环境安装 2025-08-10 17:06:01 +08:00
422373e300 提供JeecgBoot 运行环境python检查脚本 2025-08-10 16:30:13 +08:00
1cf11a4c2a 提供jeecgboot-oracle11g.dmp 2025-08-09 09:41:57 +08:00
ac446691c4 Squashed commit of the following:
commit 925f163784
Author: JEECG <445654970@qq.com>
Date:   Fri Aug 8 22:07:24 2025 +0800

    引入jeecg-boot-starter-job依赖启动报错 #8694

commit d01c1d7d47
Author: JEECG <445654970@qq.com>
Date:   Thu Aug 7 15:41:21 2025 +0800

    支持lazy-initialization

commit 3576b54945
Author: JEECG <445654970@qq.com>
Date:   Thu Aug 7 15:36:51 2025 +0800

    升级积木报表和积木BI到最新版v2.1.2

# Conflicts:
#	jeecg-boot/pom.xml
2025-08-08 22:22:30 +08:00
925f163784 引入jeecg-boot-starter-job依赖启动报错 #8694 2025-08-08 22:07:24 +08:00
0feb307e8d Merge remote-tracking branch 'origin/master' into springboot3 2025-08-07 18:11:58 +08:00
781d61e96e swagger请求头部没有X-Access-Token #8676 2025-08-07 18:02:27 +08:00
d01c1d7d47 支持lazy-initialization 2025-08-07 15:41:21 +08:00
3576b54945 升级积木报表和积木BI到最新版v2.1.2 2025-08-07 15:36:51 +08:00
a760f94b94 解决pgvector向量数据库不支持2000维度的问题 2025-08-07 13:51:46 +08:00
e795e03365 【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错 2025-08-04 18:39:35 +08:00
342bdd2e38 【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,无默认排序字段导致online报表报错 2025-08-04 18:14:11 +08:00
59ece16059 修改springboot3的配置yml 2025-08-03 12:51:32 +08:00
91208a4968 Merge remote-tracking branch 'origin/master' into springboot3 2025-08-03 12:49:26 +08:00
419e2bea0b 其他数据库配置 2025-08-03 12:47:42 +08:00
443abc3ede 其他数据库配置 2025-08-03 12:45:01 +08:00
358e46559f 其他数据库配置 2025-08-03 12:44:55 +08:00
128c2c97f6 修改springboot3的配置yml 2025-08-03 10:32:18 +08:00
424dc33bba 修改springboot3的配置yml 2025-08-03 10:13:47 +08:00
1cb48b4f0c 【解决SqlServer兼容问题,提供oracle和SqlServer的数据库脚本】
Merge remote-tracking branch 'origin/master' into springboot3

# Conflicts:
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/MybatisPlusSaasConfig.java
2025-08-03 10:07:04 +08:00
ea59454f51 oracle初始脚本 2025-08-03 10:04:37 +08:00
615a1bc4ff sqlserver初始脚本 2025-08-03 09:52:13 +08:00
d976f12c8f sqlserver初始脚本 2025-08-03 09:51:49 +08:00
3783765161 sqlserver初始脚本 2025-08-03 09:43:21 +08:00
8cc6810fdd 提交oracle配置yml 2025-08-03 09:43:07 +08:00
a902d9af19 提交SqlServer配置yml 2025-08-03 09:40:00 +08:00
37a116f2fb 提交oracle配置yml 2025-08-03 09:39:20 +08:00
1564831f7e 提交oracle配置yml 2025-08-03 09:37:36 +08:00
18c1cd00c1 提交SqlServer配置yml 2025-08-03 09:37:24 +08:00
a988b05e72 提交oracle配置yml 2025-08-03 09:31:37 +08:00
a9a6fd529d 提交SqlServer配置yml 2025-08-03 09:31:11 +08:00
6586d3a880 【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错--- 2025-08-02 19:45:36 +08:00
af354f9f5e 【issues/8666】升级mybatisPlus后SqlServer分页使用OFFSET ? ROWS FETCH NEXT ? ROWS ONLY,导致online报表报错--- 2025-08-02 19:10:24 +08:00
79b182819b Merge remote-tracking branch 'origin/master' into springboot3 2025-08-01 17:20:53 +08:00
a638a93b65 一键docker启动脚本 2025-08-01 17:13:28 +08:00
621781d336 JEECG Boot 一键docker启动脚本 2025-08-01 17:04:39 +08:00
f1cad333da 提供一键构建docker镜像的脚本,省掉手工操作步骤 2025-08-01 12:39:28 +08:00
e70844ce61 【合并v3.8.2 docker-compose优化配置】
Merge remote-tracking branch 'origin/master' into springboot3

# Conflicts:
#	jeecg-boot/jeecg-boot-base-core/pom.xml
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/Dockerfile
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-docker.yml
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	jeecg-boot/pom.xml
2025-08-01 10:54:33 +08:00
e00ffa2670 升级autopoi到1.4.14最新版 2025-08-01 10:46:07 +08:00
676fffa2c8 docker-compose增加jeecg-boot-pgvector 2025-07-31 22:47:01 +08:00
23cc569a47 docker system日志中文乱码解决 2025-07-31 18:12:57 +08:00
dafacf153b 升级版本号到3.8.2 2025-07-31 18:12:41 +08:00
7a9f357510 更新v3.8.2 功能清单 2025-07-31 17:56:40 +08:00
6c15b45a8c 【合并v3.8.2最新版代码】
Squashed commit of the following:

commit f30a8c658a
Author: JEECG <445654970@qq.com>
Date:   Thu Jul 31 11:35:16 2025 +0800

    数据库缺少openapi微服务网关配置

commit e84d7726d2
Author: JEECG <445654970@qq.com>
Date:   Thu Jul 31 10:20:09 2025 +0800

    后台接口地址修改

commit 0f39802698
Author: JEECG <445654970@qq.com>
Date:   Thu Jul 31 09:56:24 2025 +0800

    docker自动化部署命令

commit a014a3ed0e
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 21:55:16 2025 +0800

    v3.8.2 优化一键docker启动前后端

commit 5720d1a01e
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 19:26:38 2025 +0800

    升级版本号到3.8.2

commit 5eed6ac6d2
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 18:49:29 2025 +0800

    升级版本号到3.8.2

commit 0cfa1e223a
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 18:28:10 2025 +0800

    v3.8.2 系统通知改造支持分类

commit 219869f4c0
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 18:25:58 2025 +0800

    v3.8.2 版本前端代码

commit e6edde963a
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 18:25:46 2025 +0800

    v3.8.2 版本后端代码

commit c44b66128e
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 18:23:09 2025 +0800

    XXL-JOB(2.4.0 及以上)已被移除,分片参数获取方式变更。

commit 9356b04741
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 10:57:52 2025 +0800

    升级online到3.8.2-beta

commit d0a094f9a3
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 10:57:31 2025 +0800

    升级mybatis-plus到3.5.12、升级jsqlparser到4.9

commit 73eb625737
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 09:51:34 2025 +0800

    升级jimureport到v2.1.1

commit 74880705b8
Author: JEECG <445654970@qq.com>
Date:   Wed Jul 30 09:18:46 2025 +0800

    升级online到3.8.2-beta

# Conflicts:
#	jeecg-boot/jeecg-boot-base-core/pom.xml
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/JeecgSystemApplication.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	jeecg-boot/pom.xml
2025-07-31 14:23:45 +08:00
f30a8c658a 数据库缺少openapi微服务网关配置 2025-07-31 11:35:16 +08:00
e84d7726d2 后台接口地址修改 2025-07-31 10:20:09 +08:00
0f39802698 docker自动化部署命令 2025-07-31 09:56:24 +08:00
a014a3ed0e v3.8.2 优化一键docker启动前后端 2025-07-30 21:55:16 +08:00
5720d1a01e 升级版本号到3.8.2 2025-07-30 19:26:38 +08:00
5eed6ac6d2 升级版本号到3.8.2 2025-07-30 18:49:29 +08:00
0cfa1e223a v3.8.2 系统通知改造支持分类 2025-07-30 18:28:10 +08:00
219869f4c0 v3.8.2 版本前端代码 2025-07-30 18:25:58 +08:00
e6edde963a v3.8.2 版本后端代码 2025-07-30 18:25:46 +08:00
c44b66128e XXL-JOB(2.4.0 及以上)已被移除,分片参数获取方式变更。 2025-07-30 18:23:09 +08:00
9356b04741 升级online到3.8.2-beta 2025-07-30 10:57:52 +08:00
d0a094f9a3 升级mybatis-plus到3.5.12、升级jsqlparser到4.9 2025-07-30 10:57:31 +08:00
73eb625737 升级jimureport到v2.1.1 2025-07-30 09:51:34 +08:00
74880705b8 升级online到3.8.2-beta 2025-07-30 09:18:46 +08:00
f67cfa1bfb 删除重复依赖 2025-07-29 12:00:05 +08:00
8d91caa4e6 升级积木报表和积木BI到最新版 2025-07-28 18:54:21 +08:00
0d9f9a04cc 升级knife4j-openapi3-jakarta-spring-boot-starter到4.6.0解决knife4j-production不生效问题 2025-07-25 14:08:00 +08:00
90565fcf79 Merge remote-tracking branch 'origin/master' into springboot3
# Conflicts:
#	jeecg-boot/db/tables_nacos.sql
2025-07-25 13:23:47 +08:00
118775cf79 【swagger问题】不带/doc.html访问后台项目swaager,接口测试实际请求后台接口地址少了项目前缀 2025-07-25 13:14:11 +08:00
7b80ae3e68 【swagger文档】application/json变成了application/x-www-form-urlencoded 2025-07-25 13:01:36 +08:00
cf4d888839 TODO 暂时注释掉,for:【issues/8638】springboot3分支,knife4j不能正确显示文档,但是swagger-ui和v3/api-docs正常 #8638 2025-07-24 18:34:25 +08:00
336e7851aa 【online】下拉搜索+带条件表字典,报错400 2025-07-22 10:08:40 +08:00
56b9131675 【online】下拉搜索+带条件表字典,报错400 2025-07-22 09:50:22 +08:00
3c0cc49f0c 【issues/8317】菜单管理页首页国际化报错 --- 2025-07-19 09:34:17 +08:00
69b2e97935 【issues/8552】useScript的isLoading默认值应该是true 2025-07-19 09:30:23 +08:00
1c2a49d371 【issues/8564】basicTale的TableLayout换成auto不生效 2025-07-19 09:29:37 +08:00
967197d224 有数十个字段时只展示2个字段,其余字段为ifShow:false会有滚动条 2025-07-19 09:28:16 +08:00
396718bc5e 解决问题:[issues/8558]批量删除优化 2025-07-17 15:07:33 +08:00
37c62c3962 启动democloud服务时出现循环依赖报错 #8573 2025-07-11 10:44:23 +08:00
f510578cb7 启动democloud服务时出现循环依赖报错 #8573 2025-07-11 10:35:17 +08:00
96b378bb7a AI视频介绍 2025-07-09 09:49:56 +08:00
2d7c51eadc 【合并升级v3.8.1】
Merge remote-tracking branch 'origin/master' into springboot3

# Conflicts:
#	jeecg-boot/README.md
#	jeecg-boot/db/tables_nacos.sql
#	jeecg-boot/jeecg-boot-base-core/pom.xml
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/encryption/AesEncryptUtil.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebMvcConfiguration.java
#	jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/pom.xml
#	jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/app/controller/AiragAppController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/httptrace/CustomInMemoryHttpTraceRepository.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/service/impl/OpenApiPermissionServiceImpl.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ISysUserService.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
#	jeecg-boot/jeecg-server-cloud/jeecg-system-cloud-start/src/main/java/org/jeecg/JeecgSystemCloudApplication.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	jeecg-boot/pom.xml
#	jeecgboot-vue3/pnpm-lock.yaml
2025-07-08 16:33:51 +08:00
9d440a4261 升级积木报表到最新版 v2.1.0 2025-07-08 14:02:50 +08:00
4870c43f39 解决【issues/8527】apiSelect分页加载重复请求 2025-07-08 13:44:47 +08:00
9c21f621c0 开源协议 2025-07-08 11:17:34 +08:00
8d382b76ad 开源协议说明 2025-07-08 11:13:57 +08:00
410f2539e1 更新地址 2025-07-08 10:01:02 +08:00
baee00921f 修复问题:低代码开发Online表单开发主子表ERP显示问题 #8532 2025-07-07 14:51:33 +08:00
216d4b9a1f fix: 解决 xxljob 因 factoryBeanObjectType 导致的启动失败 2025-07-06 03:10:33 +08:00
e00b25af42 增加系统功能架构图 2025-07-02 18:57:50 +08:00
44d6b37873 增加博客地址 2025-07-02 16:53:06 +08:00
271712b050 增加博客地址 2025-07-02 16:51:53 +08:00
3482b3a0db 更新项目介绍 2025-07-02 10:29:22 +08:00
10bf5cf127 V3.8.1_2__openapi.sql数据重复 #8531 2025-07-02 10:13:41 +08:00
6cc74699aa 完善项目介绍 2025-07-02 09:57:15 +08:00
0e8fdc2c5a 完善项目介绍 2025-07-02 09:29:45 +08:00
bd6051d972 完善项目介绍 2025-07-02 09:24:30 +08:00
9cfb9dd2b7 完善项目介绍 2025-07-02 09:22:03 +08:00
87b41ab36f 完善项目介绍 2025-07-01 20:26:43 +08:00
378f42bcb7 完善项目介绍 2025-07-01 20:16:38 +08:00
6838888f5f 完善项目介绍 2025-07-01 20:06:27 +08:00
bb8281107e 完善项目介绍 2025-07-01 19:39:35 +08:00
e9d44bfc80 完善项目介绍 2025-07-01 18:53:40 +08:00
8057172f8c 精简项目介绍 2025-07-01 18:45:13 +08:00
c6dd83a262 精简项目介绍 2025-07-01 18:40:42 +08:00
7469474124 项目版本介绍 2025-07-01 18:29:53 +08:00
dc9f36905d 项目版本介绍 2025-07-01 18:23:33 +08:00
30486c5358 项目版本介绍 2025-07-01 18:20:42 +08:00
5b7a90c8bc 项目版本介绍 2025-07-01 15:30:27 +08:00
ac40596ad6 项目版本介绍 2025-07-01 15:25:32 +08:00
6e0edc093b 项目版本介绍 2025-07-01 15:11:14 +08:00
2831996dd4 项目版本介绍 2025-07-01 13:59:06 +08:00
130793fffe 分支说明 2025-07-01 13:54:14 +08:00
5cabfe1655 分支说明 2025-07-01 13:53:02 +08:00
e99e29a523 分支说明 2025-07-01 13:49:35 +08:00
d64e8b0adb 代码生成器模板小优化:生成的列表默认吸底、代码生成年、月、日存储格式修改 2025-07-01 10:15:32 +08:00
4108ba54c3 代码严谨处理:解决部分用户反馈Cannot invoke "org.jeecg.common.api.CommonAPI.queryUserRolesById(String)" because "this.commonAPI" is null 2025-07-01 09:37:57 +08:00
e8ad887096 代码严谨处理:解决部分用户反馈Cannot invoke "org.jeecg.common.api.CommonAPI.queryUserRolesById(String)" because "this.commonAPI" is null 2025-07-01 09:24:04 +08:00
6c24b3cf30 打包electron:build-all 报错少个文件copyChat.ts 2025-06-30 16:02:29 +08:00
208861f808 新增QQ交流群:964611995 2025-06-30 14:24:28 +08:00
f7fe1dfc58 优化初始化脚本jeecgboot-mysql-5.7.sql大小 2025-06-30 09:38:46 +08:00
e2805050cf v3.8.1发布,代码生成支持关联记录组件 2025-06-26 11:50:22 +08:00
b34bb84fc9 v3.8.1发布,更新数据库 2025-06-26 11:30:27 +08:00
11beca16da v3.8.1发布,更新前端依赖 2025-06-26 10:56:18 +08:00
b0c9a2fd9e v3.8.1发布,升级Aiflow后端解决打包过大的问题 2025-06-26 10:56:02 +08:00
6b4e8695ae v3.8.1发布,暂时注释掉报错代码 2025-06-26 10:55:41 +08:00
e8ca74f2ab v3.8.1发布,升级Aiflow前端依赖版本号 2025-06-26 10:55:25 +08:00
eabf98533a v3.8.1发布,上传前端缺少文件 2025-06-26 09:53:12 +08:00
7848881dcb v3.8.1发布,微服务启动system提示mogodb提示错误 2025-06-25 17:51:51 +08:00
553bee57f1 v3.8.1发布,修改版本号 2025-06-25 17:37:33 +08:00
b751570789 v3.8.1发布,上传新版数据库脚本 2025-06-25 16:55:31 +08:00
e45d29c4ff v3.8.1发布,上传前端代码(暂时注释仪表盘缓存刷新功能) 2025-06-25 16:44:00 +08:00
8c8a448a71 v3.8.1发布,上传后台java代码 2025-06-25 16:34:26 +08:00
0148f45979 v3.8.1发布,上传前端代码 2025-06-25 16:04:02 +08:00
3d414aaec8 v3.8.1发布,上传代码 2025-06-25 15:16:00 +08:00
7a4c66af57 v3.8.1发布,上传代码 2025-06-25 13:34:13 +08:00
444c7140f6 解决TableAction中自定义图标颜色不起作用的问题 2025-06-25 09:55:07 +08:00
0fda30b5d2 修改接口地址,验证码404 2025-06-16 15:00:39 +08:00
c8e33d43cb 体验地址更改 2025-06-13 13:56:47 +08:00
6c6af870ae jeecgboot vs 敲敲云 2025-06-13 13:53:33 +08:00
79107599a6 增加jeecgboot vs 敲敲云 说明 2025-06-13 13:51:56 +08:00
b6e8b37aee 禁用不好使 2025-06-12 17:00:35 +08:00
195ddd0421 降低shiro版本号,导致不兼容jdk8 2025-06-11 22:18:48 +08:00
9ddad931ff 【issues/8374】分页始终显示在底部 2025-06-10 09:52:27 +08:00
fc05fe1aff 补充.npmrc 2025-06-09 09:22:21 +08:00
7e325f68ca Merge pull request #8389 from 1298191366/master
open api功能优化
2025-06-06 15:22:11 +08:00
f74da23d06 升级积木报表到最新版2.0.0 2025-06-06 11:21:50 +08:00
e279915ba2 --author:wangshuai---date:2025-06-06---for:【QQYUN-12667】open api功能优化--- 2025-06-06 09:54:55 +08:00
bb6f077a95 Revert "//update---author:wangshuai---date:2025-06-05---for:open api功能优化:ak接口返回未明确提示错误---"
This reverts commit 7a031e6135.
2025-06-06 09:35:43 +08:00
7a031e6135 //update---author:wangshuai---date:2025-06-05---for:open api功能优化:ak接口返回未明确提示错误--- 2025-06-06 09:35:27 +08:00
5972c74b43 解决积木报表springboot3 找不到类base64utils #3834和SqlServer兼容问题 2025-06-05 15:51:05 +08:00
157877f9a6 【issues/8233】resetFields时无法重置 2025-06-05 09:34:54 +08:00
25a71fa66c 【issues/8232】代码设置JSelectDept组件值没翻译 2025-06-05 09:34:11 +08:00
fdc02fa68a [-- author: liusq---date:20250604--for: issue【日志管理】的异常日志列表显示不正常 #8295 --] 2025-06-05 09:33:24 +08:00
ec3c34969a ---author:chenrui---date:2025/6/4-----for:[issues/8309]系统监控>请求追踪,列表每刷新一下,总数据就减一#8309 --- 2025-06-05 09:31:32 +08:00
5a215525d5 调整aksk测试数据 2025-05-29 16:07:30 +08:00
450b93d916 Merge pull request #8358 from xlh12306/master
使用原生方式对接口进行测试 修复授权管理页面重置AK,SK未写入到数据库中的异常
2025-05-29 15:56:13 +08:00
2d62bad2a9 使用原生方式对接口进行测试 修复授权管理页面重置AK,SK未写入到数据库中的异常
使用原生方式对接口进行测试
修复授权管理页面重置AK,SK未写入到数据库中的异常
2025-05-28 22:22:39 +08:00
0b10096f1c 修复微服务启动失败报错 2025-05-28 15:49:56 +08:00
d69cb121fc 解决AI脚本节点执行报错问题 2025-05-28 11:07:33 +08:00
431ddb8fcb 系统监控的头两个tab不好使,接口404--- 2025-05-27 22:51:25 +08:00
ddf0f61ae5 修复v3.8.0 存在绕过sql黑名单限制sql注入漏洞 #8335
修复minidao `getQueryTableInfo`无法解析带括号的表名、增加数据库名解析能力
2025-05-27 18:40:34 +08:00
10a9edd10b ai⼯作流使⽤知识库报错 "白名单校验未通过" 2025-05-27 17:56:46 +08:00
4042579167 提供更新的数据库脚本,加入openapi的表和放开AI流程设计菜单 2025-05-27 09:51:52 +08:00
c71ff3fbcc 访问Swagger接口不带doc.html后缀,会丢失项目前缀/jeecg-boot/导致测试接口,返回下载文件 2025-05-26 19:14:02 +08:00
bd5fda5968 访问Swagger接口不带doc.html后缀,会丢失项目前缀/jeecg-boot/导致测试接口,返回下载文件 2025-05-26 19:03:29 +08:00
fdbd9c30ac 解决Swagger3Config 接口文档参数显示问题 #8325 2025-05-25 22:49:07 +08:00
b8b4d3f29d JVxetable升级到最新版 2025-05-25 18:09:19 +08:00
78212aa7c0 通讯录手机号码没有显示出来 #8282 2025-05-25 16:53:33 +08:00
08612d5bfa springboot3分支的redis配置格式改了 2025-05-22 11:12:27 +08:00
6dc3c6af2a nacos增加aigc配置 2025-05-22 11:01:06 +08:00
2ecce8f02d 更新nacos配置,增加aigc的配置 2025-05-22 10:59:57 +08:00
62937f14fb 升级shiro到2.0.4 2025-05-22 10:55:16 +08:00
d6ccc4a326 还原库名 2025-05-22 10:50:17 +08:00
1893108136 升级版本号到3.8.1(springboot3升级到3.4.5) 2025-05-22 10:18:25 +08:00
7980915bdc 移除AI大模型管理依赖并更新pom.xml 2025-05-22 09:28:04 +08:00
b7a6812140 更新pom.xml,添加jeecg-boot-module-airag依赖 2025-05-22 09:25:39 +08:00
550997268b 最新版 2025-05-20 10:24:34 +08:00
9e7d40a080 升级springboot3.4.5 2025-05-19 16:09:09 +08:00
7efc51e30e 更新README.md,修改新手指南和在线体验部分的描述 2025-05-19 14:14:18 +08:00
2c38db456b 合并redis配置错误 2025-05-19 13:58:09 +08:00
bd83b994bc Merge pull request #8298 from xlh12306/master
openapi相关测试项修改
2025-05-18 17:01:28 +08:00
e52538d304 升级spring3.4.5后,会有很多警告BeanPostProcessorChecker:437 - Bean 'org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration' of type [org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected/applied to a currently created BeanPostProcessor [defaultAdvisorAutoProxyCreator]? Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE. 2025-05-18 16:40:55 +08:00
e91cbd5cd8 Merge pull request #8297 from MuShan-bit/springboot3_upgrade344-fix-warn
logging(level): 设置 PostProcessorRegistrationDelegate 日志级别为 error
2025-05-18 16:33:14 +08:00
8fb81f331c 提交openAPiModel 2025-05-16 23:13:11 +08:00
fb188a83a1 提交openapi单元测试代码
调整接口管理的字段位置
授权管理删掉无用配置
授权管理编辑改为重置生成ak sk功能
授权页面应该改成跟角色授权类型的效果
2025-05-16 23:12:28 +08:00
70cec8b5c6 logging(level): 设置 PostProcessorRegistrationDelegate 日志级别为 error
- 在 application-dev.yml 文件中添加了 org.springframework.context.support.PostProcessorRegistrationDelegate 的日志级别配置
- 此修改旨在减少不必要的日志输出,提高日志的可读性和性能
2025-05-16 22:29:00 +08:00
d2365088ce AIGC大模型应用功能 2025-05-16 11:27:48 +08:00
a679571a5a 基于AK和SK认证鉴权OpenAPI 2025-05-16 10:41:24 +08:00
b9c74e549f 移除javax.annotation.Resource导入,改为使用jakarta.annotation.Resource 2025-05-16 10:31:49 +08:00
81c1724016 升级online到v3.8.0版本 2025-05-16 10:31:39 +08:00
56d59eb589 修改springboot3 v3.8.0发布时间 2025-05-16 09:58:36 +08:00
a00fcae3a3 【v3.8.0 合并】Merge remote-tracking branch 'origin/master' into springboot3
# Conflicts:
#	README.md
#	jeecg-boot/db/tables_nacos.sql
#	jeecg-boot/jeecg-boot-base-core/pom.xml
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/oConvertUtils.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebMvcConfiguration.java
#	jeecg-boot/jeecg-boot-module/jeecg-module-demo/src/main/java/org/jeecg/modules/demo/test/controller/JeecgDemoController.java
#	jeecg-boot/jeecg-boot-module/jeecg-module-demo/src/main/java/org/jeecg/modules/demo/test/entity/JeecgDemo.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiLogController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiPermissionController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/entity/OpenApi.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/entity/OpenApiAuth.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/entity/OpenApiHeader.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/entity/OpenApiLog.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/entity/OpenApiParam.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/filter/ApiAuthFilter.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/mapper/OpenApiLogMapper.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/service/OpenApiLogService.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/DuplicateCheckController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysCommentController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDataSourceController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartPermissionController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartRoleController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictItemController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysGatewayRouteController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTableWhiteListController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysCheckRule.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysComment.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDataSource.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDepartPermission.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDepartRole.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDepartRolePermission.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysDepartRoleUser.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFillRule.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFormFile.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysGatewayRoute.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysPackPermission.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysPosition.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysRoleIndex.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysTableWhiteList.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysTenantPack.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysTenantPackUser.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysThirdAccount.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysThirdAppConfig.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUserPosition.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysUserTenant.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/model/DuplicateCheckVo.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/controller/${entityPackage}/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai
#	jeecg-boot/jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/config/flyway/FlywayConfig.java
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml
#	jeecg-boot/jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/system/test/SampleTest.java
#	jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java
#	jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/loader/DynamicRouteLoader.java
#	jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/resources/application.yml
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-more/src/main/java/org/jeecg/modules/test/feign/controller/JeecgTestFeignController.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-rocketmq/src/main/java/org/jeecg/modules/test/rocketmq/controller/JeecgMqTestController.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-test/jeecg-cloud-test-seata/jeecg-cloud-test-seata-order/src/main/java/org/jeecg/modules/test/seata/order/controller/SeataOrderController.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/core/old/RemoteHttpJobBean.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/core/old/XxlJobDynamicScheduler.java
#	jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/core/old/XxlJobThreadPool.java
#	jeecg-boot/pom.xml
2025-05-15 20:01:54 +08:00
9aea5de668 基于安全认证AK和SK鉴权调用OPEN API功能 2025-05-15 10:23:27 +08:00
8979dd7ae9 Merge branch 'master' into master 2025-05-14 22:17:00 +08:00
a56bd05389 将请求方式修改为大写,修复openapi回调执行调用接口失败的问题 2025-05-14 22:04:06 +08:00
9cf3328ea4 uniapp3代码生成器模板 2025-05-14 18:33:15 +08:00
286d10a50f Merge branch 'springboot3_upgrade344' of https://github.com/jeecgboot/jeecg-boot into springboot3_upgrade344 2025-05-14 15:19:10 +08:00
37c593e1d4 删除jsqlparse代码 2025-05-14 15:04:57 +08:00
68f36cb1e5 升级online 2025-05-14 13:59:56 +08:00
78454d3434 Merge pull request #8273 from MuShan-bit/springboot3_upgrade344-upgrade-shiro2.0.4
feat: 升级 shiro 到 2.0.4 版本,解决 ShiroRequestMappingConfig 获取 RequestMappingHandlerMapping Bean 冲突
2025-05-14 09:21:36 +08:00
56fbc2ed8f feat: 升级 shiro 到 2.0.4 版本,解决Shiro获取 requestMappingHandlerMapping 时 spring-boot-autoconfigure:3.4.5 和 spring-boot-actuator-autoconfigure:3.4.5 Bean 依赖冲突, 2025-05-13 22:48:48 +08:00
197d7adaaf Merge pull request #8256 from MuShan-bit/springboot3-chore-upgrade-shiro
upgrade shiro to 2.0.4
2025-05-11 10:34:23 +08:00
49ba40e98a 提交api接口设计前端页面以及后端更改 2025-05-10 23:56:06 +08:00
e952518d71 feat: 升级 shiro 到 2.0.4 版本 2025-05-10 22:14:02 +08:00
0e184eaa64 升级shiro到2.0.4 2025-05-09 10:17:14 +08:00
86a3ed9dae 更新OpenApiController,使用创建用户生成token签名,简化用户关联逻辑 2025-05-09 10:11:33 +08:00
1e259c805e fastjson升级到2.0.57;jimureport升级到1.9.5;minidao升级到1.10.8 2025-05-08 22:39:57 +08:00
8a82141c95 升级jsqlparser到4.9 2025-05-08 16:47:46 +08:00
94bff11eb1 移除sqlparse代码改调minidao方法、升级fastjson版本号到2.0.57 2025-05-07 13:37:54 +08:00
590d73dfe3 修改版本号 2025-05-06 16:01:31 +08:00
fe9630d15c 【issues/8211】判断逻辑写的有问题--
org/jeecg/config/firewall/interceptor/LowCodeModeInterceptor.java
2025-05-06 09:24:20 +08:00
77ae25b86a 解决jeecg-boot-V3.8.0使用下拉树组件时高频率报错UT005071: Undertow request failed HttpServerExchange{ GET /sys/dict/loadTreeData} #8217 2025-05-04 17:28:30 +08:00
3b34276cf8 新增一个UI组件,支持通过部门选人,更加便捷 2025-05-04 16:34:12 +08:00
cffba084fc 【issues/8178】使用原生vxe-table组件编辑模式下失去焦点报错 2025-05-04 16:27:28 +08:00
d1589acc41 回滚swagger配置 2025-05-03 17:14:18 +08:00
888a032266 优化bean无法被所有beanpostprocessor处理 2025-04-30 10:00:02 +08:00
0d18e536f0 解决swagger生成文档,参数乱码问题 2025-04-29 16:14:51 +08:00
21392c44f8 issues/8181】同步部门(将钉钉部门同步到本地) #8181 2025-04-29 09:54:21 +08:00
2730d8e06f 流程编排脚本节点不好使问题 2025-04-28 17:36:57 +08:00
0002606d41 流程编排脚本节点不好使问题 2025-04-28 12:54:38 +08:00
8bd19484ee 升级jeecg-aiflow依赖版本至1.0.3 2025-04-28 11:51:55 +08:00
5d2db92613 默认切jdk17 2025-04-27 10:21:56 +08:00
c1b39d21dd 升级AI引擎,底层接口开放 2025-04-26 16:16:50 +08:00
e83c9b8190 【jvxeTable】expandConfig属性无用 2025-04-26 16:09:49 +08:00
309c76d268 修复swagger接口文档正常显示 2025-04-25 18:08:45 +08:00
9bd03f467d 【pull/8014】插槽方式弹窗中取消该数据checkbox的选中状态,需要点击第二次才生效。 2025-04-25 16:59:03 +08:00
f78eabfc66 使用minidao适配jsqlparser 2025-04-25 16:54:55 +08:00
e032591366 • 【AI】兼容jdk21,让程序可以启动,但是提示AI流程编排无法使用
• 【AI】流程,入参中的必填没有校验
• 【AI】开启多租户,导致流程接口调用提示流程不存在
• 【AI】流程调用流程接口改成无需登录
2025-04-24 14:02:32 +08:00
de767e07b4 【issues/8093】删除后会先变成编码再显示label文字 2025-04-24 09:27:58 +08:00
b77d3e36ab 【issues/8075】可编辑行无法获取最新的值 2025-04-24 09:27:16 +08:00
7885aaed3b 【issues/8137】vxetable表格禁用后分页隐藏了 2025-04-24 09:26:27 +08:00
6f4c2eb77c 【pull/8013】修复 BasicTable position 属性类型配置 --- 2025-04-24 09:25:22 +08:00
3f0597a0f6 【issues/7986】插槽方式弹窗中取消该数据checkbox的选中状态,需要点击第二次才生效 2025-04-24 09:24:48 +08:00
04a3764f00 弹窗中勾选,再点取消,值被选中了
弹窗勾选了值,点击取消再次打开弹窗遗留了上次的勾选的值
2025-04-24 09:24:00 +08:00
68464109de Merge remote-tracking branch 'origin/master' 2025-04-23 19:10:59 +08:00
79866c5823 AI大模型使用本地部署的deepseek报错 #8164 2025-04-23 19:10:44 +08:00
d64b8ecaef Merge pull request #8160 from EightMonth/master
修复 #8134
2025-04-23 18:42:45 +08:00
ec9f2b146a 敲敲云支持在线免费搭建AI知识库 2025-04-23 15:32:37 +08:00
69fd2888a1 Update application.yml 2025-04-23 11:12:59 +08:00
748331d649 处理jsqlparser兼容问题 2025-04-22 16:00:17 +08:00
cb1d8e3527 修复 #8134 2025-04-22 10:05:04 +08:00
a89b299a4b 邮件发送失败,修改yml配置方式 2025-04-21 10:19:23 +08:00
7a15bfc161 错别字修复 2025-04-20 16:51:56 +08:00
65f7eb9542 支持全信创环境 2025-04-18 14:54:53 +08:00
92808f9164 JeecgBoot 里程碑 v3.8.0,AI 首版本发布 2025-04-17 14:13:36 +08:00
d3ed3f49d3 JeecgBoot 里程碑 v3.8.0,AI 首版本发布 2025-04-17 14:12:34 +08:00
da3d39c59c 里程碑 v3.8.0,AI 首版本发布 2025-04-17 14:11:51 +08:00
f332758179 【issues/3656】popupdict回显 2025-04-16 18:45:59 +08:00
61a8904e52 【issues/8097】icon组件svg图标显示空白问题 2025-04-16 18:42:22 +08:00
b70e709e53 升级spring boot 3.4.4 2025-04-16 16:18:32 +08:00
b032a415aa AI介绍 2025-04-15 16:57:24 +08:00
81821eeddc AI大模型介绍 2025-04-15 16:14:07 +08:00
5288b1fe73 AI介绍 2025-04-15 16:12:52 +08:00
408f192b37 一个全栈式 AI 开发平台,旨在帮助开发者快速构建和部署个性化的 AI 应用。 2025-04-15 16:11:40 +08:00
6a9f188282 AI大模型的集成导致暂时不支持jdk21 2025-04-15 16:07:24 +08:00
168f15e1c2 AI大模型说明 2025-04-15 16:04:11 +08:00
ae814a7e8b 删除废弃无用代码 2025-04-15 15:03:25 +08:00
2ba17648c4 Merge pull request #8116 from EightMonth/springboot3
优化swagger文档改造
2025-04-15 11:41:44 +08:00
7160ea32cb 默认主题配置不生效 2025-04-15 11:24:22 +08:00
19fc610ef5 【issues/8098】修复示例中的Tab标签页关闭操作问题 2025-04-15 11:21:08 +08:00
44146f073e 【issues/8078】角色选择组件点击文字部分会一直选中 2025-04-15 11:19:36 +08:00
36caab37e2 Update application-mysql.yml 2025-04-15 11:07:54 +08:00
8abce5ad9c 升级新版online 2025-04-15 10:52:35 +08:00
6e721e4120 归集spring-doc默认配置
(cherry picked from commit d4d0c884f0)
2025-04-15 10:39:05 +08:00
447e439612 还原提交 2025-04-15 10:32:13 +08:00
088c79238e 解决翻译Popup字典错误 #8114 2025-04-15 09:52:22 +08:00
ad72c807f6 JeecgBoot是一款基于AIGC和低代码引擎的AI低代码平台,旨在帮助开发者快速实现低代码开发和构建、部署个性化的 AI 应用 2025-04-14 20:16:17 +08:00
db3d95e1a7 AI模型发布 2025-04-14 20:06:19 +08:00
1a16b5550f AI项目介绍更新 2025-04-14 20:01:04 +08:00
c6fe809013 AIGC大模型增加向量库的yml配置 2025-04-14 19:05:27 +08:00
677b57ae09 【知识库】知识库上传之后没有命中,下载文件下载不下来。但是磁盘里面有--- 2025-04-14 18:36:00 +08:00
02f21de8d5 AI大模型,key调用错误处理 2025-04-14 18:32:02 +08:00
f7ca26fff0 AI大模型调用错误处理 2025-04-14 18:15:11 +08:00
6c6aa964e8 补充AI大模型对接向量库配置说明 2025-04-14 17:45:04 +08:00
b0bab050dd AI大模型功能 2025-04-14 17:40:44 +08:00
87197be8f7 aiflow采用jdk8编译,解决项目不支持jdk8问题 2025-04-14 16:18:58 +08:00
75aa1fe5a0 解决bug:ai大模型-ai应用管理-配置菜单后404 #8111 2025-04-14 15:05:01 +08:00
3e434ce6b4 v3.8.0代码上传,AI大模型功能发布 2025-04-14 13:32:29 +08:00
e07508d29f v3.8.0代码上传,AI大模型功能发布 2025-04-14 11:42:46 +08:00
e18e980892 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-04-14 11:38:44 +08:00
a2f18fd0d9 代码生成器模板更新,popup字典下拉翻译问题 2025-04-10 15:36:17 +08:00
9ad7ef5ab4 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-04-09 16:25:32 +08:00
27a7046465 Popup字典列表渲染支持翻译 2025-04-09 16:04:08 +08:00
47a2a6fbac Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-04-09 13:45:29 +08:00
83b1c8692e ApiSelect组件支持分页下拉方案 #7883 2025-04-09 09:40:58 +08:00
73a5f64d7e 【issues/8034】hash模式下退出重登录默认跳转地址异常 2025-04-09 09:39:34 +08:00
1d18a54b8a 解决升级undertow后,性能监控tomcat信息tab项展示的问题 2025-04-09 09:36:49 +08:00
e877929a42 Merge branch 'HEAD' of https://github.com/jeecgboot/JeecgBoot.git 2025-04-08 22:05:42 +08:00
5f5970d7d5 解决钉钉登录报错 class com.alibaba.fastjson2.JSONObject cannot be cast to class com.alibaba.fastjson.JSONObject 2025-04-08 22:05:20 +08:00
e05c9ddc08 Merge pull request #8073 from EightMonth/master
新增controller测试用例
2025-04-08 16:27:43 +08:00
b77e9e25a3 AI功能介绍 2025-04-08 15:51:11 +08:00
a8bf090352 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-04-08 15:29:22 +08:00
b6c9f9db68 集成aiflow AI流程设计器 2025-04-08 14:53:58 +08:00
8c406dcdea 项目介绍 2025-04-08 11:44:45 +08:00
215b263d1a 项目介绍 2025-04-08 11:41:21 +08:00
4247ffd082 AIGC专题介绍页 2025-04-08 11:04:32 +08:00
ec87621858 AI流程大模型功能 2025-04-08 10:48:24 +08:00
bc6cf0e7b4 Merge branch 'HEAD' of https://github.com/jeecgboot/JeecgBoot.git 2025-04-08 09:56:48 +08:00
353ad058d1 AIGC 功能视频介绍 2025-04-08 09:56:32 +08:00
cf63b056d5 新增controller测试用例 2025-04-08 09:20:00 +08:00
60eeef14c7 更新pom.xml,替换aiflow依赖为jeecg-aiflow并调整版本 2025-04-08 00:02:35 +08:00
25b30153a0 集成jeecg的aiflow AI流程设计器 2025-04-07 23:23:52 +08:00
beff2a271e Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-04-07 16:10:29 +08:00
f743622655 Merge pull request #8066 from EightMonth/master
编写单个controller的测试用例
2025-04-07 16:08:30 +08:00
70a1f0b7db 编写单个controller的测试用例 2025-04-07 15:59:46 +08:00
e166d916da 重要参数补充 2025-04-07 15:42:21 +08:00
b79ba97614 v3.8.0 完整数据库脚本 2025-04-07 15:29:58 +08:00
4f371672d0 升级版本号v3.8.0,归档历史增量SQL 2025-04-07 15:18:02 +08:00
80ae183b58 升级版本号v3.8.0 发布AI大模型功能 2025-04-07 14:33:00 +08:00
b4cac11368 AI大模型管理功能后台代码 2025-04-07 14:10:37 +08:00
4936e140e9 归档老的增量SQL 2025-04-07 14:09:27 +08:00
9fd4c3b3d2 将demo迁移到module模块中 2025-04-07 14:09:17 +08:00
4f2f1d6265 将AI对话聊天界面换成新地址 2025-04-07 14:08:44 +08:00
b878f6b6be 删除老的AI聊天界面 2025-04-07 14:08:36 +08:00
507289ff6c AIGC应用平台+知识库模块 2025-04-07 14:08:27 +08:00
bb4cdf93b1 Merge pull request #8059 from EightMonth/master
优化swagger文档架构改造
2025-04-04 23:05:37 +08:00
7d7fde63ec 【issues/7996】表格列组件取消所有或者只勾选中间,显示非预期 2025-04-04 22:46:30 +08:00
c22fd21233 【issues/7812】linkageConfig改变了,vxetable没更新 2025-04-04 22:45:00 +08:00
d4d0c884f0 归集spring-doc默认配置 2025-04-03 22:31:26 +08:00
e6fe3459e4 配置调整 2025-04-03 18:17:43 +08:00
9ebc3c49ec 优化swagger文档架构改造 2025-04-03 17:54:51 +08:00
a17b403675 优化swagger文档架构改造 2025-04-03 17:46:11 +08:00
45e9b03e2d app地址修改 2025-04-03 12:05:47 +08:00
696b65240f AI大模型支持 2025-04-03 12:03:34 +08:00
f4339677e7 版本发布日期调整 2025-04-03 11:50:05 +08:00
0aaf0ad3ad AIGC应用平台介绍 2025-04-03 11:33:45 +08:00
0e5cd5bb3e AIGC介绍 2025-04-03 11:29:26 +08:00
24406a4cac AI介绍 2025-04-03 11:27:53 +08:00
1a1c840a3b AI功能展示 2025-04-03 11:25:29 +08:00
2e257343a4 aigc独立专题介绍页面 2025-04-03 11:20:05 +08:00
7871c465c8 ERP风格内嵌子表生成源代码,展开子表的会根据展开的次数进行创建销毁子表的组件 2025-04-03 10:09:36 +08:00
714d9dc244 解决启动警告 WARN io.undertow.websockets.jsr:68 - UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used 2025-04-03 00:00:18 +08:00
f23b176cf4 fix: update link text for GitHub URL in header 2025-04-02 22:45:42 +08:00
494f5e21f5 undertow配置、增加springdoc配置、简化flyway配置 2025-04-01 22:02:39 +08:00
dea260cae3 注释掉日志打印 2025-04-01 21:35:45 +08:00
0fcc08c204 fix: update import path for AiChatProperties in ChatServiceImpl 2025-04-01 21:33:08 +08:00
632fd72d79 Merge pull request #8053 from EightMonth/springboot3
排除部分接口文档,为免登录接口排除token校验请求头
2025-04-01 21:28:44 +08:00
608d2e1318 Merge pull request #8038 from EightMonth/knife_biz
Knife4j升级4.4.0 业务代码改动
2025-04-01 21:28:35 +08:00
7e436f2efd Merge pull request #8039 from EightMonth/knife_arch
Knife4j升级4.4.0 架构代码改动
2025-04-01 21:28:23 +08:00
15fc262675 排除部分接口文档,为免登录接口排除token校验请求头 2025-04-01 18:05:04 +08:00
c18fb68e81 接口文档调整,为免登录接口排除token校验请求头 2025-04-01 17:01:58 +08:00
299f63c6e9 修改token验证请求头信息及排除不需要的接口信息 2025-04-01 15:05:08 +08:00
20037ae02b 添加误移除内容 2025-03-31 16:36:43 +08:00
dcdbb5ac7a 3.7.4 版本数据库脚本 2025-03-31 16:11:25 +08:00
cd9ba3bac9 新增改动 2025-03-31 15:58:26 +08:00
060bf2282c 更新readme 2025-03-31 15:15:17 +08:00
d88f2f81e9 knife4j升级4.4.0注解改造 2025-03-31 14:54:06 +08:00
18cc746fcf 升级java-jwt到4.5.0 2025-03-31 14:35:47 +08:00
fcc7842e89 修改自动生成接口文档范围
(cherry picked from commit ff58a1dd26)
2025-03-31 14:32:33 +08:00
e91af8cfd3 knife4j升级4.4.0架构改造 2025-03-31 14:25:56 +08:00
a57cc1fa3d 3.7.4 版本升级online在线开发模块 2025-03-31 14:23:05 +08:00
80d37f9a03 3.7.4 版本升级online在线开发模块 2025-03-31 11:58:30 +08:00
502ef2f65d 【同步3.7.4版本代码】新增全局布局隐藏配置,优化多个组件的属性和逻辑 2025-03-30 19:09:07 +08:00
62daec9c16 3.7.4 版本增量升级SQL 2025-03-30 18:40:49 +08:00
9191a8b620 【3.7.4 开源代码同步】新增断言异常类和断言工具类,优化JWT工具类,更新文件类型白名单,切换undertow配置,修改多个YAML配置文件 2025-03-30 17:51:55 +08:00
4fb53637aa 支持数据库说明 2025-03-28 18:32:58 +08:00
178a2368cb 3.7.4(预计发布日期:2025-04-10,代码逐步提交) 2025-03-28 09:35:57 +08:00
0813dee0d4 优化oConvertUtils中childArray转换逻辑 2025-03-27 19:47:09 +08:00
9579a60abd jdk支持说明:支持jdk8、17、21 2025-03-27 19:38:46 +08:00
5cd5bf7a0b 移除冗余Flyway配置,优化application.yml文件 2025-03-27 18:48:03 +08:00
c0265981d1 视频介绍 2025-03-27 18:43:18 +08:00
2ec13165d3 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	jeecg-boot/pom.xml
2025-03-27 18:26:20 +08:00
ac5ee60364 Merge pull request #8027 from EightMonth/master
移除junit4,使用默认junit5
2025-03-27 18:09:34 +08:00
5ff1b56fe2 移除junit4,使用默认junit5 2025-03-27 16:58:35 +08:00
ea914be3a6 升级至3.7.4,更新Dockerfile及jdk依赖 2025-03-27 15:19:41 +08:00
cb65e1796c 【3.7.4版本底层依赖大升级】
默认改成JDK17;fastjson升级至2.0.56;升级spring-cloud小版本;升级jimureport到最新版1.9.5;升级weixin4j到2.0.1;
spring-cloud >2021.0.8
spring-cloud-alibaba >2021.0.6.2
2025-03-27 15:19:00 +08:00
ff815f1ae6 更新版本至3.7.4并调整发布时间 2025-03-27 15:17:48 +08:00
c8ebdc162f 更新版本至3.7.4并调整发布时间 2025-03-27 15:17:08 +08:00
6768d65e1e Merge pull request #8008 from EightMonth/springboot3
修复 CVE-2023-6378
2025-03-25 16:02:57 +08:00
410ab7bcc3 修复 CVE-2023-6378 2025-03-25 15:58:19 +08:00
76df4f8600 Merge pull request #8006 from EightMonth/master
回退 "fastjson升级至2.0.43"
2025-03-25 15:04:30 +08:00
a27b94c4c6 Revert "fastjson升级至2.0.43"
This reverts commit d87ffc11e7.
2025-03-25 14:55:36 +08:00
5ad06274cb 升级shiro至1.13.0及shiro-redis至3.2.3 2025-03-25 14:34:31 +08:00
d38fa1901e Merge pull request #8003 from EightMonth/master
fastjson升级至2.0.43
2025-03-25 14:29:10 +08:00
174f1ae432 Merge pull request #8004 from EightMonth/springboot3
jeewx-api修改成weixin4j
2025-03-25 14:19:42 +08:00
eef2f7e269 jeewx-api修改成weixin4j 2025-03-25 14:13:45 +08:00
6a0ec66d3d Merge branch 'springboot3' of https://github.com/jeecgboot/jeecg-boot into springboot3 2025-03-25 14:10:17 +08:00
b4aab76057 Merge branch 'master' of https://github.com/EightMonth/jeecg-boot 2025-03-25 14:00:58 +08:00
d87ffc11e7 fastjson升级至2.0.43 2025-03-25 14:00:43 +08:00
a67b3409b1 Merge pull request #7981 from EightMonth/master
修复 #7951 CVE-2023-6378
2025-03-21 23:38:08 +08:00
e11d831114 修复 #7951 CVE-2023-6378 2025-03-20 16:50:37 +08:00
ec410456b2 Merge pull request #7879 from yangyang122/feature/tenant_edit_role
in tenant mode, edit role constraints change
2025-03-20 10:46:46 +08:00
e9326cab8c Merge pull request #7651 from testnet0/master
修复flyway自动升级失败
2025-03-20 10:39:08 +08:00
61d2857ca7 【issues/7940】componentProps写成函数形式时,updateSchema写成对象时,参数没合并 --- 2025-03-20 10:09:48 +08:00
cba4847413 【issues/7948】修复JselectRole组件不支持双向绑定 --- 2025-03-20 10:09:06 +08:00
bc56384325 【issues/7954】BasicUpload组件上传文件,限制上传格式校验出错 --- 2025-03-20 10:08:20 +08:00
d7dc1b8dc7 【issues/7956】修复showSummary: false时且有内嵌子表时合计栏错位 2025-03-20 10:06:57 +08:00
11d9f2b4e4 视频介绍 2025-03-18 10:10:33 +08:00
163b0b531f 视频介绍 2025-03-18 10:08:05 +08:00
64fcf7fcfc 提供完整的初始化sql 含积木报表最新增量sql 2025-03-16 16:04:43 +08:00
e6ddeef18c 默认关闭AI助手悬浮按钮 2025-03-13 09:53:05 +08:00
d1af49a33f Merge pull request #7949 from EightMonth/springboot3
解决严重bug,War包方式部署,服务启动报错
2025-03-12 15:28:07 +08:00
03265691e6 解决严重bug,War包方式部署,服务启动报错 2025-03-12 14:12:00 +08:00
47a074d9cb 解决严重bug,War包方式部署,服务启动报错 2025-03-11 09:43:39 +08:00
c32f0407e8 更新README.md,添加AI大模型文档链接 2025-03-09 16:38:00 +08:00
22bbc23069 更新README.md,优化AI功能列表及支持模型 2025-03-07 18:25:33 +08:00
b2078d502a 更新README.md,添加AI平台支持及功能介绍 2025-03-07 18:20:10 +08:00
ed165464c8 升级druid版本到1.2.24 #7869
升级jeewx-api版本到weixin4j 2.0.0
2025-03-07 15:55:09 +08:00
9cf66e7026 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-03-06 22:04:19 +08:00
11f8038196 AIGC功能模块即将出炉 2025-03-06 22:03:29 +08:00
d2105dc095 in tenant mode, edit role constraints change 2025-03-04 14:58:38 +08:00
32287d98ac Merge pull request #7833 from hoperunChen/QQYUN/QQYUN-10958
[QQYUN-10958]删除jeecgboot中的MongoAutoConfiguration,因为jm-nosql中已经有了
2025-03-03 17:19:27 +08:00
de9cc2f30d Merge pull request #7874 from EightMonth/springboot3
修复 #7613
2025-03-03 17:05:01 +08:00
31cf94ac7b Merge pull request #7850 from EightMonth/master
修复 #7702
2025-03-03 16:38:39 +08:00
26887959cd 修复 #7613 2025-03-03 14:27:16 +08:00
0d28c92c83 master分支默认jdk8 2025-03-02 17:57:26 +08:00
1cc5cee92d 升级项目介绍 2025-03-02 17:53:04 +08:00
26246eda7a 升级druid版本到1.2.24 #7869
升级jeewx-api版本到weixin4j 2.0.0
2025-03-02 17:49:29 +08:00
10dd2a2dd0 反馈bug 2025-02-28 16:05:08 +08:00
5abc745496 jeecg官方文档更新 2025-02-26 10:30:57 +08:00
353e8e2fb6 [issues/7288]数据权限,查看自己拥有部门的权限中存在问题 #7288--- 2025-02-24 22:49:58 +08:00
56661815ec 【issues/7830】合计小数计算精度 --- 2025-02-24 22:48:45 +08:00
03b6d20fcb 修复 #7702 2025-02-24 17:33:52 +08:00
7e15e81218 版本合并,升级springboot3分支到3.7.3 2025-02-20 17:56:16 +08:00
2388c8c46d [QQYUN-10958]删除jeecgboot中的MongoAutoConfiguration,因为jm-nosql中已经有了 2025-02-20 10:43:20 +08:00
45f905ddac Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2025-02-19 18:45:26 +08:00
55696efcaa jimureport、jimubi升级到最新版1.9.4,补充权限注解 2025-02-19 18:45:14 +08:00
3671b81f01 Merge pull request #7564 from EightMonth/master
keys替换scan问题 修复 #6918 #6876
2025-02-19 18:42:09 +08:00
74ad7e6f92 jimureport、jimubi升级到最新版1.9.4 2025-02-19 15:03:07 +08:00
49d55a79f4 当用户没有角色保存操作权限时候操作角色保存仅保存和保存并关闭按钮会一直转圈不可用 2025-02-19 10:24:00 +08:00
8395d106a2 【issues/7773】合计没有跟着左右滚动条滚动 2025-02-19 10:23:10 +08:00
d716111ded 生成代码的时候,选择原生表单(form) 就会出错 #7817 2025-02-19 10:00:45 +08:00
81b4cbbe35 修复问题:线上ai助手后端内容一次性返回,消息不显示 2025-02-13 20:00:15 +08:00
86cfc18fe8 优化AI图标 2025-02-12 20:10:21 +08:00
98ba72ae4b 关注公众号了解官方动态 2025-02-12 10:45:52 +08:00
8b0e0367c7 Merge pull request #7797 from EightMonth/springboot3
固定vue-router版本号
2025-02-11 14:49:06 +08:00
334f7dbb62 Update package.json 2025-02-11 14:24:18 +08:00
29248561d6 修复第三方登录接口通过token获取用户信息漏洞 2025-02-11 11:37:55 +08:00
ad74b78134 JSelectUserByDept组件的params可选参数似乎不起作用 #7758 2025-02-11 11:32:10 +08:00
bd716417e8 【issues/7738】文件中带"success"导出报错 2025-02-11 11:30:10 +08:00
e9ddd21286 固定vue-router版本号 2025-02-11 09:53:29 +08:00
1acb773adf 完善OpenApi模块文档 2025-02-10 15:51:17 +08:00
5753f3d1d9 xxl_job的sql脚本缺少字段 2025-02-10 13:51:39 +08:00
46fb1cce91 3.7.3版本启动提示连接不上mongodb #7787 2025-02-10 13:43:42 +08:00
d0487e7a9d 语言优化 2025-02-10 11:40:00 +08:00
b8c096eee5 语言调整 2025-02-10 11:26:13 +08:00
c84f62e418 升级vite6,要求必须node20+ 2025-02-08 17:28:49 +08:00
c2107ee74a 【issues/7781】修复系统设置icon点击显示错误 2025-02-08 11:34:44 +08:00
48a9ba6253 兼容deepseek-r1模型,ai助手支持think标签 2025-02-08 10:12:02 +08:00
1a4abfc89c 关注公众号了解最新资讯 2025-02-08 10:00:08 +08:00
9550c15d56 关注公众号新版抢先看 2025-02-08 09:48:00 +08:00
229256738a v3.7.3 DeepSeek版本发布 2025-02-07 18:31:15 +08:00
781432c678 AIGC功能清单 2025-02-07 18:24:56 +08:00
a4fba72da5 3.7.3 DeepSeek版本发布 2025-02-07 17:46:33 +08:00
65f90ea84a 3.7.3版本发布 2025-02-07 17:27:43 +08:00
b8ef121fe7 升级版本号3.7.3 2025-02-07 16:52:19 +08:00
d6c6a1c01f 租户套餐管理优化体验 2025-02-07 16:38:02 +08:00
7257dfe5ba AutoPoi Excel表格导入有问题,还会报个错。 #7703--- 2025-02-07 16:34:51 +08:00
18166a3c69 官网演示版本中“我的部门”功能数据展示异常 #7658--- 2025-02-06 22:47:55 +08:00
54abb67303 数据权限,查看自己拥有部门的权限中存在问题 #7288--- 2025-02-06 22:34:24 +08:00
84f46c2142 加上AI助手两个字 2025-02-06 22:24:06 +08:00
63d60092dc 【issues/7709】当dataSource是响应式时,单元格编辑输入会自动关闭 --- 2025-02-06 22:21:09 +08:00
dd9ec47cdb 【issues/7549】Online 表单开发 页面属性 查询选择模糊查询 结果生成的代码是 JRangeNumber 而且页面中不显示:父子表--] 2025-02-06 19:21:26 +08:00
49ce9e0763 AI功能效果图 2025-02-05 19:19:38 +08:00
a7089b7b16 AI新功能安排研发中(AI应用开发平台) 2025-02-05 18:50:20 +08:00
53f8c0c076 支持DeepSeek-R1本地化 2025-01-28 09:03:42 +08:00
6ad8c3d824 issues格式 2025-01-25 10:00:59 +08:00
6947f47bd3 v3.7.2发布,提供免费大屏 2025-01-25 09:57:06 +08:00
973804189e Update issue templates 2025-01-25 09:51:58 +08:00
1942980154 AI低代码平台 2025-01-20 13:49:08 +08:00
64b852e1c6 AI 低代码 2025-01-20 13:47:34 +08:00
0277a968f2 AI低代码平台 2025-01-20 13:41:51 +08:00
79ca5ebf96 JeecgBoot AI低代码平台 2025-01-20 12:24:02 +08:00
84a7ce9b7a 【issues/7706】顶部栏导航内部路由也可以支持采用新浏览器tab打开 2025-01-16 15:00:24 +08:00
ab2469ff98 AI模型支持DeepSeek 2025-01-14 21:57:37 +08:00
8fc27bb261 AI默认切换成DeepSeek v3模型,提供更优的速度和质量 2025-01-14 21:51:39 +08:00
d9737c891f 【issues/7658】我的部门无部门列表数据时,点击查询或者重置能查出数据 --- 2025-01-13 20:25:19 +08:00
17dc1916aa 【issues/7664】JVxeTable的textarea组件@blur会重复发生 --- 2025-01-13 20:23:56 +08:00
a00e4684b5 【issues/7661】vxetable用户组件maxTagCount通过业务传递 2025-01-13 20:23:14 +08:00
a2a3ff6709 【issues/7631】JVxeTable组件的getValues回调函数参数修正 ---
【issues/7624】JVxeTable 单选删除不生效 ---
2025-01-13 20:22:13 +08:00
266f49e72f 【issues/7588】选择后自动刷新表格 2025-01-13 20:20:59 +08:00
6be0f94ddc 项目说明 2025-01-12 17:55:39 +08:00
7159df8d18 默认放开AI助手,方便用户看到 2025-01-12 17:45:47 +08:00
b4cd341abc JimuReport 1.9.3版本支持权限,将平台权限传递给积木报表 2025-01-12 17:42:08 +08:00
327f034640 JimuReport和JimuBI大屏,升级到1.9.3版本 2025-01-12 17:23:15 +08:00
00b1250901 升级积木报表到1.9.3版本,解决v1.9.2严重权限BUG 2025-01-09 11:12:48 +08:00
964e9b3851 升级积木报表到1.9.3版本,解决v1.9.2严重权限BUG 2025-01-09 10:38:50 +08:00
9c5e71476f 升级积木报表到1.9.2版本,支持文件数据集 2025-01-08 16:02:03 +08:00
80a54746b1 升级vite6后要求node20+,pnpm9+ 2025-01-08 11:39:34 +08:00
9861e1a867 【issues/7601】ant-design-vue@4.2.6后弹窗全屏底部有空隙 2025-01-06 20:14:27 +08:00
5b2ac82e94 Merge pull request #7691 from liaozhiyang/up-vite6
升级到vite6且升级其它包
2025-01-06 19:51:19 +08:00
c5909cae34 升级到vite6且升级其它包 2025-01-06 19:40:57 +08:00
b0880c373b 缺少修改手机号接口 2025-01-03 11:32:56 +08:00
2b0bedd263 完善openapi,移除过期sql 2024-12-27 14:23:01 +08:00
ac30ed67bc 修复flyway自动升级失败 2024-12-25 15:38:39 +08:00
458526075e Merge remote-tracking branch 'origin/springboot3' into springboot3 2024-12-24 15:44:51 +08:00
a1b55f0d40 解决vue-router升级版本报错问题 2024-12-24 15:44:27 +08:00
ee382c0a5b 全流程跑通 2024-12-21 23:50:07 +08:00
f7f6d0ff88 openapi全量功能 2024-12-20 17:53:45 +08:00
4d058e1dce 【issues/7561】主题切换为顶部混合模式时,页面顶部内容显示不出来,被遮盖 2024-12-17 09:43:18 +08:00
5c9c2dbebe 【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全 2024-12-17 09:43:00 +08:00
44f7075316 账户设置->修改手机号:获取验证码接口 404 错误 #7587 2024-12-16 15:42:36 +08:00
c88bfcf35a v3.7.2发布,提供免费大屏 2024-12-12 19:48:26 +08:00
11d13c8305 v3.7.2 数据库脚本 2024-12-12 12:17:47 +08:00
0582436b9c v3.7.2 数据库脚本 2024-12-11 16:22:30 +08:00
00252f392f keys替换scan问题 修复 #6918 #6876 2024-12-10 16:24:31 +08:00
ef16814216 v3.7.2 删除报错代码暂时无用 2024-12-10 15:42:10 +08:00
a626b6a4d0 快速体验入口 2024-12-09 20:02:38 +08:00
fca5d0e54e 新版发布 3.7.2 2024-12-09 17:56:20 +08:00
1c3b9a10f1 新版发布,升级3.7.2版本号 2024-12-09 17:07:38 +08:00
b0c4194602 v3.7.2 版本代码合并 2024-12-09 15:10:46 +08:00
64b29f47e0 其他数据库脚本,转库说明文档 2024-12-06 16:33:22 +08:00
6198a3702f 其他数据库脚本,转库说明文档 2024-12-06 16:32:33 +08:00
453acb9b4e 升级积木报表到最新版1.9.1,支持大屏 2024-12-04 09:58:40 +08:00
565753e370 运行时间好长,效率慢 #7491 2024-12-04 09:52:29 +08:00
e2aaf0f978 【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去 2024-11-27 18:41:24 +08:00
32c8370ef2 【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去 2024-11-27 10:51:44 +08:00
a79004b924 【issues/7488】手机号码登录,在请求头中无法获取租户id 2024-11-27 09:46:34 +08:00
eb1612f8dd 开源协议说明 2024-11-22 10:44:47 +08:00
2f0a3bcd87 Merge pull request #7379 from EightMonth/springboot3
分布式事务demo修复
2024-11-20 10:31:10 +08:00
a35555619c Merge pull request #7370 from EightMonth/master
使seata直接与springboot datasource挂钩
2024-11-20 10:30:39 +08:00
b3e3951064 【issues/7433】vue3 数据字典优化建议 2024-11-14 19:35:59 +08:00
44ec26574e 【issues/7402】CollapseContainer组件增加默认不展开属性 2024-11-12 09:37:49 +08:00
55a25caafd 【issues/7413】合计行有点对不齐 2024-11-12 09:36:53 +08:00
62f7b0d489 【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常 2024-11-12 09:35:00 +08:00
b16fdef8dc 【issues/7422】BasicTable列表canResize属性为true时合计行不能横向滚动 2024-11-12 09:34:18 +08:00
b5b667058b 【issues/7405】部门选择用户同时全部选择两页用户,回显到父页面。第二页用户显示的不是真是姓名 2024-11-12 09:33:25 +08:00
6c0c259742 QQ群满,提交新群号 ⑩716488839 2024-10-29 11:45:00 +08:00
ca56c54aa0 升级seata server1.7.0版本sql 2024-10-24 10:52:23 +08:00
30d3a9f17b 分布式事务demo修复 2024-10-24 09:15:06 +08:00
74297af987 使seata直接与springboot datasource挂钩 2024-10-22 14:09:02 +08:00
fedb6b84b9 Merge remote-tracking branch 'origin/master' 2024-10-21 11:30:20 +08:00
fdc713339e 引入AI能力,支持自动建表等功能; 2024-10-21 11:26:23 +08:00
03739f2837 【springboot3分支 issues/7353】The bean 'dataSource', defined in class path resource #7353 2024-10-19 20:18:35 +08:00
f28a2dbbeb Merge pull request #7364 from 94464562/patch-1
remove dbsource from cache
2024-10-19 17:04:24 +08:00
b81435aaca remove dbsource from cache
remove dbsource from cache
2024-10-19 11:49:27 +08:00
d9e8bd2bc8 Merge pull request #7317 from EightMonth/springboot3
修改docker镜像base为JDK17
2024-10-09 16:08:38 +08:00
81eef5a838 修改docker镜像base为JDK17 2024-10-09 16:05:22 +08:00
f528f72903 升级仪表盘到最新版 2024-10-08 22:33:29 +08:00
918286c144 升级online模块和autopoi 2024-10-08 21:18:18 +08:00
512234a804 【版本合并】 branch 'origin/master' into springboot3 2024-10-08 19:30:14 +08:00
48805484d4 MK编辑器,无法上传多个图片 2024-09-24 22:47:44 +08:00
7fecdf94e5 修改柱体颜色 2024-09-24 22:47:04 +08:00
a3997dfd16 【issues/7200】basicTable选中后没有选中样式 --- 2024-09-24 22:43:44 +08:00
c868d90c2f 【issues/7209】顶部左侧组合菜单关闭之后左侧导航没还原 --- 2024-09-24 22:43:06 +08:00
77aebf5dd2 租户套餐的菜单名称没国际化 2024-09-24 22:42:21 +08:00
e770524f3a 【issues/7203】自动生成一对多表单代码中,省市区回显问题-- 2024-09-24 22:41:34 +08:00
c5fee07cba 【issues/7136】单元格上的tooltip提示,如果表格有滚动条,会不跟着单元格滚动 2024-09-24 22:40:47 +08:00
9fd20fde9e 【issues/7250】自动锁屏无法解锁 2024-09-24 22:39:52 +08:00
2af9451b7f 【issues/7217】BasicTable树形表格设置checkStrictly无效 ---
【issues/7200】basicTable选中后没有选中样式 ---
2024-09-24 22:38:24 +08:00
575baa8d49 JeecgBoot3.7XSS漏洞处理 2024-09-14 14:15:31 +08:00
48bc76cce7 在线演示地址 2024-09-14 11:46:03 +08:00
58c0882329 更新README.md 2024-09-13 09:52:02 +08:00
c400ec8482 前端环境,要求Node 20+ 版本以上 2024-09-13 09:31:37 +08:00
2068bdc112 前端环境要求Node.js 版本建议v20.15.0 2024-09-13 09:29:01 +08:00
ffe806352e 前端环境要求Node.js 版本建议v20.15.0 2024-09-13 09:20:28 +08:00
167a6c458c 前端环境要求Node.js 版本建议v20.15.0 2024-09-13 09:18:36 +08:00
872e6ed024 开源协议中文释意 2024-09-13 09:10:45 +08:00
cc9384abb6 积木仪表盘升级到最新版1.8.1-beta 2024-09-11 22:22:02 +08:00
c346d0d6e6 flyway报错处理 2024-09-11 17:43:52 +08:00
2942d69fa1 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2024-09-11 10:32:02 +08:00
7d7cc3fb08 Merge pull request #7199 from EightMonth/master
修改redis docker 仓库源
2024-09-11 10:29:14 +08:00
0b84192c29 修改 2024-09-11 10:28:05 +08:00
9fde47957d 修改redis docker 仓库源 2024-09-11 10:27:49 +08:00
ae753f60fd 升级autopoi到最新版1.4.11 2024-09-11 09:31:49 +08:00
2d3b1418de 3.7.1版本发布 2024-09-10 19:48:03 +08:00
15f1ca953d 更新README.md 2024-09-10 16:25:38 +08:00
17180bfcd5 升级版本号3.7.1 2024-09-10 16:16:44 +08:00
c5ddea5c62 更新README.md 2024-09-10 15:51:49 +08:00
13cb18b707 3.7.1版本发布 2024-09-10 15:40:34 +08:00
17c68f6d53 3.7.1版本发布 2024-09-10 15:39:32 +08:00
39ca47d2ef tinymce优化 2024-09-09 09:32:27 +08:00
824f3c2b90 【TV360X-2314】 使用RestUitl类时发现RestTemplate超时 #7140 2024-09-04 23:02:32 +08:00
70607dbe2b 【issues/7101】列配置resizable: true时,表尾合计的列宽没有同步改变 2024-09-04 13:59:22 +08:00
7e2b4c68ec Merge remote-tracking branch 'origin/master' 2024-09-02 11:50:02 +08:00
5359fc4112 升级代码生成器依赖 2024-09-02 11:47:10 +08:00
c31a4e8ab4 Merge pull request #7142 from EightMonth/master
修复 #7081
2024-09-02 11:45:36 +08:00
2b773d6e6b 富文本编辑器,无法上传多个图片 #7076 2024-08-29 20:26:01 +08:00
996a56bd59 修复 #7081 2024-08-29 17:59:14 +08:00
4d48f9b500 Docker镜像源失效,把docker镜像源换成国内的 2024-08-26 17:18:06 +08:00
2570e454ed Docker镜像源失效,把docker镜像源换成国内的 2024-08-26 17:10:09 +08:00
4fd8ae1f94 Docker一键启动微服务前后端, mysql镜像找不到 #7119 2024-08-26 14:44:50 +08:00
72829aa2af 【issues/6999】ApiSelect联动更新字段不生效(代码还原) 2024-08-24 16:52:53 +08:00
0cada33e49 数据库配置默认增加达梦和人大金仓的配置,节省用户修改的成本 2024-08-22 19:30:55 +08:00
ca2a56248c Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2024-08-22 15:15:04 +08:00
6846e9fdef Merge pull request #7058 from EightMonth/master
修复#6903,升级xxl-job 至2.4.1版本,规避CVE-2024-24113
2024-08-22 13:30:34 +08:00
33be0079f0 启动成功打印xxl-job-admin访问地址 2024-08-22 10:37:20 +08:00
31a865f5e0 修改xxl-job初始化sql 2024-08-22 09:51:44 +08:00
114f59f712 升级积木报表到1.8.0 2024-08-21 19:20:20 +08:00
7eef470d28 Merge pull request #6912 from xzs603/master
Update ShiroConfig.java
2024-08-21 10:07:33 +08:00
ae9e85d3f6 Merge pull request #7060 from youdianfan/patch-1
【issues/7044】生产环境关闭mock启用
2024-08-11 22:25:58 +08:00
In
e9ac37d118 【issues/7044】生产环境关闭mock启用 2024-08-09 23:03:18 +08:00
1d2b10c2a5 修复#6903,升级xxl-job 至2.4.1版本,规避CVE-2024-24113 2024-08-09 15:27:19 +08:00
34442b7226 JVxeTable表格Column配置formatter属性不生效 #6950] 2024-08-07 12:01:21 +08:00
c75e9bf05b 更新视频教程 2024-08-06 20:21:49 +08:00
d1ac35108d 类型修正 2024-08-05 13:55:01 +08:00
e0fb952146 【issues/6943】mock翻页之后数据id和图片没自动刷新 2024-08-05 13:53:48 +08:00
4aa4c57db4 【issues/6953】JTreeSelect 组件能支持antdv 对应的a-tree-select 组件的插槽
【issues/1283】JtreeSelect组件初始调用了两次接口
2024-08-05 13:52:54 +08:00
517600f9a4 【issues/6920】解决热更新ScrollContainer报错 --- 2024-08-05 13:50:53 +08:00
1c9e76931f 【issues/6957】editableCell组件值长度为0,无法编辑 2024-08-05 13:49:44 +08:00
d0f09480ca socket总断,换一个写法 2024-07-26 12:00:39 +08:00
e99deb1c33 更新仪表盘效果图 2024-07-26 11:00:05 +08:00
099e745b8f 还原jackson日期格式修改,导致online的带时间的日期值都带T 2024-07-24 20:03:22 +08:00
5898656227 mac系统谷歌浏览器企业微信第三方登录成功后没有弹出绑定手机弹窗 2024-07-19 11:42:18 +08:00
7dcf8f9b5a 【issues/6883】单选模式第二次打开已勾选 2024-07-19 11:41:06 +08:00
4753a74456 【issues/6855】组件使用key作props报警告,改为itemKey 2024-07-19 11:40:31 +08:00
0a76623c53 【issues/6865】配置单个的labelWidth不生效 2024-07-19 11:39:23 +08:00
cd6bb2ca04 Update ShiroConfig.java
当使用redis的sentinel模式时,如果设置了redis的密码但未设置sentinel密码,会造成失败。NOAUTH Authentication required.
2024-07-17 16:16:33 +08:00
819555e612 【代码生成器专项优化】
代码生成没有生成前端权限指令v-auth
代码生成支持新组件JPopupDict字典
查询条件范围控件更换美观的效果: 日期范围、数字范围、金额范围等
用户和部门组件,生成代码的时候需要根据Online存储字段和显示字段配置来
原生表单校验不通过,未滚到未通过校验的字段
非原生表单校验不通过,未滚到未通过校验的字段
详情页面触发了校验修复
ERP风格子表操作列没有浮动
页面控件类型为下拉框时,生成的前端vue代码冗余","
代码生成 int类型字段的查询条件,没有渲染成数值输入框
无论是原生erp还是非原生,不选中主表的时候,直接导出子表,发现导出了所有数据
一对多erp,也改成点击行就选中
一对Tab风格样式美化
2024-07-13 18:08:34 +08:00
0148a0b45e #6861 跳转到自定义首页死循环问题 2024-07-12 14:16:09 +08:00
7049e9974e 无用参数去掉 2024-07-11 10:49:08 +08:00
1243fe1cad 【issues/6681】异步查询不生效 2024-07-11 10:39:47 +08:00
b189e6de52 【issues/6851】editableCell组件值为0时不展示 2024-07-11 10:39:17 +08:00
5dd3bdc23f [issues/6368] rangeDate去掉判断允许起始项或结束项为空兼容allowEmpty 2024-07-11 10:38:07 +08:00
7015eef621 【issues/6374】暗黑主题按钮样式丢失 2024-07-11 10:37:18 +08:00
fd92d516ee nacos支持达梦数据库 2024-07-11 10:33:35 +08:00
606f079a93 解决jdk17 内存信息-立即更新 功能报错 #6635- 2024-07-10 16:00:11 +08:00
ab86013e7b 更新 2024-07-09 21:56:37 +08:00
11ac387559 达梦数据库的nacos初始化脚本 2024-07-09 18:02:34 +08:00
ec93d615f4 nacos默认mysql配置 2024-07-09 14:46:22 +08:00
fbebaf456b nacos升级兼容达梦数据库 2024-07-09 14:44:25 +08:00
7ea46609b1 升级jimureport到最新版1.7.8 2024-07-08 12:22:41 +08:00
cacc59b8fd 升级jimureport到最新版1.7.8 2024-07-08 12:18:09 +08:00
e3cd6bfc97 升级jimureport到最新版1.7.7 2024-07-06 22:21:25 +08:00
c744633139 升级jimureport到最新版1.7.7 2024-07-06 22:20:36 +08:00
8000d61ce0 修改项目语言 2024-07-05 15:53:18 +08:00
4ac18b5d81 项目语言修改 2024-07-05 15:49:11 +08:00
0e4d304878 升级仪表盘 2024-07-03 11:56:53 +08:00
17a8964487 更新online模块为3.7.0最新依赖 2024-07-03 11:09:15 +08:00
54676a4512 更新README.md 2024-07-02 09:27:34 +08:00
2d16d1c79c 更新README.md 2024-07-02 09:24:02 +08:00
3c7da54c3c 启动jar时报错:ElasticSearch 服务连接失败 2024-07-01 19:42:15 +08:00
434d1cca61 支持Docker一键启动微服务前后端 2024-06-29 18:34:01 +08:00
7b14b5df4a 简化docker启动微服务后台,删除jeecg-boot/jeecg-server-cloud/docker-compose-base.yml 2024-06-29 18:25:55 +08:00
befa0f0603 Merge pull request #6669 from EightMonth/master
新增微服务前后端一键启动
2024-06-29 16:18:53 +08:00
0ad9942e89 支持Docker一键启动前后端 2024-06-28 18:07:32 +08:00
41cfbd192c Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2024-06-28 18:04:57 +08:00
0d79cccc52 支持Docker一键启动前后端 2024-06-28 18:01:08 +08:00
d51127a9b7 调整启动顺序 2024-06-28 17:36:57 +08:00
4a6110c618 新增j 2024-06-28 17:31:52 +08:00
b2bc848281 Merge pull request #6667 from EightMonth/master
新增jeecgboot一键前后端启动
2024-06-28 17:10:41 +08:00
65a12c1156 新增jeecgboot一键前后端启动 2024-06-28 15:40:43 +08:00
9070b4a1c7 提供分布式日志轻量级方案 Loki、grafana套件 2024-06-27 17:53:18 +08:00
6b56be941c 修复了MQ的问题
Shutdown Signal: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
2024-06-27 15:34:42 +08:00
8064ea6abb nacos镜像下载失败替换为阿里云的 2024-06-26 15:58:04 +08:00
850815b9c6 AI配置提示 2024-06-26 13:38:18 +08:00
f2c35552b8 更新README.md 2024-06-26 13:36:23 +08:00
068434a5ec 更新README.md 2024-06-26 13:18:41 +08:00
68ab90915f 更新README.md 2024-06-26 13:17:13 +08:00
9e987337c3 更新README.md 2024-06-26 13:10:43 +08:00
5d95a3277c 文档调整 2024-06-26 13:04:23 +08:00
5c4154941a 错误信息语句不通顺 #6643 2024-06-25 13:51:21 +08:00
e7dfe5cdc3 更新issue要求 2024-06-24 15:43:17 +08:00
e016390f00 更新README.md 2024-06-24 15:35:30 +08:00
f69dd81b8b 更新README.md 2024-06-24 15:18:43 +08:00
2ec292e406 更新README.md 2024-06-24 15:16:18 +08:00
aeac0549f8 更新README.md 2024-06-24 15:13:48 +08:00
c53e217448 更新README.md 2024-06-24 15:01:53 +08:00
f2dfad1b15 更新README.md 2024-06-24 14:52:17 +08:00
2bed764621 更新README.md 2024-06-24 14:42:15 +08:00
2eea01bd37 更新README.md 2024-06-24 14:34:15 +08:00
c6f482b898 更新README.md 2024-06-24 14:11:34 +08:00
67b1e237bd 文档地址更新 2024-06-23 13:59:59 +08:00
3f74fc0778 JeecgBoot 3.7.0_all 版本发布(前端和后端合并一个仓库) 2024-06-23 11:33:41 +08:00
8ac6989d2c Merge remote-tracking branch 'origin/master' into springboot3 2024-06-23 11:22:06 +08:00
c30218f17a 更新README.md 2024-06-23 11:17:26 +08:00
21711e5f0c 更新README.md 2024-06-23 11:13:15 +08:00
4368b4ce1e 前端和后端源码合并后,更新readme.md 2024-06-23 11:05:09 +08:00
03f922376e 前端和后端源码合并后,更新readme.md 2024-06-23 10:56:48 +08:00
0325e34dcb 前端和后端源码,合并到一个git仓库中,方便用户下载,避免前后端不匹配的问题 2024-06-23 10:39:52 +08:00
402ab0ffc4 补充合并丢失的代码 2024-06-23 10:27:33 +08:00
7778ede90e Merge remote-tracking branch 'origin/master' into springboot3
# Conflicts:
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/UndertowCustomizer.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysFilesController.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFiles.java
2024-06-23 10:23:56 +08:00
bb918b742e 前端代码和后端代码合并到一个仓库中 2024-06-23 10:09:17 +08:00
06144206df 修改nacos命名空间springboot3的id也是springboot3,方便理解 2024-06-22 23:23:05 +08:00
3d3b5850ad online的依赖升级个小版本号 2024-06-22 17:18:59 +08:00
816eeb9225 3.7.0版本合并springboot3分支
本次提交未升级【minidao、仪表盘、online的依赖】
2024-06-22 17:03:43 +08:00
0b42efbbbf Merge remote-tracking branch 'origin/springboot3' into springboot3 2024-06-22 14:58:29 +08:00
56da1a23c2 更新issue格式要求 2024-06-21 17:08:37 +08:00
d3c5a58db9 更新README 2024-06-21 15:19:53 +08:00
d44945f688 提示语修改 2024-06-20 19:34:15 +08:00
f370855683 还原方法模式的脱敏注解 2024-06-20 18:35:34 +08:00
c582efd115 Merge pull request #6339 from EightMonth/master
还原原有数据脱敏功能并新增@sensitive脱敏注解,不依赖原有数据脱敏功能
2024-06-20 18:11:55 +08:00
c687c7a916 修改注解名称 2024-06-20 18:03:06 +08:00
8e44080b00 还原原有数据脱敏功能并新增@Sensitive脱敏注解,不依赖原有数据脱敏功能 2024-06-20 17:57:36 +08:00
56ca53cc93 Merge pull request #6332 from EightMonth/master
优化数据脱敏功能
2024-06-20 16:10:02 +08:00
0075ec6751 更新README 2024-06-19 18:06:56 +08:00
7e31341f1a 更新readme 2024-06-19 18:03:42 +08:00
d4ca2eb934 项目地址修改 2024-06-19 17:15:20 +08:00
84946888ad 更新readme 2024-06-19 15:49:49 +08:00
d276c3d8ad 更新readme 2024-06-19 15:25:48 +08:00
7dccaf2ec8 优化数据脱敏功能 2024-06-19 12:25:34 +08:00
ae1b8d4654 优化数据脱敏功能 2024-06-19 11:15:33 +08:00
49f709a32a 升级积木报表到最新版1.7.6 2024-06-19 11:03:31 +08:00
335c369546 提示语修改 2024-06-19 10:02:33 +08:00
1a446007c7 解决租户角色保存问题 ,多租户模式下,【租户角色】新增角色后,列表中看不到新增记录 2024-06-19 10:02:22 +08:00
76f9575140 3.7.0 大版本发布(更新数据库) 2024-06-18 23:13:43 +08:00
fd7783644f Merge pull request #6329 from EightMonth/master
修复字典导出问题,修复 #6311
2024-06-18 22:43:06 +08:00
f6a3e11aa2 修复字典导出问题,修复 #6311 2024-06-18 17:34:42 +08:00
c2768cea85 解决[数据表jimu_report_data_source,字段connect_times的类型问题 #6316] 2024-06-18 16:27:37 +08:00
2d37b166a2 解决:分配权限必须退出重新登录才生效,造成很多用户困扰 2024-06-18 16:18:35 +08:00
cff5ec5a40 解决:分配权限必须退出重新登录才生效,造成很多用户困扰(目前改法缺陷:只针对当前登录人的权限修改生效) 2024-06-18 16:04:45 +08:00
0947a199b6 补充遗漏的权限配置 2024-06-18 16:03:44 +08:00
2ecfe74b33 补充遗留的权限配置 2024-06-18 12:03:14 +08:00
6147e923de 3.7.0 大版本发布(调整增量sql,如果大家报错手工执行并改下表flyway_schema_history的状态) 2024-06-18 11:58:06 +08:00
3a07d5a983 分配权限需要退出重新登录,给明确提示 2024-06-18 11:34:43 +08:00
2747868ea7 3.7.0 大版本发布(优化代码生成器模板) 2024-06-17 17:50:59 +08:00
dcc27d71b4 1 2024-06-17 16:33:19 +08:00
30c0482b6d 遗漏升级sql 2024-06-17 16:33:06 +08:00
641298b32d 补充积木报表缺少的升级sql 2024-06-17 16:31:02 +08:00
09a536f549 3.7.0 大版本发布 2024-06-17 09:24:00 +08:00
35ab818741 3.7.0 大版本发布 2024-06-15 17:33:32 +08:00
e00358859c 3.7.0 大版本发布(chatgpt依赖放到底层) 2024-06-13 16:20:35 +08:00
aa24978d2b 3.7.0 大版本发布 2024-06-13 15:06:40 +08:00
ee497a8d1e 3.7.0 大版本发布(代码生成器模板大升级) 2024-06-13 14:30:24 +08:00
935575576f 3.7.0 大版本发布 2024-06-13 14:01:37 +08:00
b45e75007b 3.7.0 大版本发布 2024-06-13 11:43:50 +08:00
52ae0c359e 3.7.0 大版本发布(补充online所需接口权限) 2024-06-13 10:51:46 +08:00
06e6594b75 3.7.0 大版本发布(升级online) 2024-06-13 10:16:01 +08:00
73d62b484c 3.7.0 大版本发布(仪表盘模块升级) 2024-06-12 18:49:38 +08:00
0ff93a220d 3.7.0 大版本发布(仪表盘模块升级) 2024-06-12 18:49:24 +08:00
2071b5bcc4 3.7.0 大版本发布 2024-06-12 16:38:38 +08:00
e1378f4ee5 3.7.0 大版本发布 2024-06-12 14:45:37 +08:00
a6b6e7c9d4 3.7.0大版本发布 2024-06-11 22:58:04 +08:00
b8e0d4391d Merge pull request #6200 from EightMonth/springboot3
修复 #6169
2024-04-30 13:52:00 +08:00
72b34d082b 修复 #6169 2024-04-30 11:53:59 +08:00
7112649a21 Merge branch 'springboot3' of https://github.com/jeecgboot/jeecg-boot into springboot3 2024-04-26 11:06:35 +08:00
fbc312c35d Merge pull request #6173 from EightMonth/springboot3
修复#6127 #6130
2024-04-25 20:04:26 +08:00
b8162a4a6d 修复#6127 #6130 2024-04-25 16:01:58 +08:00
28404d2fd3 Merge pull request #6091 from EightMonth/springboot3
升级druid v1.2.22版本兼容处理
2024-04-08 15:26:49 +08:00
c92c9be49a 升级druid v1.2.22版本兼容处理 2024-04-08 14:04:07 +08:00
58e85e0569 Merge pull request #6081 from EightMonth/springboot3
升级druid1.2.22版本兼容处理
2024-04-03 16:35:30 +08:00
6fc34d8a39 升级druid1.2.22版本兼容处理 2024-04-03 16:18:31 +08:00
790df934b5 Merge branch 'springboot3' of https://github.com/jeecgboot/jeecg-boot into springboot3
 Conflicts:
	pom.xml
2024-03-30 23:39:54 +08:00
8aee4011a2 Merge pull request #6036 from EightMonth/springboot3
合并master变更,升级 3.6.3
2024-03-25 15:32:01 +08:00
6e0277c60a 升级druid版本,修复 #5936 2024-03-25 14:37:00 +08:00
e923654161 升级jimu版本至1.7.3,屏蔽flyway 2024-03-25 10:52:37 +08:00
06b41ae479 Merge branch 'master' into springboot3
# Conflicts:
#	db/tables_nacos.sql
#	jeecg-boot-base-core/pom.xml
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysFilesController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFiles.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysPermissionServiceImpl.java
#	jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
#	jeecg-server-cloud/jeecg-cloud-gateway/pom.xml
#	jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	pom.xml
2024-03-25 09:39:13 +08:00
11af85d87a springboot3, 积木报表 聚合分组查询失败 #2398 2024-03-04 21:12:35 +08:00
4caff75cce Merge pull request #5935 from EightMonth/springboot3_config
修正spring boot3默认配置
2024-03-01 16:24:33 +08:00
811861a957 添加nacos sql自动创建nacos库 2024-03-01 16:15:06 +08:00
24623ba4b0 梳理服务配置信息 2024-03-01 16:06:12 +08:00
7c68b46943 添加springboot3的配置变更 2024-03-01 16:04:57 +08:00
7c34161369 删除无用文件 2024-02-29 17:41:13 +08:00
bc52aa918d gateway的配置改坏了,导致命名空间等不好使 2024-02-29 17:30:04 +08:00
9dfdd47b36 springboot3版本的仪表盘依赖有问题,升级一个版本 2024-01-12 11:32:26 +08:00
272a7540eb 仪表盘升级为springboot3版本 2024-01-12 11:00:51 +08:00
ad796f079f flywaydb兼容springboot3报错,先注释掉 2024-01-12 11:00:37 +08:00
e7e7716d05 Merge pull request #5782 from EightMonth/springboot3
同步主干分支版本代码,并升级jedis至3.8.0
2024-01-12 10:39:24 +08:00
c5d620d2b2 升级jedis版本至3.8.0 2024-01-08 13:54:04 +08:00
cdea05ebb0 Merge branch 'master' into springboot3
# Conflicts:
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-module-demo/src/main/java/org/jeecg/modules/demo/test/entity/JeecgDemo.java
#	jeecg-module-system/jeecg-system-biz/pom.xml
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTableWhiteListController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/WechatVerifyController.java
#	jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	pom.xml
2024-01-08 13:52:33 +08:00
ca9a433f3c Merge pull request #5765 from hoperunChen/springboot3-fix-#5723
fix issue for springboot3 #5723: 指定jaxb-runtime版本,添加修改记录
2024-01-04 21:41:11 +08:00
2be6052cd4 Merge pull request #5766 from hoperunChen/springboot3-fix-#5742
fix issue for springboot3 #5742: 修改代码生成时的schema注解参数
2024-01-04 21:40:53 +08:00
68ed67ee49 shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 Merge pull request #5767 from hoperunChen/springboot3-fix-#5741
fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理
2024-01-04 21:40:31 +08:00
d5903ba52a Merge remote-tracking branch 'upstream/springboot3' into springboot3-fix-#5741 2024-01-04 20:37:37 +08:00
3ee635eddf fix issue for springboot3 #5723: 指定jaxb-runtime版本,添加修改记录 2024-01-04 20:32:26 +08:00
21bc68fb53 fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 2024-01-04 20:19:46 +08:00
f532e57862 解决升级到springboot3, 表单excel导出失败,找不到 javax/servlet/ServletOutputStream #5738 2024-01-03 17:26:41 +08:00
da08adbea1 fix issue for springboot3 #5742: 修改代码生成时的schema注解参数 2024-01-02 13:41:54 +08:00
46e3e62b59 fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 2024-01-02 13:31:57 +08:00
3656264f8a 提供积木报表fastjson2版本 2023-12-28 22:34:23 +08:00
3361d48cd4 Merge branch 'springboot3' of https://github.com/zhangdaiscott/jeecg-boot into springboot3 2023-12-28 11:03:26 +08:00
ed86ea3da1 默认不需要nosql支持包 2023-12-28 11:03:10 +08:00
3deb0e5487 Merge pull request #5730 from EightMonth/springboot3
修改自动生成接口文档范围
2023-12-28 10:49:10 +08:00
9e4792941e 修改自动秣接口文档范围 2023-12-28 10:43:58 +08:00
b5fd5fe782 Merge pull request #5716 from EightMonth/springboot3
升级fastjson至2.0.43,替换tomcat为undertow
2023-12-26 17:21:30 +08:00
33c0104a02 增加undertow配置到test\prod 环境 2023-12-26 17:11:54 +08:00
81ed5100af 补充注释 2023-12-26 16:42:24 +08:00
87f9dc0064 去除无意义内容 2023-12-26 15:17:50 +08:00
b311fedc6b 升级fastjson至2.0.43,替换tomcat为undertow 2023-12-26 15:03:35 +08:00
e321a0405f 升级aliyun.oss和minio的依赖 2023-12-26 10:01:57 +08:00
d8bc74794d 仪表盘也支持springboot3 2023-12-21 15:31:12 +08:00
732f05dc74 提供springboot3版本的online依赖支持 2023-12-21 14:57:14 +08:00
6ce92798c6 Merge pull request #5704 from EightMonth/springboot3
升级jeecg 3.6.1版本
2023-12-21 11:46:59 +08:00
f4454e9348 Merge branch 'springboot3' into springboot3 2023-12-21 09:52:14 +08:00
d9134ae0c8 Update WechatVerifyController.java 2023-12-21 09:46:52 +08:00
25180e41c8 更新minidao支持springboot3版本 2023-12-21 09:29:16 +08:00
a99e3f2268 更新积木报表支持springboot3版本 2023-12-21 09:28:00 +08:00
d27c354bf1 修改错误的配置 2023-12-21 09:26:40 +08:00
d818b1dd9d 更新jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
bcdbec0091 更新jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
098bb12b9e 更改jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
4a6c750b19 为注释内容添加注释原因 2023-12-21 09:26:39 +08:00
d396e5304a Update pom.xml 2023-12-21 09:26:38 +08:00
9bed25be8c spring3 2023-12-21 09:26:30 +08:00
7109b42092 Merge pull request #5698 from EightMonth/springboot3
更新积木报表、Minidao支持Springboot3版本
2023-12-20 10:10:51 +08:00
1667b14194 更新minidao支持springboot3版本 2023-12-20 10:00:14 +08:00
e9514873d2 更新积木报表支持springboot3版本 2023-12-19 14:31:17 +08:00
0ee090664e 修改错误的配置 2023-11-13 20:03:53 +08:00
4a9eda4ab0 Merge pull request #5567 from EightMonth/spring3
更新jeecg-boot-starter3依赖
2023-11-13 18:45:02 +08:00
2416c8b251 更新jeecg-boot-starter3依赖 2023-11-13 16:19:22 +08:00
5b056f9dd6 更新jeecg-boot-starter3依赖 2023-11-13 16:12:46 +08:00
a93998dc56 Merge pull request #5566 from EightMonth/spring3
更改jeecg-boot-starter3依赖
2023-11-13 15:43:21 +08:00
268c27a782 更改jeecg-boot-starter3依赖 2023-11-13 15:34:25 +08:00
23ace2712a Merge pull request #5563 from EightMonth/spring3
Spring Boot3 & JDK 17
2023-11-13 09:49:04 +08:00
157feeb925 为注释内容添加注释原因 2023-11-06 14:16:02 +08:00
4e25d4162f Update pom.xml 2023-11-06 14:11:23 +08:00
47a68f31e1 spring3 2023-11-06 12:41:57 +08:00
3453 changed files with 261362 additions and 320954 deletions

5
.gitattributes vendored
View File

@ -1,5 +1,6 @@
*.js linguist-language=Java
*.css linguist-language=Java
*.html linguist-language=Java
*.vue linguist-language=Java
*.ts linguist-language=vue
*.html linguist-language=vue
*.sql linguist-language=Java
*.ftl linguist-language=Java

View File

@ -1,22 +0,0 @@
##### 版本号:
##### 分支: master还是springboot3?
##### 前端版本: vue3版还是 vue2版
##### 问题描述:
##### 截图&代码:
#### 友情提示为了提高issue处理效率
- 未按格式要求发帖、描述过于简抽象的,会被直接删掉;
- 请自己初判问题描述是否清楚,是否方便我们调查处理;
- 针对问题请说明是Online在线功能(需说明用的主题模板),还是生成的代码功能;
- springboot3_sas分支采用 `Spring Authorization Server` 替换 `Shiro`目前是beta版不稳定生产项目不要使用;

28
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,28 @@
---
name: 提交 Bug
about: 请告诉我框架存在的问题,我会协助你解决此问题!
labels: bug
assignees: getActivity
---
##### 版本号:
##### 分支:
##### 问题描述:
##### 错误截图:
#### 友情提示:
- 未按格式要求发帖、描述过于简单的,会被直接删掉;
- 描述问题请图文并茂,方便我们理解并快速定位问题;
- 如果使用的不是master请说明你使用的分支;

View File

@ -0,0 +1,27 @@
---
name: 提交建议
about: 请告诉我框架的不足之处,让我做得更好!
labels: help wanted
assignees: getActivity
---
##### 版本号:
##### 分支:
##### 问题描述:
##### 错误截图:
#### 友情提示:
- 未按格式要求发帖、描述过于简单的,会被直接删掉;
- 描述问题请图文并茂,方便我们理解并快速定位问题;
- 如果使用的不是master请说明你使用的分支;

2
.gitignore vendored
View File

@ -13,3 +13,5 @@ os_del.cmd
os_del_doc.cmd
.svn
derby.log
.cursor
.history

13
LICENSE
View File

@ -201,16 +201,3 @@
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.允许基于本平台软件开展业务系统开发。
2.JeecgBoot底层依赖的非开源功能online lib依赖、仪表盘lib依赖等统一采用LGPL开源协议不二次改造、不拆分出jeecgboot之外使用就不产生侵权
3.不得基于该平台软件的基础修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售或与JeecgBoot参与同类软件产品市场的竞争。
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
总结在遵循Apache开源协议和开源协议补充条款下允许商用使用不会造成侵权行为
解释权归http://www.jeecg.com

View File

@ -1,558 +0,0 @@
![JEECG](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/logov3.png "JeecgBoot低代码开发平台")
JEECG BOOT Low Code Development Platform
===============
当前最新版本: 3.6.3发布日期2024-03-11
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-guojusoft-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-blog-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
Project introduction
-----------------------------------
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
JeecgBoot is a `low code development platform` based on code `generators`! Front and back end separation architecture SpringBoot2.x, SpringCloud, Ant Design&Vue, Mybatis plus, Shiro, JWT, support for microservices. The powerful code generator makes the front and back end of the code generation, low code development! JeecgBoot leads a new low-code development paradigm (OnlineCoding-> Code Generator -> Manual MERGE) that helps resolve 70% of the duplication in Java projects and makes development more business-focused. Not only can quickly improve efficiency, save research and development costs, but also do not lose flexibility!
JeecgBoot provides a series of low code modules to make Online development truly zero code: Online form development, online reports, report configuration capabilities, online chart design, large screen design, mobile configuration capabilities, form designer, online design flow, process automation configuration, plug-in capabilities (pluggable) and more!
The purpose of JEECG is: simple functions are implemented by OnlineCoding configuration, so that zero code development; Complex functions are generated by code generator and manually Merge to achieve low code development, which ensures both intelligence and flexibility. The implementation of low code development and support flexible coding at the same time, to solve the current low code products are generally not flexible drawbacks!
JEECG Business process: Using workflow to implement and extend the task interface for developing and writing business logic, forms provides a variety of solutions: form designer, online configuration form, and coding form. At the same time, the separation design of process and form (loose coupling) is realized, and the flexible configuration of task nodes is supported, which not only ensures the confidentiality of the company's process, but also reduces the workload of developers.
Technical support
-----------------------------------
Problems or bugs in use can be found in [Making on the Issues](https://github.com/jeecgboot/jeecg-boot/issues/new)
Official Support: http://jeecg.com/doc/help
Download the source code
-----------------------------------
项目源码
-----------------------------------
| Source |Front-end source (Vue3 version) | The background source |
|-|-|-|
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| Gitee | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
##### Project description
| Project | description |
|--------------------|------------------------|
| `jeecg-boot` | SpringBoot background source code (support microservices) |
| `jeecgboot-vue3` | Vue3+TS new front-end source code|
| `jeecg-uniapp` | [APP development framework, a code multi terminal adaptation, and support APP, small program, H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `SpringBoot3+JDK17` | [BranchSourceCode](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) [UpgradeBlog](https://blog.csdn.net/zhangdaiscott/article/details/134805602) |
| `More` | [Download more source code](http://jeecg.com/download) |
For the project
-----------------------------------
Jeecg-Boot low code development platform can be applied in the development of any J2EE project, especially for SAAS projects, enterprise information management system (MIS), internal office system (OA), enterprise resource planning system (ERP), customer relationship management system (CRM), etc. Its semi-intelligent manual Merge development method, Can significantly improve the development efficiency of more than 70%, greatly reduce the development cost.
Docker starts the project
-----------------------------------
- [Docker starts the monomer background](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker starts the Vue3 front-end](http://help.jeecg.com/publish/docker.html)
- [Docker starts the micro-service background](https://help.jeecg.com/java/springcloud/docker.html)
- [ChatGPT AI Config](https://help.jeecg.com/java/chatgpt.html)
Technical documentation
-----------------------------------
- Website [http://www.jeecg.com](http://www.jeecg.com)
- Doc [http://help.jeecg.com](http://help.jeecg.com)
- Newbie guide [Quick start](http://www.jeecg.com/doc/quickstart) | [video](https://space.bilibili.com/454617261/channel/series) | [Q&A ](http://www.jeecg.com/doc/qa) | [help](http://jeecg.com/doc/help) | [1 minute experience](https://my.oschina.net/jeecg/blog/3083313)
- Microservice Development [Monomer upgrade to microservice](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- QQ group ⑨808791225、⑧825232878、⑦791696430、⑥730954414(full)、683903138(full)、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
- Demo [Vue3](http://boot3.jeecg.com) | [Vue2](http://boot.jeecg.com) | [APP](http://jeecg.com/appIndex)
> [please click obtain account password to obtain](http://jeecg.com/doc/demo)
Thinking
-----------------------------------
> We are pursuing the goal of implementing complex business systems without writing code! That has been done so far
- https://www.qiaoqiaoyun.com
Star charts
-----------------------------------
[![Star History Chart](https://api.star-history.com/svg?repos=jeecgboot/jeecg-boot&type=Date)](https://star-history.com/#jeecgboot/jeecg-boot)
Background directory Structure
-----------------------------------
```
project structure
├─jeecg-boot-parent
│ ├─jeecg-boot-base-core
│ ├─jeecg-module-demo
│ ├─jeecg-module-system
│ │ ├─jeecg-system-biz
│ │ ├─jeecg-system-start system (8080
│ │ ├─jeecg-system-api
│ │ │ ├─jeecg-system-cloud-api
│ │ │ ├─jeecg-system-local-api
│ ├─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 -- (9080)
├─jeecg-cloud-sentinel --sentinel (9000)
├─jeecg-cloud-test
├─jeecg-cloud-test-more
├─jeecg-cloud-test-rabbitmq
├─jeecg-cloud-test-seata
├─jeecg-cloud-test-shardingsphere
```
Why JeecgBoot?
-----------------------------------
* Adopt the latest mainstream front and back separation framework (Springboot+Mybatis+antd), easy to use; Code generator has low dependency, flexible expansion ability, and can quickly realize secondary development;
* Support microservices SpringCloud Alibaba(Nacos, Gateway, Sentinel, Skywalking), and provide switching mechanism to support free switching between single and microservices
* High development efficiency, using code generator, single table, tree list, one-to-many, one-to-one and other data models, add, delete, change and search function one-key generation, menu configuration directly use;
* Code generator provides powerful template mechanism, support custom template, currently provide four sets of style template (single table two sets, tree model one set, one to many three sets)
* Code generator is very intelligent, online business modeling, online configuration, WYSIWYG support 23 kinds of controls, a key to generate front and back end code, greatly improve the development efficiency, no longer worry about repeated work.
* Low code ability: Online online form (without coding, through online configuration of the form, to achieve the addition, deletion, change and check of the form, support single table, tree, one-to-many, one-to-one model, to achieve everyone can code)
* Low code ability: Online online report (without coding, through online configuration, to achieve data report, can quickly extract data, reduce development pressure, to achieve everyone can code)
* Low code ability: Online online chart (without coding, through online configuration, to achieve graphs, bar graphs, data reports, etc., support custom layout, to achieve everyone can code)
* Complete encapsulation of user, role, menu, organization, data dictionary, online scheduled tasks and other basic functions, support access authorization, button permission, data permission and other functions
* Commonly used common package, various tools (scheduled task, SMS interface, email sending,Excel import and export, etc.), basically meeting 80% of project requirements
* Easy Excel import and export, support single table export and one-to-many table mode export, generated code with import and export function
* Integrated simple report tools, image report and data export is very convenient, can be extremely convenient to generate graphical reports, pdf, excel, word and other reports;
* Before and after the separation technology, the page UI style is exquisite, for the commonly used components to do the encapsulation: time, row table control, interception display control, report component, editor and so on
* Query filter: query function automatically generated, the background dynamic spell SQL additional query conditions; Supports multiple matching modes (full matching, fuzzy query, included query, and unmatched query).
* Data permission (fine data permission control, control to row level, list level, form field level, realize different people see different data, different people operate different fields on the same page
* Page verification automatically generated (must be input, digital verification, amount verification, time and space, etc.);
* Support SAAS service model and provide SaaS multi-tenant architecture solution.
* Distributed file service, integration of minio, Ali OSS and other excellent third parties, to provide convenient file upload and management, but also support local storage.
* Mainstream database compatibility, a set of code is fully compatible with Mysql, Postgresql, Oracle, Sqlserver, MariaDB, dream and other mainstream databases.
* Integrate workflow activiti and realize only the configuration of flow direction in the page, which can greatly simplify the development of bpm workflow; Using bpm's process designer to draw the flow direction, a workflow is basically complete with a small amount of java code;
* Low code ability: online process design, using open source Activiti process engine, to achieve online drawing process, custom form, form attachment, business flow
* Multi-data source: its simple way of use, online configuration of data source configuration, convenient to grab data from other data;
* Provide single sign-on CAS integration solution, and complete docking code has been provided in the project
* Low code ability: form designer, support user custom form layout, support single table, one to many forms, support select, radio, checkbox, textarea, date, popup, list, macro and other controls
* Professional interface docking mechanism, unified using restful interface, integrated swagger-ui online interface documentation, Jwt token security verification, convenient client docking
* Interface security mechanism, can be refined control interface authorization, very simple to realize different clients only see their own data control
* Advanced combination query function, online configuration support primary and sub-table associated query, can save the query history
* Provide a variety of system monitoring, real-time tracking system running conditions (monitoring Redis, Tomcat, jvm, server information, request tracking, SQL monitoring)
* Message center (support SMS, email, wechat push, etc.)
* Integrate Websocket message notification mechanism
* Excellent mobile adaptive effect, providing APP release scheme:
* Support multiple languages and provide internationalization solutions;
* Data change record log, can record each change of data content, through the version comparison function to view historical changes
* The platform UI is powerful and mobile adaptation is implemented
* Platform home page style, provide a variety of combination mode, support custom style
* Provide easy to use print plug-in, support Google, Firefox, IE11+ and other browsers
* Rich sample code, provide a lot of learning case reference
* Using maven module development method
* Support dynamic menu routing
* RBAC (Role-Based Access Control) is used for permission control.
* Provide new row edit table JVXETable, easily meet a variety of complex ERP layout, with higher performance, more flexible extension, more powerful functions
Technical Architecture:
-----------------------------------
#### Development Environment
- Language: Java 8+ (less than 17)
- IDE(JAVA) : IDEA (lombok plug-in must be installed)
- IDE(front-end) : Vscode, WebStorm, IDEA
- Dependency management: Maven
- Cache: Redis
- Database: MySQL5.7 + & Oracle 11 g & Sqlserver2017 [More Databases](https://my.oschina.net/jeecg/blog/4905722)
#### backend
- Basic framework: Spring Boot 2.6.14
- Microservice framework: Spring Cloud Alibaba 2021.0.1.0
- Persistence layer framework: MybatisPlus 3.5.1
- Report tool: JimuReport 1.5.8
- Security framework: Apache Shiro 1.10.0, Jwt 3.11.0
- Microservice technology stack: Spring Cloud Alibaba, Nacos, Gateway, Sentinel, Skywalking
- Database connection pool: Alibaba Druid 1.1.22
- Log printing: logback
- Others: autopoi, fastjson, poi, Swagger-ui, quartz, lombok (simplified code), etc.
#### The front end
- Vue2 version`Vue2.6+@vue/cli+AntDesignVue+Viser-vue+Vuex` [detail](https://github.com/jeecgboot/ant-design-vue-jeecg)
- Vue3 version`Vue3.0+TypeScript+Vite+AntDesignVue+pinia+echarts` [detail](https://github.com/jeecgboot/jeecgboot-vue3)
#### Support library
| database | support |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦、人大金仓 | √ |
## Microservice solutions
1. Service registration and discovery Nacos √
2. Nacos √
3. Route gateway gateway(Three loading modes) √
4. Distributed http feign √
5. fuse degrade current limiting Sentinel √
6. Distributed files Minio and Alioss √
7. Unified permission control
8. Service monitoring SpringBootAdmin√
9. link tracking Skywalking [reference document](https://help.jeecg.com/java/springcloud/super/skywarking.html)
10. Messaging middleware RabbitMQ √
11. Distributed task xxl-job √
12. Distributed Transaction Seata
13. Distributed log elk + kafka
14. Support docker-compose, k8s, jenkins
15. CAS SSO √
16. Route traffic limiting √
#### Microservice architecture diagram
![微服务架构图](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecgboot_springcloud2022.png "在这里输入图片标题")
### Jeecg Boot product functionality blueprint
![功能蓝图](https://jeecgos.oss-cn-beijing.aliyuncs.com/upload/test/Jeecg-Boot-lantu202005_1590912449914.jpg "在这里输入图片标题")
### Function module
```
├─系统管理
│ ├─用户管理
│ ├─角色管理
│ ├─菜单管理
│ ├─权限设置(支持按钮权限、数据权限)
│ ├─表单权限(控制字段禁用、隐藏)
│ ├─部门管理
│ ├─我的部门(二级管理员)
│ └─字典管理
│ └─分类字典
│ └─系统公告
│ └─职务管理
│ └─通讯录
│ └─多租户管理
├─消息中心
│ ├─消息管理
│ ├─模板管理
├─代码生成器(低代码)
│ ├─代码生成器功能(一键生成前后端代码,生成后无需修改直接用,绝对是后端开发福音)
│ ├─代码生成器模板提供4套模板分别支持单表和一对多模型不同风格选择
│ ├─代码生成器模板生成代码自带excel导入导出
│ ├─查询过滤器(查询逻辑无需编码,系统根据页面配置自动生成)
│ ├─高级查询器(弹窗自动组合查询条件)
│ ├─Excel导入导出工具集成支持单表一对多 导入导出)
│ ├─平台移动自适应支持
├─系统监控
│ ├─Gateway路由网关
│ ├─性能扫描监控
│ │ ├─监控 Redis
│ │ ├─Tomcat
│ │ ├─jvm
│ │ ├─服务器信息
│ │ ├─请求追踪
│ │ ├─磁盘监控
│ ├─定时任务
│ ├─系统日志
│ ├─消息中心(支持短信、邮件、微信推送等等)
│ ├─数据日志(记录数据快照,可对比快照,查看数据变更情况)
│ ├─系统通知
│ ├─SQL监控
│ ├─swagger-ui(在线接口文档)
│─报表示例
│ ├─曲线图
│ └─饼状图
│ └─柱状图
│ └─折线图
│ └─面积图
│ └─雷达图
│ └─仪表图
│ └─进度条
│ └─排名列表
│ └─等等
│─大屏模板
│ ├─作战指挥中心大屏
│ └─物流服务中心大屏
│─常用示例
│ ├─自定义组件
│ ├─对象存储(对接阿里云)
│ ├─JVXETable示例各种复杂ERP布局示例
│ ├─单表模型例子
│ └─一对多模型例子
│ └─打印例子
│ └─一对多TAB例子
│ └─内嵌table例子
│ └─常用选择组件
│ └─异步树table
│ └─接口模拟测试
│ └─表格合计示例
│ └─异步树列表示例
│ └─一对多JEditable
│ └─JEditable组件示例
│ └─图片拖拽排序
│ └─图片翻页
│ └─图片预览
│ └─PDF预览
│ └─分屏功能
│─封装通用组件
│ ├─行编辑表格JEditableTable
│ └─省略显示组件
│ └─时间控件
│ └─高级查询
│ └─用户选择组件
│ └─报表组件封装
│ └─字典组件
│ └─下拉多选组件
│ └─选人组件
│ └─选部门组件
│ └─通过部门选人组件
│ └─封装曲线、柱状图、饼状图、折线图等等报表的组件(经过封装,使用简单)
│ └─在线code编辑器
│ └─上传文件组件
│ └─验证码组件
│ └─树列表组件
│ └─表单禁用组件
│ └─等等
│─更多页面模板
│ ├─各种高级表单
│ ├─各种列表效果
│ └─结果页面
│ └─异常页面
│ └─个人页面
├─高级功能
│ ├─系统编码规则
│ ├─提供单点登录CAS集成方案
│ ├─提供APP发布方案
│ ├─集成Websocket消息通知机制
├─Online在线开发(低代码)
│ ├─Online在线表单 - 功能已开放
│ ├─Online代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表(未开源)
│ ├─Online图表模板配置(未开源)
│ ├─Online布局设计(未开源)
│ ├─多数据源管理 - 功能已开放
├─积木报表设计器(低代码)
│ ├─打印设计器
│ ├─数据报表设计
│ ├─图形报表设计支持echart
│ ├─大屏设计器(未开源)
│─流程模块功能 (未开源)
│ ├─流程设计器
│ ├─表单设计器
├─大屏设计器
├─门户设计/仪表盘设计器
│ └─我的任务
│ └─历史流程
│ └─历史流程
│ └─流程实例管理
│ └─流程监听管理
│ └─流程表达式
│ └─我发起的流程
│ └─我的抄送
│ └─流程委派、抄送、跳转
│ └─。。。
│─OA办公组件 (未开源)
│ ├─更多功能
│ └─。。。
└─其他模块
└─更多功能开发中。。
```
### Effect of system
##### ChatGPT AI Dialog
> Go to the JeecgBoot background home page and click "AI Assistant" in the middle of the right side of the home page. The AI Assistant dialog screen is displayed.
![](https://oscimg.oschina.net/oscnet/up-7c6405641a40f56638999d52da0cb5b4343.png)
##### PC
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14155402_AmlV.png "在这里输入图片标题")
![](https://oscimg.oschina.net/oscnet/up-9d6f36f251e71a0b515a01323474b03004c.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160813_KmXS.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160935_Nibs.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14161004_bxQ4.png "在这里输入图片标题")
##### interactive
![](https://oscimg.oschina.net/oscnet/up-78b151fc888d4319377bf1cc311fe826871.png)
![](https://oscimg.oschina.net/oscnet/up-16c07e000278329b69b228ae3189814b8e9.png)
##### process Designer
![](https://oscimg.oschina.net/oscnet/up-981ce174e4fbb48c8a2ce4ccfd7372e2994.png)
![输入图片说明](https://static.oschina.net/uploads/img/201907/05165142_yyQ7.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160917_9Ftz.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160633_u59G.png "在这里输入图片标题")
##### min process
![](https://oscimg.oschina.net/oscnet/up-1dc0d052149ec675f3e4fad632b82b48add.png)
![](https://oscimg.oschina.net/oscnet/up-de31bc2f9d9b8332c554b0954cc73d79593.png)
![](https://oscimg.oschina.net/oscnet/up-7f83b25159663686d67ed080eb16068c3b4.png)
##### dashboard Designer
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
##### report Designer
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)
![](https://oscimg.oschina.net/oscnet/up-fa52b44445db281c51d3f267dce7450d21b.gif)
![](https://oscimg.oschina.net/oscnet/up-68a19149d640f1646c8ed89ed4375e3326c.png)
![](https://oscimg.oschina.net/oscnet/up-f7e9cb2e3740f2d19ff63b40ec2dd554f96.png)
##### form Designer
![](https://oscimg.oschina.net/oscnet/up-5f8cb657615714b02190b355e59f60c5937.png)
![](https://oscimg.oschina.net/oscnet/up-d9659b2f324e33218476ec98c9b400e6508.png)
![](https://oscimg.oschina.net/oscnet/up-4868615395272d3206dbb960ade02dbc291.png)
##### bigscreen Designer
![](https://oscimg.oschina.net/oscnet/up-402a6034124474bfef8dfc5b4b2bac1ce5c.png)
![](https://oscimg.oschina.net/oscnet/up-6f7ba2e2ebbeea0d203db8d69fd87644c9f.png)
![](https://oscimg.oschina.net/oscnet/up-ee8d34f318da466b8a6070a6e3111d12ce7.png)
![](https://oscimg.oschina.net/oscnet/up-6b81781b43086819049c4421206810667c5.png)
##### uniapp
![](https://oscimg.oschina.net/oscnet/up-aac943fbd26561879c57a41f7a406edf274.png)
![](https://oscimg.oschina.net/oscnet/up-9a44ba2e82b09c750629d12fafd7f60f553.png)
##### low app
![](https://oscimg.oschina.net/oscnet/up-4be29ae761b2615c8c54b3f668cd8432d9b.png)
![](https://oscimg.oschina.net/oscnet/up-787e76bc24b38ecc7ed19f338808d128255.png)
![](https://oscimg.oschina.net/oscnet/up-99d24a236c483362868523ad0d90f611487.png)
![](https://oscimg.oschina.net/oscnet/up-339a0f29d10449abc7724e3bcda802761c1.png)
![](https://oscimg.oschina.net/oscnet/up-b356670cdc14c609958c7619a537397c4b9.png)
##### app
![](https://oscimg.oschina.net/oscnet/da543c5d0d57baab0cecaa4670c8b68c521.jpg)
![](https://oscimg.oschina.net/oscnet/fda4bd82cab9d682de1c1fbf2060bf14fa6.jpg)
##### PAD
![](https://oscimg.oschina.net/oscnet/e90fef970a8c33790ab03ffd6c4c7cec225.jpg)
![](https://oscimg.oschina.net/oscnet/d78218803a9e856a0aa82b45efc49849a0c.jpg)
![](https://oscimg.oschina.net/oscnet/59c23b230f52384e588ee16309b44fa20de.jpg)
##### chart
![](https://oscimg.oschina.net/oscnet/up-218bc6a1669496b241ebb23506440c0083e.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160834_Lo23.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160842_QK7B.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160849_GBm5.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160858_6RAM.png "在这里输入图片标题")
##### swagger
![输入图片说明](https://static.oschina.net/uploads/img/201908/27095258_M2Xq.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160957_hN3X.png "在这里输入图片标题")
## donation
If so, buy the author a cup of coffee ☺
![](https://static.oschina.net/uploads/img/201903/08155608_0EFX.png)

674
README.md
View File

@ -1,593 +1,219 @@
![JEECG](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/logov3.png "JeecgBoot低代码开发平台")
JEECG BOOT 低代码开发平台
Jeecg AI应用平台
===============
当前最新版本: 3.6.3发布日期2024-03-11
当前最新版本: 1.0.0发布日期2025-12-05
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/jeecgboot/JeecgBoot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](https://jeecg.com)
[![](https://img.shields.io/badge/blog-技术博客-orange.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)](https://github.com/jeecgboot/jeecg-ai)
[![GitHub stars](https://img.shields.io/github/stars/jeecgboot/jeecg-ai.svg?style=social&label=Stars)](https://github.com/jeecgboot/jeecg-ai)
[![GitHub forks](https://img.shields.io/github/forks/jeecgboot/jeecg-ai.svg?style=social&label=Fork)](https://github.com/jeecgboot/jeecg-ai)
项目介绍
-----------------------------------
一个全栈式 AI 开发平台,旨在帮助开发者快速构建和部署个性化的 AI 应用。
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.xSpringCloudAnt Design&VueMybatis-plusShiroJWT支持微服务。强大的代码生成器让前后端代码一键生成实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零代码`Online表单开发、Online报表、报表配置能力、在线图表设计、大屏设计、移动配置能力、表单设计器、在线设计流程、流程自动化配置、插件能力可插拔等等
JeecgBoot平台的AIGC功能模块是一套类似`Dify``AIGC应用开发平台`+`知识库问答`是一款基于LLM大语言模型AI应用平台和 RAG 的知识库问答系统。
其直观的界面结合了 AI 流程编排、RAG 管道、知识库管理、模型管理、对接向量库、实时运行可观察等让您可以快速从原型到生产拥有AI服务能力。
`JEECG宗旨是:` 简单功能由OnlineCoding配置实现做到`零代码开发`复杂功能由代码生成器生成进行手工Merge 实现`低代码开发`,既保证了`智能`又兼顾`灵活`;实现了低代码开发的同时又支持灵活编码,解决了当前低代码产品普遍不灵活的弊端!
`JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计松耦合、并支持任务节点灵活配置既保证了公司流程的保密性又减少了开发人员的工作量。
### AI视频介绍
遇到技术问题,[请在这里反馈BUG](https://github.com/jeecgboot/jeecg-boot/issues/new)
[![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecg_aivideo.png)](https://www.bilibili.com/video/BV1zmd7YFE4w)
适用项目
-----------------------------------
Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中尤其适合SAAS项目、企业信息管理系统MIS、内部办公系统OA、企业资源计划系统ERP、客户关系管理系统CRM其半智能手工Merge的开发方式可以显著提高开发效率70%以上,极大降低开发成本。
##### 功能大模块
- AI应用开发平台
- AI知识库系统
- AI大模型管理
- AI流程编排
- AI对话支持图片
- AI对话助手(智能问答)
- AI建表Online表单
- AI写文章CMS
- AI表单字段建议表单设计器
#### Dify `VS` JEECG AI
> JEECG AI与Dify相比在多个方面展现出显著的优势特别是在文档处理、格式和图片保持方面。以下是一些具体的优点
> - Markdown文档库导入
> JEECG AI允许用户直接导入整个Markdown文档库这不仅保留markdown格式还支持图片的导入确保文档内容的完整性和可视化效果。
> - 对话回复格式美观:
> 在对话过程中JEECG AI能够保持回复内容的原格式也不丢失图片使得输出的文章更加美观不会出现格式错乱的情况还支持图片的渲染。
> - PDF文档导入与格式转换
> JEECG AI在处理PDF文档时能够更好地保持原始格式和图片确保转换后的内容与原始文档一致。这个功能在许多AI产品中表现不佳而JEECG AI在这方面做出了显著的优化
| 功能 | Dify | Jeecg AI |
|------------|------------------|-----------------------------------------|
| AI工作流 | 有 | 有 |
| RAG 管道向量搜索 | 有 | 有 |
| AI模型管理 | 有 | 有 |
| AI应用管理 | 有 | 有 |
| AI知识库 | 有 | 有 |
| 产品方向 | 一款独立的 LLM 应用开发平台 | 低代码与AIGC应用二者结合的平台 |
| 业务集成 | 业务集成能力弱 | 更方便与业务系统集成,调用系统接口和逻辑更加方便 |
| AI业务流 | 侧重AI逻辑流程 | AI流程编排作为低代码的业务引擎用户可以通过AI流程配置各种业务流和AI流程 |
| 实现语言 | python + react | JAVA + vue3 |
| 上传markdown文档库(支持图片) | 不支持 | 支持 |
| AI对话支持发图和展示图片 | 支持 | 支持 |
### 技术文档
- [AIGC开发文档](https://help.jeecg.com/aigc)
- [安装向量库 pgvector](https://help.jeecg.com/aigc/config)
## 功能特点
- AI流程: 提供强大的AI流程设计器引擎支持编排 AI 工作过程,满足复杂业务场景,支持画布上构建和实时运行查看 AI流程运行情况。
- AI流程即服务: 通过AI流程编排你需要的智能体结合AI+自定义开发节点 实现功能性 API让你瞬间拥有各种智能体API。
- AI助手对话功能: 集成 ChatGPT、Deepseek、智普、私有大模型 等 AI 模型,提供智能对话和生成式 AI 功能,深度与知识库结合提供更精准的知识。
- RAG 功能: 涵盖从文档摄入到检索的所有内容,支持从 PDF、PPT 和其他常见文档格式中提取文本支持检索增强生成RAG将未训练数据与 AI 模型集成,提升智能交互能力。
- AI 知识库: 通过导入文档或已有问答对进行训练,让 AI 模型能根据文档以交互式对话方式回答问题。
- 模型管理支持对接各种大模型包括本地私有大模型Deepseek/ Llama 3 / Qwen 2 等)、国内公共大模型(通义千问 / 腾讯混元 / 字节豆包 / 百度千帆 / 智谱 AI / Kimi 等和国外公共大模型OpenAI / Claude / Gemini 等);
- 无缝嵌入Iframe一键嵌入,支持将AI聊天助手快速嵌入到第三方系统让系统快速拥有智能问答能力提高用户满意度。
项目源码
-----------------------------------
| 仓库 |前端源码 Vue3版 | 后端JAVA源码 |
|-|-|-|
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
#### 在线体验
> 官方已推出 `SpringBoot3+JDK17版本` [分支源码下载](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) | [升级SpringBoot3博客](https://blog.csdn.net/zhangdaiscott/article/details/134805602)
- JeecgBoot演示 https://boot3.jeecg.com
- 敲敲云在线搭建AI知识库https://app.qiaoqiaoyun.com
#### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecgboot-vue3` | 前端源码 (Vue3版本) |
| `jeecg-boot` | 后端JAVA源码支持微服务 |
| `jeecg-uniapp` | [APP开发框架一份代码多终端适配同时支持APP、小程序、H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `更多开源项目` | [更多底层源码下载](http://jeecg.com/download) |
## 技术交流
- 开发文档https://help.jeecg.com/aigc
- QQ群964611995、716488839(满)
## 功能列表
- AI应用管理(普通应用、高级流程应用)
- AI模型管理
- AI知识库
- AI应用平台(普通、对接AI流程)
- AI流程编排
- AI聊天支持嵌入第三方
- AI向量库对接
快速搭建开发环境
-----------------------------------
## 支持AI模型
- [通过IDEA导入项目](https://help.jeecg.com/java/setup/idea.html)
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- [ChatGPT AI助手配置文档](https://help.jeecg.com/java/chatgpt.html)
Docker快速启动项目
-----------------------------------
- [Docker启动单体后台](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker启动Vue3前端](http://help.jeecg.com/publish/docker.html)
- [Docker启动微服务后台](https://help.jeecg.com/java/springcloud/docker.html)
技术文档
-----------------------------------
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
- 开发文档: [https://help.jeecg.com](https://help.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) | [敲敲云零代码](https://qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
>
- QQ交流群 ⑨808791225、⑧825232878、⑦791696430(满)、⑥730954414(满)、683903138(满)、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
> ` 提醒【QQ群是自助服务群建议给帮助您解决问题的同学发送指定红包表示感谢】 `
大龄码农的思考
-----------------------------------
> 作为码农年纪大了写不动代码了怎么办??哎!!
所以我们团队在追求不写代码也可实现复杂业务系统!目前已经做到了,不信你到敲敲云零代码试试(通过流程串联修改业务数据)
- https://www.qiaoqiaoyun.com
技术支持
-----------------------------------
关闭gitee的issue通道使用中遇到问题或者BUG可以在 [Github上提Issues](https://github.com/jeecgboot/jeecg-boot/issues/new)
官方支持: [http://jeecg.com/doc/help](http://jeecg.com/doc/help)
| AI大模型 | 支持 |
|---------------| --- |
| DeepSeek | √ |
| ChatGTP | √ |
| Qwq | √ |
| 智库 | √ |
| Ollama本地搭建大模型 | √ |
| 等等。。 | √ |
VUE2版本专题介绍
-----------------------------------
#### 项目介绍
- 项目名称ant-design-vue-jeecg
- 说明JeecgBoot前端提供两套解决方案一套VUE2和一套VUE3版本目前vue2版本最新代码只支持到jeecgboot 3.4.3版本,一定注意。
#### 源码下载
| 源码 | 源码地址 |
|--------------------|------------------------|
| 后端JAVA源码 `Vue2版` |https://gitee.com/jeecg/jeecg-boot/tree/v3.4.3last |
| 前端vue2源码 `Vue2版` |https://gitee.com/jeecg/ant-design-vue-jeecg |
#### Vue2与Vue3版本区别
> - VUE3版本彻底抛弃IE兼容不兼容IE和低版本浏览器只适配高版本谷歌和Edge
政府、事业类单位项目需要谨慎选择——国产化迁移是一个漫长的过程万一过程中要求IE兼容这个不可逆
> - 所以如果对浏览器有要求的项目请选择VUE2版本。
> - VUE3版是全新的技术栈紧跟主流前端重写各个功能都做了优化拥有更好的体验效果
#### 技术文档
- 在线演示:[Vue2版演示](http://boot.jeecg.com)
- 开发文档:| [开发文档](http://doc.jeecg.com) | [Vue2前端快速启动](http://doc.jeecg.com/2678320) | [Vue2前端采用Docker启动](http://doc.jeecg.com/3043612)
Star走势图
-----------------------------------
[![Star History Chart](https://api.star-history.com/svg?repos=jeecgboot/jeecg-boot&type=Date)](https://star-history.com/#jeecgboot/jeecg-boot)
后台目录结构
-----------------------------------
```
项目结构
├─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 -- 微服务测试示例(分库分表)
```
为什么选择JeecgBoot?
-----------------------------------
* 1.采用最新主流前后分离框架Springboot+Mybatis+antd容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
* 2.支持微服务SpringCloud Alibaba(Nacos、Gateway、Sentinel、Skywalking),提供切换机制支持单体和微服务自由切换
* 3.开发效率高,采用代码生成器,单表、树列表、一对多、一对一等数据模型,增删改查功能一键生成,菜单配置直接使用;
* 4.代码生成器提供强大模板机制,支持自定义模板,目前提供四套风格模板(单表两套、树模型一套、一对多三套)
* 5.代码生成器非常智能在线业务建模、在线配置、所见即所得支持23种类控件一键生成前后端代码大幅度提升开发效率不再为重复工作发愁。
* 6.低代码能力Online在线表单无需编码通过在线配置表单实现表单的增删改查支持单表、树、一对多、一对一等模型实现人人皆可编码
* 7.低代码能力Online在线报表无需编码通过在线配置方式实现数据报表可以快速抽取数据减轻开发压力实现人人皆可编码
* 8.低代码能力Online在线图表无需编码通过在线配置方式实现曲线图柱状图数据报表等支持自定义排版布局实现人人皆可编码
* 9.封装完善的用户、角色、菜单、组织机构、数据字典、在线定时任务等基础功能,支持访问授权、按钮权限、数据权限等功能
* 10.常用共通封装,各种工具类(定时任务,短信接口,邮件发送,Excel导入导出等),基本满足80%项目需求
* 11.简易Excel导入导出支持单表导出和一对多表模式导出生成的代码自带导入导出功能
* 12.集成简易报表工具图像报表和数据导出非常方便可极其方便的生成图形报表、pdf、excel、word等报表
* 13.采用前后分离技术页面UI风格精美针对常用组件做了封装时间、行表格控件、截取显示控件、报表组件编辑器等等
* 14.查询过滤器查询功能自动生成后台动态拼SQL追加查询条件支持多种匹配方式全匹配/模糊查询/包含查询/不匹配查询);
* 15.数据权限(精细化数据权限控制,控制到行级,列表级,表单字段级,实现不同人看不同数据,不同人对同一个页面操作不同字段
* 16.页面校验自动生成(必须输入、数字校验、金额校验、时间空间等);
* 17.支持SAAS服务模式提供SaaS多租户架构方案。
* 18.分布式文件服务集成minio、阿里OSS等优秀的第三方提供便捷的文件上传与管理同时也支持本地存储。
* 19.主流数据库兼容一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦等主流数据库。
* 20.集成工作流flowable、activiti并实现了只需在页面配置流程转向可极大的简化bpm工作流的开发用bpm的流程设计器画出了流程走向一个工作流基本就完成了只需写很少量的java代码
* 21.低代码能力在线流程设计采用开源flowable、activiti流程引擎实现在线画流程,自定义表单,表单挂靠,业务流转
* 22.多数据源:及其简易的使用方式,在线配置数据源配置,便捷的从其他数据抓取数据;
* 23.提供单点登录CAS集成方案项目中已经提供完善的对接代码
* 24.低代码能力表单设计器支持用户自定义表单布局支持单表一对多表单、支持select、radio、checkbox、textarea、date、popup、列表、宏等控件
* 25.专业接口对接机制统一采用restful接口方式集成swagger-ui在线接口文档Jwt token安全验证方便客户端对接
* 26.接口安全机制,可细化控制接口授权,非常简便实现不同客户端只看自己数据等控制
* 27.高级组合查询功能,在线配置支持主子表关联查询,可保存查询历史
* 28.提供各种系统监控,实时跟踪系统运行情况(监控 Redis、Tomcat、jvm、服务器信息、请求追踪、SQL监控
* 29.消息中心(支持短信、邮件、微信推送等等)
* 30.集成Websocket消息通知机制
* 31.移动自适应效果优秀提供APP发布方案
* 32.支持多语言,提供国际化方案;
* 33.数据变更记录日志,可记录数据每次变更内容,通过版本对比功能查看历史变化
* 34.平台UI强大实现了移动自适应
* 35.平台首页风格,提供多种组合模式,支持自定义风格
* 36.提供简单易用的打印插件支持谷歌、火狐、IE11+ 等各种浏览器
* 37.示例代码丰富,提供很多学习案例参考
* 38.采用maven分模块开发方式
* 39.支持菜单动态路由
* 40.权限控制采用 RBACRole-Based Access Control基于角色的访问控制
* 41.提供新行编辑表格JVXETable轻松满足各种复杂ERP布局拥有更高的性能、更灵活的扩展、更强大的功能
## AIGC能做什么
AIGC模块是一个基于AI的自动化流程编排工具和聊天应用搭建平台它可以帮助用户快速生成AI流程接口和聊天应用提高效率。
以下是一些具体的应用场景和示例:
- 你可能需要一个翻译接口可以通过AI流程编排搭建出来。
- 你可能需要一个接口转换工具可以通过AI流程编排搭建出来。比如jimureport所需要接口返回格式与你的系统不同你通过AI接口实现自动转换
- 你可能需要一个聊天机器人可以通过AI流程编排搭建出来。
- 你可能需要一个自动化流程可以通过AI流程编排搭建出来。
- 你可能需要一个自动化处理文件的流程可以通过AI流程结合python脚本实现操作电脑文件等。
技术架构:
-----------------------------------
#### 开发环境
- 语言Java 8+ (小于17)
- IDE(JAVA) IDEA (必须安装lombok插件 )
- IDE(前端) Vscode、WebStorm、IDEA
- 依赖管理Maven
- 缓存Redis
- 数据库脚本MySQL5.7+ & Oracle 11g & Sqlserver2017其他数据库[需要自己转](https://my.oschina.net/jeecg/blog/4905722)
#### 后端
- 基础框架Spring Boot 2.6.14
- 微服务框架: Spring Cloud Alibaba 2021.0.1.0
- 持久层框架MybatisPlus 3.5.1
- 报表工具: JimuReport 1.5.8
- 安全框架Apache Shiro 1.10.0Jwt 3.11.0
- 微服务技术栈Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
- 数据库连接池阿里巴巴Druid 1.1.22
- 日志打印logback
- 其他autopoi, fastjsonpoiSwagger-uiquartz, lombok简化代码等。
#### 前端
- Vue2版本`Vue2.6+@vue/cli+AntDesignVue+Viser-vue+Vuex等` [详细查看](https://github.com/jeecgboot/ant-design-vue-jeecg)
- Vue3版本`Vue3.0+TypeScript+Vite+AntDesignVue+pinia+echarts等新方案` [详细查看](https://github.com/jeecgboot/jeecgboot-vue3)
- 前端环境要求Node.js要求`Node 20+` 版本以上、pnpm 要求`9+` 版本以上
#### 支持库
` ( Vite 不再支持已结束生命周期EOL的 Node.js 18。现在需要使用 Node.js 20.19+ 或 22.12+)`
| 数据库 | 支持 |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦、人大金仓 | √ |
- 依赖管理node、npm、pnpm
- 前端IDE建议IDEA、WebStorm、Vscode
- 采用 Vue3.0+TypeScript+Vite6+Ant-Design-Vue4等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
- 最新技术栈Vue3.0 + TypeScript + Vite6 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
#### 后端
- IDE建议 IDEA (必须安装lombok插件 )
- 语言Java 默认jdk17(jdk21、jdk24)
- 依赖管理Maven
- 基础框架Spring Boot 3.5.5
- 微服务框架: Spring Cloud Alibaba 2023.0.3.3
- 持久层框架MybatisPlus 3.5.12
- 报表工具: JimuReport 2.1.3
- 安全框架Apache Shiro 2.0.4Jwt 4.5.0
- 微服务技术栈Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
- 数据库连接池阿里巴巴Druid 1.2.24
- AI大模型支持 `ChatGPT` `DeepSeek` `千问`等各种常规模式
- 日志打印logback
- 缓存Redis
- 其他autopoi, fastjsonpoiSwagger-uiquartz, lombok简化代码等。
- 默认提供MySQL5.7+数据库脚本
## 微服务解决方案
## AI应用平台功能展示
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.html)
10、消息中间件 RabbitMQ √
11、分布式任务 xxl-job √
12、分布式事务 Seata
13、分布式日志 elk + kafka
14、支持 docker-compose、k8s、jenkins
15、CAS 单点登录 √
16、路由限流 √
#### 微服务架构图
![微服务架构图](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecgboot_springcloud2022.png "在这里输入图片标题")
### Jeecg Boot 产品功能蓝图
![功能蓝图](https://jeecgos.oss-cn-beijing.aliyuncs.com/upload/test/Jeecg-Boot-lantu202005_1590912449914.jpg "在这里输入图片标题")
### 功能模块
```
├─系统管理
│ ├─用户管理
│ ├─角色管理
│ ├─菜单管理
│ ├─权限设置(支持按钮权限、数据权限)
│ ├─表单权限(控制字段禁用、隐藏)
│ ├─部门管理
│ ├─我的部门(二级管理员)
│ └─字典管理
│ └─分类字典
│ └─系统公告
│ └─职务管理
│ └─通讯录
│ └─多租户管理
├─消息中心
│ ├─消息管理
│ ├─模板管理
├─代码生成器(低代码)
│ ├─代码生成器功能(一键生成前后端代码,生成后无需修改直接用,绝对是后端开发福音)
│ ├─代码生成器模板提供4套模板分别支持单表和一对多模型不同风格选择
│ ├─代码生成器模板生成代码自带excel导入导出
│ ├─查询过滤器(查询逻辑无需编码,系统根据页面配置自动生成)
│ ├─高级查询器(弹窗自动组合查询条件)
│ ├─Excel导入导出工具集成支持单表一对多 导入导出)
│ ├─平台移动自适应支持
├─系统监控
│ ├─Gateway路由网关
│ ├─性能扫描监控
│ │ ├─监控 Redis
│ │ ├─Tomcat
│ │ ├─jvm
│ │ ├─服务器信息
│ │ ├─请求追踪
│ │ ├─磁盘监控
│ ├─定时任务
│ ├─系统日志
│ ├─消息中心(支持短信、邮件、微信推送等等)
│ ├─数据日志(记录数据快照,可对比快照,查看数据变更情况)
│ ├─系统通知
│ ├─SQL监控
│ ├─swagger-ui(在线接口文档)
│─报表示例
│ ├─曲线图
│ └─饼状图
│ └─柱状图
│ └─折线图
│ └─面积图
│ └─雷达图
│ └─仪表图
│ └─进度条
│ └─排名列表
│ └─等等
│─大屏模板
│ ├─作战指挥中心大屏
│ └─物流服务中心大屏
│─常用示例
│ ├─自定义组件
│ ├─对象存储(对接阿里云)
│ ├─JVXETable示例各种复杂ERP布局示例
│ ├─单表模型例子
│ └─一对多模型例子
│ └─打印例子
│ └─一对多TAB例子
│ └─内嵌table例子
│ └─常用选择组件
│ └─异步树table
│ └─接口模拟测试
│ └─表格合计示例
│ └─异步树列表示例
│ └─一对多JEditable
│ └─JEditable组件示例
│ └─图片拖拽排序
│ └─图片翻页
│ └─图片预览
│ └─PDF预览
│ └─分屏功能
│─封装通用组件
│ ├─行编辑表格JEditableTable
│ └─省略显示组件
│ └─时间控件
│ └─高级查询
│ └─用户选择组件
│ └─报表组件封装
│ └─字典组件
│ └─下拉多选组件
│ └─选人组件
│ └─选部门组件
│ └─通过部门选人组件
│ └─封装曲线、柱状图、饼状图、折线图等等报表的组件(经过封装,使用简单)
│ └─在线code编辑器
│ └─上传文件组件
│ └─验证码组件
│ └─树列表组件
│ └─表单禁用组件
│ └─等等
│─更多页面模板
│ ├─各种高级表单
│ ├─各种列表效果
│ └─结果页面
│ └─异常页面
│ └─个人页面
├─高级功能
│ ├─系统编码规则
│ ├─提供单点登录CAS集成方案
│ ├─提供APP发布方案
│ ├─集成Websocket消息通知机制
├─Online在线开发(低代码)
│ ├─Online在线表单 - 功能已开放
│ ├─Online代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表(未开源)
│ ├─Online图表模板配置(未开源)
│ ├─Online布局设计(未开源)
│ ├─多数据源管理 - 功能已开放
├─积木报表设计器(低代码)
│ ├─打印设计器
│ ├─数据报表设计
│ ├─图形报表设计支持echart
│ ├─大屏设计器(未开源)
│─更多商业功能 (未开源)
│ ├─流程设计器
│ ├─表单设计器
├─大屏设计器
├─门户设计/仪表盘设计器
│ └─我的任务
│ └─历史流程
│ └─历史流程
│ └─流程实例管理
│ └─流程监听管理
│ └─流程表达式
│ └─我发起的流程
│ └─我的抄送
│ └─流程委派、抄送、跳转
│ └─。。。
│─OA办公组件 (未开源)
│ ├─更多功能
│ └─。。。
└─其他模块
└─更多功能开发中。。
```
### 流程引擎推荐
JeecgBoot企业版本默认集成了activiti和flowable两套方案大家在使用本开源项目时如果想进一步集成流程引擎推荐结合贺波老师的书 [《深入Activiti流程引擎核心原理与高阶实战》](https://item.m.jd.com/product/13928958.html?gx=RnAomTM2bmCImZxDqYAkVCoIHuIYVqc)
<img src="https://jeecgos.oss-cn-beijing.aliyuncs.com/files/tuijian20231220161656.png" width="25%" height="auto">
AI模型列表
### 系统效果
![](https://oscimg.oschina.net/oscnet//a5fb3e0d69ca1706b0de221535c7acaa.png)
选择AI模型配置你的参数
##### ChatGPT AI交互
> 进入JeecgBoot后台首页点击首页右侧中间“AI助手”弹出AI助手对话界面。
![](https://oscimg.oschina.net/oscnet/up-7c6405641a40f56638999d52da0cb5b4343.png)
![](https://oscimg.oschina.net/oscnet//1f941472758a5fc227f54f2683953b8e.png)
##### PC端
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)
AI知识库支持手工录入文本导入pdf\\word\\excel等文档支持问答对训练
![输入图片说明](https://static.oschina.net/uploads/img/201904/14155402_AmlV.png "在这里输入图片标题")
![](https://oscimg.oschina.net/oscnet//150bb33f48d6c8e2ae059e2a58f4200b.png)
![](https://oscimg.oschina.net/oscnet/up-9d6f36f251e71a0b515a01323474b03004c.png)
![](https://oscimg.oschina.net/oscnet//032d16c915b0f79318935484c81df260.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160813_KmXS.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160935_Nibs.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14161004_bxQ4.png "在这里输入图片标题")
AI流程提供强大的AI流程设计器引擎支持编排 AI 工作过程,满足复杂业务场景,支持画布上构建和实时运行查看 AI流程运行情况。
##### 系统交互
![](https://oscimg.oschina.net/oscnet/up-78b151fc888d4319377bf1cc311fe826871.png)
![](https://oscimg.oschina.net/oscnet//f40f9aa275cd4aea94e1c209513151e2.png)
![](https://oscimg.oschina.net/oscnet/up-16c07e000278329b69b228ae3189814b8e9.png)
目前支持的节点有开始、结束、AI知识库节点、AI节点、分类节点、分支节点、JAVA节点、脚本节点、子流程节点、http请求节点、直接回复节点等节点
##### 流程设计
![](https://oscimg.oschina.net/oscnet/up-981ce174e4fbb48c8a2ce4ccfd7372e2994.png)
![](https://oscimg.oschina.net/oscnet//6d86480ab1bbfab5b2e6992b416b2152.png)
![输入图片说明](https://static.oschina.net/uploads/img/201907/05165142_yyQ7.png "在这里输入图片标题")
节点项配置
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160917_9Ftz.png "在这里输入图片标题")
![](https://oscimg.oschina.net/oscnet//90a5f76b6b4fc406e2e2b87245b35459.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160633_u59G.png "在这里输入图片标题")
在线运行看结果
##### 简版流程设计
![](https://oscimg.oschina.net/oscnet//bc9817a7bbd94936a5a3e885abe3cb38.png)
![](https://oscimg.oschina.net/oscnet/up-1dc0d052149ec675f3e4fad632b82b48add.png)
![](https://oscimg.oschina.net/oscnet/up-de31bc2f9d9b8332c554b0954cc73d79593.png)
AI应用配置支持AI流程配置和简单的AI配置
![](https://oscimg.oschina.net/oscnet/up-7f83b25159663686d67ed080eb16068c3b4.png)
![](https://oscimg.oschina.net/oscnet//a853d9be4d3756806799ad025e722df8.png)![](https://oscimg.oschina.net/oscnet//d3bcbf5977c6fb75a8f996e1e40590be.png)
##### 仪表盘设计器
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
可以关联多个知识库右侧是AI智能回复你可以搭建自己的智能体比如搭建一个 “诗词达人” “翻译助手”
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
![](https://oscimg.oschina.net/oscnet//c26a848136be3e22ec1e0651e78976c2.png)
##### 报表设计器
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)
可以将创建的聊天应用,集成到第三方系统中
![](https://oscimg.oschina.net/oscnet/up-fa52b44445db281c51d3f267dce7450d21b.gif)
![](https://oscimg.oschina.net/oscnet/up-68a19149d640f1646c8ed89ed4375e3326c.png)
![](https://oscimg.oschina.net/oscnet/up-f7e9cb2e3740f2d19ff63b40ec2dd554f96.png)
##### 表单设计器
![](https://oscimg.oschina.net/oscnet/up-5f8cb657615714b02190b355e59f60c5937.png)
![](https://oscimg.oschina.net/oscnet/up-d9659b2f324e33218476ec98c9b400e6508.png)
![](https://oscimg.oschina.net/oscnet/up-4868615395272d3206dbb960ade02dbc291.png)
##### 大屏设计器
![](https://oscimg.oschina.net/oscnet/up-402a6034124474bfef8dfc5b4b2bac1ce5c.png)
![](https://oscimg.oschina.net/oscnet/up-6f7ba2e2ebbeea0d203db8d69fd87644c9f.png)
![](https://oscimg.oschina.net/oscnet/up-ee8d34f318da466b8a6070a6e3111d12ce7.png)
![](https://oscimg.oschina.net/oscnet/up-6b81781b43086819049c4421206810667c5.png)
##### UNIAPP效果
![](https://oscimg.oschina.net/oscnet/up-aac943fbd26561879c57a41f7a406edf274.png)
![](https://oscimg.oschina.net/oscnet/up-9a44ba2e82b09c750629d12fafd7f60f553.png)
##### 零代码应用
![](https://oscimg.oschina.net/oscnet/up-4be29ae761b2615c8c54b3f668cd8432d9b.png)
![](https://oscimg.oschina.net/oscnet/up-787e76bc24b38ecc7ed19f338808d128255.png)
![](https://oscimg.oschina.net/oscnet/up-99d24a236c483362868523ad0d90f611487.png)
![](https://oscimg.oschina.net/oscnet/up-339a0f29d10449abc7724e3bcda802761c1.png)
![](https://oscimg.oschina.net/oscnet/up-b356670cdc14c609958c7619a537397c4b9.png)
##### 手机端
![](https://oscimg.oschina.net/oscnet/da543c5d0d57baab0cecaa4670c8b68c521.jpg)
![](https://oscimg.oschina.net/oscnet/fda4bd82cab9d682de1c1fbf2060bf14fa6.jpg)
##### PAD端
![](https://oscimg.oschina.net/oscnet/e90fef970a8c33790ab03ffd6c4c7cec225.jpg)
![](https://oscimg.oschina.net/oscnet/d78218803a9e856a0aa82b45efc49849a0c.jpg)
![](https://oscimg.oschina.net/oscnet/59c23b230f52384e588ee16309b44fa20de.jpg)
##### 图表示例
![](https://oscimg.oschina.net/oscnet/up-218bc6a1669496b241ebb23506440c0083e.png)
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160834_Lo23.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160842_QK7B.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160849_GBm5.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160858_6RAM.png "在这里输入图片标题")
##### 在线接口文档
![输入图片说明](https://static.oschina.net/uploads/img/201908/27095258_M2Xq.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160957_hN3X.png "在这里输入图片标题")
## 捐赠
如果觉得还不错,请作者喝杯咖啡吧 ☺
![](https://static.oschina.net/uploads/img/201903/08155608_0EFX.png)
![](https://oscimg.oschina.net/oscnet//39c6f589ef46f0454b229915ffa263f4.png)

216
check_jeecgenv.py Normal file
View File

@ -0,0 +1,216 @@
import os
import subprocess
import re
import sys
from typing import Tuple, Optional
def run_command(cmd: str) -> Tuple[int, str]:
"""执行命令并返回退出码和输出"""
try:
result = subprocess.run(cmd, shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
text=True)
return result.returncode, result.stdout.strip()
except Exception as e:
return -1, str(e)
def check_java() -> bool:
"""检查JDK 17+是否安装"""
print("\n检查JDK 17+...")
rc, output = run_command("java -version 2>&1")
if rc != 0:
print("❌ 未检测到Java请安装JDK 17+")
return False
version_pattern = r'"(\d+)(?:\.\d+)*(?:_\d+)?'
match = re.search(version_pattern, output)
if not match:
print("❌ 无法解析Java版本")
return False
version = int(match.group(1))
if version >= 17:
print(f"✅ JDK版本 {version} (满足17+要求)")
return True
else:
print(f"❌ JDK版本 {version} (需要17+)")
return False
def check_maven() -> bool:
"""检查Maven是否安装"""
print("\n检查Maven...")
rc, output = run_command("mvn -v")
if rc == 0:
print("✅ Maven已安装")
return True
else:
print("❌ Maven未安装")
return False
def check_node() -> bool:
"""检查Node.js 20+是否安装"""
print("\n检查Node.js 20+...")
rc, output = run_command("node -v")
if rc != 0:
print("❌ Node.js未安装")
return False
version_pattern = r'v(\d+)\.\d+\.\d+'
match = re.search(version_pattern, output)
if not match:
print("❌ 无法解析Node.js版本")
return False
version = int(match.group(1))
if version >= 20:
print(f"✅ Node.js版本 {version} (满足20+要求)")
return True
else:
print(f"❌ Node.js版本 {version} (需要20+)")
return False
def check_pnpm() -> bool:
"""检查PNPM 9+是否安装"""
print("\n检查PNPM 9+...")
rc, output = run_command("pnpm -v")
if rc != 0:
print("❌ PNPM未安装")
return False
try:
# 处理可能的版本号格式v9.0.0 或 9.0.0 或 9
version_str = output.strip().lstrip('v').split('.')[0]
version = int(version_str)
if version >= 9:
print(f"✅ PNPM版本 {output.strip()} (满足9+要求)")
return True
else:
print(f"❌ PNPM版本 {output.strip()} (需要9+)")
return False
except (ValueError, IndexError):
print(f"❌ 无法解析PNPM版本: {output.strip()}")
return False
def check_redis_connection() -> bool:
"""检查Redis连接"""
print("\n检查Redis连接...")
print("⚠️ 请确保已配置Redis连接信息并在jeecg-boot项目中正确配置")
print("⚠️ 此检查需要根据实际项目配置进行验证")
print("⚠️ 配置文件位置: jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml")
return True
def check_mysql_connection() -> bool:
"""检查MySQL连接"""
print("\n检查MySQL连接...")
print("⚠️ 请确保已配置MySQL连接信息并在jeecg-boot项目中正确配置")
print("⚠️ 此检查需要根据实际项目配置进行验证")
print("⚠️ 配置文件位置: jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml")
return True
def print_mysql_config():
"""打印MySQL配置并提示需要修改的位置"""
print("\nMySQL配置参考 (请检查以下配置是否正确):")
print("""
spring.datasource.dynamic.datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root # ← 可能需要修改
password: root # ← 可能需要修改
driver-class-name: com.mysql.cj.jdbc.Driver
""")
def check_ai_vector_db() -> bool:
"""检查AI向量库(pgvector)配置"""
print("\n检查AI知识库向量库配置...")
print("⚠️ 如果需要使用AI知识库功能请配置pgvector向量库")
print("⚠️ 配置文件位置: jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml")
print("\n配置参考:")
print("""
jeecg.ai-rag:
embed-store:
host: 127.0.0.1 # ← 可能需要修改
port: 5432 # ← 可能需要修改
database: postgres # ← 可能需要修改
user: postgres # ← 可能需要修改
password: postgres # ← 可能需要修改
table: embeddings # ← 可能需要修改
""")
print("⚠️ 注意: 请确保已安装PostgreSQL并添加pgvector扩展docker安装参考https://help.jeecg.com/aigc/config")
return True
def check_ai_config() -> bool:
"""检查AI账号配置"""
print("\n检查AI功能配置...")
print("⚠️ 如果需要使用AI聊天功能请配置AI账号信息")
print("⚠️ 配置文件位置: jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml")
print("\n配置参考:")
print("""
jeecg:
# AI集成
ai-chat:
enabled: true # ← 启用AI功能
model: deepseek-chat # ← 模型名称
apiKey: ?? # ← 必须修改为您的API Key
apiHost: https://api.deepseek.com/v1 # ← API地址
timeout: 60 # ← 超时时间(秒)
""")
print("⚠️ 注意: 请确保已获取有效的API Key并正确配置AI账号注册获取参考 https://help.jeecg.com/java/deepSeekSupport")
return True
def print_redis_config():
"""打印Redis配置并提示需要修改的位置"""
print("\nRedis配置参考 (请检查以下配置是否正确):")
print("""
spring.redis:
database: 0
host: 127.0.0.1 # ← 可能需要修改
port: 6379 # ← 可能需要修改
password: '' # ← 如果需要密码请修改
""")
def main():
print("="*50)
print("JeecgBoot 运行环境检查脚本")
print("="*50)
all_checks_passed = True
# 检查各项依赖
if not check_java():
all_checks_passed = False
if not check_maven():
all_checks_passed = False
if not check_node():
all_checks_passed = False
if not check_pnpm():
all_checks_passed = False
# 数据库提示
print("="*50)
check_redis_connection()
print_redis_config()
print("="*50)
check_mysql_connection()
print_mysql_config()
print("="*50)
check_ai_config()
print("="*50)
check_ai_vector_db()
print("\n" + "="*50)
if all_checks_passed:
print("✅ 所有基础环境检查通过")
print("⚠️ 注意: 请确保Redis和MySQL、AI账号、向量库pgvector 已正确配置并连接成功")
else:
print("❌ 部分环境检查未通过,请根据上述提示解决问题")
print("="*50)
if __name__ == "__main__":
main()
input("\n按回车键退出...") # 等待用户输入

View File

@ -1,13 +0,0 @@
FROM 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,119 +0,0 @@
#
# 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`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_cron` varchar(128) NOT NULL COMMENT '任务执行CRON',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) 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) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) 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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
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) DEFAULT NULL COMMENT '执行器地址本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态0-默认1-无需告警2-告警成功3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime 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 '执行失败-日志数量',
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型0=自动注册1=手动录入',
`address_list` varchar(512) DEFAULT NULL COMMENT '执行器地址列表多地址逗号分隔',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL);
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_cron`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '0 0 0 * * ? *', '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
commit;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
# 版本升级方法
> 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.兼容问题
每次发版,会针对不兼容地方重点说明。

View File

@ -2,7 +2,7 @@ version: '2'
services:
jeecg-boot-mysql:
build:
context: ./db
context: ./jeecg-boot/db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: '%'
@ -18,23 +18,36 @@ services:
--max_allowed_packet=128M
--default-authentication-plugin=caching_sha2_password
ports:
- 3306:3306
- 13306:3306
networks:
- jeecg-boot
jeecg-boot-redis:
image: redis:5.0
ports:
- 6379:6379
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
# ports:
# - 3792:6379
restart: always
hostname: jeecg-boot-redis
container_name: jeecg-boot-redis
networks:
- jeecg-boot
jeecg-boot-pgvector:
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/pgvector
container_name: jeecg-boot-pgvector
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: vector_db
ports:
- 5432:5432
restart: always
networks:
- jeecg-boot
jeecg-boot-system:
build:
context: ./jeecg-module-system/jeecg-system-start
context: ./jeecg-boot/jeecg-module-system/jeecg-system-start
restart: on-failure
depends_on:
- jeecg-boot-mysql
@ -46,6 +59,17 @@ services:
- 8080:8080
networks:
- jeecg-boot
jeecg-vue:
build:
context: ./jeecgboot-vue3
container_name: jeecgboot-vue3-nginx
image: jeecgboot-vue3
depends_on:
- jeecg-boot-system
networks:
- jeecg-boot
ports:
- 80:80
networks:
jeecg-boot:

View File

@ -1,275 +0,0 @@
<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.6.3</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>
</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>
<!-- 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-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-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>
</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>
</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>
</dependencies>
</project>

View File

@ -1,49 +0,0 @@
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;
}
}

View File

@ -1,580 +0,0 @@
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 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";
/**
* 同步工作流引擎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";
/**
* 文件上传类型本地localMiniominio阿里云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_";
/**
* 考勤补卡业务状态 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 textWPS模板还是公文发文模板)
*/
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://";
/** 部门表唯一keyid */
String DEPART_KEY_ID = "id";
/** 部门表唯一keyorgCode */
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";
/**
* 登录失败用于记录失败次数的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积木报表常量----
}

View File

@ -1,81 +0,0 @@
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"),
/**注册账号短信模板编码*/
REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code"),
/**会议通知*/
MEET_NOTICE_TEMPLATE_CODE("SMS_201480469","JEECG","username,title,minute,time"),
/**我的计划通知*/
PLAN_NOTICE_TEMPLATE_CODE("SMS_201470515","JEECG","username,title,time"),
/**支付成功短信通知*/
PAY_SUCCESS_NOTICE_CODE("SMS_461735163","敲敲云","realname,money,endTime"),
/**会员到期通知提醒*/
VIP_EXPIRE_NOTICE_CODE("SMS_461885023","敲敲云","realname,endTime");
/**
* 短信模板编码
*/
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;
}
}

View File

@ -1,82 +0,0 @@
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;
}
}

View File

@ -1,155 +0,0 @@
package org.jeecg.common.exception;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.enums.SentinelErrorInfoEnum;
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.web.HttpRequestMethodNotSupportedException;
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;
/**
* 异常处理器
*
* @Author scott
* @Date 2019
*/
@RestControllerAdvice
@Slf4j
public class JeecgBootExceptionHandler {
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBootException.class)
public Result<?> handleJeecgBootException(JeecgBootException e){
log.error(e.getMessage(), e);
return Result.error(e.getErrCode(), e.getMessage());
}
/**
* 处理自定义微服务异常
*/
@ExceptionHandler(JeecgCloudException.class)
public Result<?> handleJeecgCloudException(JeecgCloudException e){
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBoot401Exception.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleJeecgBoot401Exception(JeecgBoot401Exception e){
log.error(e.getMessage(), e);
return new Result(401,e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public Result<?> handlerNoFoundException(Exception e) {
log.error(e.getMessage(), e);
return Result.error(404, "路径不存在,请检查路径是否正确");
}
@ExceptionHandler(DuplicateKeyException.class)
public Result<?> handleDuplicateKeyException(DuplicateKeyException e){
log.error(e.getMessage(), 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限流自定义异常
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("没有权限,请联系管理员授权");
return Result.error(405,sb.toString());
}
/**
* spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
log.error(e.getMessage(), e);
return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
}
@ExceptionHandler(DataIntegrityViolationException.class)
public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
log.error(e.getMessage(), e);
//【issues/3624】数据库执行异常handleDataIntegrityViolationException提示有误 #3624
return Result.error("执行数据库异常,违反了完整性例如:违反惟一约束、违反非空限制、字段内容超出长度等");
}
@ExceptionHandler(PoolException.class)
public Result<?> handlePoolException(PoolException e) {
log.error(e.getMessage(), 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注入风险");
}
return Result.error("校验失败存在SQL注入风险" + msg);
}
}

View File

@ -1,19 +0,0 @@
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 "";
}

View File

@ -1,203 +0,0 @@
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("文件导入失败!");
}
}

View File

@ -1,271 +0,0 @@
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 com.google.common.base.Joiner;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
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) {
e.printStackTrace();
}
}
/**
* 校验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 exception) {
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) {
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;
}
//替换为当前系统时间(年月日)
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();
}
}
//替换为系统登录用户真实名字
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();
}
}
//替换为系统用户所拥有的所有机构编码
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();
}else{
if(user.isOneDepart()) {
returnValue = user.getSysMultiOrgCode().get(0);
}else {
returnValue = Joiner.on(",").join(user.getSysMultiOrgCode());
}
}
}
//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));
// }
}

View File

@ -1,117 +0,0 @@
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.oConvertUtils;
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;
}
}

View File

@ -1,71 +0,0 @@
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 sysUserCode;
private String sysUserName;
private String sysOrgCode;
private List<String> sysMultiOrgCode;
private boolean oneDepart;
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;
}
}

View File

@ -1,126 +0,0 @@
package org.jeecg.common.util;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.jeecg.common.constant.enums.DySmsEnum;
import org.jeecg.config.StaticConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created on 17/6/7.
* 短信API产品的DEMO程序,工程中包含了一个SmsDemo类直接通过
* 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
* 工程依赖了2个jar包(存放在工程的libs目录下)
* 1:aliyun-java-sdk-core.jar
* 2:aliyun-java-sdk-dysmsapi.jar
*
* 备注:Demo工程编码采用UTF-8
* 国际短信发送请勿参照此DEMO
* @author: jeecg-boot
*/
public class DySmsHelper {
private final static Logger logger=LoggerFactory.getLogger(DySmsHelper.class);
/**产品名称:云通信短信API产品,开发者无需替换*/
static final String PRODUCT = "Dysmsapi";
/**产品域名,开发者无需替换*/
static final String DOMAIN = "dysmsapi.aliyuncs.com";
/**TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)*/
static String accessKeyId;
static String accessKeySecret;
public static void setAccessKeyId(String accessKeyId) {
DySmsHelper.accessKeyId = accessKeyId;
}
public static void setAccessKeySecret(String accessKeySecret) {
DySmsHelper.accessKeySecret = accessKeySecret;
}
public static String getAccessKeyId() {
return accessKeyId;
}
public static String getAccessKeySecret() {
return accessKeySecret;
}
public static boolean sendSms(String phone, JSONObject templateParamJson, DySmsEnum dySmsEnum) throws ClientException {
//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//update-begin-authortaoyan date:20200811 for:配置类数据获取
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
//logger.info("阿里大鱼短信秘钥 accessKeyId" + staticConfig.getAccessKeyId());
//logger.info("阿里大鱼短信秘钥 accessKeySecret"+ staticConfig.getAccessKeySecret());
setAccessKeyId(staticConfig.getAccessKeyId());
setAccessKeySecret(staticConfig.getAccessKeySecret());
//update-end-authortaoyan date:20200811 for:配置类数据获取
//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", PRODUCT, DOMAIN);
IAcsClient acsClient = new DefaultAcsClient(profile);
//验证json参数
validateParam(templateParamJson,dySmsEnum);
//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers(phone);
//必填:短信签名-可在短信控制台中找到
request.setSignName(dySmsEnum.getSignName());
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(dySmsEnum.getTemplateCode());
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam(templateParamJson.toJSONString());
//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997");
//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
//request.setOutId("yourOutId");
boolean result = false;
//hint 此处可能会抛出异常注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
logger.info("短信接口返回的数据----------------");
logger.info("{Code:" + sendSmsResponse.getCode()+",Message:" + sendSmsResponse.getMessage()+",RequestId:"+ sendSmsResponse.getRequestId()+",BizId:"+sendSmsResponse.getBizId()+"}");
String ok = "OK";
if (ok.equals(sendSmsResponse.getCode())) {
result = true;
}
return result;
}
private static void validateParam(JSONObject templateParamJson,DySmsEnum dySmsEnum) {
String keys = dySmsEnum.getKeys();
String [] keyArr = keys.split(",");
for(String item :keyArr) {
if(!templateParamJson.containsKey(item)) {
throw new RuntimeException("模板缺少参数:"+item);
}
}
}
// public static void main(String[] args) throws ClientException, InterruptedException {
// JSONObject obj = new JSONObject();
// obj.put("code", "1234");
// sendSms("13800138000", obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
// }
}

View File

@ -1,57 +0,0 @@
package org.jeecg.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.handler.IFillRuleHandler;
/**
* 规则值自动生成工具类
*
* @author qinfeng
* @举例: 自动生成订单号;自动生成当前日期
*/
@Slf4j
public class FillRuleUtil {
/**
* @param ruleCode ruleCode
* @return
*/
@SuppressWarnings("unchecked")
public static Object executeRule(String ruleCode, JSONObject formData) {
if (!StringUtils.isEmpty(ruleCode)) {
try {
// 获取 Service
ServiceImpl impl = (ServiceImpl) SpringContextUtils.getBean("sysFillRuleServiceImpl");
// 根据 ruleCode 查询出实体
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("rule_code", ruleCode);
JSONObject entity = JSON.parseObject(JSON.toJSONString(impl.getOne(queryWrapper)));
if (entity == null) {
log.warn("填值规则:" + ruleCode + " 不存在");
return null;
}
// 获取必要的参数
String ruleClass = entity.getString("ruleClass");
JSONObject params = entity.getJSONObject("ruleParams");
if (params == null) {
params = new JSONObject();
}
if (formData == null) {
formData = new JSONObject();
}
// 通过反射执行配置的类里的方法
IFillRuleHandler ruleHandler = (IFillRuleHandler) Class.forName(ruleClass).newInstance();
return ruleHandler.execute(params, formData);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}

View File

@ -1,43 +0,0 @@
package org.jeecg.common.util;
import org.apache.commons.lang3.StringUtils;
import org.pegdown.PegDownProcessor;
import org.springframework.web.util.HtmlUtils;
/**
* HTML 工具类
* @author: jeecg-boot
* @date: 2022/3/30 14:43
*/
@SuppressWarnings("AlibabaClassNamingShouldBeCamel")
public class HTMLUtils {
/**
* 获取HTML内的文本不包含标签
*
* @param html HTML 代码
*/
public static String getInnerText(String html) {
if (StringUtils.isNotBlank(html)) {
//去掉 html 的标签
String content = html.replaceAll("</?[^>]+>", "");
// 将多个空格合并成一个空格
content = content.replaceAll("(&nbsp;)+", "&nbsp;");
// 反向转义字符
content = HtmlUtils.htmlUnescape(content);
return content.trim();
}
return "";
}
/**
* 将Markdown解析成Html
* @param markdownContent
* @return
*/
public static String parseMarkdown(String markdownContent) {
PegDownProcessor pdp = new PegDownProcessor();
return pdp.markdownToHtml(markdownContent);
}
}

View File

@ -1,59 +0,0 @@
package org.jeecg.common.util;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* IP地址
*
* @Author scott
* @email jeecgos@163.com
* @Date 2019年01月14日
*/
public class IpUtils {
private static Logger logger = LoggerFactory.getLogger(IpUtils.class);
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP地址X-Forwarded-For中第一个非unknown的有效IP字符串则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 ||CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// //使用代理则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return ip;
}
}

View File

@ -1,263 +0,0 @@
package org.jeecg.common.util;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
/**
* 调用 Restful 接口 Util
*
* @author sunjianlei
*/
@Slf4j
public class RestUtil {
private static String domain = null;
private static String path = null;
private static String getDomain() {
if (domain == null) {
domain = SpringContextUtils.getDomain();
// issues/2959
// 微服务版集成企业微信单点登录
// 因为微服务版没有端口号,导致 SpringContextUtils.getDomain() 方法获取的域名的端口号变成了:-1所以出问题了只需要把这个-1给去掉就可以了。
String port=":-1";
if (domain.endsWith(port)) {
domain = domain.substring(0, domain.length() - 3);
}
}
return domain;
}
private static String getPath() {
if (path == null) {
path = SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
}
return oConvertUtils.getString(path);
}
public static String getBaseUrl() {
String basepath = getDomain() + getPath();
log.info(" RestUtil.getBaseUrl: " + basepath);
return basepath;
}
/**
* RestAPI 调用器
*/
private final static RestTemplate RT;
static {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(3000);
requestFactory.setReadTimeout(3000);
RT = new RestTemplate(requestFactory);
// 解决乱码问题
RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
public static RestTemplate getRestTemplate() {
return RT;
}
/**
* 发送 get 请求
*/
public static JSONObject get(String url) {
return getNative(url, null, null).getBody();
}
/**
* 发送 get 请求
*/
public static JSONObject get(String url, JSONObject variables) {
return getNative(url, variables, null).getBody();
}
/**
* 发送 get 请求
*/
public static JSONObject get(String url, JSONObject variables, JSONObject params) {
return getNative(url, variables, params).getBody();
}
/**
* 发送 get 请求,返回原生 ResponseEntity 对象
*/
public static ResponseEntity<JSONObject> getNative(String url, JSONObject variables, JSONObject params) {
return request(url, HttpMethod.GET, variables, params);
}
/**
* 发送 Post 请求
*/
public static JSONObject post(String url) {
return postNative(url, null, null).getBody();
}
/**
* 发送 Post 请求
*/
public static JSONObject post(String url, JSONObject params) {
return postNative(url, null, params).getBody();
}
/**
* 发送 Post 请求
*/
public static JSONObject post(String url, JSONObject variables, JSONObject params) {
return postNative(url, variables, params).getBody();
}
/**
* 发送 POST 请求,返回原生 ResponseEntity 对象
*/
public static ResponseEntity<JSONObject> postNative(String url, JSONObject variables, JSONObject params) {
return request(url, HttpMethod.POST, variables, params);
}
/**
* 发送 put 请求
*/
public static JSONObject put(String url) {
return putNative(url, null, null).getBody();
}
/**
* 发送 put 请求
*/
public static JSONObject put(String url, JSONObject params) {
return putNative(url, null, params).getBody();
}
/**
* 发送 put 请求
*/
public static JSONObject put(String url, JSONObject variables, JSONObject params) {
return putNative(url, variables, params).getBody();
}
/**
* 发送 put 请求,返回原生 ResponseEntity 对象
*/
public static ResponseEntity<JSONObject> putNative(String url, JSONObject variables, JSONObject params) {
return request(url, HttpMethod.PUT, variables, params);
}
/**
* 发送 delete 请求
*/
public static JSONObject delete(String url) {
return deleteNative(url, null, null).getBody();
}
/**
* 发送 delete 请求
*/
public static JSONObject delete(String url, JSONObject variables, JSONObject params) {
return deleteNative(url, variables, params).getBody();
}
/**
* 发送 delete 请求,返回原生 ResponseEntity 对象
*/
public static ResponseEntity<JSONObject> deleteNative(String url, JSONObject variables, JSONObject params) {
return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class);
}
/**
* 发送请求
*/
public static ResponseEntity<JSONObject> request(String url, HttpMethod method, JSONObject variables, JSONObject params) {
return request(url, method, getHeaderApplicationJson(), variables, params, JSONObject.class);
}
/**
* 发送请求
*
* @param url 请求地址
* @param method 请求方式
* @param headers 请求头 可空
* @param variables 请求url参数 可空
* @param params 请求body参数 可空
* @param responseType 返回类型
* @return ResponseEntity<responseType>
*/
public static <T> ResponseEntity<T> request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, Object params, Class<T> responseType) {
log.info(" RestUtil --- request --- url = "+ url);
if (StringUtils.isEmpty(url)) {
throw new RuntimeException("url 不能为空");
}
if (method == null) {
throw new RuntimeException("method 不能为空");
}
if (headers == null) {
headers = new HttpHeaders();
}
// 请求体
String body = "";
if (params != null) {
if (params instanceof JSONObject) {
body = ((JSONObject) params).toJSONString();
} else {
body = params.toString();
}
}
// 拼接 url 参数
if (variables != null && !variables.isEmpty()) {
url += ("?" + asUrlVariables(variables));
}
// 发送请求
HttpEntity<String> request = new HttpEntity<>(body, headers);
return RT.exchange(url, method, request, responseType);
}
/**
* 获取JSON请求头
*/
public static HttpHeaders getHeaderApplicationJson() {
return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
}
/**
* 获取请求头
*/
public static HttpHeaders getHeader(String mediaType) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(mediaType));
headers.add("Accept", mediaType);
return headers;
}
/**
* 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式
*/
public static String asUrlVariables(JSONObject variables) {
Map<String, Object> source = variables.getInnerMap();
Iterator<String> it = source.keySet().iterator();
StringBuilder urlVariables = new StringBuilder();
while (it.hasNext()) {
String key = it.next();
String value = "";
Object object = source.get(key);
if (object != null) {
if (!StringUtils.isEmpty(object.toString())) {
value = object.toString();
}
}
urlVariables.append("&").append(key).append("=").append(value);
}
// 去掉第一个&
return urlVariables.substring(1);
}
}

View File

@ -1,124 +0,0 @@
package org.jeecg.common.util.encryption;
import org.apache.shiro.codec.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* @Description: AES 加密
* @author: jeecg-boot
* @date: 2022/3/30 11:48
*/
public class AesEncryptUtil {
/**
* 使用AES-128-CBC加密模式 key和iv可以相同
*/
private static String KEY = EncryptedString.key;
private static String IV = EncryptedString.iv;
/**
* 加密方法
* @param data 要加密的数据
* @param key 加密key
* @param iv 加密iv
* @return 加密的结果
* @throws Exception
*/
public static String encrypt(String data, String key, String iv) throws Exception {
try {
//"算法/模式/补码方式"NoPadding PkcsPadding
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = data.getBytes();
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return Base64.encodeToString(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 解密方法
* @param data 要解密的数据
* @param key 解密key
* @param iv 解密iv
* @return 解密的结果
* @throws Exception
*/
public static String desEncrypt(String data, String key, String iv) throws Exception {
//update-begin-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去,在外面处理
byte[] encrypted1 = Base64.decode(data);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original);
//加密解码后的字符串会出现\u0000
return originalString.replaceAll("\\u0000", "");
//update-end-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去,在外面处理
}
/**
* 使用默认的key和iv加密
* @param data
* @return
* @throws Exception
*/
public static String encrypt(String data) throws Exception {
return encrypt(data, KEY, IV);
}
/**
* 使用默认的key和iv解密
* @param data
* @return
* @throws Exception
*/
public static String desEncrypt(String data) throws Exception {
return desEncrypt(data, KEY, IV);
}
// /**
// * 测试
// */
// public static void main(String args[]) throws Exception {
// String test1 = "sa";
// String test =new String(test1.getBytes(),"UTF-8");
// String data = null;
// String key = KEY;
// String iv = IV;
// // /g2wzfqvMOeazgtsUVbq1kmJawROa6mcRAzwG1/GeJ4=
// data = encrypt(test, key, iv);
// System.out.println("数据:"+test);
// System.out.println("加密:"+data);
// String jiemi =desEncrypt(data, key, iv).trim();
// System.out.println("解密:"+jiemi);
// }
}

View File

@ -1,945 +0,0 @@
package org.jeecg.common.util;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.springframework.beans.BeanUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Date;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @Author 张代浩
*
*/
@Slf4j
public class oConvertUtils {
public static boolean isEmpty(Object object) {
if (object == null) {
return (true);
}
if ("".equals(object)) {
return (true);
}
if (CommonConstant.STRING_NULL.equals(object)) {
return (true);
}
return (false);
}
public static boolean isNotEmpty(Object object) {
if (object != null && !"".equals(object) && !object.equals(CommonConstant.STRING_NULL)) {
return (true);
}
return (false);
}
public static String decode(String strIn, String sourceCode, String targetCode) {
String temp = code2code(strIn, sourceCode, targetCode);
return temp;
}
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
public static String StrToUTF(String strIn, String sourceCode, String targetCode) {
strIn = "";
try {
strIn = new String(strIn.getBytes("ISO-8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return strIn;
}
private static String code2code(String strIn, String sourceCode, String targetCode) {
String strOut = null;
if (strIn == null || "".equals(strIn.trim())) {
return strIn;
}
try {
byte[] b = strIn.getBytes(sourceCode);
for (int i = 0; i < b.length; i++) {
System.out.print(b[i] + " ");
}
strOut = new String(b, targetCode);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return strOut;
}
public static int getInt(String s, int defval) {
if (s == null || "".equals(s)) {
return (defval);
}
try {
return (Integer.parseInt(s));
} catch (NumberFormatException e) {
return (defval);
}
}
public static int getInt(String s) {
if (s == null || "".equals(s)) {
return 0;
}
try {
return (Integer.parseInt(s));
} catch (NumberFormatException e) {
return 0;
}
}
public static int getInt(String s, Integer df) {
if (s == null || "".equals(s)) {
return df;
}
try {
return (Integer.parseInt(s));
} catch (NumberFormatException e) {
return 0;
}
}
public static Integer[] getInts(String[] s) {
if (s == null) {
return null;
}
Integer[] integer = new Integer[s.length];
for (int i = 0; i < s.length; i++) {
integer[i] = Integer.parseInt(s[i]);
}
return integer;
}
public static double getDouble(String s, double defval) {
if (s == null || "".equals(s)) {
return (defval);
}
try {
return (Double.parseDouble(s));
} catch (NumberFormatException e) {
return (defval);
}
}
public static double getDou(Double s, double defval) {
if (s == null) {
return (defval);
}
return s;
}
/*public static Short getShort(String s) {
if (StringUtil.isNotEmpty(s)) {
return (Short.parseShort(s));
} else {
return null;
}
}*/
public static int getInt(Object object, int defval) {
if (isEmpty(object)) {
return (defval);
}
try {
return (Integer.parseInt(object.toString()));
} catch (NumberFormatException e) {
return (defval);
}
}
public static Integer getInteger(Object object, Integer defval) {
if (isEmpty(object)) {
return (defval);
}
try {
return (Integer.parseInt(object.toString()));
} catch (NumberFormatException e) {
return (defval);
}
}
public static Integer getInt(Object object) {
if (isEmpty(object)) {
return null;
}
try {
return (Integer.parseInt(object.toString()));
} catch (NumberFormatException e) {
return null;
}
}
public static int getInt(BigDecimal s, int defval) {
if (s == null) {
return (defval);
}
return s.intValue();
}
public static Integer[] getIntegerArry(String[] object) {
int len = object.length;
Integer[] result = new Integer[len];
try {
for (int i = 0; i < len; i++) {
result[i] = new Integer(object[i].trim());
}
return result;
} catch (NumberFormatException e) {
return null;
}
}
public static String getString(String s) {
return (getString(s, ""));
}
/**
* 转义成Unicode编码
* @param s
* @return
*/
/*public static String escapeJava(Object s) {
return StringEscapeUtils.escapeJava(getString(s));
}*/
public static String getString(Object object) {
if (isEmpty(object)) {
return "";
}
return (object.toString().trim());
}
public static String getString(int i) {
return (String.valueOf(i));
}
public static String getString(float i) {
return (String.valueOf(i));
}
public static String getString(String s, String defval) {
if (isEmpty(s)) {
return (defval);
}
return (s.trim());
}
public static String getString(Object s, String defval) {
if (isEmpty(s)) {
return (defval);
}
return (s.toString().trim());
}
public static long stringToLong(String str) {
Long test = new Long(0);
try {
test = Long.valueOf(str);
} catch (Exception e) {
}
return test.longValue();
}
/**
* 获取本机IP
*/
public static String getIp() {
String ip = null;
try {
InetAddress address = InetAddress.getLocalHost();
ip = address.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return ip;
}
/**
* 判断一个类是否为基本数据类型。
*
* @param clazz
* 要判断的类。
* @return true 表示为基本数据类型。
*/
private static boolean isBaseDataType(Class clazz) throws Exception {
return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz.isPrimitive());
}
/**
* @param request
* IP
* @return IP Address
*/
public static String getIpAddrByRequest(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || CommonConstant.UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
/**
* @return 本机IP
* @throws SocketException
*/
public static String getRealIp() throws SocketException {
// 本地IP如果没有配置外网IP则返回它
String localip = null;
// 外网IP
String netip = null;
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
InetAddress ip = null;
// 是否找到外网IP
boolean finded = false;
while (netInterfaces.hasMoreElements() && !finded) {
NetworkInterface ni = netInterfaces.nextElement();
Enumeration<InetAddress> address = ni.getInetAddresses();
while (address.hasMoreElements()) {
ip = address.nextElement();
// 外网IP
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
netip = ip.getHostAddress();
finded = true;
break;
} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
// 内网IP
localip = ip.getHostAddress();
}
}
}
if (netip != null && !"".equals(netip)) {
return netip;
} else {
return localip;
}
}
/**
* java去除字符串中的空格、回车、换行符、制表符
*
* @param str
* @return
*/
public static String replaceBlank(String str) {
String dest = "";
if (str != null) {
String reg = "\\s*|\t|\r|\n";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
/**
* 判断元素是否在数组内
*
* @param child
* @param all
* @return
*/
public static boolean isIn(String child, String[] all) {
if (all == null || all.length == 0) {
return false;
}
for (int i = 0; i < all.length; i++) {
String aSource = all[i];
if (aSource.equals(child)) {
return true;
}
}
return false;
}
/**
* 判断元素是否在数组内
*
* @param childArray
* @param all
* @return
*/
public static boolean isArrayIn(String[] childArray, String[] all) {
if (all == null || all.length == 0) {
return false;
}
for (String v : childArray) {
if (!isIn(v, all)) {
return false;
}
}
return true;
}
/**
* 判断元素是否在数组内
*
* @param childArray
* @param all
* @return
*/
public static boolean isJsonArrayIn(JSONArray childArray, String[] all) {
if (all == null || all.length == 0) {
return false;
}
String[] childs = childArray.toArray(new String[]{});
for (String v : childs) {
if (!isIn(v, all)) {
return false;
}
}
return true;
}
/**
* 获取Map对象
*/
public static Map<Object, Object> getHashMap() {
return new HashMap<>(5);
}
/**
* SET转换MAP
*
* @param str
* @return
*/
public static Map<Object, Object> setToMap(Set<Object> setobj) {
Map<Object, Object> map = getHashMap();
for (Iterator iterator = setobj.iterator(); iterator.hasNext();) {
Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) iterator.next();
map.put(entry.getKey().toString(), entry.getValue() == null ? "" : entry.getValue().toString().trim());
}
return map;
}
public static boolean isInnerIp(String ipAddress) {
boolean isInnerIp = false;
long ipNum = getIpNum(ipAddress);
/**
* 私有IPA类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 当然还有127这个网段是环回地址
**/
long aBegin = getIpNum("10.0.0.0");
long aEnd = getIpNum("10.255.255.255");
long bBegin = getIpNum("172.16.0.0");
long bEnd = getIpNum("172.31.255.255");
long cBegin = getIpNum("192.168.0.0");
long cEnd = getIpNum("192.168.255.255");
String localIp = "127.0.0.1";
isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || localIp.equals(ipAddress);
return isInnerIp;
}
private static long getIpNum(String ipAddress) {
String[] ip = ipAddress.split("\\.");
long a = Integer.parseInt(ip[0]);
long b = Integer.parseInt(ip[1]);
long c = Integer.parseInt(ip[2]);
long d = Integer.parseInt(ip[3]);
long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
return ipNum;
}
private static boolean isInner(long userIp, long begin, long end) {
return (userIp >= begin) && (userIp <= end);
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
* 例如hello_world->helloWorld
*
* @param name
* 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String camelName(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains(SymbolConstant.UNDERLINE)) {
// 不含下划线,仅将首字母小写
//update-begin--Author:zhoujf Date:20180503 forTASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
//update-begin--Author:zhoujf Date:20180503 forTASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();
//update-end--Author:zhoujf Date:20180503 forTASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 处理真正的驼峰片段
if (result.length() == 0) {
// 第一个驼峰片段,全部字母都小写
result.append(camel.toLowerCase());
} else {
// 其他的驼峰片段,首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
}
return result.toString();
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
* 例如hello_world,test_id->helloWorld,testId
*
* @param name
* 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String camelNames(String names) {
if(names==null||"".equals(names)){
return null;
}
StringBuffer sf = new StringBuffer();
String[] fs = names.split(",");
for (String field : fs) {
field = camelName(field);
sf.append(field + ",");
}
String result = sf.toString();
return result.substring(0, result.length() - 1);
}
//update-begin--Author:zhoujf Date:20180503 forTASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
/**
* 将下划线大写方式命名的字符串转换为驼峰式。(首字母写)
* 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
* 例如hello_world->HelloWorld
*
* @param name
* 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String camelNameCapFirst(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains(SymbolConstant.UNDERLINE)) {
// 不含下划线,仅将首字母小写
return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 其他的驼峰片段,首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
//update-end--Author:zhoujf Date:20180503 forTASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
/**
* 将驼峰命名转化成下划线
* @param para
* @return
*/
public static String camelToUnderline(String para){
int length = 3;
if(para.length()<length){
return para.toLowerCase();
}
StringBuilder sb=new StringBuilder(para);
//定位
int temp=0;
//从第三个字符开始 避免命名不规范
for(int i=2;i<para.length();i++){
if(Character.isUpperCase(para.charAt(i))){
sb.insert(i+temp, "_");
temp+=1;
}
}
return sb.toString().toLowerCase();
}
/**
* 随机数
* @param place 定义随机数的位数
*/
public static String randomGen(int place) {
String base = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789";
StringBuffer sb = new StringBuffer();
Random rd = new Random();
for(int i=0;i<place;i++) {
sb.append(base.charAt(rd.nextInt(base.length())));
}
return sb.toString();
}
/**
* 获取类的所有属性,包括父类
*
* @param object
* @return
*/
public static Field[] getAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
/**
* 将map的key全部转成小写
* @param list
* @return
*/
public static List<Map<String, Object>> toLowerCasePageList(List<Map<String, Object>> list){
List<Map<String, Object>> select = new ArrayList<>();
for (Map<String, Object> row : list) {
Map<String, Object> resultMap = new HashMap<>(5);
Set<String> keySet = row.keySet();
for (String key : keySet) {
String newKey = key.toLowerCase();
resultMap.put(newKey, row.get(key));
}
select.add(resultMap);
}
return select;
}
/**
* 将entityList转换成modelList
* @param fromList
* @param tClass
* @param <F>
* @param <T>
* @return
*/
public static<F,T> List<T> entityListToModelList(List<F> fromList, Class<T> tClass){
if(fromList == null || fromList.isEmpty()){
return null;
}
List<T> tList = new ArrayList<>();
for(F f : fromList){
T t = entityToModel(f, tClass);
tList.add(t);
}
return tList;
}
public static<F,T> T entityToModel(F entity, Class<T> modelClass) {
log.debug("entityToModel : Entity属性的值赋值到Model");
Object model = null;
if (entity == null || modelClass ==null) {
return null;
}
try {
model = modelClass.newInstance();
} catch (InstantiationException e) {
log.error("entityToModel : 实例化异常", e);
} catch (IllegalAccessException e) {
log.error("entityToModel : 安全权限异常", e);
}
BeanUtils.copyProperties(entity, model);
return (T)model;
}
/**
* 判断 list 是否为空
*
* @param list
* @return true or false
* list == null : true
* list.size() == 0 : true
*/
public static boolean listIsEmpty(Collection list) {
return (list == null || list.size() == 0);
}
/**
* 判断旧值与新值 是否相等
*
* @param oldVal
* @param newVal
* @return
*/
public static boolean isEqual(Object oldVal, Object newVal) {
if (oldVal != null && newVal != null) {
if (isArray(oldVal)) {
return equalityOfArrays((Object[]) oldVal, (Object[]) newVal);
}else if(oldVal instanceof JSONArray){
if(newVal instanceof JSONArray){
return equalityOfJSONArray((JSONArray) oldVal, (JSONArray) newVal);
}else{
if (isEmpty(newVal) && (oldVal == null || ((JSONArray) oldVal).size() == 0)) {
return true;
}
List<Object> arrayStr = Arrays.asList(newVal.toString().split(","));
JSONArray newValArray = new JSONArray(arrayStr);
return equalityOfJSONArray((JSONArray) oldVal, newValArray);
}
}else{
return oldVal.equals(newVal);
}
} else {
if (oldVal == null && newVal == null) {
return true;
} else {
return false;
}
}
}
/**
* 方法描述 判断一个对象是否是一个数组
*
* @param obj
* @return
* @author yaomy
* @date 2018年2月5日 下午5:03:00
*/
public static boolean isArray(Object obj) {
if (obj == null) {
return false;
}
return obj.getClass().isArray();
}
/**
* 判断两个数组是否相等(数组元素不分顺序)
*
* @param oldVal
* @param newVal
* @return
*/
public static boolean equalityOfJSONArray(JSONArray oldVal, JSONArray newVal) {
if (oldVal != null && newVal != null) {
Object[] oldValArray = oldVal.toArray();
Object[] newValArray = newVal.toArray();
return equalityOfArrays(oldValArray,newValArray);
} else {
if ((oldVal == null || oldVal.size() == 0) && (newVal == null || newVal.size() == 0)) {
return true;
} else {
return false;
}
}
}
/**
* 比较带逗号的字符串
* QQYUN-5212【简流】按日期触发 多选 人员组件 选择顺序不一致时 不触发,应该是统一问题 包括多选部门组件
* @param oldVal
* @param newVal
* @return
*/
public static boolean equalityOfStringArrays(String oldVal, String newVal) {
if(oldVal.equals(newVal)){
return true;
}
if(oldVal.indexOf(",")>=0 && newVal.indexOf(",")>=0){
String[] arr1 = oldVal.split(",");
String[] arr2 = newVal.split(",");
if(arr1.length == arr2.length){
boolean flag = true;
Map<String, Integer> map = new HashMap<>();
for(String s1: arr1){
map.put(s1, 1);
}
for(String s2: arr2){
if(map.get(s2) == null){
flag = false;
break;
}
}
return flag;
}
}
return false;
}
/**
* 判断两个数组是否相等(数组元素不分顺序)
*
* @param oldVal
* @param newVal
* @return
*/
public static boolean equalityOfArrays(Object[] oldVal, Object newVal[]) {
if (oldVal != null && newVal != null) {
Arrays.sort(oldVal);
Arrays.sort(newVal);
return Arrays.equals(oldVal, newVal);
} else {
if ((oldVal == null || oldVal.length == 0) && (newVal == null || newVal.length == 0)) {
return true;
} else {
return false;
}
}
}
// public static void main(String[] args) {
//// String[] a = new String[]{"1", "2"};
//// String[] b = new String[]{"2", "1"};
// Integer a = null;
// Integer b = 1;
// System.out.println(oConvertUtils.isEqual(a, b));
// }
/**
* 判断 list 是否不为空
*
* @param list
* @return true or false
* list == null : false
* list.size() == 0 : false
*/
public static boolean listIsNotEmpty(Collection list) {
return !listIsEmpty(list);
}
/**
* 读取静态文本内容
* @param url
* @return
*/
public static String readStatic(String url) {
String json = "";
try {
//换个写法解决springboot读取jar包中文件的问题
InputStream stream = oConvertUtils.class.getClassLoader().getResourceAsStream(url.replace("classpath:", ""));
json = IOUtils.toString(stream,"UTF-8");
} catch (IOException e) {
log.error(e.getMessage(),e);
}
return json;
}
/**
* 将List 转成 JSONArray
* @return
*/
public static JSONArray list2JSONArray(List<String> list){
if(list==null || list.size()==0){
return null;
}
JSONArray array = new JSONArray();
for(String str: list){
array.add(str);
}
return array;
}
/**
* 判断两个list中的元素是否完全一致
* QQYUN-5326【简流】获取组织人员 单/多 筛选条件 没有部门筛选
* @return
*/
public static boolean isEqList(List<String> list1, List<String> list2){
if(list1.size() != list2.size()){
return false;
}
for(String str1: list1){
boolean flag = false;
for(String str2: list2){
if(str1.equals(str2)){
flag = true;
break;
}
}
if(!flag){
return false;
}
}
return true;
}
/**
* 判断 list1中的元素是否在list2中出现
* QQYUN-5326【简流】获取组织人员 单/多 筛选条件 没有部门筛选
* @param list1
* @param list2
* @return
*/
public static boolean isInList(List<String> list1, List<String> list2){
for(String str1: list1){
boolean flag = false;
for(String str2: list2){
if(str1.equals(str2)){
flag = true;
break;
}
}
if(flag){
return true;
}
}
return false;
}
/**
* 计算文件大小转成MB
* @param uploadCount
* @return
*/
public static Double calculateFileSizeToMb(Long uploadCount){
double count = 0.0;
if(uploadCount>0) {
BigDecimal bigDecimal = new BigDecimal(uploadCount);
//换算成MB
BigDecimal divide = bigDecimal.divide(new BigDecimal(1048576));
count = divide.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
return count;
}
return count;
}
}

View File

@ -1,33 +0,0 @@
package org.jeecg.common.util.sqlInjection;
import net.sf.jsqlparser.parser.CCJSqlParserDefaultVisitor;
import net.sf.jsqlparser.parser.SimpleNode;
import net.sf.jsqlparser.statement.select.UnionOp;
import org.jeecg.common.exception.JeecgSqlInjectionException;
/**
* 基于抽象语法树(AST)的注入攻击分析实现
*
* @author guyadong
*/
public class InjectionAstNodeVisitor extends CCJSqlParserDefaultVisitor {
public InjectionAstNodeVisitor() {
}
/**
* 处理禁止联合查询
*
* @param node
* @param data
* @return
*/
@Override
public Object visit(SimpleNode node, Object data) {
Object value = node.jjtGetValue();
if (value instanceof UnionOp) {
throw new JeecgSqlInjectionException("DISABLE UNION");
}
return super.visit(node, data);
}
}

View File

@ -1,172 +0,0 @@
package org.jeecg.common.util.sqlInjection;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectItem;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.WithItem;
import net.sf.jsqlparser.util.TablesNamesFinder;
import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.sqlInjection.parse.ConstAnalyzer;
import org.jeecg.common.util.sqlInjection.parse.ParserSupport;
/**
* 基于SQL语法对象的SQL注入攻击分析实现
*
* @author guyadong
*/
public class InjectionSyntaxObjectAnalyzer extends TablesNamesFinder {
/**
* 危险函数名
*/
private static final String DANGROUS_FUNCTIONS = "(sleep|benchmark|extractvalue|updatexml|ST_LatFromGeoHash|ST_LongFromGeoHash|GTID_SUBSET|GTID_SUBTRACT|floor|ST_Pointfromgeohash"
+ "|geometrycollection|multipoint|polygon|multipolygon|linestring|multilinestring)";
private static ThreadLocal<Boolean> disableSubselect = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return true;
}
};
private ConstAnalyzer constAnalyzer = new ConstAnalyzer();
public InjectionSyntaxObjectAnalyzer() {
super();
init(true);
}
@Override
public void visitBinaryExpression(BinaryExpression binaryExpression) {
if (binaryExpression instanceof ComparisonOperator) {
if (isConst(binaryExpression.getLeftExpression()) && isConst(binaryExpression.getRightExpression())) {
/** 禁用恒等式 */
throw new JeecgSqlInjectionException("DISABLE IDENTICAL EQUATION " + binaryExpression);
}
}
super.visitBinaryExpression(binaryExpression);
}
@Override
public void visit(AndExpression andExpression) {
super.visit(andExpression);
checkConstExpress(andExpression.getLeftExpression());
checkConstExpress(andExpression.getRightExpression());
}
@Override
public void visit(OrExpression orExpression) {
super.visit(orExpression);
checkConstExpress(orExpression.getLeftExpression());
checkConstExpress(orExpression.getRightExpression());
}
@Override
public void visit(Function function) {
if (function.getName().matches(DANGROUS_FUNCTIONS)) {
/** 禁用危险函数 */
throw new JeecgSqlInjectionException("DANGROUS FUNCTION: " + function.getName());
}
super.visit(function);
}
@Override
public void visit(WithItem withItem) {
try {
/** 允许 WITH 语句中的子查询 */
disableSubselect.set(false);
super.visit(withItem);
} finally {
disableSubselect.set(true);
}
}
@Override
public void visit(SubSelect subSelect) {
try {
/** 允许语句中的子查询 */
disableSubselect.set(false);
super.visit(subSelect);
} finally {
disableSubselect.set(true);
}
// if (disableSubselect.get()) {
// // 禁用子查询
// throw new JeecgSqlInjectionException("DISABLE subselect " + subSelect);
// }
}
@Override
public void visit(Column tableColumn) {
if (ParserSupport.isBoolean(tableColumn)) {
throw new JeecgSqlInjectionException("DISABLE CONST BOOL " + tableColumn);
}
super.visit(tableColumn);
}
@Override
public void visit(PlainSelect plainSelect) {
if (plainSelect.getSelectItems() != null) {
for (SelectItem item : plainSelect.getSelectItems()) {
item.accept(this);
}
}
if (plainSelect.getFromItem() != null) {
plainSelect.getFromItem().accept(this);
}
if (plainSelect.getJoins() != null) {
for (Join join : plainSelect.getJoins()) {
join.getRightItem().accept(this);
for (Expression e : join.getOnExpressions()) {
e.accept(this);
}
}
}
if (plainSelect.getWhere() != null) {
plainSelect.getWhere().accept(this);
checkConstExpress(plainSelect.getWhere());
}
if (plainSelect.getHaving() != null) {
plainSelect.getHaving().accept(this);
}
if (plainSelect.getOracleHierarchical() != null) {
plainSelect.getOracleHierarchical().accept(this);
}
if (plainSelect.getOrderByElements() != null) {
for (OrderByElement orderByElement : plainSelect.getOrderByElements()) {
orderByElement.getExpression().accept(this);
}
}
if (plainSelect.getGroupBy() != null) {
for (Expression expression : plainSelect.getGroupBy().getGroupByExpressionList().getExpressions()) {
expression.accept(this);
}
}
}
private boolean isConst(Expression expression) {
return constAnalyzer.isConstExpression(expression);
}
private void checkConstExpress(Expression expression) {
if (constAnalyzer.isConstExpression(expression)) {
/** 禁用常量表达式 */
throw new JeecgSqlInjectionException("DISABLE CONST EXPRESSION " + expression);
}
}
}

View File

@ -1,65 +0,0 @@
package org.jeecg.common.util.sqlInjection;
import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.sqlInjection.parse.ParserSupport;
;
/**
* SQL注入攻击分析器
*
* @author guyadong
* 参考:
* https://blog.csdn.net/10km/article/details/127767358
* https://gitee.com/l0km/sql2java/tree/dev/sql2java-manager/src/main/java/gu/sql2java/parser
*/
public class SqlInjectionAnalyzer {
//启用/关闭注入攻击检查
private boolean injectCheckEnable = true;
//防止SQL注入攻击分析实现
private final InjectionSyntaxObjectAnalyzer injectionChecker;
private final InjectionAstNodeVisitor injectionVisitor;
public SqlInjectionAnalyzer() {
this.injectionChecker = new InjectionSyntaxObjectAnalyzer();
this.injectionVisitor = new InjectionAstNodeVisitor();
}
/**
* 启用/关闭注入攻击检查,默认启动
*
* @param enable
* @return
*/
public SqlInjectionAnalyzer injectCheckEnable(boolean enable) {
injectCheckEnable = enable;
return this;
}
/**
* 对解析后的SQL对象执行注入攻击分析有注入攻击的危险则抛出异常{@link JeecgSqlInjectionException}
*
* @param sqlParserInfo
* @throws JeecgSqlInjectionException
*/
public ParserSupport.SqlParserInfo injectAnalyse(ParserSupport.SqlParserInfo sqlParserInfo) throws JeecgSqlInjectionException {
if (null != sqlParserInfo && injectCheckEnable) {
/** SQL注入攻击检查 */
sqlParserInfo.statement.accept(injectionChecker);
sqlParserInfo.simpleNode.jjtAccept(injectionVisitor, null);
}
return sqlParserInfo;
}
/**
* sql校验
*/
public static void checkSql(String sql,boolean check){
SqlInjectionAnalyzer sqlInjectionAnalyzer = new SqlInjectionAnalyzer();
sqlInjectionAnalyzer.injectCheckEnable(check);
ParserSupport.SqlParserInfo sqlParserInfo = ParserSupport.parse0(sql, null,null);
sqlInjectionAnalyzer.injectAnalyse(sqlParserInfo);
}
}

View File

@ -1,569 +0,0 @@
package org.jeecg.common.util.sqlInjection.parse;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.IntegerDivision;
import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.conditional.XorExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.FullTextSearch;
import net.sf.jsqlparser.expression.operators.relational.GeometryDistance;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsBooleanExpression;
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.AllColumns;
import net.sf.jsqlparser.statement.select.AllTableColumns;
import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.SubSelect;
/**
* 判断表达是否为常量的分析器
*
* @author guyadong
*/
public class ConstAnalyzer implements ExpressionVisitor, ItemsListVisitor {
private static ThreadLocal<Boolean> constFlag = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return true;
}
};
@Override
public void visit(NullValue value) {
}
@Override
public void visit(Function function) {
constFlag.set(false);
}
@Override
public void visit(SignedExpression expr) {
expr.getExpression().accept(this);
}
@Override
public void visit(JdbcParameter parameter) {
constFlag.set(false);
}
@Override
public void visit(JdbcNamedParameter parameter) {
constFlag.set(false);
}
@Override
public void visit(DoubleValue value) {
}
@Override
public void visit(LongValue value) {
}
@Override
public void visit(DateValue value) {
}
@Override
public void visit(TimeValue value) {
}
@Override
public void visit(TimestampValue value) {
}
@Override
public void visit(Parenthesis parenthesis) {
parenthesis.getExpression().accept(this);
}
@Override
public void visit(StringValue value) {
}
@Override
public void visit(Addition expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Division expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(IntegerDivision expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Multiplication expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Subtraction expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(AndExpression expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(OrExpression expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(XorExpression expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Between expr) {
expr.getLeftExpression().accept(this);
expr.getBetweenExpressionStart().accept(this);
expr.getBetweenExpressionEnd().accept(this);
}
// /**
// * 用于处理 OverlapsCondition 类型的表达式
// * @param overlapsCondition
// */
// @Override
// public void visit(OverlapsCondition overlapsCondition) {
// constFlag.set(false);
// }
// /**
// * 用于处理 SafeCastExpression 类型的表达式。
// * @param safeCastExpression
// */
// @Override
// public void visit(SafeCastExpression safeCastExpression) {
// constFlag.set(false);
// }
@Override
public void visit(EqualsTo expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(GreaterThan expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(GreaterThanEquals expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(InExpression expr) {
if (expr.getLeftExpression() != null) {
expr.getLeftExpression().accept(this);
}
}
@Override
public void visit(IsNullExpression expr) {
expr.getLeftExpression().accept(this);
}
@Override
public void visit(FullTextSearch expr) {
constFlag.set(false);
}
@Override
public void visit(IsBooleanExpression expr) {
expr.getLeftExpression().accept(this);
}
@Override
public void visit(LikeExpression expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(MinorThan expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(MinorThanEquals expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(NotEqualsTo expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Column column) {
if (!ParserSupport.isBoolean(column)) {
constFlag.set(false);
}
}
@Override
public void visit(SubSelect subSelect) {
constFlag.set(false);
}
@Override
public void visit(CaseExpression expr) {
constFlag.set(false);
}
@Override
public void visit(WhenClause expr) {
constFlag.set(false);
}
@Override
public void visit(ExistsExpression expr) {
constFlag.set(false);
}
@Override
public void visit(AnyComparisonExpression expr) {
constFlag.set(false);
}
@Override
public void visit(Concat expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(Matches expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(BitwiseAnd expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(BitwiseOr expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(BitwiseXor expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(CastExpression expr) {
expr.getLeftExpression().accept(this);
}
@Override
public void visit(TryCastExpression expr) {
constFlag.set(false);
}
@Override
public void visit(Modulo expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(AnalyticExpression expr) {
constFlag.set(false);
}
@Override
public void visit(ExtractExpression expr) {
expr.getExpression().accept(this);
}
@Override
public void visit(IntervalExpression expr) {
constFlag.set(false);
}
@Override
public void visit(OracleHierarchicalExpression expr) {
constFlag.set(false);
}
@Override
public void visit(RegExpMatchOperator expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(ExpressionList expressionList) {
for (Expression expr : expressionList.getExpressions()) {
expr.accept(this);
}
}
@Override
public void visit(NamedExpressionList namedExpressionList) {
for (Expression expr : namedExpressionList.getExpressions()) {
expr.accept(this);
}
}
@Override
public void visit(MultiExpressionList multiExprList) {
for (ExpressionList list : multiExprList.getExpressionLists()) {
visit(list);
}
}
@Override
public void visit(NotExpression notExpr) {
notExpr.getExpression().accept(this);
}
@Override
public void visit(BitwiseRightShift expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(BitwiseLeftShift expr) {
visitBinaryExpression(expr);
}
protected void visitBinaryExpression(BinaryExpression expr) {
expr.getLeftExpression().accept(this);
expr.getRightExpression().accept(this);
}
@Override
public void visit(JsonExpression jsonExpr) {
jsonExpr.getExpression().accept(this);
}
@Override
public void visit(JsonOperator expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(RegExpMySQLOperator expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(UserVariable var) {
constFlag.set(false);
}
@Override
public void visit(NumericBind bind) {
constFlag.set(false);
}
@Override
public void visit(KeepExpression expr) {
for (OrderByElement element : expr.getOrderByElements()) {
element.getExpression().accept(this);
}
}
@Override
public void visit(MySQLGroupConcat groupConcat) {
constFlag.set(false);
}
@Override
public void visit(ValueListExpression valueListExpression) {
for (Expression expr : valueListExpression.getExpressionList().getExpressions()) {
expr.accept(this);
}
}
@Override
public void visit(AllColumns allColumns) {
}
@Override
public void visit(AllTableColumns allTableColumns) {
}
@Override
public void visit(AllValue allValue) {
}
@Override
public void visit(IsDistinctExpression isDistinctExpression) {
visitBinaryExpression(isDistinctExpression);
}
@Override
public void visit(RowGetExpression rowGetExpression) {
rowGetExpression.getExpression().accept(this);
}
@Override
public void visit(HexValue hexValue) {
}
@Override
public void visit(OracleHint hint) {
}
@Override
public void visit(TimeKeyExpression timeKeyExpression) {
}
@Override
public void visit(DateTimeLiteralExpression literal) {
}
@Override
public void visit(NextValExpression nextVal) {
constFlag.set(false);
}
@Override
public void visit(CollateExpression col) {
constFlag.set(false);
}
@Override
public void visit(SimilarToExpression expr) {
visitBinaryExpression(expr);
}
@Override
public void visit(ArrayExpression array) {
array.getObjExpression().accept(this);
if (array.getIndexExpression() != null) {
array.getIndexExpression().accept(this);
}
if (array.getStartIndexExpression() != null) {
array.getStartIndexExpression().accept(this);
}
if (array.getStopIndexExpression() != null) {
array.getStopIndexExpression().accept(this);
}
}
@Override
public void visit(ArrayConstructor aThis) {
for (Expression expression : aThis.getExpressions()) {
expression.accept(this);
}
}
@Override
public void visit(VariableAssignment var) {
constFlag.set(false);
}
@Override
public void visit(XMLSerializeExpr expr) {
constFlag.set(false);
}
@Override
public void visit(TimezoneExpression expr) {
expr.getLeftExpression().accept(this);
}
@Override
public void visit(JsonAggregateFunction expression) {
Expression expr = expression.getExpression();
if (expr != null) {
expr.accept(this);
}
expr = expression.getFilterExpression();
if (expr != null) {
expr.accept(this);
}
}
@Override
public void visit(JsonFunction expression) {
for (JsonFunctionExpression expr : expression.getExpressions()) {
expr.getExpression().accept(this);
}
}
@Override
public void visit(ConnectByRootOperator connectByRootOperator) {
constFlag.set(false);
}
@Override
public void visit(OracleNamedFunctionParameter oracleNamedFunctionParameter) {
constFlag.set(false);
}
@Override
public void visit(GeometryDistance geometryDistance) {
visitBinaryExpression(geometryDistance);
}
@Override
public void visit(RowConstructor rowConstructor) {
constFlag.set(false);
}
public boolean isConstExpression(Expression expression) {
if (null != expression) {
constFlag.set(true);
expression.accept(this);
return constFlag.get();
}
return false;
}
}

View File

@ -1,177 +0,0 @@
package org.jeecg.common.util.sqlInjection.parse;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.*;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.exception.JeecgSqlInjectionException;
/**
* 解析sql支持
*/
@Slf4j
public class ParserSupport {
/**
* 解析SELECT SQL语句,解析失败或非SELECT语句则抛出异常
*
* @param sql
* @return
*/
public static Select parseSelect(String sql) {
Statement stmt;
try {
stmt = CCJSqlParserUtil.parse(checkNotNull(sql, "sql is null"));
} catch (JSQLParserException e) {
throw new JeecgBootException(e);
}
checkArgument(stmt instanceof Select, "%s is not SELECT statment", sql);
Select select = (Select) stmt;
SelectBody selectBody = select.getSelectBody();
// 暂时只支持简单的SELECT xxxx FROM ....语句不支持复杂语句如WITH
checkArgument(selectBody instanceof PlainSelect, "ONLY SUPPORT plain select statement %s", sql);
return (Select) stmt;
}
/**
* 解析SELECT SQL语句,解析失败或非SELECT语句则
*
* @param sql
* @return
*/
public static Select parseSelectUnchecked(String sql) {
try {
return parseSelect(sql);
} catch (Exception e) {
return null;
}
}
/**
* 实现SQL语句解析,解析成功则返回解析后的{@link Statement}
* 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。
*
* @param sql SQL语句
* @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略
* @param sqlSyntaxNormalizer SQL语句分析转换器为{@code null}忽略
* @throws JSQLParserException 输入的SQL语句有语法错误
* @see #parse0(String, CCJSqlParserVisitor, SqlSyntaxNormalizer)
*/
public static Statement parse(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxNormalizer) throws JSQLParserException {
return parse0(sql, visitor, sqlSyntaxNormalizer).statement;
}
/**
* 参照{@link CCJSqlParserUtil#parseAST(String)}和{@link CCJSqlParserUtil#parse(String)}实现SQL语句解析,
* 解析成功则返回解析后的{@link SqlParserInfo}对象,
* 并通过{@code visitor}参数提供基于AST(抽象语法树)的遍历所有节点的能力。
*
* @param sql SQL语句
* @param visitor 遍历所有节点的{@link SimpleNodeVisitor}接口实例,为{@code null}忽略
* @param sqlSyntaxAnalyzer SQL语句分析转换器为{@code null}忽略
* @throws JSQLParserException 输入的SQL语句有语法错误
* @see net.sf.jsqlparser.parser.Node#jjtAccept(SimpleNodeVisitor, Object)
*/
public static SqlParserInfo parse0(String sql, CCJSqlParserVisitor visitor, SqlSyntaxNormalizer sqlSyntaxAnalyzer) throws JeecgSqlInjectionException {
//检查是否非select开头暂不支持
if(!sql.toLowerCase().trim().startsWith("select ")) {
log.warn("传入sql 非select开头不支持非select开头的语句解析");
return null;
}
//检查是否存储过程,暂不支持
if(sql.toLowerCase().trim().startsWith("call ")){
log.warn("传入call 开头存储过程,不支持存储过程解析!");
return null;
}
//检查特殊语义的特殊字符,目前检查冒号、$、#三种特殊语义字符
String specialCharacters = "[:$#]";
Pattern pattern = Pattern.compile(specialCharacters);
Matcher matcher = pattern.matcher(sql);
if (matcher.find()) {
sql = sql.replaceAll("[:$#]", "@");
}
checkArgument(null != sql, "sql is null");
boolean allowComplexParsing = CCJSqlParserUtil.getNestingDepth(sql) <= CCJSqlParserUtil.ALLOWED_NESTING_DEPTH;
CCJSqlParser parser = CCJSqlParserUtil.newParser(sql).withAllowComplexParsing(allowComplexParsing);
Statement stmt;
try {
stmt = parser.Statement();
} catch (Exception ex) {
log.error("请注意SQL语法可能存在问题---> {}", ex.getMessage());
throw new JeecgSqlInjectionException("请注意SQL语法可能存在问题:"+sql);
}
if (null != visitor) {
parser.getASTRoot().jjtAccept(visitor, null);
}
if (null != sqlSyntaxAnalyzer) {
stmt.accept(sqlSyntaxAnalyzer.resetChanged());
}
return new SqlParserInfo(stmt.toString(), stmt, (SimpleNode) parser.getASTRoot());
}
/**
* 调用{@link CCJSqlParser}解析SQL语句部件返回解析生成的对象,如{@code 'ORDER BY id DESC'}
*
* @param <T>
* @param input
* @param method 指定调用的{@link CCJSqlParser}解析方法
* @param targetType 返回的解析对象类型
* @return
* @since 3.18.3
*/
public static <T> T parseComponent(String input, String method, Class<T> targetType) {
try {
CCJSqlParser parser = new CCJSqlParser(new StringProvider(input));
try {
return checkNotNull(targetType, "targetType is null").cast(parser.getClass().getMethod(method).invoke(parser));
} catch (InvocationTargetException e) {
Throwables.throwIfUnchecked(e.getTargetException());
throw new RuntimeException(e.getTargetException());
}
} catch (IllegalAccessException | NoSuchMethodException | SecurityException e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
/**
* 如果{@link Column}没有定义table,且字段名为true/false(不区分大小写)则视为布尔常量
*
* @param column
*/
public static boolean isBoolean(Column column) {
return null != column && null == column.getTable() &&
Pattern.compile("(true|false)", Pattern.CASE_INSENSITIVE).matcher(column.getColumnName()).matches();
}
public static class SqlParserInfo {
public String nativeSql;
public Statement statement;
public SimpleNode simpleNode;
SqlParserInfo(String nativeSql, Statement statement, SimpleNode simpleNode) {
this.nativeSql = nativeSql;
this.statement = statement;
this.simpleNode = simpleNode;
}
}
}

View File

@ -1,37 +0,0 @@
package org.jeecg.common.util.sqlInjection.parse;
import net.sf.jsqlparser.util.TablesNamesFinder;
/**
* SQL语句分析转换器基类<br>
* 基于SQL语法对象实现对SQL的修改
* (暂时用不到)
*
* @author guyadong
* @since 3.17.0
*/
public class SqlSyntaxNormalizer extends TablesNamesFinder {
protected static final ThreadLocal<Boolean> changed = new ThreadLocal<>();
public SqlSyntaxNormalizer() {
super();
init(true);
}
/**
* 语句改变返回{@code true},否则返回{@code false}
*/
public boolean changed() {
return Boolean.TRUE.equals(changed.get());
}
/**
* 复位线程局部变量{@link #changed}状态
*/
public SqlSyntaxNormalizer resetChanged() {
changed.remove();
return this;
}
}

View File

@ -1,255 +0,0 @@
package org.jeecg.common.util.sqlparse;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 解析所有表名和字段的类
*/
@Slf4j
public class JSqlParserAllTableManager {
private final String sql;
private final Map<String, SelectSqlInfo> allTableMap = new HashMap<>();
/**
* 别名对应实际表名
*/
private final Map<String, String> tableAliasMap = new HashMap<>();
/**
* 解析后的sql
*/
private String parsedSql = null;
JSqlParserAllTableManager(String selectSql) {
this.sql = selectSql;
}
/**
* 开始解析
*
* @return
* @throws JSQLParserException
*/
public Map<String, SelectSqlInfo> parse() throws JSQLParserException {
// 1. 创建解析器
CCJSqlParserManager mgr = new CCJSqlParserManager();
// 2. 使用解析器解析sql生成具有层次结构的java类
Statement stmt = mgr.parse(new StringReader(this.sql));
if (stmt instanceof Select) {
Select selectStatement = (Select) stmt;
SelectBody selectBody = selectStatement.getSelectBody();
this.parsedSql = selectBody.toString();
// 3. 解析select查询sql的信息
if (selectBody instanceof PlainSelect) {
PlainSelect plainSelect = (PlainSelect) selectBody;
// 4. 合并 fromItems
List<FromItem> fromItems = new ArrayList<>();
fromItems.add(plainSelect.getFromItem());
// 4.1 处理join的表
List<Join> joins = plainSelect.getJoins();
if (joins != null) {
joins.forEach(join -> fromItems.add(join.getRightItem()));
}
// 5. 处理 fromItems
for (FromItem fromItem : fromItems) {
// 5.1 通过表名的方式from
if (fromItem instanceof Table) {
this.addSqlInfoByTable((Table) fromItem);
}
// 5.2 通过子查询的方式from
else if (fromItem instanceof SubSelect) {
this.handleSubSelect((SubSelect) fromItem);
}
}
// 6. 解析 selectFields
List<SelectItem> selectItems = plainSelect.getSelectItems();
for (SelectItem selectItem : selectItems) {
// 6.1 查询的是全部字段
if (selectItem instanceof AllColumns) {
// 当 selectItem 为 AllColumns 时fromItem 必定为 Table
String tableName = plainSelect.getFromItem(Table.class).getName();
// 此处必定不为空,因为在解析 fromItem 时,已经将表名添加到 allTableMap 中
SelectSqlInfo sqlInfo = this.allTableMap.get(tableName);
assert sqlInfo != null;
// 设置为查询全部字段
sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null);
}
// 6.2 查询的是带表别名( u.* )的全部字段
else if (selectItem instanceof AllTableColumns) {
AllTableColumns allTableColumns = (AllTableColumns) selectItem;
String aliasName = allTableColumns.getTable().getName();
// 通过别名获取表名
String tableName = this.tableAliasMap.get(aliasName);
if (tableName == null) {
tableName = aliasName;
}
SelectSqlInfo sqlInfo = this.allTableMap.get(tableName);
// 如果此处为空,则说明该字段是通过子查询获取的,所以可以不处理,只有实际表才需要处理
if (sqlInfo != null) {
// 设置为查询全部字段
sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null);
}
}
// 6.3 各种字段表达式处理
else if (selectItem instanceof SelectExpressionItem) {
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
Expression expression = selectExpressionItem.getExpression();
Alias alias = selectExpressionItem.getAlias();
this.handleExpression(expression, alias, plainSelect.getFromItem());
}
}
} else {
log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName());
throw new JeecgBootException("暂时尚未处理该类型的 SelectBody");
}
} else {
// 非 select 查询sql不做处理
throw new JeecgBootException("非 select 查询sql不做处理");
}
return this.allTableMap;
}
/**
* 处理子查询
*
* @param subSelect
*/
private void handleSubSelect(SubSelect subSelect) {
try {
String subSelectSql = subSelect.getSelectBody().toString();
// 递归调用解析
Map<String, SelectSqlInfo> map = JSqlParserUtils.parseAllSelectTable(subSelectSql);
if (map != null) {
this.assignMap(map);
}
} catch (Exception e) {
log.error("解析子查询出错", e);
}
}
/**
* 处理查询字段表达式
*
* @param expression
*/
private void handleExpression(Expression expression, Alias alias, FromItem fromItem) {
// 处理函数式字段 CONCAT(name,'(',age,')')
if (expression instanceof Function) {
Function functionExp = (Function) expression;
List<Expression> expressions = functionExp.getParameters().getExpressions();
for (Expression expItem : expressions) {
this.handleExpression(expItem, null, fromItem);
}
return;
}
// 处理字段上的子查询
if (expression instanceof SubSelect) {
this.handleSubSelect((SubSelect) expression);
return;
}
// 不处理字面量
if (expression instanceof StringValue ||
expression instanceof NullValue ||
expression instanceof LongValue ||
expression instanceof DoubleValue ||
expression instanceof HexValue ||
expression instanceof DateValue ||
expression instanceof TimestampValue ||
expression instanceof TimeValue
) {
return;
}
// 处理字段
if (expression instanceof Column) {
Column column = (Column) expression;
// 查询字段名
String fieldName = column.getColumnName();
String aliasName = fieldName;
if (alias != null) {
aliasName = alias.getName();
}
String tableName;
if (column.getTable() != null) {
// 通过列的表名获取 sqlInfo
// 例如 user.name这里的 tableName 就是 user
tableName = column.getTable().getName();
// 有可能是别名,需要转换为真实表名
if (this.tableAliasMap.get(tableName) != null) {
tableName = this.tableAliasMap.get(tableName);
}
} else {
// 当column的table为空时说明是 fromItem 中的字段
tableName = ((Table) fromItem).getName();
}
SelectSqlInfo $sqlInfo = this.allTableMap.get(tableName);
if ($sqlInfo != null) {
$sqlInfo.addSelectField(aliasName, fieldName);
} else {
log.warn("发生意外情况,未找到表名为 {} 的 SelectSqlInfo", tableName);
}
}
}
/**
* 根据表名添加sqlInfo
*
* @param table
*/
private void addSqlInfoByTable(Table table) {
String tableName = table.getName();
// 解析 aliasName
if (table.getAlias() != null) {
this.tableAliasMap.put(table.getAlias().getName(), tableName);
}
SelectSqlInfo sqlInfo = new SelectSqlInfo(this.parsedSql);
sqlInfo.setFromTableName(table.getName());
this.allTableMap.put(sqlInfo.getFromTableName(), sqlInfo);
}
/**
* 合并map
*
* @param source
*/
private void assignMap(Map<String, SelectSqlInfo> source) {
for (Map.Entry<String, SelectSqlInfo> entry : source.entrySet()) {
SelectSqlInfo sqlInfo = this.allTableMap.get(entry.getKey());
if (sqlInfo == null) {
this.allTableMap.put(entry.getKey(), entry.getValue());
} else {
// 合并
if (sqlInfo.getSelectFields() == null) {
sqlInfo.setSelectFields(entry.getValue().getSelectFields());
} else {
sqlInfo.getSelectFields().addAll(entry.getValue().getSelectFields());
}
if (sqlInfo.getRealSelectFields() == null) {
sqlInfo.setRealSelectFields(entry.getValue().getRealSelectFields());
} else {
sqlInfo.getRealSelectFields().addAll(entry.getValue().getRealSelectFields());
}
}
}
}
}

View File

@ -1,184 +0,0 @@
package org.jeecg.common.util.sqlparse;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import java.io.StringReader;
import java.util.List;
import java.util.Map;
@Slf4j
public class JSqlParserUtils {
/**
* 解析 查询selectsql的信息
* 此方法会展开所有子查询到一个map里
* key只存真实的表名如果查询的没有真实的表名则会被忽略。
* value只存真实的字段名如果查询的没有真实的字段名则会被忽略。
* <p>
* 例如SELECT a.*,d.age,(SELECT count(1) FROM sys_depart) AS count FROM (SELECT username AS foo, realname FROM sys_user) a, demo d
* 解析后的结果为:{sys_user=[username, realname], demo=[age], sys_depart=[]}
*
* @param selectSql
* @return
*/
public static Map<String, SelectSqlInfo> parseAllSelectTable(String selectSql) throws JSQLParserException {
if (oConvertUtils.isEmpty(selectSql)) {
return null;
}
// log.info("解析查询Sql{}", selectSql);
JSqlParserAllTableManager allTableManager = new JSqlParserAllTableManager(selectSql);
return allTableManager.parse();
}
/**
* 解析 查询selectsql的信息子查询嵌套
*
* @param selectSql
* @return
*/
public static SelectSqlInfo parseSelectSqlInfo(String selectSql) throws JSQLParserException {
if (oConvertUtils.isEmpty(selectSql)) {
return null;
}
// log.info("解析查询Sql{}", selectSql);
// 使用 JSqlParer 解析sql
// 1、创建解析器
CCJSqlParserManager mgr = new CCJSqlParserManager();
// 2、使用解析器解析sql生成具有层次结构的java类
Statement stmt = mgr.parse(new StringReader(selectSql));
if (stmt instanceof Select) {
Select selectStatement = (Select) stmt;
// 3、解析select查询sql的信息
return JSqlParserUtils.parseBySelectBody(selectStatement.getSelectBody());
} else {
// 非 select 查询sql不做处理
throw new JeecgBootException("非 select 查询sql不做处理");
}
}
/**
* 解析 select 查询sql的信息
*
* @param selectBody
* @return
*/
private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) {
// 简单的select查询
if (selectBody instanceof PlainSelect) {
SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody);
PlainSelect plainSelect = (PlainSelect) selectBody;
FromItem fromItem = plainSelect.getFromItem();
// 解析 aliasName
if (fromItem.getAlias() != null) {
sqlInfo.setFromTableAliasName(fromItem.getAlias().getName());
}
// 解析 表名
if (fromItem instanceof Table) {
// 通过表名的方式from
Table fromTable = (Table) fromItem;
sqlInfo.setFromTableName(fromTable.getName());
} else if (fromItem instanceof SubSelect) {
// 通过子查询的方式from
SubSelect fromSubSelect = (SubSelect) fromItem;
SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(fromSubSelect.getSelectBody());
sqlInfo.setFromSubSelect(subSqlInfo);
}
// 解析 selectFields
List<SelectItem> selectItems = plainSelect.getSelectItems();
for (SelectItem selectItem : selectItems) {
if (selectItem instanceof AllColumns || selectItem instanceof AllTableColumns) {
// 全部字段
sqlInfo.setSelectAll(true);
sqlInfo.setSelectFields(null);
sqlInfo.setRealSelectFields(null);
break;
} else if (selectItem instanceof SelectExpressionItem) {
// 获取单个查询字段名
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
Expression expression = selectExpressionItem.getExpression();
Alias alias = selectExpressionItem.getAlias();
JSqlParserUtils.handleExpression(sqlInfo, expression, alias);
}
}
return sqlInfo;
} else {
log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName());
throw new JeecgBootException("暂时尚未处理该类型的 SelectBody");
}
}
/**
* 处理查询字段表达式
*
* @param sqlInfo
* @param expression
* @param alias 是否有别名无传null
*/
private static void handleExpression(SelectSqlInfo sqlInfo, Expression expression, Alias alias) {
// 处理函数式字段 CONCAT(name,'(',age,')')
if (expression instanceof Function) {
JSqlParserUtils.handleFunctionExpression((Function) expression, sqlInfo);
return;
}
// 处理字段上的子查询
if (expression instanceof SubSelect) {
SubSelect subSelect = (SubSelect) expression;
SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(subSelect.getSelectBody());
// 注:字段上的子查询,必须只查询一个字段,否则会报错,所以可以放心合并
sqlInfo.getSelectFields().addAll(subSqlInfo.getSelectFields());
sqlInfo.getRealSelectFields().addAll(subSqlInfo.getAllRealSelectFields());
return;
}
// 不处理字面量
if (expression instanceof StringValue ||
expression instanceof NullValue ||
expression instanceof LongValue ||
expression instanceof DoubleValue ||
expression instanceof HexValue ||
expression instanceof DateValue ||
expression instanceof TimestampValue ||
expression instanceof TimeValue
) {
return;
}
// 查询字段名
String selectField = expression.toString();
// 实际查询字段名
String realSelectField = selectField;
// 判断是否有别名
if (alias != null) {
selectField = alias.getName();
}
// 获取真实字段名
if (expression instanceof Column) {
Column column = (Column) expression;
realSelectField = column.getColumnName();
}
sqlInfo.addSelectField(selectField, realSelectField);
}
/**
* 处理函数式字段
*
* @param functionExp
* @param sqlInfo
*/
private static void handleFunctionExpression(Function functionExp, SelectSqlInfo sqlInfo) {
List<Expression> expressions = functionExp.getParameters().getExpressions();
for (Expression expression : expressions) {
JSqlParserUtils.handleExpression(sqlInfo, expression, null);
}
}
}

View File

@ -1,101 +0,0 @@
package org.jeecg.common.util.sqlparse.vo;
import lombok.Data;
import net.sf.jsqlparser.statement.select.SelectBody;
import java.util.HashSet;
import java.util.Set;
/**
* select 查询 sql 的信息
*/
@Data
public class SelectSqlInfo {
/**
* 查询的表名如果是子查询则此处为null
*/
private String fromTableName;
/**
* 表别名
*/
private String fromTableAliasName;
/**
* 通过子查询获取的表信息例如select name from (select * from user) u
* 如果不是子查询则为null
*/
private SelectSqlInfo fromSubSelect;
/**
* 查询的字段集合,如果是 * 则为null如果设了别名则为别名
*/
private Set<String> selectFields;
/**
* 真实的查询字段集合,如果是 * 则为null如果设了别名则为原始字段名
*/
private Set<String> realSelectFields;
/**
* 是否是查询所有字段
*/
private boolean selectAll;
/**
* 解析之后的 SQL (关键字都是大写)
*/
private final String parsedSql;
public SelectSqlInfo(String parsedSql) {
this.parsedSql = parsedSql;
}
public SelectSqlInfo(SelectBody selectBody) {
this.parsedSql = selectBody.toString();
}
public void addSelectField(String selectField, String realSelectField) {
if (this.selectFields == null) {
this.selectFields = new HashSet<>();
}
if (this.realSelectFields == null) {
this.realSelectFields = new HashSet<>();
}
this.selectFields.add(selectField);
this.realSelectFields.add(realSelectField);
}
/**
* 获取所有字段,包括子查询里的。
*
* @return
*/
public Set<String> getAllRealSelectFields() {
Set<String> fields = new HashSet<>();
// 递归获取所有字段,起个直观的方法名为:
this.recursiveGetAllFields(this, fields);
return fields;
}
/**
* 递归获取所有字段
*/
private void recursiveGetAllFields(SelectSqlInfo sqlInfo, Set<String> fields) {
if (!sqlInfo.isSelectAll() && sqlInfo.getRealSelectFields() != null) {
fields.addAll(sqlInfo.getRealSelectFields());
}
if (sqlInfo.getFromSubSelect() != null) {
recursiveGetAllFields(sqlInfo.getFromSubSelect(), fields);
}
}
@Override
public String toString() {
return "SelectSqlInfo{" +
"fromTableName='" + fromTableName + '\'' +
", fromSubSelect=" + fromSubSelect +
", aliasName='" + fromTableAliasName + '\'' +
", selectFields=" + selectFields +
", realSelectFields=" + realSelectFields +
", selectAll=" + selectAll +
"}";
}
}

View File

@ -1,147 +0,0 @@
package org.jeecg.config;
import org.jeecg.config.vo.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 加载项目配置
* @author: jeecg-boot
*/
@Component("jeecgBaseConfig")
@ConfigurationProperties(prefix = "jeecg")
public class JeecgBaseConfig {
/**
* 签名密钥串(字典等敏感接口)
* @TODO 降低使用成本加的默认值,实际以 yml配置 为准
*/
private String signatureSecret = "dd05f1c54d63749eda95f9fa6d49v442a";
/**
* 需要加强校验的接口清单
*/
private String signUrls;
/**
* 上传模式
* 本地local\Miniominio\阿里云alioss
*/
private String uploadType;
/**
* 平台安全模式配置
*/
private Firewall firewall;
/**
* shiro拦截排除
*/
private Shiro shiro;
/**
* 上传文件配置
*/
private Path path;
/**
* 前端页面访问地址
* pc: http://localhost:3100
* app: http://localhost:8051
*/
private DomainUrl domainUrl;
/**
* 文件预览
*/
private String fileViewDomain;
/**
* ES配置
*/
private Elasticsearch elasticsearch;
/**
* 微信支付
* @return
*/
private WeiXinPay weiXinPay;
public Elasticsearch getElasticsearch() {
return elasticsearch;
}
public void setElasticsearch(Elasticsearch elasticsearch) {
this.elasticsearch = elasticsearch;
}
public Firewall getFirewall() {
return firewall;
}
public void setFirewall(Firewall firewall) {
this.firewall = firewall;
}
public String getSignatureSecret() {
return signatureSecret;
}
public void setSignatureSecret(String signatureSecret) {
this.signatureSecret = signatureSecret;
}
public Shiro getShiro() {
return shiro;
}
public void setShiro(Shiro shiro) {
this.shiro = shiro;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public DomainUrl getDomainUrl() {
return domainUrl;
}
public void setDomainUrl(DomainUrl domainUrl) {
this.domainUrl = domainUrl;
}
public String getSignUrls() {
return signUrls;
}
public void setSignUrls(String signUrls) {
this.signUrls = signUrls;
}
public String getFileViewDomain() {
return fileViewDomain;
}
public void setFileViewDomain(String fileViewDomain) {
this.fileViewDomain = fileViewDomain;
}
public String getUploadType() {
return uploadType;
}
public void setUploadType(String uploadType) {
this.uploadType = uploadType;
}
public WeiXinPay getWeiXinPay() {
return weiXinPay;
}
public void setWeiXinPay(WeiXinPay weiXinPay) {
this.weiXinPay = weiXinPay;
}
}

View File

@ -1,179 +0,0 @@
package org.jeecg.config;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.constant.CommonConstant;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author scott
*/
@Configuration
@EnableSwagger2WebMvc
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Config implements WebMvcConfigurer {
/**
*
* 显示swagger-ui.html文档展示页还必须注入swagger资源
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* swagger2的配置文件这里可以配置swagger2的一些基本的内容比如扫描的包等等
*
* @return Docket
*/
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//此包路径下的类,才生成接口文档
.apis(RequestHandlerSelectors.basePackage("org.jeecg"))
//加了ApiOperation注解的类才生成接口文档
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(securityScheme()))
.securityContexts(securityContexts())
.globalOperationParameters(setHeaderToken());
}
/***
* oauth2配置
* 需要增加swagger授权回调地址
* http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
* @return
*/
@Bean
SecurityScheme securityScheme() {
return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header");
}
/**
* JWT token
* @return
*/
private List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return pars;
}
/**
* api文档的详细信息函数,注意这里的注解引用的是哪个
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// //大标题
.title("JeecgBoot 后台服务API接口文档")
// 版本号
.version("1.0")
// .termsOfServiceUrl("NO terms of service")
// 描述
.description("后台API接口")
// 作者
.contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com"))
.license("The Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
/**
* 新增 securityContexts 保持登录状态
*/
private List<SecurityContext> securityContexts() {
return new ArrayList(
Collections.singleton(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build())
);
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return new ArrayList(
Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes)));
}
/**
* 解决springboot2.6 和springfox不兼容问题
* @return
*/
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}

View File

@ -1,19 +0,0 @@
package org.jeecg.config.firewall.interceptor;
import org.jeecg.config.firewall.interceptor.enums.LowCodeUrlsEnum;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class LowCodeModeConfiguration implements WebMvcConfigurer {
public LowCodeModeInterceptor payInterceptor() {
return new LowCodeModeInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(payInterceptor()).addPathPatterns(LowCodeUrlsEnum.getLowCodeInterceptUrls());
}
}

View File

@ -1,16 +0,0 @@
package org.jeecg.config.shiro;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 免认证注解认证系统结合spring MVC的@RequestMapping获取请求路径进行免登录配置
* @author eightmonth@qq.com
* @date 2024/2/28 9:58
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreAuth {
}

View File

@ -1,104 +0,0 @@
package org.jeecg.config.shiro.ignore;
import lombok.AllArgsConstructor;
import org.jeecg.config.shiro.IgnoreAuth;
import org.springframework.aop.framework.Advised;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;
import java.lang.reflect.Method;
import java.util.*;
/**
* 在spring boot初始化时根据@RestController注解获取当前spring容器中的bean
* @author eightmonth@qq.com
* @date 2024/4/18 11:35
*/
@Component
@AllArgsConstructor
public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
List<String> ignoreAuthUrls = new ArrayList<>();
if (event.getApplicationContext().getParent() == null) {
// 只处理根应用上下文的事件,避免在子上下文中重复处理
Map<String, Object> restControllers = applicationContext.getBeansWithAnnotation(RestController.class);
for (Object restController : restControllers.values()) {
// 如 online系统的controller并不是spring 默认生成
if (restController instanceof Advised) {
ignoreAuthUrls.addAll(postProcessRestController(restController));
}
}
}
if (!CollectionUtils.isEmpty(ignoreAuthUrls)) {
InMemoryIgnoreAuth.set(ignoreAuthUrls);
}
}
private List<String> postProcessRestController(Object restController) {
List<String> ignoreAuthUrls = new ArrayList<>();
Class<?> clazz = ((Advised) restController).getTargetClass();
RequestMapping base = clazz.getAnnotation(RequestMapping.class);
String[] baseUrl = Objects.nonNull(base) ? base.value() : new String[]{};
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(GetMapping.class)) {
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PostMapping.class)) {
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PutMapping.class)) {
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(DeleteMapping.class)) {
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PatchMapping.class)) {
PatchMapping requestMapping = method.getAnnotation(PatchMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
}
}
return ignoreAuthUrls;
}
private List<String> rebuildUrl(String[] bases, String[] uris) {
List<String> urls = new ArrayList<>();
if (bases.length > 0) {
for (String base : bases) {
for (String uri : uris) {
urls.add(prefix(base) + prefix(uri));
}
}
} else {
Arrays.stream(uris).forEach(uri -> {
urls.add(prefix(uri));
});
}
return urls;
}
private String prefix(String seg) {
return seg.startsWith("/") ? seg : "/"+seg;
}
}

View File

@ -1,39 +0,0 @@
package org.jeecg.config.vo;
/**
* 平台安全配置
*
* @author: scott
* @date: 2023年09月05日 9:25
*/
public class Firewall {
/**
* 数据源安全 (开启后Online报表和图表的数据源为必填)
*/
private Boolean dataSourceSafe = false;
/**
* 低代码模式dev:开发模式prod:发布模式——关闭所有在线开发配置能力)
*/
private String lowCodeMode;
// /**
// * 表字典安全模式white:白名单——配置了白名单的表才能通过表字典方式访问black:黑名单——配置了黑名单的表不允许表字典方式访问)
// */
// private String tableDictMode;
public Boolean getDataSourceSafe() {
return dataSourceSafe;
}
public void setDataSourceSafe(Boolean dataSourceSafe) {
this.dataSourceSafe = dataSourceSafe;
}
public String getLowCodeMode() {
return lowCodeMode;
}
public void setLowCodeMode(String lowCodeMode) {
this.lowCodeMode = lowCodeMode;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,75 +0,0 @@
package org.jeecg.test.sqlinjection;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import org.jeecg.common.util.SqlInjectionUtil;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* SQL注入攻击检查测试
* @author: liusq
* @date: 2023年09月08日
*/
@Slf4j
public class TestInjectWithSqlParser {
/**
* 注入测试
*
* @param sql
* @return
*/
private boolean isExistSqlInject(String sql) {
try {
SqlInjectionUtil.specialFilterContentForOnlineReport(sql);
return false;
} catch (Exception e) {
log.info("===================================================");
return true;
}
}
@Test
public void test() throws JSQLParserException {
//不存在sql注入
assertFalse(isExistSqlInject("select * from fm_time where dept_id=:sqlparamsmap.id and time=:sqlparamsmap.time"));
assertFalse(isExistSqlInject("select * from test"));
assertFalse(isExistSqlInject("select load_file(\"C:\\\\benben.txt\")"));
assertFalse(isExistSqlInject("WITH SUB1 AS (SELECT user FROM t1) SELECT * FROM T2 WHERE id > 123 "));
//存在sql注入
assertTrue(isExistSqlInject("or 1= 1 --"));
assertTrue(isExistSqlInject("select * from test where sleep(%23)"));
assertTrue(isExistSqlInject("select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));"));
assertTrue(isExistSqlInject("select * from users;show databases;"));
assertTrue(isExistSqlInject("select * from dc_device where id=1 and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13"));
assertTrue(isExistSqlInject("update user set name = '123'"));
assertTrue(isExistSqlInject("SELECT * FROM users WHERE username = 'admin' AND password = '123456' OR 1=1;--"));
assertTrue(isExistSqlInject("select * from users where id=1 and (select count(*) from information_schema.tables where table_schema='数据库名')>4 %23"));
assertTrue(isExistSqlInject("select * from dc_device where sleep(5) %23"));
assertTrue(isExistSqlInject("select * from dc_device where id in (select id from other)"));
assertTrue(isExistSqlInject("select * from dc_device where id in (select id from other)"));
assertTrue(isExistSqlInject("select * from dc_device where 2=2.0 or 2 != 4"));
assertTrue(isExistSqlInject("select * from dc_device where 1!=2.0"));
assertTrue(isExistSqlInject("select * from dc_device where id=floor(2.0)"));
assertTrue(isExistSqlInject("select * from dc_device where not true"));
assertTrue(isExistSqlInject("select * from dc_device where 1 or id > 0"));
assertTrue(isExistSqlInject("select * from dc_device where 'tom' or id > 0"));
assertTrue(isExistSqlInject("select * from dc_device where '-2.3' "));
assertTrue(isExistSqlInject("select * from dc_device where 2 "));
assertTrue(isExistSqlInject("select * from dc_device where (3+2) "));
assertTrue(isExistSqlInject("select * from dc_device where -1 IS TRUE"));
assertTrue(isExistSqlInject("select * from dc_device where 'hello' is null "));
assertTrue(isExistSqlInject("select * from dc_device where '2022-10-31' and id > 0"));
assertTrue(isExistSqlInject("select * from dc_device where id > 0 or 1!=2.0 "));
assertTrue(isExistSqlInject("select * from dc_device where id > 0 or 1 in (1,3,4) "));
assertTrue(isExistSqlInject("select * from dc_device UNION select name from other"));
assertTrue(isExistSqlInject("(SELECT 6240 FROM (SELECT(SLEEP(5))and 1=2)vidl)"));
}
}

View File

@ -1,50 +0,0 @@
package org.jeecg.test.sqlinjection;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import org.jeecg.common.util.SqlInjectionUtil;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* SQL注入攻击检查测试
* @author: liusq
* @date: 2023年09月08日
*/
@Slf4j
public class TestSqlInjectForDict {
/**
* 注入测试
*
* @param sql
* @return
*/
private boolean isExistSqlInject(String sql) {
try {
SqlInjectionUtil.specialFilterContentForDictSql(sql);
return false;
} catch (Exception e) {
log.info("===================================================");
return true;
}
}
@Test
public void test() throws JSQLParserException {
//不存在sql注入
assertFalse(isExistSqlInject("sys_user,realname,id"));
assertFalse(isExistSqlInject("oa_officialdoc_organcode,organ_name,id"));
assertFalse(isExistSqlInject("onl_cgform_head where table_type!=3 and copy_type=0,table_txt,table_name"));
assertFalse(isExistSqlInject("onl_cgform_head where copy_type = 0,table_txt,table_name"));
//存在sql注入
assertTrue(isExistSqlInject("or 1= 1 --"));
assertTrue(isExistSqlInject("select * from test where sleep(%23)"));
}
}

View File

@ -1,60 +0,0 @@
package org.jeecg.test.sqlinjection;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import org.jeecg.common.util.SqlInjectionUtil;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* SQL注入攻击检查测试
* @author: liusq
* @date: 2023年09月08日
*/
@Slf4j
public class TestSqlInjectForOnlineReport {
/**
* 注入测试
*
* @param sql
* @return
*/
private boolean isExistSqlInject(String sql) {
try {
SqlInjectionUtil.specialFilterContentForOnlineReport(sql);
return false;
} catch (Exception e) {
log.info("===================================================");
return true;
}
}
@Test
public void test() throws JSQLParserException {
//不存在sql注入
assertFalse(isExistSqlInject("select * from fm_time where dept_id=:sqlparamsmap.id and time=:sqlparamsmap.time"));
assertFalse(isExistSqlInject("select * from test"));
assertFalse(isExistSqlInject("select load_file(\"C:\\\\benben.txt\")"));
assertFalse(isExistSqlInject("select * from dc_device where id in (select id from other)"));
assertFalse(isExistSqlInject("select * from dc_device UNION select name from other"));
//存在sql注入
assertTrue(isExistSqlInject("(SELECT 6240 FROM (SELECT(SLEEP(5))and 1=2)vidl)"));
assertTrue(isExistSqlInject("or 1= 1 --"));
assertTrue(isExistSqlInject("select * from test where sleep(%23)"));
assertTrue(isExistSqlInject("select * from test where SLEEP(3)"));
assertTrue(isExistSqlInject("select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));"));
assertTrue(isExistSqlInject("select * from users;show databases;"));
assertTrue(isExistSqlInject("select * from dc_device where id=1 and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13"));
assertTrue(isExistSqlInject("update user set name = '123'"));
assertTrue(isExistSqlInject("SELECT * FROM users WHERE username = 'admin' AND password = '123456' OR 1=1;--"));
assertTrue(isExistSqlInject("select * from users where id=1 and (select count(*) from information_schema.tables where table_schema='数据库名')>4 %23"));
assertTrue(isExistSqlInject("select * from dc_device where sleep(5) %23"));
}
}

View File

@ -1,103 +0,0 @@
package org.jeecg.test.sqlinjection;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import org.jeecg.common.util.SqlInjectionUtil;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* @Description: SQL注入测试类
* @author: scott
* @date: 2023年08月14日 9:55
*/
public class TestSqlInjection {
/**
* 表名带别名同时有html编码字符
*/
@Test
public void testSpecialSQL() {
String tableName = "sys_user t";
//解决使用参数tableName=sys_user t&复测,漏洞仍然存在
if (tableName.contains(" ")) {
tableName = tableName.substring(0, tableName.indexOf(" "));
}
//【issues/4393】 sys_user , (sys_user), sys_user%20, %60sys_user%60
String reg = "\\s+|\\(|\\)|`";
tableName = tableName.replaceAll(reg, "");
System.out.println(tableName);
}
/**
* 测试sql是否含sql注入风险
* <p>
* mybatis plus的方法
*/
@Test
public void sqlInjectionCheck() {
String sql = "select * from sys_user";
System.out.println(SqlInjectionUtils.check(sql));
}
/**
* 测试sql是否有SLEEP风险
* <p>
* mybatisPlus的方法
*/
@Test
public void sqlSleepCheck() {
SqlInjectionUtil.checkSqlAnnotation("(SELECT 6240 FROM (SELECT(SLEEP(5))and 1=2)vidl)");
}
/**
* 测试sql是否含sql注入风险
* <p>
* 自定义方法
*/
@Test
public void sqlInjectionCheck2() {
String sql = "select * from sys_user";
SqlInjectionUtil.specialFilterContentForOnlineReport(sql);
}
/**
* 字段定义只能是是字母 数字 下划线的组合(不允许有空格、转义字符串等)
* <p>
* 判断字段名是否符合规范
*/
@Test
public void testFieldSpecification() {
List<String> list = new ArrayList();
list.add("Hello World!");
list.add("Hello%20World!");
list.add("HelloWorld!");
list.add("Hello World");
list.add("age");
list.add("user_name");
list.add("user_name%20");
list.add("user_name%20 ");
for (String input : list) {
boolean containsSpecialChars = isValidString(input);
System.out.println("input:" + input + " ,包含空格和特殊字符: " + containsSpecialChars);
}
}
/**
* 字段定义只能是是字母 数字 下划线的组合(不允许有空格、转义字符串等)
*
* @param input
* @return
*/
private static boolean isValidString(String input) {
Pattern pattern = Pattern.compile("^[a-zA-Z0-9_]+$");
return pattern.matcher(input).matches();
}
}

View File

@ -1,109 +0,0 @@
package org.jeecg.test.sqlparse;
import net.sf.jsqlparser.JSQLParserException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.JSqlParserUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import org.junit.Test;
import java.util.Map;
/**
* 针对 JSqlParserUtils 的单元测试
*/
public class JSqlParserUtilsTest {
private static final String[] sqlList = new String[]{
"select * from sys_user",
"select u.* from sys_user u",
"select u.*, c.name from sys_user u, demo c",
"select u.age, c.name from sys_user u, demo c",
"select sex, age, c.name from sys_user, demo c",
// 别名测试
"select username as realname from sys_user",
"select username as realname, u.realname as aaa, u.id bbb from sys_user u",
// 不存在真实地查询字段
"select count(1) from sys_user",
// 函数式字段
"select max(sex), id from sys_user",
// 复杂嵌套函数式字段
"select CONCAT(CONCAT(' _ ', sex), ' - ' , birthday) as info, id from sys_user",
// 更复杂的嵌套函数式字段
"select CONCAT(CONCAT(101,'_',NULL, DATE(create_time),'_',sex),' - ',birthday) as info, id from sys_user",
// 子查询SQL
"select u.name1 as name2 from (select username as name1 from sys_user) u",
// 多层嵌套子查询SQL
"select u2.name2 as name3 from (select u1.name1 as name2 from (select username as name1 from sys_user) u1) u2",
// 字段子查询SQL
"select id, (select username as name1 from sys_user u2 where u1.id = u2.id) as name2 from sys_user u1",
// 带条件的SQL不解析where条件里的字段但不影响解析查询字段
"select username as name1 from sys_user where realname LIKE '%张%'",
// 多重复杂关联表查询解析包含的表为sys_user, sys_depart, sys_dict_item, demo
"" +
"SELECT " +
" u.*, d.age, sd.item_text AS sex, (SELECT count(sd.id) FROM sys_depart sd) AS count " +
"FROM " +
" (SELECT sd.username AS foo, sd.realname FROM sys_user sd) u, " +
" demo d " +
"LEFT JOIN sys_dict_item AS sd ON d.sex = sd.item_value " +
"WHERE sd.dict_id = '3d9a351be3436fbefb1307d4cfb49bf2'",
};
@Test
public void testParseSelectSql() {
System.out.println("-----------------------------------------");
for (String sql : sqlList) {
System.out.println("待测试的sql" + sql);
try {
// 解析所有的表名key=表名value=解析后的sql信息
Map<String, SelectSqlInfo> parsedMap = JSqlParserUtils.parseAllSelectTable(sql);
assert parsedMap != null;
for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) {
System.out.println("表名:" + entry.getKey());
this.printSqlInfo(entry.getValue(), 1);
}
} catch (JSQLParserException e) {
System.out.println("SQL解析出现异常" + e.getMessage());
}
System.out.println("-----------------------------------------");
}
}
private void printSqlInfo(SelectSqlInfo sqlInfo, int level) {
String beforeStr = this.getBeforeStr(level);
if (sqlInfo.getFromTableName() == null) {
// 子查询
System.out.println(beforeStr + "子查询:" + sqlInfo.getFromSubSelect().getParsedSql());
this.printSqlInfo(sqlInfo.getFromSubSelect(), level + 1);
} else {
// 非子查询
System.out.println(beforeStr + "查询的表名:" + sqlInfo.getFromTableName());
}
if (oConvertUtils.isNotEmpty(sqlInfo.getFromTableAliasName())) {
System.out.println(beforeStr + "查询的表别名:" + sqlInfo.getFromTableAliasName());
}
if (sqlInfo.isSelectAll()) {
System.out.println(beforeStr + "查询的字段:*");
} else {
System.out.println(beforeStr + "查询的字段:" + sqlInfo.getSelectFields());
System.out.println(beforeStr + "真实的字段:" + sqlInfo.getRealSelectFields());
if (sqlInfo.getFromTableName() == null) {
System.out.println(beforeStr + "所有的字段(包括子查询):" + sqlInfo.getAllRealSelectFields());
}
}
}
// 打印前缀,根据层级来打印
private String getBeforeStr(int level) {
if (level == 0) {
return "";
}
StringBuilder beforeStr = new StringBuilder();
for (int i = 0; i < level; i++) {
beforeStr.append(" ");
}
beforeStr.append("- ");
return beforeStr.toString();
}
}

15
jeecg-boot/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
## ide
**/.idea
*.iml
rebel.xml
## backend
**/target
**/logs
## front
**/*.lock
os_del.cmd
os_del_doc.cmd
.svn
derby.log

201
jeecg-boot/LICENSE Normal file
View File

@ -0,0 +1,201 @@
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.

13
jeecg-boot/db/Dockerfile Normal file
View File

@ -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 ./jeecgai-mysql-5.7.sql /docker-entrypoint-initdb.d
COPY ./tables_xxl_job.sql /docker-entrypoint-initdb.d

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,82 @@
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:
- 13306: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-pgvector:
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/pgvector
container_name: jeecg-boot-pgvector
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: vector_db
# ports:
# - 5432:5432
restart: always
networks:
- jeecg-boot
# jeecg-boot-rabbitmq:
# image: rabbitmq:3.7.7-management
## ports:
## - 5672:5672
## - 15672:15672
# restart: always
# container_name: jeecg-boot-rabbitmq
# hostname: jeecg-boot-rabbitmq
# environment:
# RABBITMQ_DEFAULT_USER: guest
# RABBITMQ_DEFAULT_PASS: guest
# networks:
# - jeecg-boot
jeecg-boot-system:
build:
context: ./jeecg-module-system/jeecg-system-start
restart: on-failure
mac_address: 02:42:ac:11:00:02
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
volumes:
- ./config:/jeecg-boot/config
networks:
jeecg-boot:
name: jeecg_boot

View File

@ -0,0 +1,399 @@
<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.boot3</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.9.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.boot3</groupId>
<artifactId>jeecg-boot-common</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--集成springmvc框架并实现自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- minidao -->
<dependency>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>minidao-spring-boot-starter-jsqlparser-4.9</artifactId>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-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>mssql-jdbc</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>${kingbase8.version}</version>
<scope>runtime</scope>
</dependency>
<!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</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>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<!-- 排除仍使用了javax.servlet的依赖 -->
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入适配jakarta的依赖包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
</exclusions>
</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>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-ui</artifactId>
<version>${knife4j-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.7.0</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-spring-boot-3-starter</artifactId>
</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>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
</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>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclusion>
</exclusions>
</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.boot3</groupId>
<artifactId>jeecg-boot-starter-chatgpt</artifactId>
</dependency>
<!-- 腾讯云 -->
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
<version>${tencentcloud-sdk-java-sms.version}</version>
<exclusions>
<exclusion>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -1,5 +1,6 @@
package org.jeecg.common.api;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.system.vo.*;
import java.util.List;
@ -19,6 +20,13 @@ public interface CommonAPI {
*/
Set<String> queryUserRoles(String username);
/**
* 1查询用户角色信息
* @param userId
* @return
*/
Set<String> queryUserRolesById(String userId);
/**
* 2查询用户权限信息
@ -50,6 +58,13 @@ public interface CommonAPI {
*/
public LoginUser getUserByName(String username);
/**
* 5根据用户账号查询用户Id
* @param username
* @return
*/
public String getUserIdByName(String username);
/**
* 6字典表的 翻译
@ -117,7 +132,6 @@ public interface CommonAPI {
*/
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 15 字典表的 翻译可批量
* @param table
@ -128,6 +142,16 @@ public interface CommonAPI {
* @return
*/
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 16 运行AIRag流程
* for [QQYUN-13634]在baseapi里面封装方法方便其他模块调用
*
* @param airagFlowDTO
* @return 流程执行结果,可能是String或者Map
* @author chenrui
* @date 2025/9/2 11:43
*/
Object runAiragFlow(AiragFlowDTO airagFlowDTO);
}

View File

@ -0,0 +1,36 @@
package org.jeecg.common.api.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* 调用AI流程入参
* for [QQYUN-13634]在baseapi里面封装方法方便其他模块调用
* @author chenrui
* @date 2025/9/2 14:11
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class AiragFlowDTO implements Serializable {
private static final long serialVersionUID = 7431775881170684867L;
/**
* 流程id
*/
private String flowId;
/**
* 输入参数
*/
private Map<String, Object> inputParams;
}

View File

@ -0,0 +1,48 @@
package org.jeecg.common.api.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 流程审批意见DTO
* @author scott
* @date 2025-01-29
*/
@Data
public class ApprovalCommentDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务ID
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 审批人ID
*/
private String approverId;
/**
* 审批人姓名
*/
private String approverName;
/**
* 审批意见
*/
private String approvalComment;
/**
* 审批时间
*/
private Date approvalTime;
}

View File

@ -2,7 +2,7 @@ package org.jeecg.common.api.dto;
import lombok.Data;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import java.io.Serializable;
/**

View File

@ -1,5 +1,6 @@
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;
@ -55,6 +56,11 @@ public class LogDTO implements Serializable {
*/
private Integer tenantId;
/**
* 客户终端类型 pc:电脑端 app:手机端 h5:移动网页端
*/
private String clientType;
public LogDTO(){
}

View File

@ -0,0 +1,47 @@
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;
/**
* online工单的地址
*/
private String onlineWorkOrderUrl;
public OnlineAuthDTO(){
}
public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl){
this.username = username;
this.possibleUrl = possibleUrl;
this.onlineFormUrl = onlineFormUrl;
}
}

View File

@ -0,0 +1,55 @@
package org.jeecg.common.api.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 移动端消息推送
* @author liusq
* @date 2025/11/12 14:11
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PushMessageDTO implements Serializable {
private static final long serialVersionUID = 7431775881170684867L;
/**
* 消息标题
*/
private String title;
/**
* 消息内容
*/
private String content;
/**
* 推送形式all全推送 single单用户推送
*/
private String pushType;
/**
* 用户名usernameList
*/
List<String> usernames;
/**
* 用户名idList
*/
List<String> userIds;
/**
* 消息附加参数
*/
Map<String,Object> payload;
}

View File

@ -84,8 +84,20 @@ public class MessageDTO implements Serializable {
* 邮件抄送地址
*/
protected Set<String> ccEmailList;
/**
* 是否为定时任务推送email
*/
private Boolean isTimeJob = false;
//---邮件相关参数-------------------------------------------------------------
/**
* 枚举org.jeecg.common.constant.enums.NoticeTypeEnum
* 通知类型(system:系统消息file:知识库flow:流程plan:日程计划meeting:会议)
*/
private String noticeType;
public MessageDTO(){
}

View File

@ -1,8 +1,8 @@
package org.jeecg.common.api.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.jeecg.common.constant.CommonConstant;
@ -15,7 +15,7 @@ import java.io.Serializable;
* @date 2019年1月19日
*/
@Data
@ApiModel(value="接口返回对象", description="接口返回对象")
@Schema(description="接口返回对象")
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ -23,31 +23,31 @@ public class Result<T> implements Serializable {
/**
* 成功标志
*/
@ApiModelProperty(value = "成功标志")
@Schema(description = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
@Schema(description = "返回处理消息")
private String message = "";
/**
* 返回代码
*/
@ApiModelProperty(value = "返回代码")
@Schema(description = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
@Schema(description = "返回数据对象")
private T result;
/**
* 时间戳
*/
@ApiModelProperty(value = "时间戳")
@Schema(description = "时间戳")
private long timestamp = System.currentTimeMillis();
public Result() {

View File

@ -20,14 +20,14 @@ 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.core.StandardReflectionParameterNameDiscoverer;
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 jakarta.annotation.Resource;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
@ -121,9 +121,8 @@ public class AutoLogAspect {
if (operateType > 0) {
return operateType;
}
//update-begin---author:wangshuai ---date:20220331 for阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
// 代码逻辑说明: 阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
return OperateTypeEnum.getTypeByMethodName(methodName);
//update-end---author:wangshuai ---date:20220331 for阿里云代码扫描规范(不允许任何魔法值出现在代码中)------------
}
/**
@ -143,14 +142,15 @@ public class AutoLogAspect {
// 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) {
if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile || 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
//MultipartFile和MultipartFile[]不能序列化从入参里排除
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) {
@ -165,14 +165,13 @@ public class AutoLogAspect {
}
};
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();
StandardReflectionParameterNameDiscoverer u= new StandardReflectionParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
for (int i = 0; i < args.length; i++) {

View File

@ -52,7 +52,9 @@ public class DictAspect {
/**
* 定义切点Pointcut
*/
@Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..)) || @annotation(org.jeecg.common.aspect.annotation.AutoDict)")
@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() {
}
@ -92,7 +94,8 @@ public class DictAspect {
* @param result
*/
private Object parseDictText(Object result) {
if (result instanceof Result) {
//if (result instanceof Result) {
if (true) {
if (((Result) result).getResult() instanceof IPage) {
List<JSONObject> items = new ArrayList<>();
@ -102,29 +105,24 @@ public class DictAspect {
Map<String, List<String>> dataListMap = new HashMap<>(5);
//取出结果集
List<Object> records=((IPage) ((Result) result).getResult()).getRecords();
//update-begin--Author:zyf -- Date:20220606 ----forVUEN-1230 判断是否含有字典注解,没有注解返回-----
// 代码逻辑说明: VUEN-1230 判断是否含有字典注解,没有注解返回-----
Boolean hasDict= checkHasDict(records);
if(!hasDict){
return result;
}
log.debug(" __ 进入字典翻译切面 DictAspect —— " );
//update-end--Author:zyf -- Date:20220606 ----forVUEN-1230 判断是否含有字典注解,没有注解返回-----
for (Object record : records) {
String json="{}";
try {
//update-begin--Author:zyf -- Date:20220531 ----forissues/#3629 DictAspect Jackson序列化报错-----
//解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
json = objectMapper.writeValueAsString(record);
//update-end--Author:zyf -- Date:20220531 ----forissues/#3629 DictAspect Jackson序列化报错-----
} catch (JsonProcessingException e) {
log.error("json解析失败"+e.getMessage(),e);
}
//update-begin--Author:scott -- Date:20211223 ----forissues/3303restcontroller返回json数据后key顺序错乱 -----
// 代码逻辑说明: issues/3303restcontroller返回json数据后key顺序错乱 -----
JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);
//update-end--Author:scott -- Date:20211223 ----forissues/3303restcontroller返回json数据后key顺序错乱 -----
//update-begin--Author:scott -- Date:20190603 ----for解决继承实体字段无法翻译问题------
//for (Field field : record.getClass().getDeclaredFields()) {
// 遍历所有字段把字典Code取出来放到 map
for (Field field : oConvertUtils.getAllFields(record)) {
@ -132,7 +130,6 @@ public class DictAspect {
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);
@ -140,26 +137,22 @@ public class DictAspect {
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]解决分布式下表字典跨库无法查询问题------------
// 代码逻辑说明: [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]解决分布式下表字典跨库无法查询问题------------
// 代码逻辑说明: [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 ----forissues/#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 ----forissues/#3629 DictAspect Jackson序列化报错-----
}
items.add(item);
}
@ -173,15 +166,12 @@ public class DictAspect {
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]解决分布式下表字典跨库无法查询问题------------
// 代码逻辑说明: [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());
@ -283,25 +273,20 @@ public class DictAspect {
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);
@ -310,10 +295,8 @@ public class DictAspect {
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);
}
@ -397,7 +380,7 @@ public class DictAspect {
if (k.trim().length() == 0) {
continue; //跳过循环
}
//update-begin--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
// 代码逻辑说明: !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());
@ -422,7 +405,6 @@ public class DictAspect {
tmpValue = commonApi.translateDict(code, k.trim());
}
}
//update-end--Author:scott -- Date:20210531 ----for !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
if (tmpValue != null) {
if (!"".equals(textValue.toString())) {

View File

@ -21,7 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
@ -57,7 +57,6 @@ public class PermissionDataAspect {
String requestMethod = request.getMethod();
String requestPath = request.getRequestURI().substring(request.getContextPath().length());
requestPath = filterUrl(requestPath);
//update-begin-author:taoyan date:20211027 for:JTC-132online报表权限online报表带参数的菜单配置数据权限无效
//先判断是否online报表请求
if(requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl())>=0 || requestPath.indexOf(UrlMatchEnum.CGREPORT_ONLY_DATA.getMatchUrl())>=0){
// 获取地址栏参数
@ -66,7 +65,6 @@ public class PermissionDataAspect {
requestPath+="?"+urlParamString;
}
}
//update-end-author:taoyan date:20211027 for:JTC-132online报表权限online报表带参数的菜单配置数据权限无效
log.debug("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod);
String username = JwtUtil.getUserNameByToken(request);
//查询数据权限信息

View File

@ -41,7 +41,6 @@ public @interface Dict {
String dictTable() default "";
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 方法描述: 数据字典表所在数据源名称
* chenrui
@ -50,5 +49,4 @@ public @interface Dict {
* @return 返回类型 String
*/
String ds() default "";
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
}

View File

@ -0,0 +1,744 @@
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令牌作废提示信息比如 “不允许同一账号多地同时登录,会往这个变量存提示信息” */
String PREFIX_USER_TOKEN_ERROR_MSG = "prefix_user_token:error:msg_";
/**============================== 【是否允许同一账号多地同时登录】登录客户端类型常量 ==============================*/
/** 客户端类型PC端 */
String CLIENT_TYPE_PC = "PC";
/** 客户端类型APP端 */
String CLIENT_TYPE_APP = "APP";
/** 客户端类型:手机号登录 */
String CLIENT_TYPE_PHONE = "PHONE";
String PREFIX_USER_TOKEN_PC = "prefix_user_token:single_login:pc:";
/** 单点登录用户在APP端的Token缓存KEY前缀 (username -> token) */
String PREFIX_USER_TOKEN_APP = "prefix_user_token:single_login:app:";
/** 单点登录用户在手机号登录的Token缓存KEY前缀 (username -> token) */
String PREFIX_USER_TOKEN_PHONE = "prefix_user_token:single_login:phone:";
/**============================== 【是否允许同一账号多地同时登录】登录客户端类型常量 ==============================*/
// /** 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";
/**
* 文件上传类型本地localMiniominio阿里云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";
/**
* 系统角色管理员编码
*/
String SYS_ROLE_ADMIN = "admin";
/**
* 考勤补卡业务状态 0处理中
*/
String SIGN_PATCH_BIZ_STATUS_0 = "0";
/**
* 考勤补卡业务状态 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 textWPS模板还是公文发文模板)
*/
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://";
/** 部门表唯一keyid */
String DEPART_KEY_ID = "id";
/** 部门表唯一keyorgCode */
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";
/**
* 通知类型,用于区分来源 file 知识 flow 流程 plan 日程 system 系统消息
*/
String NOTICE_TYPE = "noticeType";
/**
* 邮箱消息中地址登录时地址后携带的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";
/**
* 报表允许设计开发的角色
*/
public static String[] allowDevRoles = new String[]{"lowdeveloper", "admin"};
/**
* 【对应积木报表的常量】
* 数据隔离模式: 按照创建人隔离
*/
public static final String SAAS_MODE_CREATED = "created";
/**
* 【对应积木报表的常量】
* 数据隔离模式: 按照租户隔离
*/
public static final String SAAS_MODE_TENANT = "tenant";
/**
* 修改手机号短信验证码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";
/**
* 修改手机号验证码请求次数超出
*/
Integer PHONE_SMS_FAIL_CODE = 40002;
/**
* 自定义首页关联关系(ROLE:表示角色 USER:表示用户 DEFAULT:默认首页)
*
*/
String HOME_RELATION_ROLE = "ROLE";
String HOME_RELATION_USER = "USER";
String HOME_RELATION_DEFAULT = "DEFAULT";
/**
* 是否置顶(0否 1是)
*/
Integer IZ_TOP_1 = 1;
Integer IZ_TOP_0 = 0;
//关注流程缓存前缀
String FLOW_FOCUS_NOTICE_PREFIX = "flow:runtimeData:focus:notice:";
//任务缓办时间缓存前缀
String FLOW_TASK_DELAY_PREFIX = "flow:runtimeData:task:delay:";
/**
* 用户代理类型离职quit 代理agent
*/
String USER_AGENT_TYPE_QUIT = "quit";
String USER_AGENT_TYPE_AGENT = "agent";
/**
* 督办流程首节点任务taskKey
*/
String SUPERVISE_FIRST_TASK_KEY = "Task_1bhxpt0";
/**
* wps模板预览数据缓存前缀
*/
String EOA_WPS_TEMPLATE_VIEW_DATA ="eoa:wps:templateViewData:";
/**
* wps模板预览版本号缓存前缀
*/
String EOA_WPS_TEMPLATE_VIEW_VERSION ="eoa:wps:templateViewVersion:";
/**
* 表单设计器oa新增字段
* x_oa_timeout_date:逾期时间
* x_oa_archive_status:归档状态
*/
String X_OA_TIMEOUT_DATE ="x_oa_timeout_date";
String X_OA_ARCHIVE_STATUS ="x_oa_archive_status";
/**
* 流程状态
* 待提交: 1
* 处理中: 2
* 已完成: 3
* 已作废: 4
* 已挂起: 5
*/
String BPM_STATUS_1 ="1";
String BPM_STATUS_2 ="2";
String BPM_STATUS_3 ="3";
String BPM_STATUS_4 ="4";
String BPM_STATUS_5 ="5";
/**
* 默认租户产品包
*/
String TENANT_PACK_DEFAULT = "default";
/**
* 部门名称redisKey(全路径)
*/
String DEPART_NAME_REDIS_KEY_PRE = "sys:cache:departPathName:";
/**
* 默认用户排序值
*/
Integer DEFAULT_USER_SORT = 1000;
/**
* 发送短信方式:腾讯
*/
String SMS_SEND_TYPE_TENCENT = "tencent";
/**
* 发送短信方式:阿里云
*/
String SMS_SEND_TYPE_ALI_YUN = "aliyun";
}

View File

@ -4,6 +4,20 @@ package org.jeecg.common.constant;
* @author: jeecg-boot
*/
public interface DataBaseConstant {
/**
* 内置的系统变量键列表
*/
public static final String[] SYSTEM_KEYS = {
DataBaseConstant.SYS_ORG_CODE, DataBaseConstant.SYS_ORG_CODE_TABLE, DataBaseConstant.SYS_MULTI_ORG_CODE,
DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE, DataBaseConstant.SYS_ORG_ID, DataBaseConstant.SYS_ORG_ID_TABLE,
DataBaseConstant.SYS_ROLE_CODE, DataBaseConstant.SYS_ROLE_CODE_TABLE, DataBaseConstant.SYS_USER_CODE,
DataBaseConstant.SYS_USER_CODE_TABLE, DataBaseConstant.SYS_USER_ID, DataBaseConstant.SYS_USER_ID_TABLE,
DataBaseConstant.SYS_USER_NAME, DataBaseConstant.SYS_USER_NAME_TABLE, DataBaseConstant.SYS_DATE,
DataBaseConstant.SYS_DATE_TABLE, DataBaseConstant.SYS_TIME, DataBaseConstant.SYS_TIME_TABLE,
DataBaseConstant.SYS_BASE_PATH
};
//*********数据库类型****************************************
/**MYSQL数据库*/
@ -58,6 +72,22 @@ public interface DataBaseConstant {
* 数据-所属机构编码
*/
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";
/**
* 数据-系统用户编码对应登录用户账号
*/
@ -66,7 +96,14 @@ public interface DataBaseConstant {
* 数据-系统用户编码对应登录用户账号
*/
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";
/**
* 登录用户真实姓名
*/

View File

@ -0,0 +1,15 @@
package org.jeecg.common.constant;
/**
* @Description: 密码常量类
*
* @author: wangshuai
* @date: 2025/8/27 20:10
*/
public interface PasswordConstant {
/**
* 导入用户默认密码
*/
String DEFAULT_PASSWORD = "123456";
}

View File

@ -1,6 +1,7 @@
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;
@ -22,32 +23,34 @@ 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 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
// 代码逻辑说明: 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 文本数组
@ -112,11 +115,10 @@ public class ProvinceCityArea {
}
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)){
if(null != area && area.getId().equals(code)){
String pid = area.getPid();
ls.add(0,area.getText());
getAreaByCode(pid,ls);
@ -149,9 +151,8 @@ public class ProvinceCityArea {
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 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
// 代码逻辑说明: VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
area.setAheadText(cityJson.getString(cityKey));
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
this.areaList.add(area);
}
}

View File

@ -34,17 +34,22 @@ public interface ServiceNameConstants {
*/
String SERVICE_DEMO = "jeecg-demo";
/**
* 微服务名online在线模块
* 微服务名joa模块
*/
String SERVICE_ONLINE = "jeecg-online";
/**
* 微服务名OA模块
*/
String SERVICE_EOA = "jeecg-eoa";
/**
* 微服务名表单设计模块
*/
String SERVICE_FORM = "jeecg-desform";
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

Some files were not shown because too many files have changed in this diff Show More