Compare commits

...

260 Commits

Author SHA1 Message Date
657b84d3cf Merge pull request #8007 from EightMonth/springboot3_sas
修复 CVE-2023-6378
2025-03-25 16:02:45 +08:00
2021bf39f8 修复 CVE-2023-6378 2025-03-25 16:00:14 +08:00
fdeb37c3d0 Merge pull request #8005 from EightMonth/springboot3_sas
jeewx-api修改成weixin4j
2025-03-25 14:19:33 +08:00
f9123208e1 jeewx-api修改成weixin4j 2025-03-25 14:15:05 +08:00
accb8f2f9f Merge pull request #7950 from EightMonth/springboot3_sas
解决严重bug,War包方式部署,服务启动报错
2025-03-12 15:28:44 +08:00
c643994546 解决严重bug,War包方式部署,服务启动报错 2025-03-12 14:16:50 +08:00
6934a0adee Merge pull request #7875 from EightMonth/springboot3_sas
修复 #7613
2025-03-03 17:05:12 +08:00
93e32a7177 Merge branch 'springboot3' into springboot3_sas 2025-03-03 14:30:40 +08:00
26887959cd 修复 #7613 2025-03-03 14:27:16 +08:00
c9f5bb4409 【3.7.3 版本合并升级】
Merge remote-tracking branch 'origin/springboot3' into springboot3_sas

# Conflicts:
#	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/config/shiro/ShiroConfig.java
#	jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java
#	jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantPackServiceImpl.java
#	jeecgboot-vue3/package.json
2025-02-24 18:24:51 +08:00
7e15e81218 版本合并,升级springboot3分支到3.7.3 2025-02-20 17:56:16 +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
10b68858d6 Merge pull request #7796 from EightMonth/springboot3_sas
固定vue-router版本号
2025-02-11 14:49:17 +08:00
8b0e0367c7 Merge pull request #7797 from EightMonth/springboot3
固定vue-router版本号
2025-02-11 14:49:06 +08:00
da72e8f9c5 Update package.json 2025-02-11 14:27:40 +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
73e86686dc 固定vue-router版本号 2025-02-11 09:25:59 +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
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
f43d0d486b Merge pull request #7378 from EightMonth/springboot3_sas
分布式事务demo修复
2024-11-20 17:42:55 +08:00
65bde3331b 修复#7459,修复sas分支 @ignoreauth注解无效 2024-11-20 11:08:53 +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
b60942aa86 分布式事务demo修复 2024-10-24 10:48:00 +08:00
197b267e71 分布式事务demo修复 2024-10-24 09:19:49 +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
79f7134bd5 【springboot3分支 issues/7353】The bean 'dataSource', defined in class path resource #7353 2024-10-19 19:30:05 +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
6d432bc186 Merge pull request #7332 from EightMonth/springboot3_sas
修复redis序列化认证信息问题
2024-10-11 16:33:11 +08:00
415307eb9f 修复redis序列化认证信息问题 2024-10-11 16:27:28 +08:00
48e20b2af5 Merge pull request #7329 from EightMonth/springboot3_sas
Revert "修复redis序列化认证信息问题"
2024-10-11 15:03:12 +08:00
b7924b9ca8 Revert "修复redis序列化认证信息问题"
This reverts commit 4aa88189ed.
2024-10-11 14:59:11 +08:00
a10a2e0a9d Merge pull request #7327 from EightMonth/springboot3_sas
修复redis序列化认证信息问题
2024-10-11 13:44:54 +08:00
4aa88189ed 修复redis序列化认证信息问题 2024-10-11 11:43:05 +08:00
fdb05443c2 【版本合并】springboot3 sas升级到3.7.1 2024-10-10 22:48:10 +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
e3cd6bfc97 升级jimureport到最新版1.7.7 2024-07-06 22:21:25 +08:00
8000d61ce0 修改项目语言 2024-07-05 15:53:18 +08:00
4ac18b5d81 项目语言修改 2024-07-05 15:49:11 +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
548 changed files with 34768 additions and 11777 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,13 +0,0 @@
##### 版本号:
##### 问题描述:
##### 错误截图:
#### 友情提示:
- 未按格式要求发帖、描述过于简抽象的,会被直接删掉;
- 请确保问题描述清楚,方便我们理解并一次性调查解决问题;
- 如果使用的不是master请说明你使用的那个分支

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

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

View File

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

23
LICENSE
View File

@ -201,16 +201,13 @@
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
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com
本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。
开源协议中文释意如下:
1.JeecgBoot开源版本无任何限制在遵循本开源协议条款下允许商用使用不会造成侵权行为
2.允许基于本平台软件开展业务系统开发。
3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件
最终解释权归http://www.jeecg.com

View File

@ -4,16 +4,15 @@
JEECG BOOT Low Code Development Platform
JEECG BOOT AI Low Code Platform
===============
当前最新版本: 3.7.0(发布日期:2024-06-17
Current version: 3.7.3 (Release date: 2025-02-10)
[![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.7.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.7.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)
@ -22,9 +21,9 @@ JEECG BOOT Low Code Development Platform
Project introduction
-----------------------------------
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
<h3 align="center">Java AI 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 is a `AI low code 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!
@ -33,15 +32,13 @@ The purpose of JEECG is: simple functions are implemented by OnlineCoding config
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.
AI Empowering Low-Code: Currently, JeecgBoot supports AI large models such as ChatGPT and DeepSeek. The latest version defaults to using DeepSeek, which offers faster speed and higher quality. It now provides features such as AI chat assistant, AI table creation, and AI report generation.
Technical support
-----------------------------------
Problems or bugs in use can be found in [Making on the Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
Official Support: http://jeecg.com/doc/help
##### Project description
@ -61,17 +58,14 @@ Download other source code
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.
Jeecg-Boot AI low code 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
Starts the project
-----------------------------------
- [Docker starts the monomer background](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker starts the 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)
- [IDEA Quick start](https://help.jeecg.com/java/setup/idea/startup.html)
- [Docker Quick start](https://help.jeecg.com/java/docker/quick.html)
@ -79,12 +73,14 @@ 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 [OnlineDemo](http://boot3.jeecg.com) | [APP](http://jeecg.com/appIndex)
> [please click obtain account password to obtain](http://jeecg.com/doc/demo)
- Doc [DocumentCenter](http://help.jeecg.com) | [AI Config](https://help.jeecg.com/java/ai/aichat.html)
- Newbie guide [Quick start](http://www.jeecg.com/doc/quickstart) | [Q&A ](http://www.jeecg.com/doc/qa) | [1 minute experience](https://my.oschina.net/jeecg/blog/3083313)
- QQ group ⑩716488839、⑨808791225、⑧825232878、⑦791696430、⑥730954414(full)、683903138(full)、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
Star charts
@ -180,7 +176,7 @@ Technical Architecture:
#### Development Environment
- Language: Java 8+ (less than 17)
- Language: Java 8+ (17)
- IDE(JAVA) : IDEA (lombok plug-in must be installed)
@ -190,20 +186,20 @@ Technical Architecture:
- Cache: Redis
- Database: MySQL5.7 + & Oracle 11 g & Sqlserver2017 [More Databases](https://my.oschina.net/jeecg/blog/4905722)
- Database: MySQL5.7 + [More Databases](https://my.oschina.net/jeecg/blog/4905722)
#### backend
- Basic framework: Spring Boot 2.6.14
- Basic framework: Spring Boot 2.7.18
- Microservice framework: Spring Cloud Alibaba 2021.0.1.0
- Persistence layer framework: MybatisPlus 3.5.1
- Persistence layer framework: MybatisPlus 3.5.3.2
- Report tool: JimuReport 1.5.8
- Report tool: JimuReport 1.9.3
- Security framework: Apache Shiro 1.10.0, Jwt 3.11.0
- Security framework: Apache Shiro 1.12.0, Jwt 3.11.0
- Microservice technology stack: Spring Cloud Alibaba, Nacos, Gateway, Sentinel, Skywalking
@ -218,6 +214,14 @@ Technical Architecture:
- TechnologyStack`Vue3.0+TypeScript+Vite+AntDesignVue+pinia+echarts`
#### Front-end environment requirements
* `Node.js 、npm 、pnpm`
* pnpm `v9+` is now required.
* Node.js Version suggestion: `v20.15.0`
` ( Since Vite6 Node.js 18/20 + is now required )`
#### Support library
| database | support |
@ -227,44 +231,38 @@ Technical Architecture:
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦、人大金仓 | √ |
| 达梦 | √ |
| 人大金仓 | √ |
| TiDB | √ |
#### AI Support
| AI Model | Supported |
| --- | --- |
| DeepSeek | √ |
| ChatGPT | √ |
AI Config https://help.jeecg.com/java/ai/aichat.html
## 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 √
- 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 Loki+grafana
- 14. Support docker-compose, k8s, jenkins
- 15. CAS SSO √
- 16. Route traffic limiting
#### Microservice architecture diagram
@ -273,157 +271,9 @@ Technical Architecture:
### 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办公组件 (未开源)
│ ├─更多功能
│ └─。。。
└─其他模块
└─更多功能开发中。。
```
### quick start
- Microservice Development [Monomer upgrade to microservice](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- [Docker starts the micro-service background](https://help.jeecg.com/java/docker/springcloud.html)
### Effect of system
@ -470,10 +320,22 @@ Technical Architecture:
![](https://oscimg.oschina.net/oscnet/up-7f83b25159663686d67ed080eb16068c3b4.png)
##### dashboard Designer
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/darg20240726105556.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135626.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135619.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135630.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240726105547.png)
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
##### report Designer
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)

404
README.md
View File

@ -1,38 +1,38 @@
JeecgBoot 低代码开发平台
JeecgBoot AI低代码平台
===============
当前最新版本: 3.7.0发布日期2024-06-17
当前最新版本: 3.7.3发布日期2025-02-10
[![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.7.0-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)](http://guojusoft.com)
[![](https://img.shields.io/badge/version-3.7.3-brightgreen.svg)](https://github.com/jeecgboot/JeecgBoot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/jeecgboot/JeecgBoot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/jeecgboot/JeecgBoot)
项目介绍
-----------------------------------
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
<h3 align="center">Java AI Low Code Platform for Enterprise web applications</h3>
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x3.xSpringCloudAnt Design&VueMybatis-plusShiroJWT支持微服务强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
JeecgBoot 是一款基于`BPM``代码生成器`的 AI低代码平台!前后端分离架构 SpringBoot2.x/3.xSpringCloudAnt Design Vue3Mybatis-plusShiroJWT支持微服务、多租户;支持 AI 大模型 DeepSeek 和 ChatGPT、Ollama本地模型; 强大的代码生成器让前后端代码一键生成,无需写任何代码! JeecgBoot 引领 AI 低代码开发模式(AI生成-> OnlineCoding-> 代码生成器-> 手工MERGE) 帮助解决Java项目80%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性!AIGC能力AI对话助手、AI建表、AI写文章、AI流程编排、AI知识库问答等等.
JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零代码`Online表单开发、Online报表、报表配置能力、在线图表设计、仪表盘设计、大屏设计、移动配置能力、表单设计器、在线设计流程、流程自动化配置、插件能力可插拔等等
JeecgBoot 提供了一系列 `AI能力` `低代码模块`,实现在线开发`真正的零代码`Online表单开发、Online报表、报表配置能力、在线图表设计、仪表盘设计、大屏设计、移动配置能力、表单设计器、在线设计流程、流程自动化配置、插件能力可插拔、AI对话助手AI建表、AI写文章、AI流程编排、AI知识库问答、AI赋能低代码等等!
`JEECG宗旨是:` 简单功能由OnlineCoding配置实现做到`零代码开发`复杂功能由代码生成器生成进行手工Merge 实现`低代码开发`,既保证了`智能`又兼顾`灵活`;实现了低代码开发的同时又支持灵活编码,解决了当前低代码产品普遍不灵活的弊端!
`JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计松耦合、并支持任务节点灵活配置既保证了公司流程的保密性又减少了开发人员的工作量。
`AI赋能低代码:` 目前JeecgBoot支持AI大模型`ChatGPT``DeepSeek`,现在最新版默认使用`DeepSeek`速度更快质量更高。目前提供了AI对话助手、AI建表、AI报表、AI写文章、AI流程编排、AI知识库问答等功能。
适用项目
-----------------------------------
Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中支持信创国产化默认适配达梦和人大金仓。尤其适合SAAS项目、企业信息管理系统MIS、内部办公系统OA、企业资源计划系统ERP、客户关系管理系统CRM其半智能手工Merge的开发方式可以显著提高开发效率70%以上,极大降低开发成本。
JeecgBoot AI低代码平台可以应用在任何J2EE项目的开发中支持信创国产化默认适配达梦和人大金仓。尤其适合SAAS项目、企业信息管理系统MIS、内部办公系统OA、企业资源计划系统ERP、客户关系管理系统CRM其半智能手工Merge的开发方式可以显著提高开发效率70%以上,极大降低开发成本。
#### 项目说明
@ -40,67 +40,157 @@ Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecg-boot` | 后端源码JAVASpringBoot微服务架构 |
| `jeecgboot-vue3` | 前端源码VUE3vue3+vite5+ts最新技术栈 |
| `jeecg-uniapp` | APP框架,一份代码多终端适配支持APP、小程序、H5 |
| `jeecgboot-vue3` | 前端源码VUE3vue3+vite6+ts最新技术栈 |
| `jeecg-uniapp` | [配套APP框架](https://github.com/jeecgboot/jeecg-uniapp) 适配多个终端支持APP、小程序、H5 |
其他源码
-----------------------------------
- APP源码地址https://github.com/jeecgboot/jeecg-uniapp
技术支持
-----------------------------------
关闭gitee的issue通道使用中遇到问题或者BUG可以在 [Github上提Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
快速启动项目
-----------------------------------
- [前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
Docker启动项目
-----------------------------------
- [Docker启动前端](http://help.jeecg.com/publish/docker.html)
- [Docker启动后台](https://help.jeecg.com/java/setup/docker/up.html)
微服务方式启动
-----------------------------------
- [单体快速切换微服务](https://help.jeecg.com/java/springcloud/switchcloud/monomer.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)
- AI助手配置: https://help.jeecg.com/java/chatgpt.html
- 官方网站 [http://www.jeecg.com](http://www.jeecg.com)
- 在线演示 [在线演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
>
- QQ交流群 ⑨808791225、⑧825232878、⑦791696430(满)、⑥730954414(满)、683903138(满)、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
- 快速体验: [一分钟体验低代码](https://jeecg.blog.csdn.net/article/details/106079007?spm=1001.2014.3001.5502 "一分钟体验零代码") | [在线体验零代码](https://app.qiaoqiaoyun.com/myapps/index "在线体验零代码")
- 开发文档: [文档中心](https://help.jeecg.com) | [AI集成配置(支持DeepSeek)](https://help.jeecg.com/java/ai/aichat.html)
- 反馈问题: [在Github上提Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [入门视频](http://jeecg.com/doc/video)
- QQ交流群 ⑩716488839、⑨808791225(满)、其他(满)
启动项目
-----------------------------------
- [IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Docker一键启动前后端](https://help.jeecg.com/java/docker/quick.html)
AIGC功能清单
-----------------------------------
- AI对聊天助手
- AI建表Online表单
- AI写文章CMS
- AI表单建议表单设计器
- AI流程编排研发中
- AI知识库问答系统研发中
- AI应用开发平台研发中
- AI聊天窗口支持嵌入第三方研发中
<b>关注公众号了解官方动态</b>
![公众号](https://jeecg.com/images/jeecg/qrcode_jeecgboot.jpg "在这里输入图片标题")
技术架构:
-----------------------------------
#### 后端
- IDE建议 IDEA (必须安装lombok插件 )
- 语言Java 8+ (支持17)
- 依赖管理Maven
- 基础框架Spring Boot 2.7.18
- 微服务框架: Spring Cloud Alibaba 2021.0.1.0
- 持久层框架MybatisPlus 3.5.3.2
- 报表工具: JimuReport 1.9.3
- 安全框架Apache Shiro 1.12.0Jwt 3.11.0
- 微服务技术栈Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
- 数据库连接池阿里巴巴Druid 1.1.22
- AI大模型支持 `ChatGPT` `DeepSeek`切换
- 日志打印logback
- 缓存Redis
- 其他autopoi, fastjsonpoiSwagger-uiquartz, lombok简化代码等。
- 默认数据库脚本MySQL5.7+
- [其他数据库,需要自己转](https://my.oschina.net/jeecg/blog/4905722)
#### 前端
- 前端IDE建议WebStorm、Vscode
- 采用 Vue3.0+TypeScript+Vite6+Ant-Design-Vue等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
- 最新技术栈Vue3.0 + TypeScript + Vite6 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
- 依赖管理node、npm、pnpm
#### 前端环境要求
* 本地环境安装 `Node.js 、npm 、pnpm`
* pnpm 要求`9+` 版本以上
* Node.js 版本建议`v20.15.0`,要求`Node 20+` 版本以上
` ( 因为Vite6 需要 Node.js 18 / 20+ )`
#### 支持库
| 数据库 | 支持 |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| MariaDB | √ |
| 达梦 | √ |
| 人大金仓 | √ |
| TiDB | √ |
#### 支持AI大模型
| AI大模型 | 支持 |
| --- | --- |
| DeepSeek | √ |
| ChatGTP | √ |
| Ollama本地搭建大模型 | √ |
AI集成文档 https://help.jeecg.com/java/ai/aichat.html
## 微服务解决方案
- 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、轻量分布式日志 Loki+grafana套件
- 14、支持 docker-compose、k8s、jenkins
- 15、CAS 单点登录 √
- 16、路由限流 √
#### 微服务方式启动
- [单体快速切换微服务](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- [Docker一键启动微服务前后端](https://help.jeecg.com/java/docker/quickcloud.html)
#### 微服务架构图
![微服务架构图](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecgboot_springcloud2022.png "在这里输入图片标题")
为什么选择JeecgBoot?
-----------------------------------
* 1.采用最新主流前后分离框架Springboot+Mybatis+antd容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
* 1.采用最新主流前后分离框架Springboot+Mybatis+antd+vue3),容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
* 2.支持微服务SpringCloud Alibaba(Nacos、Gateway、Sentinel、Skywalking),提供切换机制支持单体和微服务自由切换
* 3.开发效率高,采用代码生成器,单表、树列表、一对多、一对一等数据模型,增删改查功能一键生成,菜单配置直接使用;
* 3.开发效率高,采用代码生成器,单表、树列表、一对多、一对一等数据模型,增删改查功能一键生成,菜单配置直接使用;引入AI能力支持自动建表等功能
* 4.代码生成器提供强大模板机制,支持自定义模板,目前提供四套风格模板(单表两套、树模型一套、一对多三套)
* 5.代码生成器非常智能在线业务建模、在线配置、所见即所得支持23种类控件一键生成前后端代码大幅度提升开发效率不再为重复工作发愁。
* 6.AI能力目前JeecgBoot支持AI大模型chatgpt和deepseek现在最新版默认使用deepseek速度更快质量更高。目前提供了AI对话助手、AI建表、AI报表等功能。
* 6.低代码能力Online在线表单无需编码通过在线配置表单实现表单的增删改查支持单表、树、一对多、一对一等模型实现人人皆可编码
* 7.低代码能力Online在线报表无需编码通过在线配置方式实现数据报表可以快速抽取数据减轻开发压力实现人人皆可编码
* 8.低代码能力Online在线图表无需编码通过在线配置方式实现曲线图柱状图数据报表等支持自定义排版布局实现人人皆可编码
* 7.低代码能力Online在线报表、Online在线图表(无需编码,通过在线配置方式,实现数据报表和图形报表,可以快速抽取数据,减轻开发压力,实现人人皆可编码)
* 9.封装完善的用户、角色、菜单、组织机构、数据字典、在线定时任务等基础功能,支持访问授权、按钮权限、数据权限等功能
* 10.常用共通封装,各种工具类(定时任务,短信接口,邮件发送,Excel导入导出等),基本满足80%项目需求
* 11.简易Excel导入导出支持单表导出和一对多表模式导出生成的代码自带导入导出功能
@ -111,7 +201,7 @@ Docker启动项目
* 16.页面校验自动生成(必须输入、数字校验、金额校验、时间空间等);
* 17.支持SAAS服务模式提供SaaS多租户架构方案。
* 18.分布式文件服务集成minio、阿里OSS等优秀的第三方提供便捷的文件上传与管理同时也支持本地存储。
* 19.主流数据库兼容一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦等主流数据库。
* 19.主流数据库兼容一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦、人大金仓等主流数据库。
* 20.集成工作流flowable并实现了只需在页面配置流程转向可极大的简化bpm工作流的开发用bpm的流程设计器画出了流程走向一个工作流基本就完成了只需写很少量的java代码
* 21.低代码能力在线流程设计采用开源flowable流程引擎实现在线画流程,自定义表单,表单挂靠,业务流转
* 22.多数据源:及其简易的使用方式,在线配置数据源配置,便捷的从其他数据抓取数据;
@ -134,103 +224,8 @@ Docker启动项目
* 39.支持菜单动态路由
* 40.权限控制采用 RBACRole-Based Access Control基于角色的访问控制
* 41.提供新行编辑表格JVXETable轻松满足各种复杂ERP布局拥有更高的性能、更灵活的扩展、更强大的功能
* 42.提供仪表盘设计器,类大屏设计支持移动端,免费的数据可视化设计工具,支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表和门户设计;目前支持多种图表类型:柱形图、折线图、散点图、饼图、环形图、面积图、漏斗图、进度图、仪表盘、雷达图、地图等等;
技术架构:
-----------------------------------
#### 开发环境
- 语言Java 8+ (小于17)
- IDE(JAVA) IDEA (必须安装lombok插件 )
- IDE(前端) Vscode、WebStorm、IDEA
- 依赖管理Maven
- 缓存Redis
- 数据库脚本MySQL5.7+ (其他数据库,[需要自己转](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简化代码等。
#### 前端
- 技术栈:`Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6` 等最新技术栈
#### 支持库
| 数据库 | 支持 |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦、人大金仓 | √ |
## 微服务解决方案
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 "在这里输入图片标题")
@ -238,14 +233,36 @@ Docker启动项目
### 分支说明
> 主干master更稳定如果你对最新技术栈无要求建议采用主干
#### springboot3分支
- 源码地址https://github.com/jeecgboot/JeecgBoot/tree/springboot3
- 架构说明升级Spring Boot3 & JDK 17 + Undertow + springdoc + fastjson2
#### springboot3_sas分支
- 源码地址https://github.com/jeecgboot/JeecgBoot/tree/springboot3_sas
- 架构说明在springboot3分支基础上采用SpringAuthorizationServer替换Shiro
### 功能模块
```
├─AI开发
│ ├─支持AI大模型ChatGPT和DeepSeek
│ ├─AI对话助手
│ ├─AI建表
│ ├─AI写文章
│ ├─AI流程编排研发中
│ ├─AI知识库问答系统研发中
│ ├─AI应用开发平台研发中
│ ├─AI聊天窗口支持嵌入第三方研发中
├─Online在线开发(低代码)
│ ├─Online在线表单
│ ├─Online代码生成器
│ ├─Online在线报表
│ ├─仪表盘设计器
│ ├─AI助手
│ ├─系统编码规则
│ ├─系统校验规则
├─积木报表设计器
@ -378,40 +395,26 @@ Docker启动项目
后台目录结构
-----------------------------------
```
项目结构
├─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 -- 微服务测试示例(分库分表)
```
### 系统效果
##### AI功能
AI聊天助手
![](https://oscimg.oschina.net/oscnet//65298d5710b4e6039a5f802b5f8505c5.png)
AI建表
![](https://oscimg.oschina.net/oscnet/up-381423599f219a67def45dfd9a99df8ef3f.png)
![](https://oscimg.oschina.net/oscnet/up-1508c2b0708c365605f68893044ee11f20d.png)
AI写文章
![](https://oscimg.oschina.net/oscnet/up-e3ee5b1fe497308805aa5e324b72994af79.png)
##### PC端
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)
@ -430,15 +433,23 @@ Docker启动项目
![](https://oscimg.oschina.net/oscnet/up-16c07e000278329b69b228ae3189814b8e9.png)
##### AI助手
![](https://oscimg.oschina.net/oscnet/up-7c6405641a40f56638999d52da0cb5b4343.png)
##### 仪表盘设计器
![](https://oscimg.oschina.net/oscnet/up-9c9d41288c31398d76b390bdd400f13a582.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/darg20240726105556.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135626.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135619.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240724135630.png)
![](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/drag20240726105547.png)
![](https://oscimg.oschina.net/oscnet/up-fad98d42b2cf92f92a903c9cff7579f18ec.png)
##### 报表设计器
![](https://oscimg.oschina.net/oscnet/up-64648de000851f15f6c7b9573d107ebb5f8.png)
@ -521,11 +532,4 @@ Docker启动项目
如果觉得还不错,请作者喝杯咖啡吧 ☺
![](https://static.oschina.net/uploads/img/201903/08155608_0EFX.png)
### 流程引擎推荐
大家在使用本开源项目时,如果想进一步集成流程引擎,推荐结合贺波老师的书 [《深入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">
![](https://static.oschina.net/uploads/img/201903/08155608_0EFX.png)

135
docker-compose-cloud.yml Normal file
View File

@ -0,0 +1,135 @@
version: '2'
services:
jeecg-boot-mysql:
build:
context: ./jeecg-boot/db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: '%'
TZ: Asia/Shanghai
restart: always
container_name: jeecg-boot-mysql
image: jeecg-boot-mysql
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--default-authentication-plugin=caching_sha2_password
ports:
- 3306:3306
networks:
- jeecg-boot
jeecg-boot-redis:
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
ports:
- 6379:6379
restart: always
hostname: jeecg-boot-redis
container_name: jeecg-boot-redis
networks:
- jeecg-boot
jeecg-boot-nacos:
restart: always
build:
context: ./jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos
ports:
- 8848:8848
container_name: jeecg-boot-nacos
depends_on:
- jeecg-boot-mysql
hostname: jeecg-boot-nacos
networks:
- jeecg-boot
jeecg-boot-system:
depends_on:
- jeecg-boot-nacos
build:
context: ./jeecg-boot/jeecg-server-cloud/jeecg-system-cloud-start
container_name: jeecg-system-start
hostname: jeecg-boot-system
restart: on-failure
environment:
- TZ=Asia/Shanghai
networks:
- jeecg-boot
jeecg-boot-demo:
depends_on:
- jeecg-boot-nacos
build:
context: ./jeecg-boot/jeecg-server-cloud/jeecg-demo-cloud-start
container_name: jeecg-demo-start
hostname: jeecg-boot-demo
restart: on-failure
environment:
- TZ=Asia/Shanghai
networks:
- jeecg-boot
jeecg-boot-gateway:
restart: on-failure
build:
context: ./jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway
ports:
- 9999:9999
depends_on:
- jeecg-boot-nacos
- jeecg-boot-system
container_name: jeecg-boot-gateway
hostname: jeecg-boot-gateway
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
# jeecg-boot-sentinel:
# restart: on-failure
# build:
# context: ./jeecg-visual/jeecg-cloud-sentinel
# ports:
# - 9000:9000
# depends_on:
# - jeecg-boot-nacos
# - jeecg-boot-demo
# - jeecg-boot-system
# - jeecg-boot-gateway
# container_name: jeecg-boot-sentinel
# hostname: jeecg-boot-sentinel
#
# jeecg-boot-xxljob:
# build:
# context: ./jeecg-visual/jeecg-cloud-xxljob
# ports:
# - 9080:9080
# container_name: jeecg-boot-xxljob
# hostname: jeecg-boot-xxljob
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:
name: jeecg_boot

View File

@ -2,13 +2,14 @@ version: '2'
services:
jeecg-boot-mysql:
build:
context: ../db
context: ./jeecg-boot/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
@ -22,28 +23,41 @@ services:
- jeecg-boot
jeecg-boot-redis:
image: redis:5.0
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
ports:
- 6379:6379
restart: always
container_name: jeecg-boot-redis
hostname: jeecg-boot-redis
container_name: jeecg-boot-redis
networks:
- jeecg-boot
jeecg-boot-system:
build:
context: ./jeecg-boot/jeecg-module-system/jeecg-system-start
restart: on-failure
depends_on:
- jeecg-boot-mysql
- jeecg-boot-redis
container_name: jeecg-boot-system
image: jeecg-boot-system
hostname: jeecg-boot-system
ports:
- 8080:8080
networks:
- jeecg-boot
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:
name: 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

View File

@ -201,16 +201,13 @@
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
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com
本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。
开源协议中文释意如下:
1.JeecgBoot开源版本无任何限制在遵循本开源协议条款下允许商用使用不会造成侵权行为
2.允许基于本平台软件开展业务系统开发。
3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件
最终解释权归http://www.jeecg.com

165
jeecg-boot/README.md Normal file
View File

@ -0,0 +1,165 @@
JeecgBoot 低代码开发平台
===============
当前最新版本: 3.7.3发布日期2025-02-10
[![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/version-3.7.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)
项目介绍
-----------------------------------
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x和3.xSpringCloudAnt Design Vue3Mybatis-plusShiroJWT支持微服务。强大的代码生成器让前后端代码一键生成实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
#### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecg-boot` | 后端源码JAVASpringBoot微服务架构 |
| `jeecgboot-vue3` | 前端源码VUE3vue3+vite5+ts最新技术栈 |
技术文档
-----------------------------------
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart)
- QQ交流群 ⑩716488839、⑨808791225、其他(满)
- 在线演示 [在线演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
启动项目
-----------------------------------
- [IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Docker一键启动前后端](https://help.jeecg.com/java/docker/quick.html)
微服务启动
-----------------------------------
- [单体快速切换微服务](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- [Docker启动微服务后台](https://help.jeecg.com/java/docker/springcloud.html)
技术架构:
-----------------------------------
#### 后端
- IDE建议 IDEA (必须安装lombok插件 )
- 语言Java 8+ (支持17)
- 依赖管理Maven
- 基础框架Spring Boot 2.7.18
- 微服务框架: Spring Cloud Alibaba 2021.0.1.0
- 持久层框架MybatisPlus 3.5.3.2
- 报表工具: JimuReport 1.8.1
- 安全框架Apache Shiro 1.12.0Jwt 3.11.0
- 微服务技术栈Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
- 数据库连接池阿里巴巴Druid 1.1.22
- 日志打印logback
- 缓存Redis
- 其他autopoi, fastjsonpoiSwagger-uiquartz, lombok简化代码等。
- 默认数据库脚本MySQL5.7+
- [其他数据库,需要自己转](https://my.oschina.net/jeecg/blog/4905722)
#### 前端
- 前端IDE建议WebStorm、Vscode
- 采用 Vue3.0+TypeScript+Vite+Ant-Design-Vue等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
- 最新技术栈Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
- 依赖管理node、npm、pnpm
#### 支持库
| 数据库 | 支持 |
| --- | --- |
| MySQL | √ |
| Oracle11g | √ |
| Sqlserver2017 | √ |
| PostgreSQL | √ |
| MariaDB | √ |
| 达梦 | √ |
| 人大金仓 | √ |
| TiDB | √ |
## 微服务解决方案
- 1、服务注册和发现 Nacos √
- 2、统一配置中心 Nacos √
- 3、路由网关 gateway(三种加载方式) √
- 4、分布式 http feign √
- 5、熔断降级限流 Sentinel √
- 6、分布式文件 Minio、阿里OSS √
- 7、统一权限控制 JWT + Shiro √
- 8、服务监控 SpringBootAdmin√
- 9、链路跟踪 Skywalking [参考文档](https://help.jeecg.com/java/springcloud/super/skywarking.html)
- 10、消息中间件 RabbitMQ √
- 11、分布式任务 xxl-job √
- 12、分布式事务 Seata
- 13、轻量分布式日志 Loki+grafana套件
- 14、支持 docker-compose、k8s、jenkins
- 15、CAS 单点登录 √
- 16、路由限流 √
后台目录结构
-----------------------------------
```
项目结构
├─jeecg-boot-parent父POM 项目依赖、modules组织
│ ├─jeecg-boot-base-core共通模块 工具类、config、权限、查询过滤器、注解等
│ ├─jeecg-module-demo 示例代码
│ ├─jeecg-module-system System系统管理目录
│ │ ├─jeecg-system-biz System系统管理权限等功能
│ │ ├─jeecg-system-start System单体启动项目(8080
│ │ ├─jeecg-system-api System系统管理模块对外api
│ │ │ ├─jeecg-system-cloud-api System模块对外提供的微服务接口
│ │ │ ├─jeecg-system-local-api System模块对外提供的单体接口
│ ├─jeecg-server-cloud --微服务模块
├─jeecg-cloud-gateway --微服务网关模块(9999)
├─jeecg-cloud-nacos --Nacos服务模块(8848)
├─jeecg-system-cloud-start --System微服务启动项目(7001)
├─jeecg-demo-cloud-start --Demo微服务启动项目(7002)
├─jeecg-visual
├─jeecg-cloud-monitor --微服务监控模块 (9111)
├─jeecg-cloud-xxljob --微服务xxljob定时任务服务端 (9080)
├─jeecg-cloud-sentinel --sentinel服务端 (9000)
├─jeecg-cloud-test -- 微服务测试示例(各种例子)
├─jeecg-cloud-test-more -- 微服务测试示例feign、熔断降级、xxljob、分布式锁
├─jeecg-cloud-test-rabbitmq -- 微服务测试示例rabbitmq
├─jeecg-cloud-test-seata -- 微服务测试示例seata分布式事务
├─jeecg-cloud-test-shardingsphere -- 微服务测试示例(分库分表)
```
#### 微服务架构图
![微服务架构图](https://jeecgos.oss-cn-beijing.aliyuncs.com/files/jeecgboot_springcloud2022.png "在这里输入图片标题")

View File

@ -1,4 +1,4 @@
FROM mysql:8.0.19
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/mysql:8.0.19
MAINTAINER jeecgos@163.com

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,115 +5,356 @@
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_general_ci;
use `xxl_job`;
SET NAMES utf8mb4;
/*
Navicat Premium Data Transfer
CREATE TABLE `xxl_job_info` (
Source Server : mysql5.7
Source Server Type : MySQL
Source Server Version : 50738 (5.7.38)
Source Host : 127.0.0.1:3306
Source Schema : xxl_job
Target Server Type : MySQL
Target Server Version : 50738 (5.7.38)
File Encoding : 65001
Date: 10/02/2025 13:49:31
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for xxl_job_group
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_group`;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器AppName',
`title` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '执行器地址类型0=自动注册1=手动录入',
`address_list` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行器地址列表多地址逗号分隔',
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of xxl_job_group
-- ----------------------------
INSERT INTO `xxl_job_group` VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2025-02-10 13:49:04');
INSERT INTO `xxl_job_group` VALUES (2, 'jeecg-demo', '测试Demo模块', 0, NULL, '2025-02-10 13:49:04');
INSERT INTO `xxl_job_group` VALUES (3, 'jeecg-system', '系统System模块', 0, NULL, '2025-02-10 13:49:04');
-- ----------------------------
-- Table structure for xxl_job_info
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_info`;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_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;
`job_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`add_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
`author` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '调度配置值含义取决于调度类型',
`misfire_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数',
`glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码',
`glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime NULL DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '子任务ID多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '调度状态0-停止1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT 0 COMMENT '下次调度时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `xxl_job_log` (
-- ----------------------------
-- Records of xxl_job_info
-- ----------------------------
INSERT INTO `xxl_job_info` VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2024-08-21 22:30:30', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '', 1, 1729353600000, 1739203200000);
INSERT INTO `xxl_job_info` VALUES (2, 3, '测试jeecg xxljob', '2024-08-21 22:41:10', '2024-08-21 22:41:30', 'JEECG', '', 'CRON', '* * * * * ?', 'DO_NOTHING', 'FIRST', 'demoJob', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2024-08-21 22:41:10', '', 1, 1739166572000, 1739166573000);
-- ----------------------------
-- Table structure for xxl_job_lock
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_lock`;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of xxl_job_lock
-- ----------------------------
INSERT INTO `xxl_job_lock` VALUES ('schedule_lock');
-- ----------------------------
-- Table structure for xxl_job_log
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_log`;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`executor_address` varchar(255) 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 '调度-时间',
`executor_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器地址本次执行的地址',
`executor_handler` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '执行器任务分片参数格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT 0 COMMENT '失败重试次数',
`trigger_time` datetime NULL DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`trigger_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '调度-日志',
`handle_time` datetime NULL DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text 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;
`handle_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '告警状态0-默认1-无需告警2-告警成功3-告警失败',
PRIMARY KEY (`id`) USING BTREE,
INDEX `I_trigger_time`(`trigger_time`) USING BTREE,
INDEX `I_handle_code`(`handle_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6761 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `xxl_job_log_report` (
-- ----------------------------
-- Records of xxl_job_log
-- ----------------------------
INSERT INTO `xxl_job_log` VALUES (6618, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:09', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式自动注册<br>执行器-地址列表null<br>路由策略第一个<br>阻塞处理策略单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6619, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:10', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6620, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:11', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6621, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:12', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6622, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:13', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6623, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:14', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6624, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:15', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6625, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:16', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6626, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:17', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6627, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:18', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6628, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:19', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6629, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:20', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6630, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:21', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6631, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:22', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6632, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:23', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6633, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:24', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6634, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:25', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6635, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:26', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6636, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:27', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6637, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:28', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6638, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:29', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6639, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:30', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6640, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:31', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6641, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:32', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6642, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:33', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6643, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:34', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6644, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:35', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6645, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:36', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6646, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:37', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6647, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:38', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6648, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:39', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6649, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:40', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6650, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:41', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6651, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:42', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6652, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:43', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6653, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:44', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6654, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:45', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6655, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:46', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6656, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:47', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6657, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:48', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6658, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:49', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6659, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:50', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6660, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:51', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6661, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:52', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6662, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:53', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6663, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:54', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6664, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:55', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6665, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:56', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6666, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:57', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6667, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:58', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6668, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:47:59', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6669, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:00', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6670, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:01', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6671, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:02', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6672, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:03', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6673, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:04', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6674, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:05', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6675, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:06', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6676, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:07', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6677, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:08', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6678, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:09', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6679, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:10', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6680, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:11', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6681, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:12', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6682, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:13', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6683, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:14', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6684, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:15', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6685, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:16', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6686, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:17', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6687, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:18', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6688, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:19', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6689, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:20', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6690, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:21', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6691, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:22', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6692, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:23', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6693, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:24', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6694, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:25', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6695, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:26', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6696, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:27', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6697, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:28', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6698, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:29', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6699, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:30', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6700, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:31', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6701, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:32', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6702, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:33', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6703, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:34', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6704, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:35', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6705, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:36', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6706, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:37', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6707, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:38', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6708, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:39', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6709, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:40', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6710, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:41', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6711, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:42', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6712, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:43', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6713, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:44', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6714, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:45', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6715, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:46', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6716, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:47', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6717, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:48', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6718, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:49', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6719, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:50', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6720, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:51', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6721, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:52', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6722, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:53', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6723, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:54', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6724, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:55', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6725, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:56', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6726, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:57', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6727, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:58', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6728, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:48:59', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6729, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:00', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6730, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:01', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6731, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:02', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6732, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:03', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6733, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:04', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6734, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:05', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6735, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:06', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6736, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:07', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6737, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:08', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6738, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:09', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6739, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:10', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6740, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:11', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6741, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:12', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6742, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:13', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6743, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:14', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6744, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:15', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6745, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:16', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6746, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:17', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6747, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:18', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6748, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:19', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6749, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:20', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6750, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:21', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6751, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:22', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6752, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:23', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6753, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:24', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
INSERT INTO `xxl_job_log` VALUES (6754, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:25', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6755, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:26', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6756, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:27', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6757, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:28', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6758, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:29', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6759, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:30', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
INSERT INTO `xxl_job_log` VALUES (6760, 3, 2, NULL, 'demoJob', '', NULL, 0, '2025-02-10 13:49:31', 500, '任务触发类型Cron触发<br>调度机器192.168.1.11<br>执行器-注册方式:自动注册<br>执行器-地址列表null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间0<br>失败重试次数0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 0);
-- ----------------------------
-- Table structure for xxl_job_log_report
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_log_report`;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime 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;
`trigger_day` datetime NULL DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT 0 COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `i_trigger_day`(`trigger_day`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `xxl_job_logglue` (
-- ----------------------------
-- Records of xxl_job_log_report
-- ----------------------------
INSERT INTO `xxl_job_log_report` VALUES (1, '2024-08-21 00:00:00', 70, 0, 5, NULL);
INSERT INTO `xxl_job_log_report` VALUES (2, '2024-08-20 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (3, '2024-08-19 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (4, '2024-09-10 00:00:00', 0, 0, 56, NULL);
INSERT INTO `xxl_job_log_report` VALUES (5, '2024-09-09 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (6, '2024-09-08 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (7, '2024-10-19 00:00:00', 0, 0, 6391, NULL);
INSERT INTO `xxl_job_log_report` VALUES (8, '2024-10-18 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (9, '2024-10-17 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (10, '2025-02-10 00:00:00', 0, 0, 116, NULL);
INSERT INTO `xxl_job_log_report` VALUES (11, '2025-02-09 00:00:00', 0, 0, 0, NULL);
INSERT INTO `xxl_job_log_report` VALUES (12, '2025-02-08 00:00:00', 0, 0, 0, NULL);
-- ----------------------------
-- Table structure for xxl_job_logglue
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_logglue`;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) 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;
`glue_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'GLUE源代码',
`glue_remark` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'GLUE备注',
`add_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
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;
-- ----------------------------
-- Records of xxl_job_logglue
-- ----------------------------
CREATE TABLE `xxl_job_group` (
-- ----------------------------
-- Table structure for xxl_job_registry
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_registry`;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`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;
`registry_group` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`registry_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`registry_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `i_g_k_v`(`registry_group`, `registry_key`, `registry_value`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `xxl_job_user` (
-- ----------------------------
-- Records of xxl_job_registry
-- ----------------------------
-- ----------------------------
-- Table structure for xxl_job_user
-- ----------------------------
DROP TABLE IF EXISTS `xxl_job_user`;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号',
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
`permission` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限:执行器ID列表多个逗号分割',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `i_username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of xxl_job_user
-- ----------------------------
INSERT INTO `xxl_job_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
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;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -3,6 +3,7 @@
> JeecgBoot属于平台级产品每次升级改动较大目前做不到平滑升级。
### 增量升级方案
#### 1.代码合并
本地通过svn或git做好主干在分支上做业务开发jeecg每次版本发布可以手工覆盖主干的代码对比合并代码
@ -11,5 +12,12 @@
- 其他库请手工执行SQL, 目录: `jeecg-module-system\jeecg-system-start\src\main\resources\flyway\sql\mysql`
> 注意: 升级sql只提供mysql版本如果有权限升级, 还需要手工角色授权,退出重新登录才好使。
#### 3.兼容问题
#### 3.其他数据库脚本说明
原先官方默认提供oracle和SqlServer的脚本但是维护成本太高未提供脚本的数据库可以参考下面的文档自己转
https://my.oschina.net/jeecg/blog/4905722
注意定时任务的表qrtz_*,需要删掉用原始的脚本重新执行一下)
quartz-2.2.3-distribution.tar.gz放到百度网盘中大家自己下载执行所需数据库脚本
https://pan.baidu.com/s/1WrmZdUuAPg3iBwJ-LoHWyg?pwd=8mdz
#### 4.兼容问题
每次发版,会针对不兼容地方重点说明。

View File

@ -23,7 +23,7 @@ services:
- jeecg-boot
jeecg-boot-redis:
image: redis:5.0
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
ports:
- 6379:6379
restart: always

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-base-core</artifactId>
@ -163,7 +163,7 @@
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>kingbase8</artifactId>
<version>${kingbase8.version}</version>
<version>9.0.0</version>
<scope>runtime</scope>
</dependency>
<!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT -->

View File

@ -84,6 +84,12 @@ public class MessageDTO implements Serializable {
* 邮件抄送地址
*/
protected Set<String> ccEmailList;
/**
* 是否为定时任务推送email
*/
private Boolean isTimeJob = false;
//---【邮件相关参数】-------------------------------------------------------------
public MessageDTO(){

View File

@ -144,7 +144,9 @@ public interface CommonConstant {
*/
String STATUS_0 = "0";
String STATUS_1 = "1";
Integer STATUS_0_INT = 0;
Integer STATUS_1_INT = 1;
/**
* 同步工作流引擎1同步0不同步
*/
@ -475,6 +477,11 @@ public interface CommonConstant {
*/
String FILE_EDITABLE = "editable";
/**
* 文件 只读
*/
String FILE_READONLY = "readonly";
/**
* 登录失败用于记录失败次数的key
*/
@ -597,6 +604,11 @@ public interface CommonConstant {
*/
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
*/

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,26 +23,30 @@ public class ProvinceCityArea {
List<Area> areaList;
public String getText(String code){
this.initAreaList();
if(this.areaList!=null || this.areaList.size()>0){
List<String> ls = new ArrayList<String>();
getAreaByCode(code,ls);
return String.join("/",ls);
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){
this.initAreaList();
if(areaList!=null && areaList.size()>0){
for(int i=areaList.size()-1;i>=0;i--){
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
String areaText = areaList.get(i).getText();
String cityText = areaList.get(i).getAheadText();
if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){
return areaList.get(i).getId();
if(StringUtils.isNotBlank(text)){
this.initAreaList();
if(areaList!=null && areaList.size()>0){
for(int i=areaList.size()-1;i>=0;i--){
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
String areaText = areaList.get(i).getText();
String cityText = areaList.get(i).getAheadText();
if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){
return areaList.get(i).getId();
}
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
}
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
}
}
return null;

View File

@ -15,15 +15,7 @@ public enum DySmsEnum {
/**修改密码短信模板编码*/
CHANGE_PASSWORD_TEMPLATE_CODE("SMS_465391221","敲敲云","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");
REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code");
/**
* 短信模板编码

View File

@ -122,7 +122,7 @@ public class JeecgBootExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public Result<?> handleAuthorizationException(AccessDeniedException e){
log.error(e.getMessage(), e);
return Result.noauth("没有权限,请联系管理员授权,后刷新缓存!");
return Result.noauth("没有权限,请联系管理员分配权限!");
}
@ExceptionHandler(Exception.class)

View File

@ -746,7 +746,11 @@ public class QueryGenerator {
private static boolean judgedIsUselessField(String name) {
return "class".equals(name) || "ids".equals(name)
|| "page".equals(name) || "rows".equals(name)
|| "sort".equals(name) || "order".equals(name);
//// update-begin--author:sunjianlei date:20240808 for【TV360X-2009】取消过滤 sort、order 字段,防止前端排序报错 ------
//// https://github.com/jeecgboot/JeecgBoot/issues/6937
// || "sort".equals(name) || "order".equals(name)
//// update-end----author:sunjianlei date:20240808 for【TV360X-2009】取消过滤 sort、order 字段,防止前端排序报错 ------
;
}
@ -801,7 +805,9 @@ public class QueryGenerator {
addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.datetimeFormat.get()));
}
}else {
addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType));
//update-begin---author:chenrui ---date:20241125 for[issues/7481]多租户模式下 数据权限使用变量:#{tenant_id} 报错------------
addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(converRuleValue(dataRule.getRuleValue()), propertyType));
//update-end---author:chenrui ---date:20241125 for[issues/7481]多租户模式下 数据权限使用变量:#{tenant_id} 报错------------
}
}
}
@ -834,6 +840,9 @@ public class QueryGenerator {
public static String getSqlRuleValue(String sqlRule){
try {
Set<String> varParams = getSqlRuleParams(sqlRule);
if (varParams == null || varParams.isEmpty()) {
return sqlRule;
}
for(String var:varParams){
String tempValue = converRuleValue(var);
sqlRule = sqlRule.replace("#{"+var+"}",tempValue);
@ -852,7 +861,9 @@ public class QueryGenerator {
return null;
}
Set<String> varParams = new HashSet<String>();
String regex = "\\#\\{\\w+\\}";
//update-begin---author:chenrui ---date:20250108 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
String regex = "#\\{\\[*\\w+]*}";
//update-end---author:chenrui ---date:20250108 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(sql);

View File

@ -54,8 +54,10 @@ public enum QueryRuleEnum {
NOT_EMPTY("NOT_EMPTY","not_empty","值不为空"),
/**查询规则 不包含*/
NOT_IN("NOT_IN","not_in","不包含"),
/**查询规则 多词匹配*/
/**查询规则 多词精确匹配*/
ELE_MATCH("ELE_MATCH","elemMatch","多词匹配"),
/**查询规则 多词精确不匹配*/
ELE_NOT_MATCH("ELE_NOT_MATCH","elemNotMatch","多词精确不匹配"),
/**查询规则 范围查询*/
RANGE("RANGE","range","范围查询"),
/**查询规则 不在范围内查询*/

View File

@ -86,7 +86,7 @@ public class JwtUtil {
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
}
@ -104,7 +104,8 @@ public class JwtUtil {
// 效验TOKEN
jwtDecoder.decode(token);
return true;
} catch (Exception exception) {
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
@ -119,6 +120,7 @@ public class JwtUtil {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
log.warn(e.getMessage(), e);
return null;
}
}
@ -225,6 +227,14 @@ public class JwtUtil {
} else {
key = key;
}
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
// 是否存在字符串标志
boolean multiStr = false;
if(oConvertUtils.isNotEmpty(key) && key.trim().matches("^\\[\\w+]$")){
key = key.substring(1,key.length()-1);
multiStr = true;
}
//update-end---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
//替换为当前系统时间(年月日)
if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) {
returnValue = DateUtils.formatDate();
@ -293,11 +303,22 @@ public class JwtUtil {
if(user==null){
//TODO 暂时使用用户登录部门,存在逻辑缺陷,不是用户所拥有的部门
returnValue = sysUser.getOrgCode();
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
returnValue = multiStr ? "'" + returnValue + "'" : returnValue;
//update-end---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
}else{
if(user.isOneDepart()) {
returnValue = user.getSysMultiOrgCode().get(0);
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
returnValue = multiStr ? "'" + returnValue + "'" : returnValue;
//update-end---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
}else {
returnValue = Joiner.on(",").join(user.getSysMultiOrgCode());
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
returnValue = user.getSysMultiOrgCode().stream()
.filter(Objects::nonNull)
.map(orgCode -> "'" + orgCode + "'")
.collect(Collectors.joining(", "));
//update-end---author:chenrui ---date:20250107 for[QQYUN-10785]数据权限,查看自己拥有部门的权限中存在问题 #7288------------
}
}
}

View File

@ -1,5 +1,6 @@
package org.jeecg.common.util;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
@ -8,11 +9,15 @@ import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.enums.DySmsEnum;
import org.jeecg.config.JeecgSmsTemplateConfig;
import org.jeecg.config.StaticConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
/**
* Created on 17/6/7.
* 短信API产品的DEMO程序,工程中包含了一个SmsDemo类直接通过
@ -75,15 +80,33 @@ public class DySmsHelper {
//验证json参数
validateParam(templateParamJson,dySmsEnum);
//update-begin---author:wangshuai---date:2024-11-05---for:【QQYUN-9422】短信模板管理阿里云---
String templateCode = dySmsEnum.getTemplateCode();
JeecgSmsTemplateConfig baseConfig = SpringContextUtils.getBean(JeecgSmsTemplateConfig.class);
if(baseConfig != null && CollectionUtil.isNotEmpty(baseConfig.getTemplateCode())){
Map<String, String> smsTemplate = baseConfig.getTemplateCode();
if(smsTemplate.containsKey(templateCode) && StringUtils.isNotEmpty(smsTemplate.get(templateCode))){
templateCode = smsTemplate.get(templateCode);
logger.info("yml中读取短信code{}",templateCode);
}
}
//签名名称
String signName = dySmsEnum.getSignName();
if(baseConfig != null && StringUtils.isNotEmpty(baseConfig.getSignature())){
logger.info("yml中读取签名名称{}",baseConfig.getSignature());
signName = baseConfig.getSignature();
}
//update-end---author:wangshuai---date:2024-11-05---for:【QQYUN-9422】短信模板管理阿里云---
//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers(phone);
//必填:短信签名-可在短信控制台中找到
request.setSignName(dySmsEnum.getSignName());
request.setSignName(signName);
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(dySmsEnum.getTemplateCode());
request.setTemplateCode(templateCode);
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam(templateParamJson.toJSONString());

View File

@ -0,0 +1,206 @@
package org.jeecg.common.util;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.jeecg.common.exception.JeecgBootException;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @program: file
* @description: 文件下载
* @author: chenrui
* @date: 2019-05-24 16:34
**/
@Slf4j
public class FileDownloadUtils {
/**
* 单文件下载
*
* @param response
* @param storePath 下载文件储存地址
* @param fileName 文件名称
* @author: chenrui
* @date: 2019/5/24 17:10
*/
public static void downloadFile(HttpServletResponse response, String storePath, String fileName) {
response.setCharacterEncoding("UTF-8");
File file = new File(storePath);
if (!file.exists()) {
throw new NullPointerException("Specified file not found");
}
if (fileName == null || fileName.isEmpty()) {
throw new NullPointerException("The file name can not null");
}
// 配置文件下载
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
// 下载文件能正常显示中文
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
// 实现文件下载
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);) {
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 多文件下载
*
* @param filesPath 下载文件集合
* @param zipFileName 多文件合称名
* @author: chenrui
* @date: 2019/5/24 17:48
*/
public static void downloadFileMulti(HttpServletResponse response, List<String> filesPath, String zipFileName) throws IOException {
//设置压缩包的名字
String downloadName = zipFileName + ".zip";
response.setCharacterEncoding("UTF-8");
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downloadName, "UTF-8"));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
log.info("开始压缩文件:" + filesPath);
//设置压缩流直接写入response实现边压缩边下载
try (ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
DataOutputStream os = new DataOutputStream(zipOut);) {
//设置压缩方法
zipOut.setMethod(ZipOutputStream.DEFLATED);
for (String filePath : filesPath) {
//循环将文件写入压缩流
File file = new File(filePath);
if (file.exists()) {
//添加ZipEntry并ZipEntry中写入文件流也就是将文件压入zip文件的目录下
String fileName = file.getName();
zipOut.putNextEntry(new ZipEntry(fileName));
//格式输出流文件
InputStream is = Files.newInputStream(file.toPath());
byte[] b = new byte[1024];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
zipOut.closeEntry();
}
}
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new JeecgBootException(e);
}
}
/**
* 下载网络资源到磁盘
*
* @param fileUrl
* @param storePath
* @author chenrui
* @date 2024/1/19 10:09
*/
public static String download2DiskFromNet(String fileUrl, String storePath) {
try {
URL url = new URL(fileUrl);
URLConnection conn = url.openConnection();
// 设置超时间为3秒
conn.setConnectTimeout(3 * 1000);
// 防止屏蔽程序
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 确保目录存在
File file = ensureDestFileDir(storePath);
try (InputStream inStream = conn.getInputStream();
FileOutputStream fs = new FileOutputStream(file);) {
int byteread;
byte[] buffer = new byte[1204];
while ((byteread = inStream.read(buffer)) != -1) {
fs.write(buffer, 0, byteread);
}
return storePath;
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new JeecgBootException(e);
}
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new JeecgBootException(e);
}
}
/**
* 获取不重名的文件
*
* @param file
* @return
* @author chenrui
* @date 2017年5月24日下午6:29:13
* @version v0.0.1
*/
public static File getUniqueFile(final File file) {
if (!file.exists()) {
return file;
}
File tmpFile = new File(file.getAbsolutePath());
File parentDir = tmpFile.getParentFile();
int count = 1;
String extension = FilenameUtils.getExtension(tmpFile.getName());
String baseName = FilenameUtils.getBaseName(tmpFile.getName());
do {
tmpFile = new File(parentDir, baseName + "(" + count++ + ")." + extension);
} while (tmpFile.exists());
return tmpFile;
}
/**
* 确保输出文件目录
*
* @param destFilePath
* @return
* @author: chenrui
* @date: 2019-05-21 16:49
*/
private static File ensureDestFileDir(String destFilePath) {
File destFile = new File(destFilePath);
FileDownloadUtils.checkDirAndCreate(destFile.getParentFile());
return destFile;
}
/**
* 验证文件夹存在且创建目录
*
* @param dir
* @author chenrui
* @date 2017年5月24日下午6:29:24
* @version v0.0.1
*/
public static void checkDirAndCreate(File dir) {
if (!dir.exists()) {
dir.mkdirs();
}
}
}

View File

@ -4,9 +4,13 @@ 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 jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.handler.IFillRuleHandler;
import org.jeecg.common.system.query.QueryGenerator;
/**
@ -42,6 +46,30 @@ public class FillRuleUtil {
if (params == null) {
params = new JSONObject();
}
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
// 解析 params 中的变量
// 优先级queryString > 系统变量 > 默认值
for (String key : params.keySet()) {
// 1. 判断 queryString 中是否有该参数,如果有就优先取值
//noinspection ConstantValue
if (request != null) {
String parameter = request.getParameter(key);
if (oConvertUtils.isNotEmpty(parameter)) {
params.put(key, parameter);
continue;
}
}
String value = params.getString(key);
// 2. 用于替换 系统变量的值 #{sys_user_code}
if (value != null && value.contains(SymbolConstant.SYS_VAR_PREFIX)) {
value = QueryGenerator.getSqlRuleValue(value);
params.put(key, value);
}
}
if (formData == null) {
formData = new JSONObject();
}

View File

@ -1,7 +1,9 @@
package org.jeecg.common.util;
import org.apache.commons.lang3.StringUtils;
import org.pegdown.PegDownProcessor;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.web.util.HtmlUtils;
/**
@ -36,8 +38,14 @@ public class HTMLUtils {
* @return
*/
public static String parseMarkdown(String markdownContent) {
PegDownProcessor pdp = new PegDownProcessor();
return pdp.markdownToHtml(markdownContent);
//update-begin---author:wangshuai---date:2024-06-26---for:【TV360X-1344】JDK17 邮箱发送失败,需要换写法---
/*PegDownProcessor pdp = new PegDownProcessor();
return pdp.markdownToHtml(markdownContent);*/
Parser parser = Parser.builder().build();
Node document = parser.parse(markdownContent);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
//update-end---author:wangshuai---date:2024-06-26---for:【TV360X-1344】JDK17 邮箱发送失败,需要换写法---
}
}

View File

@ -57,8 +57,8 @@ public class RestUtil {
static {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(3000);
requestFactory.setReadTimeout(3000);
requestFactory.setConnectTimeout(30000);
requestFactory.setReadTimeout(30000);
RT = new RestTemplate(requestFactory);
// 解决乱码问题
RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

View File

@ -84,6 +84,10 @@ public class DynamicDBUtil {
} else {
DruidDataSource dataSource = getJdbcDataSource(dbSource);
if(dataSource!=null && dataSource.isEnable()){
// 【TV360X-2060】设置超时时间 6秒
dataSource.setMaxWait(6000);
DataSourceCachePool.putCacheBasicDataSource(dbKey, dataSource);
}else{
throw new JeecgBootException("动态数据源连接失败dbKey"+dbKey);
@ -106,9 +110,10 @@ public class DynamicDBUtil {
dataSource.getConnection().commit();
dataSource.getConnection().close();
dataSource.close();
DataSourceCachePool.removeCache(dbKey);
}
} catch (SQLException e) {
e.printStackTrace();
log.warn(e.getMessage(), e);
}
}

View File

@ -73,6 +73,12 @@ public class JSqlParserUtils {
* @return
*/
private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) {
// 判断是否使用了union等操作
if (selectBody instanceof SetOperationList) {
// 如果使用了union等操作则只解析第一个查询
List<SelectBody> selectBodyList = ((SetOperationList) selectBody).getSelects();
return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0));
}
// 简单的select查询
if (selectBody instanceof PlainSelect) {
SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody);

View File

@ -58,8 +58,12 @@ public class JeecgBaseConfig {
* @return
*/
private WeiXinPay weiXinPay;
/**
* 百度开放API配置
*/
private BaiduApi baiduApi;
public Elasticsearch getElasticsearch() {
return elasticsearch;
}
@ -131,5 +135,13 @@ public class JeecgBaseConfig {
public void setWeiXinPay(WeiXinPay weiXinPay) {
this.weiXinPay = weiXinPay;
}
public BaiduApi getBaiduApi() {
return baiduApi;
}
public void setBaiduApi(BaiduApi baiduApi) {
this.baiduApi = baiduApi;
}
}

View File

@ -0,0 +1,33 @@
package org.jeecg.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @Description: 短信模板
*
* @author: wangshuai
* @date: 2024/11/5 下午3:44
*/
@Data
@Component("jeecgSmsTemplateConfig")
@ConfigurationProperties(prefix = "jeecg.oss.sms-template")
public class JeecgSmsTemplateConfig {
/**
* 短信签名
*/
private String signature;
/**
* 短信模板code
*
* @return
*/
private Map<String,String> templateCode;
}

View File

@ -21,6 +21,12 @@ public class StaticConfig {
@Value(value = "${spring.mail.username:}")
private String emailFrom;
/**
* 是否开启定时发送
*/
@Value(value = "${spring.mail.timeJobSend:false}")
private Boolean timeJobSend;
// /**
// * 签名密钥串
// */

View File

@ -1,9 +1,9 @@
//package org.jeecg.config;
//
// 已使用swagger3config平替
//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
//
//import io.swagger.annotations.ApiOperation;
//import org.jeecg.common.constant.CommonConstant;
//import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
//import org.springframework.beans.BeansException;
//import org.springframework.beans.factory.config.BeanPostProcessor;
//import org.springframework.context.annotation.Bean;
@ -19,15 +19,13 @@
//import springfox.documentation.builders.ParameterBuilder;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.oas.annotations.EnableOpenApi;
//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.WebFluxRequestHandlerProvider;
//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
//
//import java.lang.reflect.Field;
//import java.util.ArrayList;
@ -39,8 +37,7 @@
// * @Author scott
// */
//@Configuration
//@EnableSwagger2 //开启 Swagger2
//@EnableKnife4j //开启 knife4j可以不写
//@EnableSwagger2WebMvc
//@Import(BeanValidatorPluginsConfiguration.class)
//public class Swagger2Config implements WebMvcConfigurer {
//
@ -98,6 +95,14 @@
// 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());
// //update-begin-author:liusq---date:2024-08-15--for: 开启多租户时全局参数增加租户id
// if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
// ParameterBuilder tenantPar = new ParameterBuilder();
// tenantPar.name(CommonConstant.TENANT_ID).description("租户ID").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
// pars.add(tenantPar.build());
// }
// //update-end-author:liusq---date:2024-08-15--for: 开启多租户时全局参数增加租户id
//
// return pars;
// }
//
@ -152,7 +157,7 @@
//
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
// if (bean instanceof WebMvcRequestHandlerProvider) {
// customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
// }
// return bean;

View File

@ -40,7 +40,6 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
/**
* Spring Boot 2.0 解决跨域问题
@ -59,11 +58,6 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired(required = false)
private PrometheusMeterRegistry prometheusMeterRegistry;
@Autowired
private ObjectProvider<Jackson2ObjectMapperBuilder> builderProvider;
@Autowired
private JacksonProperties jacksonProperties;
/**
* 静态资源的配置 - 使得可以从磁盘中读取 Html、图片、视频、音频等
*/
@ -116,10 +110,6 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
@Primary
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
// 继承spring jackson 默认机制
if (Objects.nonNull(builderProvider.getIfAvailable())) {
objectMapper = builderProvider.getIfAvailable().createXmlMapper(false).build();
}
//处理bigDecimal
objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
@ -128,10 +118,8 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, false);
//默认的处理日期时间格式,接受通过spring.jackson.date-format配置格式化模式
if (Objects.isNull(jacksonProperties.getDateFormat())) {
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
//默认的处理日期时间格式
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
@ -143,17 +131,16 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
return objectMapper;
}
//update-begin---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
// /**
// * SpringBootAdmin的Httptrace不见了
// * https://blog.csdn.net/u013810234/article/details/110097201
// */
// @Bean
// public InMemoryHttpExchangeRepository getInMemoryHttpTrace(){
// InMemoryHttpExchangeRepository repository = new InMemoryHttpExchangeRepository();
// // 默认保存1000条http请求记录
// repository.setCapacity(1000);
// return repository;
// public InMemoryHttpTraceRepository getInMemoryHttpTrace(){
// return new InMemoryHttpTraceRepository();
// }
//update-end---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
/**

View File

@ -31,7 +31,7 @@ public class WebSocketConfig {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(websocketFilter());
//TODO 临时注释掉测试下线上socket总断的问题
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/dragChannelSocket/*", "/vxeSocket/*");
return bean;
}

View File

@ -1,8 +1,9 @@
package org.jeecg.config.security;
import lombok.RequiredArgsConstructor;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -18,10 +19,11 @@ import java.util.ArrayList;
* @date 2024/7/15 11:05
*/
@Component
@RequiredArgsConstructor
public class JeecgAuthenticationConvert implements Converter<Jwt, AbstractAuthenticationToken> {
private final CommonAPI commonAPI;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Override
public AbstractAuthenticationToken convert(Jwt source) {

View File

@ -7,6 +7,8 @@ import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.security.utils.SecureUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
@ -21,14 +23,16 @@ import java.util.Set;
* @date 2024/1/10 17:00
*/
@Service("jps")
@AllArgsConstructor
@Slf4j
public class JeecgPermissionService {
private final String SPLIT = "::";
private final String PERM_PREFIX = "jps" + SPLIT;
private final CommonAPI commonAPI;
private final RedisUtil redisUtil;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired
private RedisUtil redisUtil;
/**
* 判断接口是否有任意xxxxxx权限

View File

@ -1,7 +1,9 @@
package org.jeecg.config.security;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.lang.Nullable;
@ -28,14 +30,28 @@ import java.util.concurrent.TimeUnit;
* @author EightMonth
*/
@Component
@RequiredArgsConstructor
public class JeecgRedisOAuth2AuthorizationService implements OAuth2AuthorizationService {
public class JeecgRedisOAuth2AuthorizationService implements OAuth2AuthorizationService{
private final static Long TIMEOUT = 10L;
private static final String AUTHORIZATION = "token";
private final RedisTemplate<String, Object> redisTemplate;
private final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
@Autowired
private RedisConnectionFactory redisConnectionFactory;
/**
* 因为保存sas的认证信息至redis无法使用jeecg对redisTemplate的某些设置。
* 如果在使用时修改redisTemplate属性会发生线程安全问题最终容易引起系统无法正常运行。
* 所以重新建了一个redis client给到sas操作redis并且该redis实例不注入spring 容器中
*/
@PostConstruct
public void initSasRedis() {
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();
}
@Override
public void save(OAuth2Authorization authorization) {
@ -43,7 +59,6 @@ public class JeecgRedisOAuth2AuthorizationService implements OAuth2Authorization
if (isState(authorization)) {
String token = authorization.getAttribute("state");
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.STATE, token), authorization, TIMEOUT,
TimeUnit.MINUTES);
}
@ -54,7 +69,6 @@ public class JeecgRedisOAuth2AuthorizationService implements OAuth2Authorization
OAuth2AuthorizationCode authorizationCodeToken = authorizationCode.getToken();
long between = ChronoUnit.MINUTES.between(authorizationCodeToken.getIssuedAt(),
authorizationCodeToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.CODE, authorizationCodeToken.getTokenValue()),
authorization, between, TimeUnit.MINUTES);
}
@ -62,7 +76,6 @@ public class JeecgRedisOAuth2AuthorizationService implements OAuth2Authorization
if (isRefreshToken(authorization)) {
OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken();
long between = ChronoUnit.SECONDS.between(refreshToken.getIssuedAt(), refreshToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.REFRESH_TOKEN, refreshToken.getTokenValue()),
authorization, between, TimeUnit.SECONDS);
}
@ -70,7 +83,6 @@ public class JeecgRedisOAuth2AuthorizationService implements OAuth2Authorization
if (isAccessToken(authorization)) {
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
long between = ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt());
redisTemplate.setValueSerializer(RedisSerializer.java());
redisTemplate.opsForValue().set(buildKey(OAuth2ParameterNames.ACCESS_TOKEN, accessToken.getTokenValue()),
authorization, between, TimeUnit.SECONDS);
@ -125,7 +137,6 @@ public class JeecgRedisOAuth2AuthorizationService implements OAuth2Authorization
public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {
Assert.hasText(token, "token cannot be empty");
Assert.notNull(tokenType, "tokenType cannot be empty");
redisTemplate.setValueSerializer(RedisSerializer.java());
return (OAuth2Authorization) redisTemplate.opsForValue().get(buildKey(tokenType.getValue(), token));
}

View File

@ -16,6 +16,7 @@ import org.jeecg.config.security.phone.PhoneGrantAuthenticationConvert;
import org.jeecg.config.security.phone.PhoneGrantAuthenticationProvider;
import org.jeecg.config.security.social.SocialGrantAuthenticationConvert;
import org.jeecg.config.security.social.SocialGrantAuthenticationProvider;
import org.jeecg.config.shiro.ignore.InMemoryIgnoreAuth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
@ -42,6 +43,8 @@ import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.web.cors.CorsConfiguration;
import java.security.KeyPair;
@ -50,6 +53,7 @@ import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* spring authorization server核心配置
@ -102,6 +106,7 @@ public class SecurityConfig {
http
//设置所有请求都需要认证未认证的请求都被重定向到login页面进行登录
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(InMemoryIgnoreAuth.get().stream().map(AntPathRequestMatcher::antMatcher).toList().toArray(new AntPathRequestMatcher[0])).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/sys/cas/client/validateLogin")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/sys/randomImage/**")).permitAll()
.requestMatchers(AntPathRequestMatcher.antMatcher("/sys/checkCaptcha")).permitAll()

View File

@ -17,6 +17,7 @@ import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.security.password.PasswordGrantAuthenticationToken;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -55,6 +56,7 @@ public class AppGrantAuthenticationProvider implements AuthenticationProvider {
private final OAuth2AuthorizationService authorizationService;
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired

View File

@ -16,6 +16,7 @@ import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -56,6 +57,7 @@ public class PasswordGrantAuthenticationProvider implements AuthenticationProvid
private final OAuth2AuthorizationService authorizationService;
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired

View File

@ -16,6 +16,7 @@ import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.security.password.PasswordGrantAuthenticationToken;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -53,6 +54,7 @@ public class PhoneGrantAuthenticationProvider implements AuthenticationProvider
private final OAuth2AuthorizationService authorizationService;
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired

View File

@ -1,17 +1,15 @@
package org.jeecg.config.security.self;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysDepartModel;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -48,6 +46,7 @@ public class SelfAuthenticationProvider implements AuthenticationProvider {
private final OAuth2AuthorizationService authorizationService;
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired

View File

@ -15,6 +15,7 @@ import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.security.password.PasswordGrantAuthenticationToken;
import org.jeecg.modules.base.service.BaseCommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -51,6 +52,7 @@ public class SocialGrantAuthenticationProvider implements AuthenticationProvider
private final OAuth2AuthorizationService authorizationService;
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
@Lazy
@Autowired
private CommonAPI commonAPI;
@Autowired

View File

@ -3,21 +3,16 @@ package org.jeecg.config.shiro.ignore;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
/**
* 在spring boot初始化时根据@RestController注解获取当前spring容器中的bean
@ -27,32 +22,25 @@ import java.util.*;
@Slf4j
@Component
@AllArgsConstructor
public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
public class IgnoreAuthPostProcessor implements InitializingBean {
private RequestMappingHandlerMapping requestMappingHandlerMapping;
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
public void afterPropertiesSet() throws Exception {
long startTime = System.currentTimeMillis();
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));
}
}
Set<Class<?>> restControllers = requestMappingHandlerMapping.getHandlerMethods().values().stream().map(HandlerMethod::getBeanType).collect(Collectors.toSet());
for (Class<?> restController : restControllers) {
ignoreAuthUrls.addAll(postProcessRestController(restController));
}
log.info("Init Token ignoreAuthUrls Config [ 集合 ] {}", ignoreAuthUrls);
if (!CollectionUtils.isEmpty(ignoreAuthUrls)) {
InMemoryIgnoreAuth.set(ignoreAuthUrls);
// 添加免登录url
addIgnoreUrl(ignoreAuthUrls);
}
// 计算方法的耗时
@ -61,9 +49,8 @@ public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefre
log.info("Init Token ignoreAuthUrls Config [ 耗时 ] " + elapsedTime + "毫秒");
}
private List<String> postProcessRestController(Object restController) {
private List<String> postProcessRestController(Class<?> clazz) {
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();
@ -118,28 +105,4 @@ public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefre
private String prefix(String seg) {
return seg.startsWith("/") ? seg : "/"+seg;
}
private void addIgnoreUrl(List<String> urls){
FilterChainProxy obj = applicationContext.getBean(FilterChainProxy.class);
if (Objects.isNull(obj)) {
return;
}
List<SecurityFilterChain> filterChains = (List<SecurityFilterChain>) getProperty(obj,"filterChains");
if (!CollectionUtils.isEmpty(filterChains)) {
for (String url : urls) {
filterChains.add(0, new DefaultSecurityFilterChain(new AntPathRequestMatcher(url, null)));
}
}
}
private Object getProperty(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
return null;
}
}
}

View File

@ -0,0 +1,15 @@
package org.jeecg.config.vo;
import lombok.Data;
/**
* 百度开放api配置
*/
@Data
public class BaiduApi {
private String appId;
private String apiKey;
private String secretKey;
}

View File

@ -11,6 +11,10 @@ public class Firewall {
* 数据源安全 (开启后Online报表和图表的数据源为必填)
*/
private Boolean dataSourceSafe = false;
/**
* 是否禁止使用 * 查询所有字段
*/
private Boolean disableSelectAll = false;
/**
* 低代码模式dev:开发模式prod:发布模式——关闭所有在线开发配置能力)
*/
@ -36,4 +40,11 @@ public class Firewall {
this.lowCodeMode = lowCodeMode;
}
public Boolean getDisableSelectAll() {
return disableSelectAll;
}
public void setDisableSelectAll(Boolean disableSelectAll) {
this.disableSelectAll = disableSelectAll;
}
}

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -14,8 +14,10 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.Objects;
import java.util.function.Consumer;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* OpenAI的SSE监听
* @author chenrui
@ -29,22 +31,47 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
private SseEmitter sseEmitter;
private String topicId;
/**
* 回复消息内容
*/
private String messageContent = "";
/**
* 完成回复回调
*/
private Consumer<String> doneCallback;
/**
* 是否正在思考
*/
private boolean isThinking = false;
public OpenAISSEEventSourceListener(SseEmitter sseEmitter) {
this.sseEmitter = sseEmitter;
}
public OpenAISSEEventSourceListener(String topicId,SseEmitter sseEmitter){
public OpenAISSEEventSourceListener(String topicId, SseEmitter sseEmitter){
this.topicId = topicId;
this.sseEmitter = sseEmitter;
}
/**
* 设置消息完成响应时的回调
* for [QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持tink标签
* @param doneCallback
* @author chenrui
* @date 2025/2/7 18:14
*/
public void onDone(Consumer<String> doneCallback){
this.doneCallback = doneCallback;
}
/**
* {@inheritDoc}
*/
@Override
public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
log.info("OpenAI建立sse连接...");
log.info("ai-chat建立sse连接...");
}
/**
@ -53,10 +80,12 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
@SneakyThrows
@Override
public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
log.debug("OpenAI返回数据:{}", data);
log.debug("ai-chat返回数据:{}", data);
tokens += 1;
if (data.equals("[DONE]")) {
log.info("OpenAI返回数据结束了");
log.info("ai-chat返回数据结束了");
this.doneCallback.accept(messageContent);
messageContent = "";
sseEmitter.send(SseEmitter.event()
.id("[TOKENS]")
.data("<br/><br/>tokens" + tokens())
@ -72,12 +101,46 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
ObjectMapper mapper = new ObjectMapper();
ChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class); // 读取Json
try {
sseEmitter.send(SseEmitter.event()
.id(this.topicId)
.data(completionResponse.getChoices().get(0).getDelta())
.reconnectTime(3000));
//update-begin---author:chenrui ---date:20250207 for[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
// 兼容think标签
//update-begin---author:chenrui ---date:20250210 for判断空,防止反悔的内容为空报错.------------
if(null != completionResponse.getChoices()
&& !completionResponse.getChoices().isEmpty()
&& null != completionResponse.getChoices().get(0)) {
//update-end---author:chenrui ---date:20250210 for判断空,防止反悔的内容为空报错.------------
Message delta = completionResponse.getChoices().get(0).getDelta();
if (null != delta) {
String content = delta.getContent();
if ("<think>".equals(content)) {
isThinking = true;
content = "> ";
delta.setContent(content);
}
if ("</think>".equals(content)) {
isThinking = false;
content = "\n\n";
delta.setContent(content);
}
if (isThinking) {
if (null != content && content.contains("\n")) {
content = "\n> ";
delta.setContent(content);
}
} else {
// 响应消息体不记录思考过程
messageContent += null == content ? "" : content;
}
log.info("ai-chat返回数据,发送给前端:" + content);
sseEmitter.send(SseEmitter.event()
.id(this.topicId)
.data(delta)
.reconnectTime(3000));
}
}
//update-end---author:chenrui ---date:20250207 for[QQYUN-11102/QQYUN-11109]兼容deepseek模型,支持think标签------------
} catch (Exception e) {
log.error(e.getMessage(),e);
log.error("ai-chat返回数据,发生异常"+e.getMessage(),e);
sseEmitter.completeWithError(e);
eventSource.cancel();
}
}
@ -86,7 +149,7 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
@Override
public void onClosed(@NotNull EventSource eventSource) {
log.info("流式输出返回值总共{}tokens", tokens() - 2);
log.info("OpenAI关闭sse连接...");
log.info("ai-chat关闭sse连接...");
}
@ -96,10 +159,10 @@ public class OpenAISSEEventSourceListener extends EventSourceListener {
String errMsg = "";
ResponseBody body = null == response ? null:response.body();
if (Objects.nonNull(body)) {
log.error("OpenAI sse连接异常data{},异常:{}", body.string(), t.getMessage());
log.error("ai-chat sse连接异常data{},异常:{}", body.string(), t.getMessage());
errMsg = body.string();
} else {
log.error("OpenAI sse连接异常data{},异常:{}", response, t.getMessage());
log.error("ai-chat sse连接异常data{},异常:{}", response, t.getMessage());
errMsg = t.getMessage();
}
eventSource.cancel();

View File

@ -9,6 +9,7 @@ import com.unfbx.chatgpt.entity.chat.Message;
import com.unfbx.chatgpt.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.chatgpt.prop.AiChatProperties;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
@ -58,13 +59,12 @@ public class ChatServiceImpl implements ChatService {
private OpenAiStreamClient openAiStreamClient = null;
/**
* ai聊天配置
* for [QQYUN-10943]【AI 重要】jeecg-boot-starter-chatgpt 支持deepseek等国产模型
*/
private AiChatProperties aiChatProperties;
//update-begin---author:chenrui ---date:20240131 for[QQYUN-8212]fix 没有配置启动报错------------
public ChatServiceImpl() {
try {
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
} catch (Exception ignored) {
}
}
/**
* 防止client不能成功注入
@ -72,11 +72,17 @@ public class ChatServiceImpl implements ChatService {
* @author chenrui
* @date 2024/2/3 23:08
*/
private OpenAiStreamClient ensureClient(){
if(null == this.openAiStreamClient){
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
private void ensureClient(){
if (null == this.openAiStreamClient){
//update-begin---author:chenrui ---date:20240625 for[TV360X-1570]给于更友好的提示提示未配置ai------------
try {
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
this.aiChatProperties = SpringContextUtils.getBean(AiChatProperties.class);
} catch (Exception ignored) {
sendErrorMsg("如果您想使用AI助手请先设置相应配置!");
}
//update-end---author:chenrui ---date:20240625 for[TV360X-1570]给于更友好的提示提示未配置ai------------
}
return this.openAiStreamClient;
}
//update-end---author:chenrui ---date:20240131 for[QQYUN-8212]fix 没有配置启动报错------------
@ -98,6 +104,7 @@ public class ChatServiceImpl implements ChatService {
//超时回调
sseEmitter.onTimeout(() -> {
log.info("[{}]连接超时...................", uid);
LocalCache.CACHE.remove(uid);
});
//异常回调
sseEmitter.onError(
@ -109,7 +116,7 @@ public class ChatServiceImpl implements ChatService {
.name("发生异常!")
.data(Message.builder().content("发生异常请重试!").build())
.reconnectTime(3000));
LocalCache.CACHE.put(uid, sseEmitter);
LocalCache.CACHE.remove(uid);
} catch (IOException e) {
log.error(e.getMessage(),e);
}
@ -138,6 +145,7 @@ public class ChatServiceImpl implements ChatService {
@Override
public void sendMessage(String topicId, String message) {
ensureClient();
String uid = getUserId();
if (StrUtil.isBlank(message)) {
log.info("参数异常message为null");
@ -163,16 +171,25 @@ public class ChatServiceImpl implements ChatService {
log.info("聊天消息推送失败uid:[{}],没有创建连接,请重试。", uid);
throw new JeecgBootException("聊天消息推送失败uid:[{}],没有创建连接,请重试。~");
}
OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(topicId, sseEmitter);
ChatCompletion completion = ChatCompletion
.builder()
.messages(msgHistory)
.model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
.build();
ensureClient().streamChatCompletion(completion, openAIEventSourceListener);
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(msgHistory));
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
Result.ok(completion.tokens());
//update-begin---author:chenrui ---date:20240625 for[TV360X-1570]给于更友好的提示提示未配置ai------------
if (null != openAiStreamClient) {
OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(topicId, sseEmitter);
List<Message> finalMsgHistory = msgHistory;
openAIEventSourceListener.onDone(respMessage -> {
Message tempMessage = Message.builder().content(respMessage).role(Message.Role.ASSISTANT).build();
finalMsgHistory.add(tempMessage);
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(finalMsgHistory));
});
log.info("话题:{},开始发送消息~~~", topicId);
ChatCompletion completion = ChatCompletion
.builder()
.messages(msgHistory)
.model(aiChatProperties.getModel())
.build();
openAiStreamClient.streamChatCompletion(completion, openAIEventSourceListener);
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
}
//update-end---author:chenrui ---date:20240625 for[TV360X-1570]给于更友好的提示提示未配置ai------------
}
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
@ -194,6 +211,35 @@ public class ChatServiceImpl implements ChatService {
return Result.OK(chatHistoryVO);
}
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
/**
* 发送异常消息给前端
* [TV360X-1570]给于更友好的提示提示未配置ai
*
* @param msg
* @author chenrui
* @date 2024/6/25 10:38
*/
private void sendErrorMsg(String msg) {
String uid = getUserId();
SseEmitter sseEmitter = (SseEmitter) LocalCache.CACHE.get(uid);
if (sseEmitter == null) {
return;
}
try {
sseEmitter.send(SseEmitter.event()
.id("[ERR]")
.data(Message.builder().content(msg).build())
.reconnectTime(3000));
sseEmitter.send(SseEmitter.event()
.id("[DONE]")
.data("[DONE]")
.reconnectTime(3000));
sseEmitter.complete();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
//update-end---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------

View File

@ -95,7 +95,7 @@ public class JeecgOrderMainServiceImpl extends ServiceImpl<JeecgOrderMainMapper,
// 当传过来的id数据库不存在时说明数据库没有走新增逻辑
ticket.setOrderId(jeecgOrderMain.getId());
jeecgOrderTicketMapper.insert(ticket);
break;
continue;
}
if(orderTicket.getId().equals(ticket.getId())){
// 传过来的id和数据库id一至时说明数据库存在该数据走更新逻辑
@ -109,7 +109,7 @@ public class JeecgOrderMainServiceImpl extends ServiceImpl<JeecgOrderMainMapper,
// 当传过来的id数据库不存在时说明数据库没有走新增逻辑
customer.setOrderId(jeecgOrderMain.getId());
jeecgOrderCustomerMapper.insert(customer);
break;
continue;
}
if(customers.getId().equals(customer.getId())){
//TODO 传过来的id和数据库id一至时说明数据库存在该数据走更新逻辑

View File

@ -0,0 +1,370 @@
{
"list": [
{
"key": "1717072932495_439966",
"type": "card",
"isAutoGrid": true,
"isContainer": true,
"list": [
{
"type": "input",
"name": "名称",
"className": "form-input",
"icon": "icon-input",
"hideTitle": false,
"options": {
"width": "100%",
"defaultValue": "",
"required": true,
"dataType": null,
"pattern": "",
"placeholder": "",
"clearable": false,
"readonly": false,
"disabled": false,
"fillRuleCode": "",
"showPassword": false,
"unique": false,
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"autoWidth": 50
},
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"remoteAPI": {
"url": "",
"executed": false
},
"key": "1717072932495_556479",
"model": "input_1717072932495_556479",
"modelType": "main",
"rules": [
{
"required": true,
"message": "${title}必须填写"
}
],
"isSubItem": false
},
{
"type": "number",
"name": "数字",
"className": "form-number",
"icon": "icon-number",
"hideTitle": false,
"options": {
"width": "",
"required": false,
"defaultValue": 0,
"placeholder": "",
"controls": false,
"min": 0,
"minUnlimited": true,
"max": 100,
"maxUnlimited": true,
"step": 1,
"disabled": false,
"controlsPosition": "right",
"unitText": "",
"unitPosition": "suffix",
"showPercent": false,
"align": "left",
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"autoWidth": 50
},
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "number",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"remoteAPI": {
"url": "",
"executed": false
},
"key": "1717072985868_606195",
"model": "number_1717072985868_606195",
"modelType": "main",
"rules": [],
"isSubItem": false
}
],
"options": {
"required": false,
"hiddenOnAdd": false,
"hidden": false,
"fieldNote": ""
},
"model": "card_1717072932495_439966",
"hideTitle": false,
"modelType": "main"
},
{
"key": "1717072988159_545097",
"type": "card",
"isAutoGrid": true,
"isContainer": true,
"list": [
{
"type": "money",
"name": "金额",
"className": "form-money",
"icon": "icon-money",
"hideTitle": false,
"options": {
"width": "180px",
"placeholder": "请输入金额",
"required": false,
"unitText": "元",
"unitPosition": "suffix",
"precision": 2,
"hidden": false,
"disabled": false,
"hiddenOnAdd": false,
"fieldNote": "",
"autoWidth": 50
},
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "number",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"remoteAPI": {
"url": "",
"executed": false
},
"key": "1717072988159_568693",
"model": "money_1717072988159_568693",
"modelType": "main",
"rules": [],
"isSubItem": false
},
{
"type": "select",
"name": "下拉选择框",
"className": "form-select",
"icon": "icon-select",
"hideTitle": false,
"options": {
"defaultValue": "",
"multiple": false,
"disabled": false,
"clearable": true,
"placeholder": "",
"required": false,
"showLabel": false,
"showType": "default",
"width": "",
"useColor": false,
"colorIteratorIndex": 3,
"options": [
{
"value": "下拉框1",
"itemColor": "#2196F3"
},
{
"value": "下拉框2",
"itemColor": "#08C9C9"
},
{
"value": "下拉框3",
"itemColor": "#00C345"
}
],
"remote": false,
"filterable": false,
"remoteOptions": [],
"props": {
"value": "value",
"label": "label"
},
"remoteFunc": "",
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"autoWidth": 50
},
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": ",",
"customConfig": true
}
},
"remoteAPI": {
"url": "",
"executed": false
},
"key": "1717072991431_622198",
"model": "select_1717072991431_622198",
"modelType": "main",
"rules": [],
"isSubItem": false
}
],
"options": {
"required": false,
"hiddenOnAdd": false,
"hidden": false,
"fieldNote": ""
},
"model": "card_1717072988159_545097",
"hideTitle": false,
"modelType": "main"
},
{
"key": "1717072932495_382575",
"type": "card",
"isAutoGrid": true,
"isContainer": true,
"list": [
{
"type": "imgupload",
"name": "图片上传",
"className": "form-tupian",
"icon": "icon-tupian",
"hideTitle": false,
"options": {
"defaultValue": [],
"size": {
"width": 100,
"height": 100
},
"width": "",
"tokenFunc": "funcGetToken",
"token": "",
"domain": "http://img.h5huodong.com",
"disabled": false,
"length": 9,
"multiple": true,
"hidden": false,
"hiddenOnAdd": false,
"required": false,
"fieldNote": "",
"autoWidth": 50
},
"key": "1717072996509_795340",
"model": "imgupload_1717072996509_795340",
"modelType": "main",
"rules": [],
"isSubItem": false
},
{
"type": "file-upload",
"name": "附件",
"className": "form-file-upload",
"icon": "icon-shangchuan",
"hideTitle": false,
"options": {
"defaultValue": [],
"token": "",
"length": 1,
"drag": false,
"multiple": false,
"disabled": false,
"buttonText": "添加附件",
"tokenFunc": "funcGetToken",
"hidden": false,
"hiddenOnAdd": false,
"required": false,
"fieldNote": "",
"autoWidth": 50
},
"key": "1717072932495_669325",
"model": "file_upload_1717072932495_669325",
"modelType": "main",
"rules": [],
"isSubItem": false
}
],
"options": {
"required": false,
"hiddenOnAdd": false,
"hidden": false,
"fieldNote": ""
},
"model": "card_1717072932495_382575",
"hideTitle": false,
"modelType": "main"
}
],
"config": {
"titleField": "input_1717072932495_556479",
"showHeaderTitle": true,
"labelWidth": 100,
"labelPosition": "top",
"size": "small",
"dialogOptions": {
"top": 20,
"width": 1000,
"padding": {
"top": 25,
"right": 25,
"bottom": 30,
"left": 25
}
},
"disabledAutoGrid": false,
"designMobileView": false,
"enableComment": true,
"hasWidgets": [
"input",
"number",
"card",
"money",
"select",
"imgupload",
"file-upload"
],
"expand": {
"js": "",
"css": "",
"url": {
"js": "",
"css": ""
}
},
"transactional": true,
"customRequestURL": [
{
"url": ""
}
],
"allowExternalLink": false,
"externalLinkShowData": false,
"headerImgUrl": "",
"externalTitle": "",
"enableNotice": false,
"noticeMode": "external",
"noticeType": "system",
"noticeReceiver": "",
"allowPrint": false,
"allowJmReport": false,
"jmReportURL": "",
"bizRuleConfig": [],
"bigDataMode": false
}
}

View File

@ -0,0 +1,496 @@
{
"list": [
{
"hideTitle": false,
"options": {
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"required": false
},
"isContainer": true,
"model": "card_1717072902303_783177",
"modelType": "main",
"type": "card",
"isAutoGrid": true,
"list": [
{
"isSubItem": false,
"remoteAPI": {
"executed": false,
"url": ""
},
"icon": "icon-input",
"className": "form-input",
"rules": [
{
"required": true,
"message": "${title}必须填写"
}
],
"modelType": "main",
"type": "input",
"hideTitle": false,
"name": "名称",
"options": {
"clearable": false,
"hidden": false,
"defaultValue": "",
"pattern": "",
"fillRuleCode": "",
"fieldNote": "",
"required": true,
"readonly": false,
"unique": false,
"hiddenOnAdd": false,
"width": "100%",
"autoWidth": 100,
"showPassword": false,
"disabled": false,
"placeholder": ""
},
"model": "input_1717072902303_477529",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"key": "1717072902303_477529"
}
],
"key": "1717072902303_783177"
},
{
"options": {
"required": false,
"hiddenOnAdd": false,
"hidden": false,
"fieldNote": ""
},
"isContainer": true,
"model": "card_1717073019436_526262",
"type": "card",
"isAutoGrid": true,
"list": [
{
"isSubItem": false,
"remoteAPI": {
"executed": false,
"url": ""
},
"icon": "icon-number",
"className": "form-number",
"rules": [],
"modelType": "main",
"type": "number",
"hideTitle": false,
"name": "数字",
"options": {
"controls": false,
"showPercent": false,
"hidden": false,
"max": 100,
"defaultValue": 0,
"unitPosition": "suffix",
"fieldNote": "",
"maxUnlimited": true,
"align": "left",
"required": false,
"min": 0,
"minUnlimited": true,
"hiddenOnAdd": false,
"width": "",
"autoWidth": 50,
"step": 1,
"disabled": false,
"placeholder": "",
"controlsPosition": "right",
"unitText": ""
},
"model": "number_1717073019436_586474",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "number",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"key": "1717073019436_586474"
},
{
"isSubItem": false,
"remoteAPI": {
"executed": false,
"url": ""
},
"icon": "icon-money",
"className": "form-money",
"rules": [],
"modelType": "main",
"type": "money",
"hideTitle": false,
"name": "金额",
"options": {
"hidden": false,
"precision": 2,
"hiddenOnAdd": false,
"width": "180px",
"autoWidth": 50,
"unitPosition": "suffix",
"disabled": false,
"fieldNote": "",
"placeholder": "请输入金额",
"required": false,
"unitText": "元"
},
"model": "money_1717073021100_526660",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "number",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"key": "1717073021100_526660"
}
],
"key": "1717073019436_526262",
"hideTitle": false,
"modelType": "main"
},
{
"hideTitle": false,
"options": {
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"required": false
},
"isContainer": true,
"model": "card_1717072902303_118977",
"modelType": "main",
"type": "card",
"isAutoGrid": true,
"list": [
{
"isSubItem": false,
"remoteAPI": {
"executed": false,
"url": ""
},
"icon": "icon-select",
"className": "form-select",
"rules": [],
"modelType": "main",
"type": "select",
"hideTitle": false,
"name": "下拉选择框",
"options": {
"remoteFunc": "",
"filterable": false,
"clearable": true,
"hidden": false,
"defaultValue": "",
"remoteOptions": [],
"multiple": false,
"fieldNote": "",
"remote": false,
"required": false,
"showLabel": false,
"useColor": false,
"props": {
"label": "label",
"value": "value"
},
"colorIteratorIndex": 3,
"hiddenOnAdd": false,
"width": "",
"options": [
{
"itemColor": "#2196F3",
"value": "下拉框1"
},
{
"itemColor": "#08C9C9",
"value": "下拉框2"
},
{
"itemColor": "#00C345",
"value": "下拉框3"
}
],
"autoWidth": 50,
"showType": "default",
"disabled": false,
"placeholder": ""
},
"model": "select_1717073033259_273399",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": ",",
"customConfig": true
}
},
"key": "1717073033259_273399"
},
{
"isSubItem": false,
"remoteAPI": {
"executed": false,
"url": ""
},
"icon": "icon-textarea",
"className": "form-textarea",
"rules": [],
"modelType": "main",
"type": "textarea",
"hideTitle": false,
"name": "描述",
"options": {
"readonly": false,
"hidden": false,
"defaultValue": "",
"unique": false,
"hiddenOnAdd": false,
"width": "100%",
"pattern": "",
"autoWidth": 50,
"disabled": false,
"fieldNote": "",
"placeholder": "",
"required": false
},
"model": "textarea_1717072902303_129466",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": "",
"customConfig": false
}
},
"key": "1717072902303_129466"
}
],
"key": "1717072902303_118977"
},
{
"hideTitle": false,
"options": {
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": "",
"required": false
},
"isContainer": true,
"model": "card_1717072902304_736053",
"modelType": "main",
"type": "card",
"isAutoGrid": true,
"list": [
{
"hideTitle": false,
"isSubItem": false,
"name": "图片上传",
"icon": "icon-tupian",
"options": {
"hidden": false,
"defaultValue": [],
"length": 9,
"multiple": true,
"fieldNote": "",
"required": false,
"token": "",
"size": {
"width": 100,
"height": 100
},
"tokenFunc": "funcGetToken",
"domain": "http://img.h5huodong.com",
"hiddenOnAdd": false,
"width": "",
"autoWidth": 50,
"disabled": false
},
"className": "form-tupian",
"model": "imgupload_1717073025137_563739",
"rules": [],
"modelType": "main",
"type": "imgupload",
"key": "1717073025137_563739"
},
{
"hideTitle": false,
"isSubItem": false,
"name": "附件",
"icon": "icon-shangchuan",
"options": {
"buttonText": "添加附件",
"hidden": false,
"defaultValue": [],
"length": 1,
"multiple": false,
"fieldNote": "",
"required": false,
"token": "",
"tokenFunc": "funcGetToken",
"hiddenOnAdd": false,
"autoWidth": 50,
"disabled": false,
"drag": false
},
"className": "form-file-upload",
"model": "file_upload_1717072902304_442777",
"rules": [],
"modelType": "main",
"type": "file-upload",
"key": "1717072902304_442777"
}
],
"key": "1717072902304_736053"
},
{
"isSubItem": false,
"remoteAPI": {
"url": "",
"executed": false
},
"icon": "icon-link",
"className": "form-link-record",
"rules": [],
"modelType": "main",
"type": "link-record",
"hideTitle": false,
"name": "主表@表单控件",
"options": {
"sourceCode": "ai_control_main",
"showMode": "single",
"showType": "card",
"titleField": "wen_ben",
"showFields": [],
"allowView": true,
"allowEdit": true,
"allowAdd": true,
"allowSelect": true,
"buttonText": "添加记录",
"twoWayModel": "sub_table_design_1717137038626_791984",
"dataSelectAuth": "all",
"filters": [
{
"matchType": "AND",
"rules": []
}
],
"search": {
"enabled": false,
"field": "",
"rule": "like",
"afterShow": false,
"fields": []
},
"createMode": {
"add": true,
"select": false,
"params": {
"selectLinkModel": ""
}
},
"width": "100%",
"defaultValue": "",
"defaultValType": "none",
"required": false,
"disabled": false,
"hidden": false,
"hiddenOnAdd": false,
"fieldNote": ""
},
"model": "link_record_1717137044235_306956",
"advancedSetting": {
"defaultValue": {
"type": "compose",
"value": "",
"format": "string",
"allowFunc": true,
"valueSplit": "",
"customConfig": true
}
},
"key": "1717137044235_306956"
}
],
"config": {
"jmReportURL": "",
"enableComment": true,
"dialogOptions": {
"padding": {
"top": 25,
"left": 25,
"bottom": 30,
"right": 25
},
"top": 20,
"width": 1000
},
"allowJmReport": false,
"labelWidth": 100,
"headerImgUrl": "",
"noticeMode": "external",
"noticeReceiver": "",
"designMobileView": false,
"labelPosition": "top",
"allowPrint": false,
"enableNotice": false,
"bizRuleConfig": [],
"showHeaderTitle": true,
"bigDataMode": false,
"titleField": "input_1717072902303_477529",
"externalTitle": "",
"noticeType": "system",
"customRequestURL": [
{
"url": ""
}
],
"hasWidgets": [
"input",
"card",
"number",
"money",
"select",
"textarea",
"imgupload",
"file-upload",
"link-record"
],
"expand": {
"css": "",
"js": "",
"url": {
"css": "",
"js": ""
}
},
"size": "small",
"disabledAutoGrid": false,
"allowExternalLink": false,
"externalLinkShowData": false,
"transactional": true
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -597,7 +597,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @return
*/
@GetMapping("/sys/api/loadDictItemByKeyword")
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize);
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageNo", defaultValue = "1", required = false) Integer pageNo, @RequestParam(value = "pageSize", required = false) Integer pageSize);
/**
* 47 根据多个部门id(逗号分隔),查询返回多个部门信息

View File

@ -382,7 +382,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize) {
return null;
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -457,7 +457,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @param pageSize 分页条数
* @return
*/
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize);
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize);
/**
* 新增数据日志

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.7.0</version>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -27,7 +27,7 @@
<!-- 企业微信/钉钉 api -->
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>jeewx-api</artifactId>
<artifactId>weixin4j</artifactId>
</dependency>
<!-- 积木报表 -->
<dependency>
@ -36,14 +36,13 @@
</dependency>
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>drag-free-springboot3</artifactId>
<version>1.1.2</version>
<artifactId>jimureport-nosql-starter</artifactId>
</dependency>
<!-- 积木报表 mongo redis 支持包
<!-- 积木BI -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-nosql-starter</artifactId>
</dependency>-->
<artifactId>jimubi-spring-boot3-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,5 +1,6 @@
package org.jeecg.config.jimureport;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.system.api.ISysBaseAPI;
@ -13,6 +14,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
@ -42,18 +44,38 @@ public class JimuDragExternalServiceImpl implements IOnlDragExternalService {
* @return key = dictCode value=对应的字典项
*/
@Override
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList) {
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList, List<JSONObject> tableDictList) {
Map<String, List<DragDictModel>> manyDragDictItems = new HashMap<>();
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
dictItemsMap.forEach((k,v)->{
List<DragDictModel> dictItems = new ArrayList<>();
v.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
if(!CollectionUtils.isEmpty(codeList)){
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
dictItemsMap.forEach((k,v)->{
List<DragDictModel> dictItems = new ArrayList<>();
v.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
});
manyDragDictItems.put(k,dictItems);
});
manyDragDictItems.put(k,dictItems);
});
}
if(!CollectionUtils.isEmpty(tableDictList)){
tableDictList.forEach(item->{
List<DragDictModel> dictItems = new ArrayList<>();
JSONObject object = JSONObject.parseObject(item.toString());
String dictField = object.getString("dictField");
String dictTable = object.getString("dictTable");
String dictText = object.getString("dictText");
String fieldName = object.getString("fieldName");
List<DictModel> dictItemsList = sysBaseApi.queryTableDictItemsByCode(dictTable,dictText,dictField);
dictItemsList.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
});
manyDragDictItems.put(fieldName,dictItems);
});
}
return manyDragDictItems;
}

View File

@ -78,4 +78,30 @@ public class JimuReportTokenService implements JmReportTokenServiceI {
// 将所有信息存放至map 解析sql/api会根据map的键值解析
return map;
}
/**
* 将jeecgboot平台的权限传递给积木报表
* @param token
* @return
*/
@Override
public String[] getPermissions(String token) {
// 获取用户信息
String username = JwtUtil.getUsername(token);
SysUserCacheInfo userInfo = null;
try {
userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage());
}
if(userInfo == null){
return null;
}
// 查询权限
Set<String> userPermissions = sysBaseApi.getUserPermissionSet(userInfo.getSysUserId());
if(CollectionUtils.isEmpty(userPermissions)){
return null;
}
return userPermissions.toArray(new String[0]);
}
}

View File

@ -98,7 +98,7 @@ public class SystemApiController {
try {
SensitiveInfoUtil.handlerObject(loginUser, true);
} catch (IllegalAccessException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
return loginUser;
}
@ -666,8 +666,11 @@ public class SystemApiController {
* @return
*/
@GetMapping("/loadDictItemByKeyword")
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize) {
return sysBaseApi.loadDictItemByKeyword(dictCode, keyword, pageSize);
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode,
@RequestParam("keyword") String keyword,
@RequestParam(value = "pageNo", defaultValue = "1", required = false) Integer pageNo,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
return sysBaseApi.loadDictItemByKeyword(dictCode, keyword,pageNo, pageSize);
}
/**

View File

@ -5,12 +5,15 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.StaticConfig;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.handle.ISendMsgHandle;
import org.jeecg.modules.message.mapper.SysMessageMapper;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
@ -43,6 +46,9 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
@Autowired
private RedisUtil redisUtil;
@Autowired
private SysMessageMapper sysMessageMapper;
/**
* 真实姓名变量
@ -78,6 +84,23 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
@Override
public void sendMessage(MessageDTO messageDTO) {
String content = messageDTO.getContent();
String title = messageDTO.getTitle();
//update-begin---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
boolean timeJobSendEmail = this.isTimeJobSendEmail(messageDTO.getToUser(), title, content);
if(timeJobSendEmail){
return;
}
//update-end---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
this.sendEmailMessage(messageDTO);
}
/**
* 直接发送邮件
*
* @param messageDTO
*/
public void sendEmailMessage(MessageDTO messageDTO) {
String[] arr = messageDTO.getToUser().split(",");
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>().in(SysUser::getUsername, arr);
List<SysUser> list = sysUserMapper.selectList(query);
@ -213,4 +236,35 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 1 / 1000);
return token;
}
/**
* 是否定时发送邮箱
* @param toUser
* @param title
* @param content
* @return
*/
private boolean isTimeJobSendEmail(String toUser, String title, String content) {
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
Boolean timeJobSend = staticConfig.getTimeJobSend();
if(null != timeJobSend && timeJobSend){
this.addSysSmsSend(toUser,title,content);
return true;
}
return false;
}
/**
* 保存到短信发送表
*/
private void addSysSmsSend(String toUser, String title, String content) {
SysMessage sysMessage = new SysMessage();
sysMessage.setEsTitle(title);
sysMessage.setEsContent(content);
sysMessage.setEsReceiver(toUser);
sysMessage.setEsSendStatus("0");
sysMessage.setEsSendNum(0);
sysMessage.setEsType(MessageTypeEnum.YJ.getType());
sysMessageMapper.insert(sysMessage);
}
}

View File

@ -51,6 +51,9 @@ public class SendMsgJob implements Job {
md.setToUser(sysMessage.getEsReceiver());
md.setType(sysMessage.getEsType());
md.setToAll(false);
//update-begin---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
md.setIsTimeJob(true);
//update-end---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
sysBaseAPI.sendTemplateMessage(md);
//发送消息成功
sysMessage.setEsSendStatus(SendMsgStatusEnum.SUCCESS.getCode());

View File

@ -18,7 +18,7 @@ import static org.springframework.boot.actuate.endpoint.annotation.Selector.Matc
* @Date: 2024/5/13 17:02
*/
@Component
@Endpoint(id = "httptrace-new")
@Endpoint(id = "jeecghttptrace")
public class CustomHttpTraceEndpoint{
private final CustomInMemoryHttpTraceRepository repository;

View File

@ -26,27 +26,31 @@ public class ActuatorMemoryController {
/**
* 内存详情
* @return
* @throws Exception
*/
@GetMapping("/info")
public Result<?> getRedisInfo() throws Exception {
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
JSONObject operatingSystemJson = JSONObject.parseObject(JSONObject.toJSONString(operatingSystemMXBean));
long totalPhysicalMemory = operatingSystemJson.getLongValue("totalPhysicalMemorySize");
long freePhysicalMemory = operatingSystemJson.getLongValue("freePhysicalMemorySize");
long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
public Result<?> getRedisInfo() {
Runtime runtime = Runtime.getRuntime();
Map<String,Number> result = new HashMap<>();
result.put("memory.physical.total", totalPhysicalMemory);
result.put("memory.physical.used", freePhysicalMemory);
result.put("memory.physical.free", usedPhysicalMemory);
result.put("memory.physical.usage", NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory));
result.put("memory.runtime.total", runtime.totalMemory());
result.put("memory.runtime.used", runtime.freeMemory());
result.put("memory.runtime.max", runtime.totalMemory() - runtime.freeMemory());
result.put("memory.runtime.free", runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory());
result.put("memory.runtime.usage", NumberUtil.div(runtime.totalMemory() - runtime.freeMemory(), runtime.totalMemory()));
return Result.ok(result);
//update-begin---author:chenrui ---date:20240705 for[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
if (operatingSystemMXBean instanceof com.sun.management.OperatingSystemMXBean) {
com.sun.management.OperatingSystemMXBean opBean = (com.sun.management.OperatingSystemMXBean) operatingSystemMXBean;
// JSONObject operatingSystemJson = JSONObject.parseObject(JSONObject.toJSONString(operatingSystemMXBean));
long totalPhysicalMemory = opBean.getTotalPhysicalMemorySize();
long freePhysicalMemory = opBean.getFreePhysicalMemorySize();
long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
result.put("memory.physical.total", totalPhysicalMemory);
result.put("memory.physical.used", freePhysicalMemory);
result.put("memory.physical.free", usedPhysicalMemory);
result.put("memory.physical.usage", NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory));
}
//update-end---author:chenrui ---date:20240705 for[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
return Result.ok(result);
}
}

View File

@ -13,6 +13,7 @@ import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.quartz.entity.QuartzJob;
import org.jeecg.modules.quartz.service.IQuartzJobService;
@ -207,6 +208,12 @@ public class QuartzJobController {
public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {
// Step.1 组装查询条件
QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
// 过滤选中数据
String selections = request.getParameter("selections");
if (oConvertUtils.isNotEmpty(selections)) {
List<String> selectionList = Arrays.asList(selections.split(","));
queryWrapper.in("id",selectionList);
}
// Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
List<QuartzJob> pageList = quartzJobService.list(queryWrapper);

View File

@ -51,7 +51,7 @@ public class CommonController {
*/
@GetMapping("/403")
public Result<?> noauth() {
return Result.error("没有权限,请联系管理员授权,后刷新缓存!");
return Result.error("没有权限,请联系管理员分配权限!");
}
/**

View File

@ -6,6 +6,7 @@ import java.util.Date;
import com.alibaba.fastjson.JSON;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
@ -219,13 +220,21 @@ public class SysAnnouncementSendController {
@GetMapping(value = "/getMyAnnouncementSend")
public Result<IPage<AnnouncementSendModel>> getMyAnnouncementSend(AnnouncementSendModel announcementSendModel,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
Result<IPage<AnnouncementSendModel>> result = new Result<IPage<AnnouncementSendModel>>();
LoginUser sysUser = SecureUtil.currentUser();
String userId = sysUser.getId();
announcementSendModel.setUserId(userId);
announcementSendModel.setPageNo((pageNo-1)*pageSize);
announcementSendModel.setPageSize(pageSize);
//update-begin---author:wangshuai---date:2024-06-11---for:【TV360X-545】我的消息列表不能通过时间范围查询---
if(StringUtils.isNotEmpty(announcementSendModel.getSendTimeBegin())){
announcementSendModel.setSendTimeBegin(announcementSendModel.getSendTimeBegin() + " 00:00:00");
}
if(StringUtils.isNotEmpty(announcementSendModel.getSendTimeBegin())){
announcementSendModel.setSendTimeEnd(announcementSendModel.getSendTimeEnd() + " 23:59:59");
}
//update-end---author:wangshuai---date:2024-06-11---for:【TV360X-545】我的消息列表不能通过时间范围查询---
Page<AnnouncementSendModel> pageList = new Page<AnnouncementSendModel>(pageNo,pageSize);
pageList = sysAnnouncementSendService.getMyAnnouncementSendPage(pageList, announcementSendModel);
result.setResult(pageList);

View File

@ -14,6 +14,7 @@ import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.YouBianCodeUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
@ -67,6 +68,8 @@ public class SysDepartController {
private ISysUserService sysUserService;
@Autowired
private ISysUserDepartService sysUserDepartService;
@Autowired
private RedisUtil redisUtil;
/**
* 查询数据 查出我的部门,并以树结构数据格式响应给前端
*
@ -366,9 +369,17 @@ public class SysDepartController {
//return arg0.getOrgCode().compareTo(arg1.getOrgCode());
//}
//});
// 过滤选中数据
String selections = request.getParameter("selections");
List<String> idList = new ArrayList<>();
if (oConvertUtils.isNotEmpty(selections)) {
idList = Arrays.asList(selections.split(","));
}
//step.2 组装导出数据
Integer tenantId = sysDepart == null ? null : sysDepart.getTenantId();
List<SysDepartExportVo> sysDepartExportVos = sysDepartService.getExportDepart(tenantId);
//update-begin---author:wangshuai---date:2024-07-05---for:【TV360X-1671】部门管理不支持选中的记录导出---
List<SysDepartExportVo> sysDepartExportVos = sysDepartService.getExportDepart(tenantId,idList);
//update-end---author:wangshuai---date:2024-07-05---for:【TV360X-1671】部门管理不支持选中的记录导出---
//导出文件名称
mv.addObject(NormalExcelConstants.FILE_NAME, "部门列表");
mv.addObject(NormalExcelConstants.CLASS, SysDepartExportVo.class);
@ -464,8 +475,8 @@ public class SysDepartController {
//update-end---author:wangshuai---date:2023-10-19---for:【QQYUN-5482】系统的部门导入导出也可以改成敲敲云模式的部门路径---
//清空部门缓存
Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*");
Set keys4 = redisTemplate.keys(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
List<String> keys3 = redisUtil.scan(CacheConstant.SYS_DEPARTS_CACHE + "*");
List<String> keys4 = redisUtil.scan(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
redisTemplate.delete(keys3);
redisTemplate.delete(keys4);
return ImportExcelUtil.imporReturnRes(errorMessageList.size(), listSysDeparts.size() - errorMessageList.size(), errorMessageList);
@ -658,8 +669,8 @@ public class SysDepartController {
listSysDeparts = ExcelImportUtil.importExcel(file.getInputStream(), ExportDepartVo.class, params);
sysDepartService.importExcel(listSysDeparts,errorMessageList);
//清空部门缓存
Set keys3 = redisTemplate.keys(CacheConstant.SYS_DEPARTS_CACHE + "*");
Set keys4 = redisTemplate.keys(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
List<String> keys3 = redisUtil.scan(CacheConstant.SYS_DEPARTS_CACHE + "*");
List<String> keys4 = redisUtil.scan(CacheConstant.SYS_DEPART_IDS_CACHE + "*");
redisTemplate.delete(keys3);
redisTemplate.delete(keys4);
return ImportExcelUtil.imporReturnRes(errorMessageList.size(), listSysDeparts.size() - errorMessageList.size(), errorMessageList);

View File

@ -94,12 +94,15 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
// queryWrapper.in("depart_id",deptIds);
//我的部门,选中部门只能看当前部门下的角色
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10775]验证码可以复用 #7674------------
if(oConvertUtils.isNotEmpty(deptId)){
queryWrapper.eq("depart_id",deptId);
IPage<SysDepartRole> pageList = sysDepartRoleService.page(page, queryWrapper);
return Result.ok(pageList);
}else{
return Result.ok(null);
}
IPage<SysDepartRole> pageList = sysDepartRoleService.page(page, queryWrapper);
return Result.ok(pageList);
//update-end---author:chenrui ---date:20250107 for[QQYUN-10775]验证码可以复用 #7674------------
}
/**
@ -156,7 +159,8 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
@PreAuthorize("@jps.requiresPermissions('system:depart:role:deleteBatch')")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.sysDepartRoleService.removeByIds(Arrays.asList(ids.split(",")));
this.sysDepartRoleService.deleteDepartRole(Arrays.asList(ids.split(",")));
//this.sysDepartRoleService.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}

View File

@ -2,11 +2,13 @@ package org.jeecg.modules.system.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CacheConstant;
@ -75,8 +77,14 @@ public class SysDictController {
private JeecgPermissionService jeecgPermissionService;
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<IPage<SysDict>> queryPageList(SysDict sysDict,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
public Result<IPage<SysDict>> queryPageList(
SysDict sysDict,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
// 查询关键字模糊筛选code和name
@RequestParam(name = "keywords", required = false) String keywords,
HttpServletRequest req
) {
Result<IPage<SysDict>> result = new Result<IPage<SysDict>>();
//------------------------------------------------------------------------------------------------
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
@ -85,7 +93,12 @@ public class SysDictController {
}
//------------------------------------------------------------------------------------------------
QueryWrapper<SysDict> queryWrapper = QueryGenerator.initQueryWrapper(sysDict, req.getParameterMap());
Page<SysDict> page = new Page<SysDict>(pageNo, pageSize);
// 查询关键字模糊筛选code和name
if (oConvertUtils.isNotEmpty(keywords)) {
queryWrapper.and(i -> i.like("dict_code", keywords).or().like("dict_name", keywords));
}
Page<SysDict> page = new Page<>(pageNo, pageSize);
IPage<SysDict> pageList = sysDictService.page(page, queryWrapper);
log.debug("查询当前页:"+pageList.getCurrent());
log.debug("查询当前页数量:"+pageList.getSize());
@ -199,7 +212,8 @@ public class SysDictController {
public Result<List<DictModel>> loadDict(@PathVariable("dictCode") String dictCode,
@RequestParam(name="keyword",required = false) String keyword,
@RequestParam(value = "sign",required = false) String sign,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
@RequestParam(name = "pageNo", defaultValue = "1", required = false) Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10", required = false) Integer pageSize) {
//update-begin-author:taoyan date:2023-5-22 for: /issues/4905 因为中括号(%5)的问题导致的 表单生成器字段配置时,选择关联字段,在进行高级配置时,无法加载数据库列表,提示 Sgin签名校验错误 #4905 RouteToRequestUrlFilter
if(keyword!=null && keyword.indexOf("%5")>=0){
@ -214,7 +228,7 @@ public class SysDictController {
log.info(" 加载字典表数据,加载关键字: "+ keyword);
Result<List<DictModel>> result = new Result<List<DictModel>>();
try {
List<DictModel> ls = sysDictService.loadDict(dictCode, keyword, pageSize);
List<DictModel> ls = sysDictService.loadDict(dictCode, keyword, pageNo,pageSize);
if (ls == null) {
result.error500("字典Code格式不正确");
return result;
@ -246,12 +260,12 @@ public class SysDictController {
@RequestParam(value = "sign", required = false) String sign,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
// 首次查询查出来用户选中的值,并且不分页
Result<List<DictModel>> firstRes = this.loadDict(dictCode, keyword, sign, null);
Result<List<DictModel>> firstRes = this.loadDict(dictCode, keyword, sign,null, null);
if (!firstRes.isSuccess()) {
return firstRes;
}
// 然后再查询出第一页的数据
Result<List<DictModel>> result = this.loadDict(dictCode, "", sign, pageSize);
Result<List<DictModel>> result = this.loadDict(dictCode, "", sign,1, pageSize);
if (!result.isSuccess()) {
return result;
}
@ -660,6 +674,45 @@ public class SysDictController {
return Result.error("操作失败!");
}
}
/**
* 还原被逻辑删除的用户
*
* @param jsonObject
* @return
*/
@RequestMapping(value = "/putRecycleBin", method = RequestMethod.PUT)
public Result putRecycleBin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
try {
String ids = jsonObject.getString("ids");
if (StringUtils.isNotBlank(ids)) {
sysDictService.revertLogicDeleted(Arrays.asList(ids.split(",")));
return Result.ok("操作成功!");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error("操作失败!");
}
return Result.ok("还原成功");
}
/**
* 彻底删除字典
*
* @param ids 被删除的字典ID多个id用半角逗号分割
* @return
*/
@PreAuthorize("@jps.requiresPermissions('system:dict:deleteRecycleBin')")
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
public Result deleteRecycleBin(@RequestParam("ids") String ids) {
try {
if (StringUtils.isNotBlank(ids)) {
sysDictService.removeLogicDeleted(Arrays.asList(ids.split(",")));
}
return Result.ok("删除成功!");
} catch (Exception e) {
e.printStackTrace();
return Result.error("删除失败!");
}
}
/**
* VUEN-2584【issue】平台sql注入漏洞几个问题

View File

@ -4,7 +4,9 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.oConvertUtils;
@ -14,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
@ -74,4 +77,72 @@ public class SysGatewayRouteController extends JeecgController<SysGatewayRoute,
return Result.ok("删除路由成功");
}
/**
* 查询被删除的列表
* @return
*/
@RequestMapping(value = "/deleteList", method = RequestMethod.GET)
public Result<List<SysGatewayRoute>> deleteList(HttpServletRequest request) {
Result<List<SysGatewayRoute>> result = new Result<>();
List<SysGatewayRoute> list = sysGatewayRouteService.getDeletelist();
result.setSuccess(true);
result.setResult(list);
return result;
}
/**
* 还原被逻辑删除的路由
*
* @param jsonObject
* @return
*/
@PreAuthorize("@jps.requiresPermissions('system:getway:putRecycleBin')")
@RequestMapping(value = "/putRecycleBin", method = RequestMethod.PUT)
public Result putRecycleBin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
try {
String ids = jsonObject.getString("ids");
if (StringUtils.isNotBlank(ids)) {
sysGatewayRouteService.revertLogicDeleted(Arrays.asList(ids.split(",")));
return Result.ok("操作成功!");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error("操作失败!");
}
return Result.ok("还原成功");
}
/**
* 彻底删除路由
*
* @param ids 被删除的路由ID多个id用半角逗号分割
* @return
*/
@PreAuthorize("@jps.requiresPermissions('system:getway:deleteRecycleBin')")
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
public Result deleteRecycleBin(@RequestParam("ids") String ids) {
try {
if (StringUtils.isNotBlank(ids)) {
sysGatewayRouteService.deleteLogicDeleted(Arrays.asList(ids.split(",")));
}
return Result.ok("删除成功!");
} catch (Exception e) {
e.printStackTrace();
return Result.error("删除失败!");
}
}
/**
* 复制路由
*
* @param id 路由id
* @return
*/
@PreAuthorize("@jps.requiresPermissions('system:getway:copyRoute')")
@RequestMapping(value = "/copyRoute", method = RequestMethod.GET)
public Result<SysGatewayRoute> copyRoute(@RequestParam(name = "id", required = true) String id, HttpServletRequest req) {
Result<SysGatewayRoute> result = new Result<>();
SysGatewayRoute sysGatewayRoute= sysGatewayRouteService.copyRoute(id);
result.setResult(sysGatewayRoute);
result.setSuccess(true);
return result;
}
}

View File

@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
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.SymbolConstant;

View File

@ -220,26 +220,31 @@ public class SysPositionController {
* @param response
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, HttpServletResponse response) {
public ModelAndView exportXls(SysPosition sysPosition,HttpServletRequest request, HttpServletResponse response) {
// Step.1 组装查询条件
QueryWrapper<SysPosition> queryWrapper = null;
try {
String paramsStr = request.getParameter("paramsStr");
if (oConvertUtils.isNotEmpty(paramsStr)) {
String deString = URLDecoder.decode(paramsStr, "UTF-8");
SysPosition sysPosition = JSON.parseObject(deString, SysPosition.class);
sysPosition = JSON.parseObject(deString, SysPosition.class);
//------------------------------------------------------------------------------------------------
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
sysPosition.setTenantId(oConvertUtils.getInt(TenantContext.getTenant(),0));
}
//------------------------------------------------------------------------------------------------
queryWrapper = QueryGenerator.initQueryWrapper(sysPosition, request.getParameterMap());
}
queryWrapper = QueryGenerator.initQueryWrapper(sysPosition, request.getParameterMap());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//update-begin--Author:liusq Date:20240715 for[03]职务导出,如果选择数据则只导出相关数据--------------------
String selections = request.getParameter("selections");
if(!oConvertUtils.isEmpty(selections)){
queryWrapper.in("id",selections.split(","));
}
//update-end--Author:liusq Date:20240715 for[03]职务导出,如果选择数据则只导出相关数据----------------------
//Step.2 AutoPoi 导出Excel
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
List<SysPosition> pageList = sysPositionService.list(queryWrapper);

View File

@ -220,7 +220,7 @@ public class SysRoleController {
String username = "admin";
if(getRoleCount == 0 && !username.equals(sysUser.getUsername())){
baseCommonService.addLog("未经授权删除非本租户下的角色ID" + id + ",操作人:" + sysUser.getUsername(), CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_4);
return Result.error("删除角色失败,删除角色不属于登录租户!");
return Result.error("删除角色失败,当前角色不在此租户中。");
}
}

View File

@ -41,8 +41,9 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
* @param req
* @return
*/
//@RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:list')")
@GetMapping(value = "/list")
@PreAuthorize("@jps.requiresRoles('admin')")
public Result<?> queryPageList(
SysTableWhiteList sysTableWhiteList,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@ -63,7 +64,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
*/
@AutoLog(value = "系统表白名单-添加")
@Operation(summary = "系统表白名单-添加")
@PreAuthorize("@jps.requiresRoles('admin')")
//@RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:add')")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody SysTableWhiteList sysTableWhiteList) {
if (sysTableWhiteListService.add(sysTableWhiteList)) {
@ -81,7 +83,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
*/
@AutoLog(value = "系统表白名单-编辑")
@Operation(summary = "系统表白名单-编辑")
@PreAuthorize("@jps.requiresRoles('admin')")
//@RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:edit')")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public Result<?> edit(@RequestBody SysTableWhiteList sysTableWhiteList) {
if (sysTableWhiteListService.edit(sysTableWhiteList)) {
@ -99,7 +102,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
*/
@AutoLog(value = "系统表白名单-通过id删除")
@Operation(summary = "系统表白名单-通过id删除")
@PreAuthorize("@jps.requiresRoles('admin')")
// @RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:delete')")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id") String id) {
if (sysTableWhiteListService.deleteByIds(id)) {
@ -117,7 +121,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
*/
@AutoLog(value = "系统表白名单-批量删除")
@Operation(summary = "系统表白名单-批量删除")
@PreAuthorize("@jps.requiresRoles('admin')")
// @RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:deleteBatch')")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids") String ids) {
if (sysTableWhiteListService.deleteByIds(ids)) {
@ -135,7 +140,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
*/
@AutoLog(value = "系统表白名单-通过id查询")
@Operation(summary = "系统表白名单-通过id查询")
@PreAuthorize("@jps.requiresRoles('admin')")
// @RequiresRoles("admin")
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:queryById')")
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
SysTableWhiteList sysTableWhiteList = sysTableWhiteListService.getById(id);

View File

@ -24,11 +24,7 @@ import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.config.security.utils.SecureUtil;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.service.ISysTenantPackService;
import org.jeecg.modules.system.service.ISysTenantService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.service.ISysUserTenantService;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.vo.SysUserTenantVo;
import org.jeecg.modules.system.vo.tenant.TenantDepartAuthInfo;
import org.jeecg.modules.system.vo.tenant.TenantPackModel;
@ -151,6 +147,21 @@ public class SysTenantController {
return result;
}
/**
* [QQYUN-11032]【jeecg】租户套餐管理增加初始化套餐包按钮
* @param tenantId
* @return
* @author chenrui
* @date 2025/2/6 18:24
*/
@PreAuthorize("@jps.requiresPermissions('system:tenant:syncDefaultPack')")
@PostMapping(value = "/syncDefaultPack")
public Result<?> syncDefaultPack(@RequestParam(name="tenantId",required=true) Integer tenantId) {
//同步默认产品包
sysTenantPackService.syncDefaultPack(tenantId);
return Result.OK("操作成功");
}
/**
* 编辑
* @param

View File

@ -206,7 +206,8 @@ public class SysUserController {
// 修改用户走一个service 保证事务
//获取租户ids
String relTenantIds = jsonObject.getString("relTenantIds");
sysUserService.editUser(user, roles, departs, relTenantIds);
String updateFromPage = jsonObject.getString("updateFromPage");
sysUserService.editUser(user, roles, departs, relTenantIds, updateFromPage);
result.success("修改成功!");
}
} catch (Exception e) {
@ -223,7 +224,12 @@ public class SysUserController {
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
baseCommonService.addLog("删除用户id " +id ,CommonConstant.LOG_TYPE_2, 3);
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(id));
this.sysUserService.deleteUser(id);
if (!userNameList.isEmpty()) {
String joinedString = String.join(",", userNameList);
}
return Result.ok("删除用户成功");
}
@ -234,7 +240,13 @@ public class SysUserController {
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
baseCommonService.addLog("批量删除用户, ids " +ids ,CommonConstant.LOG_TYPE_2, 3);
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(ids.split(",")));
this.sysUserService.deleteBatchUsers(ids);
// 用户变更,触发同步工作流
if (!userNameList.isEmpty()) {
String joinedString = String.join(",", userNameList);
}
return Result.ok("批量删除用户成功");
}
@ -737,7 +749,10 @@ public class SysUserController {
if(oConvertUtils.isEmpty(depId)){
LoginUser user = SecureUtil.currentUser();
int userIdentity = user.getUserIdentity() != null?user.getUserIdentity():CommonConstant.USER_IDENTITY_1;
if(oConvertUtils.isNotEmpty(userIdentity) && userIdentity == CommonConstant.USER_IDENTITY_2 ){
//update-begin---author:chenrui ---date:20250107 for[QQYUN-10775]验证码可以复用 #7674------------
if(oConvertUtils.isNotEmpty(userIdentity) && userIdentity == CommonConstant.USER_IDENTITY_2
&& oConvertUtils.isNotEmpty(user.getDepartIds())) {
//update-end---author:chenrui ---date:20250107 for[QQYUN-10775]验证码可以复用 #7674------------
subDepids = sysDepartService.getMySubDepIdsByDepId(user.getDepartIds());
}
}else{
@ -907,6 +922,9 @@ public class SysUserController {
boolean b = sysUserDepartService.remove(queryWrapper);
if(b){
departRoleUserService.removeDeptRoleUser(Arrays.asList(userIds.split(",")),depId);
}else{
result.error500("删除失败,目标用户不在当前部门!");
return result;
}
result.success("删除成功!");
}catch(Exception e) {
@ -1287,7 +1305,7 @@ public class SysUserController {
* @param jsonObject
* @return
*/
@PreAuthorize("@jps.requiresRoles('admin')")
@PreAuthorize("@jps.requiresPermissions('system:user:app:edit')")
@RequestMapping(value = "/appEdit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysUser> appEdit(HttpServletRequest request,@RequestBody JSONObject jsonObject) {
Result<SysUser> result = new Result<SysUser>();
@ -1830,4 +1848,57 @@ public class SysUserController {
public Result<?> importAppUser(HttpServletRequest request, HttpServletResponse response)throws IOException {
return sysUserService.importAppUser(request);
}
/**
* 更改手机号(敲敲云个人设置专用)
*
* @param json
* @param request
*/
@PutMapping("/changePhone")
public Result<String> changePhone(@RequestBody JSONObject json, HttpServletRequest request){
//获取登录用户名
String username = JwtUtil.getUserNameByToken(request);
sysUserService.changePhone(json,username);
return Result.ok("修改手机号成功!");
}
/**
* 发送短信验证码接口(修改手机号)
*
* @param jsonObject
* @return
*/
@PostMapping(value = "/sendChangePhoneSms")
public Result<String> sendChangePhoneSms(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
//获取登录用户名
String username = JwtUtil.getUserNameByToken(request);
String ipAddress = IpUtils.getIpAddr(request);
sysUserService.sendChangePhoneSms(jsonObject, username, ipAddress);
return Result.ok("发送验证码成功!");
}
/**
* 发送注销用户手机号验证密码[敲敲云专用]
*
* @param jsonObject
* @return
*/
@PostMapping(value = "/sendLogOffPhoneSms")
public Result<String> sendLogOffPhoneSms(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
Result<String> result = new Result<>();
//获取登录用户名
String username = JwtUtil.getUserNameByToken(request);
String name = jsonObject.getString("username");
if (oConvertUtils.isEmpty(name) || !name.equals(username)) {
result.setSuccess(false);
result.setMessage("发送验证码失败,用户不匹配!");
return result;
}
String ipAddress = IpUtils.getIpAddr(request);
sysUserService.sendLogOffPhoneSms(jsonObject, username, ipAddress);
result.setSuccess(true);
result.setMessage("发送验证码成功!");
return result;
}
}

View File

@ -59,7 +59,7 @@ public class SysUserOnlineController {
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
Collection<String> keys = redisTemplate.keys(CommonConstant.PREFIX_USER_TOKEN + "*");
Collection<String> keys = redisUtil.scan(CommonConstant.PREFIX_USER_TOKEN + "*");
List<SysUserOnlineVO> onlineList = new ArrayList<SysUserOnlineVO>();
for (String key : keys) {
String token = (String)redisUtil.get(key);

View File

@ -11,12 +11,15 @@ import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.*;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysThirdAccount;
import org.jeecg.modules.system.entity.SysThirdAppConfig;
import org.jeecg.modules.system.entity.SysUser;
@ -25,6 +28,7 @@ import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.system.service.ISysThirdAccountService;
import org.jeecg.modules.system.service.ISysThirdAppConfigService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
@ -60,6 +64,8 @@ public class ThirdLoginController {
private RedisUtil redisUtil;
@Autowired
private AuthRequestFactory factory;
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private ThirdAppWechatEnterpriseServiceImpl thirdAppWechatEnterpriseService;
@ -69,6 +75,9 @@ public class ThirdLoginController {
@Autowired
private ISysThirdAppConfigService appConfigService;
@Autowired
public ISysBaseAPI sysBaseAPI;
@RequestMapping("/render/{source}")
public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
log.info("第三方登录进入render" + source);
@ -223,7 +232,11 @@ public class ThirdLoginController {
public Result<JSONObject> getThirdLoginUser(@PathVariable("token") String token,@PathVariable("thirdType") String thirdType,@PathVariable("tenantId") String tenantId) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
String username = JwtUtil.getUsername(token);
//update-begin---author:chenrui ---date:20250210 for[QQYUN-11021]三方登录接口通过token获取用户信息漏洞修复------------
if (!TokenUtils.verifyToken(token, sysBaseAPI, redisUtil)) {
return Result.noauth("token验证失败");
}
//update-end---author:chenrui ---date:20250210 for[QQYUN-11021]三方登录接口通过token获取用户信息漏洞修复------------
//1. 校验用户是否有效
SysUser sysUser = sysUserService.getUserByName(username);
result = sysUserService.checkUserIsEffective(sysUser);
@ -250,8 +263,8 @@ public class ThirdLoginController {
}
//update-end-author:wangshuai date:20201118 for:如果真实姓名和头像不存在就取第三方登录的
JSONObject obj = new JSONObject();
//TODO 第三方登确定登录租户和部门逻辑
//第三方登确定登录租户和部门逻辑
this.setUserTenantAndDepart(sysUser,obj,result);
//用户登录信息
obj.put("userInfo", sysUser);
//获取字典缓存【解决 #jeecg-boot/issues/3998】
@ -528,4 +541,88 @@ public class ThirdLoginController {
return Result.error("注册失败");
}
}
/**
* 设置用户租户和部门信息
*
* @param sysUser
* @param obj
* @param result
*/
private void setUserTenantAndDepart(SysUser sysUser, JSONObject obj, Result<JSONObject> result) {
//1.设置登录租户
sysUserService.setLoginTenant(sysUser, obj, sysUser.getUsername(), result);
//2.设置登录部门
String orgCode = sysUser.getOrgCode();
//部门不为空还是用原来的部门code
if(StringUtils.isEmpty(orgCode)){
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
//部门不为空取第一个作为当前登录部门
if(CollectionUtil.isNotEmpty(departs)){
orgCode = departs.get(0).getOrgCode();
sysUser.setOrgCode(orgCode);
this.sysUserService.updateUserDepart(sysUser.getUsername(), orgCode,null);
}
}
}
/**
* 新版钉钉登录
*
* @param authCode
* @param state
* @param tenantId
* @param response
* @return
*/
@ResponseBody
@GetMapping("/oauth2/dingding/login")
public String OauthDingDingLogin(@RequestParam(value = "authCode", required = false) String authCode,
@RequestParam("state") String state,
@RequestParam(name = "tenantId",defaultValue = "0") String tenantId,
HttpServletResponse response) {
SysUser loginUser = thirdAppDingtalkService.oauthDingDingLogin(authCode,Integer.valueOf(tenantId));
try {
String redirect = "";
if (state.indexOf("?") > 0) {
String[] arr = state.split("\\?");
state = arr[0];
if(arr.length>1){
redirect = arr[1];
}
}
String token = saveToken(loginUser);
state += "/oauth2-app/login?oauth2LoginToken=" + URLEncoder.encode(token, "UTF-8") + "&tenantId=" + URLEncoder.encode(tenantId, "UTF-8");
state += "&thirdType=DINGTALK";
if (redirect != null && redirect.length() > 0) {
state += "&" + redirect;
}
log.info("OAuth2登录重定向地址: " + state);
try {
response.sendRedirect(state);
return "ok";
} catch (IOException e) {
log.error(e.getMessage(),e);
return "重定向失败";
}
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(),e);
return "解码失败";
}
}
/**
* 获取企业id和应用id
* @param tenantId
* @return
*/
@ResponseBody
@GetMapping("/get/corpId/clientId")
public Result<SysThirdAppConfig> getCorpIdClientId(@RequestParam(value = "tenantId", defaultValue = "0") String tenantId){
Result<SysThirdAppConfig> result = new Result<>();
SysThirdAppConfig sysThirdAppConfig = thirdAppDingtalkService.getCorpIdClientId(Integer.valueOf(tenantId));
result.setSuccess(true);
result.setResult(sysThirdAppConfig);
return result;
}
}

View File

@ -1,6 +1,8 @@
package org.jeecg.modules.system.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.system.util.XssUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -22,8 +24,13 @@ public class WechatVerifyController {
*/
@RequestMapping(value = "/WW_verify_{code}.txt")
public void mpVerify(@PathVariable("code") String code, HttpServletResponse response) {
if(StringUtils.isEmpty(code)){
log.error("企业微信证书验证失败!(code为空)");
return;
}
try {
PrintWriter writer = response.getWriter();
code = XssUtils.scriptXss(code);
writer.write(code);
writer.close();
} catch (Exception e) {

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
@ -76,4 +77,11 @@ public class SysComment implements Serializable {
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@Schema(description = "更新日期")
private Date updateTime;
/**
* 不是数据库字段,用于评论跳转
*/
@TableField(exist = false)
private String tableId;
}

View File

@ -2,6 +2,7 @@ package org.jeecg.modules.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
@ -96,6 +97,12 @@ public class SysGatewayRoute implements Serializable {
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@Schema(description = "创建日期")
private Date createTime;
/**
* 删除状态0未删除1已删除
*/
@TableLogic
private Integer delFlag;
/* *//**更新人*//*
@Schema(description = "更新人")
private String updateBy;

View File

@ -46,7 +46,7 @@ public class SysPosition {
/**
* 职级
*/
@Excel(name = "职级", width = 15,dicCode ="position_rank")
//@Excel(name = "职级", width = 15,dicCode ="position_rank")
@Schema(description = "职级")
@Dict(dicCode = "position_rank")
private java.lang.String postRank;

View File

@ -51,10 +51,10 @@ public class SysThirdAppConfig {
@Schema(description = "钉钉/企业微信应用id对应的秘钥")
private String clientSecret;
/**企业微信自建应用Secret*/
@Excel(name = "企业微信自建应用Secret", width = 15)
@Schema(description = "企业微信自建应用Secret")
private String agentAppSecret;
/**钉钉企业id*/
@Excel(name = "钉钉企业id", width = 15)
@Schema(description = "钉钉企业id")
private String corpId;
/**第三方类别(dingtalk 钉钉 wechat_enterprise 企业微信)*/
@Excel(name = "第三方类别(dingtalk 钉钉 wechat_enterprise 企业微信)", width = 15)

View File

@ -177,5 +177,5 @@ public interface SysDepartMapper extends BaseMapper<SysDepart> {
* @param parentId
* @return
*/
List<SysDepartExportVo> getSysDepartList(@Param("parentId") String parentId,@Param("tenantId") Integer tenantId);
List<SysDepartExportVo> getSysDepartList(@Param("parentId") String parentId,@Param("tenantId") Integer tenantId, List<String> idList);
}

View File

@ -14,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface SysDepartRolePermissionMapper extends BaseMapper<SysDepartRolePermission> {
void deleteByRoleIds(@Param("ids")List<String> ids);
}

View File

@ -14,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface SysDepartRoleUserMapper extends BaseMapper<SysDepartRoleUser> {
void deleteByRoleIds(@Param("ids")List<String> ids);
}

View File

@ -200,4 +200,18 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
*/
@Select("select * from sys_dict where del_flag = 1 and tenant_id = #{tenantId}")
List<SysDict> queryDeleteListBtTenantId(@Param("tenantId") Integer tenantId);
/**
* 还原被逻辑删除的数据根据id
* @param ids
* @return
*/
int revertLogicDeleted(@Param("ids") List<String> ids);
/**
* 彻底删除的数据根据ids
* @param ids
* @return
*/
int removeLogicDeleted(@Param("ids")List<String> ids);
}

View File

@ -1,8 +1,12 @@
package org.jeecg.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.system.entity.SysGatewayRoute;
import java.util.List;
/**
* @Description: gateway路由管理
* @Author: jeecg-boot
@ -10,5 +14,22 @@ import org.jeecg.modules.system.entity.SysGatewayRoute;
* @Version: V1.0
*/
public interface SysGatewayRouteMapper extends BaseMapper<SysGatewayRoute> {
/**
* 还原逻辑删除
* @param ids
*/
int revertLogicDeleted(@Param("ids") List<String> ids);
/**
*彻底删除
* @param ids
*/
int deleteLogicDeleted(@Param("ids") List<String> ids);
/**
* 查询删除的列表
* @return
*/
@Select("select * from sys_gateway_route where del_flag = 1")
List<SysGatewayRoute> queryDeleteList();
}

View File

@ -47,7 +47,10 @@
<!-- 获取用户未读消息数量 -->
<select id="getUnreadMessageCountByUserId" resultType="java.lang.Integer">
select count(1) from sys_announcement_send where user_id = #{userId} and read_flag = 0 and create_time &gt;= #{beginDate}
<!-- update by wangshuai 2024-07-02【TV360X-1682】撤销之后数量还显示但是点开面板没有这条数据他会一直显示有数据需要联查判断已经发送的-->
select count(1) from sys_announcement_send sas
right join sys_announcement sa on sas.annt_id = sa.id and sa.send_status = '1'
where sas.user_id = #{userId} and sas.read_flag = 0 and sas.create_time &gt;= #{beginDate}
</select>
<!-- 查询消息记录 -->

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