mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-08 17:12:28 +08:00
Compare commits
89 Commits
v3.7.0_spr
...
v3.7.0_all
| Author | SHA1 | Date | |
|---|---|---|---|
| 39ca47d2ef | |||
| 824f3c2b90 | |||
| 70607dbe2b | |||
| 7e2b4c68ec | |||
| 5359fc4112 | |||
| c31a4e8ab4 | |||
| 2b773d6e6b | |||
| 996a56bd59 | |||
| 4d48f9b500 | |||
| 2570e454ed | |||
| 4fd8ae1f94 | |||
| 72829aa2af | |||
| 0cada33e49 | |||
| ca2a56248c | |||
| 6846e9fdef | |||
| 33be0079f0 | |||
| 31a865f5e0 | |||
| 114f59f712 | |||
| 7eef470d28 | |||
| ae9e85d3f6 | |||
| e9ac37d118 | |||
| 1d2b10c2a5 | |||
| 34442b7226 | |||
| c75e9bf05b | |||
| d1ac35108d | |||
| e0fb952146 | |||
| 4aa4c57db4 | |||
| 517600f9a4 | |||
| 1c9e76931f | |||
| d0f09480ca | |||
| e99deb1c33 | |||
| 099e745b8f | |||
| 5898656227 | |||
| 7dcf8f9b5a | |||
| 4753a74456 | |||
| 0a76623c53 | |||
| cd6bb2ca04 | |||
| 819555e612 | |||
| 0148a0b45e | |||
| 7049e9974e | |||
| 1243fe1cad | |||
| b189e6de52 | |||
| 5dd3bdc23f | |||
| 7015eef621 | |||
| fd92d516ee | |||
| 606f079a93 | |||
| ab86013e7b | |||
| 11ac387559 | |||
| ec93d615f4 | |||
| fbebaf456b | |||
| 7ea46609b1 | |||
| e3cd6bfc97 | |||
| 8000d61ce0 | |||
| 4ac18b5d81 | |||
| 54676a4512 | |||
| 2d16d1c79c | |||
| 3c7da54c3c | |||
| 434d1cca61 | |||
| 7b14b5df4a | |||
| befa0f0603 | |||
| 0ad9942e89 | |||
| 41cfbd192c | |||
| 0d79cccc52 | |||
| d51127a9b7 | |||
| 4a6110c618 | |||
| b2bc848281 | |||
| 65a12c1156 | |||
| 9070b4a1c7 | |||
| 6b56be941c | |||
| 8064ea6abb | |||
| 850815b9c6 | |||
| f2c35552b8 | |||
| 068434a5ec | |||
| 68ab90915f | |||
| 9e987337c3 | |||
| 5d95a3277c | |||
| 5c4154941a | |||
| e7dfe5cdc3 | |||
| e016390f00 | |||
| f69dd81b8b | |||
| 2ec292e406 | |||
| aeac0549f8 | |||
| c53e217448 | |||
| f2dfad1b15 | |||
| 2bed764621 | |||
| 2eea01bd37 | |||
| c6f482b898 | |||
| 67b1e237bd | |||
| 3f74fc0778 |
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,5 +1,5 @@
|
||||
*.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
|
||||
|
||||
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@ -1,13 +1,16 @@
|
||||
##### 版本号:
|
||||
|
||||
|
||||
##### 问题描述:
|
||||
|
||||
|
||||
|
||||
##### 错误截图:
|
||||
|
||||
|
||||
|
||||
|
||||
#### 友情提示:
|
||||
- 未按格式要求发帖、描述过于简抽象的,会被直接删掉;
|
||||
- 请确保问题描述清楚,方便我们理解并一次性调查解决问题;
|
||||
- 如果使用的不是master,请说明你使用的那个分支
|
||||
- 未按格式要求发帖、描述过于简单的,会被直接删掉;
|
||||
- 描述问题请图文并茂,方便我们理解并快速定位问题;
|
||||
- 如果使用的不是master,请说明你使用的分支;
|
||||
15
LICENSE
15
LICENSE
@ -200,17 +200,4 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||
|
||||
开源协议补充
|
||||
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
|
||||
|
||||
1.允许基于本平台软件开展业务系统开发。
|
||||
2.JeecgBoot底层依赖的非开源功能:online lib依赖、仪表盘lib依赖等,统一采用LGPL开源协议(不二次改造、不拆分出jeecgboot之外使用,就不产生侵权)
|
||||
3.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
|
||||
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
|
||||
|
||||
总结:在遵循Apache开源协议和开源协议补充条款下,允许商用使用,不会造成侵权行为!
|
||||
解释权归:http://www.jeecg.com
|
||||
|
||||
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.
|
||||
256
README-EN.md
256
README-EN.md
@ -7,13 +7,12 @@
|
||||
JEECG BOOT Low Code Development Platform
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.0(发布日期:2024-06-17)
|
||||
Current version: 3.7.0_all (Release date: 2024-06-23)
|
||||
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://www.jeecg.com)
|
||||
[](https://jeecg.blog.csdn.net)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
|
||||
@ -39,9 +38,6 @@ 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
|
||||
|
||||
@ -64,14 +60,11 @@ For the project
|
||||
Jeecg-Boot low code development platform can be applied in the development of any J2EE project, especially for SAAS projects, enterprise information management system (MIS), internal office system (OA), enterprise resource planning system (ERP), customer relationship management system (CRM), etc. Its semi-intelligent manual Merge development method, Can significantly improve the development efficiency of more than 70%, greatly reduce the development cost.
|
||||
|
||||
|
||||
|
||||
Docker starts the project
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@ -80,11 +73,12 @@ 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)
|
||||
- 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 : ⑨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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Star charts
|
||||
@ -180,7 +174,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 +184,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.7.6
|
||||
|
||||
- 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
|
||||
|
||||
@ -227,44 +221,28 @@ Technical Architecture:
|
||||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| MariaDB | √ |
|
||||
| 达梦、人大金仓 | √ |
|
||||
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
|
||||
|
||||
## Microservice solutions
|
||||
|
||||
|
||||
1. Service registration and discovery Nacos √
|
||||
|
||||
2. Nacos √
|
||||
|
||||
3. Route gateway gateway(Three loading modes) √
|
||||
|
||||
4. Distributed http feign √
|
||||
|
||||
5. fuse degrade current limiting Sentinel √
|
||||
|
||||
6. Distributed files Minio and Alioss √
|
||||
|
||||
7. Unified permission control
|
||||
|
||||
8. Service monitoring SpringBootAdmin√
|
||||
|
||||
9. link tracking Skywalking [reference document](https://help.jeecg.com/java/springcloud/super/skywarking.html)
|
||||
|
||||
10. Messaging middleware RabbitMQ √
|
||||
|
||||
11. Distributed task xxl-job √
|
||||
|
||||
12. Distributed Transaction Seata
|
||||
|
||||
13. Distributed log elk + kafka
|
||||
|
||||
14. Support docker-compose, k8s, jenkins
|
||||
|
||||
15. CAS SSO √
|
||||
|
||||
16. Route traffic limiting √
|
||||
- 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 +251,9 @@ Technical Architecture:
|
||||
### Jeecg Boot product functionality blueprint
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
### 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 +300,22 @@ Technical Architecture:
|
||||

|
||||
|
||||
##### dashboard Designer
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
##### report Designer
|
||||

|
||||
|
||||
|
||||
314
README.md
314
README.md
@ -2,15 +2,14 @@
|
||||
JeecgBoot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.0(发布日期:2024-06-17)
|
||||
当前最新版本: 3.7.0_all(发布日期:2024-06-23)
|
||||
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://jeecg.com/aboutusIndex)
|
||||
[](https://jeecg.blog.csdn.net)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/jeecgboot/JeecgBoot/blob/master/LICENSE)
|
||||
[](http://guojusoft.com)
|
||||
[](https://github.com/jeecgboot/JeecgBoot)
|
||||
[](https://github.com/jeecgboot/JeecgBoot)
|
||||
[](https://github.com/jeecgboot/JeecgBoot)
|
||||
|
||||
|
||||
|
||||
@ -19,7 +18,7 @@ JeecgBoot 低代码开发平台
|
||||
|
||||
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
|
||||
|
||||
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x和3.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
|
||||
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x和3.x,SpringCloud,Ant Design Vue3,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
|
||||
|
||||
JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零代码`:Online表单开发、Online报表、报表配置能力、在线图表设计、仪表盘设计、大屏设计、移动配置能力、表单设计器、在线设计流程、流程自动化配置、插件能力(可插拔)等等!
|
||||
|
||||
@ -41,59 +40,108 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
|--------------------|------------------------|
|
||||
| `jeecg-boot` | 后端源码JAVA(SpringBoot微服务架构) |
|
||||
| `jeecgboot-vue3` | 前端源码VUE3(vue3+vite5+ts最新技术栈) |
|
||||
| `jeecg-uniapp` | APP框架,一份代码多终端适配,支持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)
|
||||
| `jeecg-uniapp` | [配套APP框架](https://github.com/jeecgboot/jeecg-uniapp) 适配多个终端,支持APP、小程序、H5 |
|
||||
|
||||
|
||||
技术文档
|
||||
-----------------------------------
|
||||
|
||||
- 产品官网: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- 官方网站: [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
|
||||
|
||||
- 反馈问题: [在Github上提Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
|
||||
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [入门视频](http://jeecg.com/doc/video)
|
||||
- QQ交流群 : ⑨808791225、其他(满)
|
||||
- 在线演示 : [在线演示](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(满)
|
||||
|
||||
|
||||
|
||||
启动项目
|
||||
-----------------------------------
|
||||
|
||||
- [IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
|
||||
- [Docker一键启动前后端](https://help.jeecg.com/java/docker/quick.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.7.6
|
||||
- 安全框架:Apache Shiro 1.12.0,Jwt 3.11.0
|
||||
- 微服务技术栈:Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
|
||||
- 数据库连接池:阿里巴巴Druid 1.1.22
|
||||
- 日志打印:logback
|
||||
- 缓存:Redis
|
||||
- 其他:autopoi, fastjson,poi,Swagger-ui,quartz, lombok(简化代码)等。
|
||||
- 默认数据库脚本:MySQL5.7+
|
||||
- [其他数据库,需要自己转](https://my.oschina.net/jeecg/blog/4905722)
|
||||
|
||||
|
||||
#### 前端
|
||||
|
||||
- 前端IDE建议:WebStorm、Vscode
|
||||
- 采用 Vue3.0+TypeScript+Vite+Ant-Design-Vue等新技术方案,包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
|
||||
- 最新技术栈:Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
|
||||
- 依赖管理:node、npm、pnpm
|
||||
|
||||
|
||||
|
||||
#### 支持库
|
||||
|
||||
| 数据库 | 支持 |
|
||||
| --- | --- |
|
||||
| MySQL | √ |
|
||||
| Oracle11g | √ |
|
||||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| MariaDB | √ |
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
|
||||
|
||||
|
||||
## 微服务解决方案
|
||||
|
||||
|
||||
- 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)
|
||||
|
||||
|
||||
#### 微服务架构图
|
||||

|
||||
|
||||
|
||||
|
||||
为什么选择JeecgBoot?
|
||||
-----------------------------------
|
||||
* 1.采用最新主流前后分离框架(Springboot+Mybatis+antd),容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
|
||||
* 1.采用最新主流前后分离框架(Springboot+Mybatis+antd+vue3),容易上手; 代码生成器依赖性低,灵活的扩展能力,可快速实现二次开发;
|
||||
* 2.支持微服务SpringCloud Alibaba(Nacos、Gateway、Sentinel、Skywalking),提供切换机制支持单体和微服务自由切换
|
||||
* 3.开发效率高,采用代码生成器,单表、树列表、一对多、一对一等数据模型,增删改查功能一键生成,菜单配置直接使用;
|
||||
* 4.代码生成器提供强大模板机制,支持自定义模板,目前提供四套风格模板(单表两套、树模型一套、一对多三套)
|
||||
@ -111,7 +159,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 +182,8 @@ Docker启动项目
|
||||
* 39.支持菜单动态路由
|
||||
* 40.权限控制采用 RBAC(Role-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.0,Jwt 3.11.0
|
||||
|
||||
- 微服务技术栈:Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
|
||||
|
||||
- 数据库连接池:阿里巴巴Druid 1.1.22
|
||||
|
||||
- 日志打印:logback
|
||||
|
||||
- 其他:autopoi, fastjson,poi,Swagger-ui,quartz, 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、路由限流 √
|
||||
|
||||
|
||||
#### 微服务架构图
|
||||

|
||||
|
||||
### Jeecg Boot 产品功能蓝图
|
||||

|
||||
@ -238,6 +191,20 @@ 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
|
||||
|
||||
|
||||
|
||||
### 功能模块
|
||||
```
|
||||
├─Online在线开发(低代码)
|
||||
@ -378,38 +345,6 @@ 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 -- 微服务测试示例(分库分表)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### 系统效果
|
||||
|
||||
##### PC端
|
||||
@ -435,10 +370,20 @@ Docker启动项目
|
||||
|
||||
|
||||
##### 仪表盘设计器
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
##### 报表设计器
|
||||

|
||||
|
||||
@ -521,11 +466,4 @@ Docker启动项目
|
||||
|
||||
如果觉得还不错,请作者喝杯咖啡吧 ☺
|
||||
|
||||

|
||||
|
||||
|
||||
### 流程引擎推荐
|
||||
|
||||
大家在使用本开源项目时,如果想进一步集成流程引擎,推荐结合贺波老师的书 [《深入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">
|
||||

|
||||
135
docker-compose-cloud.yml
Normal file
135
docker-compose-cloud.yml
Normal 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: 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
|
||||
@ -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
|
||||
@ -26,24 +27,37 @@ services:
|
||||
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
|
||||
203
jeecg-boot/LICENSE
Normal file
203
jeecg-boot/LICENSE
Normal file
@ -0,0 +1,203 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2019 <a href="http://www.jeecg.com">Jeecg Boot</a> All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||
164
jeecg-boot/README.md
Normal file
164
jeecg-boot/README.md
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
JeecgBoot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.0_all(发布日期:2024-06-23)
|
||||
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://jeecg.com/aboutusIndex)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
|
||||
|
||||
|
||||
项目介绍
|
||||
-----------------------------------
|
||||
|
||||
<h3 align="center">Java Low Code Platform for Enterprise web applications</h3>
|
||||
|
||||
JeecgBoot 是一款基于代码生成器的`低代码开发平台`!前后端分离架构 SpringBoot2.x和3.x,SpringCloud,Ant Design Vue3,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot 引领新的低代码开发模式(OnlineCoding-> 代码生成器-> 手工MERGE), 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省研发成本,同时又不失灵活性!
|
||||
|
||||
|
||||
#### 项目说明
|
||||
|
||||
| 项目名 | 说明 |
|
||||
|--------------------|------------------------|
|
||||
| `jeecg-boot` | 后端源码JAVA(SpringBoot微服务架构) |
|
||||
| `jeecgboot-vue3` | 前端源码VUE3(vue3+vite5+ts最新技术栈) |
|
||||
|
||||
|
||||
|
||||
技术文档
|
||||
-----------------------------------
|
||||
|
||||
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart)
|
||||
- QQ交流群 : ⑨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.7.6
|
||||
- 安全框架:Apache Shiro 1.12.0,Jwt 3.11.0
|
||||
- 微服务技术栈:Spring Cloud Alibaba、Nacos、Gateway、Sentinel、Skywalking
|
||||
- 数据库连接池:阿里巴巴Druid 1.1.22
|
||||
- 日志打印:logback
|
||||
- 缓存:Redis
|
||||
- 其他:autopoi, fastjson,poi,Swagger-ui,quartz, lombok(简化代码)等。
|
||||
- 默认数据库脚本:MySQL5.7+
|
||||
- [其他数据库,需要自己转](https://my.oschina.net/jeecg/blog/4905722)
|
||||
|
||||
|
||||
#### 前端
|
||||
|
||||
- 前端IDE建议:WebStorm、Vscode
|
||||
- 采用 Vue3.0+TypeScript+Vite+Ant-Design-Vue等新技术方案,包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
|
||||
- 最新技术栈:Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
|
||||
- 依赖管理:node、npm、pnpm
|
||||
|
||||
|
||||
|
||||
#### 支持库
|
||||
|
||||
| 数据库 | 支持 |
|
||||
| --- | --- |
|
||||
| MySQL | √ |
|
||||
| Oracle11g | √ |
|
||||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| MariaDB | √ |
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
|
||||
|
||||
|
||||
|
||||
## 微服务解决方案
|
||||
|
||||
|
||||
- 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 -- 微服务测试示例(分库分表)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
#### 微服务架构图
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM mysql:8.0.19
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/mysql:8.0.19
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -104,7 +104,7 @@ public class JeecgBootExceptionHandler {
|
||||
@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
|
||||
public Result<?> handleAuthorizationException(AuthorizationException e){
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.noauth("没有权限,请联系管理员授权,后刷新缓存!");
|
||||
return Result.noauth("没有权限,请联系管理员授权后刷新缓存!");
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -12,18 +12,14 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
@ -40,7 +36,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 +54,6 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
||||
@Autowired(required = false)
|
||||
private PrometheusMeterRegistry prometheusMeterRegistry;
|
||||
|
||||
@Autowired
|
||||
private ObjectProvider<Jackson2ObjectMapperBuilder> builderProvider;
|
||||
@Autowired
|
||||
private JacksonProperties jacksonProperties;
|
||||
|
||||
/**
|
||||
* 静态资源的配置 - 使得可以从磁盘中读取 Html、图片、视频、音频等
|
||||
*/
|
||||
@ -116,10 +106,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 +114,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")));
|
||||
|
||||
@ -290,7 +290,7 @@ public class ShiroConfig {
|
||||
RedisSentinelManager sentinelManager = new RedisSentinelManager();
|
||||
sentinelManager.setMasterName(redisProperties.getSentinel().getMaster());
|
||||
sentinelManager.setHost(String.join(",", redisProperties.getSentinel().getNodes()));
|
||||
sentinelManager.setPassword(redisProperties.getSentinel().getPassword());
|
||||
sentinelManager.setPassword(redisProperties.getPassword());
|
||||
sentinelManager.setDatabase(redisProperties.getDatabase());
|
||||
|
||||
return sentinelManager;
|
||||
|
||||
@ -3,16 +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.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.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 在spring boot初始化时,根据@RestController注解获取当前spring容器中的bean
|
||||
@ -22,24 +22,20 @@ 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);
|
||||
@ -53,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();
|
||||
|
||||
@ -59,12 +59,6 @@ public class ChatServiceImpl implements ChatService {
|
||||
private OpenAiStreamClient openAiStreamClient = null;
|
||||
|
||||
//update-begin---author:chenrui ---date:20240131 for:[QQYUN-8212]fix 没有配置启动报错------------
|
||||
public ChatServiceImpl() {
|
||||
try {
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 防止client不能成功注入
|
||||
@ -73,8 +67,14 @@ public class ChatServiceImpl implements ChatService {
|
||||
* @date 2024/2/3 23:08
|
||||
*/
|
||||
private OpenAiStreamClient ensureClient(){
|
||||
if(null == this.openAiStreamClient){
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
if (null == this.openAiStreamClient){
|
||||
//update-begin---author:chenrui ---date:20240625 for:[TV360X-1570]给于更友好的提示,提示未配置ai------------
|
||||
try {
|
||||
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
|
||||
} catch (Exception ignored) {
|
||||
sendErrorMsg("如果您想使用AI助手,请先设置相应配置!");
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240625 for:[TV360X-1570]给于更友好的提示,提示未配置ai------------
|
||||
}
|
||||
return this.openAiStreamClient;
|
||||
}
|
||||
@ -163,16 +163,21 @@ 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------------
|
||||
OpenAiStreamClient client = ensureClient();
|
||||
if (null != client) {
|
||||
OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(topicId, sseEmitter);
|
||||
ChatCompletion completion = ChatCompletion
|
||||
.builder()
|
||||
.messages(msgHistory)
|
||||
.model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
|
||||
.build();
|
||||
client.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-end---author:chenrui ---date:20240625 for:[TV360X-1570]给于更友好的提示,提示未配置ai------------
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240223 for:[QQYUN-8225]聊天记录保存------------
|
||||
@ -194,6 +199,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助手------------
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ public class CommonController {
|
||||
*/
|
||||
@GetMapping("/403")
|
||||
public Result<?> noauth() {
|
||||
return Result.error("没有权限,请联系管理员授权,后刷新缓存!");
|
||||
return Result.error("没有权限,请联系管理员授权后刷新缓存!");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
<#if need_popup>
|
||||
JPopup,
|
||||
</#if>
|
||||
<#if need_popup_dict>
|
||||
JPopupDict,
|
||||
</#if>
|
||||
<#if need_category>
|
||||
JCategorySelect,
|
||||
</#if>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<#assign form_field_dictCode="${po.dictField}">
|
||||
</#if>
|
||||
<a-col :span="${form_span}">
|
||||
<a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}">
|
||||
<a-form-item label="${po.filedComment}" v-bind="validateInfos.${autoStringSuffixForModel(po)}" id="${formEntityName}-${autoStringSuffixForModel(po)}" name="${autoStringSuffixForModel(po)}">
|
||||
<#if po.classType =='date'>
|
||||
<a-date-picker placeholder="请选择${po.filedComment}" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="formData.${po.fieldName}" value-format="YYYY-MM-DD" style="width: 100%" <#if po.readonly=='Y'>disabled</#if> allow-clear />
|
||||
<#elseif po.classType =='datetime'>
|
||||
@ -33,9 +33,18 @@
|
||||
:multi="${po.extendParams.popupMulti?c}"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
<#if po.readonly=='Y'>disabled</#if><#rt> allow-clear />
|
||||
<#elseif po.classType =='popup_dict'>
|
||||
<#assign need_popup_dict = true>
|
||||
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
|
||||
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
|
||||
<j-popup-dict
|
||||
placeholder="请选择${po.filedComment}"
|
||||
v-model:value="formData.${po.fieldName}"
|
||||
dictCode="${po.dictTable},${po.dictText},${po.dictField}"
|
||||
:multi="${po.extendParams.popupMulti?c}" <#if po.readonly=='Y'>disabled</#if> />
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
<#assign need_dept = true>
|
||||
<j-select-dept v-model:value="formData.${po.fieldName}" :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled</#if> allow-clear />
|
||||
<j-select-dept v-model:value="formData.${po.fieldName}" <#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if> <#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if> <#if po.readonly=='Y'>disabled</#if> :multiple="${po.extendParams.multi?default('true')}" checkStrictly <#if po.readonly=='Y'>disabled</#if> allow-clear />
|
||||
<#elseif po.classType =='switch'>
|
||||
<#assign need_switch = true>
|
||||
<j-switch v-model:value="formData.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
|
||||
@ -50,7 +59,7 @@
|
||||
<#elseif po.classType =='sel_user'>
|
||||
<#assign need_dept_user = true>
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<j-select-user v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if> allow-clear />
|
||||
<j-select-user v-model:value="formData.${po.fieldName}" <#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if> <#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if> <#if po.readonly=='Y'>disabled</#if> allow-clear />
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<#elseif po.classType =='textarea'>
|
||||
<a-textarea v-model:value="formData.${autoStringSuffixForModel(po)}" :rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
<#if need_popup>
|
||||
import JPopup from '/@/components/Form/src/jeecg/components/JPopup.vue';
|
||||
</#if>
|
||||
<#if need_popup_dict>
|
||||
import JPopupDict from '/@/components/Form/src/jeecg/components/JPopupDict.vue';
|
||||
</#if>
|
||||
<#if need_category>
|
||||
import JCategorySelect from '/@/components/Form/src/jeecg/components/JCategorySelect.vue';
|
||||
</#if>
|
||||
@ -47,4 +50,7 @@
|
||||
</#if>
|
||||
<#if need_checkbox>
|
||||
import JCheckbox from "/@/components/Form/src/jeecg/components/JCheckbox.vue";
|
||||
</#if>
|
||||
<#if need_range_number>
|
||||
import JRangeNumber from "/@/components/Form/src/jeecg/components/JRangeNumber.vue";
|
||||
</#if>
|
||||
@ -56,66 +56,41 @@
|
||||
<#if query_field_no gt 1> </#if>]"
|
||||
<#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}"
|
||||
<#if query_field_no gt 1> </#if>:setFieldsValue="setFieldsValue" allow-clear />
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
<#if query_field_no gt 1> </#if><j-popup-dict
|
||||
<#if query_field_no gt 1> </#if>placeholder="请选择${po.filedComment}"
|
||||
<#if query_field_no gt 1> </#if>v-model:value="queryParam.${po.fieldName}"
|
||||
<#if query_field_no gt 1> </#if>dictCode="${po.dictTable},${po.dictText},${po.dictField}"
|
||||
<#if query_field_no gt 1> </#if>:multi="${po.extendParams.popupMulti?c}"
|
||||
<#if query_field_no gt 1> </#if><#if po.readonly=='Y'>disabled</#if> />
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
<#if po.dictTable?default("")?trim?length gt 1>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
<#if po.dictTable?default("")?trim?length gt 1>
|
||||
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}" allow-clear />
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#if query_field_no gt 1> </#if><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictField}" allow-clear />
|
||||
<#else>
|
||||
<#else>
|
||||
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}" allow-clear ></a-input>
|
||||
</#if>
|
||||
</#if>
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<#if query_field_no gt 1> </#if><a-input-number placeholder="请输入${po.filedComment}" v-model:value="queryParam.${po.fieldName}"></a-input-number>
|
||||
<#else>
|
||||
<#else>
|
||||
<#if query_field_no gt 1> </#if><a-input placeholder="请输入${po.filedComment}" v-model:value="queryParam.${autoStringSuffixForModel(po)}" allow-clear ></a-input>
|
||||
</#if>
|
||||
</#if>
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></a-col>
|
||||
<#else>
|
||||
<#if query_field_no gt 1> </#if><a-col :lg="6">
|
||||
<#if query_field_no gt 1> </#if><a-form-item>
|
||||
<#if query_field_no gt 1> </#if><template #label><span title="${po.filedComment}"><#if po.filedComment?default("")?trim?length gt 4>${po.filedComment?substring(0,4)}<#else>${po.filedComment}</#if></span></template>
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${autoStringSuffixForModel(po)}">
|
||||
<#if query_field_no gt 1> </#if><template #label><span title="${po.filedComment}"><#if po.filedComment?default("")?trim?length gt 4>${po.filedComment?substring(0,4)}<#else>${po.filedComment}</#if></span></template>
|
||||
<#if po.classType=='date'>
|
||||
<#if query_field_no gt 1> </#if><div style="display: flex">
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_begin" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择开始日期" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_end" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-date-picker value-format="YYYY-MM-DD" placeholder="请选择结束日期" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></div>
|
||||
<#if query_field_no gt 1> </#if><a-range-picker value-format="YYYY-MM-DD" <#if po.extendParams?exists && po.extendParams.picker?exists>picker="${po.extendParams.picker}"</#if> v-model:value="queryParam.${po.fieldName}" class="query-group-cust"/>
|
||||
<#elseif po.classType=='time'>
|
||||
<#if query_field_no gt 1> </#if><div style="display: flex">
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_begin" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><time-picker value-format="HH:mm:ss" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_end" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><time-picker value-format="HH:mm:ss" placeholder="请选择结束日期" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></div>
|
||||
<#if query_field_no gt 1> </#if><a-time-range-picker value-format="HH:mm:ss" v-model:value="queryParam.${po.fieldName}" class="query-group-cust" />
|
||||
<#elseif po.classType=='datetime'>
|
||||
<#if query_field_no gt 1> </#if><div style="display: flex">
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_begin" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if><span class="query-group-split-cust">~</span>
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_end" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-date-picker showTime value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" allow-clear />
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></div>
|
||||
<#if query_field_no gt 1> </#if><a-range-picker showTime value-format="YYYY-MM-DD HH:mm:ss" v-model:value="queryParam.${po.fieldName}" class="query-group-cust"/>
|
||||
<#else>
|
||||
<#if query_field_no gt 1> </#if><div style="display: flex">
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_begin" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最小值" v-model:value="queryParam.${po.fieldName}_begin" class="query-group-cust" allow-clear ></a-input>
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if><span class="query-group-left query-group-split-cust">~</span>
|
||||
<#if query_field_no gt 1> </#if><a-form-item name="${po.fieldName}_end" style="margin-bottom: 0;">
|
||||
<#if query_field_no gt 1> </#if><a-input placeholder="请输入最大值" v-model:value="queryParam.${po.fieldName}_end" class="query-group-cust" allow-clear ></a-input>
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></div>
|
||||
<#if query_field_no gt 1> </#if><JRangeNumber v-model:value="queryParam.${po.fieldName}" class="query-group-cust"></JRangeNumber>
|
||||
</#if>
|
||||
<#if query_field_no gt 1> </#if></a-form-item>
|
||||
<#if query_field_no gt 1> </#if></a-col>
|
||||
|
||||
@ -149,6 +149,8 @@
|
||||
<#-- update-begin---author:chenrui ---date:20231228 for:fix 带条件字典存在单引号导致js编译错误---------- -->
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#assign dictCode="dictCode: '${po.dictField}'">
|
||||
<#else>
|
||||
<#assign dictCode="dictCode: ''">
|
||||
</#if>
|
||||
|
||||
<#if po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='checkbox' || po.classType=='radio'>
|
||||
@ -229,4 +231,19 @@
|
||||
</#if>
|
||||
</#if>
|
||||
<#return flag>
|
||||
</#function>
|
||||
|
||||
<#-- vue3 native 获取范围字段 -->
|
||||
<#function getRangeField(columns) >
|
||||
<#assign rangeField = "">
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y'>
|
||||
<#if po.queryMode!='single'>
|
||||
<#if po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal' || po.classType=='time' || po.classType=='date' || po.classType=='datetime'>
|
||||
<#assign rangeField = rangeField + "${po.fieldName},">
|
||||
</#if>
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
<#return rangeField>
|
||||
</#function>
|
||||
@ -21,9 +21,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -33,7 +33,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -229,6 +229,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -247,7 +248,8 @@
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1'){
|
||||
@ -272,7 +274,8 @@
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -318,6 +321,6 @@
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
||||
@ -57,7 +57,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -104,6 +104,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#elseif po.classType=='sel_user'>
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
@ -115,6 +123,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -156,6 +172,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
component: 'JDictSelectTag',
|
||||
@ -276,8 +299,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -299,8 +337,13 @@ export const formSchema: FormSchema[] = [
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
},
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list'>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${entityName}Form" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
const isUpdate = ref(true);
|
||||
const isDetail = ref(false);
|
||||
//表单配置
|
||||
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
|
||||
const [registerForm, { setProps,resetFields, setFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -51,6 +51,14 @@
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
} finally {
|
||||
setModalProps({confirmLoading: false});
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<#assign query_field_no=0>
|
||||
@ -9,6 +10,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -18,6 +20,8 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign is_range = false>
|
||||
<#assign query_flag = false>
|
||||
<!--查询区域-->
|
||||
<div class="jeecg-basic-table-form-container">
|
||||
@ -52,11 +56,20 @@
|
||||
<#if po.classType=='popup'>
|
||||
<#assign need_popup = true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign need_popup_dict = true>
|
||||
</#if>
|
||||
<#if po.classType=='sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
</#if>
|
||||
<#if po.classType=='time'>
|
||||
<#assign need_time = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
|
||||
<#assign need_range_number = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single'>
|
||||
<#assign is_range = true>
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeSearch.ftl">
|
||||
</#list>
|
||||
@ -85,9 +98,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -97,7 +110,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -158,6 +171,9 @@
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
</#if>
|
||||
<#if is_range>
|
||||
import { cloneDeep } from "lodash-es";
|
||||
</#if>
|
||||
|
||||
const formRef = ref();
|
||||
const queryParam = reactive<any>({});
|
||||
@ -176,8 +192,13 @@
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
beforeFetch: async (params) => {
|
||||
<#if is_range>
|
||||
let rangerQuery = await setRangeQuery();
|
||||
return Object.assign(params, rangerQuery);
|
||||
<#else>
|
||||
return Object.assign(params, queryParam);
|
||||
</#if>
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
@ -270,6 +291,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -289,7 +311,8 @@
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1'){
|
||||
@ -314,7 +337,8 @@
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -407,6 +431,32 @@
|
||||
}
|
||||
initDictConfig();
|
||||
</#if>
|
||||
<#if is_range>
|
||||
|
||||
let rangeField = '${getRangeField(columns)}'
|
||||
|
||||
/**
|
||||
* 设置范围查询条件
|
||||
*/
|
||||
async function setRangeQuery(){
|
||||
let queryParamClone = cloneDeep(queryParam);
|
||||
if (rangeField) {
|
||||
let fieldsValue = rangeField.split(',');
|
||||
fieldsValue.forEach(item => {
|
||||
if (queryParamClone[item]) {
|
||||
let range = queryParamClone[item];
|
||||
queryParamClone[item+'_begin'] = range[0];
|
||||
queryParamClone[item+'_end'] = range[1];
|
||||
delete queryParamClone[item];
|
||||
} else {
|
||||
queryParamClone[item+'_begin'] = '';
|
||||
queryParamClone[item+'_end'] = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -57,7 +57,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="${entityName}Form">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
@ -14,6 +14,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -23,6 +24,7 @@
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign hasOnlyValidate = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign form_span = 24>
|
||||
<#if tableVo.fieldRowNum==2>
|
||||
<#assign form_span = 12>
|
||||
@ -38,6 +40,7 @@
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
<#assign hasOnlyValidate = true>
|
||||
</#if>
|
||||
<#assign formEntityName>${entityName}Form</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
@ -64,7 +67,10 @@
|
||||
<#if hasOnlyValidate == true>
|
||||
import { duplicateValidate } from '/@/utils/helper/validator'
|
||||
</#if>
|
||||
|
||||
<#if bpm_flag>
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
const { isDisabledAuth, hasPermission, initBpmFormData } = usePermission();
|
||||
</#if>
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: () => ({})},
|
||||
@ -101,6 +107,7 @@
|
||||
|
||||
<#if bpm_flag>
|
||||
onMounted(()=>{
|
||||
initBpmFormData(props.formData);
|
||||
initFormData();
|
||||
});
|
||||
//渲染流程表单数据
|
||||
@ -152,8 +159,18 @@
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
|
||||
@ -26,9 +26,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleCreate" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleCreate" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
@ -39,7 +39,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="ant-design:down-outlined"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -371,6 +371,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
},
|
||||
{
|
||||
label: '添加下级',
|
||||
@ -392,9 +393,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
dropDownAction.push({
|
||||
@ -417,8 +418,9 @@
|
||||
popConfirm: {
|
||||
title: '确定删除吗?',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -442,6 +444,6 @@
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
||||
|
||||
@ -61,7 +61,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -109,6 +109,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -118,6 +126,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -159,6 +175,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree'>
|
||||
component: 'JTreeSelect',
|
||||
componentProps:{
|
||||
@ -294,8 +317,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -317,8 +355,13 @@ export const formSchema: FormSchema[] = [
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
},
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list'>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
</#list>
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" :title="getTitle" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${entityName}Form" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@ -29,7 +29,7 @@
|
||||
// 当前编辑的数据
|
||||
let model:Nullable<Recordable> = null;
|
||||
//表单配置
|
||||
const [registerForm, {setProps,resetFields, setFieldsValue, validate, updateSchema}] = useForm({
|
||||
const [registerForm, { setProps,resetFields, setFieldsValue, validate, updateSchema, scrollToField }] = useForm({
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: {span: ${getFormSpan(tableVo.fieldRowNum?default(1))}},
|
||||
@ -103,6 +103,14 @@
|
||||
// 是否更改了父级节点
|
||||
changeParent: model != null && (model['${pidFieldName}'] != values['${pidFieldName}']),
|
||||
});
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
} finally {
|
||||
setModalProps({confirmLoading: false});
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -29,6 +30,8 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign is_range = false>
|
||||
<#assign query_flag = false>
|
||||
<!--查询区域-->
|
||||
<div class="jeecg-basic-table-form-container">
|
||||
@ -63,11 +66,20 @@
|
||||
<#if po.classType=='popup'>
|
||||
<#assign need_popup = true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign need_popup_dict = true>
|
||||
</#if>
|
||||
<#if po.classType=='sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
</#if>
|
||||
<#if po.classType=='time'>
|
||||
<#assign need_time = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
|
||||
<#assign need_range_number = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single'>
|
||||
<#assign is_range = true>
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeSearch.ftl">
|
||||
</#list>
|
||||
@ -96,7 +108,7 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -106,7 +118,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'"
|
||||
>批量操作
|
||||
<Icon icon="ant-design:down-outlined"></Icon>
|
||||
</a-button>
|
||||
@ -164,6 +176,9 @@
|
||||
</#if>
|
||||
<#if need_pca>
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
<#if is_range>
|
||||
import { cloneDeep } from "lodash-es";
|
||||
</#if>
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
@ -186,8 +201,13 @@
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
beforeFetch: async (params) => {
|
||||
<#if is_range>
|
||||
let rangerQuery = await setRangeQuery();
|
||||
return Object.assign(params, rangerQuery);
|
||||
<#else>
|
||||
return Object.assign(params, queryParam.value);
|
||||
</#if>
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
@ -419,6 +439,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
];
|
||||
}
|
||||
@ -443,8 +464,9 @@
|
||||
popConfirm: {
|
||||
title: '确定删除吗?',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
},
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -475,6 +497,7 @@
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
},
|
||||
];
|
||||
</#if>
|
||||
@ -569,6 +592,32 @@
|
||||
}
|
||||
initDictConfig();
|
||||
</#if>
|
||||
<#if is_range>
|
||||
|
||||
let rangeField = '${getRangeField(columns)}'
|
||||
|
||||
/**
|
||||
* 设置范围查询条件
|
||||
*/
|
||||
async function setRangeQuery(){
|
||||
let queryParamClone = cloneDeep(queryParam.value);
|
||||
if (rangeField) {
|
||||
let fieldsValue = rangeField.split(',');
|
||||
fieldsValue.forEach(item => {
|
||||
if (queryParamClone[item]) {
|
||||
let range = queryParamClone[item];
|
||||
queryParamClone[item+'_begin'] = range[0];
|
||||
queryParamClone[item+'_end'] = range[1];
|
||||
delete queryParamClone[item];
|
||||
} else {
|
||||
queryParamClone[item+'_begin'] = '';
|
||||
queryParamClone[item+'_end'] = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -61,7 +61,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}]);
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="${entityName}Form">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
@ -14,6 +14,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -22,6 +23,7 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign pidFieldName = "">
|
||||
<#assign hasOnlyValidate = false>
|
||||
<#assign form_span = 24>
|
||||
@ -56,6 +58,7 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</#if>
|
||||
<#assign formEntityName>${entityName}Form</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
@ -82,7 +85,10 @@
|
||||
<#if hasOnlyValidate == true>
|
||||
import { duplicateValidate } from '/@/utils/helper/validator'
|
||||
</#if>
|
||||
|
||||
<#if bpm_flag>
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
const { isDisabledAuth, hasPermission, initBpmFormData } = usePermission();
|
||||
</#if>
|
||||
const useForm = Form.useForm;
|
||||
const formRef = ref();
|
||||
const isUpdate = ref(true);
|
||||
@ -124,6 +130,7 @@
|
||||
|
||||
<#if bpm_flag>
|
||||
onMounted(()=>{
|
||||
initBpmFormData(props.formData);
|
||||
initFormData();
|
||||
});
|
||||
//渲染流程表单数据
|
||||
@ -196,8 +203,18 @@
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
|
||||
@ -22,9 +22,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -34,7 +34,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -251,6 +251,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -285,8 +286,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1'){
|
||||
@ -309,8 +311,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
|
||||
@ -57,7 +57,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -102,6 +102,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -112,6 +120,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -148,6 +164,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
component: 'JDictSelectTag',
|
||||
@ -269,8 +292,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -292,7 +330,14 @@ export const formSchema: FormSchema[] = [
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
<#else>
|
||||
labelKey:'realname',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',//TODO 注意string转换问题
|
||||
@ -575,8 +620,23 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -597,9 +657,16 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
},
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
<#else>
|
||||
labelKey:'realname',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
<#elseif po.classType=='list' || po.classType=='radio'>
|
||||
|
||||
@ -79,6 +79,7 @@
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: 180,
|
||||
fixed:'right'
|
||||
},
|
||||
pagination:{
|
||||
current: 1,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${entityName}Form" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
const isUpdate = ref(true);
|
||||
const isDetail = ref(false);
|
||||
//表单配置
|
||||
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
|
||||
const [registerForm, { setProps,resetFields, setFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -51,6 +51,14 @@
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
} finally {
|
||||
setModalProps({confirmLoading: false});
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#segment#${sub.entityName}Modal.vue
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${sub.entityName}Form" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
const isUpdate = ref(true);
|
||||
const isDetail = ref(false);
|
||||
//表单配置
|
||||
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
|
||||
const [registerForm, { setProps,resetFields, setFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: ${sub.entityName?uncap_first}FormSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -61,6 +61,13 @@
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setModalProps({confirmLoading: false});
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -20,6 +21,8 @@
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign query_flag = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign is_range = false>
|
||||
<!--查询区域-->
|
||||
<div class="jeecg-basic-table-form-container">
|
||||
<a-form ref="formRef" @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
@ -56,12 +59,21 @@
|
||||
<#if po.classType=='popup'>
|
||||
<#assign need_popup = true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign need_popup_dict = true>
|
||||
</#if>
|
||||
<#if po.classType=='sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
</#if>
|
||||
<#if po.classType=='time'>
|
||||
<#assign need_time = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
|
||||
<#assign need_range_number = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single'>
|
||||
<#assign is_range = true>
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeSearch.ftl">
|
||||
</#list>
|
||||
<#if query_field_no gt 2>
|
||||
@ -90,9 +102,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -102,7 +114,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'"
|
||||
>批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
@ -160,7 +172,7 @@
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage'
|
||||
import ${entityName}Modal from './components/${entityName}Modal.vue'
|
||||
import { columns, searchFormSchema, superQuerySchema } from './${entityName}.data';
|
||||
import { columns, superQuerySchema } from './${entityName}.data';
|
||||
import { list, deleteOne, batchDelete, getImportUrl,getExportUrl } from './${entityName}.api';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
<#include "/common/form/native/vue3NativeImport.ftl">
|
||||
@ -179,7 +191,9 @@
|
||||
import ${sub.entityName}List from './${sub.entityName}List.vue'
|
||||
</#list>
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
<#if is_range>
|
||||
import { cloneDeep } from "lodash-es";
|
||||
</#if>
|
||||
const formRef = ref();
|
||||
const queryParam = reactive<any>({});
|
||||
const checkedKeys = ref<Array<string | number>>([]);
|
||||
@ -199,8 +213,13 @@
|
||||
width: 120,
|
||||
fixed:'right'
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
beforeFetch: async (params) => {
|
||||
<#if is_range>
|
||||
let rangerQuery = await setRangeQuery();
|
||||
return Object.assign(params, rangerQuery);
|
||||
<#else>
|
||||
return Object.assign(params, queryParam);
|
||||
</#if>
|
||||
},
|
||||
pagination: {
|
||||
current: 1,
|
||||
@ -292,6 +311,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -310,8 +330,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -336,8 +357,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
},
|
||||
];
|
||||
</#if>
|
||||
@ -436,6 +458,32 @@
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
<#if is_range>
|
||||
|
||||
let rangeField = '${getRangeField(columns)}'
|
||||
|
||||
/**
|
||||
* 设置范围查询条件
|
||||
*/
|
||||
async function setRangeQuery(){
|
||||
let queryParamClone = cloneDeep(queryParam);
|
||||
if (rangeField) {
|
||||
let fieldsValue = rangeField.split(',');
|
||||
fieldsValue.forEach(item => {
|
||||
if (queryParamClone[item]) {
|
||||
let range = queryParamClone[item];
|
||||
queryParamClone[item+'_begin'] = range[0];
|
||||
queryParamClone[item+'_end'] = range[1];
|
||||
delete queryParamClone[item];
|
||||
} else {
|
||||
queryParamClone[item+'_begin'] = '';
|
||||
queryParamClone[item+'_end'] = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/native/vueNativeSearchStyle.ftl">
|
||||
|
||||
@ -57,7 +57,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -121,7 +121,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
|
||||
@ -87,6 +87,7 @@
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: 180,
|
||||
fixed:'right'
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" name="${entityName}Form">
|
||||
<a-row>
|
||||
<#assign need_category = false>
|
||||
<#assign bpm_flag=false>
|
||||
@ -14,6 +14,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -23,6 +24,7 @@
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign hasOnlyValidate = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign form_span = 24>
|
||||
<#if tableVo.fieldRowNum==2>
|
||||
<#assign form_span = 12>
|
||||
@ -38,6 +40,7 @@
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
<#assign hasOnlyValidate = true>
|
||||
</#if>
|
||||
<#assign formEntityName>${entityName}Form</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
<#if bpm_flag>
|
||||
@ -151,8 +154,18 @@
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -18,6 +19,7 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign form_span = 24>
|
||||
<#if tableVo.fieldRowNum==2>
|
||||
<#assign form_span = 12>
|
||||
@ -31,7 +33,7 @@
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form class="antd-modal-form" v-bind="formItemLayout" ref="formRef">
|
||||
<a-form class="antd-modal-form" v-bind="formItemLayout" ref="formRef" name="${sub.entityName}Form">
|
||||
<a-row>
|
||||
<#list sub.colums as po>
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
@ -40,6 +42,7 @@
|
||||
<#if po.fieldDbName=='bpm_status'>
|
||||
<#assign bpm_flag=true>
|
||||
</#if>
|
||||
<#assign formEntityName>${sub.entityName}</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
</a-row>
|
||||
@ -121,7 +124,18 @@
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
|
||||
@ -35,9 +35,9 @@
|
||||
<!-- 内嵌table区域 end -->
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -47,7 +47,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -257,6 +257,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -291,8 +292,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -316,8 +318,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -347,6 +350,6 @@
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
||||
@ -58,7 +58,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -106,6 +106,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -116,6 +124,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -152,6 +168,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
component: 'JDictSelectTag',
|
||||
@ -272,8 +295,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -294,8 +332,13 @@ export const formSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
@ -494,7 +537,7 @@ export const ${sub.entityName?uncap_first}Columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -565,8 +608,23 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -587,8 +645,13 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
@ -822,11 +885,27 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_depart'>
|
||||
type: JVxeTypes.departSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_user'>
|
||||
type: JVxeTypes.userSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" ref="formRef"/>
|
||||
<BasicForm @register="registerForm" ref="formRef" name="${entityName}Form" />
|
||||
<!-- 子表单区域 -->
|
||||
<a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs">
|
||||
<#list subTables as sub><#rt/>
|
||||
@ -157,6 +157,12 @@
|
||||
if (e.error === VALIDATE_FAILED) {
|
||||
// 如果有未通过表单验证的子表,就自动跳转到它所在的tab
|
||||
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
|
||||
if (e.errorFields) {
|
||||
const firstField = e.errorFields[0];
|
||||
if (firstField) {
|
||||
e.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#if sub.foreignRelationType=='1'>
|
||||
#segment#${sub.entityName}Form.vue
|
||||
<template>
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${sub.entityName}Form" class="basic-modal-form" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
|
||||
const [registerForm, { setProps, resetFields, setFieldsValue, getFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: ${sub.entityName?uncap_first}FormSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -62,8 +62,8 @@
|
||||
// 验证子表表单
|
||||
validate().then(()=>{
|
||||
return resolve()
|
||||
}).catch(()=> {
|
||||
return reject({ error: VALIDATE_FAILED ,index})
|
||||
}).catch(({ errorFields })=> {
|
||||
return reject({ error: VALIDATE_FAILED ,index, errorFields: errorFields, scrollToField: scrollToField })
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -77,5 +77,11 @@
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.basic-modal-form {
|
||||
overflow: auto;
|
||||
height: 340px;
|
||||
}
|
||||
</style>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
@ -21,9 +21,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -33,7 +33,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -230,6 +230,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -264,8 +265,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -289,8 +291,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -320,6 +323,6 @@
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
||||
@ -58,7 +58,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -106,6 +106,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -116,6 +124,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -152,6 +168,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
component: 'JDictSelectTag',
|
||||
@ -272,8 +295,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -294,8 +332,13 @@ export const formSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件------------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件------------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
@ -505,6 +548,13 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
<#elseif po.classType =='switch'>
|
||||
@ -762,11 +812,27 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_depart'>
|
||||
type: JVxeTypes.departSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_user'>
|
||||
type: JVxeTypes.userSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="${getModalWidth(tableVo.fieldRowNum?default(1))}" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" ref="formRef"/>
|
||||
<BasicForm @register="registerForm" ref="formRef" name="${entityName}Form"/>
|
||||
<!-- 子表单区域 -->
|
||||
<a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs">
|
||||
<#list subTables as sub><#rt/>
|
||||
@ -157,6 +157,12 @@
|
||||
if (e.error === VALIDATE_FAILED) {
|
||||
// 如果有未通过表单验证的子表,就自动跳转到它所在的tab
|
||||
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
|
||||
if (e.errorFields) {
|
||||
const firstField = e.errorFields[0];
|
||||
if (firstField) {
|
||||
e.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#if sub.foreignRelationType=='1'>
|
||||
#segment#${sub.entityName}Form.vue
|
||||
<template>
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${sub.entityName}Form" class="basic-modal-form"/>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
|
||||
const [registerForm, { setProps, resetFields, setFieldsValue, getFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: ${sub.entityName?uncap_first}FormSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -60,9 +60,9 @@
|
||||
// 验证子表表单
|
||||
validate().then(()=>{
|
||||
return resolve()
|
||||
}).catch(()=> {
|
||||
return reject({ error: VALIDATE_FAILED ,index})
|
||||
})
|
||||
}).catch(({ errorFields }) => {
|
||||
return reject({ error: VALIDATE_FAILED, index, errorFields: errorFields, scrollToField: scrollToField });
|
||||
});
|
||||
})
|
||||
}
|
||||
return {
|
||||
@ -75,5 +75,11 @@
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.basic-modal-form {
|
||||
overflow: auto;
|
||||
height: 340px;
|
||||
}
|
||||
</style>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -20,6 +21,8 @@
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign query_flag = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign is_range = false>
|
||||
<!--查询区域-->
|
||||
<div class="jeecg-basic-table-form-container">
|
||||
<a-form ref="formRef" @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
@ -56,12 +59,21 @@
|
||||
<#if po.classType=='popup'>
|
||||
<#assign need_popup = true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign need_popup_dict = true>
|
||||
</#if>
|
||||
<#if po.classType=='sel_tree'>
|
||||
<#assign need_select_tree = true>
|
||||
</#if>
|
||||
<#if po.classType=='time'>
|
||||
<#assign need_time = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single' && (po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal')>
|
||||
<#assign need_range_number = true>
|
||||
</#if>
|
||||
<#if po.queryMode!='single'>
|
||||
<#assign is_range = true>
|
||||
</#if>
|
||||
<#include "/common/form/native/vue3NativeSearch.ftl">
|
||||
</#list>
|
||||
<#if query_field_no gt 2>
|
||||
@ -89,9 +101,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -101,7 +113,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -163,6 +175,9 @@
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
</#if>
|
||||
<#if is_range>
|
||||
import { cloneDeep } from "lodash-es";
|
||||
</#if>
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
const formRef = ref();
|
||||
const queryParam = reactive<any>({});
|
||||
@ -182,8 +197,13 @@
|
||||
width: 120,
|
||||
fixed:'right'
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
beforeFetch: async (params) => {
|
||||
<#if is_range>
|
||||
let rangerQuery = await setRangeQuery();
|
||||
return Object.assign(params, rangerQuery);
|
||||
<#else>
|
||||
return Object.assign(params, queryParam);
|
||||
</#if>
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
@ -269,6 +289,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -285,8 +306,9 @@
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
}
|
||||
confirm: handleDelete.bind(null, record)
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -310,8 +332,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -407,6 +430,32 @@
|
||||
}
|
||||
}
|
||||
</#if>
|
||||
<#if is_range>
|
||||
|
||||
let rangeField = '${getRangeField(columns)}'
|
||||
|
||||
/**
|
||||
* 设置范围查询条件
|
||||
*/
|
||||
async function setRangeQuery(){
|
||||
let queryParamClone = cloneDeep(queryParam);
|
||||
if (rangeField) {
|
||||
let fieldsValue = rangeField.split(',');
|
||||
fieldsValue.forEach(item => {
|
||||
if (queryParamClone[item]) {
|
||||
let range = queryParamClone[item];
|
||||
queryParamClone[item+'_begin'] = range[0];
|
||||
queryParamClone[item+'_end'] = range[1];
|
||||
delete queryParamClone[item];
|
||||
} else {
|
||||
queryParamClone[item+'_begin'] = '';
|
||||
queryParamClone[item+'_end'] = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/native/vueNativeSearchStyle.ftl">
|
||||
|
||||
@ -58,7 +58,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -16,6 +17,7 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign form_span = 24>
|
||||
<#if tableVo.fieldRowNum==2>
|
||||
<#assign form_span = 12>
|
||||
@ -33,7 +35,7 @@
|
||||
<a-spin :spinning="loading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form v-bind="formItemLayout">
|
||||
<a-form v-bind="formItemLayout" name="${entityName}Form" ref="formRef">
|
||||
<a-row>
|
||||
<#list columns as po>
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
@ -42,6 +44,7 @@
|
||||
<#if po.fieldDbName=='bpm_status'>
|
||||
<#assign bpm_flag=true>
|
||||
</#if>
|
||||
<#assign formEntityName>${entityName}Form</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
</a-row>
|
||||
@ -135,6 +138,7 @@
|
||||
emits:['success'],
|
||||
setup(props, {emit}) {
|
||||
const loading = ref(false);
|
||||
const formRef = ref();
|
||||
<#list subTables as sub>
|
||||
<#if sub_index == 0>
|
||||
<#assign subTabActiveKey = '${sub.entityName?uncap_first}'>
|
||||
@ -247,6 +251,7 @@
|
||||
|
||||
async function queryMainData(id) {
|
||||
const row = await queryDataById(id);
|
||||
resetFields();
|
||||
const tmpData = {};
|
||||
Object.keys(formData).forEach((key) => {
|
||||
if(row.hasOwnProperty(key)){
|
||||
@ -268,7 +273,18 @@
|
||||
});
|
||||
|
||||
async function getFormData() {
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
return transformData(toRaw(formData))
|
||||
}
|
||||
|
||||
@ -332,7 +348,8 @@
|
||||
getFormData,
|
||||
submitForm,
|
||||
add,
|
||||
edit
|
||||
edit,
|
||||
formRef,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
<#assign need_dept = false>
|
||||
<#assign need_multi = false>
|
||||
<#assign need_popup = false>
|
||||
<#assign need_popup_dict = false>
|
||||
<#assign need_select_tag = false>
|
||||
<#assign need_select_tree = false>
|
||||
<#assign need_time = false>
|
||||
@ -20,6 +21,7 @@
|
||||
<#assign need_image_upload = false>
|
||||
<#assign need_editor = false>
|
||||
<#assign need_checkbox = false>
|
||||
<#assign need_range_number = false>
|
||||
<#assign form_span = 24>
|
||||
<#if tableVo.fieldRowNum==2>
|
||||
<#assign form_span = 12>
|
||||
@ -33,7 +35,7 @@
|
||||
<a-spin :spinning="loading">
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form v-bind="formItemLayout">
|
||||
<a-form v-bind="formItemLayout" name="${sub.entityName}Form" ref="formRef" class="antd-modal-form">
|
||||
<a-row>
|
||||
<#list sub.colums as po>
|
||||
<#if po.isShow == 'Y' && po.fieldValidType?default("") == 'only'>
|
||||
@ -42,6 +44,7 @@
|
||||
<#if po.fieldDbName=='bpm_status'>
|
||||
<#assign bpm_flag=true>
|
||||
</#if>
|
||||
<#assign formEntityName>${sub.entityName}Form</#assign>
|
||||
<#include "/common/form/native/vue3NativeForm.ftl">
|
||||
</#list>
|
||||
</a-row>
|
||||
@ -79,6 +82,7 @@
|
||||
const { createMessage } = useMessage();
|
||||
const isForm = true;
|
||||
const loading = ref(false);
|
||||
const formRef = ref();
|
||||
const formData = reactive<Record<string, any>>({
|
||||
id: '',
|
||||
<#include "/common/init/native/vue3NativeSubInitValue.ftl">
|
||||
@ -116,7 +120,18 @@
|
||||
}
|
||||
|
||||
async function getFormData() {
|
||||
await validate();
|
||||
try {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
} catch ({ errorFields }) {
|
||||
if (errorFields) {
|
||||
const firstField = errorFields[0];
|
||||
if (firstField) {
|
||||
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
return Promise.reject(errorFields);
|
||||
}
|
||||
let subFormData = toRaw(formData);
|
||||
if(Object.keys(subFormData).length>0){
|
||||
return subFormData
|
||||
@ -158,10 +173,17 @@
|
||||
setFieldsValue,
|
||||
handleFormChange,
|
||||
isForm,
|
||||
validateInfos
|
||||
validateInfos,
|
||||
formRef,
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
max-height: 340px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
@ -21,9 +21,9 @@
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
@ -33,7 +33,7 @@
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<a-button v-auth="'${entityPackage}:${tableName}:deleteBatch'">批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
@ -229,6 +229,7 @@
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: '${entityPackage}:${tableName}:edit'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -263,8 +264,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
];
|
||||
if(record.bpmStatus == '1' || !record.bpmStatus){
|
||||
@ -288,8 +290,9 @@
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
placement: 'topLeft'
|
||||
},
|
||||
auth: '${entityPackage}:${tableName}:delete'
|
||||
}
|
||||
]
|
||||
</#if>
|
||||
@ -319,6 +322,6 @@
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
||||
@ -58,7 +58,7 @@ export const columns: BasicColumn[] = [
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
@ -106,6 +106,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -116,6 +124,14 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType=='list_multi'>
|
||||
component: 'JSelectMultiple',
|
||||
componentProps:{
|
||||
@ -152,6 +168,13 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType=='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
component: 'JDictSelectTag',
|
||||
@ -272,8 +295,23 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -294,8 +332,13 @@ export const formSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
@ -505,8 +548,23 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
},
|
||||
<#elseif po.classType =='popup'>
|
||||
<#include "/common/form/vue3popup.ftl">
|
||||
<#elseif po.classType=='popup_dict'>
|
||||
component: 'JPopupDict',
|
||||
componentProps: {
|
||||
placeholder: '请选择${po.filedComment}',
|
||||
dictCode: '${po.dictTable},${po.dictText},${po.dictField}',
|
||||
multi: ${po.extendParams.popupMulti?c}
|
||||
},
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
component: 'JSelectDept',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='switch'>
|
||||
component: 'JSwitch',
|
||||
componentProps:{
|
||||
@ -527,8 +585,13 @@ export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
|
||||
<#-- update-begin---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
component: 'JSelectUser',
|
||||
<#-- update-end---author:chenrui ---date:20240102 for:[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件---------- -->
|
||||
componentProps:{
|
||||
labelKey:'realname',
|
||||
componentProps:{
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>
|
||||
labelKey: '${po.extendParams.text}',
|
||||
</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>
|
||||
rowKey: '${po.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#elseif po.classType =='textarea'>
|
||||
component: 'InputTextArea',
|
||||
@ -762,11 +825,27 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_depart'>
|
||||
type: JVxeTypes.departSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='sel_user'>
|
||||
type: JVxeTypes.userSelect,
|
||||
props:{
|
||||
<#if col.extendParams?exists && col.extendParams.text?exists>
|
||||
labelKey: '${col.extendParams.text}',
|
||||
</#if>
|
||||
<#if col.extendParams?exists && col.extendParams.store?exists>
|
||||
rowKey: '${col.extendParams.store}',
|
||||
</#if>
|
||||
},
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<!--表单区域 -->
|
||||
<div class="contentArea">
|
||||
<!--主表区域 -->
|
||||
<BasicForm @register="registerForm" ref="formRef" v-show="activeKey == refKeys[0]"/>
|
||||
<BasicForm @register="registerForm" ref="formRef" v-show="activeKey == refKeys[0]" name="${entityName}Form"/>
|
||||
<!--子表区域 -->
|
||||
<#list subTables as sub><#rt/>
|
||||
<#assign refKey = sub.entityName?uncap_first/>
|
||||
@ -192,6 +192,12 @@
|
||||
if (e.error === VALIDATE_FAILED) {
|
||||
// 如果有未通过表单验证的子表,就自动跳转到它所在的tab
|
||||
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
|
||||
if (e.errorFields) {
|
||||
const firstField = e.errorFields[0];
|
||||
if (firstField) {
|
||||
e.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#if sub.foreignRelationType=='1'>
|
||||
#segment#${sub.entityName}Form.vue
|
||||
<template>
|
||||
<BasicForm @register="registerForm"/>
|
||||
<BasicForm @register="registerForm" name="${sub.entityName}Form" class="basic-modal-form" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const [registerForm, {setProps, resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
|
||||
const [registerForm, { setProps, resetFields, setFieldsValue, getFieldsValue, validate, scrollToField }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: ${sub.entityName?uncap_first}FormSchema,
|
||||
showActionButtonGroup: false,
|
||||
@ -60,9 +60,9 @@
|
||||
// 验证子表表单
|
||||
validate().then(()=>{
|
||||
return resolve()
|
||||
}).catch(()=> {
|
||||
return reject({ error: VALIDATE_FAILED ,index})
|
||||
})
|
||||
}).catch(({ errorFields }) => {
|
||||
return reject({ error: VALIDATE_FAILED , index, errorFields: errorFields, scrollToField: scrollToField });
|
||||
});
|
||||
})
|
||||
}
|
||||
return {
|
||||
@ -75,5 +75,11 @@
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.basic-modal-form {
|
||||
overflow: auto;
|
||||
height: 340px;
|
||||
}
|
||||
</style>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
|
||||
@ -0,0 +1,288 @@
|
||||
server:
|
||||
port: 8080
|
||||
tomcat:
|
||||
max-swallow-size: -1
|
||||
error:
|
||||
include-exception: true
|
||||
include-stacktrace: ALWAYS
|
||||
include-message: ALWAYS
|
||||
servlet:
|
||||
context-path: /jeecg-boot
|
||||
compression:
|
||||
enabled: true
|
||||
min-response-size: 1024
|
||||
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: metrics,httptrace-new
|
||||
|
||||
spring:
|
||||
# flyway配置
|
||||
flyway:
|
||||
# 是否启用flyway
|
||||
enabled: false
|
||||
# 是否关闭要清除已有库下的表功能,生产环境必须为true,否则会删库,非常重要!!!
|
||||
clean-disabled: true
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
required: true
|
||||
## quartz定时任务,采用数据库方式
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: never
|
||||
#定时任务启动开关,true-开 false-关
|
||||
auto-startup: true
|
||||
#延迟1秒启动定时任务
|
||||
startup-delay: 1s
|
||||
#启动时更新己存在的Job
|
||||
overwrite-existing-jobs: true
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: MyScheduler
|
||||
instanceId: AUTO
|
||||
jobStore:
|
||||
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: true
|
||||
misfireThreshold: 12000
|
||||
clusterCheckinInterval: 15000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 10
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
#json 时间戳统一转换
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
jpa:
|
||||
open-in-view: false
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.DmDialect
|
||||
aop:
|
||||
proxy-target-class: true
|
||||
#配置freemarker
|
||||
freemarker:
|
||||
# 设置模板后缀名
|
||||
suffix: .ftl
|
||||
# 设置文档类型
|
||||
content-type: text/html
|
||||
# 设置页面编码格式
|
||||
charset: UTF-8
|
||||
# 设置页面缓存
|
||||
cache: false
|
||||
prefer-file-system-access: false
|
||||
# 设置ftl文件路径
|
||||
template-loader-path:
|
||||
- classpath:/templates
|
||||
template_update_delay: 0
|
||||
# 设置静态文件路径,js,css等
|
||||
mvc:
|
||||
static-path-pattern: /**
|
||||
#Spring Boot 2.6+后映射匹配的默认策略已从AntPathMatcher更改为PathPatternParser,需要手动指定为ant-path-matcher
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
resource:
|
||||
static-locations: classpath:/static/,classpath:/public/
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
- org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
|
||||
datasource:
|
||||
druid:
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
loginUsername: admin
|
||||
loginPassword: 123456
|
||||
allow:
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
#打开多数据源,加上上面的就可以实现多数据源的配置
|
||||
dynamic:
|
||||
druid:
|
||||
filters: stat,slf4j
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
# 最小连接池数量
|
||||
minIdle: 5
|
||||
# 最大连接池数量
|
||||
maxActive: 10
|
||||
datasource:
|
||||
# 重点是将数据源指向oracle 用compatibleMode=oracle即可
|
||||
master:
|
||||
url: jdbc:dm://127.0.0.1:30236/?schema=SYSDBA&compatibleMode=oracle&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
|
||||
username: SYSDBA
|
||||
password: SYSDBA
|
||||
driverClassName: dm.jdbc.driver.DmDriver
|
||||
#redis 配置
|
||||
redis:
|
||||
database: 0
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: ''
|
||||
#mybatis plus 设置
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml
|
||||
global-config:
|
||||
# 关闭MP3.0自带的banner
|
||||
banner: false
|
||||
db-config:
|
||||
#主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
|
||||
id-type: ASSIGN_ID
|
||||
# 默认数据库表下划线命名
|
||||
table-underline: true
|
||||
configuration:
|
||||
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
|
||||
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 返回类型为Map,显示null对应的字段
|
||||
call-setters-on-nulls: true
|
||||
#jeecg专用配置
|
||||
minidao:
|
||||
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
|
||||
jeecg:
|
||||
# 平台上线安全配置
|
||||
firewall:
|
||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||
dataSourceSafe: false
|
||||
# 低代码模式(dev:开发模式,prod:发布模式——关闭所有在线开发配置能力)
|
||||
lowCodeMode: dev
|
||||
# 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
#签名拦截接口
|
||||
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys,/sys/sendChangePwdSms,/sys/user/sendChangePhoneSms,/sys/sms,/desform/api/sendVerifyCode
|
||||
# 本地:local、Minio:minio、阿里云:alioss
|
||||
uploadType: local
|
||||
# 前端访问地址
|
||||
domainUrl:
|
||||
pc: http://localhost:3100
|
||||
app: http://localhost:8051
|
||||
path:
|
||||
#文件上传根目录 设置
|
||||
upload: /opt/upFiles
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: jeecgdev
|
||||
# ElasticSearch 6设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: 127.0.0.1:9200
|
||||
check-enabled: false
|
||||
# 在线预览文件服务器地址配置
|
||||
file-view-domain: http://fileview.jeecg.com
|
||||
# minio文件上传
|
||||
minio:
|
||||
minio_url: http://minio.jeecg.com
|
||||
minio_name: ??
|
||||
minio_pass: ??
|
||||
bucketName: otatest
|
||||
#大屏报表参数设置
|
||||
jmreport:
|
||||
#多租户模式,默认值为空(created:按照创建人隔离、tenant:按照租户隔离) (v1.6.2+ 新增)
|
||||
saasMode:
|
||||
# 平台上线安全配置(v1.6.2+ 新增)
|
||||
firewall:
|
||||
# 数据源安全 (开启后,不允许使用平台数据源、SQL解析加签并且不允许查询数据库)
|
||||
dataSourceSafe: false
|
||||
# 低代码开发模式(dev:开发模式,prod:发布模式—关闭在线报表设计功能,分配角色admin、lowdeveloper可以放开限制)
|
||||
lowCodeMode: dev
|
||||
#xxl-job配置
|
||||
xxljob:
|
||||
enabled: false
|
||||
adminAddresses: http://127.0.0.1:9080/xxl-job-admin
|
||||
appname: ${spring.application.name}
|
||||
accessToken: ''
|
||||
address: 127.0.0.1:30007
|
||||
ip: 127.0.0.1
|
||||
port: 30007
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
#分布式锁配置
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
password:
|
||||
type: STANDALONE
|
||||
enabled: true
|
||||
# ai-chat
|
||||
ai-chat:
|
||||
# 是否开启;必须。
|
||||
enabled: false
|
||||
# openAi接口秘钥,填写自己的apiKey;必须。
|
||||
apiKey: "????"
|
||||
# openAi域名,有代理就填代理的域名。默认:openAI官方apiHost
|
||||
apiHost: "https://api.openai.com"
|
||||
# 超时时间单位:s。默认 60s
|
||||
timeout: 60
|
||||
# 本地代理地址
|
||||
# proxy:
|
||||
# host: "http://127.0.0.1"
|
||||
# port: "7890"
|
||||
#cas单点登录
|
||||
cas:
|
||||
prefixUrl: http://cas.example.org:8443/cas
|
||||
#Mybatis输出sql日志
|
||||
logging:
|
||||
level:
|
||||
org.flywaydb: debug
|
||||
org.jeecg.modules.system.mapper: info
|
||||
#swagger
|
||||
knife4j:
|
||||
#开启增强配置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: false
|
||||
basic:
|
||||
enable: false
|
||||
username: jeecg
|
||||
password: jeecg1314
|
||||
#第三方登录
|
||||
justauth:
|
||||
enabled: true
|
||||
type:
|
||||
GITHUB:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/github/callback
|
||||
WECHAT_ENTERPRISE:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
|
||||
agent-id: ??
|
||||
DINGTALK:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/dingtalk/callback
|
||||
WECHAT_OPEN:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_open/callback
|
||||
cache:
|
||||
type: default
|
||||
prefix: 'demo::'
|
||||
timeout: 1h
|
||||
@ -0,0 +1,302 @@
|
||||
server:
|
||||
port: 8080
|
||||
tomcat:
|
||||
max-swallow-size: -1
|
||||
error:
|
||||
include-exception: true
|
||||
include-stacktrace: ALWAYS
|
||||
include-message: ALWAYS
|
||||
servlet:
|
||||
context-path: /jeecg-boot
|
||||
compression:
|
||||
enabled: true
|
||||
min-response-size: 1024
|
||||
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: metrics,httptrace-new
|
||||
|
||||
spring:
|
||||
# flyway配置
|
||||
flyway:
|
||||
# 是否启用flyway
|
||||
enabled: false
|
||||
# 是否关闭要清除已有库下的表功能,生产环境必须为true,否则会删库,非常重要!!!
|
||||
clean-disabled: true
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
required: true
|
||||
## quartz定时任务,采用数据库方式
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: never
|
||||
#定时任务启动开关,true-开 false-关
|
||||
auto-startup: true
|
||||
#延迟1秒启动定时任务
|
||||
startup-delay: 1s
|
||||
#启动时更新己存在的Job
|
||||
overwrite-existing-jobs: true
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: MyScheduler
|
||||
instanceId: AUTO
|
||||
jobStore:
|
||||
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: true
|
||||
misfireThreshold: 12000
|
||||
clusterCheckinInterval: 15000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 10
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
#json 时间戳统一转换
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
jpa:
|
||||
open-in-view: false
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
aop:
|
||||
proxy-target-class: true
|
||||
#配置freemarker
|
||||
freemarker:
|
||||
# 设置模板后缀名
|
||||
suffix: .ftl
|
||||
# 设置文档类型
|
||||
content-type: text/html
|
||||
# 设置页面编码格式
|
||||
charset: UTF-8
|
||||
# 设置页面缓存
|
||||
cache: false
|
||||
prefer-file-system-access: false
|
||||
# 设置ftl文件路径
|
||||
template-loader-path:
|
||||
- classpath:/templates
|
||||
template_update_delay: 0
|
||||
# 设置静态文件路径,js,css等
|
||||
mvc:
|
||||
static-path-pattern: /**
|
||||
#Spring Boot 2.6+后映射匹配的默认策略已从AntPathMatcher更改为PathPatternParser,需要手动指定为ant-path-matcher
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
resource:
|
||||
static-locations: classpath:/static/,classpath:/public/
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
- org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
|
||||
datasource:
|
||||
druid:
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
loginUsername: admin
|
||||
loginPassword: 123456
|
||||
allow:
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
dynamic:
|
||||
druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
|
||||
# 连接池的配置信息
|
||||
# 初始化大小,最小,最大
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
validationQuery: SELECT 1
|
||||
#testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
# 打开PSCache,并且指定每个连接上PSCache的大小
|
||||
poolPreparedStatements: true
|
||||
maxPoolPreparedStatementPerConnectionSize: 20
|
||||
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
filters: stat,slf4j
|
||||
# 打开mergeSql功能;慢SQL记录
|
||||
stat:
|
||||
merge-sql: true
|
||||
slow-sql-millis: 5000
|
||||
datasource:
|
||||
master:
|
||||
url: jdbc:kingbase8://127.0.0.1:4321/test
|
||||
username: system
|
||||
password: system
|
||||
driver-class-name: com.kingbase8.Driver
|
||||
#redis 配置
|
||||
redis:
|
||||
database: 0
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: ''
|
||||
#mybatis plus 设置
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml
|
||||
global-config:
|
||||
# 关闭MP3.0自带的banner
|
||||
banner: false
|
||||
db-config:
|
||||
#主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
|
||||
id-type: ASSIGN_ID
|
||||
# 默认数据库表下划线命名
|
||||
table-underline: true
|
||||
configuration:
|
||||
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
|
||||
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 返回类型为Map,显示null对应的字段
|
||||
call-setters-on-nulls: true
|
||||
#jeecg专用配置
|
||||
minidao:
|
||||
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
|
||||
jeecg:
|
||||
# 平台上线安全配置
|
||||
firewall:
|
||||
# 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||
dataSourceSafe: false
|
||||
# 低代码模式(dev:开发模式,prod:发布模式——关闭所有在线开发配置能力)
|
||||
lowCodeMode: dev
|
||||
# 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
#签名拦截接口
|
||||
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys,/sys/sendChangePwdSms,/sys/user/sendChangePhoneSms,/sys/sms,/desform/api/sendVerifyCode
|
||||
# 本地:local、Minio:minio、阿里云:alioss
|
||||
uploadType: local
|
||||
# 前端访问地址
|
||||
domainUrl:
|
||||
pc: http://localhost:3100
|
||||
app: http://localhost:8051
|
||||
path:
|
||||
#文件上传根目录 设置
|
||||
upload: /opt/upFiles
|
||||
#webapp文件路径
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/bigscreen/category/**,/bigscreen/visual/**,/bigscreen/map/**,/jmreport/bigscreen2/**
|
||||
#阿里云oss存储和大鱼短信秘钥配置
|
||||
oss:
|
||||
accessKey: ??
|
||||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: jeecgdev
|
||||
# ElasticSearch 6设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: 127.0.0.1:9200
|
||||
check-enabled: false
|
||||
# 在线预览文件服务器地址配置
|
||||
file-view-domain: http://fileview.jeecg.com
|
||||
# minio文件上传
|
||||
minio:
|
||||
minio_url: http://minio.jeecg.com
|
||||
minio_name: ??
|
||||
minio_pass: ??
|
||||
bucketName: otatest
|
||||
#大屏报表参数设置
|
||||
jmreport:
|
||||
#多租户模式,默认值为空(created:按照创建人隔离、tenant:按照租户隔离) (v1.6.2+ 新增)
|
||||
saasMode:
|
||||
# 平台上线安全配置(v1.6.2+ 新增)
|
||||
firewall:
|
||||
# 数据源安全 (开启后,不允许使用平台数据源、SQL解析加签并且不允许查询数据库)
|
||||
dataSourceSafe: false
|
||||
# 低代码开发模式(dev:开发模式,prod:发布模式—关闭在线报表设计功能,分配角色admin、lowdeveloper可以放开限制)
|
||||
lowCodeMode: dev
|
||||
#xxl-job配置
|
||||
xxljob:
|
||||
enabled: false
|
||||
adminAddresses: http://127.0.0.1:9080/xxl-job-admin
|
||||
appname: ${spring.application.name}
|
||||
accessToken: ''
|
||||
address: 127.0.0.1:30007
|
||||
ip: 127.0.0.1
|
||||
port: 30007
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
#分布式锁配置
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
password:
|
||||
type: STANDALONE
|
||||
enabled: true
|
||||
# ai-chat
|
||||
ai-chat:
|
||||
# 是否开启;必须。
|
||||
enabled: false
|
||||
# openAi接口秘钥,填写自己的apiKey;必须。
|
||||
apiKey: "????"
|
||||
# openAi域名,有代理就填代理的域名。默认:openAI官方apiHost
|
||||
apiHost: "https://api.openai.com"
|
||||
# 超时时间单位:s。默认 60s
|
||||
timeout: 60
|
||||
# 本地代理地址
|
||||
# proxy:
|
||||
# host: "http://127.0.0.1"
|
||||
# port: "7890"
|
||||
#cas单点登录
|
||||
cas:
|
||||
prefixUrl: http://cas.example.org:8443/cas
|
||||
#Mybatis输出sql日志
|
||||
logging:
|
||||
level:
|
||||
org.flywaydb: debug
|
||||
org.jeecg.modules.system.mapper: info
|
||||
#swagger
|
||||
knife4j:
|
||||
#开启增强配置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: false
|
||||
basic:
|
||||
enable: false
|
||||
username: jeecg
|
||||
password: jeecg1314
|
||||
#第三方登录
|
||||
justauth:
|
||||
enabled: true
|
||||
type:
|
||||
GITHUB:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/github/callback
|
||||
WECHAT_ENTERPRISE:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_enterprise/callback
|
||||
agent-id: ??
|
||||
DINGTALK:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/dingtalk/callback
|
||||
WECHAT_OPEN:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/sys/thirdLogin/wechat_open/callback
|
||||
cache:
|
||||
type: default
|
||||
prefix: 'demo::'
|
||||
timeout: 1h
|
||||
@ -231,7 +231,7 @@ jeecg:
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: 127.0.0.1:9200
|
||||
check-enabled: true
|
||||
check-enabled: false
|
||||
# 在线预览文件服务器地址配置
|
||||
file-view-domain: http://fileview.jeecg.com
|
||||
# minio文件上传
|
||||
|
||||
@ -10,7 +10,6 @@ database_name=jeecg-boot
|
||||
#url=jdbc:oracle:thin:@192.168.1.200:1521:ORCL
|
||||
#username=scott
|
||||
#password=tiger
|
||||
#database_name=ORCL
|
||||
|
||||
#postgre
|
||||
#diver_name=org.postgresql.Driver
|
||||
@ -20,7 +19,7 @@ database_name=jeecg-boot
|
||||
#database_name=jeecg
|
||||
#schemaName=public
|
||||
|
||||
#SQLServer2005\u4ee5\u4e0a
|
||||
#SQLServer2005\u4EE5\u4E0A
|
||||
#diver_name=org.hibernate.dialect.SQLServerDialect
|
||||
#url=jdbc:sqlserver://192.168.1.200:1433;DatabaseName=jeecg
|
||||
#username=sa
|
||||
|
||||
@ -1,5 +1,49 @@
|
||||
version: '2'
|
||||
services:
|
||||
jeecg-boot-mysql:
|
||||
build:
|
||||
context: ../db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
TZ: Asia/Shanghai
|
||||
restart: always
|
||||
container_name: jeecg-boot-mysql
|
||||
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
|
||||
container_name: jeecg-boot-redis
|
||||
hostname: jeecg-boot-redis
|
||||
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-nacos:
|
||||
restart: always
|
||||
build:
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
@ -12,4 +12,4 @@ EXPOSE 9999
|
||||
|
||||
ADD ./target/jeecg-cloud-gateway-3.7.0.jar ./
|
||||
|
||||
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.7.0.jar
|
||||
CMD sleep 100;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.7.0.jar
|
||||
@ -1,4 +1,4 @@
|
||||
FROM alibabadragonwell/dragonwell:17-anolis
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/java:21-anolis
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
@ -12,4 +12,4 @@ EXPOSE 8848
|
||||
|
||||
ADD ./target/jeecg-cloud-nacos-3.7.0.jar ./
|
||||
|
||||
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-3.7.0.jar
|
||||
CMD sleep 30;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-3.7.0.jar
|
||||
3275
jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/docs/db/nacos_dm.sql
Normal file
3275
jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/docs/db/nacos_dm.sql
Normal file
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,8 @@
|
||||
|
||||
<properties>
|
||||
<log4j2.version>2.17.0</log4j2.version>
|
||||
<dm8.version>8.1.1.49</dm8.version>
|
||||
<nacos.version>2.3.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -49,22 +51,34 @@
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.nacos</groupId>
|
||||
<artifactId>nacos-naming</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.nacos</groupId>
|
||||
<artifactId>nacos-istio</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.nacos</groupId>
|
||||
<artifactId>nacos-config</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.nacos</groupId>
|
||||
<artifactId>nacos-console</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>${nacos.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT -->
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
<artifactId>Dm8JdbcDriver18</artifactId>
|
||||
<version>${dm8.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
<artifactId>DmDialect-for-hibernate5.0</artifactId>
|
||||
<version>${dm8.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
server:
|
||||
servlet:
|
||||
contextPath: /nacos
|
||||
tomcat:
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: '%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i'
|
||||
basedir: ''
|
||||
spring:
|
||||
sql:
|
||||
init:
|
||||
platform: dm
|
||||
db:
|
||||
pool:
|
||||
config:
|
||||
driverClassName: dm.jdbc.driver.DmDriver
|
||||
num: 1
|
||||
password:
|
||||
'0': SYSDBA
|
||||
url:
|
||||
'0': jdbc:dm://192.168.1.188:30236/DMSERVER?schema=NACOS&compatibleMode=mysql&ignoreCase=true&ENCODING=utf-8
|
||||
user:
|
||||
'0': SYSDBA
|
||||
management:
|
||||
metrics:
|
||||
export:
|
||||
elastic:
|
||||
enabled: false
|
||||
influx:
|
||||
enabled: false
|
||||
nacos:
|
||||
core:
|
||||
auth:
|
||||
enabled: false
|
||||
caching:
|
||||
enabled: true
|
||||
server:
|
||||
identity:
|
||||
key: example
|
||||
value: example
|
||||
plugin:
|
||||
nacos:
|
||||
token:
|
||||
expire:
|
||||
seconds: 18000
|
||||
secret:
|
||||
key: SecretKey01234567890123456789012345345678999987654901234567890123456789
|
||||
system:
|
||||
type: nacos
|
||||
istio:
|
||||
mcp:
|
||||
server:
|
||||
enabled: false
|
||||
naming:
|
||||
empty-service:
|
||||
auto-clean: true
|
||||
clean:
|
||||
initial-delay-ms: 50000
|
||||
period-time-ms: 30000
|
||||
security:
|
||||
ignore:
|
||||
urls: /,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
|
||||
standalone: true
|
||||
@ -0,0 +1,60 @@
|
||||
server:
|
||||
servlet:
|
||||
contextPath: /nacos
|
||||
tomcat:
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: '%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i'
|
||||
basedir: ''
|
||||
spring:
|
||||
sql:
|
||||
init:
|
||||
platform: mysql
|
||||
db:
|
||||
num: 1
|
||||
password:
|
||||
'0': ${MYSQL-PWD:root}
|
||||
url:
|
||||
'0': jdbc:mysql://${MYSQL-HOST:jeecg-boot-mysql}:${MYSQL-PORT:3306}/${MYSQL-DB:nacos}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
|
||||
user:
|
||||
'0': ${MYSQL-USER:root}
|
||||
management:
|
||||
metrics:
|
||||
export:
|
||||
elastic:
|
||||
enabled: false
|
||||
influx:
|
||||
enabled: false
|
||||
nacos:
|
||||
core:
|
||||
auth:
|
||||
enabled: false
|
||||
caching:
|
||||
enabled: true
|
||||
server:
|
||||
identity:
|
||||
key: example
|
||||
value: example
|
||||
plugin:
|
||||
nacos:
|
||||
token:
|
||||
expire:
|
||||
seconds: 18000
|
||||
secret:
|
||||
key: SecretKey01234567890123456789012345345678999987654901234567890123456789
|
||||
system:
|
||||
type: nacos
|
||||
istio:
|
||||
mcp:
|
||||
server:
|
||||
enabled: false
|
||||
naming:
|
||||
empty-service:
|
||||
auto-clean: true
|
||||
clean:
|
||||
initial-delay-ms: 50000
|
||||
period-time-ms: 30000
|
||||
security:
|
||||
ignore:
|
||||
urls: /,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
|
||||
standalone: true
|
||||
@ -1,60 +1,3 @@
|
||||
server:
|
||||
servlet:
|
||||
contextPath: /nacos
|
||||
tomcat:
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: '%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i'
|
||||
basedir: ''
|
||||
spring:
|
||||
sql:
|
||||
init:
|
||||
platform: mysql
|
||||
db:
|
||||
num: 1
|
||||
password:
|
||||
'0': ${MYSQL-PWD:root}
|
||||
url:
|
||||
'0': jdbc:mysql://${MYSQL-HOST:jeecg-boot-mysql}:${MYSQL-PORT:3306}/${MYSQL-DB:nacos}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
|
||||
user:
|
||||
'0': ${MYSQL-USER:root}
|
||||
management:
|
||||
metrics:
|
||||
export:
|
||||
elastic:
|
||||
enabled: false
|
||||
influx:
|
||||
enabled: false
|
||||
nacos:
|
||||
core:
|
||||
auth:
|
||||
enabled: false
|
||||
caching:
|
||||
enabled: true
|
||||
server:
|
||||
identity:
|
||||
key: example
|
||||
value: example
|
||||
plugin:
|
||||
nacos:
|
||||
token:
|
||||
expire:
|
||||
seconds: 18000
|
||||
secret:
|
||||
key: SecretKey01234567890123456789012345345678999987654901234567890123456789
|
||||
system:
|
||||
type: nacos
|
||||
istio:
|
||||
mcp:
|
||||
server:
|
||||
enabled: false
|
||||
naming:
|
||||
empty-service:
|
||||
auto-clean: true
|
||||
clean:
|
||||
initial-delay-ms: 50000
|
||||
period-time-ms: 30000
|
||||
security:
|
||||
ignore:
|
||||
urls: /,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
|
||||
standalone: true
|
||||
profiles:
|
||||
active: mysql
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
@ -12,4 +12,4 @@ EXPOSE 7002
|
||||
|
||||
ADD ./target/jeecg-demo-cloud-start-3.7.0.jar ./
|
||||
|
||||
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-demo-cloud-start-3.7.0.jar
|
||||
CMD sleep 60;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-demo-cloud-start-3.7.0.jar
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
@ -12,4 +12,4 @@ EXPOSE 7001
|
||||
|
||||
ADD ./target/jeecg-system-cloud-start-3.7.0.jar ./
|
||||
|
||||
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-cloud-start-3.7.0.jar
|
||||
CMD sleep 60;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-cloud-start-3.7.0.jar
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM anapsix/alpine-java:8_server-jre_unlimited
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/alpine-java:8_server-jre_unlimited
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
|
||||
@ -1,119 +1,283 @@
|
||||
#
|
||||
# XXL-JOB v2.2.0
|
||||
# Copyright (c) 2015-present, xuxueli.
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
||||
use `xxl_job`;
|
||||
Source Server : mysql5.7
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50738
|
||||
Source Host : 127.0.0.1:3306
|
||||
Source Schema : xxl_job_241
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 50738
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 21/08/2024 22:43:14
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
CREATE TABLE `xxl_job_info` (
|
||||
-- ----------------------------
|
||||
-- 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, '2024-08-21 22:42:43');
|
||||
INSERT INTO `xxl_job_group` VALUES (2, 'jeecg-demo', '测试Demo模块', 0, 'http://192.168.0.105:10001/', '2024-08-21 22:42:43');
|
||||
INSERT INTO `xxl_job_group` VALUES (3, 'jeecg-system', '系统System模块', 0, 'http://192.168.0.105:10002/', '2024-08-21 22:42:43');
|
||||
|
||||
-- ----------------------------
|
||||
-- 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, 0, 1724256000000);
|
||||
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, 1724251373000, 1724251374000);
|
||||
|
||||
-- ----------------------------
|
||||
-- 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 = 82 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 (1, 1, 1, NULL, 'demoJobHandler', '', NULL, 0, '2024-08-21 22:29:07', 500, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||
INSERT INTO `xxl_job_log` VALUES (2, 1, 1, NULL, 'demoJobHandler', '', NULL, 0, '2024-08-21 22:29:48', 500, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||
INSERT INTO `xxl_job_log` VALUES (3, 1, 1, NULL, 'demoJob', '', NULL, 0, '2024-08-21 22:30:34', 500, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||
INSERT INTO `xxl_job_log` VALUES (4, 1, 1, NULL, 'demoJob', '', NULL, 0, '2024-08-21 22:30:40', 500, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:null<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>调度失败:执行器地址为空<br><br>', NULL, 0, NULL, 2);
|
||||
INSERT INTO `xxl_job_log` VALUES (5, 2, 2, 'http://192.168.0.105:10001/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:14', 500, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10001/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10001/<br>code:500<br>msg:job handler [demoJob] not found.', NULL, 0, NULL, 2);
|
||||
INSERT INTO `xxl_job_log` VALUES (6, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:27', 200, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:27', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (7, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:36', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:36', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (8, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:37', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:37', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (9, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:38', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:38', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (10, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:39', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:39', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (11, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:40', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:40', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (12, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:40', 200, '任务触发类型:手动触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:40', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (13, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:41', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:41', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (14, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:42', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:42', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (15, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:43', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:43', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (16, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:44', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:44', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (17, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:45', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:45', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (18, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:46', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:46', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (19, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:47', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:47', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (20, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:48', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:48', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (21, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:49', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:49', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (22, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:50', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:50', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (23, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:51', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:51', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (24, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:52', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:52', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (25, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:53', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:53', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (26, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:54', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:54', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (27, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:55', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:55', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (28, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:56', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:56', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (29, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:57', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:57', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (30, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:58', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:58', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (31, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:41:59', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:41:59', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (32, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:00', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:00', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (33, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:01', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:01', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (34, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:02', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:02', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (35, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:03', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:03', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (36, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:04', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:04', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (37, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:05', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:05', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (38, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:06', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:06', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (39, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:07', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:07', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (40, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:08', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:08', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (41, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:09', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:09', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (42, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:10', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:10', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (43, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:11', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:11', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (44, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:12', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:12', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (45, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:13', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:13', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (46, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:14', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:14', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (47, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:15', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:15', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (48, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:16', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:16', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (49, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:17', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:17', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (50, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:18', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:18', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (51, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:19', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:19', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (52, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:20', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:20', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (53, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:21', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:21', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (54, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:22', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:22', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (55, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:23', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:23', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (56, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:24', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:24', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (57, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:25', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:25', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (58, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:26', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:26', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (59, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:27', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:27', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (60, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:28', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:28', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (61, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:29', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:29', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (62, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:30', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:30', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (63, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:31', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:31', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (64, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:32', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:32', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (65, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:33', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:33', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (66, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:34', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:34', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (67, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:35', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:35', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (68, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:36', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:36', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (69, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:37', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:37', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (70, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:38', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:38', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (71, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:39', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:39', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (72, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:40', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:40', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (73, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:41', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:41', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (74, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:42', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:42', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (75, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:43', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:43', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (76, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:44', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:44', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (77, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:45', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:45', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (78, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:46', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:46', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (79, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:47', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:47', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (80, 3, 2, 'http://192.168.0.105:10002/', 'demoJob', '', NULL, 0, '2024-08-21 22:42:48', 200, '任务触发类型:Cron触发<br>调度机器:192.168.0.105<br>执行器-注册方式:自动注册<br>执行器-地址列表:[http://192.168.0.105:10002/]<br>路由策略:第一个<br>阻塞处理策略:单机串行<br>任务超时时间:0<br>失败重试次数:0<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>触发调度:<br>address:http://192.168.0.105:10002/<br>code:200<br>msg:null', '2024-08-21 22:42:48', 0, '', 0);
|
||||
INSERT INTO `xxl_job_log` VALUES (81, 3, 2, NULL, NULL, NULL, NULL, 0, '2024-08-21 22:42:49', 0, NULL, 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 = 4 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);
|
||||
|
||||
-- ----------------------------
|
||||
-- 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 = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
CREATE TABLE `xxl_job_user` (
|
||||
-- ----------------------------
|
||||
-- Records of xxl_job_registry
|
||||
-- ----------------------------
|
||||
INSERT INTO `xxl_job_registry` VALUES (1, 'EXECUTOR', 'jeecg-demo', 'http://192.168.0.105:10001/', '2024-08-21 22:42:43');
|
||||
INSERT INTO `xxl_job_registry` VALUES (3, 'EXECUTOR', 'jeecg-system', 'http://192.168.0.105:10002/', '2024-08-21 22:42:21');
|
||||
|
||||
-- ----------------------------
|
||||
-- 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;
|
||||
|
||||
|
||||
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;
|
||||
-- ----------------------------
|
||||
-- Records of xxl_job_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `xxl_job_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<version>2.3.2</version>
|
||||
</dependency>
|
||||
<!-- mysql -->
|
||||
<dependency>
|
||||
|
||||
@ -1,16 +1,27 @@
|
||||
package com.xxl.job.admin;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2018-10-28 00:38:13
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
public class XxlJobAdminApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XxlJobAdminApplication.class, args);
|
||||
ConfigurableApplicationContext application = SpringApplication.run(XxlJobAdminApplication.class, args);
|
||||
Environment env = application.getEnvironment();
|
||||
String port = env.getProperty("server.port");
|
||||
String path = env.getProperty("server.servlet.context-path");
|
||||
log.info("\n----------------------------------------------------------\n\t" +
|
||||
"Application XxlJobAdmin is running! Access URLs:\n\t" +
|
||||
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
|
||||
"----------------------------------------------------------");
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,6 +12,8 @@ import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -51,11 +53,12 @@ public class IndexController {
|
||||
|
||||
@RequestMapping("/toLogin")
|
||||
@PermissionLimit(limit=false)
|
||||
public String toLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
public ModelAndView toLogin(HttpServletRequest request, HttpServletResponse response,ModelAndView modelAndView) {
|
||||
if (loginService.ifLogin(request, response) != null) {
|
||||
return "redirect:/";
|
||||
modelAndView.setView(new RedirectView("/",true,false));
|
||||
return modelAndView;
|
||||
}
|
||||
return "login";
|
||||
return new ModelAndView("login");
|
||||
}
|
||||
|
||||
@RequestMapping(value="login", method=RequestMethod.POST)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
@ -34,12 +35,14 @@ public class JobGroupController {
|
||||
private XxlJobRegistryDao xxlJobRegistryDao;
|
||||
|
||||
@RequestMapping
|
||||
@PermissionLimit(adminuser = true)
|
||||
public String index(Model model) {
|
||||
return "jobgroup/jobgroup.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public Map<String, Object> pageList(HttpServletRequest request,
|
||||
@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
@ -59,6 +62,7 @@ public class JobGroupController {
|
||||
|
||||
@RequestMapping("/save")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> save(XxlJobGroup xxlJobGroup){
|
||||
|
||||
// valid
|
||||
@ -68,13 +72,23 @@ public class JobGroupController {
|
||||
if (xxlJobGroup.getAppname().length()<4 || xxlJobGroup.getAppname().length()>64) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length") );
|
||||
}
|
||||
if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) {
|
||||
return new ReturnT<String>(500, "AppName"+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")) );
|
||||
}
|
||||
if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_title")+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
if (xxlJobGroup.getAddressType()!=0) {
|
||||
if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit") );
|
||||
}
|
||||
if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList")+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
|
||||
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
||||
for (String item: addresss) {
|
||||
if (item==null || item.trim().length()==0) {
|
||||
@ -83,12 +97,16 @@ public class JobGroupController {
|
||||
}
|
||||
}
|
||||
|
||||
// process
|
||||
xxlJobGroup.setUpdateTime(new Date());
|
||||
|
||||
int ret = xxlJobGroupDao.save(xxlJobGroup);
|
||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> update(XxlJobGroup xxlJobGroup){
|
||||
// valid
|
||||
if (xxlJobGroup.getAppname()==null || xxlJobGroup.getAppname().trim().length()==0) {
|
||||
@ -126,6 +144,9 @@ public class JobGroupController {
|
||||
}
|
||||
}
|
||||
|
||||
// process
|
||||
xxlJobGroup.setUpdateTime(new Date());
|
||||
|
||||
int ret = xxlJobGroupDao.update(xxlJobGroup);
|
||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||
}
|
||||
@ -154,6 +175,7 @@ public class JobGroupController {
|
||||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> remove(int id){
|
||||
|
||||
// valid
|
||||
@ -173,6 +195,7 @@ public class JobGroupController {
|
||||
|
||||
@RequestMapping("/loadById")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<XxlJobGroup> loadById(int id){
|
||||
XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
|
||||
return jobGroup!=null?new ReturnT<XxlJobGroup>(jobGroup):new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.core.cron.CronExpression;
|
||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
||||
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
||||
import com.xxl.job.admin.core.thread.JobScheduleHelper;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
@ -16,6 +16,8 @@ import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.util.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -24,7 +26,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -34,6 +35,7 @@ import java.util.*;
|
||||
@Controller
|
||||
@RequestMapping("/jobinfo")
|
||||
public class JobInfoController {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobInfoController.class);
|
||||
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
@ -47,6 +49,8 @@ public class JobInfoController {
|
||||
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values()); // 路由策略-列表
|
||||
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
|
||||
model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values()); // 阻塞处理策略-字典
|
||||
model.addAttribute("ScheduleTypeEnum", ScheduleTypeEnum.values()); // 调度类型
|
||||
model.addAttribute("MisfireStrategyEnum", MisfireStrategyEnum.values()); // 调度过期策略
|
||||
|
||||
// 执行器列表
|
||||
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
|
||||
@ -131,36 +135,38 @@ public class JobInfoController {
|
||||
|
||||
@RequestMapping("/trigger")
|
||||
@ResponseBody
|
||||
//@PermissionLimit(limit = false)
|
||||
public ReturnT<String> triggerJob(int id, String executorParam, String addressList) {
|
||||
// force cover job param
|
||||
if (executorParam == null) {
|
||||
executorParam = "";
|
||||
}
|
||||
|
||||
JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
|
||||
return ReturnT.SUCCESS;
|
||||
public ReturnT<String> triggerJob(HttpServletRequest request, int id, String executorParam, String addressList) {
|
||||
// login user
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
// trigger
|
||||
return xxlJobService.trigger(loginUser, id, executorParam, addressList);
|
||||
}
|
||||
|
||||
@RequestMapping("/nextTriggerTime")
|
||||
@ResponseBody
|
||||
public ReturnT<List<String>> nextTriggerTime(String cron) {
|
||||
public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
|
||||
|
||||
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
|
||||
paramXxlJobInfo.setScheduleType(scheduleType);
|
||||
paramXxlJobInfo.setScheduleConf(scheduleConf);
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
try {
|
||||
CronExpression cronExpression = new CronExpression(cron);
|
||||
Date lastTime = new Date();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
lastTime = cronExpression.getNextValidTimeAfter(lastTime);
|
||||
lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
|
||||
if (lastTime != null) {
|
||||
result.add(DateUtil.formatDateTime(lastTime));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid"));
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) + e.getMessage());
|
||||
}
|
||||
return new ReturnT<List<String>>(result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.core.complete.XxlJobCompleter;
|
||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
@ -19,9 +20,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -128,27 +131,38 @@ public class JobLogController {
|
||||
|
||||
model.addAttribute("triggerCode", jobLog.getTriggerCode());
|
||||
model.addAttribute("handleCode", jobLog.getHandleCode());
|
||||
model.addAttribute("executorAddress", jobLog.getExecutorAddress());
|
||||
model.addAttribute("triggerTime", jobLog.getTriggerTime().getTime());
|
||||
model.addAttribute("logId", jobLog.getId());
|
||||
return "joblog/joblog.detail";
|
||||
}
|
||||
|
||||
@RequestMapping("/logDetailCat")
|
||||
@ResponseBody
|
||||
public ReturnT<LogResult> logDetailCat(String executorAddress, long triggerTime, long logId, int fromLineNum){
|
||||
public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum){
|
||||
try {
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(executorAddress);
|
||||
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(triggerTime, logId, fromLineNum));
|
||||
// valid
|
||||
XxlJobLog jobLog = xxlJobLogDao.load(logId); // todo, need to improve performance
|
||||
if (jobLog == null) {
|
||||
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_logid_unvalid"));
|
||||
}
|
||||
|
||||
// log cat
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
|
||||
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));
|
||||
|
||||
// is end
|
||||
if (logResult.getContent()!=null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
|
||||
XxlJobLog jobLog = xxlJobLogDao.load(logId);
|
||||
if (jobLog.getHandleCode() > 0) {
|
||||
logResult.getContent().setEnd(true);
|
||||
}
|
||||
}
|
||||
|
||||
// fix xss
|
||||
if (logResult.getContent()!=null && StringUtils.hasText(logResult.getContent().getLogContent())) {
|
||||
String newLogContent = logResult.getContent().getLogContent();
|
||||
newLogContent = HtmlUtils.htmlEscape(newLogContent, "UTF-8");
|
||||
logResult.getContent().setLogContent(newLogContent);
|
||||
}
|
||||
|
||||
return logResult;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
@ -183,7 +197,7 @@ public class JobLogController {
|
||||
log.setHandleCode(ReturnT.FAIL_CODE);
|
||||
log.setHandleMsg( I18nUtil.getString("joblog_kill_log_byman")+":" + (runResult.getMsg()!=null?runResult.getMsg():""));
|
||||
log.setHandleTime(new Date());
|
||||
xxlJobLogDao.updateHandleInfo(log);
|
||||
XxlJobCompleter.updateHandleInfoAndFinish(log);
|
||||
return new ReturnT<String>(runResult.getMsg());
|
||||
} else {
|
||||
return new ReturnT<String>(500, runResult.getMsg());
|
||||
|
||||
@ -56,6 +56,13 @@ public class UserController {
|
||||
List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role);
|
||||
int list_count = xxlJobUserDao.pageListCount(start, length, username, role);
|
||||
|
||||
// filter
|
||||
if (list!=null && list.size()>0) {
|
||||
for (XxlJobUser item: list) {
|
||||
item.setPassword(null);
|
||||
}
|
||||
}
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
|
||||
@ -3,8 +3,8 @@ package com.xxl.job.admin.controller.interceptor;
|
||||
import com.xxl.job.admin.core.util.FtlUtil;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -17,7 +17,7 @@ import java.util.HashMap;
|
||||
* @author xuxueli 2015-12-12 18:09:04
|
||||
*/
|
||||
@Component
|
||||
public class CookieInterceptor extends HandlerInterceptorAdapter {
|
||||
public class CookieInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
@ -36,8 +36,7 @@ public class CookieInterceptor extends HandlerInterceptorAdapter {
|
||||
if (modelAndView != null) {
|
||||
modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName()));
|
||||
}
|
||||
|
||||
super.postHandle(request, response, handler, modelAndView);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -18,7 +18,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author xuxueli 2015-12-12 18:09:04
|
||||
*/
|
||||
@Component
|
||||
public class PermissionInterceptor extends HandlerInterceptorAdapter {
|
||||
public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
@Resource
|
||||
private LoginService loginService;
|
||||
@ -27,7 +27,7 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return super.preHandle(request, response, handler);
|
||||
return true; // proceed with the next interceptor
|
||||
}
|
||||
|
||||
// if need login
|
||||
@ -43,8 +43,8 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
|
||||
if (needLogin) {
|
||||
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
||||
if (loginUser == null) {
|
||||
response.sendRedirect(request.getContextPath() + "/toLogin");
|
||||
//request.getRequestDispatcher("/toLogin").forward(request, response);
|
||||
response.setStatus(302);
|
||||
response.setHeader("location", request.getContextPath()+"/toLogin");
|
||||
return false;
|
||||
}
|
||||
if (needAdminuser && loginUser.getRole()!=1) {
|
||||
@ -53,7 +53,7 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
|
||||
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
|
||||
}
|
||||
|
||||
return super.preHandle(request, response, handler);
|
||||
return true; // proceed with the next interceptor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,10 +34,12 @@ public class WebExceptionResolver implements HandlerExceptionResolver {
|
||||
|
||||
// if json
|
||||
boolean isJson = false;
|
||||
HandlerMethod method = (HandlerMethod)handler;
|
||||
ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);
|
||||
if (responseBody != null) {
|
||||
isJson = true;
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod method = (HandlerMethod)handler;
|
||||
ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);
|
||||
if (responseBody != null) {
|
||||
isJson = true;
|
||||
}
|
||||
}
|
||||
|
||||
// error result
|
||||
|
||||
@ -66,7 +66,7 @@ public class EmailJobAlarm implements JobAlarm {
|
||||
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
|
||||
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailUserName(), personal);
|
||||
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom(), personal);
|
||||
helper.setTo(email);
|
||||
helper.setSubject(title);
|
||||
helper.setText(content, true);
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
package com.xxl.job.admin.core.complete;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.context.XxlJobContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2020-10-30 20:43:10
|
||||
*/
|
||||
public class XxlJobCompleter {
|
||||
private static Logger logger = LoggerFactory.getLogger(XxlJobCompleter.class);
|
||||
|
||||
/**
|
||||
* common fresh handle entrance (limit only once)
|
||||
*
|
||||
* @param xxlJobLog
|
||||
* @return
|
||||
*/
|
||||
public static int updateHandleInfoAndFinish(XxlJobLog xxlJobLog) {
|
||||
|
||||
// finish
|
||||
finishJob(xxlJobLog);
|
||||
|
||||
// text最大64kb 避免长度过长
|
||||
if (xxlJobLog.getHandleMsg().length() > 15000) {
|
||||
xxlJobLog.setHandleMsg( xxlJobLog.getHandleMsg().substring(0, 15000) );
|
||||
}
|
||||
|
||||
// fresh handle
|
||||
return XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateHandleInfo(xxlJobLog);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* do somethind to finish job
|
||||
*/
|
||||
private static void finishJob(XxlJobLog xxlJobLog){
|
||||
|
||||
// 1、handle success, to trigger child job
|
||||
String triggerChildMsg = null;
|
||||
if (XxlJobContext.HANDLE_CODE_SUCCESS == xxlJobLog.getHandleCode()) {
|
||||
XxlJobInfo xxlJobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(xxlJobLog.getJobId());
|
||||
if (xxlJobInfo!=null && xxlJobInfo.getChildJobId()!=null && xxlJobInfo.getChildJobId().trim().length()>0) {
|
||||
triggerChildMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_child_run") +"<<<<<<<<<<< </span><br>";
|
||||
|
||||
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
|
||||
for (int i = 0; i < childJobIds.length; i++) {
|
||||
int childJobId = (childJobIds[i]!=null && childJobIds[i].trim().length()>0 && isNumeric(childJobIds[i]))?Integer.valueOf(childJobIds[i]):-1;
|
||||
if (childJobId > 0) {
|
||||
|
||||
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
|
||||
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
|
||||
|
||||
// add msg
|
||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"),
|
||||
(i+1),
|
||||
childJobIds.length,
|
||||
childJobIds[i],
|
||||
(triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?I18nUtil.getString("system_success"):I18nUtil.getString("system_fail")),
|
||||
triggerChildResult.getMsg());
|
||||
} else {
|
||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"),
|
||||
(i+1),
|
||||
childJobIds.length,
|
||||
childJobIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerChildMsg != null) {
|
||||
xxlJobLog.setHandleMsg( xxlJobLog.getHandleMsg() + triggerChildMsg );
|
||||
}
|
||||
|
||||
// 2、fix_delay trigger next
|
||||
// on the way
|
||||
|
||||
}
|
||||
|
||||
private static boolean isNumeric(String str){
|
||||
try {
|
||||
int result = Integer.valueOf(str);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -55,8 +55,8 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
||||
@Value("${xxl.job.accessToken}")
|
||||
private String accessToken;
|
||||
|
||||
@Value("${spring.mail.username}")
|
||||
private String emailUserName;
|
||||
@Value("${spring.mail.from}")
|
||||
private String emailFrom;
|
||||
|
||||
@Value("${xxl.job.triggerpool.fast.max}")
|
||||
private int triggerPoolFastMax;
|
||||
@ -98,8 +98,8 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getEmailUserName() {
|
||||
return emailUserName;
|
||||
public String getEmailFrom() {
|
||||
return emailFrom;
|
||||
}
|
||||
|
||||
public int getTriggerPoolFastMax() {
|
||||
|
||||
@ -265,7 +265,7 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
*
|
||||
* @param cronExpression String representation of the cron expression the
|
||||
* new object should represent
|
||||
* @throws java.text.ParseException
|
||||
* @throws ParseException
|
||||
* if the string expression cannot be parsed into a valid
|
||||
* <CODE>CronExpression</CODE>
|
||||
*/
|
||||
@ -363,9 +363,8 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
// the second immediately following it.
|
||||
while (difference == 1000) {
|
||||
newDate = getTimeAfter(lastDate);
|
||||
if(newDate == null) {
|
||||
if(newDate == null)
|
||||
break;
|
||||
}
|
||||
|
||||
difference = newDate.getTime() - lastDate.getTime();
|
||||
|
||||
@ -533,7 +532,7 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
return i;
|
||||
}
|
||||
char c = s.charAt(i);
|
||||
if ((c >= 'A') && (c <= 'Z') && (!"L".equals(s)) && (!"LW".equals(s)) && (!s.matches("^L-[0-9]*[W]?"))) {
|
||||
if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) {
|
||||
String sub = s.substring(i, i + 3);
|
||||
int sval = -1;
|
||||
int eval = -1;
|
||||
@ -669,9 +668,8 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
if(c == '-') {
|
||||
ValueSet vs = getValue(0, s, i+1);
|
||||
lastdayOffset = vs.value;
|
||||
if(lastdayOffset > 30) {
|
||||
if(lastdayOffset > 30)
|
||||
throw new ParseException("Offset from last day must be <= 30", i+1);
|
||||
}
|
||||
i = vs.pos;
|
||||
}
|
||||
if(s.length() > i) {
|
||||
@ -734,9 +732,8 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
|
||||
if (c == 'L') {
|
||||
if (type == DAY_OF_WEEK) {
|
||||
if(val < 1 || val > 7) {
|
||||
if(val < 1 || val > 7)
|
||||
throw new ParseException("Day-of-Week values must be between 1 and 7", -1);
|
||||
}
|
||||
lastdayOfWeek = true;
|
||||
} else {
|
||||
throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i);
|
||||
@ -753,9 +750,8 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
} else {
|
||||
throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i);
|
||||
}
|
||||
if(val > 31) {
|
||||
throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i);
|
||||
}
|
||||
if(val > 31)
|
||||
throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i);
|
||||
TreeSet<Integer> set = getSet(type);
|
||||
set.add(val);
|
||||
i++;
|
||||
@ -1284,7 +1280,7 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));
|
||||
day -= lastdayOffset;
|
||||
|
||||
java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone());
|
||||
Calendar tcal = Calendar.getInstance(getTimeZone());
|
||||
tcal.set(Calendar.SECOND, 0);
|
||||
tcal.set(Calendar.MINUTE, 0);
|
||||
tcal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
@ -1320,7 +1316,7 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
t = day;
|
||||
day = daysOfMonth.first();
|
||||
|
||||
java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone());
|
||||
Calendar tcal = Calendar.getInstance(getTimeZone());
|
||||
tcal.set(Calendar.SECOND, 0);
|
||||
tcal.set(Calendar.MINUTE, 0);
|
||||
tcal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
@ -1584,9 +1580,9 @@ public final class CronExpression implements Serializable, Cloneable {
|
||||
* @param hour the hour to set
|
||||
*/
|
||||
protected void setCalendarHour(Calendar cal, int hour) {
|
||||
cal.set(java.util.Calendar.HOUR_OF_DAY, hour);
|
||||
if (cal.get(java.util.Calendar.HOUR_OF_DAY) != hour && hour != 24) {
|
||||
cal.set(java.util.Calendar.HOUR_OF_DAY, hour + 1);
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour);
|
||||
if (cal.get(Calendar.HOUR_OF_DAY) != hour && hour != 24) {
|
||||
cal.set(Calendar.HOUR_OF_DAY, hour + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -14,6 +15,7 @@ public class XxlJobGroup {
|
||||
private String title;
|
||||
private int addressType; // 执行器地址类型:0=自动注册、1=手动录入
|
||||
private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入)
|
||||
private Date updateTime;
|
||||
|
||||
// registry list
|
||||
private List<String> registryList; // 执行器地址列表(系统注册)
|
||||
@ -60,6 +62,14 @@ public class XxlJobGroup {
|
||||
return addressList;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public void setAddressList(String addressList) {
|
||||
this.addressList = addressList;
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ public class XxlJobInfo {
|
||||
private int id; // 主键ID
|
||||
|
||||
private int jobGroup; // 执行器主键ID
|
||||
private String jobCron; // 任务执行CRON表达式
|
||||
private String jobDesc;
|
||||
|
||||
private Date addTime;
|
||||
@ -21,6 +20,10 @@ public class XxlJobInfo {
|
||||
private String author; // 负责人
|
||||
private String alarmEmail; // 报警邮件
|
||||
|
||||
private String scheduleType; // 调度类型
|
||||
private String scheduleConf; // 调度配置,值含义取决于调度类型
|
||||
private String misfireStrategy; // 调度过期策略
|
||||
|
||||
private String executorRouteStrategy; // 执行器路由策略
|
||||
private String executorHandler; // 执行器,任务Handler名称
|
||||
private String executorParam; // 执行器,任务参数
|
||||
@ -56,14 +59,6 @@ public class XxlJobInfo {
|
||||
this.jobGroup = jobGroup;
|
||||
}
|
||||
|
||||
public String getJobCron() {
|
||||
return jobCron;
|
||||
}
|
||||
|
||||
public void setJobCron(String jobCron) {
|
||||
this.jobCron = jobCron;
|
||||
}
|
||||
|
||||
public String getJobDesc() {
|
||||
return jobDesc;
|
||||
}
|
||||
@ -104,6 +99,30 @@ public class XxlJobInfo {
|
||||
this.alarmEmail = alarmEmail;
|
||||
}
|
||||
|
||||
public String getScheduleType() {
|
||||
return scheduleType;
|
||||
}
|
||||
|
||||
public void setScheduleType(String scheduleType) {
|
||||
this.scheduleType = scheduleType;
|
||||
}
|
||||
|
||||
public String getScheduleConf() {
|
||||
return scheduleConf;
|
||||
}
|
||||
|
||||
public void setScheduleConf(String scheduleConf) {
|
||||
this.scheduleConf = scheduleConf;
|
||||
}
|
||||
|
||||
public String getMisfireStrategy() {
|
||||
return misfireStrategy;
|
||||
}
|
||||
|
||||
public void setMisfireStrategy(String misfireStrategy) {
|
||||
this.misfireStrategy = misfireStrategy;
|
||||
}
|
||||
|
||||
public String getExecutorRouteStrategy() {
|
||||
return executorRouteStrategy;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//package com.xxl.job.admin.core.jobbean;
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.jobbean;
|
||||
//
|
||||
//import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
//import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//package com.xxl.job.admin.core.schedule;
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.schedule;
|
||||
//
|
||||
//import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
//import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//package com.xxl.job.admin.core.quartz;
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.quartz;
|
||||
//
|
||||
//import org.quartz.SchedulerConfigException;
|
||||
//import org.quartz.spi.ThreadPool;
|
||||
|
||||
@ -8,14 +8,16 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteRound extends ExecutorRouter {
|
||||
|
||||
private static ConcurrentMap<Integer, Integer> routeCountEachJob = new ConcurrentHashMap<Integer, Integer>();
|
||||
private static ConcurrentMap<Integer, AtomicInteger> routeCountEachJob = new ConcurrentHashMap<>();
|
||||
private static long CACHE_VALID_TIME = 0;
|
||||
|
||||
private static int count(int jobId) {
|
||||
// cache clear
|
||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
||||
@ -23,11 +25,16 @@ public class ExecutorRouteRound extends ExecutorRouter {
|
||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;
|
||||
}
|
||||
|
||||
// count++
|
||||
Integer count = routeCountEachJob.get(jobId);
|
||||
count = (count==null || count>1000000)?(new Random().nextInt(100)):++count; // 初始化时主动Random一次,缓解首次压力
|
||||
AtomicInteger count = routeCountEachJob.get(jobId);
|
||||
if (count == null || count.get() > 1000000) {
|
||||
// 初始化时主动Random一次,缓解首次压力
|
||||
count = new AtomicInteger(new Random().nextInt(100));
|
||||
} else {
|
||||
// count++
|
||||
count.addAndGet(1);
|
||||
}
|
||||
routeCountEachJob.put(jobId, count);
|
||||
return count;
|
||||
return count.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user