mirror of https://github.com/jeecgboot/jeecg-boot
【版本合并】springboot3 sas升级到3.7.1
commit
fdb05443c2
|
@ -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
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
##### 版本号:
|
||||
|
||||
|
||||
##### 问题描述:
|
||||
|
||||
|
||||
|
||||
##### 错误截图:
|
||||
|
||||
|
||||
|
||||
|
||||
#### 友情提示:
|
||||
- 未按格式要求发帖、描述过于简抽象的,会被直接删掉;
|
||||
- 请确保问题描述清楚,方便我们理解并一次性调查解决问题;
|
||||
- 如果使用的不是master,请说明你使用的那个分支
|
||||
- 未按格式要求发帖、描述过于简单的,会被直接删掉;
|
||||
- 描述问题请图文并茂,方便我们理解并快速定位问题;
|
||||
- 如果使用的不是master,请说明你使用的分支;
|
23
LICENSE
23
LICENSE
|
@ -201,16 +201,13 @@
|
|||
limitations under the License.
|
||||
|
||||
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||
|
||||
开源协议补充
|
||||
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
|
||||
|
||||
1.允许基于本平台软件开展业务系统开发。
|
||||
2.JeecgBoot底层依赖的非开源功能:online lib依赖、仪表盘lib依赖等,统一采用LGPL开源协议(不二次改造、不拆分出jeecgboot之外使用,就不产生侵权)
|
||||
3.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
|
||||
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
|
||||
|
||||
总结:在遵循Apache开源协议和开源协议补充条款下,允许商用使用,不会造成侵权行为!
|
||||
解释权归:http://www.jeecg.com
|
||||
|
||||
|
||||
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。
|
||||
|
||||
开源协议中文释意如下:
|
||||
1.JeecgBoot开源版本无任何限制,在遵循本开源协议条款下,允许商用使用,不会造成侵权行为。
|
||||
2.允许基于本平台软件开展业务系统开发。
|
||||
3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件。
|
||||
|
||||
最终解释权归:http://www.jeecg.com
|
268
README-EN.md
268
README-EN.md
|
@ -7,13 +7,12 @@
|
|||
JEECG BOOT Low Code Development Platform
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.0(发布日期:2024-06-17)
|
||||
Current version: 3.7.1 (Release date: 2024-09-12)
|
||||
|
||||
|
||||
[](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)
|
||||
|
||||
|
||||
|
||||
|
@ -79,12 +72,14 @@ Technical documentation
|
|||
-----------------------------------
|
||||
|
||||
- Website: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- Doc: [http://help.jeecg.com](http://help.jeecg.com)
|
||||
- Newbie guide: [Quick start](http://www.jeecg.com/doc/quickstart) | [video](https://space.bilibili.com/454617261/channel/series) | [Q&A ](http://www.jeecg.com/doc/qa) | [help](http://jeecg.com/doc/help) | [1 minute experience](https://my.oschina.net/jeecg/blog/3083313)
|
||||
- Microservice Development: [Monomer upgrade to microservice](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
|
||||
- QQ group : ⑨808791225、⑧825232878、⑦791696430、⑥730954414(full)、683903138(full)、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
|
||||
- Demo : [OnlineDemo](http://boot3.jeecg.com) | [APP](http://jeecg.com/appIndex)
|
||||
> [please click obtain account password to obtain](http://jeecg.com/doc/demo)
|
||||
- Doc: [http://help.jeecg.com](http://help.jeecg.com)
|
||||
- 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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Star charts
|
||||
|
@ -180,7 +175,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 +185,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.8.1
|
||||
|
||||
- Security framework: Apache Shiro 1.10.0, Jwt 3.11.0
|
||||
- Security framework: Apache Shiro 1.12.0, Jwt 3.11.0
|
||||
|
||||
- Microservice technology stack: Spring Cloud Alibaba, Nacos, Gateway, Sentinel, Skywalking
|
||||
|
||||
|
@ -218,6 +213,12 @@ Technical Architecture:
|
|||
|
||||
- TechnologyStack:`Vue3.0+TypeScript+Vite+AntDesignVue+pinia+echarts`
|
||||
|
||||
#### Front-end environment requirements
|
||||
|
||||
* `Node.js 、npm 、pnpm`
|
||||
* Node.js Version suggestion: `v20.15.0`
|
||||
` ( Since Vite5 no longer supports EOL Node.js 14/16/17/19, Node.js 18/20 + is now required )`
|
||||
|
||||
#### Support library
|
||||
|
||||
| database | support |
|
||||
|
@ -227,44 +228,29 @@ Technical Architecture:
|
|||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| MariaDB | √ |
|
||||
| 达梦、人大金仓 | √ |
|
||||
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
| TiDB | √ |
|
||||
|
||||
|
||||
## 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 +259,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 +308,22 @@ Technical Architecture:
|
|||

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

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

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

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

|
||||
|
||||
|
|
325
README.md
325
README.md
|
@ -2,15 +2,14 @@
|
|||
JeecgBoot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.0(发布日期:2024-06-17)
|
||||
当前最新版本: 3.7.1(发布日期:2024-09-12)
|
||||
|
||||
|
||||
[](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,117 @@ 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)
|
||||
- 开发文档: [https://help.jeecg.com](https://help.jeecg.com)
|
||||
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
|
||||
- AI助手配置: https://help.jeecg.com/java/chatgpt.html
|
||||
|
||||
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- 在线演示 : [在线演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
|
||||
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
|
||||
>
|
||||
- QQ交流群 : ⑨808791225、⑧825232878、⑦791696430(满)、⑥730954414(满)、683903138(满)、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
- 开发文档: [https://help.jeecg.com](https://help.jeecg.com)
|
||||
- 反馈问题: [在Github上提Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
|
||||
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [入门视频](http://jeecg.com/doc/video)
|
||||
- QQ交流群 : ⑨808791225、其他(满)
|
||||
|
||||
|
||||
|
||||
|
||||
启动项目
|
||||
-----------------------------------
|
||||
|
||||
- [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.8.1
|
||||
- 安全框架: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+Vite5+Ant-Design-Vue等新技术方案,包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能
|
||||
- 最新技术栈:Vue3.0 + TypeScript + Vite5 + ant-design-vue4 + pinia + echarts + unocss + vxe-table + qiankun + es6
|
||||
- 依赖管理:node、npm、pnpm
|
||||
|
||||
|
||||
#### 前端环境要求
|
||||
|
||||
* 本地环境安装 `Node.js 、npm 、pnpm`
|
||||
* Node.js 版本建议`v20.15.0`,要求`Node 20+` 版本以上
|
||||
|
||||
` ( 因为Vite5 不再支持已 EOL 的 Node.js 14 / 16 / 17 / 19,现在需要 Node.js 18 / 20+ )`
|
||||
|
||||
|
||||
#### 支持库
|
||||
|
||||
| 数据库 | 支持 |
|
||||
| --- | --- |
|
||||
| MySQL | √ |
|
||||
| Oracle11g | √ |
|
||||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| MariaDB | √ |
|
||||
| MariaDB | √ |
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
| TiDB | √ |
|
||||
|
||||
|
||||
## 微服务解决方案
|
||||
|
||||
|
||||
- 1、服务注册和发现 Nacos √
|
||||
- 2、统一配置中心 Nacos √
|
||||
- 3、路由网关 gateway(三种加载方式) √
|
||||
- 4、分布式 http feign √
|
||||
- 5、熔断降级限流 Sentinel √
|
||||
- 6、分布式文件 Minio、阿里OSS √
|
||||
- 7、统一权限控制 JWT + Shiro √
|
||||
- 8、服务监控 SpringBootAdmin√
|
||||
- 9、链路跟踪 Skywalking [参考文档](https://help.jeecg.com/java/springcloud/super/skywarking.html)
|
||||
- 10、消息中间件 RabbitMQ √
|
||||
- 11、分布式任务 xxl-job √
|
||||
- 12、分布式事务 Seata
|
||||
- 13、轻量分布式日志 Loki+grafana套件
|
||||
- 14、支持 docker-compose、k8s、jenkins
|
||||
- 15、CAS 单点登录 √
|
||||
- 16、路由限流 √
|
||||
|
||||
|
||||
#### 微服务方式启动
|
||||
|
||||
- [单体快速切换微服务](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 +168,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 +191,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 +200,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 +354,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 +379,20 @@ Docker启动项目
|
|||
|
||||
|
||||
##### 仪表盘设计器
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

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

|
||||
|
||||
|
@ -521,11 +475,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">
|
||||

|
|
@ -0,0 +1,135 @@
|
|||
version: '2'
|
||||
services:
|
||||
jeecg-boot-mysql:
|
||||
build:
|
||||
context: ./jeecg-boot/db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
TZ: Asia/Shanghai
|
||||
restart: always
|
||||
container_name: jeecg-boot-mysql
|
||||
image: jeecg-boot-mysql
|
||||
command:
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_general_ci
|
||||
--explicit_defaults_for_timestamp=true
|
||||
--lower_case_table_names=1
|
||||
--max_allowed_packet=128M
|
||||
--default-authentication-plugin=caching_sha2_password
|
||||
ports:
|
||||
- 3306:3306
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-redis:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
hostname: jeecg-boot-redis
|
||||
container_name: jeecg-boot-redis
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-nacos:
|
||||
restart: always
|
||||
build:
|
||||
context: ./jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos
|
||||
ports:
|
||||
- 8848:8848
|
||||
container_name: jeecg-boot-nacos
|
||||
depends_on:
|
||||
- jeecg-boot-mysql
|
||||
hostname: jeecg-boot-nacos
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-system:
|
||||
depends_on:
|
||||
- jeecg-boot-nacos
|
||||
build:
|
||||
context: ./jeecg-boot/jeecg-server-cloud/jeecg-system-cloud-start
|
||||
container_name: jeecg-system-start
|
||||
hostname: jeecg-boot-system
|
||||
restart: on-failure
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-demo:
|
||||
depends_on:
|
||||
- jeecg-boot-nacos
|
||||
build:
|
||||
context: ./jeecg-boot/jeecg-server-cloud/jeecg-demo-cloud-start
|
||||
container_name: jeecg-demo-start
|
||||
hostname: jeecg-boot-demo
|
||||
restart: on-failure
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-gateway:
|
||||
restart: on-failure
|
||||
build:
|
||||
context: ./jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway
|
||||
ports:
|
||||
- 9999:9999
|
||||
depends_on:
|
||||
- jeecg-boot-nacos
|
||||
- jeecg-boot-system
|
||||
container_name: jeecg-boot-gateway
|
||||
hostname: jeecg-boot-gateway
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
# jeecg-boot-rabbitmq:
|
||||
# image: rabbitmq:3.7.7-management
|
||||
# ports:
|
||||
# - 5672:5672
|
||||
# - 15672:15672
|
||||
# restart: always
|
||||
# container_name: jeecg-boot-rabbitmq
|
||||
# hostname: jeecg-boot-rabbitmq
|
||||
# environment:
|
||||
# RABBITMQ_DEFAULT_USER: guest
|
||||
# RABBITMQ_DEFAULT_PASS: guest
|
||||
# jeecg-boot-sentinel:
|
||||
# restart: on-failure
|
||||
# build:
|
||||
# context: ./jeecg-visual/jeecg-cloud-sentinel
|
||||
# ports:
|
||||
# - 9000:9000
|
||||
# depends_on:
|
||||
# - jeecg-boot-nacos
|
||||
# - jeecg-boot-demo
|
||||
# - jeecg-boot-system
|
||||
# - jeecg-boot-gateway
|
||||
# container_name: jeecg-boot-sentinel
|
||||
# hostname: jeecg-boot-sentinel
|
||||
#
|
||||
# jeecg-boot-xxljob:
|
||||
# build:
|
||||
# context: ./jeecg-visual/jeecg-cloud-xxljob
|
||||
# ports:
|
||||
# - 9080:9080
|
||||
# container_name: jeecg-boot-xxljob
|
||||
# hostname: jeecg-boot-xxljob
|
||||
|
||||
jeecg-vue:
|
||||
build:
|
||||
context: ./jeecgboot-vue3
|
||||
container_name: jeecgboot-vue3-nginx
|
||||
image: jeecgboot-vue3
|
||||
depends_on:
|
||||
- jeecg-boot-system
|
||||
networks:
|
||||
- jeecg-boot
|
||||
ports:
|
||||
- 80:80
|
||||
|
||||
networks:
|
||||
jeecg-boot:
|
||||
name: jeecg_boot
|
|
@ -2,13 +2,14 @@ version: '2'
|
|||
services:
|
||||
jeecg-boot-mysql:
|
||||
build:
|
||||
context: ../db
|
||||
context: ./jeecg-boot/db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_ROOT_HOST: '%'
|
||||
TZ: Asia/Shanghai
|
||||
restart: always
|
||||
container_name: jeecg-boot-mysql
|
||||
image: jeecg-boot-mysql
|
||||
command:
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_general_ci
|
||||
|
@ -22,28 +23,41 @@ services:
|
|||
- jeecg-boot
|
||||
|
||||
jeecg-boot-redis:
|
||||
image: redis:5.0
|
||||
image: registry.cn-hangzhou.aliyuncs.com/jeecgdocker/redis:5.0
|
||||
ports:
|
||||
- 6379:6379
|
||||
restart: always
|
||||
container_name: jeecg-boot-redis
|
||||
hostname: jeecg-boot-redis
|
||||
container_name: jeecg-boot-redis
|
||||
networks:
|
||||
- jeecg-boot
|
||||
|
||||
jeecg-boot-system:
|
||||
build:
|
||||
context: ./jeecg-boot/jeecg-module-system/jeecg-system-start
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- jeecg-boot-mysql
|
||||
- jeecg-boot-redis
|
||||
container_name: jeecg-boot-system
|
||||
image: jeecg-boot-system
|
||||
hostname: jeecg-boot-system
|
||||
ports:
|
||||
- 8080:8080
|
||||
networks:
|
||||
- jeecg-boot
|
||||
jeecg-vue:
|
||||
build:
|
||||
context: ./jeecgboot-vue3
|
||||
container_name: jeecgboot-vue3-nginx
|
||||
image: jeecgboot-vue3
|
||||
depends_on:
|
||||
- jeecg-boot-system
|
||||
networks:
|
||||
- jeecg-boot
|
||||
ports:
|
||||
- 80:80
|
||||
|
||||
networks:
|
||||
jeecg-boot:
|
||||
name: jeecg_boot
|
||||
|
||||
# jeecg-boot-rabbitmq:
|
||||
# image: rabbitmq:3.7.7-management
|
||||
# ports:
|
||||
# - 5672:5672
|
||||
# - 15672:15672
|
||||
# restart: always
|
||||
# container_name: jeecg-boot-rabbitmq
|
||||
# hostname: jeecg-boot-rabbitmq
|
||||
# environment:
|
||||
# RABBITMQ_DEFAULT_USER: guest
|
||||
# RABBITMQ_DEFAULT_PASS: guest
|
|
@ -201,16 +201,13 @@
|
|||
limitations under the License.
|
||||
|
||||
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||
|
||||
开源协议补充
|
||||
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
|
||||
|
||||
1.允许基于本平台软件开展业务系统开发。
|
||||
2.JeecgBoot底层依赖的非开源功能:online lib依赖、仪表盘lib依赖等,统一采用LGPL开源协议(不二次改造、不拆分出jeecgboot之外使用,就不产生侵权)
|
||||
3.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
|
||||
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
|
||||
|
||||
总结:在遵循Apache开源协议和开源协议补充条款下,允许商用使用,不会造成侵权行为!
|
||||
解释权归:http://www.jeecg.com
|
||||
|
||||
|
||||
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和开源协议 双重保护许可。
|
||||
|
||||
开源协议中文释意如下:
|
||||
1.JeecgBoot开源版本无任何限制,在遵循本开源协议条款下,允许商用使用,不会造成侵权行为。
|
||||
2.允许基于本平台软件开展业务系统开发。
|
||||
3.在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件。
|
||||
|
||||
最终解释权归:http://www.jeecg.com
|
|
@ -0,0 +1,165 @@
|
|||
|
||||
JeecgBoot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 3.7.1(发布日期:2024-09-12)
|
||||
|
||||
|
||||
[](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.8.1
|
||||
- 安全框架: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 | √ |
|
||||
| 达梦 | √ |
|
||||
| 人大金仓 | √ |
|
||||
| TiDB | √ |
|
||||
|
||||
|
||||
|
||||
|
||||
## 微服务解决方案
|
||||
|
||||
|
||||
- 1、服务注册和发现 Nacos √
|
||||
- 2、统一配置中心 Nacos √
|
||||
- 3、路由网关 gateway(三种加载方式) √
|
||||
- 4、分布式 http feign √
|
||||
- 5、熔断降级限流 Sentinel √
|
||||
- 6、分布式文件 Minio、阿里OSS √
|
||||
- 7、统一权限控制 JWT + Shiro √
|
||||
- 8、服务监控 SpringBootAdmin√
|
||||
- 9、链路跟踪 Skywalking [参考文档](https://help.jeecg.com/java/springcloud/super/skywarking.html)
|
||||
- 10、消息中间件 RabbitMQ √
|
||||
- 11、分布式任务 xxl-job √
|
||||
- 12、分布式事务 Seata
|
||||
- 13、轻量分布式日志 Loki+grafana套件
|
||||
- 14、支持 docker-compose、k8s、jenkins
|
||||
- 15、CAS 单点登录 √
|
||||
- 16、路由限流 √
|
||||
|
||||
|
||||
|
||||
后台目录结构
|
||||
-----------------------------------
|
||||
```
|
||||
项目结构
|
||||
├─jeecg-boot-parent(父POM: 项目依赖、modules组织)
|
||||
│ ├─jeecg-boot-base-core(共通模块: 工具类、config、权限、查询过滤器、注解等)
|
||||
│ ├─jeecg-module-demo 示例代码
|
||||
│ ├─jeecg-module-system System系统管理目录
|
||||
│ │ ├─jeecg-system-biz System系统管理权限等功能
|
||||
│ │ ├─jeecg-system-start System单体启动项目(8080)
|
||||
│ │ ├─jeecg-system-api System系统管理模块对外api
|
||||
│ │ │ ├─jeecg-system-cloud-api System模块对外提供的微服务接口
|
||||
│ │ │ ├─jeecg-system-local-api System模块对外提供的单体接口
|
||||
│ ├─jeecg-server-cloud --微服务模块
|
||||
├─jeecg-cloud-gateway --微服务网关模块(9999)
|
||||
├─jeecg-cloud-nacos --Nacos服务模块(8848)
|
||||
├─jeecg-system-cloud-start --System微服务启动项目(7001)
|
||||
├─jeecg-demo-cloud-start --Demo微服务启动项目(7002)
|
||||
├─jeecg-visual
|
||||
├─jeecg-cloud-monitor --微服务监控模块 (9111)
|
||||
├─jeecg-cloud-xxljob --微服务xxljob定时任务服务端 (9080)
|
||||
├─jeecg-cloud-sentinel --sentinel服务端 (9000)
|
||||
├─jeecg-cloud-test -- 微服务测试示例(各种例子)
|
||||
├─jeecg-cloud-test-more -- 微服务测试示例(feign、熔断降级、xxljob、分布式锁)
|
||||
├─jeecg-cloud-test-rabbitmq -- 微服务测试示例(rabbitmq)
|
||||
├─jeecg-cloud-test-seata -- 微服务测试示例(seata分布式事务)
|
||||
├─jeecg-cloud-test-shardingsphere -- 微服务测试示例(分库分表)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
#### 微服务架构图
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
FROM mysql:8.0.19
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/jeecgdocker/mysql:8.0.19
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
|
@ -163,7 +163,7 @@
|
|||
<dependency>
|
||||
<groupId>org.jeecgframework</groupId>
|
||||
<artifactId>kingbase8</artifactId>
|
||||
<version>${kingbase8.version}</version>
|
||||
<version>9.0.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!--达梦数据库驱动 版本号1-3-26-2023.07.26-197096-20046-ENT -->
|
||||
|
|
|
@ -144,7 +144,9 @@ public interface CommonConstant {
|
|||
*/
|
||||
String STATUS_0 = "0";
|
||||
String STATUS_1 = "1";
|
||||
|
||||
Integer STATUS_0_INT = 0;
|
||||
Integer STATUS_1_INT = 1;
|
||||
|
||||
/**
|
||||
* 同步工作流引擎1同步0不同步
|
||||
*/
|
||||
|
@ -475,6 +477,11 @@ public interface CommonConstant {
|
|||
*/
|
||||
String FILE_EDITABLE = "editable";
|
||||
|
||||
/**
|
||||
* 文件 只读
|
||||
*/
|
||||
String FILE_READONLY = "readonly";
|
||||
|
||||
/**
|
||||
* 登录失败,用于记录失败次数的key
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.jeecg.common.constant;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
@ -22,26 +23,30 @@ public class ProvinceCityArea {
|
|||
List<Area> areaList;
|
||||
|
||||
public String getText(String code){
|
||||
this.initAreaList();
|
||||
if(this.areaList!=null || this.areaList.size()>0){
|
||||
List<String> ls = new ArrayList<String>();
|
||||
getAreaByCode(code,ls);
|
||||
return String.join("/",ls);
|
||||
if(StringUtils.isNotBlank(code)){
|
||||
this.initAreaList();
|
||||
if(this.areaList!=null || this.areaList.size()>0){
|
||||
List<String> ls = new ArrayList<String>();
|
||||
getAreaByCode(code,ls);
|
||||
return String.join("/",ls);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getCode(String text){
|
||||
this.initAreaList();
|
||||
if(areaList!=null && areaList.size()>0){
|
||||
for(int i=areaList.size()-1;i>=0;i--){
|
||||
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||
String areaText = areaList.get(i).getText();
|
||||
String cityText = areaList.get(i).getAheadText();
|
||||
if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){
|
||||
return areaList.get(i).getId();
|
||||
if(StringUtils.isNotBlank(text)){
|
||||
this.initAreaList();
|
||||
if(areaList!=null && areaList.size()>0){
|
||||
for(int i=areaList.size()-1;i>=0;i--){
|
||||
//update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||
String areaText = areaList.get(i).getText();
|
||||
String cityText = areaList.get(i).getAheadText();
|
||||
if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){
|
||||
return areaList.get(i).getId();
|
||||
}
|
||||
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||
}
|
||||
//update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -122,7 +122,7 @@ public class JeecgBootExceptionHandler {
|
|||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public Result<?> handleAuthorizationException(AccessDeniedException e){
|
||||
log.error(e.getMessage(), e);
|
||||
return Result.noauth("没有权限,请联系管理员授权,后刷新缓存!");
|
||||
return Result.noauth("没有权限,请联系管理员分配权限!");
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
|
|
|
@ -746,7 +746,11 @@ public class QueryGenerator {
|
|||
private static boolean judgedIsUselessField(String name) {
|
||||
return "class".equals(name) || "ids".equals(name)
|
||||
|| "page".equals(name) || "rows".equals(name)
|
||||
|| "sort".equals(name) || "order".equals(name);
|
||||
//// update-begin--author:sunjianlei date:20240808 for:【TV360X-2009】取消过滤 sort、order 字段,防止前端排序报错 ------
|
||||
//// https://github.com/jeecgboot/JeecgBoot/issues/6937
|
||||
// || "sort".equals(name) || "order".equals(name)
|
||||
//// update-end----author:sunjianlei date:20240808 for:【TV360X-2009】取消过滤 sort、order 字段,防止前端排序报错 ------
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
@ -834,6 +838,9 @@ public class QueryGenerator {
|
|||
public static String getSqlRuleValue(String sqlRule){
|
||||
try {
|
||||
Set<String> varParams = getSqlRuleParams(sqlRule);
|
||||
if (varParams == null || varParams.isEmpty()) {
|
||||
return sqlRule;
|
||||
}
|
||||
for(String var:varParams){
|
||||
String tempValue = converRuleValue(var);
|
||||
sqlRule = sqlRule.replace("#{"+var+"}",tempValue);
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* @program: file
|
||||
* @description: 文件下载
|
||||
* @author: chenrui
|
||||
* @date: 2019-05-24 16:34
|
||||
**/
|
||||
@Slf4j
|
||||
public class FileDownloadUtils {
|
||||
|
||||
/**
|
||||
* 单文件下载
|
||||
*
|
||||
* @param response
|
||||
* @param storePath 下载文件储存地址
|
||||
* @param fileName 文件名称
|
||||
* @author: chenrui
|
||||
* @date: 2019/5/24 17:10
|
||||
*/
|
||||
public static void downloadFile(HttpServletResponse response, String storePath, String fileName) {
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
File file = new File(storePath);
|
||||
if (!file.exists()) {
|
||||
throw new NullPointerException("Specified file not found");
|
||||
}
|
||||
if (fileName == null || fileName.isEmpty()) {
|
||||
throw new NullPointerException("The file name can not null");
|
||||
}
|
||||
// 配置文件下载
|
||||
response.setHeader("content-type", "application/octet-stream");
|
||||
response.setContentType("application/octet-stream");
|
||||
// 下载文件能正常显示中文
|
||||
try {
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
// 实现文件下载
|
||||
byte[] buffer = new byte[1024];
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);) {
|
||||
OutputStream os = response.getOutputStream();
|
||||
int i = bis.read(buffer);
|
||||
while (i != -1) {
|
||||
os.write(buffer, 0, i);
|
||||
i = bis.read(buffer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 多文件下载
|
||||
*
|
||||
* @param filesPath 下载文件集合
|
||||
* @param zipFileName 多文件合称名
|
||||
* @author: chenrui
|
||||
* @date: 2019/5/24 17:48
|
||||
*/
|
||||
public static void downloadFileMulti(HttpServletResponse response, List<String> filesPath, String zipFileName) throws IOException {
|
||||
//设置压缩包的名字
|
||||
String downloadName = zipFileName + ".zip";
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("content-type", "application/octet-stream");
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downloadName, "UTF-8"));
|
||||
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||
|
||||
log.info("开始压缩文件:" + filesPath);
|
||||
//设置压缩流:直接写入response,实现边压缩边下载
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
|
||||
DataOutputStream os = new DataOutputStream(zipOut);) {
|
||||
//设置压缩方法
|
||||
zipOut.setMethod(ZipOutputStream.DEFLATED);
|
||||
for (String filePath : filesPath) {
|
||||
//循环将文件写入压缩流
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
//添加ZipEntry,并ZipEntry中写入文件流也就是将文件压入zip文件的目录下
|
||||
String fileName = file.getName();
|
||||
zipOut.putNextEntry(new ZipEntry(fileName));
|
||||
//格式输出流文件
|
||||
|
||||
InputStream is = Files.newInputStream(file.toPath());
|
||||
byte[] b = new byte[1024];
|
||||
int length;
|
||||
while ((length = is.read(b)) != -1) {
|
||||
os.write(b, 0, length);
|
||||
}
|
||||
is.close();
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new JeecgBootException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载网络资源到磁盘
|
||||
*
|
||||
* @param fileUrl
|
||||
* @param storePath
|
||||
* @author chenrui
|
||||
* @date 2024/1/19 10:09
|
||||
*/
|
||||
public static String download2DiskFromNet(String fileUrl, String storePath) {
|
||||
try {
|
||||
URL url = new URL(fileUrl);
|
||||
URLConnection conn = url.openConnection();
|
||||
// 设置超时间为3秒
|
||||
conn.setConnectTimeout(3 * 1000);
|
||||
// 防止屏蔽程序
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
|
||||
// 确保目录存在
|
||||
File file = ensureDestFileDir(storePath);
|
||||
try (InputStream inStream = conn.getInputStream();
|
||||
FileOutputStream fs = new FileOutputStream(file);) {
|
||||
int byteread;
|
||||
byte[] buffer = new byte[1204];
|
||||
while ((byteread = inStream.read(buffer)) != -1) {
|
||||
fs.write(buffer, 0, byteread);
|
||||
}
|
||||
return storePath;
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new JeecgBootException(e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new JeecgBootException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取不重名的文件
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2017年5月24日下午6:29:13
|
||||
* @version v0.0.1
|
||||
*/
|
||||
public static File getUniqueFile(final File file) {
|
||||
if (!file.exists()) {
|
||||
return file;
|
||||
}
|
||||
|
||||
File tmpFile = new File(file.getAbsolutePath());
|
||||
File parentDir = tmpFile.getParentFile();
|
||||
int count = 1;
|
||||
String extension = FilenameUtils.getExtension(tmpFile.getName());
|
||||
String baseName = FilenameUtils.getBaseName(tmpFile.getName());
|
||||
do {
|
||||
tmpFile = new File(parentDir, baseName + "(" + count++ + ")." + extension);
|
||||
} while (tmpFile.exists());
|
||||
return tmpFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保输出文件目录
|
||||
*
|
||||
* @param destFilePath
|
||||
* @return
|
||||
* @author: chenrui
|
||||
* @date: 2019-05-21 16:49
|
||||
*/
|
||||
private static File ensureDestFileDir(String destFilePath) {
|
||||
File destFile = new File(destFilePath);
|
||||
FileDownloadUtils.checkDirAndCreate(destFile.getParentFile());
|
||||
return destFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证文件夹存在且创建目录
|
||||
*
|
||||
* @param dir
|
||||
* @author chenrui
|
||||
* @date 2017年5月24日下午6:29:24
|
||||
* @version v0.0.1
|
||||
*/
|
||||
public static void checkDirAndCreate(File dir) {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.pegdown.PegDownProcessor;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
/**
|
||||
|
@ -36,8 +38,14 @@ public class HTMLUtils {
|
|||
* @return
|
||||
*/
|
||||
public static String parseMarkdown(String markdownContent) {
|
||||
PegDownProcessor pdp = new PegDownProcessor();
|
||||
return pdp.markdownToHtml(markdownContent);
|
||||
//update-begin---author:wangshuai---date:2024-06-26---for:【TV360X-1344】JDK17 邮箱发送失败,需要换写法---
|
||||
/*PegDownProcessor pdp = new PegDownProcessor();
|
||||
return pdp.markdownToHtml(markdownContent);*/
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(markdownContent);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
return renderer.render(document);
|
||||
//update-end---author:wangshuai---date:2024-06-26---for:【TV360X-1344】JDK17 邮箱发送失败,需要换写法---
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,8 +58,12 @@ public class JeecgBaseConfig {
|
|||
* @return
|
||||
*/
|
||||
private WeiXinPay weiXinPay;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 百度开放API配置
|
||||
*/
|
||||
private BaiduApi baiduApi;
|
||||
|
||||
public Elasticsearch getElasticsearch() {
|
||||
return elasticsearch;
|
||||
}
|
||||
|
@ -131,5 +135,13 @@ public class JeecgBaseConfig {
|
|||
public void setWeiXinPay(WeiXinPay weiXinPay) {
|
||||
this.weiXinPay = weiXinPay;
|
||||
}
|
||||
|
||||
|
||||
public BaiduApi getBaiduApi() {
|
||||
return baiduApi;
|
||||
}
|
||||
|
||||
public void setBaiduApi(BaiduApi baiduApi) {
|
||||
this.baiduApi = baiduApi;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//package org.jeecg.config;
|
||||
//
|
||||
// 已使用swagger3config平替
|
||||
//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
//
|
||||
//import io.swagger.annotations.ApiOperation;
|
||||
//import org.jeecg.common.constant.CommonConstant;
|
||||
//import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
//import org.springframework.beans.BeansException;
|
||||
//import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
|
@ -19,15 +19,13 @@
|
|||
//import springfox.documentation.builders.ParameterBuilder;
|
||||
//import springfox.documentation.builders.PathSelectors;
|
||||
//import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
//import springfox.documentation.oas.annotations.EnableOpenApi;
|
||||
//import springfox.documentation.schema.ModelRef;
|
||||
//import springfox.documentation.service.*;
|
||||
//import springfox.documentation.spi.DocumentationType;
|
||||
//import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
//import springfox.documentation.spring.web.plugins.Docket;
|
||||
//import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
|
||||
//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
||||
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
//import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||
//
|
||||
//import java.lang.reflect.Field;
|
||||
//import java.util.ArrayList;
|
||||
|
@ -39,8 +37,7 @@
|
|||
// * @Author scott
|
||||
// */
|
||||
//@Configuration
|
||||
//@EnableSwagger2 //开启 Swagger2
|
||||
//@EnableKnife4j //开启 knife4j,可以不写
|
||||
//@EnableSwagger2WebMvc
|
||||
//@Import(BeanValidatorPluginsConfiguration.class)
|
||||
//public class Swagger2Config implements WebMvcConfigurer {
|
||||
//
|
||||
|
@ -98,6 +95,14 @@
|
|||
// List<Parameter> pars = new ArrayList<>();
|
||||
// tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
|
||||
// pars.add(tokenPar.build());
|
||||
// //update-begin-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id
|
||||
// if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
// ParameterBuilder tenantPar = new ParameterBuilder();
|
||||
// tenantPar.name(CommonConstant.TENANT_ID).description("租户ID").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
|
||||
// pars.add(tenantPar.build());
|
||||
// }
|
||||
// //update-end-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id
|
||||
//
|
||||
// return pars;
|
||||
// }
|
||||
//
|
||||
|
@ -152,7 +157,7 @@
|
|||
//
|
||||
// @Override
|
||||
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
|
||||
// if (bean instanceof WebMvcRequestHandlerProvider) {
|
||||
// customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
|
||||
// }
|
||||
// return bean;
|
||||
|
|
|
@ -40,7 +40,6 @@ import java.time.LocalDateTime;
|
|||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Spring Boot 2.0 解决跨域问题
|
||||
|
@ -59,11 +58,6 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
|||
@Autowired(required = false)
|
||||
private PrometheusMeterRegistry prometheusMeterRegistry;
|
||||
|
||||
@Autowired
|
||||
private ObjectProvider<Jackson2ObjectMapperBuilder> builderProvider;
|
||||
@Autowired
|
||||
private JacksonProperties jacksonProperties;
|
||||
|
||||
/**
|
||||
* 静态资源的配置 - 使得可以从磁盘中读取 Html、图片、视频、音频等
|
||||
*/
|
||||
|
@ -116,10 +110,6 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
|||
@Primary
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 继承spring jackson 默认机制
|
||||
if (Objects.nonNull(builderProvider.getIfAvailable())) {
|
||||
objectMapper = builderProvider.getIfAvailable().createXmlMapper(false).build();
|
||||
}
|
||||
//处理bigDecimal
|
||||
objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
|
||||
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
|
||||
|
@ -128,10 +118,8 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
|||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, false);
|
||||
//默认的处理日期时间格式,接受通过spring.jackson.date-format配置格式化模式
|
||||
if (Objects.isNull(jacksonProperties.getDateFormat())) {
|
||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
//默认的处理日期时间格式
|
||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
|
@ -143,17 +131,16 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
|||
return objectMapper;
|
||||
}
|
||||
|
||||
//update-begin---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
// /**
|
||||
// * SpringBootAdmin的Httptrace不见了
|
||||
// * https://blog.csdn.net/u013810234/article/details/110097201
|
||||
// */
|
||||
// @Bean
|
||||
// public InMemoryHttpExchangeRepository getInMemoryHttpTrace(){
|
||||
// InMemoryHttpExchangeRepository repository = new InMemoryHttpExchangeRepository();
|
||||
// // 默认保存1000条http请求记录
|
||||
// repository.setCapacity(1000);
|
||||
// return repository;
|
||||
// public InMemoryHttpTraceRepository getInMemoryHttpTrace(){
|
||||
// return new InMemoryHttpTraceRepository();
|
||||
// }
|
||||
//update-end---author:chenrui ---date:20240514 for:[QQYUN-9247]系统监控功能优化------------
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,21 +3,16 @@ package org.jeecg.config.shiro.ignore;
|
|||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.config.shiro.IgnoreAuth;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 在spring boot初始化时,根据@RestController注解获取当前spring容器中的bean
|
||||
|
@ -27,32 +22,25 @@ import java.util.*;
|
|||
@Slf4j
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
|
||||
public class IgnoreAuthPostProcessor implements InitializingBean {
|
||||
|
||||
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
List<String> ignoreAuthUrls = new ArrayList<>();
|
||||
if (event.getApplicationContext().getParent() == null) {
|
||||
// 只处理根应用上下文的事件,避免在子上下文中重复处理
|
||||
Map<String, Object> restControllers = applicationContext.getBeansWithAnnotation(RestController.class);
|
||||
for (Object restController : restControllers.values()) {
|
||||
// 如 online系统的controller并不是spring 默认生成
|
||||
if (restController instanceof Advised) {
|
||||
ignoreAuthUrls.addAll(postProcessRestController(restController));
|
||||
}
|
||||
}
|
||||
Set<Class<?>> restControllers = requestMappingHandlerMapping.getHandlerMethods().values().stream().map(HandlerMethod::getBeanType).collect(Collectors.toSet());
|
||||
for (Class<?> restController : restControllers) {
|
||||
ignoreAuthUrls.addAll(postProcessRestController(restController));
|
||||
}
|
||||
|
||||
log.info("Init Token ignoreAuthUrls Config [ 集合 ] :{}", ignoreAuthUrls);
|
||||
if (!CollectionUtils.isEmpty(ignoreAuthUrls)) {
|
||||
InMemoryIgnoreAuth.set(ignoreAuthUrls);
|
||||
|
||||
// 添加免登录url
|
||||
addIgnoreUrl(ignoreAuthUrls);
|
||||
}
|
||||
|
||||
// 计算方法的耗时
|
||||
|
@ -61,9 +49,8 @@ public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefre
|
|||
log.info("Init Token ignoreAuthUrls Config [ 耗时 ] :" + elapsedTime + "毫秒");
|
||||
}
|
||||
|
||||
private List<String> postProcessRestController(Object restController) {
|
||||
private List<String> postProcessRestController(Class<?> clazz) {
|
||||
List<String> ignoreAuthUrls = new ArrayList<>();
|
||||
Class<?> clazz = ((Advised) restController).getTargetClass();
|
||||
RequestMapping base = clazz.getAnnotation(RequestMapping.class);
|
||||
String[] baseUrl = Objects.nonNull(base) ? base.value() : new String[]{};
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
|
@ -118,28 +105,4 @@ public class IgnoreAuthPostProcessor implements ApplicationListener<ContextRefre
|
|||
private String prefix(String seg) {
|
||||
return seg.startsWith("/") ? seg : "/"+seg;
|
||||
}
|
||||
|
||||
private void addIgnoreUrl(List<String> urls){
|
||||
FilterChainProxy obj = applicationContext.getBean(FilterChainProxy.class);
|
||||
if (Objects.isNull(obj)) {
|
||||
return;
|
||||
}
|
||||
List<SecurityFilterChain> filterChains = (List<SecurityFilterChain>) getProperty(obj,"filterChains");
|
||||
|
||||
if (!CollectionUtils.isEmpty(filterChains)) {
|
||||
for (String url : urls) {
|
||||
filterChains.add(0, new DefaultSecurityFilterChain(new AntPathRequestMatcher(url, null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object getProperty(Object obj, String fieldName) {
|
||||
try {
|
||||
Field field = obj.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(obj);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.jeecg.config.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 百度开放api配置
|
||||
*/
|
||||
@Data
|
||||
public class BaiduApi {
|
||||
|
||||
private String appId;
|
||||
private String apiKey;
|
||||
private String secretKey;
|
||||
|
||||
}
|
|
@ -11,6 +11,10 @@ public class Firewall {
|
|||
* 数据源安全 (开启后,Online报表和图表的数据源为必填)
|
||||
*/
|
||||
private Boolean dataSourceSafe = false;
|
||||
/**
|
||||
* 是否禁止使用 * 查询所有字段
|
||||
*/
|
||||
private Boolean disableSelectAll = false;
|
||||
/**
|
||||
* 低代码模式(dev:开发模式,prod:发布模式——关闭所有在线开发配置能力)
|
||||
*/
|
||||
|
@ -36,4 +40,11 @@ public class Firewall {
|
|||
this.lowCodeMode = lowCodeMode;
|
||||
}
|
||||
|
||||
public Boolean getDisableSelectAll() {
|
||||
return disableSelectAll;
|
||||
}
|
||||
|
||||
public void setDisableSelectAll(Boolean disableSelectAll) {
|
||||
this.disableSelectAll = disableSelectAll;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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助手------------
|
||||
|
|
|
@ -95,7 +95,7 @@ public class JeecgOrderMainServiceImpl extends ServiceImpl<JeecgOrderMainMapper,
|
|||
// 当传过来的id数据库不存在时,说明数据库没有,走新增逻辑
|
||||
ticket.setOrderId(jeecgOrderMain.getId());
|
||||
jeecgOrderTicketMapper.insert(ticket);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(orderTicket.getId().equals(ticket.getId())){
|
||||
// 传过来的id和数据库id一至时,说明数据库存在该数据,走更新逻辑
|
||||
|
@ -109,7 +109,7 @@ public class JeecgOrderMainServiceImpl extends ServiceImpl<JeecgOrderMainMapper,
|
|||
// 当传过来的id数据库不存在时,说明数据库没有,走新增逻辑
|
||||
customer.setOrderId(jeecgOrderMain.getId());
|
||||
jeecgOrderCustomerMapper.insert(customer);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(customers.getId().equals(customer.getId())){
|
||||
//TODO 传过来的id和数据库id一至时,说明数据库存在该数据,走更新逻辑
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/loadDictItemByKeyword")
|
||||
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize);
|
||||
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageNo", defaultValue = "1", required = false) Integer pageNo, @RequestParam(value = "pageSize", required = false) Integer pageSize);
|
||||
|
||||
/**
|
||||
* 47 根据多个部门id(逗号分隔),查询返回多个部门信息
|
||||
|
|
|
@ -382,7 +382,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-system-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -457,7 +457,7 @@ public interface ISysBaseAPI extends CommonAPI {
|
|||
* @param pageSize 分页条数
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize);
|
||||
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize);
|
||||
|
||||
/**
|
||||
* 新增数据日志
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.7.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -36,8 +36,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>drag-free-springboot3</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<artifactId>jimureport-dashboard-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- 积木报表 mongo redis 支持包
|
||||
<dependency>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.config.jimureport;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.dto.LogDTO;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
|
@ -13,6 +14,7 @@ import org.springframework.beans.BeanUtils;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -42,18 +44,38 @@ public class JimuDragExternalServiceImpl implements IOnlDragExternalService {
|
|||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
@Override
|
||||
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList) {
|
||||
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList, List<JSONObject> tableDictList) {
|
||||
Map<String, List<DragDictModel>> manyDragDictItems = new HashMap<>();
|
||||
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
|
||||
dictItemsMap.forEach((k,v)->{
|
||||
List<DragDictModel> dictItems = new ArrayList<>();
|
||||
v.forEach(dictItem->{
|
||||
DragDictModel dictModel = new DragDictModel();
|
||||
BeanUtils.copyProperties(dictItem,dictModel);
|
||||
dictItems.add(dictModel);
|
||||
if(!CollectionUtils.isEmpty(codeList)){
|
||||
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
|
||||
dictItemsMap.forEach((k,v)->{
|
||||
List<DragDictModel> dictItems = new ArrayList<>();
|
||||
v.forEach(dictItem->{
|
||||
DragDictModel dictModel = new DragDictModel();
|
||||
BeanUtils.copyProperties(dictItem,dictModel);
|
||||
dictItems.add(dictModel);
|
||||
});
|
||||
manyDragDictItems.put(k,dictItems);
|
||||
});
|
||||
manyDragDictItems.put(k,dictItems);
|
||||
});
|
||||
}
|
||||
|
||||
if(!CollectionUtils.isEmpty(tableDictList)){
|
||||
tableDictList.forEach(item->{
|
||||
List<DragDictModel> dictItems = new ArrayList<>();
|
||||
JSONObject object = JSONObject.parseObject(item.toString());
|
||||
String dictField = object.getString("dictField");
|
||||
String dictTable = object.getString("dictTable");
|
||||
String dictText = object.getString("dictText");
|
||||
String fieldName = object.getString("fieldName");
|
||||
List<DictModel> dictItemsList = sysBaseApi.queryTableDictItemsByCode(dictTable,dictText,dictField);
|
||||
dictItemsList.forEach(dictItem->{
|
||||
DragDictModel dictModel = new DragDictModel();
|
||||
BeanUtils.copyProperties(dictItem,dictModel);
|
||||
dictItems.add(dictModel);
|
||||
});
|
||||
manyDragDictItems.put(fieldName,dictItems);
|
||||
});
|
||||
}
|
||||
return manyDragDictItems;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public class SystemApiController {
|
|||
try {
|
||||
SensitiveInfoUtil.handlerObject(loginUser, true);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return loginUser;
|
||||
}
|
||||
|
@ -666,8 +666,11 @@ public class SystemApiController {
|
|||
* @return
|
||||
*/
|
||||
@GetMapping("/loadDictItemByKeyword")
|
||||
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||
return sysBaseApi.loadDictItemByKeyword(dictCode, keyword, pageSize);
|
||||
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode,
|
||||
@RequestParam("keyword") String keyword,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1", required = false) Integer pageNo,
|
||||
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||
return sysBaseApi.loadDictItemByKeyword(dictCode, keyword,pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.jeecg.common.constant.SymbolConstant;
|
|||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.ImportExcelUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.security.utils.SecureUtil;
|
||||
import org.jeecg.modules.quartz.entity.QuartzJob;
|
||||
import org.jeecg.modules.quartz.service.IQuartzJobService;
|
||||
|
@ -207,6 +208,12 @@ public class QuartzJobController {
|
|||
public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {
|
||||
// Step.1 组装查询条件
|
||||
QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
|
||||
// 过滤选中数据
|
||||
String selections = request.getParameter("selections");
|
||||
if (oConvertUtils.isNotEmpty(selections)) {
|
||||
List<String> selectionList = Arrays.asList(selections.split(","));
|
||||
queryWrapper.in("id",selectionList);
|
||||
}
|
||||
// Step.2 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
List<QuartzJob> pageList = quartzJobService.list(queryWrapper);
|
||||
|
|
|
@ -51,7 +51,7 @@ public class CommonController {
|
|||
*/
|
||||
@GetMapping("/403")
|
||||
public Result<?> noauth() {
|
||||
return Result.error("没有权限,请联系管理员授权,后刷新缓存!");
|
||||
return Result.error("没有权限,请联系管理员分配权限!");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.Date;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.DataBaseConstant;
|
||||
|
@ -219,13 +220,21 @@ public class SysAnnouncementSendController {
|
|||
@GetMapping(value = "/getMyAnnouncementSend")
|
||||
public Result<IPage<AnnouncementSendModel>> getMyAnnouncementSend(AnnouncementSendModel announcementSendModel,
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
|
||||
Result<IPage<AnnouncementSendModel>> result = new Result<IPage<AnnouncementSendModel>>();
|
||||
LoginUser sysUser = SecureUtil.currentUser();
|
||||
String userId = sysUser.getId();
|
||||
announcementSendModel.setUserId(userId);
|
||||
announcementSendModel.setPageNo((pageNo-1)*pageSize);
|
||||
announcementSendModel.setPageSize(pageSize);
|
||||
//update-begin---author:wangshuai---date:2024-06-11---for:【TV360X-545】我的消息列表不能通过时间范围查询---
|
||||
if(StringUtils.isNotEmpty(announcementSendModel.getSendTimeBegin())){
|
||||
announcementSendModel.setSendTimeBegin(announcementSendModel.getSendTimeBegin() + " 00:00:00");
|
||||
}
|
||||
if(StringUtils.isNotEmpty(announcementSendModel.getSendTimeBegin())){
|
||||
announcementSendModel.setSendTimeEnd(announcementSendModel.getSendTimeEnd() + " 23:59:59");
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-06-11---for:【TV360X-545】我的消息列表不能通过时间范围查询---
|
||||
Page<AnnouncementSendModel> pageList = new Page<AnnouncementSendModel>(pageNo,pageSize);
|
||||
pageList = sysAnnouncementSendService.getMyAnnouncementSendPage(pageList, announcementSendModel);
|
||||
result.setResult(pageList);
|
||||
|
|
|
@ -366,9 +366,17 @@ public class SysDepartController {
|
|||
//return arg0.getOrgCode().compareTo(arg1.getOrgCode());
|
||||
//}
|
||||
//});
|
||||
// 过滤选中数据
|
||||
String selections = request.getParameter("selections");
|
||||
List<String> idList = new ArrayList<>();
|
||||
if (oConvertUtils.isNotEmpty(selections)) {
|
||||
idList = Arrays.asList(selections.split(","));
|
||||
}
|
||||
//step.2 组装导出数据
|
||||
Integer tenantId = sysDepart == null ? null : sysDepart.getTenantId();
|
||||
List<SysDepartExportVo> sysDepartExportVos = sysDepartService.getExportDepart(tenantId);
|
||||
//update-begin---author:wangshuai---date:2024-07-05---for:【TV360X-1671】部门管理不支持选中的记录导出---
|
||||
List<SysDepartExportVo> sysDepartExportVos = sysDepartService.getExportDepart(tenantId,idList);
|
||||
//update-end---author:wangshuai---date:2024-07-05---for:【TV360X-1671】部门管理不支持选中的记录导出---
|
||||
//导出文件名称
|
||||
mv.addObject(NormalExcelConstants.FILE_NAME, "部门列表");
|
||||
mv.addObject(NormalExcelConstants.CLASS, SysDepartExportVo.class);
|
||||
|
|
|
@ -156,7 +156,8 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
|
|||
@PreAuthorize("@jps.requiresPermissions('system:depart:role:deleteBatch')")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
this.sysDepartRoleService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
this.sysDepartRoleService.deleteDepartRole(Arrays.asList(ids.split(",")));
|
||||
//this.sysDepartRoleService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("批量删除成功!");
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@ package org.jeecg.modules.system.controller;
|
|||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
|
@ -75,8 +77,14 @@ public class SysDictController {
|
|||
private JeecgPermissionService jeecgPermissionService;
|
||||
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
public Result<IPage<SysDict>> queryPageList(SysDict sysDict,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
|
||||
public Result<IPage<SysDict>> queryPageList(
|
||||
SysDict sysDict,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
// 查询关键字,模糊筛选code和name
|
||||
@RequestParam(name = "keywords", required = false) String keywords,
|
||||
HttpServletRequest req
|
||||
) {
|
||||
Result<IPage<SysDict>> result = new Result<IPage<SysDict>>();
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
|
@ -85,7 +93,12 @@ public class SysDictController {
|
|||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
QueryWrapper<SysDict> queryWrapper = QueryGenerator.initQueryWrapper(sysDict, req.getParameterMap());
|
||||
Page<SysDict> page = new Page<SysDict>(pageNo, pageSize);
|
||||
// 查询关键字,模糊筛选code和name
|
||||
if (oConvertUtils.isNotEmpty(keywords)) {
|
||||
queryWrapper.and(i -> i.like("dict_code", keywords).or().like("dict_name", keywords));
|
||||
}
|
||||
|
||||
Page<SysDict> page = new Page<>(pageNo, pageSize);
|
||||
IPage<SysDict> pageList = sysDictService.page(page, queryWrapper);
|
||||
log.debug("查询当前页:"+pageList.getCurrent());
|
||||
log.debug("查询当前页数量:"+pageList.getSize());
|
||||
|
@ -199,7 +212,8 @@ public class SysDictController {
|
|||
public Result<List<DictModel>> loadDict(@PathVariable("dictCode") String dictCode,
|
||||
@RequestParam(name="keyword",required = false) String keyword,
|
||||
@RequestParam(value = "sign",required = false) String sign,
|
||||
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||
@RequestParam(name = "pageNo", defaultValue = "1", required = false) Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10", required = false) Integer pageSize) {
|
||||
|
||||
//update-begin-author:taoyan date:2023-5-22 for: /issues/4905 因为中括号(%5)的问题导致的 表单生成器字段配置时,选择关联字段,在进行高级配置时,无法加载数据库列表,提示 Sgin签名校验错误! #4905 RouteToRequestUrlFilter
|
||||
if(keyword!=null && keyword.indexOf("%5")>=0){
|
||||
|
@ -214,7 +228,7 @@ public class SysDictController {
|
|||
log.info(" 加载字典表数据,加载关键字: "+ keyword);
|
||||
Result<List<DictModel>> result = new Result<List<DictModel>>();
|
||||
try {
|
||||
List<DictModel> ls = sysDictService.loadDict(dictCode, keyword, pageSize);
|
||||
List<DictModel> ls = sysDictService.loadDict(dictCode, keyword, pageNo,pageSize);
|
||||
if (ls == null) {
|
||||
result.error500("字典Code格式不正确!");
|
||||
return result;
|
||||
|
@ -246,12 +260,12 @@ public class SysDictController {
|
|||
@RequestParam(value = "sign", required = false) String sign,
|
||||
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
|
||||
// 首次查询查出来用户选中的值,并且不分页
|
||||
Result<List<DictModel>> firstRes = this.loadDict(dictCode, keyword, sign, null);
|
||||
Result<List<DictModel>> firstRes = this.loadDict(dictCode, keyword, sign,null, null);
|
||||
if (!firstRes.isSuccess()) {
|
||||
return firstRes;
|
||||
}
|
||||
// 然后再查询出第一页的数据
|
||||
Result<List<DictModel>> result = this.loadDict(dictCode, "", sign, pageSize);
|
||||
Result<List<DictModel>> result = this.loadDict(dictCode, "", sign,1, pageSize);
|
||||
if (!result.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
|
@ -660,6 +674,45 @@ public class SysDictController {
|
|||
return Result.error("操作失败!");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 还原被逻辑删除的用户
|
||||
*
|
||||
* @param jsonObject
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/putRecycleBin", method = RequestMethod.PUT)
|
||||
public Result putRecycleBin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
|
||||
try {
|
||||
String ids = jsonObject.getString("ids");
|
||||
if (StringUtils.isNotBlank(ids)) {
|
||||
sysDictService.revertLogicDeleted(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("操作成功!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("操作失败!");
|
||||
}
|
||||
return Result.ok("还原成功");
|
||||
}
|
||||
/**
|
||||
* 彻底删除字典
|
||||
*
|
||||
* @param ids 被删除的字典ID,多个id用半角逗号分割
|
||||
* @return
|
||||
*/
|
||||
@PreAuthorize("@jps.requiresPermissions('system:dict:deleteRecycleBin')")
|
||||
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
|
||||
public Result deleteRecycleBin(@RequestParam("ids") String ids) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(ids)) {
|
||||
sysDictService.removeLogicDeleted(Arrays.asList(ids.split(",")));
|
||||
}
|
||||
return Result.ok("删除成功!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("删除失败!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VUEN-2584【issue】平台sql注入漏洞几个问题
|
||||
|
|
|
@ -4,7 +4,9 @@ import com.alibaba.fastjson.JSONArray;
|
|||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
|
@ -14,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -74,4 +77,72 @@ public class SysGatewayRouteController extends JeecgController<SysGatewayRoute,
|
|||
return Result.ok("删除路由成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询被删除的列表
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/deleteList", method = RequestMethod.GET)
|
||||
public Result<List<SysGatewayRoute>> deleteList(HttpServletRequest request) {
|
||||
Result<List<SysGatewayRoute>> result = new Result<>();
|
||||
List<SysGatewayRoute> list = sysGatewayRouteService.getDeletelist();
|
||||
result.setSuccess(true);
|
||||
result.setResult(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原被逻辑删除的路由
|
||||
*
|
||||
* @param jsonObject
|
||||
* @return
|
||||
*/
|
||||
@PreAuthorize("@jps.requiresPermissions('system:getway:putRecycleBin')")
|
||||
@RequestMapping(value = "/putRecycleBin", method = RequestMethod.PUT)
|
||||
public Result putRecycleBin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
|
||||
try {
|
||||
String ids = jsonObject.getString("ids");
|
||||
if (StringUtils.isNotBlank(ids)) {
|
||||
sysGatewayRouteService.revertLogicDeleted(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("操作成功!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("操作失败!");
|
||||
}
|
||||
return Result.ok("还原成功");
|
||||
}
|
||||
/**
|
||||
* 彻底删除路由
|
||||
*
|
||||
* @param ids 被删除的路由ID,多个id用半角逗号分割
|
||||
* @return
|
||||
*/
|
||||
@PreAuthorize("@jps.requiresPermissions('system:getway:deleteRecycleBin')")
|
||||
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
|
||||
public Result deleteRecycleBin(@RequestParam("ids") String ids) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(ids)) {
|
||||
sysGatewayRouteService.deleteLogicDeleted(Arrays.asList(ids.split(",")));
|
||||
}
|
||||
return Result.ok("删除成功!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return Result.error("删除失败!");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 复制路由
|
||||
*
|
||||
* @param id 路由id
|
||||
* @return
|
||||
*/
|
||||
@PreAuthorize("@jps.requiresPermissions('system:getway:copyRoute')")
|
||||
@RequestMapping(value = "/copyRoute", method = RequestMethod.GET)
|
||||
public Result<SysGatewayRoute> copyRoute(@RequestParam(name = "id", required = true) String id, HttpServletRequest req) {
|
||||
Result<SysGatewayRoute> result = new Result<>();
|
||||
SysGatewayRoute sysGatewayRoute= sysGatewayRouteService.copyRoute(id);
|
||||
result.setResult(sysGatewayRoute);
|
||||
result.setSuccess(true);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
|
|
|
@ -220,26 +220,31 @@ public class SysPositionController {
|
|||
* @param response
|
||||
*/
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, HttpServletResponse response) {
|
||||
public ModelAndView exportXls(SysPosition sysPosition,HttpServletRequest request, HttpServletResponse response) {
|
||||
// Step.1 组装查询条件
|
||||
QueryWrapper<SysPosition> queryWrapper = null;
|
||||
try {
|
||||
String paramsStr = request.getParameter("paramsStr");
|
||||
if (oConvertUtils.isNotEmpty(paramsStr)) {
|
||||
String deString = URLDecoder.decode(paramsStr, "UTF-8");
|
||||
SysPosition sysPosition = JSON.parseObject(deString, SysPosition.class);
|
||||
sysPosition = JSON.parseObject(deString, SysPosition.class);
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||
if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){
|
||||
sysPosition.setTenantId(oConvertUtils.getInt(TenantContext.getTenant(),0));
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
queryWrapper = QueryGenerator.initQueryWrapper(sysPosition, request.getParameterMap());
|
||||
}
|
||||
queryWrapper = QueryGenerator.initQueryWrapper(sysPosition, request.getParameterMap());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//update-begin--Author:liusq Date:20240715 for:[03]职务导出,如果选择数据则只导出相关数据--------------------
|
||||
String selections = request.getParameter("selections");
|
||||
if(!oConvertUtils.isEmpty(selections)){
|
||||
queryWrapper.in("id",selections.split(","));
|
||||
}
|
||||
//update-end--Author:liusq Date:20240715 for:[03]职务导出,如果选择数据则只导出相关数据----------------------
|
||||
//Step.2 AutoPoi 导出Excel
|
||||
ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
|
||||
List<SysPosition> pageList = sysPositionService.list(queryWrapper);
|
||||
|
|
|
@ -220,7 +220,7 @@ public class SysRoleController {
|
|||
String username = "admin";
|
||||
if(getRoleCount == 0 && !username.equals(sysUser.getUsername())){
|
||||
baseCommonService.addLog("未经授权,删除非本租户下的角色ID:" + id + ",操作人:" + sysUser.getUsername(), CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_4);
|
||||
return Result.error("删除角色失败,删除角色不属于登录租户!");
|
||||
return Result.error("删除角色失败,当前角色不在此租户中。");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,9 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:list')")
|
||||
@GetMapping(value = "/list")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
public Result<?> queryPageList(
|
||||
SysTableWhiteList sysTableWhiteList,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
|
@ -63,7 +64,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
*/
|
||||
@AutoLog(value = "系统表白名单-添加")
|
||||
@Operation(summary = "系统表白名单-添加")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
//@RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:add')")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody SysTableWhiteList sysTableWhiteList) {
|
||||
if (sysTableWhiteListService.add(sysTableWhiteList)) {
|
||||
|
@ -81,7 +83,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
*/
|
||||
@AutoLog(value = "系统表白名单-编辑")
|
||||
@Operation(summary = "系统表白名单-编辑")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
//@RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:edit')")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<?> edit(@RequestBody SysTableWhiteList sysTableWhiteList) {
|
||||
if (sysTableWhiteListService.edit(sysTableWhiteList)) {
|
||||
|
@ -99,7 +102,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
*/
|
||||
@AutoLog(value = "系统表白名单-通过id删除")
|
||||
@Operation(summary = "系统表白名单-通过id删除")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
// @RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:delete')")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id") String id) {
|
||||
if (sysTableWhiteListService.deleteByIds(id)) {
|
||||
|
@ -117,7 +121,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
*/
|
||||
@AutoLog(value = "系统表白名单-批量删除")
|
||||
@Operation(summary = "系统表白名单-批量删除")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
// @RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:deleteBatch')")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids") String ids) {
|
||||
if (sysTableWhiteListService.deleteByIds(ids)) {
|
||||
|
@ -135,7 +140,8 @@ public class SysTableWhiteListController extends JeecgController<SysTableWhiteLi
|
|||
*/
|
||||
@AutoLog(value = "系统表白名单-通过id查询")
|
||||
@Operation(summary = "系统表白名单-通过id查询")
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
// @RequiresRoles("admin")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:tableWhite:queryById')")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
SysTableWhiteList sysTableWhiteList = sysTableWhiteListService.getById(id);
|
||||
|
|
|
@ -206,7 +206,8 @@ public class SysUserController {
|
|||
// 修改用户走一个service 保证事务
|
||||
//获取租户ids
|
||||
String relTenantIds = jsonObject.getString("relTenantIds");
|
||||
sysUserService.editUser(user, roles, departs, relTenantIds);
|
||||
String updateFromPage = jsonObject.getString("updateFromPage");
|
||||
sysUserService.editUser(user, roles, departs, relTenantIds, updateFromPage);
|
||||
result.success("修改成功!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -223,7 +224,12 @@ public class SysUserController {
|
|||
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
|
||||
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
|
||||
baseCommonService.addLog("删除用户,id: " +id ,CommonConstant.LOG_TYPE_2, 3);
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(id));
|
||||
this.sysUserService.deleteUser(id);
|
||||
|
||||
if (!userNameList.isEmpty()) {
|
||||
String joinedString = String.join(",", userNameList);
|
||||
}
|
||||
return Result.ok("删除用户成功");
|
||||
}
|
||||
|
||||
|
@ -234,7 +240,13 @@ public class SysUserController {
|
|||
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
|
||||
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
|
||||
baseCommonService.addLog("批量删除用户, ids: " +ids ,CommonConstant.LOG_TYPE_2, 3);
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(ids.split(",")));
|
||||
this.sysUserService.deleteBatchUsers(ids);
|
||||
|
||||
// 用户变更,触发同步工作流
|
||||
if (!userNameList.isEmpty()) {
|
||||
String joinedString = String.join(",", userNameList);
|
||||
}
|
||||
return Result.ok("批量删除用户成功");
|
||||
}
|
||||
|
||||
|
@ -907,6 +919,9 @@ public class SysUserController {
|
|||
boolean b = sysUserDepartService.remove(queryWrapper);
|
||||
if(b){
|
||||
departRoleUserService.removeDeptRoleUser(Arrays.asList(userIds.split(",")),depId);
|
||||
}else{
|
||||
result.error500("删除失败,目标用户不在当前部门!");
|
||||
return result;
|
||||
}
|
||||
result.success("删除成功!");
|
||||
}catch(Exception e) {
|
||||
|
@ -1262,6 +1277,12 @@ public class SysUserController {
|
|||
updateUser.setUpdateBy(JwtUtil.getUserNameByToken(request));
|
||||
updateUser.setUpdateTime(new Date());
|
||||
sysUserService.revertLogicDeleted(Arrays.asList(userIds.split(",")), updateUser);
|
||||
// 用户变更,触发同步工作流
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(userIds.split(",")));
|
||||
if (!userNameList.isEmpty()) {
|
||||
String joinedString = String.join(",", userNameList);
|
||||
}
|
||||
|
||||
}
|
||||
return Result.ok("还原成功");
|
||||
}
|
||||
|
@ -1287,7 +1308,7 @@ public class SysUserController {
|
|||
* @param jsonObject
|
||||
* @return
|
||||
*/
|
||||
@PreAuthorize("@jps.requiresRoles('admin')")
|
||||
@PreAuthorize("@jps.requiresPermissions('system:user:app:edit')")
|
||||
@RequestMapping(value = "/appEdit", method = {RequestMethod.PUT,RequestMethod.POST})
|
||||
public Result<SysUser> appEdit(HttpServletRequest request,@RequestBody JSONObject jsonObject) {
|
||||
Result<SysUser> result = new Result<SysUser>();
|
||||
|
|
|
@ -11,12 +11,14 @@ import me.zhyd.oauth.model.AuthCallback;
|
|||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysThirdAccount;
|
||||
import org.jeecg.modules.system.entity.SysThirdAppConfig;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
|
@ -25,6 +27,7 @@ import org.jeecg.modules.system.service.ISysDictService;
|
|||
import org.jeecg.modules.system.service.ISysThirdAccountService;
|
||||
import org.jeecg.modules.system.service.ISysThirdAppConfigService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.service.ISysDepartService;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -60,6 +63,8 @@ public class ThirdLoginController {
|
|||
private RedisUtil redisUtil;
|
||||
@Autowired
|
||||
private AuthRequestFactory factory;
|
||||
@Autowired
|
||||
private ISysDepartService sysDepartService;
|
||||
|
||||
@Autowired
|
||||
private ThirdAppWechatEnterpriseServiceImpl thirdAppWechatEnterpriseService;
|
||||
|
@ -250,8 +255,8 @@ public class ThirdLoginController {
|
|||
}
|
||||
//update-end-author:wangshuai date:20201118 for:如果真实姓名和头像不存在就取第三方登录的
|
||||
JSONObject obj = new JSONObject();
|
||||
//TODO 第三方登确定登录租户和部门逻辑
|
||||
|
||||
//第三方登确定登录租户和部门逻辑
|
||||
this.setUserTenantAndDepart(sysUser,obj,result);
|
||||
//用户登录信息
|
||||
obj.put("userInfo", sysUser);
|
||||
//获取字典缓存【解决 #jeecg-boot/issues/3998】
|
||||
|
@ -528,4 +533,28 @@ public class ThirdLoginController {
|
|||
return Result.error("注册失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户租户和部门信息
|
||||
*
|
||||
* @param sysUser
|
||||
* @param obj
|
||||
* @param result
|
||||
*/
|
||||
private void setUserTenantAndDepart(SysUser sysUser, JSONObject obj, Result<JSONObject> result) {
|
||||
//1.设置登录租户
|
||||
sysUserService.setLoginTenant(sysUser, obj, sysUser.getUsername(), result);
|
||||
//2.设置登录部门
|
||||
String orgCode = sysUser.getOrgCode();
|
||||
//部门不为空还是用原来的部门code
|
||||
if(StringUtils.isEmpty(orgCode)){
|
||||
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
||||
//部门不为空取第一个作为当前登录部门
|
||||
if(CollectionUtil.isNotEmpty(departs)){
|
||||
orgCode = departs.get(0).getOrgCode();
|
||||
sysUser.setOrgCode(orgCode);
|
||||
this.sysUserService.updateUserDepart(sysUser.getUsername(), orgCode,null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.modules.system.util.XssUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -22,8 +24,13 @@ public class WechatVerifyController {
|
|||
*/
|
||||
@RequestMapping(value = "/WW_verify_{code}.txt")
|
||||
public void mpVerify(@PathVariable("code") String code, HttpServletResponse response) {
|
||||
if(StringUtils.isEmpty(code)){
|
||||
log.error("企业微信证书验证失败!(code为空)");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PrintWriter writer = response.getWriter();
|
||||
code = XssUtils.scriptXss(code);
|
||||
writer.write(code);
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
@ -76,4 +77,11 @@ public class SysComment implements Serializable {
|
|||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "更新日期")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 不是数据库字段,用于评论跳转
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String tableId;
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.jeecg.modules.system.entity;
|
|||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
@ -96,6 +97,12 @@ public class SysGatewayRoute implements Serializable {
|
|||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "创建日期")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 删除状态(0未删除,1已删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
/* *//**更新人*//*
|
||||
@Schema(description = "更新人")
|
||||
private String updateBy;
|
||||
|
|
|
@ -46,7 +46,7 @@ public class SysPosition {
|
|||
/**
|
||||
* 职级
|
||||
*/
|
||||
@Excel(name = "职级", width = 15,dicCode ="position_rank")
|
||||
//@Excel(name = "职级", width = 15,dicCode ="position_rank")
|
||||
@Schema(description = "职级")
|
||||
@Dict(dicCode = "position_rank")
|
||||
private java.lang.String postRank;
|
||||
|
|
|
@ -177,5 +177,5 @@ public interface SysDepartMapper extends BaseMapper<SysDepart> {
|
|||
* @param parentId
|
||||
* @return
|
||||
*/
|
||||
List<SysDepartExportVo> getSysDepartList(@Param("parentId") String parentId,@Param("tenantId") Integer tenantId);
|
||||
List<SysDepartExportVo> getSysDepartList(@Param("parentId") String parentId,@Param("tenantId") Integer tenantId, List<String> idList);
|
||||
}
|
||||
|
|
|
@ -14,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||
*/
|
||||
public interface SysDepartRolePermissionMapper extends BaseMapper<SysDepartRolePermission> {
|
||||
|
||||
void deleteByRoleIds(@Param("ids")List<String> ids);
|
||||
}
|
||||
|
|
|
@ -14,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||
*/
|
||||
public interface SysDepartRoleUserMapper extends BaseMapper<SysDepartRoleUser> {
|
||||
|
||||
void deleteByRoleIds(@Param("ids")List<String> ids);
|
||||
}
|
||||
|
|
|
@ -200,4 +200,18 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
|
|||
*/
|
||||
@Select("select * from sys_dict where del_flag = 1 and tenant_id = #{tenantId}")
|
||||
List<SysDict> queryDeleteListBtTenantId(@Param("tenantId") Integer tenantId);
|
||||
|
||||
/**
|
||||
* 还原被逻辑删除的数据(根据id)
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
int revertLogicDeleted(@Param("ids") List<String> ids);
|
||||
|
||||
/**
|
||||
* 彻底删除的数据(根据ids)
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
int removeLogicDeleted(@Param("ids")List<String> ids);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package org.jeecg.modules.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.jeecg.modules.system.entity.SysGatewayRoute;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: gateway路由管理
|
||||
* @Author: jeecg-boot
|
||||
|
@ -10,5 +14,22 @@ import org.jeecg.modules.system.entity.SysGatewayRoute;
|
|||
* @Version: V1.0
|
||||
*/
|
||||
public interface SysGatewayRouteMapper extends BaseMapper<SysGatewayRoute> {
|
||||
/**
|
||||
* 还原逻辑删除
|
||||
* @param ids
|
||||
*/
|
||||
int revertLogicDeleted(@Param("ids") List<String> ids);
|
||||
|
||||
/**
|
||||
*彻底删除
|
||||
* @param ids
|
||||
*/
|
||||
int deleteLogicDeleted(@Param("ids") List<String> ids);
|
||||
|
||||
/**
|
||||
* 查询删除的列表
|
||||
* @return
|
||||
*/
|
||||
@Select("select * from sys_gateway_route where del_flag = 1")
|
||||
List<SysGatewayRoute> queryDeleteList();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,10 @@
|
|||
|
||||
<!-- 获取用户未读消息数量 -->
|
||||
<select id="getUnreadMessageCountByUserId" resultType="java.lang.Integer">
|
||||
select count(1) from sys_announcement_send where user_id = #{userId} and read_flag = 0 and create_time >= #{beginDate}
|
||||
<!-- update by wangshuai 2024-07-02【TV360X-1682】撤销之后数量还显示,但是点开面板没有这条数据,他会一直显示有数据,需要联查判断已经发送的-->
|
||||
select count(1) from sys_announcement_send sas
|
||||
right join sys_announcement sa on sas.annt_id = sa.id and sa.send_status = '1'
|
||||
where sas.user_id = #{userId} and sas.read_flag = 0 and sas.create_time >= #{beginDate}
|
||||
</select>
|
||||
|
||||
<!-- 查询消息记录 -->
|
||||
|
|
|
@ -58,6 +58,10 @@
|
|||
<if test="announcementSendModel.msgCategory !=null and announcementSendModel.msgCategory != ''">
|
||||
and sa.msg_category = #{announcementSendModel.msgCategory}
|
||||
</if>
|
||||
<if test="announcementSendModel.sendTimeBegin !=null and announcementSendModel.sendTimeBegin != ''
|
||||
and announcementSendModel.sendTimeEnd != '' and announcementSendModel.sendTimeEnd != ''">
|
||||
and sa.send_time between #{announcementSendModel.sendTimeBegin} and #{announcementSendModel.sendTimeEnd}
|
||||
</if>
|
||||
order by sas.read_flag,sa.send_time desc
|
||||
</select>
|
||||
|
||||
|
|
|
@ -182,9 +182,15 @@
|
|||
parent_id = #{parentId}
|
||||
</when>
|
||||
<otherwise>
|
||||
parent_id IS NULL OR parent_id=''
|
||||
(parent_id IS NULL OR parent_id='')
|
||||
</otherwise>
|
||||
</choose>
|
||||
<if test="idList != null and !idList.isEmpty()">
|
||||
and id in
|
||||
<foreach item="id" index="index" collection="idList" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
ORDER BY depart_order DESC
|
||||
</select>
|
||||
</mapper>
|
|
@ -2,4 +2,11 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.jeecg.modules.system.mapper.SysDepartRolePermissionMapper">
|
||||
|
||||
<delete id="deleteByRoleIds">
|
||||
DELETE FROM sys_depart_role_permission
|
||||
WHERE role_id IN
|
||||
<foreach collection="ids" item="roleId" open="(" close=")" separator="," >
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
|
@ -2,4 +2,11 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.jeecg.modules.system.mapper.SysDepartRoleUserMapper">
|
||||
|
||||
<delete id="deleteByRoleIds">
|
||||
DELETE FROM sys_depart_role_user
|
||||
WHERE drole_id IN
|
||||
<foreach collection="ids" item="roleId" open="(" close=")" separator="," >
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
|
@ -217,5 +217,29 @@
|
|||
and tenant_id = #{tenantId}
|
||||
</select>
|
||||
|
||||
<!-- 还原被逻辑删除的字典 -->
|
||||
<update id="revertLogicDeleted">
|
||||
UPDATE
|
||||
sys_dict
|
||||
SET
|
||||
del_flag = 0
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND id IN
|
||||
<foreach collection="ids" item="dictId" open="(" close=")" separator="," >
|
||||
#{dictId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 彻底删除字典 -->
|
||||
<delete id="removeLogicDeleted">
|
||||
DELETE FROM sys_dict
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND id IN
|
||||
<foreach collection="ids" item="dictId" open="(" close=")" separator="," >
|
||||
#{dictId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -2,4 +2,29 @@
|
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.jeecg.modules.system.mapper.SysGatewayRouteMapper">
|
||||
|
||||
<!-- 还原被逻辑删除的路由 -->
|
||||
<update id="revertLogicDeleted">
|
||||
UPDATE
|
||||
sys_gateway_route
|
||||
SET
|
||||
del_flag = 0
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND id IN
|
||||
<foreach collection="ids" item="routeId" open="(" close=")" separator="," >
|
||||
#{routeId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 彻底删除路由 -->
|
||||
<delete id="deleteLogicDeleted">
|
||||
DELETE FROM sys_gateway_route
|
||||
WHERE
|
||||
del_flag = 1
|
||||
AND id IN
|
||||
<foreach collection="ids" item="routeId" open="(" close=")" separator="," >
|
||||
#{routeId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
|
@ -181,7 +181,29 @@
|
|||
|
||||
<!-- 查询部门权限数据 -->
|
||||
<select id="queryDepartPermissionList" parameterType="String" resultType="org.jeecg.modules.system.entity.SysPermission">
|
||||
SELECT * FROM sys_permission
|
||||
SELECT
|
||||
id,
|
||||
parent_id,
|
||||
name,
|
||||
url,
|
||||
component,
|
||||
is_route,
|
||||
component_name,
|
||||
redirect,
|
||||
menu_type,
|
||||
perms,
|
||||
perms_type,
|
||||
sort_no,
|
||||
always_show,
|
||||
icon,
|
||||
is_leaf AS leaf,
|
||||
keep_alive,
|
||||
hidden,
|
||||
hide_tab,
|
||||
rule_flag,
|
||||
status,
|
||||
internal_or_external
|
||||
FROM sys_permission
|
||||
where del_flag = 0
|
||||
and id in (
|
||||
select permission_id from sys_depart_permission where depart_id = #{departId}
|
||||
|
|
|
@ -10,9 +10,20 @@
|
|||
AND role_name like #{bindKeyword}
|
||||
</if>
|
||||
<if test="role.roleCode!='' and role.roleCode!=null">
|
||||
<bind name="bindRoleCode" value="'%'+role.roleCode+'%'"/>
|
||||
AND role_code like #{bindRoleCode}
|
||||
<choose>
|
||||
<when test="role.roleCode.indexOf(',') != -1">
|
||||
AND role_code in
|
||||
<foreach item="item" index="index" collection="role.roleCode.split(',')" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
<bind name="bindRoleCode" value="'%'+role.roleCode+'%'"/>
|
||||
AND role_code like #{bindRoleCode}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
|
||||
<!-- 根据部门查询部门用户 分页 -->
|
||||
<select id="queryDepartUserPageList" resultType="org.jeecg.modules.system.entity.SysUser">
|
||||
select a.*, c.depart_name as org_code_txt from sys_user a
|
||||
join sys_user_depart b on b.user_id = a.id
|
||||
join sys_depart c on b.dep_id = c.id
|
||||
<!-- update by wangshuai 2024-07-03【issues/6342】部门人员选择组件出现人员重复-->
|
||||
select DISTINCT a.* from sys_user a
|
||||
left join sys_user_depart b on b.user_id = a.id
|
||||
left join sys_depart c on b.dep_id = c.id
|
||||
<bind name="bindOrgCode" value="orgCode+'%'"/>
|
||||
where a.del_flag = 0 and a.status = 1 and c.org_code like #{bindOrgCode} and a.username!='_reserve_user_external'
|
||||
<if test="username!=null and username!=''">
|
||||
|
|
|
@ -74,4 +74,13 @@ public class AnnouncementSendModel implements Serializable {
|
|||
*/
|
||||
private java.lang.String msgAbstract;
|
||||
|
||||
/**
|
||||
* 发布开始日期
|
||||
*/
|
||||
private java.lang.String sendTimeBegin;
|
||||
|
||||
/**
|
||||
* 发布结束日期
|
||||
*/
|
||||
private java.lang.String sendTimeEnd;
|
||||
}
|
||||
|
|
|
@ -21,4 +21,9 @@ public interface ISysDepartRoleService extends IService<SysDepartRole> {
|
|||
*/
|
||||
List<SysDepartRole> queryDeptRoleByDeptAndUser(String orgCode, String userId);
|
||||
|
||||
/**
|
||||
* 删除部门角色和对应关联表信息
|
||||
* @param ids
|
||||
*/
|
||||
void deleteDepartRole(List<String> ids);
|
||||
}
|
||||
|
|
|
@ -229,9 +229,10 @@ public interface ISysDepartService extends IService<SysDepart>{
|
|||
/**
|
||||
* 根据租户id导出部门
|
||||
* @param tenantId
|
||||
* @param idList
|
||||
* @return
|
||||
*/
|
||||
List<SysDepartExportVo> getExportDepart(Integer tenantId);
|
||||
List<SysDepartExportVo> getExportDepart(Integer tenantId, List<String> idList);
|
||||
|
||||
/**
|
||||
* 导出系统部门excel
|
||||
|
|
|
@ -194,7 +194,7 @@ public interface ISysDictService extends IService<SysDict> {
|
|||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String condition, String keyword, int pageSize);
|
||||
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String condition, String keyword, int pageNo, int pageSize);
|
||||
|
||||
/**
|
||||
* 查询字典表所有数据
|
||||
|
@ -264,10 +264,11 @@ public interface ISysDictService extends IService<SysDict> {
|
|||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword
|
||||
* @param pageNo
|
||||
* @param pageSize 每页条数
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> loadDict(String dictCode, String keyword, Integer pageSize);
|
||||
List<DictModel> loadDict(String dictCode, String keyword, Integer pageNo, Integer pageSize);
|
||||
|
||||
/**
|
||||
* 根据应用id获取字典列表和详情
|
||||
|
@ -287,4 +288,16 @@ public interface ISysDictService extends IService<SysDict> {
|
|||
* @param sysDictVo
|
||||
*/
|
||||
void editDictByLowAppId(SysDictVo sysDictVo);
|
||||
|
||||
/**
|
||||
* 还原逻辑删除
|
||||
* @param ids
|
||||
*/
|
||||
boolean revertLogicDeleted(List<String> ids);
|
||||
|
||||
/**
|
||||
* 彻底删除数据
|
||||
* @param ids
|
||||
*/
|
||||
boolean removeLogicDeleted(List<String> ids);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.system.entity.SysGatewayRoute;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: gateway路由管理
|
||||
* @Author: jeecg-boot
|
||||
|
@ -35,4 +37,28 @@ public interface ISysGatewayRouteService extends IService<SysGatewayRoute> {
|
|||
*/
|
||||
void clearRedis();
|
||||
|
||||
/**
|
||||
* 还原逻辑删除
|
||||
* @param ids
|
||||
*/
|
||||
void revertLogicDeleted(List<String> ids);
|
||||
|
||||
/**
|
||||
* 彻底删除
|
||||
* @param ids
|
||||
*/
|
||||
void deleteLogicDeleted(List<String> ids);
|
||||
|
||||
/**
|
||||
* 复制路由
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
SysGatewayRoute copyRoute(String id);
|
||||
|
||||
/**
|
||||
* 获取删除列表
|
||||
* @return
|
||||
*/
|
||||
List<SysGatewayRoute> getDeletelist();
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param user
|
||||
* @param roles
|
||||
*/
|
||||
public void addUserWithRole(SysUser user, String roles);
|
||||
public void addUserWithRole(SysUser user,String roles);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param user
|
||||
* @param roles
|
||||
*/
|
||||
public void editUserWithRole(SysUser user, String roles);
|
||||
public void editUserWithRole(SysUser user,String roles);
|
||||
|
||||
/**
|
||||
* 获取用户的授权角色
|
||||
|
@ -113,7 +113,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param version 前端UI版本
|
||||
* @return
|
||||
*/
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username, String version);
|
||||
public SysRoleIndex getDynamicIndexByUserRole(String username,String version);
|
||||
|
||||
/**
|
||||
* 查询用户信息包括 部门信息
|
||||
|
@ -177,7 +177,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param username 用户账户名称
|
||||
* @return
|
||||
*/
|
||||
public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username);
|
||||
public IPage<SysUser> getUserByRoleId(Page<SysUser> page,String roleId, String username);
|
||||
|
||||
/**
|
||||
* 通过用户名获取用户角色集合
|
||||
|
@ -311,8 +311,9 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param roles 选择的角色id,多个以逗号隔开
|
||||
* @param departs 选择的部门id,多个以逗号隔开
|
||||
* @param relTenantIds 多个租户id
|
||||
* @param updateFromPage 更新来自的页面 [TV360X-1686]
|
||||
*/
|
||||
void editUser(SysUser user, String roles, String departs, String relTenantIds);
|
||||
void editUser(SysUser user, String roles, String departs, String relTenantIds, String updateFromPage);
|
||||
|
||||
/**
|
||||
* userId转为username
|
||||
|
@ -355,7 +356,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param sysUser
|
||||
* @return
|
||||
*/
|
||||
Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result);
|
||||
Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result);
|
||||
|
||||
//--- author:taoyan date:20221231 for: QQYUN-3515【应用】应用下的组织机构管理功能,细节实现 ---
|
||||
/**
|
||||
|
@ -399,7 +400,7 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
*/
|
||||
void editTenantUser(SysUser sysUser, String tenantId, String departs, String roles);
|
||||
|
||||
/**
|
||||
/**
|
||||
* 修改用户账号状态
|
||||
* @param id 账号id
|
||||
* @param status 账号状态
|
||||
|
|
|
@ -1546,8 +1546,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
|
||||
return sysDictService.loadDict(dictCode, keyword, pageSize);
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize) {
|
||||
return sysDictService.loadDict(dictCode, keyword,pageNo, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -276,15 +276,30 @@ public class SysCommentServiceImpl extends ServiceImpl<SysCommentMapper, SysComm
|
|||
// update-begin-author:taoyan date:2023-5-10 for: QQYUN-4744【系统通知】6、系统通知@人后,对方看不到是哪个表单@的,没有超链接
|
||||
String tableName = sysComment.getTableName();
|
||||
String prefix = "desform:";
|
||||
if(tableName!=null && tableName.startsWith(prefix)){
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put(CommonConstant.NOTICE_MSG_BUS_TYPE, "comment");
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("code", tableName.substring(prefix.length()));
|
||||
params.put("dataId", sysComment.getTableDataId());
|
||||
params.put("type", "designForm");
|
||||
data.put(CommonConstant.NOTICE_MSG_SUMMARY, params);
|
||||
md.setData(data);
|
||||
if (tableName != null) {
|
||||
// 表单设计器
|
||||
if (tableName.startsWith(prefix)) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put(CommonConstant.NOTICE_MSG_BUS_TYPE, "comment");
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("code", tableName.substring(prefix.length()));
|
||||
params.put("dataId", sysComment.getTableDataId());
|
||||
params.put("type", "designForm");
|
||||
data.put(CommonConstant.NOTICE_MSG_SUMMARY, params);
|
||||
md.setData(data);
|
||||
}
|
||||
// Online表单,判断是否携带id
|
||||
else if (oConvertUtils.isNotEmpty(sysComment.getTableId())) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put(CommonConstant.NOTICE_MSG_BUS_TYPE, "comment");
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("code", tableName);
|
||||
params.put("formId", sysComment.getTableId());
|
||||
params.put("dataId", sysComment.getTableDataId());
|
||||
params.put("type", "cgform");
|
||||
data.put(CommonConstant.NOTICE_MSG_SUMMARY, params);
|
||||
md.setData(data);
|
||||
}
|
||||
}
|
||||
// update-end-author:taoyan date:2023-5-10 for: QQYUN-4744【系统通知】6、系统通知@人后,对方看不到是哪个表单@的,没有超链接
|
||||
|
||||
|
|
|
@ -2,10 +2,14 @@ package org.jeecg.modules.system.service.impl;
|
|||
|
||||
import org.jeecg.modules.system.entity.SysDepartRole;
|
||||
import org.jeecg.modules.system.mapper.SysDepartRoleMapper;
|
||||
import org.jeecg.modules.system.mapper.SysDepartRolePermissionMapper;
|
||||
import org.jeecg.modules.system.mapper.SysDepartRoleUserMapper;
|
||||
import org.jeecg.modules.system.service.ISysDepartRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -18,8 +22,26 @@ import java.util.List;
|
|||
@Service
|
||||
public class SysDepartRoleServiceImpl extends ServiceImpl<SysDepartRoleMapper, SysDepartRole> implements ISysDepartRoleService {
|
||||
|
||||
@Autowired
|
||||
SysDepartRolePermissionMapper sysDepartRolePermissionMapper;
|
||||
|
||||
@Autowired
|
||||
SysDepartRoleUserMapper sysDepartRoleUserMapper;
|
||||
|
||||
@Override
|
||||
public List<SysDepartRole> queryDeptRoleByDeptAndUser(String orgCode, String userId) {
|
||||
return this.baseMapper.queryDeptRoleByDeptAndUser(orgCode,userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门角色和对应关联表信息
|
||||
* @param ids
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteDepartRole(List<String> ids) {
|
||||
this.baseMapper.deleteBatchIds(ids);
|
||||
this.sysDepartRolePermissionMapper.deleteByRoleIds(ids);
|
||||
this.sysDepartRoleUserMapper.deleteByRoleIds(ids);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1226,12 +1226,13 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
|
|||
/**
|
||||
* 系统部门导出
|
||||
* @param tenantId
|
||||
* @param idList 需要查询部门sql的id集合
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<SysDepartExportVo> getExportDepart(Integer tenantId) {
|
||||
public List<SysDepartExportVo> getExportDepart(Integer tenantId, List<String> idList) {
|
||||
//获取父级部门
|
||||
List<SysDepartExportVo> parentDepart = departMapper.getSysDepartList("", tenantId);
|
||||
List<SysDepartExportVo> parentDepart = departMapper.getSysDepartList("", tenantId, idList);
|
||||
//子部门
|
||||
List<SysDepartExportVo> childrenDepart = new ArrayList<>();
|
||||
//把一级部门名称放在里面
|
||||
|
@ -1248,7 +1249,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
|
|||
List<String> path = new ArrayList<>();
|
||||
path.add(sysDepart.getDepartName());
|
||||
//创建子部门路径
|
||||
findSysDepartPath(sysDepart, path, tenantId, childrenDepart, departIdList);
|
||||
findSysDepartPath(sysDepart, path, tenantId, childrenDepart, departIdList, idList);
|
||||
path.clear();
|
||||
}
|
||||
exportDepartVoList.addAll(childrenDepart);
|
||||
|
@ -1356,11 +1357,12 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
|
|||
* @param tenantId 租户id
|
||||
* @param childrenDepart 子部门
|
||||
* @param departIdList 部门id集合
|
||||
* @param idList 需要查询sql的部门id集合
|
||||
*/
|
||||
private void findSysDepartPath(SysDepartExportVo departVo, List<String> path, Integer tenantId, List<SysDepartExportVo> childrenDepart, List<String> departIdList) {
|
||||
private void findSysDepartPath(SysDepartExportVo departVo, List<String> path, Integer tenantId, List<SysDepartExportVo> childrenDepart, List<String> departIdList, List<String> idList) {
|
||||
//step 1.查询子部门的数据
|
||||
//获取租户id和部门父id获取的部门数据
|
||||
List<SysDepartExportVo> departList = departMapper.getSysDepartList(departVo.getId(), tenantId);
|
||||
List<SysDepartExportVo> departList = departMapper.getSysDepartList(departVo.getId(), tenantId, idList);
|
||||
//部门为空判断
|
||||
if (departList == null || departList.size() <= 0) {
|
||||
//判断最后一个子部门是否已拼接
|
||||
|
@ -1382,7 +1384,7 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
|
|||
childrenDepart.add(departVo);
|
||||
}
|
||||
//step 3.递归查询子路径,直到找不到为止
|
||||
findSysDepartPath(exportDepartVo, cPath, tenantId, childrenDepart, departIdList);
|
||||
findSysDepartPath(exportDepartVo, cPath, tenantId, childrenDepart, departIdList, idList);
|
||||
}
|
||||
}
|
||||
//========================end 系统下部门与人员导入 ==================================================================
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.jeecg.common.system.vo.DictQuery;
|
|||
import org.jeecg.common.util.CommonUtils;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.SqlInjectionUtil;
|
||||
import org.jeecg.common.util.dynamic.db.DbTypeUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.SysDict;
|
||||
|
@ -94,6 +95,11 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
|
||||
// 4.执行SQL 查询是否存在值
|
||||
try{
|
||||
//update-begin---author:chenrui ---date:20240715 for:[TV360X-49]postgres日期、年月日时分秒唯一校验报错------------
|
||||
if(DbTypeUtils.dbTypeIsPostgre(CommonUtils.getDatabaseTypeEnum())){
|
||||
duplicateCheckVo.setFieldName("CAST("+duplicateCheckVo.getFieldName()+" as text)");
|
||||
}
|
||||
//update-end---author:chenrui ---date:20240715 for:[TV360X-49]postgres日期、年月日时分秒唯一校验报错------------
|
||||
if (StringUtils.isNotBlank(duplicateCheckVo.getDataId())) {
|
||||
// [1].编辑页面校验
|
||||
count = sysDictMapper.duplicateCheckCountSql(duplicateCheckVo);
|
||||
|
@ -504,8 +510,9 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
// }
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryLittleTableDictItems(String tableSql, String text, String code, String condition, String keyword, int pageSize) {
|
||||
Page<DictModel> page = new Page<DictModel>(1, pageSize);
|
||||
public List<DictModel> queryLittleTableDictItems(String tableSql, String text, String code, String condition, String keyword, int pageNo, int pageSize) {
|
||||
int current = oConvertUtils.getInt(pageNo, 1);
|
||||
Page<DictModel> page = new Page<DictModel>(current, pageSize);
|
||||
page.setSearchCount(false);
|
||||
|
||||
//为了防止sql(jeecg提供了防注入的方法,可以在拼接 SQL 语句时自动对参数进行转义,避免SQL注入攻击)
|
||||
|
@ -743,7 +750,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> loadDict(String dictCode, String keyword, Integer pageSize) {
|
||||
public List<DictModel> loadDict(String dictCode, String keyword, Integer pageNo, Integer pageSize) {
|
||||
// 【QQYUN-6533】表字典白名单check
|
||||
sysBaseAPI.dictTableWhiteListCheckByDict(dictCode);
|
||||
// 1.表字典黑名单check
|
||||
|
@ -777,7 +784,7 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
}
|
||||
List<DictModel> ls;
|
||||
if (pageSize != null) {
|
||||
ls = this.queryLittleTableDictItems(params[0], params[1], params[2], condition, keyword, pageSize);
|
||||
ls = this.queryLittleTableDictItems(params[0], params[1], params[2], condition, keyword, pageNo,pageSize);
|
||||
} else {
|
||||
ls = this.queryAllTableDictItems(params[0], params[1], params[2], condition, keyword);
|
||||
}
|
||||
|
@ -834,6 +841,30 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||
redisUtil.removeAll(CacheConstant.SYS_DICT_CACHE + "::" + dict.getDictCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原逻辑删除
|
||||
* @param ids
|
||||
*/
|
||||
@Override
|
||||
public boolean revertLogicDeleted(List<String> ids) {
|
||||
return baseMapper.revertLogicDeleted(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 彻底删除
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean removeLogicDeleted(List<String> ids) {
|
||||
// 1. 删除字典
|
||||
int line = this.baseMapper.removeLogicDeleted(ids);
|
||||
// 2. 删除字典选项配置
|
||||
line += this.sysDictItemMapper.delete(new LambdaQueryWrapper<SysDictItem>().in(SysDictItem::getDictId, ids));
|
||||
return line > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加字典
|
||||
* @param dictName
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.jeecg.modules.system.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
@ -14,14 +15,15 @@ import org.jeecg.common.util.oConvertUtils;
|
|||
import org.jeecg.modules.system.entity.SysGatewayRoute;
|
||||
import org.jeecg.modules.system.mapper.SysGatewayRouteMapper;
|
||||
import org.jeecg.modules.system.service.ISysGatewayRouteService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: gateway路由管理
|
||||
|
@ -37,7 +39,7 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
|
|||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private static final String STRING_STATUS = "status";
|
||||
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MMdd");
|
||||
@Override
|
||||
public void addRoute2Redis(String key) {
|
||||
List<SysGatewayRoute> ls = this.list(new LambdaQueryWrapper<SysGatewayRoute>());
|
||||
|
@ -46,7 +48,13 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
|
|||
|
||||
@Override
|
||||
public void deleteById(String id) {
|
||||
//1.将状态修改成禁用
|
||||
SysGatewayRoute route = new SysGatewayRoute();
|
||||
route.setId(id);
|
||||
route.setStatus(0);
|
||||
this.baseMapper.updateById(route);
|
||||
this.removeById(id);
|
||||
//2.刷新路由
|
||||
this.resreshRouter(id);
|
||||
}
|
||||
|
||||
|
@ -71,6 +79,8 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
|
|||
route.setRouterId(json.getString("routerId"));
|
||||
route.setName(json.getString("name"));
|
||||
route.setPredicates(json.getString("predicates"));
|
||||
//初始化删除状态
|
||||
route.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
String filters = json.getString("filters");
|
||||
if (ObjectUtil.isEmpty(filters)) {
|
||||
filters = "[]";
|
||||
|
@ -109,5 +119,70 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
|
|||
redisTemplate.opsForValue().set(CacheConstant.GATEWAY_ROUTES, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原逻辑删除
|
||||
* @param ids
|
||||
*/
|
||||
@Override
|
||||
public void revertLogicDeleted(List<String> ids) {
|
||||
this.baseMapper.revertLogicDeleted(ids);
|
||||
resreshRouter(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 彻底删除
|
||||
* @param ids
|
||||
*/
|
||||
@Override
|
||||
public void deleteLogicDeleted(List<String> ids) {
|
||||
this.baseMapper.deleteLogicDeleted(ids);
|
||||
resreshRouter(ids.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由复制
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SysGatewayRoute copyRoute(String id) {
|
||||
log.info("--gateway 路由复制--");
|
||||
SysGatewayRoute targetRoute = new SysGatewayRoute();
|
||||
try {
|
||||
SysGatewayRoute sourceRoute = this.baseMapper.selectById(id);
|
||||
//1.复制路由
|
||||
BeanUtils.copyProperties(sourceRoute,targetRoute);
|
||||
//1.1 获取当前日期
|
||||
String formattedDate = dateFormat.format(new Date());
|
||||
String copyRouteName = sourceRoute.getName() + "_copy_";
|
||||
//1.2 判断数据库是否存在
|
||||
Long count = this.baseMapper.selectCount(new LambdaQueryWrapper<SysGatewayRoute>().eq(SysGatewayRoute::getName, copyRouteName + formattedDate));
|
||||
//1.3 新的路由名称
|
||||
copyRouteName += count > 0?RandomUtil.randomNumbers(4):formattedDate;
|
||||
|
||||
targetRoute.setId(null);
|
||||
targetRoute.setName(copyRouteName);
|
||||
targetRoute.setCreateTime(new Date());
|
||||
targetRoute.setStatus(0);
|
||||
targetRoute.setDelFlag(CommonConstant.DEL_FLAG_0);
|
||||
this.baseMapper.insert(targetRoute);
|
||||
//2.刷新路由
|
||||
resreshRouter(null);
|
||||
} catch (Exception e) {
|
||||
log.error("路由配置解析失败", e);
|
||||
resreshRouter(null);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return targetRoute;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询删除列表
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<SysGatewayRoute> getDeletelist() {
|
||||
return baseMapper.queryDeleteList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,15 @@ public class SysUserDepartServiceImpl extends ServiceImpl<SysUserDepartMapper, S
|
|||
//update-end---author:liusq ---date:20231215 for:逗号分割多个用户翻译问题------------
|
||||
//update-begin---author:wangshuai ---date:20220608 for:[VUEN-1238]邮箱回复时,发送到显示的为用户id------------
|
||||
if(oConvertUtils.isNotEmpty(id)){
|
||||
query.eq(SysUser::getId, id);
|
||||
//update-begin---author:wangshuai ---date:2024-06-25 for:【TV360X-1482】写信,选择用户后第一次回显没翻译------------
|
||||
String COMMA = ",";
|
||||
if(oConvertUtils.isNotEmpty(isMultiTranslate) && id.contains(COMMA)){
|
||||
String[] idArr = id.split(COMMA);
|
||||
query.in(SysUser::getId, Arrays.asList(idArr));
|
||||
}else {
|
||||
query.eq(SysUser::getId, id);
|
||||
}
|
||||
//update-end---author:wangshuai ---date:2024-06-25 for:【TV360X-1482】写信,选择用户后第一次回显没翻译------------
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20220608 for:[VUEN-1238]邮箱回复时,发送到显示的为用户id------------
|
||||
//update-begin---author:wangshuai ---date:20220902 for:[VUEN-2121]临时用户不能直接显示------------
|
||||
|
|
|
@ -208,7 +208,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserTenantId(item.getId(),posTenantId);
|
||||
//update-end---author:wangshuai---date:2023-11-15---for:【QQYUN-7028】用户职务保存后未回显---
|
||||
//update-end---author:wangshuai ---date:20230228 for:[QQYUN-4354]加入更多字段:当前加入时间应该取当前租户的/职位也是当前租户下的------------
|
||||
item.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
item.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
|
||||
//update-begin---author:wangshuai---date:2023-10-08---for:【QQYUN-6668】钉钉部门和用户同步,我怎么知道哪些用户是双向绑定成功的---
|
||||
//是否根据租户隔离(敲敲云用户列表专用,用于展示是否同步钉钉)
|
||||
|
@ -271,13 +271,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteUser(String userId) {
|
||||
//update-begin---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
//验证用户是否为管理员
|
||||
this.checkUserAdminRejectDel(userId);
|
||||
//update-end---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
|
||||
//2.删除用户
|
||||
//1.删除用户
|
||||
this.removeById(userId);
|
||||
return false;
|
||||
}
|
||||
|
@ -286,9 +280,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteBatchUsers(String userIds) {
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
this.checkUserAdminRejectDel(userIds);
|
||||
//2.删除用户
|
||||
//1.删除用户
|
||||
this.removeByIds(Arrays.asList(userIds.split(",")));
|
||||
return false;
|
||||
}
|
||||
|
@ -492,7 +484,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId, String username) {
|
||||
public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId,String username) {
|
||||
return userMapper.getUserByDepId(page, departId,username);
|
||||
}
|
||||
|
||||
|
@ -535,7 +527,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
//根据部门orgCode查询部门,需要将职位id进行传递
|
||||
for (SysUserSysDepartModel model:list) {
|
||||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(model.getId());
|
||||
model.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
model.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
}
|
||||
Integer total = baseMapper.getUserByOrgCodeTotal(orgCode, userParams);
|
||||
|
||||
|
@ -781,19 +773,21 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
public void editUser(SysUser user, String roles, String departs, String relTenantIds) {
|
||||
public void editUser(SysUser user, String roles, String departs, String relTenantIds, String updateFromPage) {
|
||||
//获取用户编辑前台传过来的租户id
|
||||
this.editUserTenants(user.getId(),relTenantIds);
|
||||
//step.1 修改用户基础信息
|
||||
this.updateById(user);
|
||||
//step.2 修改角色
|
||||
//处理用户角色 先删后加
|
||||
sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
|
||||
if(oConvertUtils.isNotEmpty(roles)) {
|
||||
String[] arr = roles.split(",");
|
||||
for (String roleId : arr) {
|
||||
SysUserRole userRole = new SysUserRole(user.getId(), roleId);
|
||||
sysUserRoleMapper.insert(userRole);
|
||||
if (oConvertUtils.isEmpty(updateFromPage) || !"deptUsers".equalsIgnoreCase(updateFromPage)) {
|
||||
// 处理用户角色 先删后加 , 如果是在部门用户页面修改用户,不处理用户角色,因为该页面无法编辑用户角色.
|
||||
sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
|
||||
if (oConvertUtils.isNotEmpty(roles)) {
|
||||
String[] arr = roles.split(",");
|
||||
for (String roleId : arr) {
|
||||
SysUserRole userRole = new SysUserRole(user.getId(), roleId);
|
||||
sysUserRoleMapper.insert(userRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,7 +838,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames= CacheConstant.SYS_USERS_CACHE, key="#username")
|
||||
@Cacheable(cacheNames=CacheConstant.SYS_USERS_CACHE, key="#username")
|
||||
@SensitiveEncode
|
||||
public LoginUser getEncodeUserInfo(String username){
|
||||
if(oConvertUtils.isEmpty(username)) {
|
||||
|
@ -887,6 +881,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
SysUserTenant userTenant = new SysUserTenant();
|
||||
userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
|
||||
userTenantMapper.update(userTenant,query);
|
||||
//update-end---author:wangshuai ---date:20230111 for:[QQYUN-3951]租户用户离职重构------------
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -905,7 +900,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result){
|
||||
public Result<JSONObject> setLoginTenant(SysUser sysUser, JSONObject obj, String username, Result<JSONObject> result){
|
||||
// update-begin--Author:sunjianlei Date:20210802 for:获取用户租户信息
|
||||
//用户有哪些租户
|
||||
// List<SysTenant> tenantList = null;
|
||||
|
@ -1345,7 +1340,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
* @param orgName
|
||||
* @param orgId
|
||||
*/
|
||||
private void getParentDepart(SysDepart depart, List<String> orgName, List<String> orgId){
|
||||
private void getParentDepart(SysDepart depart,List<String> orgName,List<String> orgId){
|
||||
String pid = depart.getParentId();
|
||||
orgName.add(0, depart.getDepartName());
|
||||
orgId.add(0, depart.getId());
|
||||
|
@ -1473,7 +1468,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
private void userPositionId(SysUser sysUser) {
|
||||
if(null != sysUser){
|
||||
List<String> positionList = sysUserPositionMapper.getPositionIdByUserId(sysUser.getId());
|
||||
sysUser.setPost(CommonUtils.getSplitText(positionList, SymbolConstant.COMMA));
|
||||
sysUser.setPost(CommonUtils.getSplitText(positionList,SymbolConstant.COMMA));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1524,7 +1519,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
* @param departChargeUsers
|
||||
* @param departId
|
||||
*/
|
||||
private void removeDepartmentManager(List<String> departChargeUserIdList, List<SysUser> departChargeUsers, String departId){
|
||||
private void removeDepartmentManager(List<String> departChargeUserIdList,List<SysUser> departChargeUsers,String departId){
|
||||
//移除部门负责人
|
||||
for(String chargeUserId: departChargeUserIdList){
|
||||
for(SysUser chargeUser: departChargeUsers){
|
||||
|
@ -1912,6 +1907,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void changePhone(JSONObject json, String username) {
|
||||
String smscode = json.getString("smscode");
|
||||
|
@ -1945,7 +1941,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
userMapper.updateById(sysUser);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证手机号
|
||||
*
|
||||
|
@ -1965,7 +1961,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
//验证完成之后清空手机验证码
|
||||
redisUtil.removeAll(phoneKey);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress) {
|
||||
String type = jsonObject.getString("type");
|
||||
|
@ -2008,7 +2004,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
log.warn("--------[警告] IP地址:{}, 短信接口请求太多-------", clientIp);
|
||||
throw new JeecgBootException("短信接口请求太多,请稍后再试!", CommonConstant.PHONE_SMS_FAIL_CODE);
|
||||
}
|
||||
|
||||
|
||||
//随机数
|
||||
String captcha = RandomUtil.randomNumbers(6);
|
||||
JSONObject obj = new JSONObject();
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jeecg.common.config.TenantContext;
|
|||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.exception.JeecgBootBizTipException;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.*;
|
||||
|
@ -1147,6 +1148,11 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
}
|
||||
// 获取【钉钉】所有的部门
|
||||
List<Department> departments = JdtDepartmentAPI.listAll(accessToken);
|
||||
//update-begin---author:wangshuai---date:2024-06-25---for:【TV360X-1316】钉钉同步提示消息不正确---
|
||||
if(departments.isEmpty()){
|
||||
throw new JeecgBootBizTipException("请查看配置参数和白名单是否配置!");
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-06-25---for:【TV360X-1316】钉钉同步提示消息不正确---
|
||||
String username = JwtUtil.getUserNameByToken(SpringContextUtils.getHttpServletRequest());
|
||||
List<JdtDepartmentTreeVo> departmentTreeList = JdtDepartmentTreeVo.listToTree(departments);
|
||||
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
|
@ -1182,7 +1188,11 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
try {
|
||||
userMapper.updateById(updateSysUser);
|
||||
String str = String.format("用户 %s(%s) 更新成功!", updateSysUser.getRealname(), updateSysUser.getUsername());
|
||||
syncInfo.addSuccessInfo(str);
|
||||
//update-begin---author:wangshuai---date:2024-06-24---for:【TV360X-1317】钉钉同步 同步成功之后 重复提示---
|
||||
if(!syncInfo.getSuccessInfo().contains(str)){
|
||||
syncInfo.addSuccessInfo(str);
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-06-24---for:【TV360X-1317】钉钉同步 同步成功之后 重复提示---
|
||||
} catch (Exception e) {
|
||||
this.syncUserCollectErrInfo(e, user, syncInfo);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,38 @@
|
|||
}
|
||||
return "";
|
||||
}
|
||||
<#elseif po.classType=='switch'>
|
||||
<#assign switch_extend_arr=['Y','N']>
|
||||
<#if po.dictField?default("")?contains("[")>
|
||||
<#assign switch_extend_arr=po.dictField?eval>
|
||||
</#if>
|
||||
<#list switch_extend_arr as a>
|
||||
<#if a_index == 0>
|
||||
<#assign switch_extend_arr1=a>
|
||||
<#else>
|
||||
<#assign switch_extend_arr2=a>
|
||||
</#if>
|
||||
</#list>
|
||||
@Excel(name = "${po.filedComment}", width = 15,replace = {"是_${switch_extend_arr1}","否_${switch_extend_arr2}"} )
|
||||
@ApiModelProperty(value = "${po.filedComment}")
|
||||
private ${po.fieldType} ${po.fieldName};
|
||||
<#elseif po.classType=='pca'>
|
||||
@Excel(name = "${po.filedComment}", width = 15,exportConvert=true,importConvert = true )
|
||||
@ApiModelProperty(value = "${po.filedComment}")
|
||||
private ${po.fieldType} ${po.fieldName};
|
||||
|
||||
public String convertis${po.fieldName?cap_first}() {
|
||||
return SpringContextUtils.getBean(ProvinceCityArea.class).getText(${po.fieldName});
|
||||
}
|
||||
|
||||
public void convertset${po.fieldName?cap_first}(String text) {
|
||||
this.${po.fieldName} = SpringContextUtils.getBean(ProvinceCityArea.class).getCode(text);
|
||||
}
|
||||
<#elseif po.classType=='cat_tree'>
|
||||
<#assign list_field_dictCode=', dictTable = "sys_category", dicText = "name", dicCode = "id"'>
|
||||
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
|
||||
@ApiModelProperty(value = "${po.filedComment}")
|
||||
private ${po.fieldType} ${po.fieldName};
|
||||
<#else>
|
||||
@Schema(description = "${po.filedComment}")
|
||||
<#if po.fieldDbName == 'del_flag'>
|
||||
|
|
|
@ -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>/>
|
||||
|
@ -82,7 +91,7 @@
|
|||
<j-image-upload <#if po.uploadnum??>:fileMax=${po.uploadnum}<#else>:fileMax="0"</#if> v-model:value="formData.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
|
||||
<#elseif po.classType=='umeditor'>
|
||||
<#assign need_editor = true>
|
||||
<j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
|
||||
<j-editor v-model:value="formData.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if> :autoFocus="false"/>
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
<a-input v-model:value="formData.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> allow-clear ></a-input>
|
||||
<#elseif po.classType == 'sel_tree'>
|
||||
|
|
|
@ -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>
|
|
@ -9,9 +9,11 @@
|
|||
<#assign query_field_dictCode="">
|
||||
<#if po.dictTable?default("")?trim?length gt 1>
|
||||
<#assign need_select_tag = true>
|
||||
<#assign need_multi = true>
|
||||
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#assign need_select_tag = true>
|
||||
<#assign need_multi = true>
|
||||
<#assign query_field_dictCode="${po.dictField}">
|
||||
</#if>
|
||||
<#if po.queryMode=='single'>
|
||||
|
@ -56,66 +58,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 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>
|
||||
<#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>
|
||||
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
|
||||
<#if po.dictTable?default("")?trim?length gt 1>
|
||||
<#if query_field_no gt 1> </#if><j-select-multiple 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>
|
||||
<#if query_field_no gt 1> </#if><j-select-multiple placeholder="请选择${po.filedComment}" v-model:value="queryParam.${po.fieldName}" dictCode="${po.dictField}" allow-clear />
|
||||
<#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>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
-- 注意:该页面对应的前台目录为views/${entityPackage}文件夹下
|
||||
-- 注意:该页面对应的前台目录为views/${entityPackagePath}文件夹下
|
||||
-- 如果你想更改到其他目录,请修改sql中component字段对应的值
|
||||
|
||||
<#assign id = '${.now?string["yyyyMMddhhmmSSsss"]}0'>
|
||||
|
||||
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
|
||||
VALUES ('${id}', NULL, '${tableVo.ftlDescription}', '/${entityPackage}/${entityName?uncap_first}List', '${entityPackage}/${entityName}List', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
|
||||
VALUES ('${id}', NULL, '${tableVo.ftlDescription}', '/${entityPackagePath}/${entityName?uncap_first}List', '${entityPackagePath}/${entityName}List', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '${.now?string["yyyy-MM-dd HH:mm:ss"]}', NULL, NULL, 0);
|
||||
|
||||
-- 权限控制sql
|
||||
-- 新增
|
||||
|
|
|
@ -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>
|
|
@ -1,6 +1,7 @@
|
|||
package ${bussiPackage}.${entityPackage}.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -11,6 +12,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.query.QueryRuleEnum;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import ${bussiPackage}.${entityPackage}.entity.${entityName};
|
||||
import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
|
||||
|
@ -37,10 +39,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
<#assign bpm_flag=false>
|
||||
<#assign has_multi_query_field=false>
|
||||
<#list originalColumns as po>
|
||||
<#if po.fieldDbName=='bpm_status'>
|
||||
<#assign bpm_flag=true>
|
||||
</#if>
|
||||
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
|
||||
<#assign has_multi_query_field=true>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
/**
|
||||
|
@ -51,7 +57,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||
*/
|
||||
@Tag(name="${tableVo.ftlDescription}")
|
||||
@RestController
|
||||
@RequestMapping("/${entityPackage}/${entityName?uncap_first}")
|
||||
@RequestMapping("/${entityPackagePath}/${entityName?uncap_first}")
|
||||
@Slf4j
|
||||
public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> {
|
||||
@Autowired
|
||||
|
@ -73,7 +79,19 @@ public class ${entityName}Controller extends JeecgController<${entityName}, I${e
|
|||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
|
||||
<#if has_multi_query_field>
|
||||
// 自定义查询规则
|
||||
Map<String, QueryRuleEnum> customeRuleMap = new HashMap<>();
|
||||
// 自定义多选的查询规则为:LIKE_WITH_OR
|
||||
<#list originalColumns as po>
|
||||
<#if po.isQuery=='Y' && (po.classType=='list' || po.classType=='list_multi' || po.classType=='radio' || po.classType=='checkbox')>
|
||||
customeRuleMap.put("${po.fieldName}", QueryRuleEnum.LIKE_WITH_OR);
|
||||
</#if>
|
||||
</#list>
|
||||
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap(),customeRuleMap);
|
||||
<#else>
|
||||
QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap());
|
||||
</#if>
|
||||
Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize);
|
||||
IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
|
|
|
@ -9,6 +9,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import org.jeecg.common.constant.ProvinceCityArea;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
@ -33,6 +35,7 @@ public class ${entityName} implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
|
||||
<#assign excel_ignore_classType_arr=['pca','switch','cat_tree']>
|
||||
<#list originalColumns as po>
|
||||
<#-- 生成字典Code -->
|
||||
<#assign list_field_dictCode="">
|
||||
|
@ -68,7 +71,7 @@ public class ${entityName} implements Serializable {
|
|||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
</#if>
|
||||
<#else>
|
||||
<#if !excel_ignore_arr?seq_contains("${po.fieldName}")>
|
||||
<#if !excel_ignore_arr?seq_contains("${po.fieldName}") && !excel_ignore_classType_arr?seq_contains("${po.classType}")>
|
||||
@Excel(name = "${po.filedComment}", width = 15${list_field_dictCode})
|
||||
</#if>
|
||||
</#if>
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
model: {},
|
||||
backRouteName:'index',
|
||||
url: {
|
||||
queryById: "/${entityPackage}/${entityName?uncap_first}/queryById",
|
||||
add: "/${entityPackage}/${entityName?uncap_first}/add",
|
||||
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
|
||||
queryById: "/${entityPackagePath}/${entityName?uncap_first}/queryById",
|
||||
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
|
||||
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
return {
|
||||
CustomBar:this.CustomBar,
|
||||
NavBarColor:this.NavBarColor,
|
||||
url: "/${entityPackage}/${entityName?uncap_first}/list",
|
||||
url: "/${entityPackagePath}/${entityName?uncap_first}/list",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -318,11 +318,11 @@
|
|||
}
|
||||
],
|
||||
url: {
|
||||
list: "/${entityPackage}/${entityName?uncap_first}/list",
|
||||
delete: "/${entityPackage}/${entityName?uncap_first}/delete",
|
||||
deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
|
||||
exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
|
||||
importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
|
||||
list: "/${entityPackagePath}/${entityName?uncap_first}/list",
|
||||
delete: "/${entityPackagePath}/${entityName?uncap_first}/delete",
|
||||
deleteBatch: "/${entityPackagePath}/${entityName?uncap_first}/deleteBatch",
|
||||
exportXlsUrl: "/${entityPackagePath}/${entityName?uncap_first}/exportXls",
|
||||
importExcelUrl: "${entityPackagePath}/${entityName?uncap_first}/importExcel",
|
||||
<#if bpm_flag>startProcess: '/act/process/extActProcess/startMutilProcess'</#if>
|
||||
},
|
||||
<#if bpm_flag>
|
||||
|
@ -380,7 +380,7 @@
|
|||
let params = {
|
||||
flowCode: this.flowCode,
|
||||
id: record.id,
|
||||
formUrl: '${entityPackage}/modules/${entityName}Form',
|
||||
formUrl: '${entityPackagePath}/modules/${entityName}Form',
|
||||
formUrlMobile: ''
|
||||
}
|
||||
postAction(this.url.startProcess, params).then(res=>{
|
||||
|
|
|
@ -165,9 +165,9 @@
|
|||
confirmLoading: false,
|
||||
<#include "/common/validatorRulesTemplate/main.ftl">
|
||||
url: {
|
||||
add: "/${entityPackage}/${entityName?uncap_first}/add",
|
||||
edit: "/${entityPackage}/${entityName?uncap_first}/edit",
|
||||
queryById: "/${entityPackage}/${entityName?uncap_first}/queryById"
|
||||
add: "/${entityPackagePath}/${entityName?uncap_first}/add",
|
||||
edit: "/${entityPackagePath}/${entityName?uncap_first}/edit",
|
||||
queryById: "/${entityPackagePath}/${entityName?uncap_first}/queryById"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
|
@ -286,7 +289,7 @@
|
|||
let params = {
|
||||
flowCode: 'dev_${tableName}_001',
|
||||
id: record.id,
|
||||
formUrl: '${entityPackage}/components/${entityName}Form',
|
||||
formUrl: '${entityPackagePath}/components/${entityName}Form',
|
||||
formUrlMobile: ''
|
||||
}
|
||||
await startProcess(params);
|
||||
|
@ -318,6 +321,6 @@
|
|||
</#if>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="less" scoped>
|
||||
<#include "/common/form/vue3SearchStyle.ftl">
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue